docs(dimensions): post-merge review nits from #888 (#889)

- 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 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-07-03 17:26:00 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent 86c924a6e9
commit a5154ee884
3 changed files with 15 additions and 6 deletions
+7 -1
View File
@@ -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_*
+3
View File
@@ -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)
}
@@ -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', () => {