@flowselections/logistiek-engine 1.0.34 → 1.0.89

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.
Files changed (244) hide show
  1. package/dist-lib/components/AfrondWachtrijCard.d.ts +2 -0
  2. package/dist-lib/components/AfrondWachtrijCard.d.ts.map +1 -0
  3. package/dist-lib/components/AfrondWachtrijCard.js +27 -0
  4. package/dist-lib/components/BeladingsafwijkingenCard.d.ts +2 -0
  5. package/dist-lib/components/BeladingsafwijkingenCard.d.ts.map +1 -0
  6. package/dist-lib/components/BeladingsafwijkingenCard.js +44 -0
  7. package/dist-lib/components/FlowCanvas.d.ts +34 -0
  8. package/dist-lib/components/FlowCanvas.d.ts.map +1 -0
  9. package/dist-lib/components/FlowCanvas.js +490 -0
  10. package/dist-lib/components/FlowOrders.d.ts +8 -0
  11. package/dist-lib/components/FlowOrders.d.ts.map +1 -0
  12. package/dist-lib/components/FlowOrders.js +171 -0
  13. package/dist-lib/components/FlowPage.d.ts +2 -0
  14. package/dist-lib/components/FlowPage.d.ts.map +1 -0
  15. package/dist-lib/components/FlowPage.js +310 -0
  16. package/dist-lib/components/GeblokkeerdeOrdersCard.d.ts.map +1 -1
  17. package/dist-lib/components/GeblokkeerdeOrdersCard.js +21 -2
  18. package/dist-lib/components/InklapbaarVenster.d.ts +9 -0
  19. package/dist-lib/components/InklapbaarVenster.d.ts.map +1 -0
  20. package/dist-lib/components/InklapbaarVenster.js +10 -0
  21. package/dist-lib/components/KardekkingCard.d.ts +2 -0
  22. package/dist-lib/components/KardekkingCard.d.ts.map +1 -0
  23. package/dist-lib/components/KardekkingCard.js +29 -0
  24. package/dist-lib/components/LogistiekEnginePage.d.ts.map +1 -1
  25. package/dist-lib/components/LogistiekEnginePage.js +15 -3
  26. package/dist-lib/components/LogistiekEngineQueuePage.d.ts +2 -0
  27. package/dist-lib/components/LogistiekEngineQueuePage.d.ts.map +1 -0
  28. package/dist-lib/components/LogistiekEngineQueuePage.js +13 -0
  29. package/dist-lib/components/NodeTracePanel.d.ts +14 -0
  30. package/dist-lib/components/NodeTracePanel.d.ts.map +1 -0
  31. package/dist-lib/components/NodeTracePanel.js +46 -0
  32. package/dist-lib/components/OrderJourneyBar.d.ts +9 -0
  33. package/dist-lib/components/OrderJourneyBar.d.ts.map +1 -0
  34. package/dist-lib/components/OrderJourneyBar.js +26 -0
  35. package/dist-lib/components/OrderLogboek.d.ts +10 -0
  36. package/dist-lib/components/OrderLogboek.d.ts.map +1 -0
  37. package/dist-lib/components/OrderLogboek.js +92 -0
  38. package/dist-lib/components/OrderStopBanner.d.ts +12 -0
  39. package/dist-lib/components/OrderStopBanner.d.ts.map +1 -0
  40. package/dist-lib/components/OrderStopBanner.js +36 -0
  41. package/dist-lib/components/OrderTraceDetails.d.ts +22 -0
  42. package/dist-lib/components/OrderTraceDetails.d.ts.map +1 -0
  43. package/dist-lib/components/OrderTraceDetails.js +88 -0
  44. package/dist-lib/components/PlanWachtrijPage.d.ts +2 -0
  45. package/dist-lib/components/PlanWachtrijPage.d.ts.map +1 -0
  46. package/dist-lib/components/PlanWachtrijPage.js +99 -0
  47. package/dist-lib/components/PlannerDiffCard.d.ts +2 -0
  48. package/dist-lib/components/PlannerDiffCard.d.ts.map +1 -0
  49. package/dist-lib/components/PlannerDiffCard.js +25 -0
  50. package/dist-lib/components/RegiePage.d.ts.map +1 -1
  51. package/dist-lib/components/RegiePage.js +28 -78
  52. package/dist-lib/components/TaakGezondheidCard.d.ts +2 -0
  53. package/dist-lib/components/TaakGezondheidCard.d.ts.map +1 -0
  54. package/dist-lib/components/TaakGezondheidCard.js +31 -0
  55. package/dist-lib/components/WerktijdenCard.d.ts +2 -0
  56. package/dist-lib/components/WerktijdenCard.d.ts.map +1 -0
  57. package/dist-lib/components/WerktijdenCard.js +37 -0
  58. package/dist-lib/components/WerkwijzeHerindelingCard.d.ts.map +1 -1
  59. package/dist-lib/components/WerkwijzeHerindelingCard.js +100 -6
  60. package/dist-lib/hooks/useAfrondWachtrij.d.ts +28 -0
  61. package/dist-lib/hooks/useAfrondWachtrij.d.ts.map +1 -0
  62. package/dist-lib/hooks/useAfrondWachtrij.js +88 -0
  63. package/dist-lib/hooks/useBeladingsafwijkingen.d.ts +39 -0
  64. package/dist-lib/hooks/useBeladingsafwijkingen.d.ts.map +1 -0
  65. package/dist-lib/hooks/useBeladingsafwijkingen.js +119 -0
  66. package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts +7 -0
  67. package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts.map +1 -1
  68. package/dist-lib/hooks/useGeblokkeerdeOrders.js +28 -2
  69. package/dist-lib/hooks/useLogisticsTrace.d.ts +78 -0
  70. package/dist-lib/hooks/useLogisticsTrace.d.ts.map +1 -0
  71. package/dist-lib/hooks/useLogisticsTrace.js +152 -0
  72. package/dist-lib/hooks/useOrderNodeTrace.d.ts +11 -0
  73. package/dist-lib/hooks/useOrderNodeTrace.d.ts.map +1 -0
  74. package/dist-lib/hooks/useOrderNodeTrace.js +26 -0
  75. package/dist-lib/hooks/useOrderTrace.d.ts +74 -0
  76. package/dist-lib/hooks/useOrderTrace.d.ts.map +1 -0
  77. package/dist-lib/hooks/useOrderTrace.js +134 -0
  78. package/dist-lib/hooks/useOrderVersies.d.ts +47 -0
  79. package/dist-lib/hooks/useOrderVersies.d.ts.map +1 -0
  80. package/dist-lib/hooks/useOrderVersies.js +194 -0
  81. package/dist-lib/hooks/usePlanWachtrij.d.ts +33 -0
  82. package/dist-lib/hooks/usePlanWachtrij.d.ts.map +1 -0
  83. package/dist-lib/hooks/usePlanWachtrij.js +104 -0
  84. package/dist-lib/hooks/useRecalcJob.js +1 -1
  85. package/dist-lib/hooks/useRuleEngine.d.ts +1 -0
  86. package/dist-lib/hooks/useRuleEngine.d.ts.map +1 -1
  87. package/dist-lib/hooks/useRuleEngine.js +1 -0
  88. package/dist-lib/hooks/useShippingNoteDiagnose.d.ts +20 -0
  89. package/dist-lib/hooks/useShippingNoteDiagnose.d.ts.map +1 -0
  90. package/dist-lib/hooks/useShippingNoteDiagnose.js +52 -0
  91. package/dist-lib/hooks/useShippingNoteStatus.d.ts +29 -0
  92. package/dist-lib/hooks/useShippingNoteStatus.d.ts.map +1 -0
  93. package/dist-lib/hooks/useShippingNoteStatus.js +107 -0
  94. package/dist-lib/hooks/useTaakGezondheid.d.ts +16 -0
  95. package/dist-lib/hooks/useTaakGezondheid.d.ts.map +1 -0
  96. package/dist-lib/hooks/useTaakGezondheid.js +43 -0
  97. package/dist-lib/hooks/useWerktijden.d.ts +33 -0
  98. package/dist-lib/hooks/useWerktijden.d.ts.map +1 -0
  99. package/dist-lib/hooks/useWerktijden.js +88 -0
  100. package/dist-lib/hooks/useWerkwijzeStatus.d.ts +12 -1
  101. package/dist-lib/hooks/useWerkwijzeStatus.d.ts.map +1 -1
  102. package/dist-lib/hooks/useWerkwijzeStatus.js +61 -5
  103. package/dist-lib/index.d.ts +23 -0
  104. package/dist-lib/index.d.ts.map +1 -1
  105. package/dist-lib/index.js +23 -0
  106. package/dist-lib/integrations/supabase/auth-middleware.d.ts +4993 -459
  107. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  108. package/dist-lib/integrations/supabase/client.server.d.ts +4993 -459
  109. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  110. package/dist-lib/integrations/supabase/client.server.js +1 -1
  111. package/dist-lib/integrations/supabase/moduleClient.d.ts +4993 -459
  112. package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
  113. package/dist-lib/integrations/supabase/previewAuthStorage.d.ts +1 -1
  114. package/dist-lib/integrations/supabase/previewAuthStorage.d.ts.map +1 -1
  115. package/dist-lib/integrations/supabase/previewAuthStorage.js +8 -1
  116. package/dist-lib/integrations/supabase/types.d.ts +5022 -432
  117. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  118. package/dist-lib/lib/attachAuthToken.js +1 -1
  119. package/dist-lib/lib/bufferDecision.test.d.ts +2 -0
  120. package/dist-lib/lib/bufferDecision.test.d.ts.map +1 -0
  121. package/dist-lib/lib/bufferDecision.test.js +104 -0
  122. package/dist-lib/lib/cartCoverage.functions.d.ts +30820 -0
  123. package/dist-lib/lib/cartCoverage.functions.d.ts.map +1 -0
  124. package/dist-lib/lib/cartCoverage.functions.js +20 -0
  125. package/dist-lib/lib/cartPlanRequests.server.d.ts +1 -1
  126. package/dist-lib/lib/cartPlanRequests.server.d.ts.map +1 -1
  127. package/dist-lib/lib/cartPlanRequests.server.js +49 -8
  128. package/dist-lib/lib/floridayDocuments.functions.d.ts +13623 -21
  129. package/dist-lib/lib/floridayDocuments.functions.d.ts.map +1 -1
  130. package/dist-lib/lib/floridayDocuments.functions.js +5 -5
  131. package/dist-lib/lib/floridayDocuments.server.d.ts +14 -0
  132. package/dist-lib/lib/floridayDocuments.server.d.ts.map +1 -1
  133. package/dist-lib/lib/floridayDocuments.server.js +58 -0
  134. package/dist-lib/lib/floridayGuard.server.d.ts +1 -1
  135. package/dist-lib/lib/floridayGuard.server.d.ts.map +1 -1
  136. package/dist-lib/lib/floridayGuard.server.js +6 -3
  137. package/dist-lib/lib/floridayPush.functions.d.ts +4993 -459
  138. package/dist-lib/lib/floridayPush.functions.d.ts.map +1 -1
  139. package/dist-lib/lib/floridayPush.functions.js +3 -3
  140. package/dist-lib/lib/flowGraph.d.ts +43 -0
  141. package/dist-lib/lib/flowGraph.d.ts.map +1 -0
  142. package/dist-lib/lib/flowGraph.js +153 -0
  143. package/dist-lib/lib/flowJourney.d.ts +40 -0
  144. package/dist-lib/lib/flowJourney.d.ts.map +1 -0
  145. package/dist-lib/lib/flowJourney.js +156 -0
  146. package/dist-lib/lib/flowNodes.d.ts +26 -0
  147. package/dist-lib/lib/flowNodes.d.ts.map +1 -0
  148. package/dist-lib/lib/flowNodes.js +64 -0
  149. package/dist-lib/lib/flowRoute.d.ts +117 -0
  150. package/dist-lib/lib/flowRoute.d.ts.map +1 -0
  151. package/dist-lib/lib/flowRoute.js +583 -0
  152. package/dist-lib/lib/flowTree.d.ts +149 -0
  153. package/dist-lib/lib/flowTree.d.ts.map +1 -0
  154. package/dist-lib/lib/flowTree.js +908 -0
  155. package/dist-lib/lib/foutTekst.d.ts +4 -0
  156. package/dist-lib/lib/foutTekst.d.ts.map +1 -0
  157. package/dist-lib/lib/foutTekst.js +43 -0
  158. package/dist-lib/lib/handlers/index.d.ts +1 -0
  159. package/dist-lib/lib/handlers/index.d.ts.map +1 -1
  160. package/dist-lib/lib/handlers/index.js +1 -0
  161. package/dist-lib/lib/handlers/logistics-shipping-note-now.server.d.ts +3 -0
  162. package/dist-lib/lib/handlers/logistics-shipping-note-now.server.d.ts.map +1 -0
  163. package/dist-lib/lib/handlers/logistics-shipping-note-now.server.js +100 -0
  164. package/dist-lib/lib/handlers/logistics-tick.server.d.ts +2 -0
  165. package/dist-lib/lib/handlers/logistics-tick.server.d.ts.map +1 -1
  166. package/dist-lib/lib/handlers/logistics-tick.server.js +153 -2
  167. package/dist-lib/lib/handlers/logistics-tick.test.d.ts +2 -0
  168. package/dist-lib/lib/handlers/logistics-tick.test.d.ts.map +1 -0
  169. package/dist-lib/lib/handlers/logistics-tick.test.js +63 -0
  170. package/dist-lib/lib/loadCarrierPlanner.d.ts +2 -0
  171. package/dist-lib/lib/loadCarrierPlanner.d.ts.map +1 -1
  172. package/dist-lib/lib/loadCarrierPlanner.js +18 -0
  173. package/dist-lib/lib/loadCarrierPlanning.functions.d.ts +22705 -35
  174. package/dist-lib/lib/loadCarrierPlanning.functions.d.ts.map +1 -1
  175. package/dist-lib/lib/loadCarrierPlanning.functions.js +7 -7
  176. package/dist-lib/lib/loadCarrierPlanning.server.d.ts +33 -12
  177. package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
  178. package/dist-lib/lib/loadCarrierPlanning.server.js +534 -228
  179. package/dist-lib/lib/logisticsPlanner.d.ts.map +1 -1
  180. package/dist-lib/lib/logisticsPlanner.js +14 -2
  181. package/dist-lib/lib/logisticsRecalcJob.functions.d.ts +9082 -14
  182. package/dist-lib/lib/logisticsRecalcJob.functions.d.ts.map +1 -1
  183. package/dist-lib/lib/logisticsRecalcJob.functions.js +4 -4
  184. package/dist-lib/lib/logisticsRecalcJob.server.d.ts.map +1 -1
  185. package/dist-lib/lib/logisticsRecalcJob.server.js +17 -2
  186. package/dist-lib/lib/logisticsRecalculate.functions.d.ts +4993 -459
  187. package/dist-lib/lib/logisticsRecalculate.functions.d.ts.map +1 -1
  188. package/dist-lib/lib/logisticsRecalculate.functions.js +2 -2
  189. package/dist-lib/lib/modulePrompts.d.ts.map +1 -1
  190. package/dist-lib/lib/modulePrompts.js +893 -0
  191. package/dist-lib/lib/nodeTrace.d.ts +65 -0
  192. package/dist-lib/lib/nodeTrace.d.ts.map +1 -0
  193. package/dist-lib/lib/nodeTrace.js +182 -0
  194. package/dist-lib/lib/pickQueueCleanup.server.d.ts +14 -0
  195. package/dist-lib/lib/pickQueueCleanup.server.d.ts.map +1 -0
  196. package/dist-lib/lib/pickQueueCleanup.server.js +80 -0
  197. package/dist-lib/lib/planQueue.server.d.ts.map +1 -1
  198. package/dist-lib/lib/planQueue.server.js +164 -3
  199. package/dist-lib/lib/plannerDiff.d.ts +37 -0
  200. package/dist-lib/lib/plannerDiff.d.ts.map +1 -0
  201. package/dist-lib/lib/plannerDiff.functions.d.ts +30821 -0
  202. package/dist-lib/lib/plannerDiff.functions.d.ts.map +1 -0
  203. package/dist-lib/lib/plannerDiff.functions.js +21 -0
  204. package/dist-lib/lib/plannerDiff.js +74 -0
  205. package/dist-lib/lib/plannerDiff.server.d.ts +5 -0
  206. package/dist-lib/lib/plannerDiff.server.d.ts.map +1 -0
  207. package/dist-lib/lib/plannerDiff.server.js +60 -0
  208. package/dist-lib/lib/plannerDiff.test.d.ts +2 -0
  209. package/dist-lib/lib/plannerDiff.test.d.ts.map +1 -0
  210. package/dist-lib/lib/plannerDiff.test.js +41 -0
  211. package/dist-lib/lib/resolveBuffer.test.d.ts +2 -0
  212. package/dist-lib/lib/resolveBuffer.test.d.ts.map +1 -0
  213. package/dist-lib/lib/resolveBuffer.test.js +38 -0
  214. package/dist-lib/lib/ruleEngineImpact.d.ts.map +1 -1
  215. package/dist-lib/lib/ruleEngineImpact.js +11 -4
  216. package/dist-lib/lib/ruleEngineSchema.d.ts.map +1 -1
  217. package/dist-lib/lib/ruleEngineSchema.js +102 -6
  218. package/dist-lib/lib/ruleEngineWizard.d.ts.map +1 -1
  219. package/dist-lib/lib/ruleEngineWizard.js +3 -1
  220. package/dist-lib/lib/shippingNoteQueue.server.d.ts +18 -0
  221. package/dist-lib/lib/shippingNoteQueue.server.d.ts.map +1 -0
  222. package/dist-lib/lib/shippingNoteQueue.server.js +304 -0
  223. package/dist-lib/lib/stopReden.d.ts +43 -0
  224. package/dist-lib/lib/stopReden.d.ts.map +1 -0
  225. package/dist-lib/lib/stopReden.js +197 -0
  226. package/dist-lib/lib/taskCounts.d.ts +2 -0
  227. package/dist-lib/lib/taskCounts.d.ts.map +1 -0
  228. package/dist-lib/lib/taskCounts.js +15 -0
  229. package/dist-lib/lib/taskCounts.test.d.ts +2 -0
  230. package/dist-lib/lib/taskCounts.test.d.ts.map +1 -0
  231. package/dist-lib/lib/taskCounts.test.js +12 -0
  232. package/dist-lib/lib/trace.server.d.ts +75 -0
  233. package/dist-lib/lib/trace.server.d.ts.map +1 -0
  234. package/dist-lib/lib/trace.server.js +78 -0
  235. package/dist-lib/lib/vakUitleg.d.ts +19 -0
  236. package/dist-lib/lib/vakUitleg.d.ts.map +1 -0
  237. package/dist-lib/lib/vakUitleg.js +133 -0
  238. package/package.json +158 -131
  239. package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts +0 -2
  240. package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts.map +0 -1
  241. package/dist-lib/components/rule-engine/FloridayConnectionBanner.js +0 -41
  242. package/dist-lib/integrations/supabase/client.d.ts +0 -20293
  243. package/dist-lib/integrations/supabase/client.d.ts.map +0 -1
  244. package/dist-lib/integrations/supabase/client.js +0 -13
