@flowselections/logistiek-engine 1.0.53 → 1.0.90

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 (168) hide show
  1. package/README.md +24 -24
  2. package/dist-lib/components/AfrondWachtrijCard.d.ts +2 -0
  3. package/dist-lib/components/AfrondWachtrijCard.d.ts.map +1 -0
  4. package/dist-lib/components/AfrondWachtrijCard.js +27 -0
  5. package/dist-lib/components/BeladingsafwijkingenCard.d.ts +2 -0
  6. package/dist-lib/components/BeladingsafwijkingenCard.d.ts.map +1 -0
  7. package/dist-lib/components/BeladingsafwijkingenCard.js +44 -0
  8. package/dist-lib/components/FlowCanvas.d.ts +6 -0
  9. package/dist-lib/components/FlowCanvas.d.ts.map +1 -1
  10. package/dist-lib/components/FlowCanvas.js +79 -18
  11. package/dist-lib/components/FlowOrders.d.ts.map +1 -1
  12. package/dist-lib/components/FlowOrders.js +59 -13
  13. package/dist-lib/components/FlowPage.d.ts.map +1 -1
  14. package/dist-lib/components/FlowPage.js +175 -6
  15. package/dist-lib/components/GeblokkeerdeOrdersCard.d.ts.map +1 -1
  16. package/dist-lib/components/GeblokkeerdeOrdersCard.js +21 -2
  17. package/dist-lib/components/KardekkingCard.d.ts +2 -0
  18. package/dist-lib/components/KardekkingCard.d.ts.map +1 -0
  19. package/dist-lib/components/KardekkingCard.js +29 -0
  20. package/dist-lib/components/LogistiekEnginePage.d.ts.map +1 -1
  21. package/dist-lib/components/LogistiekEnginePage.js +7 -1
  22. package/dist-lib/components/LogistiekEngineQueuePage.d.ts.map +1 -1
  23. package/dist-lib/components/LogistiekEngineQueuePage.js +4 -2
  24. package/dist-lib/components/NodeTracePanel.d.ts +4 -1
  25. package/dist-lib/components/NodeTracePanel.d.ts.map +1 -1
  26. package/dist-lib/components/NodeTracePanel.js +8 -2
  27. package/dist-lib/components/OrderStopBanner.d.ts +9 -2
  28. package/dist-lib/components/OrderStopBanner.d.ts.map +1 -1
  29. package/dist-lib/components/OrderStopBanner.js +27 -13
  30. package/dist-lib/components/OrderTraceDetails.d.ts.map +1 -1
  31. package/dist-lib/components/OrderTraceDetails.js +2 -1
  32. package/dist-lib/components/PlanWachtrijPage.d.ts +2 -0
  33. package/dist-lib/components/PlanWachtrijPage.d.ts.map +1 -0
  34. package/dist-lib/components/PlanWachtrijPage.js +99 -0
  35. package/dist-lib/components/PlannerDiffCard.d.ts +2 -0
  36. package/dist-lib/components/PlannerDiffCard.d.ts.map +1 -0
  37. package/dist-lib/components/PlannerDiffCard.js +25 -0
  38. package/dist-lib/components/RegiePage.d.ts.map +1 -1
  39. package/dist-lib/components/RegiePage.js +21 -13
  40. package/dist-lib/components/TaakGezondheidCard.d.ts +2 -0
  41. package/dist-lib/components/TaakGezondheidCard.d.ts.map +1 -0
  42. package/dist-lib/components/TaakGezondheidCard.js +31 -0
  43. package/dist-lib/hooks/useAfrondWachtrij.d.ts +28 -0
  44. package/dist-lib/hooks/useAfrondWachtrij.d.ts.map +1 -0
  45. package/dist-lib/hooks/useAfrondWachtrij.js +88 -0
  46. package/dist-lib/hooks/useBeladingsafwijkingen.d.ts +39 -0
  47. package/dist-lib/hooks/useBeladingsafwijkingen.d.ts.map +1 -0
  48. package/dist-lib/hooks/useBeladingsafwijkingen.js +119 -0
  49. package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts +7 -0
  50. package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts.map +1 -1
  51. package/dist-lib/hooks/useGeblokkeerdeOrders.js +28 -2
  52. package/dist-lib/hooks/useLogisticsTrace.js +1 -1
  53. package/dist-lib/hooks/useOrderTrace.js +1 -1
  54. package/dist-lib/hooks/useOrderVersies.d.ts.map +1 -1
  55. package/dist-lib/hooks/useOrderVersies.js +17 -3
  56. package/dist-lib/hooks/usePlanWachtrij.d.ts +33 -0
  57. package/dist-lib/hooks/usePlanWachtrij.d.ts.map +1 -0
  58. package/dist-lib/hooks/usePlanWachtrij.js +104 -0
  59. package/dist-lib/hooks/useRecalcJob.js +1 -1
  60. package/dist-lib/hooks/useShippingNoteDiagnose.d.ts +20 -0
  61. package/dist-lib/hooks/useShippingNoteDiagnose.d.ts.map +1 -0
  62. package/dist-lib/hooks/useShippingNoteDiagnose.js +52 -0
  63. package/dist-lib/hooks/useTaakGezondheid.d.ts +16 -0
  64. package/dist-lib/hooks/useTaakGezondheid.d.ts.map +1 -0
  65. package/dist-lib/hooks/useTaakGezondheid.js +43 -0
  66. package/dist-lib/hooks/useWerktijden.js +1 -1
  67. package/dist-lib/hooks/useWerkwijzeStatus.js +1 -1
  68. package/dist-lib/index.d.ts +10 -0
  69. package/dist-lib/index.d.ts.map +1 -1
  70. package/dist-lib/index.js +10 -0
  71. package/dist-lib/integrations/supabase/auth-middleware.d.ts +3147 -159
  72. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  73. package/dist-lib/integrations/supabase/client.server.d.ts +3147 -159
  74. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  75. package/dist-lib/integrations/supabase/client.server.js +1 -1
  76. package/dist-lib/integrations/supabase/moduleClient.d.ts +3147 -159
  77. package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
  78. package/dist-lib/integrations/supabase/previewAuthStorage.d.ts +1 -1
  79. package/dist-lib/integrations/supabase/previewAuthStorage.d.ts.map +1 -1
  80. package/dist-lib/integrations/supabase/previewAuthStorage.js +8 -1
  81. package/dist-lib/integrations/supabase/types.d.ts +3183 -161
  82. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  83. package/dist-lib/lib/attachAuthToken.js +1 -1
  84. package/dist-lib/lib/bufferDecision.test.d.ts +2 -0
  85. package/dist-lib/lib/bufferDecision.test.d.ts.map +1 -0
  86. package/dist-lib/lib/bufferDecision.test.js +104 -0
  87. package/dist-lib/lib/cartCoverage.functions.d.ts +30820 -0
  88. package/dist-lib/lib/cartCoverage.functions.d.ts.map +1 -0
  89. package/dist-lib/lib/cartCoverage.functions.js +20 -0
  90. package/dist-lib/lib/floridayDocuments.functions.d.ts +8979 -15
  91. package/dist-lib/lib/floridayDocuments.functions.d.ts.map +1 -1
  92. package/dist-lib/lib/floridayDocuments.functions.js +5 -5
  93. package/dist-lib/lib/floridayPush.functions.d.ts +3147 -159
  94. package/dist-lib/lib/floridayPush.functions.d.ts.map +1 -1
  95. package/dist-lib/lib/floridayPush.functions.js +3 -3
  96. package/dist-lib/lib/flowJourney.d.ts +40 -0
  97. package/dist-lib/lib/flowJourney.d.ts.map +1 -0
  98. package/dist-lib/lib/flowJourney.js +156 -0
  99. package/dist-lib/lib/flowNodes.d.ts +3 -0
  100. package/dist-lib/lib/flowNodes.d.ts.map +1 -1
  101. package/dist-lib/lib/flowNodes.js +6 -0
  102. package/dist-lib/lib/flowRoute.d.ts +11 -1
  103. package/dist-lib/lib/flowRoute.d.ts.map +1 -1
  104. package/dist-lib/lib/flowRoute.js +343 -40
  105. package/dist-lib/lib/flowTree.d.ts +86 -1
  106. package/dist-lib/lib/flowTree.d.ts.map +1 -1
  107. package/dist-lib/lib/flowTree.js +391 -2
  108. package/dist-lib/lib/foutTekst.d.ts +4 -0
  109. package/dist-lib/lib/foutTekst.d.ts.map +1 -0
  110. package/dist-lib/lib/foutTekst.js +43 -0
  111. package/dist-lib/lib/handlers/logistics-tick.server.d.ts +2 -0
  112. package/dist-lib/lib/handlers/logistics-tick.server.d.ts.map +1 -1
  113. package/dist-lib/lib/handlers/logistics-tick.server.js +56 -0
  114. package/dist-lib/lib/handlers/logistics-tick.test.d.ts +2 -0
  115. package/dist-lib/lib/handlers/logistics-tick.test.d.ts.map +1 -0
  116. package/dist-lib/lib/handlers/logistics-tick.test.js +63 -0
  117. package/dist-lib/lib/loadCarrierPlanning.functions.d.ts +14965 -25
  118. package/dist-lib/lib/loadCarrierPlanning.functions.d.ts.map +1 -1
  119. package/dist-lib/lib/loadCarrierPlanning.functions.js +7 -7
  120. package/dist-lib/lib/loadCarrierPlanning.server.d.ts +24 -12
  121. package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
  122. package/dist-lib/lib/loadCarrierPlanning.server.js +490 -211
  123. package/dist-lib/lib/logisticsRecalcJob.functions.d.ts +5986 -10
  124. package/dist-lib/lib/logisticsRecalcJob.functions.d.ts.map +1 -1
  125. package/dist-lib/lib/logisticsRecalcJob.functions.js +4 -4
  126. package/dist-lib/lib/logisticsRecalcJob.server.d.ts.map +1 -1
  127. package/dist-lib/lib/logisticsRecalcJob.server.js +17 -2
  128. package/dist-lib/lib/logisticsRecalculate.functions.d.ts +3147 -159
  129. package/dist-lib/lib/logisticsRecalculate.functions.d.ts.map +1 -1
  130. package/dist-lib/lib/logisticsRecalculate.functions.js +2 -2
  131. package/dist-lib/lib/modulePrompts.d.ts.map +1 -1
  132. package/dist-lib/lib/modulePrompts.js +3436 -3325
  133. package/dist-lib/lib/nodeTrace.d.ts +4 -0
  134. package/dist-lib/lib/nodeTrace.d.ts.map +1 -1
  135. package/dist-lib/lib/nodeTrace.js +6 -15
  136. package/dist-lib/lib/planQueue.server.d.ts.map +1 -1
  137. package/dist-lib/lib/planQueue.server.js +24 -3
  138. package/dist-lib/lib/plannerDiff.d.ts +37 -0
  139. package/dist-lib/lib/plannerDiff.d.ts.map +1 -0
  140. package/dist-lib/lib/plannerDiff.functions.d.ts +30821 -0
  141. package/dist-lib/lib/plannerDiff.functions.d.ts.map +1 -0
  142. package/dist-lib/lib/plannerDiff.functions.js +21 -0
  143. package/dist-lib/lib/plannerDiff.js +74 -0
  144. package/dist-lib/lib/plannerDiff.server.d.ts +5 -0
  145. package/dist-lib/lib/plannerDiff.server.d.ts.map +1 -0
  146. package/dist-lib/lib/plannerDiff.server.js +60 -0
  147. package/dist-lib/lib/plannerDiff.test.d.ts +2 -0
  148. package/dist-lib/lib/plannerDiff.test.d.ts.map +1 -0
  149. package/dist-lib/lib/plannerDiff.test.js +41 -0
  150. package/dist-lib/lib/resolveBuffer.test.d.ts +2 -0
  151. package/dist-lib/lib/resolveBuffer.test.d.ts.map +1 -0
  152. package/dist-lib/lib/resolveBuffer.test.js +38 -0
  153. package/dist-lib/lib/ruleEngineSchema.d.ts.map +1 -1
  154. package/dist-lib/lib/ruleEngineSchema.js +52 -0
  155. package/dist-lib/lib/stopReden.d.ts +43 -0
  156. package/dist-lib/lib/stopReden.d.ts.map +1 -0
  157. package/dist-lib/lib/stopReden.js +197 -0
  158. package/dist-lib/lib/taskCounts.d.ts +2 -0
  159. package/dist-lib/lib/taskCounts.d.ts.map +1 -0
  160. package/dist-lib/lib/taskCounts.js +15 -0
  161. package/dist-lib/lib/taskCounts.test.d.ts +2 -0
  162. package/dist-lib/lib/taskCounts.test.d.ts.map +1 -0
  163. package/dist-lib/lib/taskCounts.test.js +12 -0
  164. package/dist-lib/lib/trace.server.d.ts.map +1 -1
  165. package/dist-lib/lib/trace.server.js +3 -0
  166. package/dist-lib/lib/vakUitleg.d.ts.map +1 -1
  167. package/dist-lib/lib/vakUitleg.js +2 -1
  168. package/package.json +12 -9
