Founder test on a real company (2026-09-05): a supplier created from "Webhallen Oktober · Dataskärmar till kontoret" kept that text as its name, and the SCB facts fetched for the party were nowhere on the supplier page. - Företagsuppgifter on /suppliers/[id] and /customers/[id]: legal name, org number, VAT number, country, then the SCB facts under one source line, with "Hämta uppgifter" or "Hitta i företagsregistret" as the one action. The registry helpers move out of the dossier into RegistryFacts so the three surfaces share them. - The enrich route makes the registry's legal name the displayed name of the party and of supplier and customer rows that still carry the party's old name; all-capitals names are set in title case (lib/parties/registry-name.ts). Names a person set stay. - legacyLedgerKey: a party confirmed under the pre-2026-09-04 key keeps its vouchers, so a rebuild attaches the new key instead of offering the same company again. - GET /api/parties/[id] reports whether SCB is configured. Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
60 lines
2.2 KiB
TypeScript
60 lines
2.2 KiB
TypeScript
/**
|
|
* Registry facts as the dossier and the supplier and customer pages show
|
|
* them: which SCB fields, in what order, with what label, and how a coded
|
|
* or composite value prints. One module so the three surfaces cannot drift.
|
|
*/
|
|
import type { ReactNode } from 'react'
|
|
import type { Dossier } from '@/lib/parties/register'
|
|
|
|
export const REGISTRY_FIELDS = [
|
|
'f_tax',
|
|
'vat_registration',
|
|
'employer_registration',
|
|
'company_status',
|
|
'legal_form',
|
|
'bolagsverket_status',
|
|
'employees_band',
|
|
'turnover_band',
|
|
'industry',
|
|
'postal_address',
|
|
'seat',
|
|
'registered_at',
|
|
'active_since',
|
|
'active_until',
|
|
'phone',
|
|
'email',
|
|
'workplaces',
|
|
'trade_name',
|
|
] as const
|
|
|
|
/** Live registry facts, in the order the dossier shows them; the VAT number sits in its own row above. */
|
|
export function registryFacts(facts: Dossier['facts']): Dossier['facts'] {
|
|
const scb = facts.filter((f) => f.source === 'registry_scb')
|
|
return REGISTRY_FIELDS.flatMap((field) => scb.filter((f) => f.field === field))
|
|
}
|
|
|
|
export function registryLabel(t: (k: string) => string, field: string): string {
|
|
return REGISTRY_FIELDS.includes(field as (typeof REGISTRY_FIELDS)[number]) ? t(`fact_${field}`) : field
|
|
}
|
|
|
|
/** Coded facts show their label; address and seat compose; the rest print. */
|
|
export function registryValue(value: unknown): ReactNode {
|
|
if (value === null || value === undefined) return '·'
|
|
if (typeof value === 'string' || typeof value === 'number') return String(value)
|
|
const v = value as Record<string, unknown>
|
|
if (typeof v.label === 'string') {
|
|
const label = typeof v.year === 'string' && v.year ? `${v.label} (${v.year})` : v.label
|
|
return v.warning ? <span className="text-warning">{label}</span> : label
|
|
}
|
|
if ('street' in v || 'city' in v) {
|
|
return [v.co, v.street, [v.postal_code, v.city].filter(Boolean).join(' ')].filter(Boolean).join(', ')
|
|
}
|
|
if ('municipality' in v || 'municipality_code' in v) {
|
|
const parts = [v.municipality ?? v.municipality_code, v.county ?? v.county_code].filter(Boolean) as string[]
|
|
// "Stockholm, Stockholm": the county adds nothing when it repeats the municipality.
|
|
return parts.filter((x, i) => i === 0 || x !== parts[0]).join(', ')
|
|
}
|
|
if ('code' in v) return String(v.code)
|
|
return JSON.stringify(v)
|
|
}
|