Files
boc/sie-import/index.mjs
T
Bernt bae705aa97 ARCHITECTURE: NFC roadmap, edge AI, audit logging
- Add NFC ePassport roadmap (ICAO 9303, eIDAS)
- Add TensorFlow.js edge face detection (BlazeFace)
- Add structured audit logger (GDPR-compliant)
- Risk scoring support

Part of KYC Apple Native UX v1.1.0
2026-06-29 16:24:48 +00:00

161 lines
5.2 KiB
JavaScript

/**
* AAMOS SIE4 Import Service
* Port: 3251
*/
import express from 'express';
import { randomUUID } from 'crypto';
import { parseSIE4 } from './parser.mjs';
const PORT = parseInt(process.env.PORT || '3251', 10);
const LEDGER_BASE = process.env.LEDGER_URL || 'http://127.0.0.1:3250';
const app = express();
app.use(express.json({ limit: '10mb' }));
// ── Health ───────────────────────────────────────────────────────────────────
app.get('/health', (_req, res) => {
res.json({ ok: true, service: 'aamos-sie-import', port: PORT });
});
// ── SIE4 Import ──────────────────────────────────────────────────────────────
app.post('/api/sie/import', async (req, res) => {
const { sie_content, tenant_id, dry_run = false } = req.body ?? {};
if (!sie_content || typeof sie_content !== 'string') {
return res.status(400).json({ ok: false, error: 'sie_content (string) is required' });
}
const trace_id = randomUUID();
const correlation_id = randomUUID();
// ── Parse ────────────────────────────────────────────────────────────────
let parsed;
try {
parsed = parseSIE4(sie_content);
} catch (err) {
return res.status(400).json({
ok: false,
error: `SIE4 parse error: ${err.message}`,
trace_id,
});
}
const { journal_entries } = parsed;
// ── Dry run ───────────────────────────────────────────────────────────────
if (dry_run) {
return res.json({
ok: true,
dry_run: true,
imported_count: 0,
skipped_count: journal_entries.length,
parsed_entries: journal_entries.length,
company: parsed.company,
org_nr: parsed.org_nr,
fiscal_year: parsed.fiscal_year,
accounts_count: parsed.accounts.length,
errors: [],
trace_id,
correlation_id,
});
}
// ── Live import ───────────────────────────────────────────────────────────
const errors = [];
let imported_count = 0;
let skipped_count = 0;
const baseHeaders = {
'Content-Type': 'application/json',
'X-Tenant-Id': tenant_id || '',
'X-User-Id': 'sie-import',
'X-Trace-Id': trace_id,
'X-Correlation-Id': correlation_id,
};
for (const entry of journal_entries) {
const entryRef = `${entry.series}${entry.number}`;
const journalBody = {
date: entry.date,
description: entry.description,
source_type: 'import_sie',
series: entry.series,
series_number: entry.number,
correlation_id,
lines: entry.transactions.map(t => ({
account: t.account,
amount: t.amount,
date: t.date,
description: t.description,
})),
};
try {
// 1. Create journal entry
const createResp = await fetch(`${LEDGER_BASE}/api/ledger/journal`, {
method: 'POST',
headers: baseHeaders,
body: JSON.stringify(journalBody),
});
if (!createResp.ok) {
const text = await createResp.text().catch(() => createResp.status.toString());
errors.push({ entry: entryRef, step: 'create', error: text });
skipped_count++;
continue;
}
const created = await createResp.json().catch(() => null);
const journalId =
created?.id ??
created?.journal_id ??
created?.data?.id ??
null;
if (!journalId) {
errors.push({ entry: entryRef, step: 'create', error: 'No journal ID in response' });
skipped_count++;
continue;
}
// 2. Post / commit the journal entry
const postResp = await fetch(`${LEDGER_BASE}/api/ledger/journal/${journalId}/post`, {
method: 'POST',
headers: baseHeaders,
body: JSON.stringify({}),
});
if (!postResp.ok) {
const text = await postResp.text().catch(() => postResp.status.toString());
errors.push({ entry: entryRef, step: 'post', error: text });
skipped_count++;
continue;
}
imported_count++;
} catch (err) {
errors.push({ entry: entryRef, step: 'network', error: err.message });
skipped_count++;
}
}
res.json({
ok: errors.length === 0,
imported_count,
skipped_count,
errors,
trace_id,
correlation_id,
});
});
// ── Start ─────────────────────────────────────────────────────────────────────
app.listen(PORT, '127.0.0.1', () => {
console.log(`[aamos-sie-import] Listening on 127.0.0.1:${PORT}`);
});