Files
accounted/lib/documents/__tests__/inbox-field-visibility.test.ts
T
d7320a6c87 feat(invoice-inbox): show receipt fields on receipts, invoice fields on invoices (#1426)
* feat(invoice-inbox): show receipt fields on receipts, invoice fields on invoices

A kassakvitto has no due date, no OCR reference, no invoice number and no
bankgiro: it is already paid. The rail rendered all four as empty boxes
anyway, so a perfectly extracted receipt looked like a failed extraction.
The date was mislabelled too: on a receipt the document date is the
purchase date, not a "Fakturadatum".

When extracted_data.documentKind is 'receipt' the rail now labels the date
"Inköpsdatum" and folds the five invoice-only fields behind a quiet "Visa
fakturafält (N)" link.

Two rules keep it safe when the classification is wrong: a field holding a
value is never hidden (a hybrid restaurangnota with an invoice number
still shows it), and the fold is one click from being undone.

Logic lives in lib/documents/inbox-field-visibility.ts rather than the
component: this repo has no jsdom or testing-library, so display rules are
only testable as a React-free module.

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

* fix(invoice-inbox): reset the invoice-field fold when switching documents

Review catch (PR Agent on #1426): showAllFields was component state with no
per-item reset, and EditableFieldsList stays mounted across selections in
the rail. Expanding "Visa fakturafält" on one receipt therefore left the
invoice-only fields open on the next document, which reads as if that one
carried them too.

Reset alongside drafts and edit provenance in the existing itemId effect,
and moved the declaration up next to the other state so it is defined
above its first use rather than relying on hoisting.

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

---------

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 20:26:16 +02:00

73 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect } from 'vitest'
import { selectInboxFields } from '@/lib/documents/inbox-field-visibility'
const FIELDS = [
{ key: 'supplier.name', label: 'Leverantör' },
{ key: 'totals.total', label: 'Totalt' },
{ key: 'totals.vatAmount', label: 'Moms' },
{ key: 'supplier.bankgiro', label: 'Bankgiro' },
{ key: 'supplier.plusgiro', label: 'Plusgiro' },
{ key: 'invoice.invoiceNumber', label: 'Fakturanr' },
{ key: 'invoice.paymentReference', label: 'OCR/Referens' },
{ key: 'invoice.invoiceDate', label: 'Fakturadatum' },
{ key: 'invoice.dueDate', label: 'Förfallodatum' },
]
const none = () => false
const keys = (r: { shown: { key: string }[] }) => r.shown.map((f) => f.key)
const labelOf = (r: { shown: { key: string; label: string }[] }, key: string) =>
r.shown.find((f) => f.key === key)?.label
describe('selectInboxFields', () => {
it('leaves invoices exactly as they are', () => {
for (const kind of ['supplier_invoice', 'government_letter', 'other', null, undefined]) {
const r = selectInboxFields({ documentKind: kind, fields: FIELDS, hasValue: none, showAll: false })
expect(keys(r)).toEqual(FIELDS.map((f) => f.key))
expect(r.hiddenCount).toBe(0)
expect(labelOf(r, 'invoice.invoiceDate')).toBe('Fakturadatum')
}
})
it('hides the five invoice-only fields on a receipt and counts them', () => {
const r = selectInboxFields({ documentKind: 'receipt', fields: FIELDS, hasValue: none, showAll: false })
expect(r.hiddenCount).toBe(5)
expect(keys(r)).toEqual([
'supplier.name',
'totals.total',
'totals.vatAmount',
'invoice.invoiceDate',
])
})
it('relabels the date as the purchase date on a receipt', () => {
const r = selectInboxFields({ documentKind: 'receipt', fields: FIELDS, hasValue: none, showAll: false })
expect(labelOf(r, 'invoice.invoiceDate')).toBe('Inköpsdatum')
})
it('NEVER hides a field that holds a value, even on a receipt', () => {
// Misclassification, or a hybrid restaurangnota carrying an invoice
// number: data must never disappear behind a heuristic.
const r = selectInboxFields({
documentKind: 'receipt',
fields: FIELDS,
hasValue: (k) => k === 'invoice.invoiceNumber',
showAll: false,
})
expect(keys(r)).toContain('invoice.invoiceNumber')
expect(r.hiddenCount).toBe(4)
})
it('showAll restores every field, still relabelled', () => {
const r = selectInboxFields({ documentKind: 'receipt', fields: FIELDS, hasValue: none, showAll: true })
expect(keys(r)).toEqual(FIELDS.map((f) => f.key))
expect(r.hiddenCount).toBe(0)
expect(labelOf(r, 'invoice.invoiceDate')).toBe('Inköpsdatum')
})
it('does not mutate the callers field list', () => {
const copy = FIELDS.map((f) => ({ ...f }))
selectInboxFields({ documentKind: 'receipt', fields: copy, hasValue: none, showAll: true })
expect(copy.find((f) => f.key === 'invoice.invoiceDate')?.label).toBe('Fakturadatum')
})
})