@@ -0,0 +1,65 @@
1
+ import type { TraceEventRow } from "../hooks/useLogisticsTrace";
2
+ export type NodeStatus = "geslaagd" | "wachtend" | "waarschuwing" | "overgeslagen" | "mislukt";
3
+ export interface NodeTraceGroep {
4
+ nodeId: string;
5
+ events: TraceEventRow[];
6
+ aantal: number;
7
+ eerste: string | null;
8
+ laatste: string | null;
9
+ duurMs: number | null;
10
+ status: NodeStatus;
11
+ pogingen: number;
12
+ reden: string | null;
13
+ errorClass: string | null;
14
+ volgendeStap: string | null;
15
+ /** Auditpunt 5: dit vakje staat niet in het logboek, maar is uit de kaart afgeleid. */
16
+ afgeleid?: boolean;
17
+ }
18
+ /** Terugval voor oude gebeurtenissen zonder vastgelegd vakje. */
19
+ export declare function gokNode(e: TraceEventRow): string | null;
20
+ /** Groepeert de gebeurtenissen van één order per vakje van de flowkaart. */
21
+ export declare function groepeerPerNode(events: TraceEventRow[] | null | undefined): Map<string, NodeTraceGroep>;
22
+ /** De vakjes op volgorde van de eerste gebeurtenis: de reis van de order. */
23
+ export declare function reisVolgorde(groepen: Map<string, NodeTraceGroep>): NodeTraceGroep[];
24
+ export interface VakSamenvatting {
25
+ beslissing: string | null;
26
+ reden: string | null;
27
+ regel: string | null;
28
+ berekening: {
29
+ setting?: string;
30
+ formula?: string;
31
+ result?: string;
32
+ conclusion?: string;
33
+ values?: Record<string, unknown>;
34
+ } | null;
35
+ volgendeStap: string | null;
36
+ /** Auditpunt 5: dit vakje staat niet in het logboek, maar is uit de kaart afgeleid. */
37
+ afgeleid?: boolean;
38
+ fout: string | null;
39
+ errorClass: string | null;
40
+ pogingen: number;
41
+ volgendePoging: string | null;
42
+ aantalBeslissingen: number;
43
+ aantalAutomatisch: number;
44
+ }
45
+ /** Is dit een automatische database-regel (trigger) in plaats van een engine-beslissing? */
46
+ export declare function isAutomatisch(e: TraceEventRow): boolean;
47
+ /** Korte samenvatting van wat de Engine in dit vakje besliste. */
48
+ export declare function samenvatVak(groep: NodeTraceGroep): VakSamenvatting;
49
+ export interface Gebundeld {
50
+ key: string;
51
+ /** Eén losse engine-gebeurtenis, of null bij een bundel. */
52
+ event: TraceEventRow | null;
53
+ /** Bij een bundel: alle gelijksoortige automatische regels. */
54
+ events: TraceEventRow[];
55
+ aantal: number;
56
+ laatste: string | null;
57
+ label: string;
58
+ }
59
+ /**
60
+ * Engine-gebeurtenissen blijven los; automatische database-regels worden
61
+ * per soort (stap + tabel + actie) samengevoegd tot één regel met telling.
62
+ * Nieuwste eerst.
63
+ */
64
+ export declare function bundelGebeurtenissen(events: TraceEventRow[] | null | undefined): Gebundeld[];
65
+ //# sourceMappingURL=nodeTrace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeTrace.d.ts","sourceRoot":"","sources":["../../src/lib/nodeTrace.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAGhE,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,cAAc,GAAG,cAAc,GAAG,SAAS,CAAC;AAE/F,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,uFAAuF;IACvF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAGD,iEAAiE;AACjE,wBAAgB,OAAO,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAwBvD;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CA+CvG;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,cAAc,EAAE,CAMnF;AAMD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE;QACV,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,GAAG,IAAI,CAAC;IACT,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,uFAAuF;IACvF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,CAAC,EAAE,aAAa,GAAG,OAAO,CAEvD;AAQD,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CA8BlE;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,4DAA4D;IAC5D,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IAC5B,+DAA+D;IAC/D,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,EAAE,CAuC5F"}
@@ -0,0 +1,182 @@
1
+ // ============================================================================
2
+ // src/lib/nodeTrace.ts — gebeurtenissen van een order per vakje van de flowkaart
3
+ // ============================================================================
4
+ // De Engine legt bij nieuwe gebeurtenissen het vakje (node_id) vast. Oudere
5
+ // gebeurtenissen missen dat; die plaatsen we met een terugval op stap/fase.
6
+ // Alleen lezen: hier wordt niets bepaald, alleen gegroepeerd.
7
+ // ============================================================================
8
+ import { FLOW_NODE } from "./flowNodes";
9
+ /** Terugval voor oude gebeurtenissen zonder vastgelegd vakje. */
10
+ export function gokNode(e) {
11
+ if (e.nodeId)
12
+ return e.nodeId;
13
+ // Automatische registraties: eerst op tabel en actie, dan pas op tekst.
14
+ const tabel = (e.dbTable ?? "").toLowerCase();
15
+ if (tabel) {
16
+ if (tabel === "logistics_plan_queue") {
17
+ return (e.dbAction ?? "").toUpperCase() === "INSERT" ? FLOW_NODE.ontvangst : FLOW_NODE.indeling;
18
+ }
19
+ if (/control|scan/.test(tabel))
20
+ return FLOW_NODE.controle;
21
+ if (/print|slip|shipping_note|document/.test(tabel))
22
+ return FLOW_NODE.stations;
23
+ if (/pick|cart/.test(tabel))
24
+ return FLOW_NODE.picken;
25
+ if (/order/.test(tabel))
26
+ return FLOW_NODE.ontvangst;
27
+ }
28
+ const t = `${e.phase ?? ""} ${e.step ?? ""}`.toLowerCase();
29
+ if (/binnengekomen|ontvangst|nieuwe order|combineren|buffer/.test(t))
30
+ return FLOW_NODE.ontvangst;
31
+ if (/indeling|plan|kar|belading/.test(t))
32
+ return FLOW_NODE.indeling;
33
+ if (/pick(?!station)/.test(t))
34
+ return FLOW_NODE.picken;
35
+ if (/vrijgave|aanmeld|drukte|vertraging|wacht/.test(t))
36
+ return FLOW_NODE.vrijgave;
37
+ if (/pakbon|print|verzendbrief|document|station|floriday/.test(t))
38
+ return FLOW_NODE.stations;
39
+ if (/controle|scan|afmeld/.test(t))
40
+ return FLOW_NODE.controle;
41
+ if (/afgehandeld|gereed|klaar/.test(t))
42
+ return FLOW_NODE.eind;
43
+ return null;
44
+ }
45
+ /** Groepeert de gebeurtenissen van één order per vakje van de flowkaart. */
46
+ export function groepeerPerNode(events) {
47
+ const veilig = Array.isArray(events) ? events : [];
48
+ const map = new Map();
49
+ for (const e of veilig) {
50
+ const id = gokNode(e);
51
+ if (!id)
52
+ continue;
53
+ const bestaand = map.get(id);
54
+ if (bestaand) {
55
+ bestaand.events.push(e);
56
+ }
57
+ else {
58
+ map.set(id, {
59
+ nodeId: id,
60
+ events: [e],
61
+ aantal: 0,
62
+ eerste: null,
63
+ laatste: null,
64
+ duurMs: null,
65
+ status: "geslaagd",
66
+ pogingen: 0,
67
+ reden: null,
68
+ errorClass: null,
69
+ volgendeStap: null,
70
+ });
71
+ }
72
+ }
73
+ for (const groep of map.values()) {
74
+ groep.events.sort((a, b) => (a.createdAt < b.createdAt ? -1 : a.createdAt > b.createdAt ? 1 : 0));
75
+ const laatsteEvent = groep.events[groep.events.length - 1];
76
+ groep.aantal = groep.events.length;
77
+ groep.eerste = groep.events[0]?.createdAt ?? null;
78
+ groep.laatste = laatsteEvent?.createdAt ?? null;
79
+ const totaal = groep.events.reduce((som, e) => som + (e.durationMs ?? 0), 0);
80
+ groep.duurMs = totaal > 0 ? totaal : null;
81
+ groep.pogingen = groep.events.reduce((m, e) => Math.max(m, e.attempts ?? 0), 0);
82
+ groep.volgendeStap = laatsteEvent?.nextStep ?? null;
83
+ // De laatste registratie bepaalt de stand: een vakje dat eerst wachtte en
84
+ // daarna is afgerond, is afgerond. Een latere "wachtend" blijft wachtend.
85
+ const bepalend = laatsteEvent ?? groep.events[0];
86
+ groep.status = bepalend?.status ?? "geslaagd";
87
+ groep.reden = bepalend?.reason ?? bepalend?.error ?? bepalend?.decision ?? null;
88
+ groep.errorClass = bepalend?.errorClass ?? null;
89
+ }
90
+ return map;
91
+ }
92
+ /** De vakjes op volgorde van de eerste gebeurtenis: de reis van de order. */
93
+ export function reisVolgorde(groepen) {
94
+ return [...groepen.values()].sort((a, b) => {
95
+ const ta = a.eerste ?? "";
96
+ const tb = b.eerste ?? "";
97
+ return ta < tb ? -1 : ta > tb ? 1 : 0;
98
+ });
99
+ }
100
+ /** Is dit een automatische database-regel (trigger) in plaats van een engine-beslissing? */
101
+ export function isAutomatisch(e) {
102
+ return (e.phase ?? "").toLowerCase() === "database";
103
+ }
104
+ function calcVan(e) {
105
+ const c = e.calc;
106
+ if (!c || typeof c !== "object")
107
+ return null;
108
+ return c;
109
+ }
110
+ /** Korte samenvatting van wat de Engine in dit vakje besliste. */
111
+ export function samenvatVak(groep) {
112
+ const events = Array.isArray(groep.events) ? groep.events : [];
113
+ const engine = events.filter((e) => !isAutomatisch(e));
114
+ const relevant = engine.length > 0 ? engine : events;
115
+ const laatsteMet = (kies) => {
116
+ for (let i = relevant.length - 1; i >= 0; i--) {
117
+ const ev = relevant[i];
118
+ if (!ev)
119
+ continue;
120
+ const v = kies(ev);
121
+ if (v !== null && v !== undefined && v !== "")
122
+ return v;
123
+ }
124
+ return null;
125
+ };
126
+ const foutEvent = [...relevant].reverse().find((e) => e.status === "mislukt") ?? null;
127
+ return {
128
+ beslissing: laatsteMet((e) => e.decision),
129
+ reden: laatsteMet((e) => e.reason) ?? groep.reden,
130
+ regel: laatsteMet((e) => e.rule),
131
+ berekening: laatsteMet((e) => calcVan(e)),
132
+ volgendeStap: laatsteMet((e) => e.nextStep) ?? groep.volgendeStap,
133
+ fout: foutEvent?.error ?? null,
134
+ errorClass: foutEvent?.errorClass ?? groep.errorClass,
135
+ pogingen: groep.pogingen,
136
+ volgendePoging: laatsteMet((e) => e.nextAttemptAt),
137
+ aantalBeslissingen: engine.length,
138
+ aantalAutomatisch: events.length - engine.length,
139
+ };
140
+ }
141
+ /**
142
+ * Engine-gebeurtenissen blijven los; automatische database-regels worden
143
+ * per soort (stap + tabel + actie) samengevoegd tot één regel met telling.
144
+ * Nieuwste eerst.
145
+ */
146
+ export function bundelGebeurtenissen(events) {
147
+ const veilig = Array.isArray(events) ? [...events] : [];
148
+ veilig.sort((a, b) => (a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0));
149
+ const uit = [];
150
+ const index = new Map();
151
+ for (const e of veilig) {
152
+ if (!isAutomatisch(e)) {
153
+ uit.push({
154
+ key: e.id,
155
+ event: e,
156
+ events: [e],
157
+ aantal: 1,
158
+ laatste: e.createdAt,
159
+ label: e.step,
160
+ });
161
+ continue;
162
+ }
163
+ const key = `auto:${e.step}|${e.dbTable ?? ""}|${e.dbAction ?? ""}`;
164
+ const bestaand = index.get(key);
165
+ if (bestaand) {
166
+ bestaand.events.push(e);
167
+ bestaand.aantal += 1;
168
+ continue;
169
+ }
170
+ const bundel = {
171
+ key,
172
+ event: null,
173
+ events: [e],
174
+ aantal: 1,
175
+ laatste: e.createdAt,
176
+ label: e.step,
177
+ };
178
+ index.set(key, bundel);
179
+ uit.push(bundel);
180
+ }
181
+ return uit;
182
+ }
@@ -0,0 +1,14 @@
1
+ import type { SupabaseClient } from "@supabase/supabase-js";
2
+ export interface PickQueueCleanupResult {
3
+ mode: string | null;
4
+ cartRows: number;
5
+ retiredOrderRows: number;
6
+ errors: string[];
7
+ }
8
+ /**
9
+ * Verbergt oude orderregels uit het actieve pickscherm zodra dezelfde
10
+ * pickeenheid concrete karregels heeft. De regel blijft als printhistorie
11
+ * bestaan; karrencontrole gebruikt de canonieke kargegevens en blijft intact.
12
+ */
13
+ export declare function retireSupersededOrderRows(sb: SupabaseClient): Promise<PickQueueCleanupResult>;
14
+ //# sourceMappingURL=pickQueueCleanup.server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pickQueueCleanup.server.d.ts","sourceRoot":"","sources":["../../src/lib/pickQueueCleanup.server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,cAAc,GACjB,OAAO,CAAC,sBAAsB,CAAC,CAiFjC"}
@@ -0,0 +1,80 @@
1
+ const REPLACED_REASON = "Vervangen door actuele karregels.";
2
+ /**
3
+ * Verbergt oude orderregels uit het actieve pickscherm zodra dezelfde
4
+ * pickeenheid concrete karregels heeft. De regel blijft als printhistorie
5
+ * bestaan; karrencontrole gebruikt de canonieke kargegevens en blijft intact.
6
+ */
7
+ export async function retireSupersededOrderRows(sb) {
8
+ const result = {
9
+ mode: null,
10
+ cartRows: 0,
11
+ retiredOrderRows: 0,
12
+ errors: [],
13
+ };
14
+ const { data: modeData, error: modeError } = await sb.rpc("logistics_pick_mode");
15
+ if (modeError) {
16
+ result.errors.push(modeError.message);
17
+ return result;
18
+ }
19
+ const modeValue = Array.isArray(modeData) ? modeData[0] : modeData;
20
+ const modeObject = modeValue && typeof modeValue === "object"
21
+ ? modeValue
22
+ : null;
23
+ result.mode = String(modeObject?.["pickMode"] ?? modeObject?.["mode"] ?? "");
24
+ if (result.mode !== "cart")
25
+ return result;
26
+ const { data: cartRows, error: cartRowsError } = await sb
27
+ .from("pick_queue")
28
+ .select("order_number")
29
+ .is("cancelled_at", null)
30
+ .not("payload->>cartRowFor", "is", null);
31
+ if (cartRowsError) {
32
+ result.errors.push(cartRowsError.message);
33
+ return result;
34
+ }
35
+ const safeCartRows = Array.isArray(cartRows) ? cartRows : [];
36
+ const orderNumbers = [...new Set(safeCartRows
37
+ .map((row) => row.order_number)
38
+ .filter((value) => typeof value === "string" && value.length > 0))];
39
+ result.cartRows = safeCartRows.length;
40
+ if (orderNumbers.length === 0)
41
+ return result;
42
+ const replacedAt = new Date().toISOString();
43
+ const { data: oldRows, error: oldRowsError } = await sb
44
+ .from("pick_queue")
45
+ .select("id, payload")
46
+ .in("order_number", orderNumbers)
47
+ .is("cancelled_at", null)
48
+ .is("payload->>cartRowFor", null);
49
+ if (oldRowsError) {
50
+ result.errors.push(oldRowsError.message);
51
+ return result;
52
+ }
53
+ const safeOldRows = Array.isArray(oldRows) ? oldRows : [];
54
+ for (const row of safeOldRows) {
55
+ const payload = row.payload && typeof row.payload === "object" && !Array.isArray(row.payload)
56
+ ? row.payload
57
+ : {};
58
+ const { error } = await sb
59
+ .from("pick_queue")
60
+ .update({
61
+ cancelled_at: replacedAt,
62
+ payload: {
63
+ ...payload,
64
+ cartPlanReady: true,
65
+ cartPlanReason: null,
66
+ supersededByCartRows: true,
67
+ supersededReason: REPLACED_REASON,
68
+ supersededAt: replacedAt,
69
+ },
70
+ updated_at: replacedAt,
71
+ })
72
+ .eq("id", row.id)
73
+ .is("cancelled_at", null);
74
+ if (error)
75
+ result.errors.push(error.message);
76
+ else
77
+ result.retiredOrderRows += 1;
78
+ }
79
+ return result;
80
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"planQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/planQueue.server.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,2FAA2F;IAC3F,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAwBD,wFAAwF;AACxF,wBAAsB,YAAY,CAChC,EAAE,EAAE,cAAc,EAClB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAC3D,OAAO,CAAC,eAAe,CAAC,CAsG1B;AA0CD,4EAA4E;AAE5E,wBAAsB,cAAc,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE"}
1
+ {"version":3,"file":"planQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/planQueue.server.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAQ5D,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,2FAA2F;IAC3F,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAwBD,wFAAwF;AACxF,wBAAsB,YAAY,CAChC,EAAE,EAAE,cAAc,EAClB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAC3D,OAAO,CAAC,eAAe,CAAC,CAwQ1B;AAmDD,4EAA4E;AAE5E,wBAAsB,cAAc,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE"}
@@ -9,6 +9,9 @@
9
9
  // ============================================================================
