Files
accounted/lib/company/__tests__/connection-iban.test.ts
T
MattssonandClaude Fable 5 d0640e0968 fix(settings): clarify bankgiro source on Foretag tab, offer IBAN prefill from bank connection (#1695)
* fix(settings): stop registry bank data masquerading as a setting, offer IBAN from bank connection

User report: the Foretag tab shows a bankgiro from the Bolagsverket snapshot,
which reads as a configured setting while the field payment files and
invoices actually use (Fakturering) was empty.

- Note on the Foretag Bankuppgifter row: data is from Bolagsverket; the
  editable fields live under Installningar -> Fakturering.
- One-click IBAN prefill on the SEK payment account, sourced from the
  connected bank accounts (cash_accounts.iban). Deterministic: only offered
  when every connected account agrees on a single IBAN.
- Delete dead BankDetailsForm.tsx (unmounted since the settings
  restructure); its bank fields are edited via InvoicePaymentAccountsSettings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(settings): only suggest IBAN from enabled, still-connected SEK accounts

Skeptic refutation on the initial PR state: cash_accounts keeps rows after
disconnect (bank_connection_id nulled) and the connect picker mirrors
deselected accounts with enabled=false, so an unfiltered read could offer a
closed or third-party IBAN as the invoice payee / pain.001 sender. Filter on
enabled=true, currency=SEK and a non-null bank_connection_id, matching the
enable-banking session-sharing invariant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 17:18:51 +02:00

68 lines
2.0 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { formatIbanGroups, uniqueConnectionIban } from '../connection-iban'
const IBAN_A = 'SE3550000000054910000003'
const IBAN_B = 'SE4550000000058398257466'
describe('uniqueConnectionIban', () => {
it('returns null for non-array input', () => {
expect(uniqueConnectionIban(null)).toBeNull()
expect(uniqueConnectionIban(undefined)).toBeNull()
expect(uniqueConnectionIban('rows')).toBeNull()
expect(uniqueConnectionIban({ iban: IBAN_A })).toBeNull()
})
it('returns null for an empty result', () => {
expect(uniqueConnectionIban([])).toBeNull()
})
it('returns the IBAN when exactly one account carries one', () => {
expect(uniqueConnectionIban([{ iban: IBAN_A }])).toBe(IBAN_A)
})
it('normalises spacing and case', () => {
expect(uniqueConnectionIban([{ iban: 'se35 5000 0000 0549 1000 0003' }])).toBe(IBAN_A)
})
it('treats the same IBAN across several accounts as one', () => {
expect(
uniqueConnectionIban([
{ iban: IBAN_A },
{ iban: 'SE35 5000 0000 0549 1000 0003' },
]),
).toBe(IBAN_A)
})
it('returns null when accounts disagree: no guessing between banks', () => {
expect(uniqueConnectionIban([{ iban: IBAN_A }, { iban: IBAN_B }])).toBeNull()
})
it('skips rows without a usable IBAN', () => {
expect(
uniqueConnectionIban([
null,
'not-a-row',
{ iban: null },
{ iban: 42 },
{ iban: 'NOT-AN-IBAN' },
{ iban: IBAN_A },
]),
).toBe(IBAN_A)
})
it('returns null when only invalid IBANs exist', () => {
expect(uniqueConnectionIban([{ iban: 'SE12' }, { iban: '' }])).toBeNull()
})
})
describe('formatIbanGroups', () => {
it('groups the IBAN in blocks of four', () => {
expect(formatIbanGroups(IBAN_A)).toBe('SE35 5000 0000 0549 1000 0003')
})
it('leaves a trailing partial group intact', () => {
expect(formatIbanGroups('SE355000')).toBe('SE35 5000')
expect(formatIbanGroups('SE3550001')).toBe('SE35 5000 1')
})
})