39e407644d
- 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>
118 lines
2.9 KiB
TypeScript
118 lines
2.9 KiB
TypeScript
'use client'
|
|
|
|
import { getAccountDescription, type AccountType } from '@/lib/bookkeeping/account-descriptions'
|
|
import {
|
|
Tooltip,
|
|
TooltipTrigger,
|
|
TooltipContent,
|
|
TooltipProvider,
|
|
} from '@/components/ui/info-tooltip'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
const TYPE_COLORS: Record<AccountType, string> = {
|
|
asset: 'bg-green-500',
|
|
liability: 'bg-orange-500',
|
|
equity: 'bg-blue-500',
|
|
revenue: 'bg-purple-500',
|
|
expense: 'bg-red-500',
|
|
untaxed_reserves: 'bg-amber-500',
|
|
}
|
|
|
|
const TYPE_LABELS: Record<AccountType, string> = {
|
|
asset: 'Tillgång',
|
|
liability: 'Skuld',
|
|
equity: 'Eget kapital',
|
|
revenue: 'Intäkt',
|
|
expense: 'Kostnad',
|
|
untaxed_reserves: 'Obeskattade reserver',
|
|
}
|
|
|
|
interface AccountNumberProps {
|
|
number: string
|
|
name?: string
|
|
showName?: boolean
|
|
size?: 'sm' | 'default'
|
|
className?: string
|
|
}
|
|
|
|
export function AccountNumber({
|
|
number,
|
|
name,
|
|
showName,
|
|
size = 'default',
|
|
className,
|
|
}: AccountNumberProps) {
|
|
const desc = getAccountDescription(number)
|
|
const displayName = desc?.name ?? name
|
|
|
|
const numberElement = (
|
|
<span
|
|
className={cn(
|
|
'font-mono',
|
|
size === 'sm' ? 'text-xs' : 'text-sm',
|
|
className,
|
|
)}
|
|
>
|
|
{number}
|
|
</span>
|
|
)
|
|
|
|
if (!desc) {
|
|
return (
|
|
<>
|
|
{numberElement}
|
|
{showName && displayName && (
|
|
<span className="ml-1">{displayName}</span>
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<TooltipProvider delayDuration={200}>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<span
|
|
className={cn(
|
|
'inline-flex items-center gap-1 cursor-help',
|
|
'decoration-dotted underline underline-offset-4 decoration-muted-foreground/40',
|
|
)}
|
|
>
|
|
<span
|
|
className={cn(
|
|
'font-mono',
|
|
size === 'sm' ? 'text-xs' : 'text-sm',
|
|
className,
|
|
)}
|
|
>
|
|
{number}
|
|
</span>
|
|
{showName && displayName && (
|
|
<span className={size === 'sm' ? 'text-xs' : 'text-sm'}>
|
|
{displayName}
|
|
</span>
|
|
)}
|
|
</span>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="top" className="max-w-xs p-3">
|
|
<div className="space-y-1.5">
|
|
<div className="flex items-center gap-2">
|
|
<span className={cn('h-2 w-2 rounded-full shrink-0', TYPE_COLORS[desc.type])} />
|
|
<span className="text-xs text-muted-foreground">
|
|
{desc.classLabel} · {TYPE_LABELS[desc.type]}
|
|
</span>
|
|
</div>
|
|
<div className="font-medium">
|
|
<span className="font-mono mr-1.5">{number}</span>
|
|
{desc.name}
|
|
</div>
|
|
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
{desc.explanation}
|
|
</p>
|
|
</div>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</TooltipProvider>
|
|
)
|
|
}
|