@flowselections/logistiek-engine 1.0.33 → 1.0.53
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/README.md +24 -24
- package/dist-lib/components/FloridayPoortCard.d.ts.map +1 -1
- package/dist-lib/components/FloridayPoortCard.js +2 -1
- package/dist-lib/components/FlowCanvas.d.ts +28 -0
- package/dist-lib/components/FlowCanvas.d.ts.map +1 -0
- package/dist-lib/components/FlowCanvas.js +429 -0
- package/dist-lib/components/FlowOrders.d.ts +8 -0
- package/dist-lib/components/FlowOrders.d.ts.map +1 -0
- package/dist-lib/components/FlowOrders.js +125 -0
- package/dist-lib/components/FlowPage.d.ts +2 -0
- package/dist-lib/components/FlowPage.d.ts.map +1 -0
- package/dist-lib/components/FlowPage.js +141 -0
- package/dist-lib/components/InklapbaarVenster.d.ts +9 -0
- package/dist-lib/components/InklapbaarVenster.d.ts.map +1 -0
- package/dist-lib/components/InklapbaarVenster.js +10 -0
- package/dist-lib/components/LogistiekEnginePage.d.ts.map +1 -1
- package/dist-lib/components/LogistiekEnginePage.js +9 -3
- package/dist-lib/components/LogistiekEngineQueuePage.d.ts +2 -0
- package/dist-lib/components/LogistiekEngineQueuePage.d.ts.map +1 -0
- package/dist-lib/components/LogistiekEngineQueuePage.js +11 -0
- package/dist-lib/components/NodeTracePanel.d.ts +11 -0
- package/dist-lib/components/NodeTracePanel.d.ts.map +1 -0
- package/dist-lib/components/NodeTracePanel.js +40 -0
- package/dist-lib/components/OrderJourneyBar.d.ts +9 -0
- package/dist-lib/components/OrderJourneyBar.d.ts.map +1 -0
- package/dist-lib/components/OrderJourneyBar.js +26 -0
- package/dist-lib/components/OrderLogboek.d.ts +10 -0
- package/dist-lib/components/OrderLogboek.d.ts.map +1 -0
- package/dist-lib/components/OrderLogboek.js +92 -0
- package/dist-lib/components/OrderStopBanner.d.ts +5 -0
- package/dist-lib/components/OrderStopBanner.d.ts.map +1 -0
- package/dist-lib/components/OrderStopBanner.js +22 -0
- package/dist-lib/components/OrderTraceDetails.d.ts +22 -0
- package/dist-lib/components/OrderTraceDetails.d.ts.map +1 -0
- package/dist-lib/components/OrderTraceDetails.js +87 -0
- package/dist-lib/components/RegiePage.d.ts.map +1 -1
- package/dist-lib/components/RegiePage.js +11 -69
- package/dist-lib/components/WerktijdenCard.d.ts +2 -0
- package/dist-lib/components/WerktijdenCard.d.ts.map +1 -0
- package/dist-lib/components/WerktijdenCard.js +37 -0
- package/dist-lib/components/WerkwijzeHerindelingCard.d.ts.map +1 -1
- package/dist-lib/components/WerkwijzeHerindelingCard.js +100 -6
- package/dist-lib/hooks/useFloridayGate.d.ts +10 -0
- package/dist-lib/hooks/useFloridayGate.d.ts.map +1 -1
- package/dist-lib/hooks/useFloridayGate.js +4 -0
- package/dist-lib/hooks/useLogisticsTrace.d.ts +78 -0
- package/dist-lib/hooks/useLogisticsTrace.d.ts.map +1 -0
- package/dist-lib/hooks/useLogisticsTrace.js +152 -0
- package/dist-lib/hooks/useOrderNodeTrace.d.ts +11 -0
- package/dist-lib/hooks/useOrderNodeTrace.d.ts.map +1 -0
- package/dist-lib/hooks/useOrderNodeTrace.js +26 -0
- package/dist-lib/hooks/useOrderTrace.d.ts +74 -0
- package/dist-lib/hooks/useOrderTrace.d.ts.map +1 -0
- package/dist-lib/hooks/useOrderTrace.js +134 -0
- package/dist-lib/hooks/useOrderVersies.d.ts +47 -0
- package/dist-lib/hooks/useOrderVersies.d.ts.map +1 -0
- package/dist-lib/hooks/useOrderVersies.js +180 -0
- package/dist-lib/hooks/useRuleEngine.d.ts +1 -0
- package/dist-lib/hooks/useRuleEngine.d.ts.map +1 -1
- package/dist-lib/hooks/useRuleEngine.js +1 -0
- package/dist-lib/hooks/useShippingNoteStatus.d.ts +29 -0
- package/dist-lib/hooks/useShippingNoteStatus.d.ts.map +1 -0
- package/dist-lib/hooks/useShippingNoteStatus.js +107 -0
- package/dist-lib/hooks/useWerktijden.d.ts +33 -0
- package/dist-lib/hooks/useWerktijden.d.ts.map +1 -0
- package/dist-lib/hooks/useWerktijden.js +88 -0
- package/dist-lib/hooks/useWerkwijzeStatus.d.ts +12 -1
- package/dist-lib/hooks/useWerkwijzeStatus.d.ts.map +1 -1
- package/dist-lib/hooks/useWerkwijzeStatus.js +60 -4
- package/dist-lib/index.d.ts +13 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +13 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +1600 -54
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +1600 -54
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.js +1 -1
- package/dist-lib/integrations/supabase/moduleClient.d.ts +1600 -54
- package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +1618 -50
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/cartPlanRequests.server.d.ts +1 -1
- package/dist-lib/lib/cartPlanRequests.server.d.ts.map +1 -1
- package/dist-lib/lib/cartPlanRequests.server.js +49 -8
- package/dist-lib/lib/floridayDocuments.functions.d.ts +4644 -6
- package/dist-lib/lib/floridayDocuments.functions.d.ts.map +1 -1
- package/dist-lib/lib/floridayDocuments.functions.js +1 -1
- package/dist-lib/lib/floridayDocuments.server.d.ts +14 -0
- package/dist-lib/lib/floridayDocuments.server.d.ts.map +1 -1
- package/dist-lib/lib/floridayDocuments.server.js +58 -0
- package/dist-lib/lib/floridayGuard.server.d.ts +2 -2
- package/dist-lib/lib/floridayGuard.server.d.ts.map +1 -1
- package/dist-lib/lib/floridayGuard.server.js +34 -5
- package/dist-lib/lib/floridayPush.functions.d.ts +1600 -54
- package/dist-lib/lib/floridayPush.functions.d.ts.map +1 -1
- package/dist-lib/lib/floridayPush.functions.js +1 -1
- package/dist-lib/lib/flowGraph.d.ts +43 -0
- package/dist-lib/lib/flowGraph.d.ts.map +1 -0
- package/dist-lib/lib/flowGraph.js +153 -0
- package/dist-lib/lib/flowNodes.d.ts +23 -0
- package/dist-lib/lib/flowNodes.d.ts.map +1 -0
- package/dist-lib/lib/flowNodes.js +58 -0
- package/dist-lib/lib/flowRoute.d.ts +107 -0
- package/dist-lib/lib/flowRoute.d.ts.map +1 -0
- package/dist-lib/lib/flowRoute.js +280 -0
- package/dist-lib/lib/flowTree.d.ts +64 -0
- package/dist-lib/lib/flowTree.d.ts.map +1 -0
- package/dist-lib/lib/flowTree.js +519 -0
- package/dist-lib/lib/handlers/index.d.ts +1 -0
- package/dist-lib/lib/handlers/index.d.ts.map +1 -1
- package/dist-lib/lib/handlers/index.js +1 -0
- package/dist-lib/lib/handlers/logistics-shipping-note-now.server.d.ts +3 -0
- package/dist-lib/lib/handlers/logistics-shipping-note-now.server.d.ts.map +1 -0
- package/dist-lib/lib/handlers/logistics-shipping-note-now.server.js +100 -0
- package/dist-lib/lib/handlers/logistics-tick.server.d.ts.map +1 -1
- package/dist-lib/lib/handlers/logistics-tick.server.js +97 -2
- package/dist-lib/lib/loadCarrierPlanner.d.ts +2 -0
- package/dist-lib/lib/loadCarrierPlanner.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanner.js +18 -0
- package/dist-lib/lib/loadCarrierPlanning.functions.d.ts +7740 -10
- package/dist-lib/lib/loadCarrierPlanning.functions.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanning.functions.js +1 -1
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts +9 -0
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanning.server.js +44 -17
- package/dist-lib/lib/logisticsPlanner.d.ts.map +1 -1
- package/dist-lib/lib/logisticsPlanner.js +14 -2
- package/dist-lib/lib/logisticsRecalcJob.functions.d.ts +3096 -4
- package/dist-lib/lib/logisticsRecalcJob.functions.d.ts.map +1 -1
- package/dist-lib/lib/logisticsRecalcJob.functions.js +1 -1
- package/dist-lib/lib/logisticsRecalculate.functions.d.ts +1600 -54
- package/dist-lib/lib/logisticsRecalculate.functions.d.ts.map +1 -1
- package/dist-lib/lib/logisticsRecalculate.functions.js +1 -1
- package/dist-lib/lib/modulePrompts.d.ts +1 -0
- package/dist-lib/lib/modulePrompts.d.ts.map +1 -1
- package/dist-lib/lib/modulePrompts.js +3482 -2610
- package/dist-lib/lib/nodeTrace.d.ts +61 -0
- package/dist-lib/lib/nodeTrace.d.ts.map +1 -0
- package/dist-lib/lib/nodeTrace.js +191 -0
- package/dist-lib/lib/pickQueueCleanup.server.d.ts +14 -0
- package/dist-lib/lib/pickQueueCleanup.server.d.ts.map +1 -0
- package/dist-lib/lib/pickQueueCleanup.server.js +80 -0
- package/dist-lib/lib/planQueue.server.d.ts.map +1 -1
- package/dist-lib/lib/planQueue.server.js +140 -0
- package/dist-lib/lib/ruleEngineImpact.d.ts.map +1 -1
- package/dist-lib/lib/ruleEngineImpact.js +11 -4
- package/dist-lib/lib/ruleEngineSchema.d.ts.map +1 -1
- package/dist-lib/lib/ruleEngineSchema.js +57 -6
- package/dist-lib/lib/ruleEngineWizard.d.ts.map +1 -1
- package/dist-lib/lib/ruleEngineWizard.js +3 -1
- package/dist-lib/lib/shippingNoteQueue.server.d.ts +18 -0
- package/dist-lib/lib/shippingNoteQueue.server.d.ts.map +1 -0
- package/dist-lib/lib/shippingNoteQueue.server.js +304 -0
- package/dist-lib/lib/trace.server.d.ts +75 -0
- package/dist-lib/lib/trace.server.d.ts.map +1 -0
- package/dist-lib/lib/trace.server.js +75 -0
- package/dist-lib/lib/vakUitleg.d.ts +19 -0
- package/dist-lib/lib/vakUitleg.d.ts.map +1 -0
- package/dist-lib/lib/vakUitleg.js +132 -0
- package/package.json +26 -2
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts +0 -2
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts.map +0 -1
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.js +0 -41
- package/dist-lib/integrations/supabase/client.d.ts +0 -20293
- package/dist-lib/integrations/supabase/client.d.ts.map +0 -1
- package/dist-lib/integrations/supabase/client.js +0 -13
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/lib/flowTree.ts — vertakkende beslisboom van de Logistiek Engine
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Bouwt uit WIZARD_STEPS en de opgeslagen werkwijze een boom waarin ELK
|
|
5
|
+
// beslismoment al zijn uitkomsten laat zien. De vertakkingen komen uit de
|
|
6
|
+
// `dependsOn`-regels van het schema: een instelling die alleen geldt bij een
|
|
7
|
+
// bepaalde keuze hangt onder de pijl van die keuze. De actieve route wordt met
|
|
8
|
+
// dezelfde `fieldVisible`-logica bepaald die de engine en het instelscherm
|
|
9
|
+
// gebruiken. Er staat hier geen aparte flowlogica.
|
|
10
|
+
// ============================================================================
|
|
11
|
+
import { fieldVisible, optionLabel, } from "./ruleEngineSchema";
|
|
12
|
+
import { WIZARD_STEPS, fieldHelp } from "./ruleEngineWizard";
|
|
13
|
+
export const NODE_SIZE = {
|
|
14
|
+
start: { w: 240, h: 60 },
|
|
15
|
+
end: { w: 240, h: 60 },
|
|
16
|
+
source: { w: 260, h: 96 },
|
|
17
|
+
step: { w: 300, h: 88 },
|
|
18
|
+
decision: { w: 280, h: 118 },
|
|
19
|
+
setting: { w: 240, h: 66 },
|
|
20
|
+
option: { w: 150, h: 30 },
|
|
21
|
+
merge: { w: 14, h: 14 },
|
|
22
|
+
};
|
|
23
|
+
const DAY_SHORT = {
|
|
24
|
+
mon: "ma",
|
|
25
|
+
tue: "di",
|
|
26
|
+
wed: "wo",
|
|
27
|
+
thu: "do",
|
|
28
|
+
fri: "vr",
|
|
29
|
+
sat: "za",
|
|
30
|
+
sun: "zo",
|
|
31
|
+
};
|
|
32
|
+
function isDecision(field) {
|
|
33
|
+
if (field.type === "toggle")
|
|
34
|
+
return true;
|
|
35
|
+
if (field.type === "select" || field.type === "radio") {
|
|
36
|
+
return Array.isArray(field.options) && field.options.length >= 2;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
function rulesOf(field) {
|
|
41
|
+
if (!field.dependsOn)
|
|
42
|
+
return [];
|
|
43
|
+
return Array.isArray(field.dependsOn) ? field.dependsOn : [field.dependsOn];
|
|
44
|
+
}
|
|
45
|
+
function optionsOf(field) {
|
|
46
|
+
if (field.type === "toggle") {
|
|
47
|
+
return [
|
|
48
|
+
{ value: "true", label: "ja" },
|
|
49
|
+
{ value: "false", label: "nee" },
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
return (field.options ?? []).map((o) => ({ value: o.value, label: o.label }));
|
|
53
|
+
}
|
|
54
|
+
function currentOf(field, value) {
|
|
55
|
+
if (field.type === "toggle")
|
|
56
|
+
return value === true ? "true" : "false";
|
|
57
|
+
return String(value ?? "");
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Zoekt de schemavelden op die bij een vakje horen. Gebruikt dezelfde
|
|
61
|
+
* WIZARD_STEPS als het instelscherm, zodat er geen tweede definitie ontstaat.
|
|
62
|
+
*/
|
|
63
|
+
export function fieldsFor(storeId, keys) {
|
|
64
|
+
const veiligeKeys = Array.isArray(keys) ? keys : [];
|
|
65
|
+
if (!storeId || !veiligeKeys.length)
|
|
66
|
+
return [];
|
|
67
|
+
const stappen = Array.isArray(WIZARD_STEPS) ? WIZARD_STEPS : [];
|
|
68
|
+
const alle = [];
|
|
69
|
+
for (const stap of stappen) {
|
|
70
|
+
if (stap.storeId !== storeId)
|
|
71
|
+
continue;
|
|
72
|
+
for (const group of Array.isArray(stap.groups) ? stap.groups : []) {
|
|
73
|
+
for (const field of Array.isArray(group.fields) ? group.fields : [])
|
|
74
|
+
alle.push(field);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return veiligeKeys
|
|
78
|
+
.map((k) => alle.find((f) => f.key === k))
|
|
79
|
+
.filter((f) => Boolean(f));
|
|
80
|
+
}
|
|
81
|
+
export function valueText(field, value) {
|
|
82
|
+
if (value === undefined || value === null || value === "")
|
|
83
|
+
return "niet ingesteld";
|
|
84
|
+
switch (field.type) {
|
|
85
|
+
case "toggle":
|
|
86
|
+
return value === true ? "aan" : "uit";
|
|
87
|
+
case "select":
|
|
88
|
+
case "radio":
|
|
89
|
+
return optionLabel(field, value);
|
|
90
|
+
case "days": {
|
|
91
|
+
const days = Array.isArray(value) ? value : [];
|
|
92
|
+
return days.length ? days.map((d) => DAY_SHORT[d] ?? d).join(", ") : "geen";
|
|
93
|
+
}
|
|
94
|
+
case "number":
|
|
95
|
+
return `${String(value)}${field.unit ? ` ${field.unit}` : ""}`;
|
|
96
|
+
case "priority": {
|
|
97
|
+
const entries = Array.isArray(value) ? value : [];
|
|
98
|
+
return `${entries.filter((e) => e?.enabled).length} actief`;
|
|
99
|
+
}
|
|
100
|
+
case "textarea":
|
|
101
|
+
case "text": {
|
|
102
|
+
const t = String(value);
|
|
103
|
+
return t.length > 40 ? `${t.slice(0, 39)}…` : t;
|
|
104
|
+
}
|
|
105
|
+
default:
|
|
106
|
+
return String(value);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** Toestand van een tak-pijl uit een beslissing. */
|
|
110
|
+
function edgeState(decision, isCurrent) {
|
|
111
|
+
if (decision === "active")
|
|
112
|
+
return isCurrent ? "active" : "possible";
|
|
113
|
+
if (decision === "possible")
|
|
114
|
+
return isCurrent ? "possible" : "disabled";
|
|
115
|
+
return "disabled";
|
|
116
|
+
}
|
|
117
|
+
function weakest(a, b) {
|
|
118
|
+
const rank = { active: 0, possible: 1, disabled: 2 };
|
|
119
|
+
return rank[a] >= rank[b] ? a : b;
|
|
120
|
+
}
|
|
121
|
+
/** Bouwt de complete beslisboom van binnenkomst tot afgehandelde order. */
|
|
122
|
+
export function buildFlowTree(settings) {
|
|
123
|
+
const veilig = settings && typeof settings === "object" ? settings : {};
|
|
124
|
+
const nodes = [];
|
|
125
|
+
const edges = [];
|
|
126
|
+
const decisionIds = new Map();
|
|
127
|
+
const pendingRefs = [];
|
|
128
|
+
const add = (node) => {
|
|
129
|
+
const size = NODE_SIZE[node.kind];
|
|
130
|
+
const n = { ...node, ancestors: node.ancestors ?? [], w: size.w, h: size.h };
|
|
131
|
+
nodes.push(n);
|
|
132
|
+
return n;
|
|
133
|
+
};
|
|
134
|
+
const link = (from, to, state, label, ancestors = [], kind = "flow") => {
|
|
135
|
+
edges.push({ id: `${kind}:${from}->${to}:${label ?? ""}`, from, to, label, state, kind, ancestors });
|
|
136
|
+
};
|
|
137
|
+
// ── Start en herkomst ──────────────────────────────────────────────────────
|
|
138
|
+
add({
|
|
139
|
+
id: "__start",
|
|
140
|
+
kind: "start",
|
|
141
|
+
label: "Order komt binnen",
|
|
142
|
+
sublabel: "Floriday of eigen verkoop",
|
|
143
|
+
state: "active",
|
|
144
|
+
help: [
|
|
145
|
+
"Hier begint de route. Elke order die binnenkomt start bovenaan deze kaart en loopt via alle stappen naar 'Order afgehandeld'.",
|
|
146
|
+
"Gekleurde vakjes en dikke pijlen zijn de route die nu geldt. Lichte vakjes zijn keuzes die je ook kunt maken; grijze, gestippelde takken zijn op dit moment niet bereikbaar door een keuze eerder in de route.",
|
|
147
|
+
],
|
|
148
|
+
});
|
|
149
|
+
add({
|
|
150
|
+
id: "__bron",
|
|
151
|
+
kind: "source",
|
|
152
|
+
label: "Waar komt de order vandaan?",
|
|
153
|
+
sublabel: "vaste regel — geen instelling",
|
|
154
|
+
state: "active",
|
|
155
|
+
help: [
|
|
156
|
+
"De engine herkent zelf waar een order vandaan komt: Floriday, de mailbox voor bestellingen, de actiemail of handmatige invoer. Dit is geen instelling; alle vier de routes bestaan altijd.",
|
|
157
|
+
"Het verschil zit vooral bij de verzendbrief: een Floriday-order krijgt uitsluitend de officiële Floriday-afleverbrief, de overige orders de eigen verzendbrieflayout uit de Layout maker.",
|
|
158
|
+
"Verder doorlopen alle orders dezelfde stappen en dezelfde regels hieronder.",
|
|
159
|
+
],
|
|
160
|
+
});
|
|
161
|
+
link("__start", "__bron", "active");
|
|
162
|
+
add({ id: "__bron_merge", kind: "merge", label: "", state: "active", help: [] });
|
|
163
|
+
const bronnen = [
|
|
164
|
+
{
|
|
165
|
+
id: "__bron_floriday",
|
|
166
|
+
label: "Bestellingen uit Floriday",
|
|
167
|
+
sub: "order_source: floriday",
|
|
168
|
+
help: [
|
|
169
|
+
"Floriday levert per artikel een eigen verkooporder aan. Eén bestelling van één klant komt daardoor binnen als losse regels met elk een eigen FO-nummer.",
|
|
170
|
+
"Daarom volgt hierna eerst de stap 'Bestelregels samenvoegen'.",
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: "__bron_mail",
|
|
175
|
+
label: "Bestellingen uit de mail",
|
|
176
|
+
sub: "mailbox voor bestellingen",
|
|
177
|
+
help: [
|
|
178
|
+
"Bestellingen die per e-mail binnenkomen en via de mailboxmodule als ordervoorstel worden goedgekeurd.",
|
|
179
|
+
"Een goedgekeurd voorstel wordt één order en loopt daarna dezelfde route als alle andere orders.",
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: "__bron_actiemail",
|
|
184
|
+
label: "Bestellingen uit de actiemail",
|
|
185
|
+
sub: "actiemail kwekers",
|
|
186
|
+
help: [
|
|
187
|
+
"Bestellingen die voortkomen uit een actiemail aan kwekers/klanten.",
|
|
188
|
+
"Ook deze orders lopen daarna dezelfde route als alle andere orders.",
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: "__bron_handmatig",
|
|
193
|
+
label: "Handmatige bestellingen",
|
|
194
|
+
sub: "ingevoerd in verkoop",
|
|
195
|
+
help: [
|
|
196
|
+
"Orders die een medewerker zelf aanmaakt in het verkoopscherm.",
|
|
197
|
+
"Deze orders zijn al één bestelling met één ordernummer en worden niet samengevoegd.",
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
];
|
|
201
|
+
for (const b of bronnen) {
|
|
202
|
+
add({ id: b.id, kind: "source", label: b.label, sublabel: b.sub, state: "active", help: b.help });
|
|
203
|
+
link("__bron", b.id, "active");
|
|
204
|
+
}
|
|
205
|
+
// ── Floriday: bestelregels eerst samenvoegen tot één bestelling ────────────
|
|
206
|
+
const ovFields = (veilig["order_verwerking"]?.fields ?? {});
|
|
207
|
+
const samenvoegenAan = ovFields["floriday_merge_lines"] !== false;
|
|
208
|
+
add({
|
|
209
|
+
id: "stap:bestelregels_samenvoegen",
|
|
210
|
+
kind: "step",
|
|
211
|
+
label: "Bestelregels samenvoegen",
|
|
212
|
+
sublabel: samenvoegenAan
|
|
213
|
+
? "aan — regels van dezelfde klant en levermoment worden één bestelling"
|
|
214
|
+
: "uit — elke Floriday-regel blijft een eigen order",
|
|
215
|
+
state: samenvoegenAan ? "active" : "disabled",
|
|
216
|
+
storeId: "order_verwerking",
|
|
217
|
+
fieldKeys: ["floriday_merge_lines"],
|
|
218
|
+
lines: [
|
|
219
|
+
samenvoegenAan
|
|
220
|
+
? "Samenvoegen: aan (zelfde klant, levermoment en afleverlocatie)"
|
|
221
|
+
: "Samenvoegen: uit",
|
|
222
|
+
"Laagste FO-nummer blijft het ordernummer",
|
|
223
|
+
"Al ingedeelde, geprinte of gecontroleerde orders blijven ongewijzigd",
|
|
224
|
+
],
|
|
225
|
+
help: [
|
|
226
|
+
"Floriday stuurt elke bestelregel als een eigen verkooporder. Deze stap bundelt de regels van dezelfde klant, hetzelfde levermoment en dezelfde afleverlocatie tot één bestelling met één ordernummer.",
|
|
227
|
+
"Het laagste FO-nummer van de groep blijft staan; de andere nummers worden als herkomst bewaard, zodat documenten en terugkoppeling naar Floriday blijven kloppen.",
|
|
228
|
+
"Orders die al vastliggen (ingedeeld, geprint, gescand of afgehandeld) worden nooit alsnog samengevoegd.",
|
|
229
|
+
],
|
|
230
|
+
});
|
|
231
|
+
link("__bron_floriday", "stap:bestelregels_samenvoegen", samenvoegenAan ? "active" : "possible");
|
|
232
|
+
link("stap:bestelregels_samenvoegen", "__bron_merge", samenvoegenAan ? "active" : "possible");
|
|
233
|
+
link("__bron_mail", "__bron_merge", "active");
|
|
234
|
+
link("__bron_actiemail", "__bron_merge", "active");
|
|
235
|
+
link("__bron_handmatig", "__bron_merge", "active");
|
|
236
|
+
let tail = "__bron_merge";
|
|
237
|
+
// ── Stappen ────────────────────────────────────────────────────────────────
|
|
238
|
+
WIZARD_STEPS.forEach((step, index) => {
|
|
239
|
+
const values = (veilig?.[step.storeId]?.fields ?? {});
|
|
240
|
+
const groups = Array.isArray(step.groups) ? step.groups : [];
|
|
241
|
+
const fieldsInOrder = [];
|
|
242
|
+
for (const group of groups) {
|
|
243
|
+
for (const field of Array.isArray(group.fields) ? group.fields : []) {
|
|
244
|
+
if (field.type === "guidance")
|
|
245
|
+
continue;
|
|
246
|
+
fieldsInOrder.push({ field, group });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const keysHere = new Set(fieldsInOrder.map((f) => f.field.key));
|
|
250
|
+
const order = new Map(fieldsInOrder.map((f, i) => [f.field.key, i]));
|
|
251
|
+
// Elk veld hangt onder de "diepste" beslissing uit dezelfde stap waar het
|
|
252
|
+
// van afhangt (de regel waarvan het bronveld het laatst in de volgorde staat).
|
|
253
|
+
const childrenOf = new Map();
|
|
254
|
+
const roots = [];
|
|
255
|
+
for (const item of fieldsInOrder) {
|
|
256
|
+
const local = rulesOf(item.field).filter((r) => !r.step && keysHere.has(r.key));
|
|
257
|
+
if (!local.length) {
|
|
258
|
+
roots.push(item);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
const parentRule = local.reduce((best, r) => (order.get(r.key) ?? -1) > (order.get(best.key) ?? -1) ? r : best);
|
|
262
|
+
const list = childrenOf.get(parentRule.key) ?? [];
|
|
263
|
+
list.push({ ...item, rule: parentRule });
|
|
264
|
+
childrenOf.set(parentRule.key, list);
|
|
265
|
+
}
|
|
266
|
+
const ctx = {
|
|
267
|
+
nodes,
|
|
268
|
+
edges,
|
|
269
|
+
settings: veilig,
|
|
270
|
+
step,
|
|
271
|
+
values,
|
|
272
|
+
fieldsInOrder,
|
|
273
|
+
childrenOf,
|
|
274
|
+
decisionIds,
|
|
275
|
+
pendingRefs,
|
|
276
|
+
};
|
|
277
|
+
const stepNode = add({
|
|
278
|
+
id: `stap:${step.id}`,
|
|
279
|
+
kind: "step",
|
|
280
|
+
label: `${index + 1}. ${step.label}`,
|
|
281
|
+
sublabel: step.description,
|
|
282
|
+
stepId: step.id,
|
|
283
|
+
storeId: step.storeId,
|
|
284
|
+
state: "active",
|
|
285
|
+
help: [
|
|
286
|
+
step.description,
|
|
287
|
+
`Achter deze stap staan ${fieldsInOrder.length} instellingen. Klik op het vakje om ze allemaal in het zijpaneel te openen.`,
|
|
288
|
+
"De vertakkingen hieronder laten zien welke instellingen alleen gelden bij een bepaalde keuze.",
|
|
289
|
+
],
|
|
290
|
+
});
|
|
291
|
+
link(tail, stepNode.id, "active");
|
|
292
|
+
const stapMerge = `samen:stap:${step.id}`;
|
|
293
|
+
fan(ctx, stepNode.id, "active", roots, [], stapMerge);
|
|
294
|
+
nodes.push({ id: stapMerge, kind: "merge", label: "", state: "active", ancestors: [], help: [], w: NODE_SIZE.merge.w, h: NODE_SIZE.merge.h });
|
|
295
|
+
tail = stapMerge;
|
|
296
|
+
});
|
|
297
|
+
// ── Einde ──────────────────────────────────────────────────────────────────
|
|
298
|
+
add({
|
|
299
|
+
id: "__eind",
|
|
300
|
+
kind: "end",
|
|
301
|
+
label: "Order afgehandeld",
|
|
302
|
+
sublabel: "gecontroleerd en afgemeld",
|
|
303
|
+
state: "active",
|
|
304
|
+
help: [
|
|
305
|
+
"Dit is het einde van de route: de order is gepickt, gecontroleerd en afgemeld.",
|
|
306
|
+
"Pas als alle stappen hierboven doorlopen zijn, komt een order hier terecht.",
|
|
307
|
+
],
|
|
308
|
+
});
|
|
309
|
+
link(tail, "__eind", "active");
|
|
310
|
+
// ── Verwijspijlen tussen stappen ───────────────────────────────────────────
|
|
311
|
+
for (const ref of pendingRefs) {
|
|
312
|
+
const from = decisionIds.get(`${ref.storeId}:${ref.key}`);
|
|
313
|
+
if (!from)
|
|
314
|
+
continue;
|
|
315
|
+
const fromNode = nodes.find((n) => n.id === from);
|
|
316
|
+
const label = fromNode
|
|
317
|
+
? ref.values
|
|
318
|
+
.map((v) => fromNode.options?.find((o) => o.value === String(v))?.label ?? String(v))
|
|
319
|
+
.join(" / ")
|
|
320
|
+
: undefined;
|
|
321
|
+
link(from, ref.toNode, ref.state, label, ref.ancestors, "ref");
|
|
322
|
+
}
|
|
323
|
+
return { nodes, edges };
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Waaiert een lijst velden uit vanaf `from`: elke beslissing wordt een eigen arm
|
|
327
|
+
* met al haar keuzes; losse instellingen worden per blok gebundeld in één
|
|
328
|
+
* vakje. Alle armen komen samen in `mergeId`.
|
|
329
|
+
*/
|
|
330
|
+
function fan(ctx, from, fromState, items, ancestors, mergeId) {
|
|
331
|
+
const size = NODE_SIZE;
|
|
332
|
+
// `from` is uniek per tak (stap, of het tussenpunt van een keuze).
|
|
333
|
+
const takSleutel = from.replace(/[^a-z0-9_]+/gi, "_");
|
|
334
|
+
const push = (e) => {
|
|
335
|
+
ctx.edges.push({
|
|
336
|
+
id: `${e.kind ?? "flow"}:${e.from}->${e.to}:${e.suffix ?? e.label ?? ""}`,
|
|
337
|
+
from: e.from,
|
|
338
|
+
to: e.to,
|
|
339
|
+
label: e.label,
|
|
340
|
+
state: e.state,
|
|
341
|
+
kind: e.kind ?? "flow",
|
|
342
|
+
ancestors: e.ancestors,
|
|
343
|
+
});
|
|
344
|
+
};
|
|
345
|
+
const uitlegVoor = (field, group, state) => {
|
|
346
|
+
const help = [];
|
|
347
|
+
const uitleg = fieldHelp(field);
|
|
348
|
+
if (uitleg)
|
|
349
|
+
help.push(uitleg);
|
|
350
|
+
help.push(`Onderdeel van stap "${ctx.step.label}", blok "${group.label}".`);
|
|
351
|
+
help.push(`Nu ingesteld op: ${valueText(field, ctx.values[field.key])}.`);
|
|
352
|
+
if (ancestors.length) {
|
|
353
|
+
help.push(`Deze tak geldt alleen onder: ${ancestors
|
|
354
|
+
.map((a) => ctx.nodes.find((n) => n.id === a)?.label ?? a)
|
|
355
|
+
.join(" → ")}.`);
|
|
356
|
+
}
|
|
357
|
+
if (state === "disabled") {
|
|
358
|
+
help.push("Deze tak is op dit moment niet bereikbaar door een keuze eerder in de route.");
|
|
359
|
+
}
|
|
360
|
+
else if (state === "possible") {
|
|
361
|
+
help.push("Deze tak is mogelijk, maar niet de keuze die nu geldt.");
|
|
362
|
+
}
|
|
363
|
+
return help;
|
|
364
|
+
};
|
|
365
|
+
const verwijzingen = (field, toNode, state, help) => {
|
|
366
|
+
for (const rule of rulesOf(field)) {
|
|
367
|
+
if (!rule.step)
|
|
368
|
+
continue;
|
|
369
|
+
ctx.pendingRefs.push({ toNode, storeId: rule.step, key: rule.key, values: rule.in, state, ancestors });
|
|
370
|
+
help.push("De gestippelde pijl laat zien van welke keuze uit een andere stap dit vakje afhangt.");
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
const stateVan = (field) => fieldVisible(field, ctx.values, ctx.settings) ? fromState : weakest(fromState, "disabled");
|
|
374
|
+
let armen = 0;
|
|
375
|
+
// ── Losse instellingen: per blok één vakje ────────────────────────────────
|
|
376
|
+
const losse = items.filter((i) => !isDecision(i.field));
|
|
377
|
+
const perBlok = new Map();
|
|
378
|
+
for (const { field, group } of losse) {
|
|
379
|
+
const b = perBlok.get(group.id) ?? { group, fields: [] };
|
|
380
|
+
b.fields.push(field);
|
|
381
|
+
perBlok.set(group.id, b);
|
|
382
|
+
}
|
|
383
|
+
for (const { group, fields } of perBlok.values()) {
|
|
384
|
+
const id = `blok:${ctx.step.storeId}:${group.id}:${takSleutel}`;
|
|
385
|
+
const states = fields.map(stateVan);
|
|
386
|
+
const state = states.some((s) => s !== "disabled") ? fromState : weakest(fromState, "disabled");
|
|
387
|
+
const lines = fields.map((f) => `${f.label}: ${valueText(f, ctx.values[f.key])}`);
|
|
388
|
+
const help = [];
|
|
389
|
+
if (group.description)
|
|
390
|
+
help.push(group.description);
|
|
391
|
+
help.push(`Vaste instellingen in blok "${group.label}" van stap "${ctx.step.label}":`);
|
|
392
|
+
help.push(...lines);
|
|
393
|
+
help.push("Dubbelklik op het vakje om deze instellingen hier meteen aan te passen.");
|
|
394
|
+
for (const f of fields)
|
|
395
|
+
verwijzingen(f, id, state, help);
|
|
396
|
+
const h = Math.min(6, lines.length) * 16 + 44;
|
|
397
|
+
ctx.nodes.push({
|
|
398
|
+
id,
|
|
399
|
+
kind: "setting",
|
|
400
|
+
label: group.label,
|
|
401
|
+
sublabel: `${fields.length} instelling${fields.length === 1 ? "" : "en"}`,
|
|
402
|
+
lines,
|
|
403
|
+
fieldKeys: fields.map((f) => f.key),
|
|
404
|
+
state,
|
|
405
|
+
stepId: ctx.step.id,
|
|
406
|
+
storeId: ctx.step.storeId,
|
|
407
|
+
ancestors,
|
|
408
|
+
help,
|
|
409
|
+
w: size.setting.w,
|
|
410
|
+
h,
|
|
411
|
+
});
|
|
412
|
+
push({ from, to: id, state, ancestors });
|
|
413
|
+
push({ from: id, to: mergeId, state, ancestors });
|
|
414
|
+
armen++;
|
|
415
|
+
}
|
|
416
|
+
// ── Beslissingen: elke keuze een eigen tak ────────────────────────────────
|
|
417
|
+
for (const { field, group } of items) {
|
|
418
|
+
if (!isDecision(field))
|
|
419
|
+
continue;
|
|
420
|
+
const state = stateVan(field);
|
|
421
|
+
const id = `keuze:${ctx.step.storeId}:${field.key}`;
|
|
422
|
+
const value = ctx.values[field.key];
|
|
423
|
+
const options = optionsOf(field);
|
|
424
|
+
const current = currentOf(field, value);
|
|
425
|
+
const eigenMerge = `samen:${ctx.step.storeId}:${field.key}`;
|
|
426
|
+
const help = uitlegVoor(field, group, state);
|
|
427
|
+
help.push(`Mogelijke keuzes: ${options.map((o) => o.label).join(" · ")}. Kies je hier iets anders, dan wordt meteen een andere tak actief én werkt de engine daarna volgens die keuze.`);
|
|
428
|
+
verwijzingen(field, id, state, help);
|
|
429
|
+
ctx.nodes.push({
|
|
430
|
+
id,
|
|
431
|
+
kind: "decision",
|
|
432
|
+
label: field.label,
|
|
433
|
+
sublabel: group.label,
|
|
434
|
+
state,
|
|
435
|
+
stepId: ctx.step.id,
|
|
436
|
+
storeId: ctx.step.storeId,
|
|
437
|
+
fieldKey: field.key,
|
|
438
|
+
fieldKeys: [field.key],
|
|
439
|
+
options,
|
|
440
|
+
currentValue: current,
|
|
441
|
+
isBoolean: field.type === "toggle",
|
|
442
|
+
mergeId: eigenMerge,
|
|
443
|
+
ancestors,
|
|
444
|
+
help,
|
|
445
|
+
w: size.decision.w,
|
|
446
|
+
h: size.decision.h,
|
|
447
|
+
});
|
|
448
|
+
ctx.decisionIds.set(`${ctx.step.storeId}:${field.key}`, id);
|
|
449
|
+
push({ from, to: id, state, ancestors });
|
|
450
|
+
const kinderen = ctx.childrenOf.get(field.key) ?? [];
|
|
451
|
+
const takAncestors = [...ancestors, id];
|
|
452
|
+
// Takken: één per verzameling keuzes waar dezelfde kinderen onder hangen,
|
|
453
|
+
// zodat een instelling die bij "scanner" én "scan_only" geldt één vakje blijft.
|
|
454
|
+
const takken = new Map();
|
|
455
|
+
for (const k of kinderen) {
|
|
456
|
+
const waarden = options.map((o) => o.value).filter((v) => k.rule.in.some((r) => String(r) === v));
|
|
457
|
+
if (!waarden.length)
|
|
458
|
+
continue;
|
|
459
|
+
const sleutel = waarden.join("|");
|
|
460
|
+
const tak = takken.get(sleutel) ?? { waarden, kinderen: [] };
|
|
461
|
+
tak.kinderen.push(k);
|
|
462
|
+
takken.set(sleutel, tak);
|
|
463
|
+
}
|
|
464
|
+
const gedekt = new Set([...takken.values()].flatMap((t) => t.waarden));
|
|
465
|
+
const labelVan = (waarden) => waarden.map((v) => options.find((o) => o.value === v)?.label ?? v).join(" / ");
|
|
466
|
+
for (const option of options) {
|
|
467
|
+
if (gedekt.has(option.value))
|
|
468
|
+
continue;
|
|
469
|
+
// Keuze zonder eigen vervolg: een klein label-vakje, zodat alle uitkomsten
|
|
470
|
+
// naast elkaar zichtbaar blijven.
|
|
471
|
+
const optState = edgeState(state, option.value === current);
|
|
472
|
+
const optId = `optie:${ctx.step.storeId}:${field.key}:${option.value}`;
|
|
473
|
+
ctx.nodes.push({
|
|
474
|
+
id: optId,
|
|
475
|
+
kind: "option",
|
|
476
|
+
label: option.label,
|
|
477
|
+
state: optState,
|
|
478
|
+
stepId: ctx.step.id,
|
|
479
|
+
storeId: ctx.step.storeId,
|
|
480
|
+
fieldKey: field.key,
|
|
481
|
+
ancestors: takAncestors,
|
|
482
|
+
help: [
|
|
483
|
+
`Uitkomst "${option.label}" van "${field.label}".`,
|
|
484
|
+
optState === "active"
|
|
485
|
+
? "Dit is de keuze die nu geldt."
|
|
486
|
+
: "Deze keuze geldt nu niet; kies hem in de beslistegel om deze tak actief te maken.",
|
|
487
|
+
"Er hangen geen extra instellingen onder deze uitkomst; de route gaat direct verder.",
|
|
488
|
+
],
|
|
489
|
+
w: size.option.w,
|
|
490
|
+
h: size.option.h,
|
|
491
|
+
});
|
|
492
|
+
push({ from: id, to: optId, state: optState, ancestors: takAncestors });
|
|
493
|
+
push({ from: optId, to: eigenMerge, state: optState, ancestors: takAncestors });
|
|
494
|
+
}
|
|
495
|
+
for (const [sleutel, tak] of takken) {
|
|
496
|
+
const takState = edgeState(state, tak.waarden.includes(current));
|
|
497
|
+
// Klein tussenpunt met het keuzelabel; daarachter waaieren de kinderen uit.
|
|
498
|
+
const takId = `tak:${ctx.step.storeId}:${field.key}:${sleutel}`;
|
|
499
|
+
ctx.nodes.push({
|
|
500
|
+
id: takId,
|
|
501
|
+
kind: "merge",
|
|
502
|
+
label: "",
|
|
503
|
+
state: takState,
|
|
504
|
+
ancestors: takAncestors,
|
|
505
|
+
help: [],
|
|
506
|
+
w: size.merge.w,
|
|
507
|
+
h: size.merge.h,
|
|
508
|
+
});
|
|
509
|
+
push({ from: id, to: takId, label: labelVan(tak.waarden), suffix: sleutel, state: takState, ancestors: takAncestors });
|
|
510
|
+
const sub = { ...ctx };
|
|
511
|
+
fan(sub, takId, takState, tak.kinderen, takAncestors, eigenMerge);
|
|
512
|
+
}
|
|
513
|
+
ctx.nodes.push({ id: eigenMerge, kind: "merge", label: "", state, ancestors, help: [], w: size.merge.w, h: size.merge.h });
|
|
514
|
+
push({ from: eigenMerge, to: mergeId, state, ancestors });
|
|
515
|
+
armen++;
|
|
516
|
+
}
|
|
517
|
+
if (armen === 0)
|
|
518
|
+
push({ from, to: mergeId, state: fromState, ancestors });
|
|
519
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/handlers/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/handlers/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC"}
|
|
@@ -2,3 +2,4 @@
|
|
|
2
2
|
// src/lib/handlers/index.ts — server-route handlers voor shells
|
|
3
3
|
// ============================================================================
|
|
4
4
|
export { handleLogisticsTick } from "./logistics-tick.server.js";
|
|
5
|
+
export { handleShippingNoteNow } from "./logistics-shipping-note-now.server.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logistics-shipping-note-now.server.d.ts","sourceRoot":"","sources":["../../../src/lib/handlers/logistics-shipping-note-now.server.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAQ5D,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,CAiGnB"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/lib/handlers/logistics-shipping-note-now.server.ts
|
|
3
|
+
// Verzendbrief direct ophalen op het moment dat de pakbon naar het pickstation
|
|
4
|
+
// wordt gestuurd, in plaats van te wachten op de volgende ronde van de cron.
|
|
5
|
+
//
|
|
6
|
+
// Alleen-lezen richting Floriday: er wordt geen status gewijzigd en geen order
|
|
7
|
+
// of kar afgehandeld. Het maken van de printopdracht is idempotent, dus vaker
|
|
8
|
+
// aanroepen levert nooit een dubbele verzendbrief op.
|
|
9
|
+
// Geen omgevingswaarden in deze code: de sleutel komt uit de omgeving.
|
|
10
|
+
// ============================================================================
|
|
11
|
+
const CORS_HEADERS = {
|
|
12
|
+
"Access-Control-Allow-Origin": "*",
|
|
13
|
+
"Access-Control-Allow-Headers": "apikey, authorization, content-type",
|
|
14
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
15
|
+
};
|
|
16
|
+
export async function handleShippingNoteNow(request, supabase) {
|
|
17
|
+
if (request.method === "OPTIONS") {
|
|
18
|
+
return new Response(null, { status: 204, headers: CORS_HEADERS });
|
|
19
|
+
}
|
|
20
|
+
const apikey = request.headers.get("apikey") ??
|
|
21
|
+
request.headers.get("authorization")?.replace(/^Bearer /i, "") ??
|
|
22
|
+
"";
|
|
23
|
+
const expected = (process.env["SUPABASE_PUBLISHABLE_KEY"] ??
|
|
24
|
+
process.env["SUPABASE_ANON_KEY"] ??
|
|
25
|
+
"").replace(/^["']|["']$/g, "");
|
|
26
|
+
if (!expected || apikey !== expected) {
|
|
27
|
+
return new Response(JSON.stringify({ error: "Unauthorized" }), {
|
|
28
|
+
status: 401,
|
|
29
|
+
headers: { "Content-Type": "application/json", ...CORS_HEADERS },
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const { runShippingNoteQueue } = await import("../shippingNoteQueue.server.js");
|
|
34
|
+
if (typeof runShippingNoteQueue !== "function") {
|
|
35
|
+
throw new Error("Deze versie van de Logistiek Engine bevat geen verzendbriefverwerking. Werk de module bij.");
|
|
36
|
+
}
|
|
37
|
+
// 1. Inhaalslag: pakbonnen die nog geen verzendbriefaanvraag hebben er
|
|
38
|
+
// alsnog bij zetten. Idempotent, dus nooit een tweede aanvraag.
|
|
39
|
+
let backfill = null;
|
|
40
|
+
try {
|
|
41
|
+
const { data } = await supabase.rpc("logistics_ensure_shipping_notes", { p_limit: 500 });
|
|
42
|
+
backfill = data ?? null;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
backfill = null;
|
|
46
|
+
}
|
|
47
|
+
// 1b. Foutieve eigen verzendbrieven bij Floriday-orders opruimen.
|
|
48
|
+
try {
|
|
49
|
+
await supabase.rpc("logistics_fix_wrong_shipping_notes");
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
/* opschonen mag de ronde niet blokkeren */
|
|
53
|
+
}
|
|
54
|
+
// 2. Alle openstaande aanvragen mogen nu meteen worden opgepakt.
|
|
55
|
+
let wake = null;
|
|
56
|
+
try {
|
|
57
|
+
const { data } = await supabase.rpc("logistics_shipping_notes_wake_all");
|
|
58
|
+
wake = data ?? null;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
wake = null;
|
|
62
|
+
}
|
|
63
|
+
// 3. Gebundeld verwerken tot alles op is of het tijdbudget vol is; de knop
|
|
64
|
+
// hoeft niet te wachten tot de laatste ronde klaar is.
|
|
65
|
+
const totaal = { claimed: 0, printed: 0, waiting: 0, retrying: 0, failed: 0, errors: [] };
|
|
66
|
+
const deadline = Date.now() + 20000;
|
|
67
|
+
let rondes = 0;
|
|
68
|
+
while (Date.now() < deadline && rondes < 40) {
|
|
69
|
+
const ronde = await runShippingNoteQueue(supabase, { limit: 10 });
|
|
70
|
+
rondes++;
|
|
71
|
+
totaal.claimed += ronde.claimed;
|
|
72
|
+
totaal.printed += ronde.printed;
|
|
73
|
+
totaal.waiting += ronde.waiting;
|
|
74
|
+
totaal.retrying += ronde.retrying;
|
|
75
|
+
totaal.failed += ronde.failed;
|
|
76
|
+
if (Array.isArray(ronde.errors))
|
|
77
|
+
totaal.errors.push(...ronde.errors);
|
|
78
|
+
if (ronde.claimed === 0)
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
return Response.json({
|
|
82
|
+
ok: true,
|
|
83
|
+
shippingNotes: {
|
|
84
|
+
found: totaal.claimed,
|
|
85
|
+
printed: totaal.printed,
|
|
86
|
+
waitingForFloriday: totaal.waiting,
|
|
87
|
+
retrying: totaal.retrying,
|
|
88
|
+
failed: totaal.failed,
|
|
89
|
+
printJobsCreated: totaal.printed,
|
|
90
|
+
rounds: rondes,
|
|
91
|
+
backfill,
|
|
92
|
+
wake,
|
|
93
|
+
errors: totaal.errors.slice(0, 20),
|
|
94
|
+
},
|
|
95
|
+
}, { headers: CORS_HEADERS });
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
return Response.json({ ok: false, error: String(e?.message ?? e) }, { status: 500, headers: CORS_HEADERS });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logistics-tick.server.d.ts","sourceRoot":"","sources":["../../../src/lib/handlers/logistics-tick.server.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAQ5D,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"logistics-tick.server.d.ts","sourceRoot":"","sources":["../../../src/lib/handlers/logistics-tick.server.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAQ5D,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,CAuRnB"}
|