fix(import): label the SIE preview IB total as "summa debet", not "IB Summa" (#2142)

The fourth stat card in the SIE preview showed the debit-side total of the
opening-balance voucher under the label "IB Summa". A user read it as the
net ingående balans and could not reconcile it against any single figure.

- Relabel the card "IB, summa debet" and add a one-line helper saying it is
  the sum of all debit balances in IB, not a single account balance. The
  number equals "Total debet" in the Balansräkning (IB) card right below.
- Review step: "Skapar IB-verifikation, summa debet X" instead of
  "Skapar verifikation för IB på X".
- Comment the field in generateImportPreview so the meaning is explicit.

No data or logic change: openingBalanceTotal keeps its semantics.


Claude-Session: https://claude.ai/code/session_01AvaV9n4GswzF2Mq932PXTJ

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-09-04 09:42:41 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Fable 5.1
parent 8265b5d166
commit 227a6317f1
4 changed files with 8 additions and 2 deletions
+1
View File
@@ -1476,6 +1476,7 @@ One line per decision: `[YYYY-MM-DD] <decision>: <why>`. Appended by agents and
[2026-09-01] mcp.tool_called gets errorCause = errorCauseTag(err) on the two execution catch paths only (#2051): SQLSTATE or coded-error code, else the error class name, capped at 64 chars; a plain Error deliberately tags null because the class name 'Error' is noise, and pre-execution denials pass nothing since their errorCode already IS the vocabulary. Raw driver messages stay out of event_log on purpose: a constraint-violation message can quote row values.
[2026-09-01] counterparty_aliases joins the categorization_templates audit-trigger strip list (20260901200000) instead of staying logged: prod falsified the original exclusion list within 30 minutes of 20260901103000 going live (15 of the first 16 UPDATE audit rows were alias+learning noise, ~800/day projected vs ~50/day of real rule changes), because the learning path merges aliases in the same write that bumps occurrence_count. Explicit trade-off: a human editing ONLY aliases is no longer logged; accepted since alias growth is overwhelmingly automatic and any change also touching accounts/VAT/pattern/active still logs (first real one, 19:02:17Z same day, captured correctly). Pre-fix noise rows stay in audit_log (append-only) and the read model stops labelling the column so they render as no-ops.
[2026-09-01] MCP catalog budget attacked at the duplicated staged envelope rather than by demoting more reads: measuring the payload by segment showed outputSchema is 38 % of the whole catalog (23 290 tokens) and STAGED_OPERATION_SCHEMA alone 14 736 of it, the same envelope transmitted 58 times, while descriptions (what the three previous rounds trimmed) are only 10 %. period_status now carries its shape in one sentence instead of declared JSON Schema, matching actor/approve/preview which were always bare objects; 2 552 tokens reclaimed with no tool demoted and no field removed. Every edit is in the LOOSER direction because the server emits structuredContent for every tool and the documented failure mode is a declaration too tight making a strict client reject a successful call. next kept additionalProperties: false: staging.test.ts pins it closed and a guard whose reason is not in front of you is not one to loosen for 420 tokens. Ceiling ratcheted to 60 000 rather than the usual ~300 margin, leaving ~1 070 deliberate working margin: server.ts took 70 commits in 14 days and the previous 116-token margin is what starts the ratchet-block-bump-demote cycle visible in the bench log.
[2026-09-01] SIE preview "IB Summa" card relabelled "IB, summa debet" with a visible helper, kept hard-coded Swedish: SIEPreviewStep has no translations at all (SIE-spec terminology), so localising one of four stat cards would produce a mixed-language grid; a user (Jonas Forsslund) read the old label as a net ingående balans and could not reconcile it.
[2026-09-01] Other companies' accounts in the EB account picker are collapsed behind a disclosure, not removed: a sibling claim (claimed_by_company_id from PR #2116) is a strong hint, not proof of ownership, and hiding the rows outright would leave a legacy or mis-booked account unreachable without a database edit. The main list, 'Markera alla' and the 'x av y' counter cover own accounts only; the settings row shows one muted summary line instead of the foreign rows. Brand-new never-claimed accounts still list (unchecked): Enable Banking's account resource carries no owner org number, so nothing in the data attributes them.
[2026-09-01] EB callback re-stamps a sibling claim across an in-place renewal (PR #2141 skeptic finding): accountsMetadata is rebuilt from the bank's list on every callback, so the claimed_by_company_* label from PR #2116 was lost the first time the consent was renewed and the sibling's accounts came back as plain unchecked own accounts. The label is re-derived from a fresh cross-company lookup on accounts that stay disabled here, never copied from the prior row, so a released claim clears itself; an enabled account is the active company's standing state and is never labelled. partitionByClaim also requires enabled === false alongside the flag: a syncing account must never be tucked out of sight, whatever wrote the flag.
[2026-09-01] Inbox +lev/+ver plus-addressing (#2129) stores the sender's tag in a new nullable invoice_inbox_items.kind_hint column rather than inside extracted_data.documentKind: retry-extraction overwrites that JSONB container wholesale, and the sender's statement must outlive the AI's guess. Unknown tags route with kind_hint NULL (a typo never loses a document); the type filter's two narrow entries exclude unclassified rows on purpose (a narrow filter promises a known kind; 'Alla typer' is where the rest live), and the whole type menu stays hidden until at least one row is classified so an unclassified inbox gets no dead control.
+1 -1
View File
@@ -350,7 +350,7 @@ export default function ImportReviewStep({
</Label>
<p className="text-sm text-muted-foreground">
{hasOpeningBalances
? `Skapar verifikation för IB på ${formatCurrency(preview.openingBalanceTotal)}`
? `Skapar IB-verifikation, summa debet ${formatCurrency(preview.openingBalanceTotal)}`
: 'Inga ingående balanser i filen'}
</p>
{existingIbCount > 0 && (
+4 -1
View File
@@ -149,9 +149,12 @@ export default function SIEPreviewStep({
<Card>
<CardContent className="pt-6">
<div className="flex items-center gap-2 text-muted-foreground mb-1">
<span className="text-sm">IB Summa</span>
<span className="text-sm">IB, summa debet</span>
</div>
<p className="text-2xl font-display tabular-nums">{formatCurrency(preview.openingBalanceTotal)}</p>
<p className="mt-1 text-xs text-muted-foreground">
Summan av alla debetsaldon i ingående balans, inte ett enskilt kontosaldo.
</p>
</CardContent>
</Card>
</div>
+2
View File
@@ -89,6 +89,8 @@ export function generateImportPreview(
accountCount: parsed.stats.totalAccounts,
voucherCount: parsed.stats.totalVouchers,
transactionLineCount: parsed.stats.totalTransactionLines,
// Debit-side total of the IB voucher (shown as "IB, summa debet"), not a
// net opening balance: a balanced IB nets to zero.
openingBalanceTotal: totalDebit,
trialBalance: {
totalDebit,