@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.
- package/dist-lib/components/AfrondWachtrijCard.d.ts +2 -0
- package/dist-lib/components/AfrondWachtrijCard.d.ts.map +1 -0
- package/dist-lib/components/AfrondWachtrijCard.js +27 -0
- package/dist-lib/components/BeladingsafwijkingenCard.d.ts +2 -0
- package/dist-lib/components/BeladingsafwijkingenCard.d.ts.map +1 -0
- package/dist-lib/components/BeladingsafwijkingenCard.js +44 -0
- package/dist-lib/components/FlowCanvas.d.ts +34 -0
- package/dist-lib/components/FlowCanvas.d.ts.map +1 -0
- package/dist-lib/components/FlowCanvas.js +490 -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 +171 -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 +310 -0
- package/dist-lib/components/GeblokkeerdeOrdersCard.d.ts.map +1 -1
- package/dist-lib/components/GeblokkeerdeOrdersCard.js +21 -2
- 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/KardekkingCard.d.ts +2 -0
- package/dist-lib/components/KardekkingCard.d.ts.map +1 -0
- package/dist-lib/components/KardekkingCard.js +29 -0
- package/dist-lib/components/LogistiekEnginePage.d.ts.map +1 -1
- package/dist-lib/components/LogistiekEnginePage.js +15 -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 +13 -0
- package/dist-lib/components/NodeTracePanel.d.ts +14 -0
- package/dist-lib/components/NodeTracePanel.d.ts.map +1 -0
- package/dist-lib/components/NodeTracePanel.js +46 -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 +12 -0
- package/dist-lib/components/OrderStopBanner.d.ts.map +1 -0
- package/dist-lib/components/OrderStopBanner.js +36 -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 +88 -0
- package/dist-lib/components/PlanWachtrijPage.d.ts +2 -0
- package/dist-lib/components/PlanWachtrijPage.d.ts.map +1 -0
- package/dist-lib/components/PlanWachtrijPage.js +99 -0
- package/dist-lib/components/PlannerDiffCard.d.ts +2 -0
- package/dist-lib/components/PlannerDiffCard.d.ts.map +1 -0
- package/dist-lib/components/PlannerDiffCard.js +25 -0
- package/dist-lib/components/RegiePage.d.ts.map +1 -1
- package/dist-lib/components/RegiePage.js +28 -78
- package/dist-lib/components/TaakGezondheidCard.d.ts +2 -0
- package/dist-lib/components/TaakGezondheidCard.d.ts.map +1 -0
- package/dist-lib/components/TaakGezondheidCard.js +31 -0
- 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/useAfrondWachtrij.d.ts +28 -0
- package/dist-lib/hooks/useAfrondWachtrij.d.ts.map +1 -0
- package/dist-lib/hooks/useAfrondWachtrij.js +88 -0
- package/dist-lib/hooks/useBeladingsafwijkingen.d.ts +39 -0
- package/dist-lib/hooks/useBeladingsafwijkingen.d.ts.map +1 -0
- package/dist-lib/hooks/useBeladingsafwijkingen.js +119 -0
- package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts +7 -0
- package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts.map +1 -1
- package/dist-lib/hooks/useGeblokkeerdeOrders.js +28 -2
- 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 +194 -0
- package/dist-lib/hooks/usePlanWachtrij.d.ts +33 -0
- package/dist-lib/hooks/usePlanWachtrij.d.ts.map +1 -0
- package/dist-lib/hooks/usePlanWachtrij.js +104 -0
- package/dist-lib/hooks/useRecalcJob.js +1 -1
- 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/useShippingNoteDiagnose.d.ts +20 -0
- package/dist-lib/hooks/useShippingNoteDiagnose.d.ts.map +1 -0
- package/dist-lib/hooks/useShippingNoteDiagnose.js +52 -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/useTaakGezondheid.d.ts +16 -0
- package/dist-lib/hooks/useTaakGezondheid.d.ts.map +1 -0
- package/dist-lib/hooks/useTaakGezondheid.js +43 -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 +61 -5
- package/dist-lib/index.d.ts +23 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +23 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +4993 -459
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +4993 -459
- 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 +4993 -459
- package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/previewAuthStorage.d.ts +1 -1
- package/dist-lib/integrations/supabase/previewAuthStorage.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/previewAuthStorage.js +8 -1
- package/dist-lib/integrations/supabase/types.d.ts +5022 -432
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/attachAuthToken.js +1 -1
- package/dist-lib/lib/bufferDecision.test.d.ts +2 -0
- package/dist-lib/lib/bufferDecision.test.d.ts.map +1 -0
- package/dist-lib/lib/bufferDecision.test.js +104 -0
- package/dist-lib/lib/cartCoverage.functions.d.ts +30820 -0
- package/dist-lib/lib/cartCoverage.functions.d.ts.map +1 -0
- package/dist-lib/lib/cartCoverage.functions.js +20 -0
- 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 +13623 -21
- package/dist-lib/lib/floridayDocuments.functions.d.ts.map +1 -1
- package/dist-lib/lib/floridayDocuments.functions.js +5 -5
- 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 +4993 -459
- package/dist-lib/lib/floridayPush.functions.d.ts.map +1 -1
- package/dist-lib/lib/floridayPush.functions.js +3 -3
- 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/flowJourney.d.ts +40 -0
- package/dist-lib/lib/flowJourney.d.ts.map +1 -0
- package/dist-lib/lib/flowJourney.js +156 -0
- package/dist-lib/lib/flowNodes.d.ts +26 -0
- package/dist-lib/lib/flowNodes.d.ts.map +1 -0
- package/dist-lib/lib/flowNodes.js +64 -0
- package/dist-lib/lib/flowRoute.d.ts +117 -0
- package/dist-lib/lib/flowRoute.d.ts.map +1 -0
- package/dist-lib/lib/flowRoute.js +583 -0
- package/dist-lib/lib/flowTree.d.ts +149 -0
- package/dist-lib/lib/flowTree.d.ts.map +1 -0
- package/dist-lib/lib/flowTree.js +908 -0
- package/dist-lib/lib/foutTekst.d.ts +4 -0
- package/dist-lib/lib/foutTekst.d.ts.map +1 -0
- package/dist-lib/lib/foutTekst.js +43 -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 +2 -0
- package/dist-lib/lib/handlers/logistics-tick.server.d.ts.map +1 -1
- package/dist-lib/lib/handlers/logistics-tick.server.js +153 -2
- package/dist-lib/lib/handlers/logistics-tick.test.d.ts +2 -0
- package/dist-lib/lib/handlers/logistics-tick.test.d.ts.map +1 -0
- package/dist-lib/lib/handlers/logistics-tick.test.js +63 -0
- 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 +22705 -35
- package/dist-lib/lib/loadCarrierPlanning.functions.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanning.functions.js +7 -7
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts +33 -12
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanning.server.js +534 -228
- 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 +9082 -14
- package/dist-lib/lib/logisticsRecalcJob.functions.d.ts.map +1 -1
- package/dist-lib/lib/logisticsRecalcJob.functions.js +4 -4
- package/dist-lib/lib/logisticsRecalcJob.server.d.ts.map +1 -1
- package/dist-lib/lib/logisticsRecalcJob.server.js +17 -2
- package/dist-lib/lib/logisticsRecalculate.functions.d.ts +4993 -459
- package/dist-lib/lib/logisticsRecalculate.functions.d.ts.map +1 -1
- package/dist-lib/lib/logisticsRecalculate.functions.js +2 -2
- package/dist-lib/lib/modulePrompts.d.ts.map +1 -1
- package/dist-lib/lib/modulePrompts.js +893 -0
- package/dist-lib/lib/nodeTrace.d.ts +65 -0
- package/dist-lib/lib/nodeTrace.d.ts.map +1 -0
- package/dist-lib/lib/nodeTrace.js +182 -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 +164 -3
- package/dist-lib/lib/plannerDiff.d.ts +37 -0
- package/dist-lib/lib/plannerDiff.d.ts.map +1 -0
- package/dist-lib/lib/plannerDiff.functions.d.ts +30821 -0
- package/dist-lib/lib/plannerDiff.functions.d.ts.map +1 -0
- package/dist-lib/lib/plannerDiff.functions.js +21 -0
- package/dist-lib/lib/plannerDiff.js +74 -0
- package/dist-lib/lib/plannerDiff.server.d.ts +5 -0
- package/dist-lib/lib/plannerDiff.server.d.ts.map +1 -0
- package/dist-lib/lib/plannerDiff.server.js +60 -0
- package/dist-lib/lib/plannerDiff.test.d.ts +2 -0
- package/dist-lib/lib/plannerDiff.test.d.ts.map +1 -0
- package/dist-lib/lib/plannerDiff.test.js +41 -0
- package/dist-lib/lib/resolveBuffer.test.d.ts +2 -0
- package/dist-lib/lib/resolveBuffer.test.d.ts.map +1 -0
- package/dist-lib/lib/resolveBuffer.test.js +38 -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 +102 -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/stopReden.d.ts +43 -0
- package/dist-lib/lib/stopReden.d.ts.map +1 -0
- package/dist-lib/lib/stopReden.js +197 -0
- package/dist-lib/lib/taskCounts.d.ts +2 -0
- package/dist-lib/lib/taskCounts.d.ts.map +1 -0
- package/dist-lib/lib/taskCounts.js +15 -0
- package/dist-lib/lib/taskCounts.test.d.ts +2 -0
- package/dist-lib/lib/taskCounts.test.d.ts.map +1 -0
- package/dist-lib/lib/taskCounts.test.js +12 -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 +78 -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 +133 -0
- package/package.json +158 -131
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts +0 -2
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts.map +0 -1
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.js +0 -41
- package/dist-lib/integrations/supabase/client.d.ts +0 -20293
- package/dist-lib/integrations/supabase/client.d.ts.map +0 -1
- package/dist-lib/integrations/supabase/client.js +0 -13
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/lib/flowRoute.ts — de route van één herberekening (versie) van een order
|
|
3
|
+
// over de flowkaart
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Uit de logboekgegevens van één versie leiden we af tot welke stap de order
|
|
6
|
+
// is gekomen en waar hij eventueel is vastgelopen. Die informatie leggen we als
|
|
7
|
+
// laag over de flowkaart: de gelopen route wordt blauw, de rest licht, en het
|
|
8
|
+
// vastgelopen vakje krijgt een rode markering.
|
|
9
|
+
//
|
|
10
|
+
// Belangrijk: de kaart zelf blijft de actuele werkwijze. Welke keuze binnen een
|
|
11
|
+
// stap gold, komt uit de instellingen van nú; het logboek bewaart (nog) geen
|
|
12
|
+
// momentopname van de werkwijze per herberekening. Dat melden we in de kaart.
|
|
13
|
+
// ============================================================================
|
|
14
|
+
import { WIZARD_STEPS } from "./ruleEngineWizard";
|
|
15
|
+
import { FLOW_NODE, bronNodeVoor } from "./flowNodes";
|
|
16
|
+
import { vakUitleg } from "./vakUitleg";
|
|
17
|
+
import { stopReden, samenkomstStop } from "./stopReden";
|
|
18
|
+
const STEP_IDS = WIZARD_STEPS.map((s) => s.id);
|
|
19
|
+
const STAP = {
|
|
20
|
+
combineren: STEP_IDS[0] ?? "orders_combineren",
|
|
21
|
+
indeling: STEP_IDS[1] ?? "beladingindeling",
|
|
22
|
+
picken: STEP_IDS[2] ?? "picken",
|
|
23
|
+
drukte: STEP_IDS[3] ?? "drukte_vertraging",
|
|
24
|
+
stations: STEP_IDS[4] ?? "pickstations",
|
|
25
|
+
controle: STEP_IDS[5] ?? "controle",
|
|
26
|
+
};
|
|
27
|
+
export const REASON_LABEL = {
|
|
28
|
+
afmetingen_onbekend: "Afmetingen van fust/product onbekend",
|
|
29
|
+
kargrens_overschreden: "Kargrens overschreden (te veel lagen/karren)",
|
|
30
|
+
bufferdekking_onvolledig: "Buffer nog niet compleet: niet alle orders binnen",
|
|
31
|
+
werktijden_ontbreken: "Werktijden van de klant ontbreken",
|
|
32
|
+
fust_onbekend: "Fusttype onbekend",
|
|
33
|
+
geen_regels: "Order heeft geen regels",
|
|
34
|
+
dubbele_regels: "Order heeft dubbele bestelregels; er is niets ingedeeld",
|
|
35
|
+
};
|
|
36
|
+
export function redenTekst(code, error) {
|
|
37
|
+
const label = code ? REASON_LABEL[code] ?? code.replace(/_/g, " ") : null;
|
|
38
|
+
if (label && error && !error.includes(code ?? ""))
|
|
39
|
+
return `${label} — ${error}`;
|
|
40
|
+
return label ?? error ?? "Onbekende reden";
|
|
41
|
+
}
|
|
42
|
+
const AFGEROND = new Set(["verzonden", "gereed voor facturatie", "afgehandeld", "gefactureerd", "afgemeld"]);
|
|
43
|
+
/** Leidt uit één versie + de huidige stand van de order de gelopen route af. */
|
|
44
|
+
export function bepaalRoute(versie, order, carts, isLaatste) {
|
|
45
|
+
const bron = order?.orderSource ? bronNodeVoor(order.orderSource) : null;
|
|
46
|
+
const source = bron === FLOW_NODE.bronFloriday
|
|
47
|
+
? "floriday"
|
|
48
|
+
: bron === FLOW_NODE.bronMail
|
|
49
|
+
? "mail"
|
|
50
|
+
: bron === FLOW_NODE.bronActiemail
|
|
51
|
+
? "actiemail"
|
|
52
|
+
: bron === FLOW_NODE.bronHandmatig
|
|
53
|
+
? "handmatig"
|
|
54
|
+
: null;
|
|
55
|
+
const reached = [];
|
|
56
|
+
let stuck = null;
|
|
57
|
+
let busy = null;
|
|
58
|
+
let finished = false;
|
|
59
|
+
if (!versie) {
|
|
60
|
+
return {
|
|
61
|
+
source,
|
|
62
|
+
reached,
|
|
63
|
+
stuck: null,
|
|
64
|
+
busy: { stepId: STAP.combineren, reason: "Order is binnen, maar nog nooit ingedeeld" },
|
|
65
|
+
finished: false,
|
|
66
|
+
summary: "Nog geen herberekening bekend voor deze order.",
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// 1. Ontvangen en combineren: zodra er een wachtrijrij is, is de order binnen.
|
|
70
|
+
reached.push(STAP.combineren);
|
|
71
|
+
// 2. Karindeling: de uitkomst van de planwachtrij.
|
|
72
|
+
const status = (versie.status ?? "pending").toLowerCase();
|
|
73
|
+
if (status === "pending") {
|
|
74
|
+
busy = { stepId: STAP.indeling, reason: "Wacht op de planronde" };
|
|
75
|
+
}
|
|
76
|
+
else if (status === "running") {
|
|
77
|
+
reached.push(STAP.indeling);
|
|
78
|
+
busy = { stepId: STAP.indeling, reason: "Karindeling wordt nu berekend" };
|
|
79
|
+
}
|
|
80
|
+
else if (status === "failed" || status === "geblokkeerd") {
|
|
81
|
+
reached.push(STAP.indeling);
|
|
82
|
+
stuck = {
|
|
83
|
+
stepId: STAP.indeling,
|
|
84
|
+
reason: (status === "geblokkeerd" ? "Geblokkeerd: " : "Mislukt: ") +
|
|
85
|
+
redenTekst(versie.reasonCode, versie.error ?? versie.lastError),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
reached.push(STAP.indeling);
|
|
90
|
+
}
|
|
91
|
+
if (!stuck && !busy) {
|
|
92
|
+
// 3–5. Picken, vrijgave en pickstations: pakbonnen/printopdrachten.
|
|
93
|
+
if (versie.printJobs > 0) {
|
|
94
|
+
reached.push(STAP.picken, STAP.drukte, STAP.stations);
|
|
95
|
+
if (versie.printFailed > 0 && versie.printFailed >= versie.printJobs) {
|
|
96
|
+
stuck = { stepId: STAP.stations, reason: "Printopdracht mislukt of geannuleerd" };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else if (versie.lastErrorStep && versie.errors > 0 && (versie.lastPhase ?? "").includes("verzendbrief")) {
|
|
100
|
+
reached.push(STAP.picken, STAP.drukte, STAP.stations);
|
|
101
|
+
stuck = { stepId: STAP.stations, reason: `Verzendbrief: ${versie.lastError ?? "fout"}` };
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
reached.push(STAP.picken);
|
|
105
|
+
busy = { stepId: STAP.drukte, reason: "Ingedeeld; wacht op vrijgave/aanmeldmoment" };
|
|
106
|
+
}
|
|
107
|
+
const ship = (versie.shippingStatus ?? "").toLowerCase();
|
|
108
|
+
if (!stuck && (ship === "mislukt" || ship === "geblokkeerd")) {
|
|
109
|
+
stuck = { stepId: STAP.stations, reason: `Verzendbrief ${ship}${versie.lastError ? `: ${versie.lastError}` : ""}` };
|
|
110
|
+
}
|
|
111
|
+
// 6. Controle en afronding: alleen aantoonbaar voor de laatste versie
|
|
112
|
+
// (de karrenstand is een stand van nú).
|
|
113
|
+
if (!stuck && isLaatste && carts && carts.total > 0) {
|
|
114
|
+
if (carts.printed > 0) {
|
|
115
|
+
if (!reached.includes(STAP.stations))
|
|
116
|
+
reached.push(STAP.drukte, STAP.stations);
|
|
117
|
+
busy = null;
|
|
118
|
+
if (carts.controlled >= carts.total) {
|
|
119
|
+
reached.push(STAP.controle);
|
|
120
|
+
finished = true;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
reached.push(STAP.controle);
|
|
124
|
+
busy = {
|
|
125
|
+
stepId: STAP.controle,
|
|
126
|
+
reason: `${carts.controlled} van ${carts.total} karren gecontroleerd`,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (isLaatste && order?.status && AFGEROND.has(order.status.toLowerCase())) {
|
|
132
|
+
if (!reached.includes(STAP.controle))
|
|
133
|
+
reached.push(STAP.drukte, STAP.stations, STAP.controle);
|
|
134
|
+
busy = null;
|
|
135
|
+
finished = true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (isLaatste && order?.cancelledAt) {
|
|
139
|
+
stuck = { stepId: stuck?.stepId ?? busy?.stepId ?? STAP.combineren, reason: "Order is geannuleerd" };
|
|
140
|
+
busy = null;
|
|
141
|
+
finished = false;
|
|
142
|
+
}
|
|
143
|
+
const uniek = [...new Set(reached)];
|
|
144
|
+
const summary = finished
|
|
145
|
+
? "Route volledig doorlopen: order is gecontroleerd en afgemeld."
|
|
146
|
+
: stuck
|
|
147
|
+
? `Vastgelopen bij "${stapLabel(stuck.stepId)}": ${stuck.reason}`
|
|
148
|
+
: busy
|
|
149
|
+
? `Nu bij "${stapLabel(busy.stepId)}": ${busy.reason}`
|
|
150
|
+
: `Gekomen tot "${stapLabel(uniek[uniek.length - 1] ?? STAP.combineren)}".`;
|
|
151
|
+
return { source, reached: uniek, stuck, busy, finished, summary };
|
|
152
|
+
}
|
|
153
|
+
export function stapLabel(stepId) {
|
|
154
|
+
return WIZARD_STEPS.find((s) => s.id === stepId)?.label ?? stepId;
|
|
155
|
+
}
|
|
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
|
+
};
|
|
166
|
+
/** Stapvolgorde-index van een knoop; -1 = vóór de eerste stap; 99 = einde. */
|
|
167
|
+
function stapIndex(node, byId) {
|
|
168
|
+
if (!node)
|
|
169
|
+
return -1;
|
|
170
|
+
if (node.id === "__eind")
|
|
171
|
+
return 99;
|
|
172
|
+
if (node.id.startsWith("__"))
|
|
173
|
+
return -1;
|
|
174
|
+
const extra = EXTRA_STAP_INDEX[node.id];
|
|
175
|
+
if (extra !== undefined)
|
|
176
|
+
return extra;
|
|
177
|
+
const m = /^(?:samen:)?stap:(.+)$/.exec(node.id);
|
|
178
|
+
if (m)
|
|
179
|
+
return STEP_IDS.indexOf(m[1]);
|
|
180
|
+
if (node.stepId)
|
|
181
|
+
return STEP_IDS.indexOf(node.stepId);
|
|
182
|
+
for (const a of [...node.ancestors].reverse()) {
|
|
183
|
+
const anc = byId.get(a);
|
|
184
|
+
if (anc?.stepId)
|
|
185
|
+
return STEP_IDS.indexOf(anc.stepId);
|
|
186
|
+
}
|
|
187
|
+
return -1;
|
|
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
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Maakt een kopie van de kaart waarin alleen de gelopen route "active" is.
|
|
302
|
+
* Knopen/pijlen die de order (nog) niet heeft bereikt worden "possible".
|
|
303
|
+
*
|
|
304
|
+
* Zijn er echte gebeurtenissen per vakje (`groepen`), dan winnen die: de reis
|
|
305
|
+
* komt dan uit wat de Engine heeft vastgelegd. De heuristiek hieronder blijft
|
|
306
|
+
* de terugval voor oudere gebeurtenissen zonder vakje.
|
|
307
|
+
*/
|
|
308
|
+
export function applyRoute(tree, route, groepen, stand) {
|
|
309
|
+
const markers = new Map();
|
|
310
|
+
const nodes = Array.isArray(tree?.nodes) ? tree.nodes : [];
|
|
311
|
+
const edges = Array.isArray(tree?.edges) ? tree.edges : [];
|
|
312
|
+
if (!route)
|
|
313
|
+
return { tree: { nodes, edges }, markers, wachtpunten: new Set() };
|
|
314
|
+
const echt = groepen && groepen.size > 0 ? groepen : null;
|
|
315
|
+
const byId = new Map(nodes.map((n) => [n.id, n]));
|
|
316
|
+
const maxIdx = route.reached.reduce((m, id) => Math.max(m, STEP_IDS.indexOf(id)), -1);
|
|
317
|
+
const bereikt = (idx) => (idx === 99 ? route.finished : idx <= maxIdx);
|
|
318
|
+
// Het bronvakje van deze order (Floriday, mail, actiemail of handmatig).
|
|
319
|
+
const bronNode = route.source === "floriday"
|
|
320
|
+
? FLOW_NODE.bronFloriday
|
|
321
|
+
: route.source === "mail"
|
|
322
|
+
? FLOW_NODE.bronMail
|
|
323
|
+
: route.source === "actiemail"
|
|
324
|
+
? FLOW_NODE.bronActiemail
|
|
325
|
+
: route.source === "handmatig"
|
|
326
|
+
? FLOW_NODE.bronHandmatig
|
|
327
|
+
: null;
|
|
328
|
+
const bronTak = (id) => id === FLOW_NODE.bronFloriday ||
|
|
329
|
+
id === FLOW_NODE.bronMail ||
|
|
330
|
+
id === FLOW_NODE.bronActiemail ||
|
|
331
|
+
id === FLOW_NODE.bronHandmatig;
|
|
332
|
+
/** Hoort dit bronvakje (of de samenvoegstap erna) bij deze order? */
|
|
333
|
+
const bronOk = (id) => {
|
|
334
|
+
if (bronTak(id))
|
|
335
|
+
return id === bronNode;
|
|
336
|
+
if (id === FLOW_NODE.samenvoegen)
|
|
337
|
+
return bronNode === FLOW_NODE.bronFloriday;
|
|
338
|
+
return true;
|
|
339
|
+
};
|
|
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? */
|
|
546
|
+
const opReis = (n) => {
|
|
547
|
+
if (bronTak(n.id) || n.id === FLOW_NODE.samenvoegen) {
|
|
548
|
+
return bronOk(n.id) && bereikt(-1);
|
|
549
|
+
}
|
|
550
|
+
return bereikt(stapIndex(n, byId));
|
|
551
|
+
};
|
|
552
|
+
const newNodes = nodes.map((n) => {
|
|
553
|
+
const ok = n.state === "active" && opReis(n);
|
|
554
|
+
return ok ? { ...n, route: true } : { ...n, state: demote(n.state), route: false };
|
|
555
|
+
});
|
|
556
|
+
const nodeState = new Map(newNodes.map((n) => [n.id, n.state]));
|
|
557
|
+
const newEdges = edges.map((e) => {
|
|
558
|
+
if (e.state !== "active")
|
|
559
|
+
return e;
|
|
560
|
+
const to = byId.get(e.to);
|
|
561
|
+
const from = byId.get(e.from);
|
|
562
|
+
const ok = nodeState.get(e.from) === "active" &&
|
|
563
|
+
nodeState.get(e.to) === "active" &&
|
|
564
|
+
bereikt(Math.max(stapIndex(from, byId), stapIndex(to, byId))) &&
|
|
565
|
+
bronOk(e.from) &&
|
|
566
|
+
bronOk(e.to);
|
|
567
|
+
return ok ? { ...e, route: true } : { ...e, state: "possible", route: false };
|
|
568
|
+
});
|
|
569
|
+
if (route.stuck)
|
|
570
|
+
markers.set(`stap:${route.stuck.stepId}`, { kind: "stuck", text: route.stuck.reason });
|
|
571
|
+
else if (route.busy)
|
|
572
|
+
markers.set(`stap:${route.busy.stepId}`, { kind: "busy", text: route.busy.reason });
|
|
573
|
+
if (route.finished)
|
|
574
|
+
markers.set("__eind", { kind: "done", text: "Afgehandeld" });
|
|
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
|
+
};
|
|
583
|
+
}
|