fix(year-end): typed preflight blocker codes so remediation links render (#1420)
* fix(year-end): typed preflight blocker codes so remediation links render validateYearEndReadiness emits Swedish blocker strings but the wizard's BlockerRow matched English phrases, so no remediation link ever rendered, and the voucher-gap branch pointed at /bookkeeping/voucher-gaps which only exists as an API route. Blockers now carry stable machine codes end to end (YearEndBlockerCode on YearEndValidation.blockers, mirrored additively as blockerItems on BokslutReadinessReport); errors stays the plain string mirror so the v1 compliance check and MCP tool keep their exact shapes. BlockerRow matches on code and links only to pages that exist; the voucher-gap and dead-link branches are removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(year-end): code the unbooked-transaction blockers #1414 added #1414 landed two new blockers in validateYearEndReadiness using the old errors.push style, which this branch had already renamed to a typed blockers array. Merging main left them referencing a variable that no longer exists. Converted both to the typed scheme: UNBOOKED_TRANSACTIONS (the safety guard that stops executeYearEndClosing from aborting at the step 7 lock AFTER the closing entry posted at step 4) and UNBOOKED_CHECK_FAILED (the fail-closed variant). Neither behaviour changes; both keep their Swedish wording verbatim. The MCP year_end_readiness classifier now routes on the stable YearEndBlockerCode instead of regexing the Swedish message, with the wording heuristic kept as a fallback for an unmapped or legacy English message. The public `kind` values are unchanged, so MCP consumers see the same output; both new codes map to 'unbooked_transactions' as before, since an agent reacts to "we could not tell" the same way it reacts to a real count. UNBOOKED_TRANSACTIONS gets a /transactions remediation link in the preflight step: that page is where a transaction is booked or marked private, the two remedies the message names. UNBOOKED_CHECK_FAILED gets none: the remedy is to re-run the check. --------- Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Jakob Wennberg
Claude Fable 5
parent
31fba5e8f9
commit
78a37f6396
@@ -3399,8 +3399,38 @@ export interface SequenceMismatch {
|
||||
// Year-End Closing Types (Årsbokslut)
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* Stable machine codes for year-end readiness blockers. One code per
|
||||
* blockers.push site in validateYearEndReadiness: the wizard matches on
|
||||
* these to attach remediation links, so codes must never be renamed once
|
||||
* shipped. The Swedish message stays the display text.
|
||||
*/
|
||||
export type YearEndBlockerCode =
|
||||
| 'PERIOD_NOT_FOUND'
|
||||
| 'PERIOD_NOT_ENDED'
|
||||
| 'PERIOD_ALREADY_CLOSED'
|
||||
| 'CLOSING_ENTRY_EXISTS'
|
||||
| 'DRAFT_ENTRIES'
|
||||
| 'UNEXPLAINED_VOUCHER_GAP'
|
||||
| 'SEQUENCE_COUNTER_BEHIND'
|
||||
| 'TRIAL_BALANCE_UNBALANCED'
|
||||
| 'CONTINUITY_MISMATCH'
|
||||
| 'NEXT_PERIOD_HAS_IB'
|
||||
| 'UNBOOKED_TRANSACTIONS'
|
||||
| 'UNBOOKED_CHECK_FAILED'
|
||||
|
||||
export interface YearEndBlocker {
|
||||
code: YearEndBlockerCode
|
||||
/** Swedish, user-facing: bokslut is a stays-Swedish surface. */
|
||||
message: string
|
||||
}
|
||||
|
||||
export interface YearEndValidation {
|
||||
ready: boolean
|
||||
/** Blocking errors with stable machine codes. */
|
||||
blockers: YearEndBlocker[]
|
||||
/** Blocker messages only; mirrors `blockers`. Kept so existing consumers
|
||||
* of the string list (v1 compliance check, MCP tool) stay unchanged. */
|
||||
errors: string[]
|
||||
warnings: string[]
|
||||
draftCount: number
|
||||
|
||||
Reference in New Issue
Block a user