feat(reports): bokslutsbilagor, the pärm per räkenskapsår (Reko bilagor, PR 4) (#1874)
* feat(reports): bokslutsbilagor, the pärm per räkenskapsår (Reko bilagor, PR 4) One bilaga per balance account as of the balansdag: IB, movement and UB from the trial balance, what it was reconciled against, the difference, the sign-off with who, when and note, and every attached file with its SHA-256; the closing checklist as the first page. JSON and PDF through /api/reports/bokslutsbilagor, in the reports library and on the Avstämning page, and written into every period folder of the full archive. Built from the attested rows, never by recomputing live status. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RvFveUpbdPBXdm7f5FEYoz * fix(reports): load the pärm renderer on demand in the full archive so PDF stubs elsewhere keep working Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RvFveUpbdPBXdm7f5FEYoz * fix(reconciliation): neutral rail dot for a manual account that is merely not attested yet An unsigned manual account without a system specification has nothing to compare against, so an amber dot read as a problem on every balance account of a freshly migrated company. Neutral until it is signed or a specification differs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RvFveUpbdPBXdm7f5FEYoz --------- Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
Jakob Wennberg
parent
c62321988b
commit
9ce1ebc65f
@@ -81,9 +81,17 @@ export function ReconciliationRail({ accounts, selectedKey, onSelect }: Reconcil
|
||||
return synced ? t('rail_synced', { date: formatDate(synced) }) : t('rail_never_synced')
|
||||
}
|
||||
|
||||
// A manual account with nothing to compare against is not a problem, just
|
||||
// not attested yet: neutral until it is signed or a specification differs.
|
||||
const dotState = (account: ReconciliationAccount): keyof typeof DOT_CLASS => {
|
||||
const state = account.status?.state ?? 'unknown'
|
||||
if (account.kind === 'manual' && state === 'open' && account.status?.unexplained_difference == null) return 'unknown'
|
||||
return state
|
||||
}
|
||||
|
||||
const renderRow = (account: ReconciliationAccount) => {
|
||||
const selected = account.account_key === selectedKey
|
||||
const state = account.status?.state ?? 'unknown'
|
||||
const state = dotState(account)
|
||||
const open = account.status
|
||||
? account.status.open_counts.proposed +
|
||||
account.status.open_counts.unmatched_external +
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
'use client'
|
||||
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import { Scale } from 'lucide-react'
|
||||
import { QUIET_LINK_CLASS } from '@/components/ui/dry-table'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { PageHeader } from '@/components/ui/page-header'
|
||||
import { HelpPopover } from '@/components/ui/help-popover'
|
||||
import { EmptyState } from '@/components/ui/empty-state'
|
||||
@@ -41,6 +44,7 @@ interface ReconciliationWorkspaceProps {
|
||||
|
||||
export function ReconciliationWorkspace({ initialPeriods, initialCompanyId }: ReconciliationWorkspaceProps) {
|
||||
const t = useTranslations('reconciliation')
|
||||
const tParm = useTranslations('bokslutsbilagor')
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const searchParams = useSearchParams()
|
||||
@@ -120,6 +124,9 @@ export function ReconciliationWorkspace({ initialPeriods, initialCompanyId }: Re
|
||||
}
|
||||
action={
|
||||
<div className="flex flex-wrap items-center justify-end gap-2">
|
||||
<Link href="/reports/bokslutsbilagor" className={cn(QUIET_LINK_CLASS, 'mr-2')}>
|
||||
{tParm('open_parm')}
|
||||
</Link>
|
||||
<SegmentedControl
|
||||
value={mode}
|
||||
onChange={setMode}
|
||||
|
||||
Reference in New Issue
Block a user