@flowselections/layout-maker 1.36.7 → 1.45.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/components/AfleverbriefBuilderPage.d.ts +10 -0
- package/dist-lib/components/AfleverbriefBuilderPage.d.ts.map +1 -0
- package/dist-lib/components/AfleverbriefBuilderPage.js +101 -0
- package/dist-lib/components/BlokOntwerperPage.d.ts.map +1 -1
- package/dist-lib/components/BlokOntwerperPage.js +8 -3
- package/dist-lib/components/ComputersLijst.d.ts.map +1 -1
- package/dist-lib/components/ComputersLijst.js +1 -1
- package/dist-lib/components/FustKolomVolgorde.d.ts +11 -0
- package/dist-lib/components/FustKolomVolgorde.d.ts.map +1 -0
- package/dist-lib/components/FustKolomVolgorde.js +52 -0
- package/dist-lib/components/LayoutsPage.d.ts.map +1 -1
- package/dist-lib/components/LayoutsPage.js +10 -9
- package/dist-lib/components/PaginaDocument.d.ts +4 -1
- package/dist-lib/components/PaginaDocument.d.ts.map +1 -1
- package/dist-lib/components/PaginaDocument.js +10 -5
- package/dist-lib/components/PakbonBuilderPage.d.ts.map +1 -1
- package/dist-lib/components/PakbonBuilderPage.js +34 -14
- package/dist-lib/components/PakbonPreview.d.ts +4 -2
- package/dist-lib/components/PakbonPreview.d.ts.map +1 -1
- package/dist-lib/components/PakbonPreview.js +74 -24
- package/dist-lib/components/PakbonSectiesPanel.d.ts +5 -3
- package/dist-lib/components/PakbonSectiesPanel.d.ts.map +1 -1
- package/dist-lib/components/PakbonSectiesPanel.js +8 -5
- package/dist-lib/components/PdfMapToestemmingBanner.d.ts +2 -1
- package/dist-lib/components/PdfMapToestemmingBanner.d.ts.map +1 -1
- package/dist-lib/components/PdfMapToestemmingBanner.js +73 -14
- package/dist-lib/components/PdfVoorbeeld.d.ts +20 -0
- package/dist-lib/components/PdfVoorbeeld.d.ts.map +1 -0
- package/dist-lib/components/PdfVoorbeeld.js +95 -0
- package/dist-lib/components/PrintProgrammaUitleg.d.ts.map +1 -1
- package/dist-lib/components/PrintProgrammaUitleg.js +1 -1
- package/dist-lib/components/PrintQueuePage.d.ts.map +1 -1
- package/dist-lib/components/PrintQueuePage.js +81 -43
- package/dist-lib/components/PrintplekDetailPage.d.ts.map +1 -1
- package/dist-lib/components/PrintplekDetailPage.js +2 -2
- package/dist-lib/components/PrintplekWizard.d.ts.map +1 -1
- package/dist-lib/components/PrintplekWizard.js +6 -2
- package/dist-lib/components/ProductiebonBuilderPage.d.ts.map +1 -1
- package/dist-lib/components/ProductiebonBuilderPage.js +13 -7
- package/dist-lib/index.d.ts +16 -6
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +11 -5
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +3585 -1267
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +3585 -1267
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/moduleClient.d.ts +25898 -0
- package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -0
- package/dist-lib/integrations/supabase/moduleClient.js +29 -0
- package/dist-lib/integrations/supabase/types.d.ts +3607 -1265
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +1 -0
- package/dist-lib/lib/aiLayout.functions.d.ts +3585 -1267
- package/dist-lib/lib/aiLayout.functions.d.ts.map +1 -1
- package/dist-lib/lib/code128.d.ts +5 -0
- package/dist-lib/lib/code128.d.ts.map +1 -0
- package/dist-lib/lib/code128.js +51 -0
- package/dist-lib/lib/documentVoorbeeld.functions.d.ts +23 -0
- package/dist-lib/lib/documentVoorbeeld.functions.d.ts.map +1 -0
- package/dist-lib/lib/documentVoorbeeld.functions.js +37 -0
- package/dist-lib/lib/fontMetrics.d.ts +15 -0
- package/dist-lib/lib/fontMetrics.d.ts.map +1 -0
- package/dist-lib/lib/fontMetrics.js +118 -0
- package/dist-lib/lib/htmlNaarPdf.server.d.ts +2 -2
- package/dist-lib/lib/htmlNaarPdf.server.d.ts.map +1 -1
- package/dist-lib/lib/htmlNaarPdf.server.js +2 -1
- package/dist-lib/lib/htmlPdf.server.d.ts +11 -0
- package/dist-lib/lib/htmlPdf.server.d.ts.map +1 -1
- package/dist-lib/lib/htmlPdf.server.js +170 -9
- package/dist-lib/lib/layoutPreview.d.ts.map +1 -1
- package/dist-lib/lib/layoutPreview.js +6 -3
- package/dist-lib/lib/orderData.server.d.ts.map +1 -1
- package/dist-lib/lib/orderData.server.js +49 -16
- package/dist-lib/lib/pakbonBarcodeVerzoek.d.ts +39 -0
- package/dist-lib/lib/pakbonBarcodeVerzoek.d.ts.map +1 -0
- package/dist-lib/lib/pakbonBarcodeVerzoek.js +80 -0
- package/dist-lib/lib/pakbonBuilder.d.ts +90 -5
- package/dist-lib/lib/pakbonBuilder.d.ts.map +1 -1
- package/dist-lib/lib/pakbonBuilder.js +455 -58
- package/dist-lib/lib/pakbonContent.d.ts +41 -0
- package/dist-lib/lib/pakbonContent.d.ts.map +1 -0
- package/dist-lib/lib/pakbonContent.js +668 -0
- package/dist-lib/lib/pakbonDocument.d.ts +199 -0
- package/dist-lib/lib/pakbonDocument.d.ts.map +1 -0
- package/dist-lib/lib/pakbonDocument.js +735 -0
- package/dist-lib/lib/pakbonHtml.d.ts +21 -2
- package/dist-lib/lib/pakbonHtml.d.ts.map +1 -1
- package/dist-lib/lib/pakbonHtml.js +144 -36
- package/dist-lib/lib/pakbonPresentation.d.ts +8 -0
- package/dist-lib/lib/pakbonPresentation.d.ts.map +1 -0
- package/dist-lib/lib/pakbonPresentation.js +31 -0
- package/dist-lib/lib/pakbonScan.d.ts +44 -0
- package/dist-lib/lib/pakbonScan.d.ts.map +1 -0
- package/dist-lib/lib/pakbonScan.js +87 -0
- package/dist-lib/lib/pdfJobSaver.d.ts +10 -6
- package/dist-lib/lib/pdfJobSaver.d.ts.map +1 -1
- package/dist-lib/lib/pdfJobSaver.js +302 -99
- package/dist-lib/lib/pdfMap.d.ts +37 -2
- package/dist-lib/lib/pdfMap.d.ts.map +1 -1
- package/dist-lib/lib/pdfMap.js +120 -7
- package/dist-lib/lib/pdfOpslagStatus.d.ts +23 -0
- package/dist-lib/lib/pdfOpslagStatus.d.ts.map +1 -0
- package/dist-lib/lib/pdfOpslagStatus.js +74 -0
- package/dist-lib/lib/printApi.d.ts +31 -0
- package/dist-lib/lib/printApi.d.ts.map +1 -1
- package/dist-lib/lib/printApi.js +62 -1
- package/dist-lib/lib/printQueue.server.d.ts +13 -0
- package/dist-lib/lib/printQueue.server.d.ts.map +1 -1
- package/dist-lib/lib/printQueue.server.js +673 -96
- package/dist-lib/lib/printService.functions.d.ts +11840 -2568
- package/dist-lib/lib/printService.functions.d.ts.map +1 -1
- package/dist-lib/lib/profielHtml.d.ts.map +1 -1
- package/dist-lib/lib/profielHtml.js +8 -1
- package/dist-lib/lib/supabaseClient.d.ts +1 -3
- package/dist-lib/lib/supabaseClient.d.ts.map +1 -1
- package/dist-lib/lib/supabaseClient.js +4 -8
- package/dist-lib/lib/useDocumentData.d.ts +8 -0
- package/dist-lib/lib/useDocumentData.d.ts.map +1 -1
- package/dist-lib/lib/useDocumentData.js +1 -1
- package/dist-lib/lib/voorbeeldPrint.d.ts +3 -0
- package/dist-lib/lib/voorbeeldPrint.d.ts.map +1 -1
- package/dist-lib/lib/voorbeeldPrint.js +65 -17
- package/package.json +9 -2
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { type DemoOrder, type PakbonConfig } from "./pakbonBuilder.js";
|
|
2
|
-
/** Gegevensvorm van een pakbon.
|
|
3
|
-
export type PakbonOrder = DemoOrder
|
|
2
|
+
/** Gegevensvorm van een pakbon. Engine-metadata blijft naast ordergegevens beschikbaar. */
|
|
3
|
+
export type PakbonOrder = DemoOrder & {
|
|
4
|
+
barcode?: string;
|
|
5
|
+
cart?: {
|
|
6
|
+
cart_label?: string;
|
|
7
|
+
cart_index?: number;
|
|
8
|
+
cart_total?: number;
|
|
9
|
+
cart_id?: string;
|
|
10
|
+
cart_items?: unknown[];
|
|
11
|
+
barcode?: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
4
14
|
export interface PakbonLogo {
|
|
5
15
|
id: string;
|
|
6
16
|
naam?: string;
|
|
@@ -20,6 +30,15 @@ export interface PakbonRenderOpties {
|
|
|
20
30
|
logos?: PakbonLogo[];
|
|
21
31
|
/** Documentlogo: gebruikt wanneer een logoblok zelf geen logo heeft. */
|
|
22
32
|
logoId?: string | null;
|
|
33
|
+
/** Variant die uitsluitend door de Logistics Engine wordt bepaald. */
|
|
34
|
+
layoutVariant?: string | null;
|
|
35
|
+
/** Laat de vaste paginavoet weg (voor een tweede voorbeeldvariant). */
|
|
36
|
+
zonderPaginavoet?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Alleen voor "Voorbeeld printen": toont na de hele-karpagina's ook een
|
|
39
|
+
* deelkarpagina, net als het voorbeeld op het scherm.
|
|
40
|
+
*/
|
|
41
|
+
voorbeeldBeideVarianten?: boolean;
|
|
23
42
|
}
|
|
24
43
|
export declare function esc(v: unknown): string;
|
|
25
44
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pakbonHtml.d.ts","sourceRoot":"","sources":["../../src/lib/pakbonHtml.ts"],"names":[],"mappings":"AAUA,OAAO,
|
|
1
|
+
{"version":3,"file":"pakbonHtml.d.ts","sourceRoot":"","sources":["../../src/lib/pakbonHtml.ts"],"names":[],"mappings":"AAUA,OAAO,EAwBL,KAAK,SAAS,EAEd,KAAK,YAAY,EAGlB,MAAM,iBAAiB,CAAC;AAMzB,2FAA2F;AAC3F,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QACL,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAWD,wBAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAKtC;AAyBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAqF3D;AA4rBD,oEAAoE;AACpE,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,YAAY,GAAG,OAAO,EAC9B,KAAK,EAAE,WAAW,EAClB,MAAM,GAAE,kBAAuB,GAC9B,MAAM,CAyDR;AAgBD,gEAAgE;AAChE,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,YAAY,GAAG,OAAO,EAC9B,KAAK,EAAE,WAAW,EAClB,MAAM,GAAE,kBAAuB,GAC9B,MAAM,CAkFR;AAED,iEAAiE;AACjE,wBAAgB,oBAAoB,IAAI,WAAW,CAElD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,YAAY,GAAG,OAAO,EAC9B,KAAK,EAAE,WAAW,EAClB,MAAM,GAAE,kBAAuB,GAC9B,IAAI,CAsCN;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,YAAY,GAAG,OAAO,EAC9B,KAAK,EAAE,WAAW,EAClB,MAAM,GAAE,kBAAuB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAUf"}
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
// layoutconfiguratie en de echte ordergegevens. Zo tonen het live voorbeeld en
|
|
8
8
|
// de afdruk altijd exact dezelfde secties — inclusief de orderregels.
|
|
9
9
|
// ============================================================================
|
|
10
|
-
import { DEMO_ORDER, conditieContext, groepeerIdentiekeKarren, groepeerIdentiekeLagen, karBundelTekst, fustVerzamellijst, pickMethode, productVeldBreedtes,
|
|
10
|
+
import { DEMO_ORDER, deelkarVoorbeeldOrder, conditieContext, groepeerIdentiekeKarren, groepeerIdentiekeLagen, karBundelTekst, fustVerzamellijst, fustRegels, FUSTREGEL_LABELS, FUSTREGEL_RECHTS, pickMethode, pakbonLayoutVariant, productVeldBreedtes, sectieOnderdruktVoorVariant, laagBundelTekst, leesPakbonConfig, sectieZichtbaar, sorteerProducten, totalen, vulVeldcodes, } from "./pakbonBuilder.js";
|
|
11
11
|
import { haalPrintLogos } from "./logoLibrary.js";
|
|
12
|
+
import { code128BarsHtml } from "./code128.js";
|
|
13
|
+
import { karMetadata } from "./pakbonPresentation.js";
|
|
12
14
|
// --- kleine hulpjes ---------------------------------------------------------
|
|
13
15
|
const arr = (v) => (Array.isArray(v) ? v : []);
|
|
14
16
|
const opt = (s, key, fallback) => s.opties?.[key] ?? fallback;
|
|
@@ -24,6 +26,24 @@ const cel = (p, veld) => {
|
|
|
24
26
|
return "";
|
|
25
27
|
return String(p[veld] ?? "");
|
|
26
28
|
};
|
|
29
|
+
/** Rendert uitsluitend een bestaande barcodewaarde uit de Engine-payload. */
|
|
30
|
+
function barcodeHtml(value, hoogteMm = 15) {
|
|
31
|
+
const tekst = String(value ?? "").trim();
|
|
32
|
+
if (!tekst)
|
|
33
|
+
return "";
|
|
34
|
+
const hoogte = Number.isFinite(hoogteMm) && hoogteMm > 0 ? hoogteMm : 15;
|
|
35
|
+
return `<div class="barcode"><div class="barcode-bars" data-barcode="${esc(tekst)}" style="height:${hoogte}mm">${code128BarsHtml(tekst)}</div><div>${esc(tekst)}</div></div>`;
|
|
36
|
+
}
|
|
37
|
+
/** Barcode van één pakbon; bij één geselecteerde kar mag diens Engine-barcode worden gebruikt. */
|
|
38
|
+
function pakbonBarcode(order) {
|
|
39
|
+
const direct = String(order.barcode ?? order.cart?.barcode ?? "").trim();
|
|
40
|
+
if (direct)
|
|
41
|
+
return direct;
|
|
42
|
+
const karren = Array.isArray(order.karren) ? order.karren : [];
|
|
43
|
+
if (karren.length !== 1)
|
|
44
|
+
return undefined;
|
|
45
|
+
return String(karren[0]?.barcode ?? "").trim() || undefined;
|
|
46
|
+
}
|
|
27
47
|
/**
|
|
28
48
|
* Vult ontbrekende onderdelen aan met veilige lege waarden, zodat een module
|
|
29
49
|
* die maar een deel van de gegevens heeft nooit een lege of stukke pakbon
|
|
@@ -38,11 +58,21 @@ export function maakPakbonOrder(input) {
|
|
|
38
58
|
out[v] = b[v] === undefined || b[v] === null ? "" : String(b[v]);
|
|
39
59
|
return out;
|
|
40
60
|
};
|
|
61
|
+
const cart = (bron["cart"] && typeof bron["cart"] === "object" ? bron["cart"] : {});
|
|
62
|
+
const topBarcode = String(bron["barcode"] ?? cart["barcode"] ?? "").trim();
|
|
41
63
|
const karren = arr(bron["karren"]).map((k, i) => ({
|
|
42
64
|
karnummer: Number(k["karnummer"] ?? i + 1),
|
|
65
|
+
barcode: String(k["barcode"] ?? "").trim() || undefined,
|
|
43
66
|
route: String(k["route"] ?? ""),
|
|
44
67
|
chauffeur: String(k["chauffeur"] ?? ""),
|
|
45
68
|
gewicht: String(k["gewicht"] ?? ""),
|
|
69
|
+
cart_label: String(k["cart_label"] ?? k["cartLabel"] ?? cart["cart_label"] ?? cart["cartLabel"] ?? "").trim() || undefined,
|
|
70
|
+
cart_index: Number(k["cart_index"] ?? k["cartIndex"] ?? cart["cart_index"] ?? cart["cartIndex"] ?? 0) || undefined,
|
|
71
|
+
cart_total: Number(k["cart_total"] ?? k["cartTotal"] ?? cart["cart_total"] ?? cart["cartTotal"] ?? 0) || undefined,
|
|
72
|
+
cart_id: String(k["cart_id"] ?? k["cartId"] ?? cart["cart_id"] ?? cart["cartId"] ?? "").trim() || undefined,
|
|
73
|
+
cart_items: Array.isArray(k["cart_items"] ?? k["items"] ?? cart["cart_items"] ?? cart["items"])
|
|
74
|
+
? (k["cart_items"] ?? k["items"] ?? cart["cart_items"] ?? cart["items"])
|
|
75
|
+
: undefined,
|
|
46
76
|
gedeeld: k["gedeeld"] === true,
|
|
47
77
|
lagen: arr(k["lagen"]).map((l, j) => ({
|
|
48
78
|
laagnummer: Number(l["laagnummer"] ?? j + 1),
|
|
@@ -89,6 +119,17 @@ export function maakPakbonOrder(input) {
|
|
|
89
119
|
afleveradres: groep("afleveradres", ["naam", "adres", "plaats", "land"]),
|
|
90
120
|
factuuradres: groep("factuuradres", ["naam", "adres", "plaats", "land"]),
|
|
91
121
|
transport: groep("transport", ["transporteur", "route", "chauffeur", "track"]),
|
|
122
|
+
barcode: topBarcode || undefined,
|
|
123
|
+
cart: Object.keys(cart).length ? {
|
|
124
|
+
cart_label: String(cart["cart_label"] ?? cart["cartLabel"] ?? "").trim() || undefined,
|
|
125
|
+
cart_index: Number(cart["cart_index"] ?? cart["cartIndex"] ?? 0) || undefined,
|
|
126
|
+
cart_total: Number(cart["cart_total"] ?? cart["cartTotal"] ?? 0) || undefined,
|
|
127
|
+
cart_id: String(cart["cart_id"] ?? cart["cartId"] ?? "").trim() || undefined,
|
|
128
|
+
cart_items: Array.isArray(cart["cart_items"] ?? cart["items"])
|
|
129
|
+
? (cart["cart_items"] ?? cart["items"])
|
|
130
|
+
: undefined,
|
|
131
|
+
barcode: String(cart["barcode"] ?? "").trim() || undefined,
|
|
132
|
+
} : undefined,
|
|
92
133
|
karren,
|
|
93
134
|
};
|
|
94
135
|
}
|
|
@@ -310,19 +351,7 @@ function karKop(s, kar, velden, bundelTekst = "") {
|
|
|
310
351
|
.replace(/\{chauffeur\}/g, kar.chauffeur)
|
|
311
352
|
.replace(/\{lagen\}/g, String(kar.lagen.length))
|
|
312
353
|
.replace(/\{producten\}/g, String(kar.lagen.reduce((n, l) => n + l.producten.length, 0)));
|
|
313
|
-
const info =
|
|
314
|
-
if (velden.includes("lagen"))
|
|
315
|
-
info.push(`${kar.lagen.length} lagen`);
|
|
316
|
-
if (velden.includes("producten"))
|
|
317
|
-
info.push(`${kar.lagen.reduce((n, l) => n + l.producten.reduce((m, p) => m + p.aantal, 0), 0)} producten`);
|
|
318
|
-
if (velden.includes("gewicht") && kar.gewicht)
|
|
319
|
-
info.push(kar.gewicht);
|
|
320
|
-
if (velden.includes("chauffeur") && kar.chauffeur)
|
|
321
|
-
info.push(kar.chauffeur);
|
|
322
|
-
if (velden.includes("route") && kar.route)
|
|
323
|
-
info.push(kar.route);
|
|
324
|
-
if (kar.gedeeld)
|
|
325
|
-
info.push("gedeelde kar");
|
|
354
|
+
const info = karMetadata(kar, velden);
|
|
326
355
|
const toonNummer = velden.includes("karnummer");
|
|
327
356
|
if (!toonNummer && !info.length && !bundelTekst)
|
|
328
357
|
return "";
|
|
@@ -340,9 +369,7 @@ function karKop(s, kar, velden, bundelTekst = "") {
|
|
|
340
369
|
]
|
|
341
370
|
.filter(Boolean)
|
|
342
371
|
.join(" ");
|
|
343
|
-
return `<div class="karkop" style="${stijl}"><
|
|
344
|
-
.map((t) => `<span>${esc(t)}</span>`)
|
|
345
|
-
.join("")}</span></div>`;
|
|
372
|
+
return `<div class="karkop" style="${stijl}"><div class="karkop-titel">${links}</div>${info.length ? `<div class="karkop-meta">${esc(info.join(" · "))}</div>` : ""}</div>`;
|
|
346
373
|
}
|
|
347
374
|
function laagKop(s, laag, velden, compact, bundelTekst = "") {
|
|
348
375
|
const tekst = optS(s, "koptekst", "Laag {laag}").replace(/\{laag\}/g, String(laag.laagnummer));
|
|
@@ -361,20 +388,26 @@ function laagKop(s, laag, velden, compact, bundelTekst = "") {
|
|
|
361
388
|
info.push(laag.opmerking);
|
|
362
389
|
if (!velden.includes("laagnummer") && !info.length && !bundelTekst)
|
|
363
390
|
return "";
|
|
364
|
-
return `<div class="laagkop${compact ? " compact" : ""}"><
|
|
391
|
+
return `<div class="laagkop${compact ? " compact" : ""}"><div class="laagkop-titel">${velden.includes("laagnummer") ? esc(tekst) : ""}${bundelTekst ? ` <span class="bundel">${esc(bundelTekst)}</span>` : ""}</div>${info.length ? `<div class="laagkop-meta">${esc(info.join(" · "))}</div>` : ""}</div>`;
|
|
365
392
|
}
|
|
366
393
|
function bundelMelding(tekst) {
|
|
367
394
|
return `<div class="bundel">${esc(tekst)}</div>`;
|
|
368
395
|
}
|
|
369
396
|
function karBlok(s, kar, lagen, zoek, omkaderd, aantal = 1) {
|
|
370
|
-
//
|
|
371
|
-
|
|
397
|
+
// Alleen bij écht samengevoegde karren vervalt het unieke karnummer; een
|
|
398
|
+
// losse kar (bijv. met eigen Engine-barcode) houdt zijn eigen gegevens.
|
|
399
|
+
const bundelt = opt(s, "bundel_identiek", true) !== false && aantal > 1;
|
|
372
400
|
const velden = lijst(s, "velden").filter((v) => !(bundelt && (v === "karnummer" || v === "barcode" || v === "qrcode")));
|
|
373
401
|
const lagenSectie = zoek("lagen");
|
|
374
402
|
const productSectie = zoek("producten");
|
|
375
403
|
const fustSectie = zoek("fusten");
|
|
376
404
|
const lagenModus = lagenSectie ? optS(lagenSectie, "modus", "apart") : "geen";
|
|
377
405
|
let inhoud = karKop(s, kar, velden, karBundelTekst(aantal));
|
|
406
|
+
// De Engine-cartregels zijn selectie-/controlegegevens. De zichtbare
|
|
407
|
+
// productregels komen uitsluitend uit de ingestelde lagen/productsectie,
|
|
408
|
+
// net als in het live voorbeeld.
|
|
409
|
+
if (kar.barcode)
|
|
410
|
+
inhoud += barcodeHtml(kar.barcode);
|
|
378
411
|
if (lagen.length && lagenSectie && lagenModus !== "geen") {
|
|
379
412
|
const lVelden = lijst(lagenSectie, "velden");
|
|
380
413
|
const toonProducten = lagenModus !== "nummer" && lagenModus !== "regel";
|
|
@@ -403,9 +436,10 @@ const FUST_KOLOM_LABELS = {
|
|
|
403
436
|
locatie: "Locatie",
|
|
404
437
|
fustsoort: "Tray/fust",
|
|
405
438
|
planten_per_fust: "Pl./fust",
|
|
439
|
+
fust_aantal: "Fusten",
|
|
406
440
|
aantal: "Planten",
|
|
407
441
|
};
|
|
408
|
-
const FUST_RECHTS = new Set(["planten_per_fust", "aantal"]);
|
|
442
|
+
const FUST_RECHTS = new Set(["planten_per_fust", "fust_aantal", "aantal"]);
|
|
409
443
|
/** Verzamellijst met alle te picken fusten per fusttype. */
|
|
410
444
|
function fustVerzamellijstHtml(order, s) {
|
|
411
445
|
const groepen = fustVerzamellijst(order?.karren);
|
|
@@ -442,7 +476,9 @@ function fustVerzamellijstHtml(order, s) {
|
|
|
442
476
|
: "";
|
|
443
477
|
return `${kopTekst ? `<div class="sectitel">${esc(kopTekst)}</div>` : ""}${blokken}${totaalHtml}`;
|
|
444
478
|
}
|
|
445
|
-
function karrenHtml(s, order, zoek
|
|
479
|
+
function karrenHtml(s, order, zoek,
|
|
480
|
+
/** Kop die op iedere nieuwe karpagina wordt herhaald (HELE KAR / DEELKAR). */
|
|
481
|
+
paginaKop = "") {
|
|
446
482
|
const modus = optS(s, "modus", "pagina");
|
|
447
483
|
if (modus === "geen")
|
|
448
484
|
return "";
|
|
@@ -466,13 +502,13 @@ function karrenHtml(s, order, zoek) {
|
|
|
466
502
|
const laagGroepen = groepeerIdentiekeLagen(lagen, String(lagenModus) === "gebundeld");
|
|
467
503
|
laagGroepen.forEach((lg, j) => {
|
|
468
504
|
const breek = i > 0 || j > 0;
|
|
469
|
-
delen.push(`<div class="${breek ? "breekvoor" : ""}">${blokFrame(s, karBlok(s, kar, [lg.laag], zoek, modus === "blok" || modus === "passend", groep.aantal))}</div>`);
|
|
505
|
+
delen.push(`<div class="${breek ? "breekvoor" : ""}">${breek ? paginaKop : ""}${blokFrame(s, karBlok(s, kar, [lg.laag], zoek, modus === "blok" || modus === "passend", groep.aantal))}</div>`);
|
|
470
506
|
});
|
|
471
507
|
return;
|
|
472
508
|
}
|
|
473
509
|
const breek = i > 0 && perPagina;
|
|
474
510
|
const scheider = i > 0 && !perPagina ? scheidingHtml(scheiding) : "";
|
|
475
|
-
delen.push(`<div class="${breek ? "breekvoor" : ""} ${modus === "passend" ? "heelhouden" : ""}">${scheider}${blokFrame(s, karBlok(s, kar, lagen, zoek, modus === "blok" || modus === "passend", groep.aantal))}</div>`);
|
|
511
|
+
delen.push(`<div class="${breek ? "breekvoor" : ""} ${modus === "passend" ? "heelhouden" : ""}">${breek ? paginaKop : ""}${scheider}${blokFrame(s, karBlok(s, kar, lagen, zoek, modus === "blok" || modus === "passend", groep.aantal))}</div>`);
|
|
476
512
|
});
|
|
477
513
|
return delen.join("");
|
|
478
514
|
}
|
|
@@ -557,8 +593,38 @@ function sectieHtml(s, order, zoek, opties) {
|
|
|
557
593
|
.join("");
|
|
558
594
|
return titelHtml(s) + body;
|
|
559
595
|
}
|
|
596
|
+
case "fustregels": {
|
|
597
|
+
const velden = lijst(s, "velden").filter((v) => FUSTREGEL_LABELS[v]);
|
|
598
|
+
if (!velden.length)
|
|
599
|
+
return "";
|
|
600
|
+
const regels = fustRegels(order.karren, {
|
|
601
|
+
comprimeren: opt(s, "comprimeren", true) !== false,
|
|
602
|
+
sortering: optS(s, "sortering", "fustsoort"),
|
|
603
|
+
});
|
|
604
|
+
if (!regels.length)
|
|
605
|
+
return "";
|
|
606
|
+
const randen = opt(s, "randen", true) !== false;
|
|
607
|
+
const zebra = !!opt(s, "zebra", false);
|
|
608
|
+
const cls = randen ? "onder" : "";
|
|
609
|
+
const kop = opt(s, "toonKoppen", true) !== false
|
|
610
|
+
? `<tr>${velden
|
|
611
|
+
.map((v) => `<th class="${cls}"${FUSTREGEL_RECHTS.has(v) ? ' style="text-align:right"' : ""}>${esc(FUSTREGEL_LABELS[v])}</th>`)
|
|
612
|
+
.join("")}</tr>`
|
|
613
|
+
: "";
|
|
614
|
+
const rijen = regels
|
|
615
|
+
.map((r, i) => `<tr${zebra && i % 2 === 1 ? ' style="background:#f4f4f4"' : ""}>${velden
|
|
616
|
+
.map((v) => `<td class="${cls}"${FUSTREGEL_RECHTS.has(v) ? ' style="text-align:right"' : ""}>${esc(String(r[v] ?? ""))}</td>`)
|
|
617
|
+
.join("")}</tr>`)
|
|
618
|
+
.join("");
|
|
619
|
+
const totaalFusten = regels.reduce((n, r) => n + r.fust_aantal, 0);
|
|
620
|
+
const totaalPlanten = regels.reduce((n, r) => n + r.aantal, 0);
|
|
621
|
+
const totaal = opt(s, "toonTotaal", true) !== false
|
|
622
|
+
? `<div class="totalen" style="justify-content:flex-end"><span>${totaalFusten} fusten</span><span>${totaalPlanten} planten</span></div>`
|
|
623
|
+
: "";
|
|
624
|
+
return `${titelHtml(s)}<table class="regels">${kop}${rijen}</table>${totaal}`;
|
|
625
|
+
}
|
|
560
626
|
case "pickmethode":
|
|
561
|
-
if (optS(s, "methode", "kar")
|
|
627
|
+
if (optS(s, "methode", "kar") === "kar")
|
|
562
628
|
return "";
|
|
563
629
|
return fustVerzamellijstHtml(order, s);
|
|
564
630
|
case "karren":
|
|
@@ -591,8 +657,11 @@ function sectieHtml(s, order, zoek, opties) {
|
|
|
591
657
|
return `<div class="${opt(s, "kader", false) ? "kader" : ""}" style="font-size:${Number(opt(s, "fontgrootte", 9))}pt">${esc(vulVeldcodes(optS(s, "tekst", ""), order))}</div>`;
|
|
592
658
|
case "qrcode":
|
|
593
659
|
return `<div><div class="qr" style="width:${Number(opt(s, "grootte", 25))}mm;height:${Number(opt(s, "grootte", 25))}mm"></div><div class="klein">${esc(vulVeldcodes(optS(s, "waarde", ""), order))}</div></div>`;
|
|
594
|
-
case "barcode":
|
|
595
|
-
|
|
660
|
+
case "barcode": {
|
|
661
|
+
// Alleen de Engine-waarde mag op de pakbon komen; nooit een lokaal
|
|
662
|
+
// gegenereerde orderwaarde of een layout-default als barcode gebruiken.
|
|
663
|
+
return barcodeHtml(pakbonBarcode(order), Number(opt(s, "hoogte", 15)));
|
|
664
|
+
}
|
|
596
665
|
case "afbeelding": {
|
|
597
666
|
const url = optS(s, "url", "");
|
|
598
667
|
return url
|
|
@@ -610,20 +679,44 @@ export function renderPakbonBody(config, order, opties = {}) {
|
|
|
610
679
|
const ctx = conditieContext(order);
|
|
611
680
|
const alleSecties = arr(cfg.secties);
|
|
612
681
|
const methode = pickMethode(alleSecties);
|
|
613
|
-
const
|
|
682
|
+
const variant = pakbonLayoutVariant(opties.layoutVariant);
|
|
683
|
+
const secties = alleSecties.filter((s) => sectieZichtbaar(s, ctx) && !sectieOnderdruktVoorVariant(s.type, methode, variant));
|
|
684
|
+
const heeftKarBarcodes = secties.some((s) => s.type === "karren") &&
|
|
685
|
+
(Array.isArray(order.karren) ? order.karren : []).some((kar) => Boolean(String(kar.barcode ?? "").trim()));
|
|
614
686
|
const zoek = (t) => secties.find((s) => s.type === t);
|
|
615
687
|
const opts = { ...opties, logoId: opties.logoId ?? cfg.logo?.logoId ?? null };
|
|
616
|
-
const
|
|
688
|
+
const variantKop = variant
|
|
689
|
+
? `<div class="pakbonvariant">${variant === "full_cart" ? "HELE KAR" : "DEELKAR"}</div>`
|
|
690
|
+
: "";
|
|
691
|
+
const kop = variantKop + documentLogoHtml(cfg.logo, opts);
|
|
617
692
|
const totalenSectie = zoek("totalen");
|
|
618
693
|
const totalenElkePagina = !!totalenSectie && opt(totalenSectie, "elke_pagina", false) === true;
|
|
619
694
|
const inhoud = secties
|
|
620
695
|
.filter((s) => !(s.type === "totalen" && totalenElkePagina))
|
|
621
|
-
.
|
|
696
|
+
.filter((s) => !(s.type === "barcode" && heeftKarBarcodes))
|
|
697
|
+
.map((s) => s.type === "karren"
|
|
698
|
+
? karrenHtml(s, order, zoek, variantKop)
|
|
699
|
+
: blokFrame(s, sectieHtml(s, order, zoek, opts)))
|
|
622
700
|
.join("");
|
|
623
|
-
const
|
|
701
|
+
const pickSectie = alleSecties.find((s) => s.type === "pickmethode");
|
|
702
|
+
const pickInstellingen = pickSectie ?? alleSecties[0];
|
|
703
|
+
// Elke pakbon krijgt de Engine-barcode wanneer die is aangeleverd. Een
|
|
704
|
+
// expliciet barcodeblok rendert hem zelf; anders voegen we hem één keer
|
|
705
|
+
// automatisch toe. Zonder Engine-barcode wordt nooit een waarde verzonnen.
|
|
706
|
+
// De schakelaar staat op het pickmethodeblok (pakbon) of het
|
|
707
|
+
// handtekeningblok (afleverbrief); standaard staat de barcode aan.
|
|
708
|
+
const barcodeSchakelaarSectie = pickSectie ?? alleSecties.find((s) => s.type === "handtekening");
|
|
709
|
+
const barcodeAan = barcodeSchakelaarSectie
|
|
710
|
+
? opt(barcodeSchakelaarSectie, "toonBarcode", true) !== false
|
|
711
|
+
: true;
|
|
712
|
+
const automatischeBarcode = barcodeAan && !heeftKarBarcodes && !secties.some((s) => s.type === "barcode");
|
|
713
|
+
const barcode = automatischeBarcode
|
|
714
|
+
? barcodeHtml(pakbonBarcode(order), Number(pickInstellingen ? opt(pickInstellingen, "barcodeHoogte", 15) : 15))
|
|
715
|
+
: "";
|
|
716
|
+
const voet = totalenElkePagina && totalenSectie && !opties.zonderPaginavoet
|
|
624
717
|
? `<div class="paginavoet">${sectieHtml(totalenSectie, order, zoek, opts)}</div>`
|
|
625
718
|
: "";
|
|
626
|
-
return kop + inhoud + voet;
|
|
719
|
+
return kop + inhoud + (barcode ? `<div class="blok">${barcode}</div>` : "") + voet;
|
|
627
720
|
}
|
|
628
721
|
/** Het documentlogo bovenaan de pakbon. */
|
|
629
722
|
function documentLogoHtml(logoCfg, opties) {
|
|
@@ -642,7 +735,18 @@ export function renderPakbonDocument(config, order, opties = {}) {
|
|
|
642
735
|
const marge = opties.margeMm ?? 12;
|
|
643
736
|
const font = opties.lettertype ?? 'Arial, Helvetica, "Segoe UI", sans-serif';
|
|
644
737
|
const grootte = opties.lettergrootte ?? 8.5;
|
|
645
|
-
|
|
738
|
+
let body = renderPakbonBody(config, order, opties);
|
|
739
|
+
if (opties.voorbeeldBeideVarianten) {
|
|
740
|
+
// Zelfde opbouw als het voorbeeld op het scherm: eerst de hele karren,
|
|
741
|
+
// daarna één deelkarpagina zonder karindeling.
|
|
742
|
+
const deel = renderPakbonBody(config, deelkarVoorbeeldOrder(order), {
|
|
743
|
+
...opties,
|
|
744
|
+
layoutVariant: "partial_order",
|
|
745
|
+
zonderPaginavoet: true,
|
|
746
|
+
});
|
|
747
|
+
body = renderPakbonBody(config, order, { ...opties, layoutVariant: "full_cart" }) +
|
|
748
|
+
`<div class="breekvoor">${deel}</div>`;
|
|
749
|
+
}
|
|
646
750
|
// De layout bepaalt of er paginanummers op de afdruk komen; de PDF-motor
|
|
647
751
|
// leest dit uit de meta, zodat de wachtrij niets extra hoeft door te geven.
|
|
648
752
|
const totalen = arr(leesPakbonConfig(config).secties).find((s) => s.type === "totalen");
|
|
@@ -656,6 +760,7 @@ export function renderPakbonDocument(config, order, opties = {}) {
|
|
|
656
760
|
* { box-sizing: border-box; }
|
|
657
761
|
html, body { margin: 0; padding: 0; }
|
|
658
762
|
body { font-family: ${font}; font-size: ${grootte}pt; color: #111827; line-height: 1.35; }
|
|
763
|
+
.pakbonvariant { border-top: 0.6mm solid #111827; border-bottom: 0.6mm solid #111827; padding: 2mm 1mm; margin-bottom: 2mm; text-align: center; font-size: 15pt; font-weight: 800; line-height: 1.1; }
|
|
659
764
|
.blok { margin-bottom: 2mm; }
|
|
660
765
|
.sectitel { font-size: 90%; font-weight: 600; text-transform: uppercase; color: #6b7280; margin-bottom: 0.6mm; }
|
|
661
766
|
.fustgroepkop { display: flex; justify-content: space-between; font-weight: 600; color: #111827; border-bottom: 0.45mm solid #111827; padding-bottom: 0.5mm; margin-bottom: 0.6mm; }
|
|
@@ -681,10 +786,13 @@ tr.zebra td { background: #f3f4f6; }
|
|
|
681
786
|
.tweekolom { display: grid; grid-template-columns: 1fr 1fr; gap: 3mm; }
|
|
682
787
|
.karblok { margin-bottom: 2mm; }
|
|
683
788
|
.karblok.omkaderd { border: 0.25mm solid #d1d5db; border-radius: 1mm; padding: 1.5mm; }
|
|
684
|
-
.karkop { display:
|
|
789
|
+
.karkop { display: block; padding: 0.8mm 1.5mm; border-radius: 1mm; margin-bottom: 1mm; overflow-wrap: anywhere; }
|
|
790
|
+
.karkop-titel { font-weight: 700; }
|
|
791
|
+
.karkop-meta { margin-top: 0.4mm; font-size: 78%; font-weight: 400; color: #4b5563; overflow-wrap: anywhere; }
|
|
685
792
|
.bundel { display: inline-block; border: 0.3mm dashed #6b7280; border-radius: 1mm; padding: 0.4mm 1.5mm; margin-bottom: 1mm; font-weight: 700; text-transform: uppercase; letter-spacing: 0.2mm; font-size: 90%; }
|
|
686
793
|
.laag { margin-bottom: 1.5mm; }
|
|
687
|
-
.laagkop { display:
|
|
794
|
+
.laagkop { display: block; font-weight: 500; border-bottom: 0.2mm solid #d1d5db; padding-bottom: 0.4mm; margin-bottom: 0.6mm; overflow-wrap: anywhere; }
|
|
795
|
+
.laagkop-meta { margin-top: 0.25mm; font-size: 82%; font-weight: 400; color: #4b5563; overflow-wrap: anywhere; }
|
|
688
796
|
.laagkop.compact { border-bottom: none; }
|
|
689
797
|
.meta { display: flex; gap: 3mm; font-size: 88%; font-weight: 400; color: #4b5563; }
|
|
690
798
|
.totalen { display: flex; flex-wrap: wrap; gap: 5mm; border-top: 0.25mm solid #d1d5db; padding-top: 1.2mm; font-weight: 500; }
|
|
@@ -695,7 +803,7 @@ tr.zebra td { background: #f3f4f6; }
|
|
|
695
803
|
.lijn { border-top: 0.25mm solid #d1d5db; margin: 1.5mm 0; }
|
|
696
804
|
.balk { height: 1mm; background: #374151; margin: 1.5mm 0; }
|
|
697
805
|
.qr { border: 0.25mm dashed #9ca3af; }
|
|
698
|
-
.
|
|
806
|
+
.barcode { display:flex; flex-direction:column; align-items:center; gap:0.8mm; } .barcode-bars { width:45mm; display:flex; background:#fff; }
|
|
699
807
|
.klein { font-size: 85%; color: #6b7280; }
|
|
700
808
|
.breekvoor { break-before: page; page-break-before: always; }
|
|
701
809
|
.heelhouden { break-inside: avoid; page-break-inside: avoid; }
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DemoKar } from "./pakbonBuilder.js";
|
|
2
|
+
/**
|
|
3
|
+
* Canonieke zichtbare metadata van een kar. Zowel het live voorbeeld als de
|
|
4
|
+
* print-renderer gebruiken deze lijst, zodat geen van beide zelf regels kan
|
|
5
|
+
* toevoegen of in een andere volgorde kan zetten.
|
|
6
|
+
*/
|
|
7
|
+
export declare function karMetadata(kar: DemoKar, velden: string[]): string[];
|
|
8
|
+
//# sourceMappingURL=pakbonPresentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pakbonPresentation.d.ts","sourceRoot":"","sources":["../../src/lib/pakbonPresentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAqBpE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonieke zichtbare metadata van een kar. Zowel het live voorbeeld als de
|
|
3
|
+
* print-renderer gebruiken deze lijst, zodat geen van beide zelf regels kan
|
|
4
|
+
* toevoegen of in een andere volgorde kan zetten.
|
|
5
|
+
*/
|
|
6
|
+
export function karMetadata(kar, velden) {
|
|
7
|
+
const info = [];
|
|
8
|
+
if (velden.includes("lagen"))
|
|
9
|
+
info.push(`${kar.lagen.length} lagen`);
|
|
10
|
+
if (velden.includes("producten")) {
|
|
11
|
+
const aantal = kar.lagen.reduce((totaal, laag) => totaal + laag.producten.reduce((som, product) => som + product.aantal, 0), 0);
|
|
12
|
+
info.push(`${aantal} producten`);
|
|
13
|
+
}
|
|
14
|
+
if (velden.includes("gewicht") && kar.gewicht)
|
|
15
|
+
info.push(kar.gewicht);
|
|
16
|
+
if (velden.includes("chauffeur") && kar.chauffeur)
|
|
17
|
+
info.push(kar.chauffeur);
|
|
18
|
+
if (velden.includes("route") && kar.route)
|
|
19
|
+
info.push(kar.route);
|
|
20
|
+
if (kar.gedeeld)
|
|
21
|
+
info.push("gedeelde kar");
|
|
22
|
+
const label = kar.cart_label ||
|
|
23
|
+
(kar.cart_index && kar.cart_total ? `Kar ${kar.cart_index} van ${kar.cart_total}` : "");
|
|
24
|
+
if (label)
|
|
25
|
+
info.push(label);
|
|
26
|
+
if (kar.cart_id)
|
|
27
|
+
info.push(`ID ${kar.cart_id}`);
|
|
28
|
+
if (kar.cart_items?.length)
|
|
29
|
+
info.push(`${kar.cart_items.length} karregels`);
|
|
30
|
+
return info;
|
|
31
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type PakbonLayoutVariant } from "./pakbonBuilder.js";
|
|
2
|
+
export interface PakbonScanRegel {
|
|
3
|
+
artikelnummer: string;
|
|
4
|
+
artikelnaam: string;
|
|
5
|
+
potmaat: string;
|
|
6
|
+
kleur: string;
|
|
7
|
+
fustsoort: string;
|
|
8
|
+
planten_per_fust: number;
|
|
9
|
+
aantal: number;
|
|
10
|
+
fust_aantal: number;
|
|
11
|
+
}
|
|
12
|
+
export interface PakbonScanInhoud {
|
|
13
|
+
barcode: string;
|
|
14
|
+
order_ref: string | null;
|
|
15
|
+
order_nummer: string | null;
|
|
16
|
+
klant_naam: string | null;
|
|
17
|
+
klant_nummer: string | null;
|
|
18
|
+
cart_id: string | null;
|
|
19
|
+
cart_label: string | null;
|
|
20
|
+
cart_index: number | null;
|
|
21
|
+
cart_total: number | null;
|
|
22
|
+
layout_variant: PakbonLayoutVariant | null;
|
|
23
|
+
layout_id: string | null;
|
|
24
|
+
print_job_id: string | null;
|
|
25
|
+
is_herprint: boolean;
|
|
26
|
+
regels: PakbonScanRegel[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Bouwt de scanregel uit de order zoals die op de pakbon is gerenderd.
|
|
30
|
+
* Bij een deelkar (`partial_order`) staan uitsluitend de fusten van die
|
|
31
|
+
* deelkar op de pakbon, dus ook uitsluitend die regels in de registratie.
|
|
32
|
+
*/
|
|
33
|
+
export declare function bouwPakbonScanInhoud(order: unknown, opties: {
|
|
34
|
+
barcode: unknown;
|
|
35
|
+
layoutVariant?: PakbonLayoutVariant | null;
|
|
36
|
+
layoutId?: string | null;
|
|
37
|
+
printJobId?: string | null;
|
|
38
|
+
isHerprint?: boolean;
|
|
39
|
+
}): PakbonScanInhoud | null;
|
|
40
|
+
/** Slaat de scaninhoud op; een herprint werkt dezelfde barcode bij. */
|
|
41
|
+
export declare function bewaarPakbonScanInhoud(db: {
|
|
42
|
+
from: (tabel: string) => any;
|
|
43
|
+
}, inhoud: PakbonScanInhoud | null): Promise<void>;
|
|
44
|
+
//# sourceMappingURL=pakbonScan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pakbonScan.d.ts","sourceRoot":"","sources":["../../src/lib/pakbonScan.ts"],"names":[],"mappings":"AASA,OAAO,EAAuC,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEhG,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC3C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAWD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE;IACN,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GACA,gBAAgB,GAAG,IAAI,CA8DzB;AAED,uEAAuE;AACvE,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE;IAAE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAA;CAAE,EACpC,MAAM,EAAE,gBAAgB,GAAG,IAAI,GAC9B,OAAO,CAAC,IAAI,CAAC,CAMf"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/lib/pakbonScan.ts — registreert wat er achter een pakbonbarcode zit
|
|
3
|
+
// ----------------------------------------------------------------------------
|
|
4
|
+
// De barcodewaarde blijft eigendom van de Logistics Engine: deze module
|
|
5
|
+
// genereert of wijzigt nooit een barcode. Wel legt zij vast WAT er op de
|
|
6
|
+
// gedrukte pakbon staat, zodat een scanner daaruit een afleverbrief kan
|
|
7
|
+
// opbouwen: order, klant, kar en de gedrukte regels.
|
|
8
|
+
// ============================================================================
|
|
9
|
+
import { beperkTotDeelkar, fustVerzamellijst } from "./pakbonBuilder.js";
|
|
10
|
+
function tekst(waarde) {
|
|
11
|
+
return waarde === undefined || waarde === null ? "" : String(waarde).trim();
|
|
12
|
+
}
|
|
13
|
+
function getal(waarde) {
|
|
14
|
+
const n = Number(waarde);
|
|
15
|
+
return Number.isFinite(n) && n !== 0 ? n : null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Bouwt de scanregel uit de order zoals die op de pakbon is gerenderd.
|
|
19
|
+
* Bij een deelkar (`partial_order`) staan uitsluitend de fusten van die
|
|
20
|
+
* deelkar op de pakbon, dus ook uitsluitend die regels in de registratie.
|
|
21
|
+
*/
|
|
22
|
+
export function bouwPakbonScanInhoud(order, opties) {
|
|
23
|
+
const barcode = tekst(opties.barcode);
|
|
24
|
+
if (!barcode)
|
|
25
|
+
return null;
|
|
26
|
+
const ruw = (order && typeof order === "object" ? order : {});
|
|
27
|
+
// Restpakbon: precies dezelfde beperking als bij het afdrukken, zodat de
|
|
28
|
+
// scanner nooit meer regels terugkrijgt dan er op het vel staan.
|
|
29
|
+
const o = (opties.layoutVariant === "partial_order" ? beperkTotDeelkar(ruw) : ruw);
|
|
30
|
+
const alleKarren = Array.isArray(o["karren"]) ? o["karren"] : [];
|
|
31
|
+
const cart = (o["cart"] && typeof o["cart"] === "object" ? o["cart"] : {});
|
|
32
|
+
const cartId = tekst(cart["cart_id"]);
|
|
33
|
+
// Een order kan meerdere karren bevatten. Voor een deelkar mag de scanner
|
|
34
|
+
// nooit de inhoud van de andere karren terugkrijgen: selecteer dus eerst op
|
|
35
|
+
// het door de Engine meegestuurde cart_id.
|
|
36
|
+
const passendeKarren = cartId
|
|
37
|
+
? alleKarren.filter((kar) => tekst(kar["cart_id"]) === cartId)
|
|
38
|
+
: alleKarren;
|
|
39
|
+
const karren = passendeKarren.length ? passendeKarren : alleKarren;
|
|
40
|
+
const eersteKar = (karren[0] ?? {});
|
|
41
|
+
const regels = [];
|
|
42
|
+
for (const groep of fustVerzamellijst(karren)) {
|
|
43
|
+
for (const pr of groep.producten) {
|
|
44
|
+
const bestaand = regels.find((r) => r.artikelnummer === pr.artikelnummer && r.fustsoort === (pr.fustsoort || groep.fusttype));
|
|
45
|
+
if (bestaand) {
|
|
46
|
+
bestaand.aantal += Number(pr.aantal) || 0;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
regels.push({
|
|
50
|
+
artikelnummer: pr.artikelnummer,
|
|
51
|
+
artikelnaam: pr.artikelnaam,
|
|
52
|
+
potmaat: pr.potmaat,
|
|
53
|
+
kleur: pr.kleur,
|
|
54
|
+
fustsoort: pr.fustsoort || groep.fusttype,
|
|
55
|
+
planten_per_fust: Number(pr.planten_per_fust) || 0,
|
|
56
|
+
aantal: Number(pr.aantal) || 0,
|
|
57
|
+
fust_aantal: Number(pr.fust_aantal) || Number(groep.aantal) || 0,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
barcode,
|
|
63
|
+
order_ref: tekst(o["order"]?.referentie) || null,
|
|
64
|
+
order_nummer: tekst(o["order"]?.nummer) || null,
|
|
65
|
+
klant_naam: tekst(o["klant"]?.naam) || null,
|
|
66
|
+
klant_nummer: tekst(o["klant"]?.nummer) || null,
|
|
67
|
+
cart_id: tekst(cart["cart_id"] ?? eersteKar["cart_id"]) || null,
|
|
68
|
+
cart_label: tekst(cart["cart_label"] ?? eersteKar["cart_label"]) || null,
|
|
69
|
+
cart_index: getal(cart["cart_index"] ?? eersteKar["cart_index"]),
|
|
70
|
+
cart_total: getal(cart["cart_total"] ?? eersteKar["cart_total"]),
|
|
71
|
+
layout_variant: opties.layoutVariant ?? null,
|
|
72
|
+
layout_id: opties.layoutId ?? null,
|
|
73
|
+
print_job_id: opties.printJobId ?? null,
|
|
74
|
+
is_herprint: opties.isHerprint === true,
|
|
75
|
+
regels,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** Slaat de scaninhoud op; een herprint werkt dezelfde barcode bij. */
|
|
79
|
+
export async function bewaarPakbonScanInhoud(db, inhoud) {
|
|
80
|
+
if (!inhoud)
|
|
81
|
+
return;
|
|
82
|
+
const { error } = await db
|
|
83
|
+
.from("pakbon_barcode_inhoud")
|
|
84
|
+
.upsert({ ...inhoud, updated_at: new Date().toISOString() }, { onConflict: "barcode" });
|
|
85
|
+
if (error)
|
|
86
|
+
throw new Error(error.message ?? "Opslaan van pakbon-scaninhoud mislukt");
|
|
87
|
+
}
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
+
import { supabase } from "./supabaseClient.js";
|
|
1
2
|
type PdfServiceState = {
|
|
2
3
|
gestart: boolean;
|
|
3
4
|
bezig: boolean;
|
|
4
5
|
interval: number | null;
|
|
5
6
|
gemeldePrinters: Set<string>;
|
|
7
|
+
writerId: string;
|
|
8
|
+
kanaal?: ReturnType<typeof supabase.channel> | null;
|
|
6
9
|
};
|
|
7
10
|
declare global {
|
|
8
11
|
interface Window {
|
|
9
12
|
__layoutMakerPdfService?: PdfServiceState;
|
|
10
13
|
}
|
|
11
14
|
}
|
|
12
|
-
/**
|
|
15
|
+
/** Herstelt uitsluitend de lokale aflevering van een reeds gerenderde PDF. */
|
|
16
|
+
export declare function bewaarPdfJobOpnieuw(jobId: string): Promise<boolean>;
|
|
17
|
+
/** Downloadt exact het opgeslagen artefact; legacy jobs vallen terug op base64. */
|
|
18
|
+
export declare function downloadPdfJob(jobId: string, documentnaam: string): Promise<void>;
|
|
19
|
+
export declare function controleerPdfMap(printerId: string): Promise<"ok" | "map_ontbreekt" | "geen_rechten">;
|
|
13
20
|
export declare function startPdfMapService(): void;
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
* naar de map die op deze computer voor de virtuele printer is gekozen.
|
|
17
|
-
*/
|
|
18
|
-
export declare function bewaarPdfJobZodraKlaar(jobId: string, printerId: string): Promise<boolean>;
|
|
21
|
+
/** Wacht alleen op het eindresultaat; de singleton met databaseclaim schrijft. */
|
|
22
|
+
export declare function bewaarPdfJobZodraKlaar(jobId: string, _printerId: string): Promise<boolean>;
|
|
19
23
|
export {};
|
|
20
24
|
//# sourceMappingURL=pdfJobSaver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdfJobSaver.d.ts","sourceRoot":"","sources":["../../src/lib/pdfJobSaver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pdfJobSaver.d.ts","sourceRoot":"","sources":["../../src/lib/pdfJobSaver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAgC5C,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CACrD,CAAC;AAEF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,uBAAuB,CAAC,EAAE,eAAe,CAAC;KAC3C;CACF;AAiND,8EAA8E;AAC9E,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgCzE;AAED,mFAAmF;AACnF,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBvF;AAED,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,eAAe,GAAG,cAAc,CAAC,CAI1G;AAoCD,wBAAgB,kBAAkB,IAAI,IAAI,CA+BzC;AAED,kFAAkF;AAClF,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAehG"}
|