@flowselections/pick-schermen-kwekers 1.0.2 → 1.0.3
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/PickPublicPage.d.ts +7 -0
- package/dist-lib/components/PickPublicPage.d.ts.map +1 -0
- package/dist-lib/components/PickPublicPage.js +19 -0
- package/dist-lib/components/PickstationsPage.d.ts.map +1 -1
- package/dist-lib/components/PickstationsPage.js +57 -14
- package/dist-lib/components/pick/LanguageTiles.d.ts +8 -0
- package/dist-lib/components/pick/LanguageTiles.d.ts.map +1 -0
- package/dist-lib/components/pick/LanguageTiles.js +11 -0
- package/dist-lib/components/pick/PickScherm.d.ts +6 -4
- package/dist-lib/components/pick/PickScherm.d.ts.map +1 -1
- package/dist-lib/components/pick/PickScherm.js +145 -61
- package/dist-lib/components/pick/QueueTable.d.ts +4 -1
- package/dist-lib/components/pick/QueueTable.d.ts.map +1 -1
- package/dist-lib/components/pick/QueueTable.js +11 -10
- package/dist-lib/hooks/usePickQueue.d.ts +7 -1
- package/dist-lib/hooks/usePickQueue.d.ts.map +1 -1
- package/dist-lib/hooks/usePickQueue.js +43 -6
- package/dist-lib/index.d.ts +5 -6
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +6 -12
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +8929 -5189
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +8929 -5189
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +8929 -5189
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +9245 -5437
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/layoutApi.d.ts +23 -0
- package/dist-lib/lib/layoutApi.d.ts.map +1 -0
- package/dist-lib/lib/layoutApi.js +94 -0
- package/dist-lib/lib/layoutMaker/documentProfiles.d.ts +50 -0
- package/dist-lib/lib/layoutMaker/documentProfiles.d.ts.map +1 -0
- package/dist-lib/lib/layoutMaker/documentProfiles.js +458 -0
- package/dist-lib/lib/layoutMaker/documentTypes.d.ts +123 -0
- package/dist-lib/lib/layoutMaker/documentTypes.d.ts.map +1 -0
- package/dist-lib/lib/layoutMaker/documentTypes.js +74 -0
- package/dist-lib/lib/layoutMaker/logoLibrary.d.ts +13 -0
- package/dist-lib/lib/layoutMaker/logoLibrary.d.ts.map +1 -0
- package/dist-lib/lib/layoutMaker/logoLibrary.js +54 -0
- package/dist-lib/lib/layoutMaker/pakbonBuilder.d.ts +196 -0
- package/dist-lib/lib/layoutMaker/pakbonBuilder.d.ts.map +1 -0
- package/dist-lib/lib/layoutMaker/pakbonBuilder.js +813 -0
- package/dist-lib/lib/layoutMaker/pakbonHtml.d.ts +48 -0
- package/dist-lib/lib/layoutMaker/pakbonHtml.d.ts.map +1 -0
- package/dist-lib/lib/layoutMaker/pakbonHtml.js +703 -0
- package/dist-lib/lib/layoutRenderer.d.ts +7 -0
- package/dist-lib/lib/layoutRenderer.d.ts.map +1 -0
- package/dist-lib/lib/layoutRenderer.js +233 -0
- package/dist-lib/lib/layoutTypes.d.ts +84 -0
- package/dist-lib/lib/layoutTypes.d.ts.map +1 -0
- package/dist-lib/lib/layoutTypes.js +25 -0
- package/dist-lib/lib/logisticsApi.d.ts +54 -0
- package/dist-lib/lib/logisticsApi.d.ts.map +1 -0
- package/dist-lib/lib/logisticsApi.js +72 -0
- package/dist-lib/lib/logisticsTypes.d.ts +34 -0
- package/dist-lib/lib/logisticsTypes.d.ts.map +1 -0
- package/dist-lib/lib/logisticsTypes.js +36 -0
- package/dist-lib/lib/orderContext.d.ts +50 -0
- package/dist-lib/lib/orderContext.d.ts.map +1 -0
- package/dist-lib/lib/orderContext.js +162 -0
- package/dist-lib/lib/pakbonOrderInput.d.ts +8 -0
- package/dist-lib/lib/pakbonOrderInput.d.ts.map +1 -0
- package/dist-lib/lib/pakbonOrderInput.js +150 -0
- package/dist-lib/lib/pickApi.d.ts +24 -1
- package/dist-lib/lib/pickApi.d.ts.map +1 -1
- package/dist-lib/lib/pickApi.js +46 -5
- package/dist-lib/lib/pickI18n.d.ts +14 -0
- package/dist-lib/lib/pickI18n.d.ts.map +1 -0
- package/dist-lib/lib/pickI18n.js +500 -0
- package/dist-lib/lib/pickPrint.d.ts +18 -0
- package/dist-lib/lib/pickPrint.d.ts.map +1 -0
- package/dist-lib/lib/pickPrint.js +184 -0
- package/dist-lib/lib/pickTypes.d.ts +1 -0
- package/dist-lib/lib/pickTypes.d.ts.map +1 -1
- package/package.json +5 -20
- package/dist-lib/components/PickBeheerPage.d.ts +0 -2
- package/dist-lib/components/PickBeheerPage.d.ts.map +0 -1
- package/dist-lib/components/PickBeheerPage.js +0 -84
- package/dist-lib/components/PickDashboardPage.d.ts +0 -2
- package/dist-lib/components/PickDashboardPage.d.ts.map +0 -1
- package/dist-lib/components/PickDashboardPage.js +0 -54
- package/dist-lib/components/PickKioskPage.d.ts +0 -7
- package/dist-lib/components/PickKioskPage.d.ts.map +0 -1
- package/dist-lib/components/PickKioskPage.js +0 -18
- package/dist-lib/components/PickstationDetailPage.d.ts +0 -6
- package/dist-lib/components/PickstationDetailPage.d.ts.map +0 -1
- package/dist-lib/components/PickstationDetailPage.js +0 -25
- package/dist-lib/components/pick/ConfigCrud.d.ts +0 -27
- package/dist-lib/components/pick/ConfigCrud.d.ts.map +0 -1
- package/dist-lib/components/pick/ConfigCrud.js +0 -64
- package/dist-lib/components/pick/CountryTiles.d.ts +0 -9
- package/dist-lib/components/pick/CountryTiles.d.ts.map +0 -1
- package/dist-lib/components/pick/CountryTiles.js +0 -13
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ResolvedLayout } from "./layoutTypes";
|
|
2
|
+
export declare function esc(value: unknown): string;
|
|
3
|
+
/** Leest een waarde uit de datacontext via een puntpad ("klant.naam", "regels.0.aantal"). */
|
|
4
|
+
export declare function readPath(data: unknown, path: string | null | undefined): unknown;
|
|
5
|
+
/** Bouwt een volledig printbaar HTML-document op basis van de layout. */
|
|
6
|
+
export declare function renderLayoutHtml(resolved: ResolvedLayout, data: unknown, locale?: string): string;
|
|
7
|
+
//# sourceMappingURL=layoutRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layoutRenderer.d.ts","sourceRoot":"","sources":["../../src/lib/layoutRenderer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,cAAc,EACf,MAAM,eAAe,CAAC;AAYvB,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM1C;AAOD,6FAA6F;AAC7F,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAUhF;AAkMD,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,SAAU,GAAG,MAAM,CAkClG"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
const PAPER_SIZES = {
|
|
2
|
+
A3: { w: 297, h: 420 },
|
|
3
|
+
A4: { w: 210, h: 297 },
|
|
4
|
+
A5: { w: 148, h: 210 },
|
|
5
|
+
A6: { w: 105, h: 148 },
|
|
6
|
+
A7: { w: 74, h: 105 },
|
|
7
|
+
LETTER: { w: 216, h: 279 },
|
|
8
|
+
LEGAL: { w: 216, h: 356 },
|
|
9
|
+
};
|
|
10
|
+
export function esc(value) {
|
|
11
|
+
return String(value ?? "")
|
|
12
|
+
.replace(/&/g, "&")
|
|
13
|
+
.replace(/</g, "<")
|
|
14
|
+
.replace(/>/g, ">")
|
|
15
|
+
.replace(/"/g, """);
|
|
16
|
+
}
|
|
17
|
+
function num(value, fallback = 0) {
|
|
18
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
19
|
+
return Number.isFinite(n) ? n : fallback;
|
|
20
|
+
}
|
|
21
|
+
/** Leest een waarde uit de datacontext via een puntpad ("klant.naam", "regels.0.aantal"). */
|
|
22
|
+
export function readPath(data, path) {
|
|
23
|
+
if (!path)
|
|
24
|
+
return undefined;
|
|
25
|
+
let current = data;
|
|
26
|
+
for (const part of String(path).split(".")) {
|
|
27
|
+
if (current === null || current === undefined)
|
|
28
|
+
return undefined;
|
|
29
|
+
const key = part.trim();
|
|
30
|
+
if (key === "")
|
|
31
|
+
continue;
|
|
32
|
+
current = Array.isArray(current) && /^\d+$/.test(key) ? current[Number(key)] : current[key];
|
|
33
|
+
}
|
|
34
|
+
return current;
|
|
35
|
+
}
|
|
36
|
+
function formatValue(value, stijl, locale) {
|
|
37
|
+
if (value === null || value === undefined || value === "")
|
|
38
|
+
return "";
|
|
39
|
+
const format = String(stijl?.["formaat"] ?? stijl?.["format"] ?? "").toLowerCase();
|
|
40
|
+
if (format === "datum" || format === "date") {
|
|
41
|
+
const d = new Date(String(value));
|
|
42
|
+
return Number.isNaN(d.getTime()) ? String(value) : d.toLocaleDateString(locale);
|
|
43
|
+
}
|
|
44
|
+
if (format === "datumtijd" || format === "datetime") {
|
|
45
|
+
const d = new Date(String(value));
|
|
46
|
+
return Number.isNaN(d.getTime()) ? String(value) : d.toLocaleString(locale);
|
|
47
|
+
}
|
|
48
|
+
if ((format === "bedrag" || format === "currency") && Number.isFinite(Number(value))) {
|
|
49
|
+
return new Intl.NumberFormat(locale, { style: "currency", currency: "EUR" }).format(Number(value));
|
|
50
|
+
}
|
|
51
|
+
if (typeof value === "boolean")
|
|
52
|
+
return value ? "✔" : "";
|
|
53
|
+
if (typeof value === "object")
|
|
54
|
+
return JSON.stringify(value);
|
|
55
|
+
return String(value);
|
|
56
|
+
}
|
|
57
|
+
/** Vervangt {{veldpad}} in vrije tekst door waarden uit de datacontext. */
|
|
58
|
+
function interpolate(text, data) {
|
|
59
|
+
return text.replace(/\{\{\s*([^}]+?)\s*\}\}/g, (_m, path) => {
|
|
60
|
+
const v = readPath(data, path);
|
|
61
|
+
return v === null || v === undefined ? "" : String(v);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function styleAttr(el, extra = []) {
|
|
65
|
+
const s = el.stijl ?? {};
|
|
66
|
+
const parts = [
|
|
67
|
+
`left:${num(el.x)}mm`,
|
|
68
|
+
`top:${num(el.y)}mm`,
|
|
69
|
+
];
|
|
70
|
+
if (el.breedte !== null && el.breedte !== undefined)
|
|
71
|
+
parts.push(`width:${num(el.breedte)}mm`);
|
|
72
|
+
if (el.hoogte !== null && el.hoogte !== undefined)
|
|
73
|
+
parts.push(`height:${num(el.hoogte)}mm`);
|
|
74
|
+
if (el.rotatie)
|
|
75
|
+
parts.push(`transform:rotate(${num(el.rotatie)}deg)`, "transform-origin:left top");
|
|
76
|
+
if (el.z_index !== null && el.z_index !== undefined)
|
|
77
|
+
parts.push(`z-index:${num(el.z_index)}`);
|
|
78
|
+
const map = {
|
|
79
|
+
fontFamily: "font-family",
|
|
80
|
+
lettertype: "font-family",
|
|
81
|
+
fontSize: "font-size",
|
|
82
|
+
lettergrootte: "font-size",
|
|
83
|
+
fontWeight: "font-weight",
|
|
84
|
+
dikte: "font-weight",
|
|
85
|
+
fontStyle: "font-style",
|
|
86
|
+
color: "color",
|
|
87
|
+
kleur: "color",
|
|
88
|
+
background: "background",
|
|
89
|
+
achtergrond: "background",
|
|
90
|
+
textAlign: "text-align",
|
|
91
|
+
uitlijning: "text-align",
|
|
92
|
+
lineHeight: "line-height",
|
|
93
|
+
regelafstand: "line-height",
|
|
94
|
+
letterSpacing: "letter-spacing",
|
|
95
|
+
padding: "padding",
|
|
96
|
+
border: "border",
|
|
97
|
+
borderRadius: "border-radius",
|
|
98
|
+
textTransform: "text-transform",
|
|
99
|
+
opacity: "opacity",
|
|
100
|
+
verticalAlign: "vertical-align",
|
|
101
|
+
};
|
|
102
|
+
for (const [key, css] of Object.entries(map)) {
|
|
103
|
+
const raw = s[key];
|
|
104
|
+
if (raw === undefined || raw === null || raw === "")
|
|
105
|
+
continue;
|
|
106
|
+
const value = typeof raw === "number" && ["font-size", "line-height", "letter-spacing"].includes(css)
|
|
107
|
+
? css === "line-height"
|
|
108
|
+
? String(raw)
|
|
109
|
+
: `${raw}pt`
|
|
110
|
+
: String(raw);
|
|
111
|
+
parts.push(`${css}:${value}`);
|
|
112
|
+
}
|
|
113
|
+
return [...parts, ...extra].join(";");
|
|
114
|
+
}
|
|
115
|
+
function renderTable(el, data, locale) {
|
|
116
|
+
const cfg = el.config ?? {};
|
|
117
|
+
const columns = Array.isArray(cfg["kolommen"])
|
|
118
|
+
? cfg["kolommen"]
|
|
119
|
+
: Array.isArray(cfg["columns"])
|
|
120
|
+
? cfg["columns"]
|
|
121
|
+
: [];
|
|
122
|
+
const rowsPath = el.veldpad ?? cfg["rijenpad"] ?? cfg["rowsPath"] ?? null;
|
|
123
|
+
const rows = readPath(data, rowsPath);
|
|
124
|
+
const list = Array.isArray(rows) ? rows : [];
|
|
125
|
+
const showHeader = cfg["kop"] !== false && cfg["header"] !== false;
|
|
126
|
+
const head = showHeader
|
|
127
|
+
? `<thead><tr>${columns
|
|
128
|
+
.map((c) => `<th style="${c?.breedte ? `width:${num(c.breedte)}mm;` : ""}text-align:${esc(c?.uitlijning ?? c?.align ?? "left")}">${esc(c?.label ?? c?.titel ?? c?.veldpad ?? "")}</th>`)
|
|
129
|
+
.join("")}</tr></thead>`
|
|
130
|
+
: "";
|
|
131
|
+
const body = list
|
|
132
|
+
.map((row) => `<tr>${columns
|
|
133
|
+
.map((c) => `<td style="text-align:${esc(c?.uitlijning ?? c?.align ?? "left")}">${esc(formatValue(readPath(row, c?.veldpad ?? c?.field ?? c?.key), c ?? null, locale))}</td>`)
|
|
134
|
+
.join("")}</tr>`)
|
|
135
|
+
.join("");
|
|
136
|
+
return `<div class="el" style="${styleAttr(el)}"><table class="lay-table">${head}<tbody>${body}</tbody></table></div>`;
|
|
137
|
+
}
|
|
138
|
+
function renderElement(el, resolved, data, locale) {
|
|
139
|
+
const type = String(el.type ?? "").toLowerCase();
|
|
140
|
+
const s = el.stijl ?? {};
|
|
141
|
+
if (["tabel", "table", "regels", "lines"].includes(type)) {
|
|
142
|
+
return renderTable(el, data, locale);
|
|
143
|
+
}
|
|
144
|
+
if (["logo", "afbeelding", "image", "img"].includes(type)) {
|
|
145
|
+
const logo = el.logo_id ? resolved.logos[el.logo_id] : undefined;
|
|
146
|
+
const src = logo?.bestand_url ?? el.content ?? "";
|
|
147
|
+
if (!src)
|
|
148
|
+
return "";
|
|
149
|
+
return `<div class="el" style="${styleAttr(el)}"><img src="${esc(src)}" style="width:100%;height:100%;object-fit:${esc(s["objectFit"] ?? "contain")}" alt="" /></div>`;
|
|
150
|
+
}
|
|
151
|
+
if (["lijn", "line", "scheiding", "divider"].includes(type)) {
|
|
152
|
+
const thickness = num(s["dikte"] ?? s["lineWidth"] ?? 0.3, 0.3);
|
|
153
|
+
const color = String(s["kleur"] ?? s["color"] ?? "#000");
|
|
154
|
+
const vertical = num(el.hoogte) > num(el.breedte);
|
|
155
|
+
const extra = vertical
|
|
156
|
+
? [`width:${thickness}mm`, `background:${color}`]
|
|
157
|
+
: [`height:${thickness}mm`, `background:${color}`];
|
|
158
|
+
return `<div class="el" style="${styleAttr(el, extra)}"></div>`;
|
|
159
|
+
}
|
|
160
|
+
if (["rechthoek", "rect", "box", "vlak", "kader"].includes(type)) {
|
|
161
|
+
const extra = [];
|
|
162
|
+
if (!s["border"] && (s["randdikte"] || s["borderWidth"])) {
|
|
163
|
+
extra.push(`border:${num(s["randdikte"] ?? s["borderWidth"], 0.3)}mm solid ${String(s["randkleur"] ?? s["borderColor"] ?? "#000")}`);
|
|
164
|
+
}
|
|
165
|
+
return `<div class="el" style="${styleAttr(el, extra)}"></div>`;
|
|
166
|
+
}
|
|
167
|
+
if (["barcode", "qr", "qrcode"].includes(type)) {
|
|
168
|
+
const raw = el.veldpad ? readPath(data, el.veldpad) : el.content;
|
|
169
|
+
const value = raw === null || raw === undefined ? "" : String(raw);
|
|
170
|
+
if (!value)
|
|
171
|
+
return "";
|
|
172
|
+
if (type === "barcode") {
|
|
173
|
+
return `<div class="el" style="${styleAttr(el)}"><div class="barcode">*${esc(value)}*</div><div class="barcode-text">${esc(value)}</div></div>`;
|
|
174
|
+
}
|
|
175
|
+
const url = `https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=${encodeURIComponent(value)}`;
|
|
176
|
+
return `<div class="el" style="${styleAttr(el)}"><img src="${esc(url)}" style="width:100%;height:100%;object-fit:contain" alt="" /></div>`;
|
|
177
|
+
}
|
|
178
|
+
// Tekst en velden (standaard)
|
|
179
|
+
const value = el.veldpad
|
|
180
|
+
? formatValue(readPath(data, el.veldpad), el.stijl, locale)
|
|
181
|
+
: interpolate(String(el.content ?? ""), data);
|
|
182
|
+
const prefix = el.stijl?.["prefix"] ? String(el.stijl["prefix"]) : "";
|
|
183
|
+
const suffix = el.stijl?.["suffix"] ? String(el.stijl["suffix"]) : "";
|
|
184
|
+
const text = value === "" ? "" : `${prefix}${value}${suffix}`;
|
|
185
|
+
const label = el.stijl?.["label"] ? `<span class="lbl">${esc(String(el.stijl["label"]))}</span> ` : "";
|
|
186
|
+
return `<div class="el" style="${styleAttr(el)}">${label}${esc(text).replace(/\n/g, "<br />")}</div>`;
|
|
187
|
+
}
|
|
188
|
+
function pageSize(layout) {
|
|
189
|
+
const ps = layout.page_settings ?? {};
|
|
190
|
+
let w = num(ps["breedte_mm"] ?? layout.breedte_mm, 0);
|
|
191
|
+
let h = num(ps["hoogte_mm"] ?? layout.hoogte_mm, 0);
|
|
192
|
+
if (!w || !h) {
|
|
193
|
+
const preset = PAPER_SIZES[String(layout.papierformaat ?? "A4").toUpperCase()] ?? PAPER_SIZES["A4"];
|
|
194
|
+
w = w || preset.w;
|
|
195
|
+
h = h || preset.h;
|
|
196
|
+
}
|
|
197
|
+
const landscape = String(ps["orientatie"] ?? layout.orientatie ?? "portrait").toLowerCase() === "landscape";
|
|
198
|
+
return landscape && w < h ? { w: h, h: w } : { w, h };
|
|
199
|
+
}
|
|
200
|
+
/** Bouwt een volledig printbaar HTML-document op basis van de layout. */
|
|
201
|
+
export function renderLayoutHtml(resolved, data, locale = "nl-NL") {
|
|
202
|
+
const { layout } = resolved;
|
|
203
|
+
const { w, h } = pageSize(layout);
|
|
204
|
+
const ps = layout.page_settings ?? {};
|
|
205
|
+
const mt = num(ps["marge_boven"] ?? layout.marge_boven, 0);
|
|
206
|
+
const mr = num(ps["marge_rechts"] ?? layout.marge_rechts, 0);
|
|
207
|
+
const mb = num(ps["marge_onder"] ?? layout.marge_onder, 0);
|
|
208
|
+
const ml = num(ps["marge_links"] ?? layout.marge_links, 0);
|
|
209
|
+
const cfg = layout.config ?? {};
|
|
210
|
+
const baseFont = String(cfg["lettertype"] ?? ps["lettertype"] ?? "Arial, Helvetica, sans-serif");
|
|
211
|
+
const baseSize = num(cfg["lettergrootte"] ?? ps["lettergrootte"], 10);
|
|
212
|
+
const body = resolved.elements
|
|
213
|
+
.map((el) => renderElement(el, resolved, data, locale))
|
|
214
|
+
.join("\n");
|
|
215
|
+
return `<!DOCTYPE html>
|
|
216
|
+
<html lang="nl"><head><meta charset="utf-8" />
|
|
217
|
+
<title>${esc(layout.naam)}</title>
|
|
218
|
+
<style>
|
|
219
|
+
@page { size: ${w}mm ${h}mm; margin: 0; }
|
|
220
|
+
* { box-sizing: border-box; }
|
|
221
|
+
html, body { margin: 0; padding: 0; }
|
|
222
|
+
body { font-family: ${baseFont}; font-size: ${baseSize}pt; color: #000; }
|
|
223
|
+
.page { position: relative; width: ${w}mm; height: ${h}mm; overflow: hidden; }
|
|
224
|
+
.content { position: absolute; left: ${ml}mm; top: ${mt}mm; right: ${mr}mm; bottom: ${mb}mm; }
|
|
225
|
+
.el { position: absolute; white-space: pre-wrap; }
|
|
226
|
+
.lbl { font-weight: 600; }
|
|
227
|
+
.lay-table { width: 100%; border-collapse: collapse; font-size: inherit; }
|
|
228
|
+
.lay-table th, .lay-table td { padding: 1mm 1.5mm; border-bottom: 0.2mm solid #999; vertical-align: top; }
|
|
229
|
+
.barcode { font-family: "Libre Barcode 39", monospace; font-size: 30pt; letter-spacing: 4px; line-height: 1; }
|
|
230
|
+
.barcode-text { font-size: 8pt; letter-spacing: 2px; }
|
|
231
|
+
</style></head>
|
|
232
|
+
<body><div class="page"><div class="content">${body}</div></div></body></html>`;
|
|
233
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export interface DocumentLayoutRow {
|
|
2
|
+
id: string;
|
|
3
|
+
naam: string;
|
|
4
|
+
documenttype: string;
|
|
5
|
+
papierformaat: string | null;
|
|
6
|
+
breedte_mm: number | null;
|
|
7
|
+
hoogte_mm: number | null;
|
|
8
|
+
orientatie: string | null;
|
|
9
|
+
marge_boven: number | null;
|
|
10
|
+
marge_onder: number | null;
|
|
11
|
+
marge_links: number | null;
|
|
12
|
+
marge_rechts: number | null;
|
|
13
|
+
huidige_versie: number | null;
|
|
14
|
+
page_settings: Record<string, any> | null;
|
|
15
|
+
config: Record<string, any> | null;
|
|
16
|
+
actief: boolean;
|
|
17
|
+
is_standaard: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface DocumentLayoutElementRow {
|
|
20
|
+
id: string;
|
|
21
|
+
layout_id: string;
|
|
22
|
+
element_key: string | null;
|
|
23
|
+
parent_key: string | null;
|
|
24
|
+
type: string;
|
|
25
|
+
content: string | null;
|
|
26
|
+
veldpad: string | null;
|
|
27
|
+
logo_id: string | null;
|
|
28
|
+
x: number | null;
|
|
29
|
+
y: number | null;
|
|
30
|
+
breedte: number | null;
|
|
31
|
+
hoogte: number | null;
|
|
32
|
+
rotatie: number | null;
|
|
33
|
+
z_index: number | null;
|
|
34
|
+
volgorde: number | null;
|
|
35
|
+
verborgen: boolean | null;
|
|
36
|
+
stijl: Record<string, any> | null;
|
|
37
|
+
config: Record<string, any> | null;
|
|
38
|
+
}
|
|
39
|
+
export interface LayoutLogoRow {
|
|
40
|
+
id: string;
|
|
41
|
+
naam: string;
|
|
42
|
+
bestand_url: string | null;
|
|
43
|
+
bestandspad: string | null;
|
|
44
|
+
}
|
|
45
|
+
export interface DocumentLayoutVariableRow {
|
|
46
|
+
id: string;
|
|
47
|
+
layout_id: string;
|
|
48
|
+
naam: string;
|
|
49
|
+
expressie: string | null;
|
|
50
|
+
}
|
|
51
|
+
export interface LayoutRef {
|
|
52
|
+
layoutId: string;
|
|
53
|
+
layoutName?: string | null;
|
|
54
|
+
layoutVersion?: number | null;
|
|
55
|
+
layoutDocumentType?: string | null;
|
|
56
|
+
}
|
|
57
|
+
export interface ResolvedLayout {
|
|
58
|
+
layout: DocumentLayoutRow;
|
|
59
|
+
elements: DocumentLayoutElementRow[];
|
|
60
|
+
variables: DocumentLayoutVariableRow[];
|
|
61
|
+
logos: Record<string, LayoutLogoRow>;
|
|
62
|
+
}
|
|
63
|
+
/** Eén sectie uit config.pakbon.secties van de Layout maker. */
|
|
64
|
+
export interface LayoutSectie {
|
|
65
|
+
id: string;
|
|
66
|
+
type: string;
|
|
67
|
+
titel?: string | null;
|
|
68
|
+
zichtbaar?: boolean;
|
|
69
|
+
opties?: Record<string, any> | null;
|
|
70
|
+
condities?: any[] | null;
|
|
71
|
+
}
|
|
72
|
+
/** Leest de sectie-opbouw uit de layoutrij; leeg als het geen sectie-layout is. */
|
|
73
|
+
export declare function layoutSecties(layout: DocumentLayoutRow): LayoutSectie[];
|
|
74
|
+
/** Wordt gegooid wanneer er geen actieve layout is ingesteld voor een documentsoort. */
|
|
75
|
+
export declare class MissingLayoutError extends Error {
|
|
76
|
+
documentType: string;
|
|
77
|
+
constructor(documentType: string);
|
|
78
|
+
}
|
|
79
|
+
/** Wordt gegooid wanneer de layout bestaat maar geen secties én geen elementen heeft. */
|
|
80
|
+
export declare class EmptyLayoutError extends Error {
|
|
81
|
+
layoutName: string;
|
|
82
|
+
constructor(layoutName: string);
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=layoutTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layoutTypes.d.ts","sourceRoot":"","sources":["../../src/lib/layoutTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Types voor documentlayouts uit de Layout maker (public.document_layouts e.v.).
|
|
2
|
+
// Deze module bevat GEEN eigen sjablonen: alles komt uit de database.
|
|
3
|
+
/** Leest de sectie-opbouw uit de layoutrij; leeg als het geen sectie-layout is. */
|
|
4
|
+
export function layoutSecties(layout) {
|
|
5
|
+
const cfg = layout.config ?? {};
|
|
6
|
+
const pakbon = cfg["pakbon"];
|
|
7
|
+
const secties = pakbon && typeof pakbon === "object" && !Array.isArray(pakbon) ? pakbon["secties"] : null;
|
|
8
|
+
return Array.isArray(secties) ? secties : [];
|
|
9
|
+
}
|
|
10
|
+
/** Wordt gegooid wanneer er geen actieve layout is ingesteld voor een documentsoort. */
|
|
11
|
+
export class MissingLayoutError extends Error {
|
|
12
|
+
constructor(documentType) {
|
|
13
|
+
super(`Geen layout ingesteld voor ${documentType}`);
|
|
14
|
+
this.name = "MissingLayoutError";
|
|
15
|
+
this.documentType = documentType;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** Wordt gegooid wanneer de layout bestaat maar geen secties én geen elementen heeft. */
|
|
19
|
+
export class EmptyLayoutError extends Error {
|
|
20
|
+
constructor(layoutName) {
|
|
21
|
+
super(`Layout heeft nog geen inhoud (${layoutName})`);
|
|
22
|
+
this.name = "EmptyLayoutError";
|
|
23
|
+
this.layoutName = layoutName;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type LogisticsTask } from "./logisticsTypes";
|
|
2
|
+
export declare const OWNER_MODULE = "pickschermen";
|
|
3
|
+
export type LogisticsEventInput = {
|
|
4
|
+
event_type: "order.received" | "order.changed" | "stock.changed" | string;
|
|
5
|
+
order_ref: string;
|
|
6
|
+
strategy_id?: string | null;
|
|
7
|
+
shadow?: boolean;
|
|
8
|
+
payload?: Record<string, any>;
|
|
9
|
+
};
|
|
10
|
+
/** Meldt een gebeurtenis aan de Engine door een rij in logistics_events te zetten. */
|
|
11
|
+
export declare function sendLogisticsEvent(input: LogisticsEventInput): Promise<{
|
|
12
|
+
ok: boolean;
|
|
13
|
+
}>;
|
|
14
|
+
/** Haalt openstaande taken op (standaard pick.execute), gesorteerd op planned_start. */
|
|
15
|
+
export declare function fetchLogisticsTasks(options?: {
|
|
16
|
+
type?: string | null;
|
|
17
|
+
statuses?: string[];
|
|
18
|
+
}): Promise<LogisticsTask[]>;
|
|
19
|
+
/** Meldt voortgang terug op de taakrij zelf. */
|
|
20
|
+
export declare function updateLogisticsTaskStatus(vars: {
|
|
21
|
+
taskId: string;
|
|
22
|
+
status: "in_progress" | "done" | "failed" | "skipped" | "cancelled" | string;
|
|
23
|
+
result?: Record<string, any> | null;
|
|
24
|
+
}): Promise<{
|
|
25
|
+
ok: boolean;
|
|
26
|
+
}>;
|
|
27
|
+
/** Alleen-lezen: strategieën en hun instellingen, uitsluitend om te tonen. */
|
|
28
|
+
export declare function fetchLogisticsStrategies(): Promise<{
|
|
29
|
+
color: string;
|
|
30
|
+
created_at: string;
|
|
31
|
+
description: string | null;
|
|
32
|
+
id: string;
|
|
33
|
+
is_active: boolean;
|
|
34
|
+
name: string;
|
|
35
|
+
priority: number;
|
|
36
|
+
updated_at: string;
|
|
37
|
+
updated_by: string | null;
|
|
38
|
+
user_id: string;
|
|
39
|
+
version: number;
|
|
40
|
+
}[]>;
|
|
41
|
+
export declare function fetchLogisticsRuleConfigs(): Promise<{
|
|
42
|
+
created_at: string;
|
|
43
|
+
current_version: number;
|
|
44
|
+
description: string | null;
|
|
45
|
+
id: string;
|
|
46
|
+
is_active: boolean;
|
|
47
|
+
name: string;
|
|
48
|
+
settings: import("../integrations/supabase/types").Json;
|
|
49
|
+
status: string;
|
|
50
|
+
strategy_id: string | null;
|
|
51
|
+
updated_at: string;
|
|
52
|
+
user_id: string;
|
|
53
|
+
}[]>;
|
|
54
|
+
//# sourceMappingURL=logisticsApi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logisticsApi.d.ts","sourceRoot":"","sources":["../../src/lib/logisticsApi.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAErE,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,gBAAgB,GAAG,eAAe,GAAG,eAAe,GAAG,MAAM,CAAC;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B,CAAC;AAEF,sFAAsF;AACtF,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB;;GAWlE;AAED,wFAAwF;AACxF,wBAAsB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAClD,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAyB3B;AAED,gDAAgD;AAChD,wBAAsB,yBAAyB,CAAC,IAAI,EAAE;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;CACrC;;GAWA;AAED,8EAA8E;AAC9E,wBAAsB,wBAAwB;;;;;;;;;;;;KAI7C;AAED,wBAAsB,yBAAyB;;;;;;;;;;;;KAI9C"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Koppeling met de Logistics Engine via de gedeelde Supabase-database.
|
|
2
|
+
// Geen secrets, geen HTTP-endpoints: gewoon tabellen lezen en schrijven.
|
|
3
|
+
import { supabase } from "../integrations/supabase/client";
|
|
4
|
+
import { normalizeTask } from "./logisticsTypes";
|
|
5
|
+
export const OWNER_MODULE = "pickschermen";
|
|
6
|
+
/** Meldt een gebeurtenis aan de Engine door een rij in logistics_events te zetten. */
|
|
7
|
+
export async function sendLogisticsEvent(input) {
|
|
8
|
+
const { error } = await supabase.from("logistics_events").insert({
|
|
9
|
+
source_module: OWNER_MODULE,
|
|
10
|
+
event_type: input.event_type,
|
|
11
|
+
order_ref: input.order_ref,
|
|
12
|
+
strategy_id: input.strategy_id ?? null,
|
|
13
|
+
shadow: input.shadow ?? true,
|
|
14
|
+
payload: input.payload ?? {},
|
|
15
|
+
});
|
|
16
|
+
if (error)
|
|
17
|
+
throw new Error(error.message);
|
|
18
|
+
return { ok: true };
|
|
19
|
+
}
|
|
20
|
+
/** Haalt openstaande taken op (standaard pick.execute), gesorteerd op planned_start. */
|
|
21
|
+
export async function fetchLogisticsTasks(options) {
|
|
22
|
+
const statuses = options?.statuses ?? ["planned", "ready", "in_progress"];
|
|
23
|
+
const type = options?.type === undefined ? "pick.execute" : options.type;
|
|
24
|
+
let query = supabase
|
|
25
|
+
.from("logistics_tasks")
|
|
26
|
+
.select("*")
|
|
27
|
+
.eq("owner_module", OWNER_MODULE)
|
|
28
|
+
.in("status", statuses)
|
|
29
|
+
.order("planned_start", { ascending: true });
|
|
30
|
+
if (type)
|
|
31
|
+
query = query.eq("task_type", type);
|
|
32
|
+
const { data, error } = await query;
|
|
33
|
+
if (error)
|
|
34
|
+
throw new Error(error.message);
|
|
35
|
+
const rows = Array.isArray(data) ? data : [];
|
|
36
|
+
return rows
|
|
37
|
+
.map(normalizeTask)
|
|
38
|
+
.filter((t) => t !== null)
|
|
39
|
+
.sort((a, b) => {
|
|
40
|
+
const av = a.planned_start ? new Date(a.planned_start).getTime() : Number.MAX_SAFE_INTEGER;
|
|
41
|
+
const bv = b.planned_start ? new Date(b.planned_start).getTime() : Number.MAX_SAFE_INTEGER;
|
|
42
|
+
return av - bv;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/** Meldt voortgang terug op de taakrij zelf. */
|
|
46
|
+
export async function updateLogisticsTaskStatus(vars) {
|
|
47
|
+
const patch = { status: vars.status };
|
|
48
|
+
if (vars.status === "in_progress")
|
|
49
|
+
patch.started_at = new Date().toISOString();
|
|
50
|
+
if (vars.status === "done" || vars.status === "failed") {
|
|
51
|
+
patch.completed_at = new Date().toISOString();
|
|
52
|
+
}
|
|
53
|
+
if (vars.result !== undefined && vars.result !== null)
|
|
54
|
+
patch.result = vars.result;
|
|
55
|
+
const { error } = await supabase.from("logistics_tasks").update(patch).eq("id", vars.taskId);
|
|
56
|
+
if (error)
|
|
57
|
+
throw new Error(error.message);
|
|
58
|
+
return { ok: true };
|
|
59
|
+
}
|
|
60
|
+
/** Alleen-lezen: strategieën en hun instellingen, uitsluitend om te tonen. */
|
|
61
|
+
export async function fetchLogisticsStrategies() {
|
|
62
|
+
const { data, error } = await supabase.from("logistics_strategies").select("*");
|
|
63
|
+
if (error)
|
|
64
|
+
throw new Error(error.message);
|
|
65
|
+
return Array.isArray(data) ? data : [];
|
|
66
|
+
}
|
|
67
|
+
export async function fetchLogisticsRuleConfigs() {
|
|
68
|
+
const { data, error } = await supabase.from("logistics_rule_configs").select("*");
|
|
69
|
+
if (error)
|
|
70
|
+
throw new Error(error.message);
|
|
71
|
+
return Array.isArray(data) ? data : [];
|
|
72
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type LogisticsTaskStatus = "planned" | "ready" | "in_progress" | "done" | "skipped" | "cancelled" | "failed";
|
|
2
|
+
export type LoadCarrierType = "trolley" | "danish_container" | "dense_container" | "pallet" | "box" | "loose";
|
|
3
|
+
export interface LoadCarrier {
|
|
4
|
+
type: LoadCarrierType | string;
|
|
5
|
+
count: number;
|
|
6
|
+
}
|
|
7
|
+
export interface PickExecutePayload {
|
|
8
|
+
pickMode?: string | null;
|
|
9
|
+
pickStartMode?: string | null;
|
|
10
|
+
pickMinutes?: number | null;
|
|
11
|
+
staff?: number | null;
|
|
12
|
+
reserveMinutes?: number | null;
|
|
13
|
+
scanner?: string | boolean | null;
|
|
14
|
+
loadCarriers?: LoadCarrier[] | null;
|
|
15
|
+
[key: string]: any;
|
|
16
|
+
}
|
|
17
|
+
export interface LogisticsTask {
|
|
18
|
+
id: string;
|
|
19
|
+
type: string;
|
|
20
|
+
status: LogisticsTaskStatus | string;
|
|
21
|
+
planned_start: string | null;
|
|
22
|
+
planned_end: string | null;
|
|
23
|
+
rule_version: string | number | null;
|
|
24
|
+
order_ref: string | null;
|
|
25
|
+
customer_ref: string | null;
|
|
26
|
+
delivery_location_ref: string | null;
|
|
27
|
+
shadow?: boolean | null;
|
|
28
|
+
payload: PickExecutePayload | null;
|
|
29
|
+
}
|
|
30
|
+
/** Normaliseert een taak uit de Engine; velden kunnen camelCase of snake_case zijn. */
|
|
31
|
+
export declare function normalizeTask(raw: unknown): LogisticsTask | null;
|
|
32
|
+
/** Belading dreigt te laat: planned_end is verstreken of binnen `thresholdMinutes`. */
|
|
33
|
+
export declare function isLateRisk(task: LogisticsTask, thresholdMinutes?: number, now?: number): boolean;
|
|
34
|
+
//# sourceMappingURL=logisticsTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logisticsTypes.d.ts","sourceRoot":"","sources":["../../src/lib/logisticsTypes.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,OAAO,GACP,aAAa,GACb,MAAM,GACN,SAAS,GACT,WAAW,GACX,QAAQ,CAAC;AAEb,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,kBAAkB,GAClB,iBAAiB,GACjB,QAAQ,GACR,KAAK,GACL,OAAO,CAAC;AAEZ,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IAClC,YAAY,CAAC,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACpC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAAC;IACrC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACrC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACpC;AAED,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAoBhE;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,gBAAgB,SAAK,EAAE,GAAG,SAAa,GAAG,OAAO,CAMhG"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Types voor de koppeling met de Logistics Engine.
|
|
2
|
+
// De Engine beslist; deze module voert alleen uit.
|
|
3
|
+
/** Normaliseert een taak uit de Engine; velden kunnen camelCase of snake_case zijn. */
|
|
4
|
+
export function normalizeTask(raw) {
|
|
5
|
+
if (!raw || typeof raw !== "object")
|
|
6
|
+
return null;
|
|
7
|
+
const r = raw;
|
|
8
|
+
const id = r.id ?? r.taskId ?? r.task_id;
|
|
9
|
+
if (!id)
|
|
10
|
+
return null;
|
|
11
|
+
const payload = (r.payload ?? r.data ?? null);
|
|
12
|
+
return {
|
|
13
|
+
id: String(id),
|
|
14
|
+
type: String(r.task_type ?? r.type ?? r.taskType ?? "unknown"),
|
|
15
|
+
status: String(r.status ?? "planned"),
|
|
16
|
+
planned_start: r.planned_start ?? r.plannedStart ?? null,
|
|
17
|
+
planned_end: r.planned_end ?? r.plannedEnd ?? null,
|
|
18
|
+
rule_version: r.rule_version ?? r.ruleVersion ?? null,
|
|
19
|
+
order_ref: r.order_ref ?? r.orderRef ?? r.order?.orderRef ?? null,
|
|
20
|
+
customer_ref: r.customer_ref ?? r.customerRef ?? payload?.customerRef ?? null,
|
|
21
|
+
delivery_location_ref: r.delivery_location_ref ?? r.deliveryLocationRef ?? payload?.deliveryLocationRef ?? null,
|
|
22
|
+
shadow: r.shadow ?? null,
|
|
23
|
+
payload,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** Belading dreigt te laat: planned_end is verstreken of binnen `thresholdMinutes`. */
|
|
27
|
+
export function isLateRisk(task, thresholdMinutes = 15, now = Date.now()) {
|
|
28
|
+
if (!task.planned_end)
|
|
29
|
+
return false;
|
|
30
|
+
if (task.status === "done" || task.status === "cancelled" || task.status === "skipped")
|
|
31
|
+
return false;
|
|
32
|
+
const end = new Date(task.planned_end).getTime();
|
|
33
|
+
if (Number.isNaN(end))
|
|
34
|
+
return false;
|
|
35
|
+
return end - now <= thresholdMinutes * 60000;
|
|
36
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface PakbonProduct {
|
|
2
|
+
artikelnummer: string | null;
|
|
3
|
+
artikelnaam: string | null;
|
|
4
|
+
potmaat: string | null;
|
|
5
|
+
kleur: string | null;
|
|
6
|
+
aantal: number;
|
|
7
|
+
locatie: string | null;
|
|
8
|
+
fust_aantal: number;
|
|
9
|
+
fustsoort: string | null;
|
|
10
|
+
planten_per_fust: number | null;
|
|
11
|
+
barcode: string | null;
|
|
12
|
+
opmerking: string | null;
|
|
13
|
+
}
|
|
14
|
+
export interface PakbonLaag {
|
|
15
|
+
laagnummer: number;
|
|
16
|
+
belading: string;
|
|
17
|
+
producten: PakbonProduct[];
|
|
18
|
+
}
|
|
19
|
+
export interface PakbonKar {
|
|
20
|
+
karnummer: string | number;
|
|
21
|
+
karsoort: string | null;
|
|
22
|
+
lagen: PakbonLaag[];
|
|
23
|
+
producten: PakbonProduct[];
|
|
24
|
+
aantal_lagen: number;
|
|
25
|
+
}
|
|
26
|
+
export interface PakbonFust {
|
|
27
|
+
fusttype: string;
|
|
28
|
+
aantal: number;
|
|
29
|
+
}
|
|
30
|
+
export interface PakbonData {
|
|
31
|
+
order: Record<string, any>;
|
|
32
|
+
klant: Record<string, any>;
|
|
33
|
+
afleveradres: Record<string, any>;
|
|
34
|
+
regels: Record<string, any>[];
|
|
35
|
+
karren: PakbonKar[];
|
|
36
|
+
fusten: PakbonFust[];
|
|
37
|
+
totalen: {
|
|
38
|
+
karren: number;
|
|
39
|
+
lagen: number;
|
|
40
|
+
producten: number;
|
|
41
|
+
fusten: number;
|
|
42
|
+
gewicht: number;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Bouwt de datacontext voor de pakbon-sectierenderer. */
|
|
46
|
+
export declare function fetchPakbonData(args: {
|
|
47
|
+
orderId?: string | null;
|
|
48
|
+
orderNumber?: string | null;
|
|
49
|
+
}): Promise<PakbonData | null>;
|
|
50
|
+
//# sourceMappingURL=orderContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orderContext.d.ts","sourceRoot":"","sources":["../../src/lib/orderContext.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;IAC9B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AA2FD,0DAA0D;AAC1D,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA6E7B"}
|