- Readiness: all 18 checks (medicine lots, treatment log gaps, labels, harvest withdrawal), medicine subjects masked without veterinary-medicines:read, report PDF (counts only), summary cached 60 s, 409 codes READINESS_*. - Frontend: /compliance page with acknowledge/revoke, dashboard line and nav; veterinary medicine catalogue, lots, movement book with inventory and disposal; label designer check panel, print card with gap list and proof print, food business master data, product legal name. - Service worker: cacheability is path-based (the backend sends no-store on every answer); compliance, medicine, restriction, notice and label check/print paths and restricted document kinds are never cached. - ARCHITECTURE.md §2, §12.10–12.11, Annahmen 86–90. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
58 lines
1.9 KiB
TypeScript
58 lines
1.9 KiB
TypeScript
import { apiFetch, apiFetchBlob } from "@/lib/auth/api-client";
|
||
import { CreateLabelTemplateInput, LabelTemplate, UpdateLabelTemplateInput } from "./types";
|
||
|
||
export function fetchLabelTemplates(): Promise<LabelTemplate[]> {
|
||
return apiFetch<LabelTemplate[]>("/label-templates");
|
||
}
|
||
|
||
export function createLabelTemplate(input: CreateLabelTemplateInput): Promise<LabelTemplate> {
|
||
return apiFetch<LabelTemplate>("/label-templates", {
|
||
method: "POST",
|
||
body: JSON.stringify(input),
|
||
});
|
||
}
|
||
|
||
export function updateLabelTemplate(
|
||
id: string,
|
||
input: UpdateLabelTemplateInput,
|
||
): Promise<LabelTemplate> {
|
||
return apiFetch<LabelTemplate>(`/label-templates/${encodeURIComponent(id)}`, {
|
||
method: "PATCH",
|
||
body: JSON.stringify(input),
|
||
});
|
||
}
|
||
|
||
export function deactivateLabelTemplate(id: string): Promise<LabelTemplate> {
|
||
return apiFetch<LabelTemplate>(`/label-templates/${encodeURIComponent(id)}`, { method: "DELETE" });
|
||
}
|
||
|
||
export interface PrintLabelsOptions {
|
||
/** 1 = top left of the sheet; omitted prints from the start. */
|
||
startPosition?: number;
|
||
/** A test print stamped „MUSTER – nicht verkaufsfähig“; always allowed. */
|
||
proof?: boolean;
|
||
}
|
||
|
||
/**
|
||
* The label PDF. A 409 `LABEL_PARTICULARS_MISSING` throws an `ApiError` whose
|
||
* `body.gaps` lists what is missing (`labelParticularsMissing` reads it).
|
||
*/
|
||
export async function printLabels(
|
||
templateId: string,
|
||
bottlingBatchId: string,
|
||
options: PrintLabelsOptions = {},
|
||
): Promise<Blob> {
|
||
const params = new URLSearchParams();
|
||
if (options.startPosition && options.startPosition > 1) {
|
||
params.set("startPosition", String(options.startPosition));
|
||
}
|
||
if (options.proof) params.set("proof", "true");
|
||
const query = params.size > 0 ? `?${params.toString()}` : "";
|
||
const { blob } = await apiFetchBlob(
|
||
`/label-templates/${encodeURIComponent(templateId)}/print/${encodeURIComponent(bottlingBatchId)}${query}`,
|
||
"etiketten.pdf",
|
||
{ cache: "no-store" },
|
||
);
|
||
return blob;
|
||
}
|