The ISO 20022 pain.001 salary payment file could never be generated: the
route required company_settings.iban/bic, but no settings screen wrote
those columns, so every request returned 400. The specific reason was
also swallowed by getErrorMessage (isSwedishUserMessage did not know
"krävs"/"saknar"), surfacing only the generic "Förfrågan innehåller
ogiltiga uppgifter" (issue #945).
- Add IBAN + BIC inputs to Settings > Fakturering > Bankuppgifter. BIC
auto-derives from the clearing number / bank already entered, so in
practice only the IBAN is typed. Validated client- and server-side.
- Route requires the company IBAN (canonical debtor form every Swedish
bank accepts) and derives the BIC, with clear actionable errors.
- Employees are unchanged: domestic clearing + account (BBAN), which is
what Swedish payroll collects. Only the company (debtor) uses IBAN.
- getErrorMessage recognizes "krävs"/"saknar" so payment-file reasons
surface instead of the generic 400.
Fixes#945
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Em dashes (—) and en dashes (–) had spread across comments, docs, tests,
and a few UI strings, reading as AI-generated boilerplate rather than
house style. Replaced each with punctuation matching its context: colon
for explanatory clauses, comma for asides, plain hyphen for numeric/legal
ranges (e.g. "21-23§"), "to"/"till" for date ranges, parentheses for
paired-dash asides. messages/en.json and messages/sv.json were fixed by
hand together to keep sv/en in sync.
Left untouched where the dash is the functional subject rather than
decorative punctuation: date-range-parser.ts's separator regex,
charset-repair.ts's CP1252 byte-mapping table (and its test), the SIE
encoding mojibake docs, generic-csv.ts's minus-sign normalizer, the
agent system-prompt files that already instruct against em dashes, and
a golden iXBRL test fixture compared byte-for-byte.
Also fixes two bugs surfaced along the way: an off-by-one in
ApiKeysPanel's scope-label split (a leftover from an earlier partial
pass), and a charset-repair test that had lost the literal en-dash it
exists to verify.
Regenerated the agent atom seed migration (skills:generate) since 27
SKILL.md files changed. Added a CLAUDE.md rule against em/en dashes,
with an explicit carve-out for the functional-dash cases above.
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* fix(invoices): apply configured voucher series to payments + preview next voucher
The booking engine resolves the series from
default_voucher_series_per_source_type, but the global "Standardserie"
dropdown wrote a separate field the engine ignored, and cash-method invoice
payments (invoice_cash_payment) weren't exposed in settings — so configured
series were silently dropped to "A".
- Expose cash/private payment source types in the per-source-type form
- Write the global default through to the map on save, keeping overrides
- Resolve voucher-sequences/next by source_type (+date) to match the engine
- Show the upcoming voucher (V2) in the payment dialog title
- Share resolveInvoicePaymentSourceType so preview and booking can't drift
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(salary): keep AGI panel in sync with Skatteverket signing state
The AGI panel mixed run-scoped generation state (agi_generated_at,
agi_declarations) with period-scoped submission state (extension_data
agi_submission_{period}), so the two could drift and present
contradictory UI. Reconcile them:
- Auto-detect a Mina Sidor BankID signature: while awaiting_signing,
poll /agi/kvittenser on mount and on tab refocus so the panel flips
to "signed" (hiding the signing actions) without a manual
"Hamta kvittens" click.
- Warn instead of offering to sign when the locked granskningsunderlag
predates the run's latest AGI generation (draftIsStale) — avoids
filing superseded figures.
- Self-heal a stale "AGI-XML saknas" error once the run's AGI is
(re)generated out-of-band (MCP/API/other tab).
- Refetch the salary run on tab focus so agi_generated_at reflects
out-of-band generation without a hard reload.
- /agi/lasUpp now clears the cached agi_submission_{period} record, so
unlocking drops the panel back to the pre-submission state instead of
stranding it on a released "redo att signeras" draft.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: Implement VAT registration handling and invoice item line types
- Added VAT registration check in commitCreateInvoice to set VAT rate to 0% for non-VAT registered companies.
- Updated invoice creation logic to reflect 'exempt' VAT treatment and adjusted related fields accordingly.
- Introduced support for free-text and blank spacer rows in invoice items by adding a new line_type field.
- Enhanced invoice and credit note handling to accommodate new line types.
- Added new localized messages for text rows in English and Swedish.
- Created tests for salary run approval logic, ensuring bank details are validated correctly.
- Implemented effective net payout calculation for salary runs, considering tax overrides.
- Added SQL migrations to support new invoice item line types and accounting method awareness for linking invoices to vouchers.
* feat(articles): artikelregister with revenue account + VAT rate per article
Article register (non-inventory) with per-article VAT rate and optional
BAS class-3 revenue-account override. Includes API routes, UI pages,
MCP tools, pending-operation staging, and the activate-or-create
account flow (ACCOUNTS_NOT_IN_CHART -> ActivateAccountsDialog,
unknown numbers -> AddAccountDialog) reusing the journal entry UX.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(bookkeeping): no-doc-required batch + bulk-missing endpoints
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(payments): supplier payment lines + cash-method invoice matching
Shared payment-line proposal for supplier invoices, improved
match-invoice/match-supplier-invoice flows (kontantmetoden-aware),
and voucher-link support without requiring a 151x clearing entry.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(bookkeeping): new journal entry dialog, SIE import tweaks, misc
New journal entry dialog component, journal list/page updates,
invoice editor updates, SIE import adjustments, transaction ingest
and api-key tweaks, pr-agent workflow update.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(invoices): implement tax reduction features and localization updates
* feat(tests): add VAT registration gate to pending operations commit tests
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(email): remove dead, diverged email-template forks (audit E2)
extensions/general/email/lib/{invoice,reminder}-templates.ts had zero importers and had diverged from the live lib/email/* copies (which carry later i18n / CSP / Räntelagen-dunning fixes). Pure deletion of a drift hazard.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(docker): hosted preset was missing skatteverket / invoice-inbox / document-extraction / cloud-backup (audit E7)
docker/extensions.hosted.json shipped only 5 of the 9 extensions in extensions.config.json — so a Docker 'hosted' image silently ran without Skatteverket filing, the invoice inbox, document extraction and cloud backup. Aligned with the hosted config.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(errors): return English error messages on the en locale (audit C9)
The structured-error branches in getErrorMessage returned hardcoded Swedish regardless of locale, so English users saw Swedish prose. For the en locale, prefer the registry's English message for any known code; the Swedish (default) path is left entirely unchanged, and codes absent from the registry still fall through. + regression test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Introduced new error classes for better error categorization:
- JournalEntryNotBalancedError
- FiscalPeriodNotFoundError
- EntryDateOutsideFiscalPeriodError
- JournalEntryNotFoundError
- CannotReverseNonPostedError
- CannotCorrectNonPostedError
- EntryAlreadyReversedError
- CurrencyRevaluationAlreadyExistsError
- InvalidMappingResultError
- BookkeepingDatabaseError
- Updated existing functions in engine.ts and transaction-entries.ts to throw specific errors instead of generic ones.
- Enhanced error response handling in get-error-message.ts to provide localized messages for new error types.
- Added unit tests for new error classes and error handling functions to ensure correctness and coverage.