2e669a64e3
* fix(skatteverket): skip skattekonto rows without belopp instead of failing the whole sync SKV's transaktioner response can contain a row without beloppSkatteverket despite the spec typing it as required. The row mapped to a NULL in the NOT NULL belopp_skatteverket column, so the batch upsert failed with 23502 and every sync for the company (post-connect, manual, nightly cron) died permanently on the same row. Filter out rows that cannot satisfy the table's NOT NULL columns before mapping, sync the rest, log one structured warn with the offending row as diagnostic, and report the count as skipped in the sync result. Skipping over coalescing to 0 kr is deliberate: an invented amount would be renderable, matchable and bookable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(skatteverket): durable skipped-row trace in extension_data, minimized log Review batch for PR #1837: - Compliance swarm (GDPR Art.5(1)(c) high, ISO A.8.11 medium): the warn log no longer carries the raw SKV row; it logs status, missing fields, transaktionsidentitet and transaktionsdatum only. - Swedish accounting review (BFL 5 kap fullstandighet, BFNAR 2013:2 kap 8): skipped rows are now retained durably and queryably in the company-scoped extension_data key skattekonto_skipped_rows, raw payload included, overwritten each sync so a completed row self-clears the trace. - CodeRabbit: eventBus.clear() in beforeEach; new test case covering rows missing transaktionsdatum and transaktionstext; warn assertion retargeted to the minimized shape. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(skatteverket): uncapped skipped count, merge-history trace with truncation flag Second review cycle for PR #1837 (Swedish accounting review): - skipped now counts the full payload before the trace cap, and the trace record carries truncated: true (plus traceTruncated in the log) when entries had to be dropped past MAX_SKIPPED_ROWS_RETAINED. - The extension_data trace merges with the previous record instead of overwriting it: entries keep firstSeenAt/lastSeenAt, survive aging out of SKV's ~555-day window, and leave the trace only when their transaktionsidentitet arrives complete and lands in skattekonto_transactions (BFNAR 2013:2 kap 8 behandlingshistorik). - Tests: aged-out retention + id resolution, 60-row truncation case. Saldo-reconciliation finding dispositioned without code change: the existing drift detector already compares the unfiltered SKV saldo against GL 1630 and alerts, which covers a skipped row's balance effect. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>