From a5154ee884600389a0c3064f07571bd8508d1e98 Mon Sep 17 00:00:00 2001 From: Jakob Wennberg <149234542+jakobwennberg@users.noreply.github.com> Date: Fri, 3 Jul 2026 17:26:00 +0200 Subject: [PATCH] docs(dimensions): post-merge review nits from #888 (#889) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SIE round-trip fixture: vouchers in ascending verno order (A1, A2, A3) per SIE4 core invariant 5 — the custom-dim voucher was spliced out of order - commitEntry: note that source_type is a HEADER column repeated by the join — reading lines[0] IS reading the entry header, lines cannot mix source types (a reviewer misread this as per-line logic) - dimension-rules: sharpen the credit-note exemption rationale — credit notes copy the original's bags, so enforcement is either a no-op or would force the exact asymmetric-tag P&L skew the feature prevents Co-authored-by: Claude Fable 5 --- lib/bookkeeping/dimension-rules.ts | 8 +++++++- lib/bookkeeping/engine.ts | 3 +++ lib/import/__tests__/sie-dimensions-roundtrip.test.ts | 10 +++++----- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/bookkeeping/dimension-rules.ts b/lib/bookkeeping/dimension-rules.ts index 9e8ea62c..b01a4076 100644 --- a/lib/bookkeeping/dimension-rules.ts +++ b/lib/bookkeeping/dimension-rules.ts @@ -186,7 +186,13 @@ export function assertMandatoryDimensions( * result account must not be able to block closing the year * - storno/correction/credit notes are HOW history gets fixed — blocking * them on entries that pre-date a rule would make old mistakes - * permanent (same argument as the commitEntry bypass for reversals) + * permanent (same argument as the commitEntry bypass for reversals). + * Credit notes specifically COPY the original's bags (PR7) so the + * reversal nets against the same dimension cells: if the original + * satisfied the rules, so does the copy (enforcement = no-op); if the + * original pre-dates the rules, enforcing would demand an ASYMMETRIC + * tag — a credit in P001 with no original in P001 — which is exactly + * the project-P&L skew this feature exists to prevent * - accrual dissolutions replay a schedule created before the rule * * Operational sources (manual, bank_transaction, invoice_*, supplier_* diff --git a/lib/bookkeeping/engine.ts b/lib/bookkeeping/engine.ts index 5bd3d883..0ccc1e2e 100644 --- a/lib/bookkeeping/engine.ts +++ b/lib/bookkeeping/engine.ts @@ -592,6 +592,9 @@ export async function commitEntry( // System/correction sources are exempt — see // DIMENSION_RULE_EXEMPT_SOURCE_TYPES (imported history, bokslut // mechanics and credit instruments must never be blocked by policy). + // source_type is a HEADER column (journal_entries) — the join repeats + // the same value on every line, so reading lines[0] IS reading the + // entry header; lines cannot mix source types. if (!isDimensionRuleExemptSource(typedLines[0]?.journal_entries?.source_type)) { assertMandatoryDimensions(typedLines, rules) } diff --git a/lib/import/__tests__/sie-dimensions-roundtrip.test.ts b/lib/import/__tests__/sie-dimensions-roundtrip.test.ts index ea720774..abb8786b 100644 --- a/lib/import/__tests__/sie-dimensions-roundtrip.test.ts +++ b/lib/import/__tests__/sie-dimensions-roundtrip.test.ts @@ -69,11 +69,6 @@ const SOURCE_SIE = [ '#TRANS 5010 {1 "KS01" 2 "KB1" 6 "P001"} 15000.00', '#TRANS 1930 {} -15000.00', '}', - '#VER A 3 20260117 "Avdelningskostnad"', - '{', - '#TRANS 5010 {20 "SYD" 25 "T1"} 800.00', - '#TRANS 1930 {} -800.00', - '}', '#VER A 2 20260116 "Odeklarerat projekt"', '{', // P002 is referenced but never declared via #OBJEKT — import synthesizes @@ -81,6 +76,11 @@ const SOURCE_SIE = [ '#TRANS 5010 {6 "P002"} 500.00', '#TRANS 1930 {} -500.00', '}', + '#VER A 3 20260117 "Avdelningskostnad"', + '{', + '#TRANS 5010 {20 "SYD" 25 "T1"} 800.00', + '#TRANS 1930 {} -800.00', + '}', ].join('\n') describe('SIE dimensions round-trip', () => {