@@ -14,6 +14,7 @@
14
14
  import { WIZARD_STEPS } from "./ruleEngineWizard";
15
15
  import { FLOW_NODE, bronNodeVoor } from "./flowNodes";
16
16
  import { vakUitleg } from "./vakUitleg";
17
+ import { stopReden, samenkomstStop } from "./stopReden";
17
18
  const STEP_IDS = WIZARD_STEPS.map((s) => s.id);
18
19
  const STAP = {
19
20
  combineren: STEP_IDS[0] ?? "orders_combineren",
@@ -30,6 +31,7 @@ export const REASON_LABEL = {
30
31
  werktijden_ontbreken: "Werktijden van de klant ontbreken",
31
32
  fust_onbekend: "Fusttype onbekend",
32
33
  geen_regels: "Order heeft geen regels",
34
+ dubbele_regels: "Order heeft dubbele bestelregels; er is niets ingedeeld",
33
35
  };
34
36
  export function redenTekst(code, error) {
35
37
  const label = code ? REASON_LABEL[code] ?? code.replace(/_/g, " ") : null;
@@ -152,6 +154,15 @@ export function stapLabel(stepId) {
152
154
  return WIZARD_STEPS.find((s) => s.id === stepId)?.label ?? stepId;
153
155
  }
154
156
  // ── Route over de kaart leggen ──────────────────────────────────────────────
157
+ /**
158
+ * Twee extra vakjes tussen "Pickstations en documenten" en "Controle en
159
+ * afmelden": die horen niet bij de instellingenstappen, maar hebben wel een
160
+ * vaste plek in de volgorde.
161
+ */
162
+ const EXTRA_STAP_INDEX = {
163
+ "stap:pakbon_geprint": STEP_IDS.indexOf(STAP.stations) + 0.3,
164
+ "stap:kar_afgemeld": STEP_IDS.indexOf(STAP.stations) + 0.6,
165
+ };
155
166
  /** Stapvolgorde-index van een knoop; -1 = vóór de eerste stap; 99 = einde. */
156
167
  function stapIndex(node, byId) {
157
168
  if (!node)
@@ -160,6 +171,9 @@ function stapIndex(node, byId) {
160
171
  return 99;
161
172
  if (node.id.startsWith("__"))
162
173
  return -1;
174
+ const extra = EXTRA_STAP_INDEX[node.id];
175
+ if (extra !== undefined)
176
+ return extra;
163
177
  const m = /^(?:samen:)?stap:(.+)$/.exec(node.id);
164
178
  if (m)
165
179
  return STEP_IDS.indexOf(m[1]);
@@ -172,6 +186,117 @@ function stapIndex(node, byId) {
172
186
  }
173
187
  return -1;
174
188
  }
189
+ /** Zet op het laatste vakje van de route altijd een reden waarom het daar stopt. */
190
+ function markeerEindpunt(markers, routeNodes, routeEdges, byId, groepen, stand) {
191
+ const heeftVervolg = new Set(routeEdges.filter((e) => routeNodes.has(e.to)).map((e) => e.from));
192
+ const kandidaten = [...routeNodes].filter((id) => id !== "__start" && !heeftVervolg.has(id));
193
+ const eindpunten = new Set(kandidaten);
194
+ if (kandidaten.length === 0)
195
+ return { eind: null, eindpunten };
196
+ let eind = null;
197
+ let besteIdx = -Infinity;
198
+ let besteTijd = "";
199
+ for (const id of kandidaten) {
200
+ const idx = stapIndex(byId.get(id), byId);
201
+ const tijd = groepen?.get(id)?.laatste ?? "";
202
+ if (idx > besteIdx || (idx === besteIdx && tijd > besteTijd)) {
203
+ eind = id;
204
+ besteIdx = idx;
205
+ besteTijd = tijd;
206
+ }
207
+ }
208
+ if (!eind)
209
+ return { eind: null, eindpunten };
210
+ const bestaand = markers.get(eind);
211
+ const stop = stopReden({
212
+ nodeId: eind,
213
+ groep: groepen?.get(eind) ?? null,
214
+ stand,
215
+ verouderd: bestaand?.verouderd === true,
216
+ });
217
+ markers.set(eind, {
218
+ kind: bestaand?.kind ?? (stop.soort === "mislukt" ? "stuck" : stop.soort === "klaar" ? "done" : "busy"),
219
+ text: bestaand?.text ?? stop.titel,
220
+ ...bestaand,
221
+ eindpunt: true,
222
+ // Een wachtpunt heeft al zijn eigen stopreden; die blijft staan.
223
+ stop: bestaand?.stop ?? stop,
224
+ });
225
+ return { eind, eindpunten };
226
+ }
227
+ /**
228
+ * Samenkomstpunten waar de route nog niet voorbij mag: de ingestelde
229
+ * voorwaarde ("alle lijnen" of een verplichte lijn) is nog niet gehaald.
230
+ * Loopt de maximale wachttijd af, dan gaat de route alsnog verder; zo kan een
231
+ * tak die nooit gebeurt de flow niet voor altijd vastzetten.
232
+ */
233
+ function bepaalWachtpunten(nodes, edges, routeNodes, routeEdges, echt, markers) {
234
+ const wachtpunten = new Set();
235
+ const nu = Date.now();
236
+ for (const node of nodes) {
237
+ const wacht = node.wacht;
238
+ if (node.kind !== "merge" || !wacht || !routeNodes.has(node.id))
239
+ continue;
240
+ const inkomend = edges.filter((e) => e.kind === "flow" && e.to === node.id && e.state !== "disabled");
241
+ const nodig = wacht.wanneer === "specifiek"
242
+ ? inkomend.filter((e) => e.id === wacht.verplichteLijn)
243
+ : inkomend;
244
+ if (nodig.length === 0)
245
+ continue;
246
+ const naam = (id) => nodes.find((n) => n.id === id)?.label || "een eerdere tak";
247
+ const klaar = [];
248
+ const open = [];
249
+ const mislukt = [];
250
+ let eerste = "";
251
+ for (const e of nodig) {
252
+ const groep = echt.get(e.from);
253
+ const gelopen = routeEdges.has(e.id) || !!groep;
254
+ if (groep?.status === "mislukt")
255
+ mislukt.push(naam(e.from));
256
+ if (gelopen) {
257
+ klaar.push(naam(e.from));
258
+ const t = groep?.laatste ?? "";
259
+ if (t && (!eerste || t < eerste))
260
+ eerste = t;
261
+ }
262
+ else {
263
+ open.push(naam(e.from));
264
+ }
265
+ }
266
+ if (open.length === 0 && mislukt.length === 0)
267
+ continue;
268
+ // Vangnet: na de maximale wachttijd loopt de route alsnog door.
269
+ const start = eerste ? new Date(eerste).getTime() : NaN;
270
+ const verlopen = Number.isFinite(start) && nu - start > wacht.maxWachtMinuten * 60000;
271
+ if (verlopen && mislukt.length === 0) {
272
+ const bestaand = markers.get(node.id);
273
+ markers.set(node.id, {
274
+ kind: bestaand?.kind ?? "busy",
275
+ text: "Doorgegaan na maximale wachttijd",
276
+ beslissing: "Doorgegaan na maximale wachttijd",
277
+ waarom: `Er is langer dan ${wacht.maxWachtMinuten} minuten gewacht op ${open.join(", ")}; de flow is daarna verdergegaan.`,
278
+ feiten: [`Voorwaarde: ${wacht.label}`, `Nog niet klaar: ${open.join(", ")}`],
279
+ ...bestaand,
280
+ });
281
+ continue;
282
+ }
283
+ wachtpunten.add(node.id);
284
+ markers.set(node.id, {
285
+ kind: mislukt.length > 0 ? "stuck" : "busy",
286
+ text: mislukt.length > 0 ? "Verplichte tak is mislukt" : "Wacht op andere takken",
287
+ beslissing: mislukt.length > 0 ? "Verplichte tak is mislukt" : "Wacht op andere takken",
288
+ eindpunt: true,
289
+ stop: samenkomstStop({
290
+ wachtOp: open,
291
+ mislukt,
292
+ voorwaarde: wacht.label,
293
+ maxWachtMinuten: wacht.maxWachtMinuten,
294
+ }),
295
+ feiten: klaar.length > 0 ? [`Al klaar: ${klaar.join(", ")}`] : [],
296
+ });
297
+ }
298
+ return wachtpunten;
299
+ }
175
300
  /**
176
301
  * Maakt een kopie van de kaart waarin alleen de gelopen route "active" is.
177
302
  * Knopen/pijlen die de order (nog) niet heeft bereikt worden "possible".
@@ -180,12 +305,12 @@ function stapIndex(node, byId) {
180
305
  * komt dan uit wat de Engine heeft vastgelegd. De heuristiek hieronder blijft
181
306
  * de terugval voor oudere gebeurtenissen zonder vakje.
182
307
  */
183
- export function applyRoute(tree, route, groepen) {
308
+ export function applyRoute(tree, route, groepen, stand) {
184
309
  const markers = new Map();
185
310
  const nodes = Array.isArray(tree?.nodes) ? tree.nodes : [];
186
311
  const edges = Array.isArray(tree?.edges) ? tree.edges : [];
187
312
  if (!route)
188
- return { tree: { nodes, edges }, markers };
313
+ return { tree: { nodes, edges }, markers, wachtpunten: new Set() };
189
314
  const echt = groepen && groepen.size > 0 ? groepen : null;
190
315
  const byId = new Map(nodes.map((n) => [n.id, n]));
191
316
  const maxIdx = route.reached.reduce((m, id) => Math.max(m, STEP_IDS.indexOf(id)), -1);
@@ -212,25 +337,218 @@ export function applyRoute(tree, route, groepen) {
212
337
  return bronNode === FLOW_NODE.bronFloriday;
213
338
  return true;
214
339
  };
215
- /** Ligt dit vakje op de reis? Echte gebeurtenissen gaan vóór de heuristiek. */
340
+ const demote = (s) => (s === "active" ? "possible" : s);
341
+ // ── Route uit echte gebeurtenissen: altijd een aaneengesloten pad ──────────
342
+ if (echt) {
343
+ // Alleen lijnen die volgens de huidige werkwijze bestaan en bij deze bron horen.
344
+ const bruikbaar = (e) => e.kind === "flow" &&
345
+ e.state === "active" &&
346
+ bronOk(e.from) &&
347
+ bronOk(e.to) &&
348
+ byId.get(e.from)?.state === "active" &&
349
+ byId.get(e.to)?.state === "active";
350
+ const uit = new Map();
351
+ for (const e of edges) {
352
+ if (!bruikbaar(e))
353
+ continue;
354
+ const lijst = uit.get(e.from);
355
+ if (lijst)
356
+ lijst.push({ to: e.to, edgeId: e.id });
357
+ else
358
+ uit.set(e.from, [{ to: e.to, edgeId: e.id }]);
359
+ }
360
+ // Kortste pad vanaf het startvakje naar elk bereikbaar vakje.
361
+ const vorige = new Map();
362
+ const gezien = new Set(["__start"]);
363
+ const rij = ["__start"];
364
+ for (let i = 0; i < rij.length; i++) {
365
+ const huidig = rij[i];
366
+ for (const stap of uit.get(huidig) ?? []) {
367
+ if (gezien.has(stap.to))
368
+ continue;
369
+ gezien.add(stap.to);
370
+ vorige.set(stap.to, { from: huidig, edgeId: stap.edgeId });
371
+ rij.push(stap.to);
372
+ }
373
+ }
374
+ // Bewijs: vakjes waarvoor daadwerkelijk iets is vastgelegd, plus het bronvakje.
375
+ const bewijs = new Set([...echt.keys()]);
376
+ if (bronNode)
377
+ bewijs.add(bronNode);
378
+ const routeNodes = new Set(["__start"]);
379
+ const routeEdges = new Set();
380
+ const onbereikbaar = new Set();
381
+ for (const id of bewijs) {
382
+ if (!byId.has(id) || !gezien.has(id)) {
383
+ onbereikbaar.add(id);
384
+ continue;
385
+ }
386
+ let stap = id;
387
+ while (stap && stap !== "__start") {
388
+ routeNodes.add(stap);
389
+ const p = vorige.get(stap);
390
+ if (!p)
391
+ break;
392
+ routeEdges.add(p.edgeId);
393
+ stap = p.from;
394
+ }
395
+ }
396
+ // Samenkomstpunten met een eigen voorwaarde kunnen de route hier stoppen.
397
+ const wachtpunten = bepaalWachtpunten(nodes, edges, routeNodes, routeEdges, echt, markers);
398
+ // Een stap die nog loopt (wachtend/waarschuwing) houdt alleen de volgende
399
+ // echte stap tegen. De keuze-, uitkomst- en samenkomstvakjes van diezelfde
400
+ // stap staan al vast en blijven dus wel blauw.
401
+ const lopend = new Set();
402
+ for (const g of echt.values()) {
403
+ if (g.status !== "wachtend" && g.status !== "waarschuwing")
404
+ continue;
405
+ if (!routeNodes.has(g.nodeId))
406
+ continue;
407
+ lopend.add(g.nodeId);
408
+ }
409
+ const isStapVak = (id) => id.startsWith("stap:") || byId.get(id)?.kind === "step";
410
+ /** Een volgende stap mag alsnog blauw worden als die zelf geslaagd is. */
411
+ const isGeslaagdeStap = (id) => echt.get(id)?.status === "geslaagd";
412
+ // Voorbij een samenkomst-wachtpunt loopt de blauwe route niet meer; het
413
+ // grijze vervolg daarachter blijft gewoon staan (er wordt niets weggesnoeid).
414
+ const kandidaatEdges = edges.filter((e) => routeEdges.has(e.id) && !wachtpunten.has(e.from));
415
+ const verdereStap = new Map();
416
+ for (const e of kandidaatEdges) {
417
+ const lijst = verdereStap.get(e.from);
418
+ if (lijst)
419
+ lijst.push({ to: e.to, id: e.id });
420
+ else
421
+ verdereStap.set(e.from, [{ to: e.to, id: e.id }]);
422
+ }
423
+ const routeTot = new Set(["__start"]);
424
+ const routeEdgeIds = new Set();
425
+ /** Per knoop: welke lopende stappen liggen er vóór dit punt op de route? */
426
+ const naLopend = new Map();
427
+ /** Lopende stappen waar de route toch langs mocht (latere stap is geslaagd). */
428
+ const doorgelaten = new Set();
429
+ const rijRoute = ["__start"];
430
+ for (let i = 0; i < rijRoute.length; i++) {
431
+ const huidig = rijRoute[i];
432
+ const oorsprongen = new Set(naLopend.get(huidig) ?? []);
433
+ if (lopend.has(huidig))
434
+ oorsprongen.add(huidig);
435
+ const na = oorsprongen.size > 0;
436
+ for (const { to: volgend, id: edgeId } of verdereStap.get(huidig) ?? []) {
437
+ // Na een lopende stap stopt de blauwe route bij het eerstvolgende
438
+ // stapvakje — tenzij van die stap zelf iets geslaagds is vastgelegd.
439
+ if (na && isStapVak(volgend)) {
440
+ if (!isGeslaagdeStap(volgend))
441
+ continue;
442
+ for (const o of oorsprongen)
443
+ doorgelaten.add(o);
444
+ routeEdgeIds.add(edgeId);
445
+ if (!routeTot.has(volgend)) {
446
+ routeTot.add(volgend);
447
+ rijRoute.push(volgend);
448
+ }
449
+ continue;
450
+ }
451
+ routeEdgeIds.add(edgeId);
452
+ let veranderd = false;
453
+ if (na) {
454
+ const set = naLopend.get(volgend) ?? new Set();
455
+ for (const o of oorsprongen) {
456
+ if (!set.has(o)) {
457
+ set.add(o);
458
+ veranderd = true;
459
+ }
460
+ }
461
+ naLopend.set(volgend, set);
462
+ }
463
+ if (routeTot.has(volgend)) {
464
+ if (veranderd)
465
+ rijRoute.push(volgend);
466
+ continue;
467
+ }
468
+ routeTot.add(volgend);
469
+ rijRoute.push(volgend);
470
+ }
471
+ }
472
+ const routeEdgeLijst = kandidaatEdges.filter((e) => routeEdgeIds.has(e.id));
473
+ // Alleen lopende stappen waar de route écht stopt gelden als wachtpunt.
474
+ for (const id of lopend)
475
+ if (!doorgelaten.has(id))
476
+ wachtpunten.add(id);
477
+ const newNodes = nodes.map((n) => routeTot.has(n.id) && n.state === "active"
478
+ ? { ...n, route: true }
479
+ : { ...n, state: demote(n.state), route: false });
480
+ const newEdges = edges.map((e) => routeEdgeIds.has(e.id) ? { ...e, route: true } : { ...e, state: demote(e.state), route: false });
481
+ /** Waar hoort bewijs heen dat niet meer op de kaart bereikbaar is? */
482
+ const vervangend = (id) => {
483
+ const n = byId.get(id);
484
+ const stapId = n?.stepId ? `stap:${n.stepId}` : null;
485
+ if (stapId && routeTot.has(stapId))
486
+ return stapId;
487
+ for (const a of [...(n?.ancestors ?? [])].reverse()) {
488
+ if (routeTot.has(a))
489
+ return a;
490
+ }
491
+ return null;
492
+ };
493
+ for (const g of echt.values()) {
494
+ const kind = g.status === "mislukt" ? "stuck" : g.status === "wachtend" || g.status === "waarschuwing" ? "busy" : "done";
495
+ const uitleg = vakUitleg(g);
496
+ const verouderd = onbereikbaar.has(g.nodeId);
497
+ const doel = verouderd ? vervangend(g.nodeId) : g.nodeId;
498
+ if (!doel)
499
+ continue;
500
+ const bestaand = markers.get(doel);
501
+ const marker = {
502
+ kind: bestaand && bestaand.kind === "stuck" ? bestaand.kind : kind,
503
+ text: uitleg.beslissing,
504
+ beslissing: uitleg.beslissing,
505
+ waarom: uitleg.waarom,
506
+ feiten: uitleg.feiten,
507
+ at: g.laatste,
508
+ durationMs: g.duurMs,
509
+ count: (bestaand?.count ?? 0) + g.aantal,
510
+ attempts: Math.max(bestaand?.attempts ?? 0, g.pogingen),
511
+ errorClass: g.errorClass ?? bestaand?.errorClass ?? null,
512
+ nextStep: g.volgendeStap,
513
+ verouderd: verouderd || bestaand?.verouderd === true,
514
+ };
515
+ markers.set(doel, marker);
516
+ }
517
+ // Een lopende stap waar de route stopt is een stoppunt met eigen uitleg.
518
+ for (const id of lopend) {
519
+ if (!routeTot.has(id) || doorgelaten.has(id))
520
+ continue;
521
+ const bestaand = markers.get(id);
522
+ markers.set(id, {
523
+ kind: bestaand?.kind ?? "busy",
524
+ text: bestaand?.text ?? "Deze stap loopt nog",
525
+ ...bestaand,
526
+ eindpunt: true,
527
+ stop: bestaand?.stop ??
528
+ stopReden({
529
+ nodeId: id,
530
+ groep: echt.get(id) ?? null,
531
+ stand: stand ?? null,
532
+ verouderd: bestaand?.verouderd === true,
533
+ }),
534
+ });
535
+ }
536
+ markeerEindpunt(markers, routeTot, routeEdgeLijst.map((e) => ({ from: e.from, to: e.to })), byId, echt, stand ?? null);
537
+ return {
538
+ // Een geselecteerde order kleurt alleen de gelopen route. De volledige
539
+ // flowchart blijft zichtbaar, ook na een fout of definitief stoppunt.
540
+ tree: { nodes: newNodes, edges: newEdges },
541
+ markers,
542
+ wachtpunten,
543
+ };
544
+ }
545
+ /** Ligt dit vakje op de reis volgens de heuristiek? */
216
546
  const opReis = (n) => {
217
547
  if (bronTak(n.id) || n.id === FLOW_NODE.samenvoegen) {
218
- return bronOk(n.id) && (echt ? true : bereikt(-1));
219
- }
220
- if (echt) {
221
- if (echt.has(n.id))
222
- return true;
223
- if (n.ancestors.some((a) => echt.has(a)))
224
- return true;
225
- if (n.stepId && echt.has(`stap:${n.stepId}`))
226
- return true;
227
- if (n.id === "__start" || n.id === "__bron" || n.id === "__bron_merge")
228
- return true;
229
- return false;
548
+ return bronOk(n.id) && bereikt(-1);
230
549
  }
231
550
  return bereikt(stapIndex(n, byId));
232
551
  };
233
- const demote = (s) => (s === "active" ? "possible" : s);
234
552
  const newNodes = nodes.map((n) => {
235
553
  const ok = n.state === "active" && opReis(n);
236
554
  return ok ? { ...n, route: true } : { ...n, state: demote(n.state), route: false };
@@ -243,38 +561,23 @@ export function applyRoute(tree, route, groepen) {
243
561
  const from = byId.get(e.from);
244
562
  const ok = nodeState.get(e.from) === "active" &&
245
563
  nodeState.get(e.to) === "active" &&
246
- (echt
247
- ? !!(from && to && opReis(from) && opReis(to))
248
- : bereikt(Math.max(stapIndex(from, byId), stapIndex(to, byId)))) &&
564
+ bereikt(Math.max(stapIndex(from, byId), stapIndex(to, byId))) &&
249
565
  bronOk(e.from) &&
250
566
  bronOk(e.to);
251
567
  return ok ? { ...e, route: true } : { ...e, state: "possible", route: false };
252
568
  });
253
- if (echt) {
254
- for (const g of echt.values()) {
255
- const kind = g.status === "mislukt" ? "stuck" : g.status === "wachtend" || g.status === "waarschuwing" ? "busy" : "done";
256
- const uitleg = vakUitleg(g);
257
- markers.set(g.nodeId, {
258
- kind,
259
- text: uitleg.beslissing,
260
- beslissing: uitleg.beslissing,
261
- waarom: uitleg.waarom,
262
- feiten: uitleg.feiten,
263
- at: g.laatste,
264
- durationMs: g.duurMs,
265
- count: g.aantal,
266
- attempts: g.pogingen,
267
- errorClass: g.errorClass,
268
- nextStep: g.volgendeStap,
269
- });
270
- }
271
- return { tree: { nodes: newNodes, edges: newEdges }, markers };
272
- }
273
569
  if (route.stuck)
274
570
  markers.set(`stap:${route.stuck.stepId}`, { kind: "stuck", text: route.stuck.reason });
275
571
  else if (route.busy)
276
572
  markers.set(`stap:${route.busy.stepId}`, { kind: "busy", text: route.busy.reason });
277
573
  if (route.finished)
278
574
  markers.set("__eind", { kind: "done", text: "Afgehandeld" });
279
- return { tree: { nodes: newNodes, edges: newEdges }, markers };
575
+ const heuristischeRoute = new Set(newNodes.filter((n) => n.route).map((n) => n.id));
576
+ markeerEindpunt(markers, heuristischeRoute, newEdges.filter((e) => e.route).map((e) => ({ from: e.from, to: e.to })), byId, null, stand ?? null);
577
+ return {
578
+ // Ook oudere orders houden de volledige grijze vervolgstructuur in beeld.
579
+ tree: { nodes: newNodes, edges: newEdges },
580
+ markers,
581
+ wachtpunten: new Set(),
582
+ };
280
583
  }
@@ -30,9 +30,21 @@ export interface TreeNode {
30
30
  fieldKeys?: string[];
31
31
  /** Ligt op de gelopen route van een gekozen order (blauwe lijn). */
32
32
  route?: boolean;
33
+ /** Alleen bij samenkomstpunten: wanneer mag de flow hier verder? */
34
+ wacht?: MergeWacht;
33
35
  w: number;
34
36
  h: number;
35
37
  }
38
+ /** Wanneer een samenkomstpunt de flow doorlaat. */
39
+ export interface MergeWacht {
40
+ wanneer: "een" | "alle" | "specifiek";
41
+ /** Alleen bij "specifiek": de id van de verplichte binnenkomende lijn. */
42
+ verplichteLijn: string | null;
43
+ /** Vangnet: na zoveel minuten gaat de flow alsnog verder. */
44
+ maxWachtMinuten: number;
45
+ /** Korte tekst voor op de kaart ("alle", "één", naam van de lijn). */
46
+ label: string;
47
+ }
36
48
  export interface TreeEdge {
37
49
  id: string;
38
50
  from: string;
@@ -60,5 +72,78 @@ export declare const NODE_SIZE: Record<TreeNodeKind, {
60
72
  export declare function fieldsFor(storeId?: string, keys?: string[]): RuleField[];
61
73
  export declare function valueText(field: RuleField, value: unknown): string;
62
74
  /** Bouwt de complete beslisboom van binnenkomst tot afgehandelde order. */
63
- export declare function buildFlowTree(settings: RuleEngineSettings): FlowTree;
75
+ export declare function buildFlowTree(settings: RuleEngineSettings, overrides?: MergeOverrides): FlowTree;
76
+ /** Handmatige keuzes per ruitje, bewaard bij de werkwijze. */
77
+ export interface MergeOverride {
78
+ /** Ruitje weggehaald: de lijnen worden rechtstreeks doorgetrokken. */
79
+ verwijderd?: boolean;
80
+ /** Per binnenkomende lijn: mag een order hier doorlopen? */
81
+ lijnen?: Record<string, "door" | "stop">;
82
+ /** Wanneer mag de flow hier verder? Standaard: zodra één lijn klaar is. */
83
+ wanneer?: "een" | "alle" | "specifiek";
84
+ /** Alleen bij "specifiek": id van de verplichte binnenkomende lijn. */
85
+ verplichteLijn?: string;
86
+ /** Vangnet tegen eeuwig wachten, in minuten. */
87
+ maxWachtMinuten?: number;
88
+ }
89
+ export type MergeOverrides = Record<string, MergeOverride>;
90
+ /** Standaard vangnet: na een half uur gaat de flow alsnog verder. */
91
+ export declare const MERGE_MAX_WACHT_MINUTEN = 30;
92
+ /** Eén binnenkomende lijn van een samenkomstpunt, zoals het paneel die toont. */
93
+ export interface MergeLijn {
94
+ id: string;
95
+ from: string;
96
+ naam: string;
97
+ /** Telt mee voor de voorwaarde (niet uitgeschakeld en niet op "stopt hier"). */
98
+ telt: boolean;
99
+ }
100
+ /**
101
+ * De voorwaarde van één samenkomstpunt, met de lijnen die meetellen.
102
+ * Lijnen die volgens de huidige werkwijze uitgeschakeld zijn of op "Stopt hier"
103
+ * staan tellen nooit mee: een tak die nooit gelopen kan worden mag de flow niet
104
+ * tegenhouden.
105
+ */
106
+ export declare function mergeVoorwaarde(tree: FlowTree, mergeId: string, override: MergeOverride | undefined): {
107
+ wanneer: "een" | "alle" | "specifiek";
108
+ lijnen: MergeLijn[];
109
+ verplichteLijn: string | null;
110
+ maxWachtMinuten: number;
111
+ /** De gekozen verplichte lijn bestaat niet meer: teruggevallen op "één". */
112
+ terugval: boolean;
113
+ /**
114
+ * De meetellende lijnen sluiten elkaar uit (verschillende herkomsten, of
115
+ * takken van dezelfde keuze): een order komt maar via één binnen, dus "alle
116
+ * flows" kan hier nooit gehaald worden en is niet in te stellen.
117
+ */
118
+ uitsluitend: boolean;
119
+ label: string;
120
+ };
121
+ /**
122
+ * Overbodige ruitjes wegrekenen: een ruitje met één lijn erin en één lijn eruit
123
+ * voegt niets toe, en een ruitje waar niets meer op uitkomt hoort er niet te
124
+ * staan. De vaste verzamelpunten per stap blijven altijd staan.
125
+ */
126
+ export declare function vereenvoudigMerges(tree: FlowTree, behoud?: Set<string>): FlowTree;
127
+ /** Handmatige keuzes van de gebruiker op de ruitjes toepassen. */
128
+ export declare function pasMergeOverridesToe(tree: FlowTree, overrides: MergeOverrides | undefined): FlowTree;
129
+ /**
130
+ * Zonder geselecteerde order: vakjes waar de route ophoudt krijgen geen
131
+ * doorlopende lijnen meer.
132
+ *
133
+ * Eindstation is:
134
+ * - een vakje waarvan élk vervolg uitgeschakeld is, en
135
+ * - een uitkomst-tegel (`option`): daar hangt per definitie niets meer onder.
136
+ *
137
+ * Het samenkomstpunt van een beslissing waar daarna niets meer op uitkomt,
138
+ * verdwijnt mee. De doorgaande route tussen de stappen blijft altijd heel.
139
+ */
140
+ export declare function verbergEindnodeLijnen(tree: FlowTree): FlowTree;
141
+ /**
142
+ * Het vakje "Verzendbrief" per herkomst juist tonen.
143
+ *
144
+ * Bij een Floriday-order geldt uitsluitend het officiele Floriday-document;
145
+ * de regel over de eigen layout hoort daar niet te staan. Alleen tekst: de
146
+ * kaartstructuur, instellingen en route blijven ongewijzigd.
147
+ */
148
+ export declare function verduidelijkVerzendbrief(tree: FlowTree, source: "floriday" | "mail" | "actiemail" | "handmatig" | null): FlowTree;
64
149
  //# sourceMappingURL=flowTree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"flowTree.d.ts","sourceRoot":"","sources":["../../src/lib/flowTree.ts"],"names":[],"mappings":"AAWA,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,SAAS,EAEf,MAAM,oBAAoB,CAAC;AAG5B,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC;AAE3D,MAAM,MAAM,YAAY,GACpB,OAAO,GACP,KAAK,GACL,QAAQ,GACR,MAAM,GACN,UAAU,GACV,SAAS,GACT,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,oEAAoE;IACpE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,CAAC;IACjB,4EAA4E;IAC5E,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,oEAAoE;IACpE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,YAAY,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CASpE,CAAC;AAwCF;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAcxE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CA0BlE;AA6BD,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,kBAAkB,GAAG,QAAQ,CA+NpE"}
1
+ {"version":3,"file":"flowTree.d.ts","sourceRoot":"","sources":["../../src/lib/flowTree.ts"],"names":[],"mappings":"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"}