fix(salary): make pain.001 betalfil generatable (company IBAN + BIC) (#950)
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>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
bacc5914af
commit
c1ea0d9bf2
@@ -147,6 +147,38 @@ describe('getErrorMessage: accumulated validation details', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('getErrorMessage: payment-file route messages surface (issue #945)', () => {
|
||||
// These specific { error: '...' } strings previously collapsed to the generic
|
||||
// HTTP-400 message because isSwedishUserMessage did not recognize "krävs" /
|
||||
// "saknar", so the user learned nothing about why the betalfil failed.
|
||||
it('surfaces a "saknar bankkontouppgifter" message instead of the generic 400', () => {
|
||||
const msg = getErrorMessage(
|
||||
{ error: '2 anställd(a) saknar bankkontouppgifter' },
|
||||
{ context: 'salary', statusCode: 400 },
|
||||
)
|
||||
expect(msg).toBe('2 anställd(a) saknar bankkontouppgifter')
|
||||
expect(msg).not.toBe('Förfrågan innehåller ogiltiga uppgifter.')
|
||||
})
|
||||
|
||||
it('surfaces a "... krävs ..." message instead of the generic 400', () => {
|
||||
const msg = getErrorMessage(
|
||||
{ error: 'Momsregistreringsnummer krävs när företaget är momsregistrerat (ML 11 kap. 8§)' },
|
||||
{ context: 'settings', statusCode: 400 },
|
||||
)
|
||||
expect(msg).toContain('krävs')
|
||||
expect(msg).not.toBe('Förfrågan innehåller ogiltiga uppgifter.')
|
||||
})
|
||||
|
||||
it('surfaces the missing company bank-account message', () => {
|
||||
const msg = getErrorMessage(
|
||||
{ error: 'Företagets bankkonto (clearingnummer och kontonummer) saknas i företagsinställningar. Fyll i det under Inställningar → Fakturering för att skapa betalfil.' },
|
||||
{ context: 'salary', statusCode: 400 },
|
||||
)
|
||||
expect(msg).toContain('Företagets bankkonto')
|
||||
expect(msg).not.toBe('Förfrågan innehåller ogiltiga uppgifter.')
|
||||
})
|
||||
})
|
||||
|
||||
describe('getErrorMessage: existing patterns still work', () => {
|
||||
it('regex match for "Entry date ... outside fiscal period" on plain string', () => {
|
||||
const msg = getErrorMessage('Entry date 2024-06-15 is outside fiscal period "FY 2025"')
|
||||
|
||||
@@ -166,6 +166,8 @@ function isSwedishUserMessage(message: string): boolean {
|
||||
/försök igen/i,
|
||||
/ogiltigt?/i,
|
||||
/saknas/i,
|
||||
/saknar/i,
|
||||
/krävs/i,
|
||||
/måste/i,
|
||||
/redan finns/i,
|
||||
/gick fel/i,
|
||||
|
||||
Reference in New Issue
Block a user