fix(sie): selectable IB voucher series, smarter IB toggle on re-import, orphan-IB guard (#1896)
* fix(sie): selectable IB voucher series that never collides with the file's numbering The Ingående balanser voucher was hardcoded to series A and created before the file's vouchers, so it consumed the A series' next number and shifted every imported A voucher one number higher than in the source system (issue #1882). - IB voucher series is now selectable in the import wizard; the default is the first of M,O,P,Q,R,S,T,V,W,X,Y,Z not used by the file's #VER records (M matches the existing migration-adjustment series). - Plumbed end to end: wizard -> /api/import/sie/execute -> executeSIEImport, v1 REST options.openingBalanceSeries, MCP gnubok_import_sie opening_balance_series -> commitImportSie. - The wizard's 'Importera ingående balanser' toggle now defaults OFF when a posted IB voucher already exists inside the file's fiscal year, with a hint saying why. - Orphan-IB guard in executeSIEImport: replace_sie_import deletes only source_type='import' entries and clears the period's OB pointer, so a prior import's IB voucher survived every replace cycle and each re-import created another one (field report: five accumulated). The import now skips IB creation with a warning when a posted opening_balance entry already exists in the period. - MCP import_opening_balances default (false) vs web (true) documented as deliberate in the tool schema and DECISIONS.md. Fixes #1882 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sie): harden IB series fix after skeptic review (relink orphan, exclude fallback series, type-check option) Skeptic findings on PR #1896, all four blocking items: - Orphan-IB guard now relinks a single surviving opening-balance voucher as the period's OB entry (permitted by the immutability trigger while the pointer is NULL): without it, reports showed IB 0, year-end's duplicate-IB blocker never armed, and the manual IB flow could double-book. It also diffs the survivor's lines against the file's IB and calls out stale amounts in the warning instead of keeping them silently; reverseEntry clears the pointer again for the storno-then-reimport path. - Series-less #VER records resolve to the transaction fallback series at import time, so the IB default picker now treats that series as used by the file (the same #1882 shift pattern through the fallback). The wizard recomputes its IB default with the effective transaction series once loaded. - openingBalanceSeries is type-checked on the web execute route, the MCP stage, and the staged-operation commit: a non-string falls back to the default instead of crashing mid-import after side effects. - The wizard's IB series select flags series used by the file and shows an attention line when the chosen series collides; the engine warns when an explicitly chosen series collides with the file's series (the choice is honored). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sie): uppercase caller-chosen IB series before persisting Swedish accounting review on PR #1896: a lowercase series from v1 or MCP was persisted as-is, booking a case-distinct parallel series next to its uppercase sibling (BFL 5 kap requires one systematic series) and slipping past the file-collision warning. Normalize centrally in executeSIEImport, the single funnel for web, v1, and MCP. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
79013cf092
commit
c6f2bebab9
@@ -1217,6 +1217,9 @@ One line per decision: `[YYYY-MM-DD] <decision>: <why>`. Appended by agents and
|
||||
[2026-08-25] WhatsApp instant received-signal = emoji reaction (U+2705) sent from the webhook, not an extra text message: reactions add no chat bubble so the one-combined-ack-per-burst design survives; best-effort and not persisted as an outbound row (cosmetic, like mark-read), gated on the CHAT_ALLOWED_MIME_TYPES allowlist so junk never earns a checkmark.
|
||||
[2026-08-24] MCP lazy authentication (#1814 PR 2) lists the FULL default tool catalog to anonymous clients and only gates tools/call: the agent has to be able to name a protected tool to trigger the 401 challenge that opens the Connect (and signup) prompt; listing only public tools would hide the trigger. Descriptions are public documentation anyway.
|
||||
[2026-08-24] Public (pre-auth) MCP tools are the three documentation tools only (search_tools, list_skills, load_skill); org-number lookup stays behind the challenge for now because the TIC lookup lives in another extension and cross-extension imports are forbidden.
|
||||
[2026-08-25] SIE IB voucher series (issue #1882): default is 'M' (first candidate of M,O,P,Q,R,S,T,V,W,X,Y,Z not used by the file's #VER), matching the migration-adjustment series and avoiding conventional series letters; user-overridable in the wizard, openingBalanceSeries in APIs, opening_balance_series in MCP. MCP import_opening_balances stays default false (web true) deliberately: agent imports are often continuation imports where an IB entry would duplicate a prior year's UB, and the divergence is now documented in the tool schema.
|
||||
[2026-08-25] IB accumulation root cause (issue #1882): replace_sie_import deletes only source_type='import' rows and clears the OB pointer, so the IB voucher (source_type='opening_balance') survives every replace cycle and each re-import created another one. Fixed app-side with an orphan-IB guard in executeSIEImport (skip + warning when a posted opening_balance entry already exists in the period) instead of amending the RPC: the RPC change needs a migration + pg tests on a legally sensitive delete path and is left as a follow-up.
|
||||
[2026-08-25] Orphan-IB guard relinks a single survivor and diffs its amounts (skeptic pass on PR #1896): skipping alone left the period pointer NULL, so reports showed IB 0 (compute_prior_opening_balances excludes entries dated on period_start), year-end's duplicate-IB blocker never armed, and the manual IB flow could double-book; relink is permitted by enforce_opening_balance_immutability while the pointer is NULL, reverseEntry clears it again for the storno-then-reimport path, and a stale orphan whose amounts differ from the file is called out in the warning instead of silently kept. Auto-storno of the stale orphan was deliberately NOT done: reversing posted entries inside an import needs founder sign-off.
|
||||
[2026-08-25] reset_fiscal_year (#1883) catches foreign_key_violation and aborts instead of enumerating every table that references journal_entries: RESTRICT/NO ACTION FKs (assets, accruals, salary runs) fail the whole reset with FISCAL_YEAR_RESET_LINKED_ENTRIES, SET NULL FKs (transactions, invoice payments) unlink as their designers intended. Future FKs stay covered without touching the RPC.
|
||||
[2026-08-25] Fiscal-year reset treats a posted vat_settlement verifikat, SKV declaration lock/submit audit rows and skatteverket-extension submission_* keys as "VAT declared" evidence and refuses: SKV's actual declaration state is not observable from the DB, so every local trace fails closed (same posture as company_migration_reset 20260818224000).
|
||||
[2026-08-25] Proposal prefill/preview (lib/bookkeeping/proposal-lines.ts) mirrors the ENGINE's formulas, not the historical preview: net leg = gross minus single-rounded VAT (independently rounded extractNet/extractVat unbalances 12% grosses at 14 mod 28 ore), plain Math.round ore parity via a local engineRound (roundOre's EPSILON nudge diverges from booked verifikat at exact-half floats like 8.62*0.25), legacy counterparty proposals now render the 2645/2614 fiktiv-moms pair the legacy booking path actually emits (the 2026-07-29 decision claimed preview/engine parity but the preview omitted the pair; once 'Andra rader' made the preview bookable, the omission would book RC expenses without fiktiv moms), sign-mismatched counterparty matches are mirrored like the server, static template accounts are entity-resolved (_ab), the 'none' VAT sentinel is resolved via resolveExplicitVat before line computation, and the settlement swap applies only to a literal 1930 leg (applySettlementAccount parity). Chosen over sourcing the prefill from MappingResult builders directly to keep the client dialog free of server-only inputs; skeptic counterexamples are locked in proposal-lines.test.ts.
|
||||
|
||||
Reference in New Issue
Block a user