'use client' import { useMemo, useState } from 'react' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { Checkbox } from '@/components/ui/checkbox' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { CheckCircle2, AlertTriangle } from 'lucide-react' import Link from 'next/link' import type { YearEndResult, ContinuityDiscrepancy } from '@/types' import { formatCurrency } from '@/lib/utils' import { formatVoucher } from '@/lib/bookkeeping/voucher-series-resolver' interface ResultStepProps { result: YearEndResult } const ORE_TOLERANCE = 0.005 export function ResultStep({ result }: ResultStepProps) { const [acknowledged, setAcknowledged] = useState(false) const continuity = result.continuity const discrepancies = continuity?.discrepancies ?? [] // If the wizard reached ResultStep, executeYearEndClosing already enforced // that no per-account diff exceeded ORE_TOLERANCE: but surface a panel // grouped by BAS class so the user can confirm visually before leaving. return (

Bokslutet är klart

Perioden är stängd och en ny räkenskapsperiod har skapats.

Resultat

{result.revaluationEntry && ( )} {result.resultAppropriationEntry && ( )}
{result.resultAppropriationFailed && (

Omföringen av föregående års resultat (2099 → 2098) kunde inte bokföras. {' '} Bokslutet och de ingående balanserna är klara, men konto 2099 “Årets resultat” bär fortfarande föregående års resultat in i den nya perioden. Det måste flyttas till 2098 innan balansräkningen stämmer. Kör om bokslutet eller kontakta support: felet är loggat.

)} {continuity && ( )}
) } function ResultRow({ label, value, href }: { label: string; value: string; href?: string }) { return (
{label} {href ? ( {value} ) : ( {value} )}
) } interface ContinuityPanelProps { discrepancies: ContinuityDiscrepancy[] checkedAccounts: number } function ContinuityPanel({ discrepancies, checkedAccounts }: ContinuityPanelProps) { const grouped = useMemo(() => { const byClass = new Map() for (const d of discrepancies) { const klass = parseInt(d.account_number[0]) || 0 if (klass !== 1 && klass !== 2) continue const list = byClass.get(klass) ?? [] list.push(d) byClass.set(klass, list) } return byClass }, [discrepancies]) const hasIssues = discrepancies.some( (d) => Math.abs(d.difference) > ORE_TOLERANCE ) return (

IB/UB-avstämning

{hasIssues ? ( Avvikelser ) : ( Stämmer )}

{checkedAccounts} balanskonto(n) jämförda mellan utgående balans i stängd period och ingående balans i ny period.

{discrepancies.length === 0 ? (

Inga avvikelser. Alla balanskonton i klass 1 och 2 matchar inom tolerans (±0,005 SEK).

) : (
{[1, 2].map((klass) => { const rows = grouped.get(klass) ?? [] if (rows.length === 0) return null return (

Klass {klass}: {klass === 1 ? 'Tillgångar' : 'Skulder & eget kapital'}

Konto UB (föregående) IB (ny period) Diff Status {rows.map((d) => { const overTol = Math.abs(d.difference) > ORE_TOLERANCE return ( {d.account_number} {d.account_name} {formatCurrency(d.previous_ub_net)} {formatCurrency(d.current_ib_net)} {formatCurrency(d.difference)} {overTol ? ( Avviker ) : ( OK )} ) })}
) })}
)}
) }