@flowselections/logistiek-engine 1.0.34 → 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/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/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 +1 -1
- package/dist-lib/lib/floridayGuard.server.d.ts.map +1 -1
- package/dist-lib/lib/floridayGuard.server.js +6 -3
- 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.map +1 -1
- package/dist-lib/lib/modulePrompts.js +3459 -2677
- 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 +50 -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
|
@@ -30,6 +30,20 @@ export const RULE_STEPS = [
|
|
|
30
30
|
description: "Bepaal wanneer een order in een gecombineerde order (orderbuffer) terechtkomt.",
|
|
31
31
|
supportsConditions: true,
|
|
32
32
|
groups: [
|
|
33
|
+
{
|
|
34
|
+
id: "herkomst",
|
|
35
|
+
label: "Herkomst van bestellingen",
|
|
36
|
+
description: "Bestellingen komen binnen uit Floriday, de mailbox voor bestellingen, de actiemail of handmatige invoer.",
|
|
37
|
+
fields: [
|
|
38
|
+
{
|
|
39
|
+
key: "floriday_merge_lines",
|
|
40
|
+
label: "Floriday-bestelregels samenvoegen tot \u00e9\u00e9n bestelling",
|
|
41
|
+
type: "toggle",
|
|
42
|
+
default: true,
|
|
43
|
+
description: "Floriday levert elke bestelregel als een eigen verkooporder. Staat dit aan, dan worden regels van dezelfde klant, hetzelfde levermoment en dezelfde afleverlocatie samengevoegd tot \u00e9\u00e9n order met \u00e9\u00e9n ordernummer (het laagste FO-nummer). Orders die al zijn ingedeeld, geprint of gecontroleerd blijven ongewijzigd.",
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
33
47
|
{
|
|
34
48
|
id: "orderbuffer",
|
|
35
49
|
label: "Orderbuffer",
|
|
@@ -232,6 +246,27 @@ export const RULE_STEPS = [
|
|
|
232
246
|
dependsOn: { key: "mode", in: ["auto"] },
|
|
233
247
|
},
|
|
234
248
|
{ key: "max_customers", label: "Maximaal aantal klanten per ladingdrager", type: "number", min: 1, max: 99, default: 2, dependsOn: [{ key: "mode", in: ["auto"] }, { key: "fill_customers_as_much_as_fits", in: [false] }] },
|
|
249
|
+
{
|
|
250
|
+
key: "max_customers_per_layer",
|
|
251
|
+
label: "Maximaal aantal klanten op een laag",
|
|
252
|
+
type: "number",
|
|
253
|
+
min: 1,
|
|
254
|
+
max: 99,
|
|
255
|
+
default: 1,
|
|
256
|
+
description: "Staat dit op 1, dan mogen op één laag alleen producten van dezelfde klant staan. Meerdere bestellingen van dezelfde klant mogen wel samen op een laag.",
|
|
257
|
+
dependsOn: { key: "mode", in: ["auto"] },
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
key: "cart_plan_freeze",
|
|
261
|
+
label: "Wanneer ligt de karrenindeling vast?",
|
|
262
|
+
type: "select",
|
|
263
|
+
default: "per_cart",
|
|
264
|
+
options: [
|
|
265
|
+
{ value: "per_cart", label: "Als de pakbon is uitgeprint" },
|
|
266
|
+
{ value: "first_packing_slip", label: "Als de eerste pakbon van de order of buffer is uitgeprint" },
|
|
267
|
+
],
|
|
268
|
+
description: "Per kar: alleen de kar met een geprinte pakbon blijft staan, de rest mag nog opnieuw ingedeeld worden. Eerste pakbon: zodra de eerste pakbon van de order of buffer is geprint, ligt de hele indeling vast en komen er hoogstens karren bij.",
|
|
269
|
+
},
|
|
235
270
|
{
|
|
236
271
|
key: "fill_layers_as_much_as_fits",
|
|
237
272
|
label: "Lagen: zoveel als past",
|
|
@@ -538,8 +573,8 @@ export const RULE_STEPS = [
|
|
|
538
573
|
},
|
|
539
574
|
{
|
|
540
575
|
value: "manual_approval",
|
|
541
|
-
label: "
|
|
542
|
-
description: "De Engine
|
|
576
|
+
label: "Handmatig herinplannen",
|
|
577
|
+
description: "De Engine doet niets met vertraagde orders: de nieuwe leverdag wordt handmatig in de Afhandeling-module bepaald.",
|
|
543
578
|
},
|
|
544
579
|
],
|
|
545
580
|
},
|
|
@@ -782,7 +817,7 @@ export const RULE_STEPS = [
|
|
|
782
817
|
options: [
|
|
783
818
|
{ value: "after_checkin", label: "Na het aanmeldmoment van het transport" },
|
|
784
819
|
{ value: "after_scan", label: "Automatisch afdrukken nadat een kar is gescand" },
|
|
785
|
-
{ value: "with_packing_slip", label: "
|
|
820
|
+
{ value: "with_packing_slip", label: "Als de pakbon wordt uitgeprint" },
|
|
786
821
|
{ value: "manual_approval", label: "Pas na handmatige goedkeuring op een pickstation" },
|
|
787
822
|
],
|
|
788
823
|
},
|
|
@@ -883,16 +918,18 @@ export const RULE_STEPS = [
|
|
|
883
918
|
type: "select",
|
|
884
919
|
default: "scanner",
|
|
885
920
|
options: [
|
|
886
|
-
{ value: "scanner", label: "Scancontrole" },
|
|
921
|
+
{ value: "scanner", label: "Scancontrole met verzendbrief uitprinten" },
|
|
922
|
+
{ value: "scan_only", label: "Scannen voor afmelden" },
|
|
887
923
|
{ value: "paper", label: "Papieren controle" },
|
|
888
924
|
{ value: "skip", label: "Controle overslaan" },
|
|
889
925
|
],
|
|
926
|
+
description: "Bij 'Scannen voor afmelden' scant de medewerker alleen de pakbon; die ene scan meldt de hele kar direct af. Er wordt dan niets geprint.",
|
|
890
927
|
},
|
|
891
928
|
{
|
|
892
929
|
key: "control_scanner_id",
|
|
893
930
|
label: "Scanner",
|
|
894
931
|
type: "scanner",
|
|
895
|
-
dependsOn: [{ key: "control_mode", in: ["scanner"] }],
|
|
932
|
+
dependsOn: [{ key: "control_mode", in: ["scanner", "scan_only"] }],
|
|
896
933
|
description: "De scanner die bij deze controlepost hoort. Alle pakbonnen die gecontroleerd moeten worden, komen bij deze scanner binnen.",
|
|
897
934
|
},
|
|
898
935
|
{
|
|
@@ -920,6 +957,13 @@ export const RULE_STEPS = [
|
|
|
920
957
|
default: false,
|
|
921
958
|
description: "Staat dit uit, dan verstuurt de Logistics Engine geen enkele statuswijziging naar Floriday. Staat dit aan, dan wordt een order pas op afgehandeld gezet nadat de karrencontrole is goedgekeurd.",
|
|
922
959
|
},
|
|
960
|
+
{
|
|
961
|
+
key: "floriday_delivery_note_create",
|
|
962
|
+
label: "Verzendbrief laten aanmaken in Floriday",
|
|
963
|
+
type: "toggle",
|
|
964
|
+
default: false,
|
|
965
|
+
description: "Staat dit aan, dan laat de Engine bij een Floriday-order een officiele verzendbrief aanmaken zodra de pakbon naar het pickstation gaat, en haalt dat document daarna op. De order wordt hierdoor niet afgemeld; dat blijft aan de controlescan.",
|
|
966
|
+
},
|
|
923
967
|
{
|
|
924
968
|
key: "floriday_stock_updates",
|
|
925
969
|
label: "Voorraad doorgeven aan Floriday",
|
|
@@ -935,7 +979,7 @@ export const RULE_STEPS = [
|
|
|
935
979
|
max: 100,
|
|
936
980
|
default: 100,
|
|
937
981
|
unit: "%",
|
|
938
|
-
dependsOn: { key: "control_mode", in: ["scanner", "paper"] },
|
|
982
|
+
dependsOn: { key: "control_mode", in: ["scanner", "scan_only", "paper"] },
|
|
939
983
|
},
|
|
940
984
|
],
|
|
941
985
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ruleEngineWizard.d.ts","sourceRoot":"","sources":["../../src/lib/ruleEngineWizard.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,SAAS,EAEf,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,2EAA2E;IAC3E,cAAc,EAAE,OAAO,CAAC;CACzB;AAeD,eAAO,MAAM,YAAY,EAAE,UAAU,EAsDpC,CAAC;AA+BF,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAEzD;
|
|
1
|
+
{"version":3,"file":"ruleEngineWizard.d.ts","sourceRoot":"","sources":["../../src/lib/ruleEngineWizard.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,SAAS,EAEf,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,2EAA2E;IAC3E,cAAc,EAAE,OAAO,CAAC;CACzB;AAeD,eAAO,MAAM,YAAY,EAAE,UAAU,EAsDpC,CAAC;AA+BF,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAEzD;AAwED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAE9D;AAyCD,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAStF"}
|
|
@@ -114,6 +114,8 @@ const EXTRA_HELP = {
|
|
|
114
114
|
multi_order: "Aan: orders van meerdere bestellingen mogen op dezelfde drager staan.",
|
|
115
115
|
max_orders: "Meer orders op één drager betekent minder karren, maar wel meer sorteerwerk.",
|
|
116
116
|
max_customers: "Handig als klanten hun eigen kar willen ontvangen.",
|
|
117
|
+
max_customers_per_layer: "Op 1 komen er nooit twee verschillende klanten op dezelfde laag; meerdere bestellingen van dezelfde klant mogen wel samen.",
|
|
118
|
+
cart_plan_freeze: "Bepaalt hoe streng een eenmaal geprinte indeling vaststaat. Per kar blijft alleen de geprinte kar staan; bij 'eerste pakbon' ligt de hele order of buffer vast zodra er één pakbon uit de printer is.",
|
|
117
119
|
max_layers: "Het aantal lagen dat je fysiek op een kar of container kwijt kunt.",
|
|
118
120
|
max_boxes_per_pallet: "Het aantal dozen dat je fysiek op één pallet kwijt kunt.",
|
|
119
121
|
optimal_fill: "Aan: het systeem zoekt de indeling waarbij de minste dragers nodig zijn.",
|
|
@@ -144,7 +146,7 @@ const EXTRA_HELP = {
|
|
|
144
146
|
shipping_note_layout: "\u00c9\u00e9n layout voor de verzend-, aflever- en veilingbrief van BVO orders.",
|
|
145
147
|
production_note_release: "Bepaalt op welk moment de productiebon beschikbaar komt.",
|
|
146
148
|
production_note_station: "Het pickstation waar de productiebon uitgeprint wordt.",
|
|
147
|
-
control_mode: "Hoe je controleert of de kar klopt voordat hij weggaat.",
|
|
149
|
+
control_mode: "Hoe je controleert of de kar klopt voordat hij weggaat. Bij 'Scannen voor afmelden' is één pakbonscan genoeg en wordt de hele kar direct afgemeld.",
|
|
148
150
|
control_print_items: "Welke papieren de medewerker bij de controle krijgt.",
|
|
149
151
|
sample_percentage: "100% betekent alles controleren; lager betekent steekproefsgewijs.",
|
|
150
152
|
pick_reserve_minutes: "Extra tijd die je altijd vrijhoudt vóór de vervoerder komt.",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
+
export interface ShippingNoteRun {
|
|
3
|
+
/** Het aantal aanvragen dat deze ronde is opgepakt. */
|
|
4
|
+
claimed: number;
|
|
5
|
+
/** Aantal aangemaakte verzendbrief-printopdrachten. */
|
|
6
|
+
printed: number;
|
|
7
|
+
/** Aantal aanvragen dat wacht op het officiële Floriday-document. */
|
|
8
|
+
waiting: number;
|
|
9
|
+
/** Aantal aanvragen dat door een tijdelijke storing opnieuw wordt geprobeerd. */
|
|
10
|
+
retrying: number;
|
|
11
|
+
/** Aantal aanvragen met een definitieve fout. */
|
|
12
|
+
failed: number;
|
|
13
|
+
errors: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare function runShippingNoteQueue(sb: SupabaseClient, options?: {
|
|
16
|
+
limit?: number;
|
|
17
|
+
}): Promise<ShippingNoteRun>;
|
|
18
|
+
//# sourceMappingURL=shippingNoteQueue.server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shippingNoteQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/shippingNoteQueue.server.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK5D,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAqCD,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CAmU1B"}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/lib/shippingNoteQueue.server.ts
|
|
3
|
+
// Verzendbrief bij het printen van een kar.
|
|
4
|
+
//
|
|
5
|
+
// De pakbon is de enige bron voor kar en printer. De wachtrijregel bewaart
|
|
6
|
+
// alleen de verwijzing naar de pakbon; op het moment dat de printopdracht
|
|
7
|
+
// wordt aangemaakt worden kar en printer uit die pakbon gelezen.
|
|
8
|
+
//
|
|
9
|
+
// BVO-orders krijgen hun eigen layout al vanuit de database. FO-orders (Floriday)
|
|
10
|
+
// komen hier langs: alleen het officiële Floriday-document mag worden geprint.
|
|
11
|
+
// Er wordt niets bevestigd of afgehandeld, en er komen geen omgevings- of
|
|
12
|
+
// klantwaarden in deze code.
|
|
13
|
+
// ============================================================================
|
|
14
|
+
import { trace, newTraceId, classifyError } from "./trace.server.js";
|
|
15
|
+
import { FLOW_NODE } from "./flowNodes.js";
|
|
16
|
+
/** Na dit aantal pogingen is een aanvraag definitief mislukt. */
|
|
17
|
+
const MAX_ATTEMPTS = 60;
|
|
18
|
+
function pickPdf(result) {
|
|
19
|
+
const base64 = result["pdfBase64"] ??
|
|
20
|
+
result["base64"] ??
|
|
21
|
+
result["pdf"] ??
|
|
22
|
+
null;
|
|
23
|
+
const url = result["url"] ??
|
|
24
|
+
result["pdfUrl"] ??
|
|
25
|
+
result["documentUrl"] ??
|
|
26
|
+
null;
|
|
27
|
+
return { base64: base64 ?? null, url: url ?? null };
|
|
28
|
+
}
|
|
29
|
+
/** Bepaalt of een Floriday-antwoord tijdelijk is of "nog niet beschikbaar". */
|
|
30
|
+
function classifyFloridayReason(message) {
|
|
31
|
+
const tijdelijk = /(timeout|time-out|tijdelijk|netwerk|network|rate.?limit|429|50\d|service unavailable|unavailable|opnieuw)/i;
|
|
32
|
+
return tijdelijk.test(message) ? "tijdelijk" : "nog_niet_beschikbaar";
|
|
33
|
+
}
|
|
34
|
+
export async function runShippingNoteQueue(sb, options = {}) {
|
|
35
|
+
const run = {
|
|
36
|
+
claimed: 0,
|
|
37
|
+
printed: 0,
|
|
38
|
+
waiting: 0,
|
|
39
|
+
retrying: 0,
|
|
40
|
+
failed: 0,
|
|
41
|
+
errors: [],
|
|
42
|
+
};
|
|
43
|
+
const { data, error } = await sb.rpc("logistics_slip_note_claim", {
|
|
44
|
+
_limit: options.limit ?? 10,
|
|
45
|
+
_lease_seconds: 120,
|
|
46
|
+
});
|
|
47
|
+
if (error) {
|
|
48
|
+
run.errors.push(`Verzendbrieven niet leesbaar: ${error.message}`);
|
|
49
|
+
return run;
|
|
50
|
+
}
|
|
51
|
+
const rows = Array.isArray(data) ? data : [];
|
|
52
|
+
run.claimed = rows.length;
|
|
53
|
+
if (rows.length === 0)
|
|
54
|
+
return run;
|
|
55
|
+
const { getFlorydayDocument } = await import("./floridayDocuments.server.js");
|
|
56
|
+
for (const row of rows) {
|
|
57
|
+
const attempts = Number(row.attempts ?? 0);
|
|
58
|
+
const traceId = newTraceId();
|
|
59
|
+
const basis = {
|
|
60
|
+
traceId,
|
|
61
|
+
orderRef: row.order_number ?? row.order_id ?? null,
|
|
62
|
+
orderSource: "floriday",
|
|
63
|
+
cartRef: row.cart_id ?? null,
|
|
64
|
+
slipRef: row.slip_job_id ?? null,
|
|
65
|
+
phase: "verzendbrief",
|
|
66
|
+
actor: "logistiek-engine:verzendbriefwachtrij",
|
|
67
|
+
attempts,
|
|
68
|
+
nodeId: FLOW_NODE.stations,
|
|
69
|
+
};
|
|
70
|
+
await trace(sb, {
|
|
71
|
+
...basis,
|
|
72
|
+
step: "Verzendbriefaanvraag opgepakt",
|
|
73
|
+
status: "geslaagd",
|
|
74
|
+
input: { aanvraagId: row.id, pakbonJobId: row.slip_job_id, pogingen: attempts },
|
|
75
|
+
nextStep: "Officiële Floriday-verzendbrief ophalen",
|
|
76
|
+
});
|
|
77
|
+
const faal = async (code, reden, fulfillmentOrderId) => {
|
|
78
|
+
await sb.rpc("logistics_slip_note_finish", {
|
|
79
|
+
_id: row.id,
|
|
80
|
+
_ok: false,
|
|
81
|
+
_status: "mislukt",
|
|
82
|
+
_fulfillment_order_id: fulfillmentOrderId ?? null,
|
|
83
|
+
_error_code: code,
|
|
84
|
+
_error: reden,
|
|
85
|
+
});
|
|
86
|
+
run.failed++;
|
|
87
|
+
await trace(sb, {
|
|
88
|
+
...basis,
|
|
89
|
+
step: "Verzendbrief definitief mislukt",
|
|
90
|
+
status: "mislukt",
|
|
91
|
+
decision: code,
|
|
92
|
+
reason: reden,
|
|
93
|
+
error: reden,
|
|
94
|
+
errorClass: classifyError(code, reden),
|
|
95
|
+
nextStep: "Handmatig oplossen; de Engine probeert het niet meer.",
|
|
96
|
+
calc: { values: { pogingen: attempts, maximaal: MAX_ATTEMPTS }, conclusion: reden },
|
|
97
|
+
...(fulfillmentOrderId ? { externalRef: fulfillmentOrderId } : {}),
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
const wacht = async (reden, klasse) => {
|
|
101
|
+
if (attempts >= MAX_ATTEMPTS) {
|
|
102
|
+
await faal("wachten_verlopen", `Na ${attempts} pogingen is er nog steeds geen officiële verzendbrief. Laatste reden: ${reden}`);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
await sb.rpc("logistics_slip_note_keep_waiting", {
|
|
106
|
+
_id: row.id,
|
|
107
|
+
_reason: reden,
|
|
108
|
+
_class: klasse,
|
|
109
|
+
});
|
|
110
|
+
if (klasse === "tijdelijk")
|
|
111
|
+
run.retrying++;
|
|
112
|
+
else
|
|
113
|
+
run.waiting++;
|
|
114
|
+
await trace(sb, {
|
|
115
|
+
...basis,
|
|
116
|
+
step: "Wachten op officiële Floriday-verzendbrief",
|
|
117
|
+
status: "wachtend",
|
|
118
|
+
decision: klasse,
|
|
119
|
+
reason: reden,
|
|
120
|
+
errorClass: "extern",
|
|
121
|
+
rule: "FO-orders krijgen uitsluitend het officiële Floriday-document",
|
|
122
|
+
nextStep: "Automatisch opnieuw proberen",
|
|
123
|
+
calc: {
|
|
124
|
+
setting: "Maximaal aantal pogingen voor de verzendbrief",
|
|
125
|
+
values: { poging: attempts, maximaal: MAX_ATTEMPTS },
|
|
126
|
+
conclusion: `Nog ${Math.max(MAX_ATTEMPTS - attempts, 0)} poging(en) over.`,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
try {
|
|
131
|
+
if (!row.order_number) {
|
|
132
|
+
await faal("geen_ordernummer", "Bij deze kar hoort geen ordernummer; de verzendbrief kan niet worden opgehaald.");
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
// Een verzendbrief ophalen is een leesactie. Wacht daarom niet op de
|
|
136
|
+
// status-/afhandelpush: die is bewust geblokkeerd tot na de controlescan.
|
|
137
|
+
const { data: order, error: orderError } = await sb
|
|
138
|
+
.from("orders")
|
|
139
|
+
.select("floriday_sales_order_id")
|
|
140
|
+
.eq("id", row.order_id ?? "")
|
|
141
|
+
.maybeSingle();
|
|
142
|
+
if (orderError) {
|
|
143
|
+
await wacht(`De Floriday-order kon niet worden gelezen: ${orderError.message}`, "tijdelijk");
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
const salesOrderId = String(order?.["floriday_sales_order_id"] ?? "").trim();
|
|
147
|
+
if (!salesOrderId) {
|
|
148
|
+
await faal("sales_order_ontbreekt", "Bij deze FO-order ontbreekt het Floriday sales-order-ID; de verzendbrief kan niet worden opgehaald.");
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
// Stap 1: zorg dat Floriday een officiele verzendbrief heeft. Bestaat er
|
|
152
|
+
// al een fulfillment-order voor deze pakbon, dan wordt er geen tweede
|
|
153
|
+
// aangemaakt.
|
|
154
|
+
let bestaandeFo = String(row.fulfillment_order_id ?? "").trim() || null;
|
|
155
|
+
if (!bestaandeFo) {
|
|
156
|
+
const { createFlorydayDeliveryNote } = await import("./floridayDocuments.server.js");
|
|
157
|
+
const startAanmaak = Date.now();
|
|
158
|
+
const aangemaakt = await createFlorydayDeliveryNote(sb, row.order_number);
|
|
159
|
+
await trace(sb, {
|
|
160
|
+
...basis,
|
|
161
|
+
step: "Floriday: verzendbrief aanvragen",
|
|
162
|
+
status: aangemaakt.fulfillmentOrderId ? "geslaagd" : aangemaakt.ok ? "wachtend" : "mislukt",
|
|
163
|
+
externalSystem: "floriday",
|
|
164
|
+
externalAction: "fulfillment-order aanmaken",
|
|
165
|
+
...(aangemaakt.fulfillmentOrderId ? { externalRef: aangemaakt.fulfillmentOrderId } : {}),
|
|
166
|
+
externalResponse: aangemaakt,
|
|
167
|
+
durationMs: Date.now() - startAanmaak,
|
|
168
|
+
...(aangemaakt.error ? { error: aangemaakt.error } : {}),
|
|
169
|
+
});
|
|
170
|
+
if (aangemaakt.fulfillmentOrderId) {
|
|
171
|
+
bestaandeFo = aangemaakt.fulfillmentOrderId;
|
|
172
|
+
await sb
|
|
173
|
+
.from("logistics_slip_shipping_note")
|
|
174
|
+
.update({ fulfillment_order_id: bestaandeFo })
|
|
175
|
+
.eq("id", row.id)
|
|
176
|
+
.is("fulfillment_order_id", null);
|
|
177
|
+
}
|
|
178
|
+
else if (!aangemaakt.ok) {
|
|
179
|
+
await wacht(`Wachten op Floriday-verzendbrief: ${aangemaakt.error ?? "Floriday heeft het document nog niet aangemaakt."}`, aangemaakt.skipped ? "nog_niet_beschikbaar" : classifyFloridayReason(aangemaakt.error ?? ""));
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Stap 2: het officiele document ophalen.
|
|
184
|
+
const startOphalen = Date.now();
|
|
185
|
+
const doc = (await getFlorydayDocument(sb, {
|
|
186
|
+
kind: "delivery-note",
|
|
187
|
+
salesOrderId,
|
|
188
|
+
...(bestaandeFo ? { fulfillmentOrderId: bestaandeFo } : {}),
|
|
189
|
+
}));
|
|
190
|
+
await trace(sb, {
|
|
191
|
+
...basis,
|
|
192
|
+
step: "Floriday: verzendbrief ophalen",
|
|
193
|
+
status: doc["ok"] ? "geslaagd" : "wachtend",
|
|
194
|
+
externalSystem: "floriday",
|
|
195
|
+
externalAction: "delivery-note ophalen",
|
|
196
|
+
...(bestaandeFo ? { externalRef: bestaandeFo } : {}),
|
|
197
|
+
externalResponse: {
|
|
198
|
+
ok: doc["ok"] ?? false,
|
|
199
|
+
error: doc["error"] ?? null,
|
|
200
|
+
heeftBestand: Boolean(doc["pdfBase64"] ?? doc["base64"] ?? doc["pdf"] ?? doc["url"]),
|
|
201
|
+
},
|
|
202
|
+
durationMs: Date.now() - startOphalen,
|
|
203
|
+
});
|
|
204
|
+
if (!doc["ok"]) {
|
|
205
|
+
const message = String(doc["error"] ?? "") ||
|
|
206
|
+
"Wachten op officiële Floriday-afleverbrief: Floriday heeft het document nog niet aangemaakt.";
|
|
207
|
+
await wacht(message, classifyFloridayReason(message));
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const fulfillmentOrderId = String(doc["fulfillmentOrderId"] ?? doc["fulfillment_order_id"] ?? "").trim() ||
|
|
211
|
+
bestaandeFo;
|
|
212
|
+
const { base64, url } = pickPdf(doc);
|
|
213
|
+
if (!base64 && !url) {
|
|
214
|
+
// Nooit een leeg of zelfgemaakt document printen.
|
|
215
|
+
await wacht("Wachten op officiële Floriday-afleverbrief: Floriday gaf nog geen bruikbaar bestand terug.", "nog_niet_beschikbaar");
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
// De pakbon is de bron voor printer en kar.
|
|
219
|
+
const { data: slip } = await sb
|
|
220
|
+
.from("print_jobs")
|
|
221
|
+
.select("payload, printer_id, documentnaam, is_herprint")
|
|
222
|
+
.eq("id", row.slip_job_id)
|
|
223
|
+
.maybeSingle();
|
|
224
|
+
const slipRow = (slip ?? null);
|
|
225
|
+
if (!slipRow) {
|
|
226
|
+
await faal("pakbon_verdwenen", "De bijbehorende pakbon bestaat niet meer; er wordt geen losse verzendbrief gemaakt.", fulfillmentOrderId);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const slipPayload = slipRow["payload"] ?? {};
|
|
230
|
+
const printerId = slipRow["printer_id"] ?? null;
|
|
231
|
+
const cartId = slipPayload["cart_id"] ?? row.cart_id;
|
|
232
|
+
if (!printerId) {
|
|
233
|
+
await wacht("De pakbon heeft nog geen printer toegewezen gekregen; de verzendbrief wacht op dezelfde printer.", "tijdelijk");
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const idempotentie = `verzendbrief-bij-pakbon:${row.slip_job_id}`;
|
|
237
|
+
const { data: bestaand } = await sb
|
|
238
|
+
.from("print_jobs")
|
|
239
|
+
.select("id")
|
|
240
|
+
.eq("idempotentie_sleutel", idempotentie)
|
|
241
|
+
.maybeSingle();
|
|
242
|
+
let jobId = bestaand?.["id"] ?? null;
|
|
243
|
+
if (!jobId) {
|
|
244
|
+
const { data: job, error: jobError } = await sb
|
|
245
|
+
.from("print_jobs")
|
|
246
|
+
.insert({
|
|
247
|
+
printer_id: printerId,
|
|
248
|
+
documenttype: "afleverbrief",
|
|
249
|
+
documentnaam: `Verzendbrief ${row.order_number}`,
|
|
250
|
+
status: "wachtend",
|
|
251
|
+
idempotentie_sleutel: idempotentie,
|
|
252
|
+
pdf_base64: base64,
|
|
253
|
+
pdf_url: url,
|
|
254
|
+
herkomst: "logistiek-engine",
|
|
255
|
+
gebruiker_naam: "Pickstation",
|
|
256
|
+
is_herprint: Boolean(slipRow["is_herprint"] ?? false),
|
|
257
|
+
payload: {
|
|
258
|
+
...slipPayload,
|
|
259
|
+
source: "pickstation",
|
|
260
|
+
document_type_code: "verzendbrief",
|
|
261
|
+
documentType: "verzendbrief",
|
|
262
|
+
trigger: "with_packing_slip",
|
|
263
|
+
is_floriday: true,
|
|
264
|
+
packing_slip_job_id: row.slip_job_id,
|
|
265
|
+
print_batch_key: row.batch_key ?? `kar-print:${row.slip_job_id}`,
|
|
266
|
+
order_id: row.order_id,
|
|
267
|
+
order_number: row.order_number,
|
|
268
|
+
cart_id: cartId,
|
|
269
|
+
fulfillment_order_id: fulfillmentOrderId,
|
|
270
|
+
},
|
|
271
|
+
})
|
|
272
|
+
.select("id")
|
|
273
|
+
.maybeSingle();
|
|
274
|
+
if (jobError) {
|
|
275
|
+
await wacht(`De verzendbrief kon nog niet worden klaargezet om te printen: ${jobError.message}`, "tijdelijk");
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
jobId = job?.["id"] ?? null;
|
|
279
|
+
}
|
|
280
|
+
await sb.rpc("logistics_slip_note_finish", {
|
|
281
|
+
_id: row.id,
|
|
282
|
+
_ok: true,
|
|
283
|
+
_status: "geprint",
|
|
284
|
+
_print_job_id: jobId,
|
|
285
|
+
_fulfillment_order_id: fulfillmentOrderId,
|
|
286
|
+
});
|
|
287
|
+
run.printed++;
|
|
288
|
+
await trace(sb, {
|
|
289
|
+
...basis,
|
|
290
|
+
step: "Verzendbrief klaargezet om te printen",
|
|
291
|
+
status: "geslaagd",
|
|
292
|
+
decision: "samen met de pakbon naar dezelfde printer",
|
|
293
|
+
...(fulfillmentOrderId ? { externalRef: fulfillmentOrderId } : {}),
|
|
294
|
+
output: { printJobId: jobId, printerId, cartId },
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
catch (e) {
|
|
298
|
+
const message = String(e?.message ?? e);
|
|
299
|
+
run.errors.push(message);
|
|
300
|
+
await wacht(`Onverwachte fout bij het ophalen van de verzendbrief: ${message}`, "tijdelijk");
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return run;
|
|
304
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
+
export type TraceStatus = "geslaagd" | "wachtend" | "waarschuwing" | "overgeslagen" | "mislukt";
|
|
3
|
+
/**
|
|
4
|
+
* Foutsoort — zodat het logboek onderscheid maakt tussen een storing en een
|
|
5
|
+
* bewuste regel.
|
|
6
|
+
* technisch = database/API/printer/integratie ging stuk
|
|
7
|
+
* ontbrekende_gegevens = de order of stamgegevens missen iets
|
|
8
|
+
* configuratie = een instelling of koppeling staat niet goed
|
|
9
|
+
* regel = de Engine mag bewust niet verder (business rule)
|
|
10
|
+
* extern = een extern systeem heeft (nog) niet geleverd
|
|
11
|
+
*/
|
|
12
|
+
export type TraceErrorClass = "technisch" | "ontbrekende_gegevens" | "configuratie" | "regel" | "extern";
|
|
13
|
+
/** Berekening achter een beslissing, in begrijpelijke stappen. */
|
|
14
|
+
export interface TraceCalc {
|
|
15
|
+
/** Welke instelling(en) meespeelden. */
|
|
16
|
+
setting?: string;
|
|
17
|
+
/** De gebruikte waarden, bijv. { lagen: 7, maxPerKar: 5 }. */
|
|
18
|
+
values?: Record<string, unknown>;
|
|
19
|
+
/** De rekenstap zelf, bijv. "7 / 5". */
|
|
20
|
+
formula?: string;
|
|
21
|
+
/** De uitkomst, bijv. "1 volle kar + 1 deelkar". */
|
|
22
|
+
result?: string;
|
|
23
|
+
/** Conclusie in gewone taal. */
|
|
24
|
+
conclusion?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface TraceEvent {
|
|
27
|
+
traceId?: string | null;
|
|
28
|
+
orderRef?: string | null;
|
|
29
|
+
orderSource?: "floriday" | "eigen" | null;
|
|
30
|
+
cartRef?: string | null;
|
|
31
|
+
slipRef?: string | null;
|
|
32
|
+
phase: string;
|
|
33
|
+
step: string;
|
|
34
|
+
status: TraceStatus;
|
|
35
|
+
actor?: string;
|
|
36
|
+
/** Vakje in de flowkaart waar deze stap hoort (id uit flowTree). */
|
|
37
|
+
nodeId?: string;
|
|
38
|
+
input?: unknown;
|
|
39
|
+
output?: unknown;
|
|
40
|
+
reads?: unknown;
|
|
41
|
+
decision?: string;
|
|
42
|
+
reason?: string;
|
|
43
|
+
values?: unknown;
|
|
44
|
+
rule?: string;
|
|
45
|
+
/** Berekening achter de beslissing. */
|
|
46
|
+
calc?: TraceCalc;
|
|
47
|
+
/** Wat de order hierna gaat doen. */
|
|
48
|
+
nextStep?: string;
|
|
49
|
+
errorClass?: TraceErrorClass;
|
|
50
|
+
dbTable?: string;
|
|
51
|
+
dbRecord?: string;
|
|
52
|
+
dbAction?: string;
|
|
53
|
+
dbOld?: unknown;
|
|
54
|
+
dbNew?: unknown;
|
|
55
|
+
externalSystem?: string;
|
|
56
|
+
externalAction?: string;
|
|
57
|
+
externalRef?: string;
|
|
58
|
+
externalStatus?: string;
|
|
59
|
+
externalResponse?: unknown;
|
|
60
|
+
error?: string;
|
|
61
|
+
attempts?: number;
|
|
62
|
+
nextAttemptAt?: string | null;
|
|
63
|
+
durationMs?: number;
|
|
64
|
+
}
|
|
65
|
+
/** Bepaalt de foutsoort uit een reden-code of foutmelding. */
|
|
66
|
+
export declare function classifyError(reasonCode?: string | null, message?: string | null): TraceErrorClass;
|
|
67
|
+
/** Nieuw trace-id voor één volledige verwerkingsronde van een order. */
|
|
68
|
+
export declare function newTraceId(): string;
|
|
69
|
+
/** Eén gebeurtenis vastleggen. Faalt nooit hard. */
|
|
70
|
+
export declare function trace(sb: SupabaseClient, event: TraceEvent): Promise<void>;
|
|
71
|
+
/** Meerdere gebeurtenissen in één keer vastleggen. */
|
|
72
|
+
export declare function traceBatch(sb: SupabaseClient, events: TraceEvent[]): Promise<void>;
|
|
73
|
+
/** Meet de duur van een stap en legt uitkomst of fout vast. */
|
|
74
|
+
export declare function traced<T>(sb: SupabaseClient, event: Omit<TraceEvent, "status">, run: () => Promise<T>): Promise<T>;
|
|
75
|
+
//# sourceMappingURL=trace.server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.server.d.ts","sourceRoot":"","sources":["../../src/lib/trace.server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/lib/trace.server.ts — audittrail vanuit de Engine zelf
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Elke stap, beslissing, databasewijziging en externe aanvraag wordt hier
|
|
5
|
+
// vastgelegd via public.logistics_trace. Loggen mag de verwerking nooit
|
|
6
|
+
// blokkeren: fouten worden bewust ingeslikt.
|
|
7
|
+
// ============================================================================
|
|
8
|
+
/** Bepaalt de foutsoort uit een reden-code of foutmelding. */
|
|
9
|
+
export function classifyError(reasonCode, message) {
|
|
10
|
+
const t = `${reasonCode ?? ""} ${message ?? ""}`.toLowerCase();
|
|
11
|
+
if (/afmeting|ontbreek|onbekend|geen regels|mist|niet gevuld|leeg/.test(t))
|
|
12
|
+
return "ontbrekende_gegevens";
|
|
13
|
+
if (/instelling|configurat|layout|mapping|niet ingesteld|werktijden/.test(t))
|
|
14
|
+
return "configuratie";
|
|
15
|
+
if (/kargrens|regel|niet toegestaan|geblokkeerd|vrijgave|aanmeldmoment|bevroren/.test(t))
|
|
16
|
+
return "regel";
|
|
17
|
+
if (/floriday|api|http|timeout|extern|printer/.test(t))
|
|
18
|
+
return "extern";
|
|
19
|
+
return "technisch";
|
|
20
|
+
}
|
|
21
|
+
/** Nieuw trace-id voor één volledige verwerkingsronde van een order. */
|
|
22
|
+
export function newTraceId() {
|
|
23
|
+
return globalThis.crypto?.randomUUID?.() ?? "";
|
|
24
|
+
}
|
|
25
|
+
function clean(event) {
|
|
26
|
+
const out = {};
|
|
27
|
+
for (const [key, value] of Object.entries(event)) {
|
|
28
|
+
if (value !== undefined && value !== null && value !== "")
|
|
29
|
+
out[key] = value;
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
/** Eén gebeurtenis vastleggen. Faalt nooit hard. */
|
|
34
|
+
export async function trace(sb, event) {
|
|
35
|
+
try {
|
|
36
|
+
await sb.rpc("logistics_trace", { p: clean(event) });
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
/* loggen mag de verwerking niet blokkeren */
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Meerdere gebeurtenissen in één keer vastleggen. */
|
|
43
|
+
export async function traceBatch(sb, events) {
|
|
44
|
+
if (!Array.isArray(events) || events.length === 0)
|
|
45
|
+
return;
|
|
46
|
+
try {
|
|
47
|
+
await sb.rpc("logistics_trace_batch", { p: events.map(clean) });
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
/* loggen mag de verwerking niet blokkeren */
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Meet de duur van een stap en legt uitkomst of fout vast. */
|
|
54
|
+
export async function traced(sb, event, run) {
|
|
55
|
+
const start = Date.now();
|
|
56
|
+
try {
|
|
57
|
+
const result = await run();
|
|
58
|
+
await trace(sb, {
|
|
59
|
+
...event,
|
|
60
|
+
status: "geslaagd",
|
|
61
|
+
durationMs: Date.now() - start,
|
|
62
|
+
output: event.output ?? result,
|
|
63
|
+
});
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
await trace(sb, {
|
|
68
|
+
...event,
|
|
69
|
+
status: "mislukt",
|
|
70
|
+
durationMs: Date.now() - start,
|
|
71
|
+
error: String(e?.message ?? e),
|
|
72
|
+
});
|
|
73
|
+
throw e;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type NodeTraceGroep } from "./nodeTrace";
|
|
2
|
+
export interface VakUitleg {
|
|
3
|
+
/** Welke keuze de Engine hier maakte. */
|
|
4
|
+
beslissing: string;
|
|
5
|
+
/** Waarom die keuze is gemaakt. */
|
|
6
|
+
waarom: string | null;
|
|
7
|
+
/** De bepalende gegevens en instellingen, als korte paren. */
|
|
8
|
+
feiten: string[];
|
|
9
|
+
/** Regel/instelling waarop de keuze steunt. */
|
|
10
|
+
regel: string | null;
|
|
11
|
+
/** Is dit afgeleid uit de registraties in plaats van vastgelegd? */
|
|
12
|
+
afgeleid: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Maakt van de gebeurtenissen van één vakje een vaste uitleg:
|
|
16
|
+
* welke keuze is gemaakt, waarom, en welke gegevens dat bepaalden.
|
|
17
|
+
*/
|
|
18
|
+
export declare function vakUitleg(groep: NodeTraceGroep): VakUitleg;
|
|
19
|
+
//# sourceMappingURL=vakUitleg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vakUitleg.d.ts","sourceRoot":"","sources":["../../src/lib/vakUitleg.ts"],"names":[],"mappings":"AASA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjE,MAAM,WAAW,SAAS;IACxB,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,oEAAoE;IACpE,QAAQ,EAAE,OAAO,CAAC;CACnB;AA6DD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,CAoD1D"}
|