- Expand BAS reference from ~180 to ~1,276 accounts (full BAS Kontoplan 2026) with K2 exclusion flags, per-class data files, and computed SRU codes - Evolve invoice inbox into unified document inbox handling invoices, receipts, and government letters with AI-powered classification (Claude Haiku Vision) - Add multi-pass document-to-transaction matching engine with greedy assignment for both supplier invoices (reference/amount/date/name) and receipts (weighted amount/merchant/date scoring) - Add supplier invoice matching in transaction ingest pipeline - Inject booking template suggestions into AI extraction prompts - Surface matched documents in swipe categorization UI with one-tap booking - Auto-activate missing BAS accounts during SIE import against full reference - Add K2 filter toggle in Chart of Accounts manager - Add receipt confirmation route with BFNAR representation fields - Add database migrations for K2 support and document matching columns - Remove obsolete extension migration scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
94 lines
2.6 KiB
TypeScript
94 lines
2.6 KiB
TypeScript
import type { InboxItemStatus, InvoiceExtractionResult, DocumentClassificationType } from '@/types'
|
|
|
|
const STATUS_LABELS: Record<InboxItemStatus, string> = {
|
|
pending: 'Väntar',
|
|
processing: 'Bearbetar',
|
|
ready: 'Klar',
|
|
confirmed: 'Bekräftad',
|
|
rejected: 'Avvisad',
|
|
error: 'Fel',
|
|
}
|
|
|
|
export function getStatusLabel(status: InboxItemStatus): string {
|
|
return STATUS_LABELS[status] ?? status
|
|
}
|
|
|
|
const STATUS_VARIANTS: Record<InboxItemStatus, string> = {
|
|
pending: 'secondary',
|
|
processing: 'default',
|
|
ready: 'warning',
|
|
confirmed: 'success',
|
|
rejected: 'destructive',
|
|
error: 'destructive',
|
|
}
|
|
|
|
export function getStatusVariant(status: InboxItemStatus): string {
|
|
return STATUS_VARIANTS[status] ?? 'outline'
|
|
}
|
|
|
|
export function getConfidenceLabel(confidence: number | null): { label: string; variant: string } {
|
|
if (confidence == null) {
|
|
return { label: 'Okänd', variant: 'outline' }
|
|
}
|
|
if (confidence >= 0.9) {
|
|
return { label: 'Hög', variant: 'success' }
|
|
}
|
|
if (confidence >= 0.7) {
|
|
return { label: 'Medium', variant: 'warning' }
|
|
}
|
|
return { label: 'Låg', variant: 'destructive' }
|
|
}
|
|
|
|
export function formatExtractionSummary(
|
|
data: InvoiceExtractionResult | null | undefined
|
|
): { supplierName: string; total: number; lineCount: number } {
|
|
if (!data) {
|
|
return { supplierName: '', total: 0, lineCount: 0 }
|
|
}
|
|
return {
|
|
supplierName: data.supplier?.name ?? '',
|
|
total: data.totals?.total ?? 0,
|
|
lineCount: data.lineItems?.length ?? 0,
|
|
}
|
|
}
|
|
|
|
// Document type labels (Swedish)
|
|
const DOCUMENT_TYPE_LABELS: Record<DocumentClassificationType, string> = {
|
|
supplier_invoice: 'Faktura',
|
|
receipt: 'Kvitto',
|
|
government_letter: 'Myndighetspost',
|
|
unknown: 'Övrigt',
|
|
}
|
|
|
|
export function getDocumentTypeLabel(type: DocumentClassificationType): string {
|
|
return DOCUMENT_TYPE_LABELS[type] ?? type
|
|
}
|
|
|
|
const DOCUMENT_TYPE_VARIANTS: Record<DocumentClassificationType, string> = {
|
|
supplier_invoice: 'default',
|
|
receipt: 'secondary',
|
|
government_letter: 'outline',
|
|
unknown: 'outline',
|
|
}
|
|
|
|
export function getDocumentTypeVariant(type: DocumentClassificationType): string {
|
|
return DOCUMENT_TYPE_VARIANTS[type] ?? 'outline'
|
|
}
|
|
|
|
/**
|
|
* Format extraction summary for receipt documents
|
|
*/
|
|
export function formatReceiptSummary(
|
|
data: Record<string, unknown> | null | undefined
|
|
): { merchantName: string; total: number } {
|
|
if (!data) {
|
|
return { merchantName: '', total: 0 }
|
|
}
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const d = data as any
|
|
return {
|
|
merchantName: d.merchant?.name ?? '',
|
|
total: d.totals?.total ?? 0,
|
|
}
|
|
}
|