Files
accounted/lib/errors/__tests__/signoff-codes.test.ts
T
Mattsson 51b68afc87 fix(reconciliation): judge bank sign-off from the fiscal period start and show the refusal (#2200)
A user with a September-to-August fiscal year could not sign off 1930:
the dialog let them press Signera, the server refused, and the dialog
showed "Något gick fel. Försök igen."

Three defects, one flow:

- signOffAccount judged a bank account over the calendar year from
  1 January (the getAccountStatus default) while the page the signer
  looked at was scoped to the fiscal period. The sign-off now resolves
  the fiscal period covering through_date and judges from its start,
  for every caller (dashboard, v1, MCP, pending-operation executor).
- The dialog decided whether the "sign anyway" override was needed from
  the page tile, which can be scoped to a narrower range. It now
  previews the exact sign-off with dry_run on open and on every date
  change, and NOT_RECONCILED carries the unexplained amount in
  details so the warning can name it.
- The routes passed the refusal through getErrorMessage(), which did
  not know the sign-off codes and replaced the Swedish text with its
  generic fallback. The codes are now in the structured error registry
  with a thrown_message_sv flag: the mapper passes the thrower's text
  (dates, amounts) through verbatim and English users get message_en.


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

Signed-off-by: Emil <emilmattsson14@gmail.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 23:11:42 +02:00

61 lines
2.4 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { getErrorMessage } from '../get-error-message'
import { getErrorEntry } from '../structured-errors'
import { ReconciliationSignoffError, type SignoffErrorCode } from '@/lib/reconciliation/signoff'
/**
* The sign-off refusals are composed in Swedish at the throw site (a date, an
* amount). Before these codes were registered, getErrorMessage() fell through
* to its generic fallback and the dialog showed "Något gick fel. Försök igen."
* for a refused sign-off.
*/
const CODES: SignoffErrorCode[] = [
'INVALID_DATE',
'DATE_IN_FUTURE',
'NOT_FETCHED_THROUGH',
'OUTSIDE_UNKNOWN',
'NOT_RECONCILED',
'NOTE_REQUIRED',
'ALREADY_SIGNED_OFF',
'SIGNOFF_NOT_FOUND',
'ALREADY_REOPENED',
'SIGNOFF_RACE',
'EXTERNAL_BALANCE_NOT_ALLOWED',
]
describe('reconciliation sign-off codes in the error registry', () => {
it('registers every code with a Swedish and an English message', () => {
for (const code of CODES) {
const entry = getErrorEntry(code)
expect(entry, code).toBeDefined()
expect(entry?.message_sv, code).toMatch(/\S/)
expect(entry?.message_en, code).toMatch(/\S/)
expect(entry?.thrown_message_sv, code).toBe(true)
}
})
it('passes the thrown Swedish text through verbatim, runtime detail included', () => {
const err = new ReconciliationSignoffError(
'Skattekontot är hämtat t.o.m. 2026-08-20. Hämta igen innan du stämmer av ett senare datum.',
'NOT_FETCHED_THROUGH',
)
expect(getErrorMessage(err)).toBe(
'Skattekontot är hämtat t.o.m. 2026-08-20. Hämta igen innan du stämmer av ett senare datum.',
)
const refused = new ReconciliationSignoffError(
'Kontot har en oförklarad differens. Koppla eller bokför raderna först, eller signera med en notering.',
'NOT_RECONCILED',
{ unexplained_difference: 53717 },
)
expect(getErrorMessage(refused)).toBe(
'Kontot har en oförklarad differens. Koppla eller bokför raderna först, eller signera med en notering.',
)
expect(getErrorMessage(refused)).not.toMatch(/Något gick fel/)
})
it('gives English users the registry text', () => {
const err = new ReconciliationSignoffError('Kontot har en oförklarad differens.', 'NOT_RECONCILED')
expect(getErrorMessage(err, { locale: 'en' })).toBe(getErrorEntry('NOT_RECONCILED')?.message_en)
})
})