feat: unified document inbox, full BAS 2026, and document-transaction matching
- 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>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
6956a757f3
commit
39e407644d
@@ -1,4 +1,4 @@
|
||||
import type { InboxItemStatus, InvoiceExtractionResult } from '@/types'
|
||||
import type { InboxItemStatus, InvoiceExtractionResult, DocumentClassificationType } from '@/types'
|
||||
|
||||
const STATUS_LABELS: Record<InboxItemStatus, string> = {
|
||||
pending: 'Väntar',
|
||||
@@ -51,3 +51,43 @@ export function formatExtractionSummary(
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,15 +72,15 @@ export const SECTORS: Sector[] = [
|
||||
},
|
||||
{
|
||||
slug: 'invoice-inbox',
|
||||
name: 'Leverantörsfaktura-inbox',
|
||||
name: 'Dokumentinkorg',
|
||||
sector: 'general',
|
||||
category: 'import',
|
||||
icon: 'Inbox',
|
||||
dataPattern: 'manual',
|
||||
hasOwnData: true,
|
||||
description: 'Ta emot leverantörsfakturor via e-post eller uppladdning',
|
||||
description: 'Ta emot alla dokument via e-post — fakturor, kvitton och myndighetspost',
|
||||
longDescription:
|
||||
'Skicka leverantörsfakturor till en dedikerad e-postadress eller ladda upp manuellt. AI extraherar automatiskt leverantörsdata, belopp och moms. Granska och bekräfta med ett klick för att skapa leverantörsfakturor.',
|
||||
'Skicka alla affärsdokument till en dedikerad e-postadress. AI klassificerar automatiskt dokumenttyp (faktura, kvitto, myndighetspost), extraherar data och matchar mot transaktioner. En inkorg för alla dokument.',
|
||||
},
|
||||
{
|
||||
slug: 'calendar',
|
||||
|
||||
@@ -13,7 +13,7 @@ const WORKSPACES: Record<WorkspaceKey, ComponentType<WorkspaceComponentProps>> =
|
||||
'general/ai-categorization': dynamic(() => import('@/components/extensions/general/AiCategorizationWorkspace')),
|
||||
'general/ai-chat': dynamic(() => import('@/components/extensions/general/AiChatWorkspace')),
|
||||
'general/push-notifications': dynamic(() => import('@/components/extensions/general/PushNotificationsWorkspace')),
|
||||
'general/invoice-inbox': dynamic(() => import('@/components/extensions/general/InvoiceInboxWorkspace')),
|
||||
'general/invoice-inbox': dynamic(() => import('@/components/extensions/general/DocumentInboxWorkspace')),
|
||||
'general/calendar': dynamic(() => import('@/components/extensions/general/CalendarWorkspace')),
|
||||
'general/enable-banking': dynamic(() => import('@/components/extensions/general/EnableBankingWorkspace')),
|
||||
'general/user-description-match': dynamic(() => import('@/components/extensions/general/UserDescriptionMatchWorkspace')),
|
||||
|
||||
Reference in New Issue
Block a user