feat: add foreign currency support, refactor bookkeeping engine, and improve invoice inbox document classification

- Add currency-utils module for SEK conversion with exchange rates
- Refactor createJournalEntry to use draft+commit flow preventing voucher number gaps (BFL 5 kap. 7§)
- Add foreign currency support to invoice entries with per-line SEK conversion
- Centralize category-to-account mapping into single source of truth
- Refactor invoice inbox to use shared document analyzer with document type classification (receipt, supplier invoice, government letter)
- Update mapping engine, supplier invoice entries, and transaction entries
- Fix report component rendering issues
- Add new validation schemas and tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-02-27 09:50:06 +01:00
co-authored by Claude Opus 4.6
parent 547fd053ec
commit 6f4573f380
33 changed files with 1365 additions and 497 deletions
@@ -1,6 +1,7 @@
'use client'
import type { AgingBucketsArtifact } from '@/types/chat'
import { formatCurrency } from '@/lib/utils'
const BUCKET_COLORS = [
'bg-green-500',
@@ -14,10 +15,6 @@ interface ChatAgingBucketsProps {
artifact: AgingBucketsArtifact
}
function formatAmount(amount: number): string {
return new Intl.NumberFormat('sv-SE').format(Math.round(amount))
}
export function ChatAgingBuckets({ artifact }: ChatAgingBucketsProps) {
const { title, buckets, total } = artifact
@@ -28,7 +25,7 @@ export function ChatAgingBuckets({ artifact }: ChatAgingBucketsProps) {
<div className="flex items-baseline justify-between mb-3">
<h4 className="text-sm font-semibold">{title}</h4>
<span className="text-sm font-bold tabular-nums">
{formatAmount(total)} kr
{formatCurrency(total)}
</span>
</div>
@@ -43,7 +40,7 @@ export function ChatAgingBuckets({ artifact }: ChatAgingBucketsProps) {
key={i}
className={`${BUCKET_COLORS[i % BUCKET_COLORS.length]} transition-all`}
style={{ width: `${widthPercent}%` }}
title={`${bucket.label}: ${formatAmount(bucket.amount)} kr`}
title={`${bucket.label}: ${formatCurrency(bucket.amount)}`}
/>
)
})}
@@ -65,7 +62,7 @@ export function ChatAgingBuckets({ artifact }: ChatAgingBucketsProps) {
{bucket.count} st
</span>
<span className="font-medium tabular-nums">
{formatAmount(bucket.amount)} kr
{formatCurrency(bucket.amount)}
</span>
</div>
</div>