10
10
  import { replanBufferInternal, replanOrderInternal } from "./loadCarrierPlanning.server.js";
11
11
  import { attachIndelingToTasks } from "./loadCarrierTaskSync.server.js";
12
+ import { trace, newTraceId, classifyError } from "./trace.server.js";
13
+ import { FLOW_NODE } from "./flowNodes.js";
14
+ import { completePlannerDiffRuns, skipPlannerDiffRuns } from "./plannerDiff.server.js";
12
15
  const EMPTY = {
13
16
  claimed: 0,
14
17
  planned: 0,
@@ -37,10 +40,55 @@ export async function runPlanQueue(sb, options = {}) {
37
40
  // Voorkomt dat dezelfde buffer binnen één ronde meerdere keren wordt gepland.
38
41
  const plannedBuffers = new Set();
39
42
  const touchedDates = new Set();
43
+ // Herkenbare ordernummers voor het logboek; nooit verzinnen bij ontbreken.
44
+ const orderNumbers = new Map();
45
+ {
46
+ const ids = Array.from(new Set(rows.map((r) => r.order_id).filter(Boolean)));
47
+ if (ids.length > 0) {
48
+ const { data: orderRows } = await sb
49
+ .from("orders")
50
+ .select("id, order_number, order_source")
51
+ .in("id", ids);
52
+ for (const o of Array.isArray(orderRows) ? orderRows : []) {
53
+ orderNumbers.set(String(o?.id), {
54
+ number: o?.order_number ? String(o.order_number) : null,
55
+ source: o?.order_source === "floriday" ? "floriday" : o?.order_source ? "eigen" : null,
56
+ });
57
+ }
58
+ }
59
+ }
40
60
  for (const row of rows) {
61
+ // Het trace-id is de wachtrijrij zelf: zo horen alle stappen van deze
62
+ // herberekening aantoonbaar bij één "versie" in het orderlogboek.
63
+ const traceId = row.id || newTraceId();
64
+ const gevonden = orderNumbers.get(row.order_id);
65
+ const basis = {
66
+ traceId,
67
+ orderRef: gevonden?.number ?? row.order_id,
68
+ orderSource: gevonden?.source ?? null,
69
+ phase: "karindeling",
70
+ actor: "logistiek-engine:planwachtrij",
71
+ attempts: Number(row.attempts ?? 0),
72
+ nodeId: FLOW_NODE.indeling,
73
+ };
41
74
  if (Date.now() > deadlineAt) {
42
75
  // Teruggeven aan de wachtrij; de volgende ronde pakt hem weer op.
43
- await sb.rpc("logistics_plan_finish", { p_id: row.id, p_error: "deadline" });
76
+ // Doorschuiven is geen mislukking: geen extra poging, geen foutmelding.
77
+ await sb.rpc("logistics_plan_defer", { p_id: row.id });
78
+ await trace(sb, {
79
+ ...basis,
80
+ step: "Indelen uitgesteld",
81
+ status: "wachtend",
82
+ decision: "Order blijft wachten",
83
+ reason: "De ronde was te lang bezig; deze order gaat mee met de volgende ronde.",
84
+ errorClass: "regel",
85
+ nextStep: "Volgende planronde (elke minuut)",
86
+ calc: {
87
+ setting: "Maximale duur van één planronde",
88
+ values: { rondeEindigdeOm: new Date(deadlineAt).toISOString(), beoordeeldOm: new Date().toISOString() },
89
+ conclusion: "De order is niet overgeslagen, maar doorgeschoven naar de eerstvolgende ronde.",
90
+ },
91
+ });
44
92
  continue;
45
93
  }
46
94
  try {
@@ -54,23 +102,74 @@ export async function runPlanQueue(sb, options = {}) {
54
102
  }
55
103
  const bufferId = group.find((g) => g.buffer_id)?.buffer_id ?? null;
56
104
  let blocked = false;
105
+ await trace(sb, {
106
+ ...basis,
107
+ nodeId: FLOW_NODE.ontvangst,
108
+ step: "Order opgepakt voor indeling",
109
+ status: "geslaagd",
110
+ decision: bufferId ? "Order hoort bij een buffer" : "Order wordt los ingedeeld",
111
+ reason: bufferId
112
+ ? "De order zit in een buffer; alle orders van die buffer worden samen ingedeeld."
113
+ : "Er is geen open buffer voor deze order, dus hij wordt zelfstandig ingedeeld.",
114
+ reads: { geraakteOrders: group.length, bufferId, planDatums: [...touchedDates] },
115
+ nextStep: "Karrenindeling berekenen",
116
+ });
117
+ const startMs = Date.now();
57
118
  if (bufferId) {
58
119
  if (!plannedBuffers.has(bufferId)) {
59
120
  plannedBuffers.add(bufferId);
60
121
  const plan = await replanBufferInternal(sb, bufferId);
61
122
  if (plan.skipped === "locked") {
62
123
  result.skippedLocked++;
124
+ await trace(sb, {
125
+ ...basis,
126
+ step: "Indeling overgeslagen",
127
+ status: "overgeslagen",
128
+ decision: "Indeling blijft zoals hij is",
129
+ reason: "De karren van deze buffer zijn al geprint, gescand of gecontroleerd.",
130
+ errorClass: "regel",
131
+ durationMs: Date.now() - startMs,
132
+ calc: {
133
+ setting: "Wanneer mag een karrenindeling niet meer veranderen",
134
+ conclusion: "Bevroren karren worden nooit opnieuw ingedeeld, ook niet bij een herberekening.",
135
+ },
136
+ nextStep: "Pickstations en documenten",
137
+ });
63
138
  }
64
139
  else if (plan.skipped === "blocked") {
65
140
  blocked = true;
66
141
  result.blocked++;
67
142
  if (result.errors.length < 5 && plan.blockedReason)
68
143
  result.errors.push(plan.blockedReason);
144
+ await trace(sb, {
145
+ ...basis,
146
+ step: "Indeling geblokkeerd",
147
+ status: "mislukt",
148
+ decision: "Order gaat niet verder",
149
+ errorClass: classifyError(null, plan.blockedReason ?? null),
150
+ durationMs: Date.now() - startMs,
151
+ nextStep: "Gegevens aanvullen en opnieuw indelen",
152
+ ...(plan.blockedReason ? { reason: plan.blockedReason, error: plan.blockedReason } : {}),
153
+ });
69
154
  }
70
155
  else {
71
156
  result.planned++;
72
157
  result.cartsCreated += Number(plan.cartsCreated ?? 0);
73
158
  await attachIndelingToTasks(sb, plan);
159
+ await trace(sb, {
160
+ ...basis,
161
+ step: "Buffer ingedeeld op karren",
162
+ status: "geslaagd",
163
+ decision: "Karrenindeling gemaakt",
164
+ durationMs: Date.now() - startMs,
165
+ output: { bufferId, karrenAangemaakt: Number(plan.cartsCreated ?? 0) },
166
+ calc: {
167
+ setting: "Indelingsmethode van de actieve werkwijze",
168
+ values: { buffer: bufferId, karren: Number(plan.cartsCreated ?? 0) },
169
+ result: `${Number(plan.cartsCreated ?? 0)} kar(ren) voor deze buffer`,
170
+ },
171
+ nextStep: "Vrijgave en aanmeldmoment",
172
+ });
74
173
  }
75
174
  }
76
175
  }
@@ -78,23 +177,63 @@ export async function runPlanQueue(sb, options = {}) {
78
177
  const plan = await replanOrderInternal(sb, row.order_id);
79
178
  if (plan?.skipped === "locked") {
80
179
  result.skippedLocked++;
180
+ await trace(sb, {
181
+ ...basis,
182
+ step: "Indeling overgeslagen",
183
+ status: "overgeslagen",
184
+ decision: "Indeling blijft zoals hij is",
185
+ reason: "De karren van deze order zijn al geprint, gescand of gecontroleerd.",
186
+ errorClass: "regel",
187
+ durationMs: Date.now() - startMs,
188
+ nextStep: "Pickstations en documenten",
189
+ });
81
190
  }
82
191
  else if (plan?.skipped === "blocked") {
83
192
  blocked = true;
84
193
  result.blocked++;
85
194
  if (result.errors.length < 5 && plan.blockedReason)
86
195
  result.errors.push(plan.blockedReason);
196
+ await trace(sb, {
197
+ ...basis,
198
+ step: "Indeling geblokkeerd",
199
+ status: "mislukt",
200
+ decision: "Order gaat niet verder",
201
+ errorClass: classifyError(null, plan.blockedReason ?? null),
202
+ durationMs: Date.now() - startMs,
203
+ nextStep: "Gegevens aanvullen en opnieuw indelen",
204
+ ...(plan.blockedReason ? { reason: plan.blockedReason, error: plan.blockedReason } : {}),
205
+ });
87
206
  }
88
207
  else if (plan) {
89
208
  result.planned++;
90
209
  result.cartsCreated += Number(plan.cartsCreated ?? 0);
91
210
  await attachIndelingToTasks(sb, plan);
211
+ await trace(sb, {
212
+ ...basis,
213
+ step: "Order ingedeeld op karren",
214
+ status: "geslaagd",
215
+ decision: "Karrenindeling gemaakt",
216
+ durationMs: Date.now() - startMs,
217
+ output: { karrenAangemaakt: Number(plan.cartsCreated ?? 0) },
218
+ calc: {
219
+ setting: "Indelingsmethode van de actieve werkwijze",
220
+ values: { karren: Number(plan.cartsCreated ?? 0) },
221
+ result: `${Number(plan.cartsCreated ?? 0)} kar(ren) voor deze order`,
222
+ },
223
+ nextStep: "Vrijgave en aanmeldmoment",
224
+ });
92
225
  }
93
226
  }
94
227
  // De blokkade zet de wachtrijregel zelf al op 'geblokkeerd'; die mag niet
95
- // alsnog als afgerond worden weggeschreven.
96
- if (blocked)
228
+ // alsnog als afgerond worden weggeschreven. Een wachtende vergelijking
229
+ // krijgt geen "na"-stand en wordt daarom als overgeslagen afgesloten.
230
+ if (blocked) {
231
+ const skipWarnings = await skipPlannerDiffRuns(sb, [row.order_id, ...group.map((g) => g.order_id)].filter(Boolean), "Indeling geblokkeerd; geen nieuwe karindeling om mee te vergelijken.").catch((e) => [String(e)]);
232
+ for (const w of skipWarnings)
233
+ if (result.errors.length < 10)
234
+ result.errors.push(w);
97
235
  continue;
236
+ }
98
237
  // Orders zonder taken krijgen een order.received-event, zodat de
99
238
  // taakdispatcher er taken van maakt.
100
239
  for (const g of group.length > 0 ? group : [{ order_id: row.order_id }]) {
@@ -102,6 +241,11 @@ export async function runPlanQueue(sb, options = {}) {
102
241
  continue;
103
242
  await sb.rpc("logistics_plan_ensure_event", { p_order_id: g.order_id });
104
243
  }
244
+ // Dry-run: vergelijking oud/nieuw wegschrijven (alleen als er een momentopname wacht).
245
+ const diffWarnings = await completePlannerDiffRuns(sb, [row.order_id, ...group.map((g) => g.order_id)].filter(Boolean)).catch((e) => [String(e)]);
246
+ for (const w of diffWarnings)
247
+ if (result.errors.length < 10)
248
+ result.errors.push(w);
105
249
  await sb.rpc("logistics_plan_finish", { p_id: row.id, p_error: null });
106
250
  }
107
251
  catch (err) {
@@ -110,6 +254,15 @@ export async function runPlanQueue(sb, options = {}) {
110
254
  if (result.errors.length < 5)
111
255
  result.errors.push(message);
112
256
  await sb.rpc("logistics_plan_finish", { p_id: row.id, p_error: message });
257
+ await trace(sb, {
258
+ ...basis,
259
+ step: "Indelen mislukt",
260
+ status: "mislukt",
261
+ decision: "Order gaat niet verder",
262
+ errorClass: classifyError(null, message),
263
+ error: message,
264
+ nextStep: "Automatisch opnieuw geprobeerd in de volgende planronde",
265
+ });
113
266
  }
114
267
  }
115
268
  if (result.planned > 0) {
@@ -135,6 +288,9 @@ async function runDayLevelSteps(sb, dates, result) {
135
288
  { fn: "logistics_prune_buffer_member_queue", args: {} },
136
289
  { fn: "logistics_apply_document_layouts", args: {} },
137
290
  { fn: "logistics_capacity_day_check", args: { p_from: from, p_to: to >= from ? to : from } },
291
+ // Legt per order vast waar hij in de flow staat (vrijgave, pickstation,
292
+ // picken, controle, afgehandeld). Alleen meekijkend.
293
+ { fn: "logistics_trace_progress", args: { p_limit: 200 } },
138
294
  ];
139
295
  for (const call of calls) {
140
296
  const { error } = await sb.rpc(call.fn, call.args);
@@ -153,6 +309,11 @@ async function syncPickQueue(sb, result) {
153
309
  if (pruneError && result.errors.length < 10) {
154
310
  result.errors.push(`logistics_prune_buffer_member_queue: ${pruneError.message}`);
155
311
  }
312
+ // Ook zonder nieuwe planning schuift de reis van bestaande orders door.
313
+ const { error: traceError } = await sb.rpc("logistics_trace_progress", { p_limit: 200 });
314
+ if (traceError && result.errors.length < 10) {
315
+ result.errors.push(`logistics_trace_progress: ${traceError.message}`);
316
+ }
156
317
  }
157
318
  /** Ruimt afgeronde wachtrijrijen op volgens de ingestelde bewaartermijn. */
158
319
  export async function prunePlanQueue(sb) {
@@ -0,0 +1,37 @@
1
+ export interface SnapshotItem {
2
+ orderItemId: string | null;
3
+ crates: number | string | null;
4
+ }
5
+ export interface SnapshotCart {
6
+ cartId?: string;
7
+ cartNumber: number | null;
8
+ bufferId?: string | null;
9
+ orderId?: string | null;
10
+ items: SnapshotItem[];
11
+ }
12
+ export interface PlannerDiffResult {
13
+ identical: boolean;
14
+ cartsBefore: number;
15
+ cartsAfter: number;
16
+ differences: Array<{
17
+ cartNumber: number | null;
18
+ before: string | null;
19
+ after: string | null;
20
+ }>;
21
+ }
22
+ export declare function compareSnapshots(before: unknown, after: unknown): PlannerDiffResult;
23
+ /** Overzicht: laatste vergelijking per buffer. 'wachtend' en 'overgeslagen' tellen niet als vergeleken of afwijkend. */
24
+ export declare function summarizeDiffRuns<T extends {
25
+ buffer_id: string | null;
26
+ order_ref: string | null;
27
+ status: string;
28
+ identical: boolean | null;
29
+ }>(rows: T[]): {
30
+ totaal: number;
31
+ identiek: number;
32
+ afwijkend: number;
33
+ mislukt: number;
34
+ overgeslagen: number;
35
+ afwijkingen: T[];
36
+ };
37
+ //# sourceMappingURL=plannerDiff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plannerDiff.d.ts","sourceRoot":"","sources":["../../src/lib/plannerDiff.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAChC;AACD,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AACD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAChG;AAiBD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAyBnF;AAED,wHAAwH;AACxH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,EAC3I,IAAI,EAAE,CAAC,EAAE;;;;;;;EAsBV"}