* chore: repo-wide bloat sweep, remove dead code and fold duplicate helpers Remove 33 dead files, ~270 unreferenced exports/types, 13 dead i18n namespaces and 4 unused dependencies; fold byte-identical helper copies into one canonical home each (lib/utils chunk/sleep/utcDateStamp, lib/dates/iso, lib/invariants/uuid, lib/xml/escape, lib/reports/sru/format, lib/pdf/number-text, lib/browser/panel-request, lib/api/v1/body + v1ValidationError rolled out to ~55 v1 routes, booking-template schemas). No behaviour change: v1 bodies and status codes, MCP tool schemas, DB writes and money math are untouched. Naive ore rounding was deliberately not swapped for roundOre; see DECISIONS.md 2026-09-02 for the full list of things left alone on purpose. tsc, lint, 19588 unit tests and check:guards green; antipattern baseline ratcheted (naive-ore-round 622 -> 620, hand-rolled-invariant 115 -> 113). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * test(transactions): import RawTransaction from @/types after the ingest re-export removal CI's type ratchet (check:types, full tsconfig) caught the one test file that still imported the type through lib/transactions/ingest. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
78 lines
2.2 KiB
TypeScript
78 lines
2.2 KiB
TypeScript
'use client'
|
|
|
|
import {
|
|
monthsBetween,
|
|
parseDateParts,
|
|
validatePeriodDuration,
|
|
} from '@/lib/bookkeeping/validate-period-duration'
|
|
import type { EntityType } from '@/types'
|
|
|
|
function endsOnDec31(end: string): boolean {
|
|
const e = parseDateParts(end)
|
|
return e.month === 12 && e.day === 31
|
|
}
|
|
|
|
/**
|
|
* Map validatePeriodDuration's English messages to user-facing Swedish copy.
|
|
*/
|
|
function toSwedishError(msg: string): string {
|
|
if (msg.includes('after period start')) return 'Slutdatum måste vara efter startdatum.'
|
|
if (msg.includes('1st of a month')) return 'Startdatum måste vara den första i månaden.'
|
|
if (msg.includes('last day of a month')) return 'Slutdatum måste vara den sista i månaden.'
|
|
if (msg.includes('exceeds maximum 18 months')) return 'Räkenskapsåret får vara högst 18 månader (BFL 3 kap.).'
|
|
return msg
|
|
}
|
|
|
|
export interface FiscalPeriodValidation {
|
|
/** User-facing Swedish error, or null if valid */
|
|
error: string | null
|
|
/** Integer month count, or null if inputs are incomplete/invalid */
|
|
months: number | null
|
|
/** True if inputs are complete enough to render the summary */
|
|
canSummarise: boolean
|
|
}
|
|
|
|
/**
|
|
* Validation for the first fiscal period, used by the settings
|
|
* FiscalPeriodEditor. Returns Swedish error copy.
|
|
*/
|
|
export function validateFirstPeriod(
|
|
startDate: string,
|
|
endDate: string,
|
|
entityType: EntityType | undefined
|
|
): FiscalPeriodValidation {
|
|
if (!startDate || !endDate) {
|
|
return { error: null, months: null, canSummarise: false }
|
|
}
|
|
if (endDate <= startDate) {
|
|
return {
|
|
error: 'Slutdatum måste vara efter startdatum.',
|
|
months: null,
|
|
canSummarise: false,
|
|
}
|
|
}
|
|
|
|
const baseError = validatePeriodDuration(startDate, endDate, { isFirstPeriod: true })
|
|
if (baseError) {
|
|
return {
|
|
error: toSwedishError(baseError),
|
|
months: monthsBetween(startDate, endDate),
|
|
canSummarise: true,
|
|
}
|
|
}
|
|
|
|
if (entityType === 'enskild_firma' && !endsOnDec31(endDate)) {
|
|
return {
|
|
error: 'Enskild firma måste ha slutdatum 31 december (BFL 3 kap.).',
|
|
months: monthsBetween(startDate, endDate),
|
|
canSummarise: true,
|
|
}
|
|
}
|
|
|
|
return {
|
|
error: null,
|
|
months: monthsBetween(startDate, endDate),
|
|
canSummarise: true,
|
|
}
|
|
}
|