Classic now renders through buildRenderModel, computeFrame, the template and renderCore, with S.No and HSN/SAC columns, GST slots only through checked Slot components, taxable value, reverse-charge line, cancelled tag, continuation band and Page n of N. Letter absorbs its height deficit in elastic gaps. A harness runs 15 fixtures on A4 and Letter plus an item sweep and asserts zero audit errors, repeated headers, no split blocks, rupee extraction and deterministic output. The legacy InvoiceDocument is removed.
50 lines
1.8 KiB
TypeScript
50 lines
1.8 KiB
TypeScript
import type { MarginPreset, PageId } from "../engine/geometry";
|
|
|
|
/** Page and template choices frozen with an invoice at issue (stored as JSON). */
|
|
export interface RenderPrefsV1 {
|
|
version: 1;
|
|
templateId: string;
|
|
pageSize: PageId;
|
|
margins: MarginPreset;
|
|
logo?: {
|
|
/** The logo already contains the business name, so a template drops its own name lockup. */
|
|
useWordmark?: boolean;
|
|
};
|
|
}
|
|
|
|
export const DEFAULT_PREFS: RenderPrefsV1 = {
|
|
version: 1,
|
|
templateId: "classic",
|
|
pageSize: "A4",
|
|
margins: "template",
|
|
};
|
|
|
|
const PAGE_SIZE_IDS: readonly PageId[] = ["A4", "LETTER"];
|
|
const MARGIN_IDS: readonly MarginPreset[] = ["template", "narrow", "normal"];
|
|
|
|
/** Tolerant: anything unreadable or out of range falls back to the default for that field. */
|
|
export function parsePrefs(json: string | null | undefined): RenderPrefsV1 {
|
|
if (!json) return { ...DEFAULT_PREFS };
|
|
let raw: unknown;
|
|
try {
|
|
raw = JSON.parse(json);
|
|
} catch {
|
|
return { ...DEFAULT_PREFS };
|
|
}
|
|
if (typeof raw !== "object" || raw === null) return { ...DEFAULT_PREFS };
|
|
const o = raw as Record<string, unknown>;
|
|
const prefs: RenderPrefsV1 = {
|
|
version: 1,
|
|
templateId: typeof o.templateId === "string" && o.templateId ? o.templateId : DEFAULT_PREFS.templateId,
|
|
pageSize: PAGE_SIZE_IDS.includes(o.pageSize as PageId) ? (o.pageSize as PageId) : DEFAULT_PREFS.pageSize,
|
|
margins: MARGIN_IDS.includes(o.margins as MarginPreset) ? (o.margins as MarginPreset) : DEFAULT_PREFS.margins,
|
|
};
|
|
const logo = o.logo;
|
|
if (typeof logo === "object" && logo !== null && typeof (logo as { useWordmark?: unknown }).useWordmark === "boolean") {
|
|
prefs.logo = { useWordmark: (logo as { useWordmark: boolean }).useWordmark };
|
|
}
|
|
return prefs;
|
|
}
|
|
|
|
export const prefsToJson = (prefs: RenderPrefsV1): string => JSON.stringify(prefs);
|