@flowselections/logistiek-engine 1.0.27 → 1.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -24
- package/dist-lib/components/AfmetingenBronnenCard.d.ts +2 -0
- package/dist-lib/components/AfmetingenBronnenCard.d.ts.map +1 -0
- package/dist-lib/components/AfmetingenBronnenCard.js +46 -0
- package/dist-lib/components/BufferDebugCard.d.ts.map +1 -1
- package/dist-lib/components/BufferDebugCard.js +6 -1
- package/dist-lib/components/ConsistentieCard.d.ts.map +1 -1
- package/dist-lib/components/ConsistentieCard.js +1 -1
- package/dist-lib/components/GeblokkeerdeOrdersCard.d.ts +2 -0
- package/dist-lib/components/GeblokkeerdeOrdersCard.d.ts.map +1 -0
- package/dist-lib/components/GeblokkeerdeOrdersCard.js +44 -0
- package/dist-lib/components/KarplanStatusCard.d.ts +2 -0
- package/dist-lib/components/KarplanStatusCard.d.ts.map +1 -0
- package/dist-lib/components/KarplanStatusCard.js +31 -0
- package/dist-lib/components/RegiePage.d.ts.map +1 -1
- package/dist-lib/components/RegiePage.js +4 -1
- package/dist-lib/components/RuleEnginePage.d.ts.map +1 -1
- package/dist-lib/components/RuleEnginePage.js +7 -4
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts +2 -0
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts.map +1 -0
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.js +41 -0
- package/dist-lib/components/rule-engine/RuleFieldInput.d.ts.map +1 -1
- package/dist-lib/components/rule-engine/RuleFieldInput.js +9 -0
- package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts +28 -0
- package/dist-lib/hooks/useGeblokkeerdeOrders.d.ts.map +1 -0
- package/dist-lib/hooks/useGeblokkeerdeOrders.js +94 -0
- package/dist-lib/hooks/useRecalcJob.d.ts.map +1 -1
- package/dist-lib/hooks/useRecalcJob.js +26 -1
- package/dist-lib/hooks/useScannersPrinters.d.ts +11 -0
- package/dist-lib/hooks/useScannersPrinters.d.ts.map +1 -0
- package/dist-lib/hooks/useScannersPrinters.js +65 -0
- package/dist-lib/index.d.ts +3 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +3 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +2105 -68
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +20293 -0
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -0
- package/dist-lib/integrations/supabase/client.js +13 -0
- package/dist-lib/integrations/supabase/client.server.d.ts +2105 -68
- 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 +2105 -68
- package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +2135 -54
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +1 -0
- package/dist-lib/lib/attachAuthToken.d.ts +2 -0
- package/dist-lib/lib/attachAuthToken.d.ts.map +1 -0
- package/dist-lib/lib/attachAuthToken.js +50 -0
- package/dist-lib/lib/bufferMatching.d.ts.map +1 -1
- package/dist-lib/lib/bufferMatching.js +1 -0
- package/dist-lib/lib/cartPlanRequests.server.d.ts +13 -0
- package/dist-lib/lib/cartPlanRequests.server.d.ts.map +1 -0
- package/dist-lib/lib/cartPlanRequests.server.js +168 -0
- package/dist-lib/lib/controlScan.server.d.ts +12 -0
- package/dist-lib/lib/controlScan.server.d.ts.map +1 -0
- package/dist-lib/lib/controlScan.server.js +197 -0
- package/dist-lib/lib/dimensionData.server.d.ts +11 -1
- package/dist-lib/lib/dimensionData.server.d.ts.map +1 -1
- package/dist-lib/lib/dimensionData.server.js +58 -48
- package/dist-lib/lib/dimensionPlanner.d.ts +26 -1
- package/dist-lib/lib/dimensionPlanner.d.ts.map +1 -1
- package/dist-lib/lib/dimensionPlanner.js +37 -6
- package/dist-lib/lib/floridayDocuments.functions.d.ts +6314 -203
- package/dist-lib/lib/floridayDocuments.functions.d.ts.map +1 -1
- package/dist-lib/lib/floridayDocuments.functions.js +4 -3
- package/dist-lib/lib/floridayPush.functions.d.ts +2106 -69
- package/dist-lib/lib/floridayPush.functions.d.ts.map +1 -1
- package/dist-lib/lib/floridayPush.functions.js +2 -1
- package/dist-lib/lib/handlers/logistics-tick.server.d.ts.map +1 -1
- package/dist-lib/lib/handlers/logistics-tick.server.js +64 -0
- package/dist-lib/lib/loadCarrierPlanning.functions.d.ts +10480 -295
- package/dist-lib/lib/loadCarrierPlanning.functions.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanning.functions.js +6 -5
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts +42 -0
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanning.server.js +583 -31
- package/dist-lib/lib/logisticsPlanner.d.ts.map +1 -1
- package/dist-lib/lib/logisticsPlanner.js +24 -9
- package/dist-lib/lib/logisticsRecalcJob.functions.d.ts +4231 -157
- package/dist-lib/lib/logisticsRecalcJob.functions.d.ts.map +1 -1
- package/dist-lib/lib/logisticsRecalcJob.functions.js +3 -2
- package/dist-lib/lib/logisticsRecalcJob.server.d.ts.map +1 -1
- package/dist-lib/lib/logisticsRecalcJob.server.js +1 -0
- package/dist-lib/lib/logisticsRecalculate.functions.d.ts +2106 -69
- package/dist-lib/lib/logisticsRecalculate.functions.d.ts.map +1 -1
- package/dist-lib/lib/logisticsRecalculate.functions.js +3 -1
- package/dist-lib/lib/modulePrompts.d.ts.map +1 -1
- package/dist-lib/lib/modulePrompts.js +2560 -1586
- package/dist-lib/lib/planQueue.server.d.ts.map +1 -1
- package/dist-lib/lib/planQueue.server.js +6 -0
- package/dist-lib/lib/readableServerErrors.d.ts +2 -0
- package/dist-lib/lib/readableServerErrors.d.ts.map +1 -0
- package/dist-lib/lib/readableServerErrors.js +36 -0
- package/dist-lib/lib/ruleEngineSchema.d.ts +1 -1
- package/dist-lib/lib/ruleEngineSchema.d.ts.map +1 -1
- package/dist-lib/lib/ruleEngineSchema.js +72 -51
- package/dist-lib/lib/ruleEngineWizard.d.ts.map +1 -1
- package/dist-lib/lib/ruleEngineWizard.js +5 -6
- package/package.json +1 -1
|
@@ -18,155 +18,155 @@ export const PROMPT_MODULE_LABELS = {
|
|
|
18
18
|
};
|
|
19
19
|
function sharedBlock(moduleKey) {
|
|
20
20
|
const key = moduleKey === "<modulesleutel>" ? "<modulesleutel>" : moduleKey;
|
|
21
|
-
return `Alle communicatie met de Logistics Engine loopt uitsluitend via de gedeelde
|
|
22
|
-
Supabase-database. Je leest en schrijft gewoon tabellen met de bestaande
|
|
23
|
-
Supabase-client van deze module (ingelogde gebruiker, RLS). Geen API-key,
|
|
24
|
-
geen header, geen secret, geen edge function.
|
|
25
|
-
|
|
26
|
-
Verbinding — verplicht en fail-closed:
|
|
27
|
-
- Gebruik de Supabase-client van je EIGEN module, lazy geïnstantieerd en
|
|
28
|
-
uitsluitend gevoed door import.meta.env.VITE_SUPABASE_URL en
|
|
29
|
-
import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY. Ontbreekt er een waarde, gooi
|
|
30
|
-
dan een harde fout; raad nooit een verbinding.
|
|
31
|
-
- Hardcodeer NOOIT een Supabase project-ref, URL of anon-key — ook niet als
|
|
32
|
-
fallback, voorbeeld of default. De shell bepaalt via env welke database geldt.
|
|
33
|
-
- Importeer NOOIT uit "@/integrations/supabase/client": dat bestand wordt door
|
|
34
|
-
de Supabase-integratie automatisch gegenereerd en overschreven met een
|
|
35
|
-
vastgezette project-ref, wat in een andere shell naar de verkeerde database
|
|
36
|
-
schrijft. Zet je eigen client in bijvoorbeeld
|
|
37
|
-
"@/integrations/supabase/moduleClient" en sluit het gegenereerde bestand uit
|
|
38
|
-
van je library-build.
|
|
39
|
-
|
|
40
|
-
De Engine beslist alles over buffering, belading, picken, controle, printen en
|
|
41
|
-
transport. Deze module voert alleen nog taken uit en beslist zelf niets meer.
|
|
42
|
-
|
|
43
|
-
--- Gebeurtenis melden: RPC logistics_emit_event (idempotent) ---
|
|
44
|
-
const { data } = await supabase.rpc("logistics_emit_event", {
|
|
45
|
-
p_source_module: "${key}",
|
|
46
|
-
p_event_type: "order.received", // of order.changed, stock.changed
|
|
47
|
-
p_order_ref: "SO-12345",
|
|
48
|
-
p_payload: {
|
|
49
|
-
checkinAt: "2026-08-01T10:00:00Z",
|
|
50
|
-
pickupAt: "2026-08-01T14:00:00Z",
|
|
51
|
-
customerRef: "CUST-1",
|
|
52
|
-
deliveryLocationRef: "LOC-1",
|
|
53
|
-
bufferRef: null,
|
|
54
|
-
loadCarriers: [{ type: "trolley", count: 3 }],
|
|
55
|
-
ruleVersion: null, // optioneel: plan op een vastgelegde regelversie
|
|
56
|
-
},
|
|
57
|
-
p_strategy_id: null, // uuid van logistics_strategies indien bekend
|
|
58
|
-
p_shadow: true,
|
|
59
|
-
p_idempotency_key: "${key}:SO-12345:order.received:v1",
|
|
60
|
-
});
|
|
61
|
-
// data = { eventId, planRunId, status, duplicate }
|
|
62
|
-
Geef ALTIJD een p_idempotency_key mee die uniek is per gebeurtenis. Stuur je
|
|
63
|
-
dezelfde melding twee keer (retry, dubbele webhook), dan plant de Engine maar
|
|
64
|
-
één keer en krijg je duplicate: true terug.
|
|
65
|
-
De Engine pakt de rij direct op (status pending -> processed), plant de keten en
|
|
66
|
-
zet plan_run_id en error terug op dezelfde rij.
|
|
67
|
-
|
|
68
|
-
--- Taken ophalen: SELECT op public.logistics_tasks ---
|
|
69
|
-
const { data } = await supabase
|
|
70
|
-
.from("logistics_tasks")
|
|
71
|
-
.select("*")
|
|
72
|
-
.eq("owner_module", "${key}")
|
|
73
|
-
.eq("status", "planned")
|
|
74
|
-
.order("planned_start", { ascending: true });
|
|
75
|
-
Kolommen: order_ref, buffer_ref, task_type, sequence, depends_on,
|
|
76
|
-
planned_start, planned_end, due_at, status, shadow, payload, result,
|
|
77
|
-
rule_version, claimed_by, claimed_at, error.
|
|
78
|
-
|
|
79
|
-
Realtime kan gewoon met supabase.channel() op logistics_tasks (in useEffect,
|
|
80
|
-
met removeChannel in de cleanup).
|
|
81
|
-
|
|
82
|
-
--- Taak claimen: ALTIJD via RPC, nooit met een eigen UPDATE ---
|
|
83
|
-
const { data: taak } = await supabase.rpc("logistics_claim_task", {
|
|
84
|
-
p_task_id: taskId, p_worker: "station-3",
|
|
85
|
-
});
|
|
86
|
-
if (!taak) { /* al door iemand anders geclaimd */ }
|
|
87
|
-
|
|
88
|
-
// of automatisch de eerstvolgende taak van deze module:
|
|
89
|
-
const { data: volgende } = await supabase.rpc("logistics_claim_next_task", {
|
|
90
|
-
p_owner_module: "${key}", p_worker: "station-3",
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
--- Taak afmelden: ook via RPC ---
|
|
94
|
-
await supabase.rpc("logistics_complete_task", { p_task_id: taskId, p_result: { ... } });
|
|
95
|
-
await supabase.rpc("logistics_fail_task", { p_task_id: taskId, p_error: "reden" });
|
|
96
|
-
|
|
97
|
-
--- Order annuleren ---
|
|
98
|
-
await supabase.rpc("logistics_emit_event", {
|
|
99
|
-
p_source_module: "${key}",
|
|
100
|
-
p_event_type: "order.cancelled",
|
|
101
|
-
p_order_ref: "SO-12345",
|
|
102
|
-
p_payload: { reason: "klant belde af" },
|
|
103
|
-
p_idempotency_key: "${key}:SO-12345:cancel:v1",
|
|
104
|
-
});
|
|
105
|
-
Al afgeronde taken blijven staan. Annuleer nooit zelf met een eigen UPDATE.
|
|
106
|
-
|
|
107
|
-
--- Order splitsen ---
|
|
108
|
-
await supabase.rpc("logistics_emit_event", {
|
|
109
|
-
p_source_module: "${key}",
|
|
110
|
-
p_event_type: "order.split",
|
|
111
|
-
p_order_ref: "SO-12345",
|
|
112
|
-
p_payload: {
|
|
113
|
-
checkinAt: "...", pickupAt: "...",
|
|
114
|
-
children: [
|
|
115
|
-
{ orderRef: "SO-12345-A", loadCarriers: [{ type: "trolley", count: 1 }] },
|
|
116
|
-
{ orderRef: "SO-12345-B", loadCarriers: [{ type: "trolley", count: 2 }] },
|
|
117
|
-
],
|
|
118
|
-
},
|
|
119
|
-
p_idempotency_key: "${key}:SO-12345:split:v1",
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
--- Spoed / prioriteit ---
|
|
123
|
-
await supabase.rpc("logistics_set_order_priority", {
|
|
124
|
-
p_order_ref: "SO-12345", p_priority: 100,
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
--- Instellingen inzien (nooit zelf beslissen) ---
|
|
128
|
-
public.logistics_strategies de logistieke strategieën
|
|
129
|
-
public.logistics_rule_configs settings (jsonb) per strategie + current_version
|
|
130
|
-
public.logistics_plan_runs momentopname van de instellingen per planronde
|
|
131
|
-
Alleen lezen, en alleen om te tonen.
|
|
132
|
-
|
|
133
|
-
Ladingdragers: trolley, danish_container, euro_rolcontainer, pallet, euro_pallet, loose
|
|
134
|
-
Taakstatussen: planned, claimed, in_progress, done, skipped, cancelled,
|
|
135
|
-
superseded, failed
|
|
136
|
-
|
|
137
|
-
Eigenaarschap: meldingen, planruns en taken hebben een kolom user_id die de
|
|
138
|
-
database automatisch vult met het ingelogde account.
|
|
139
|
-
|
|
140
|
-
Start in schaduwmodus (shadow: true): eigen logica blijft draaien, Engine-taken
|
|
141
|
-
worden alleen getoond en vergeleken. Elke taak draagt rule_version — een lopende
|
|
21
|
+
return `Alle communicatie met de Logistics Engine loopt uitsluitend via de gedeelde
|
|
22
|
+
Supabase-database. Je leest en schrijft gewoon tabellen met de bestaande
|
|
23
|
+
Supabase-client van deze module (ingelogde gebruiker, RLS). Geen API-key,
|
|
24
|
+
geen header, geen secret, geen edge function.
|
|
25
|
+
|
|
26
|
+
Verbinding — verplicht en fail-closed:
|
|
27
|
+
- Gebruik de Supabase-client van je EIGEN module, lazy geïnstantieerd en
|
|
28
|
+
uitsluitend gevoed door import.meta.env.VITE_SUPABASE_URL en
|
|
29
|
+
import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY. Ontbreekt er een waarde, gooi
|
|
30
|
+
dan een harde fout; raad nooit een verbinding.
|
|
31
|
+
- Hardcodeer NOOIT een Supabase project-ref, URL of anon-key — ook niet als
|
|
32
|
+
fallback, voorbeeld of default. De shell bepaalt via env welke database geldt.
|
|
33
|
+
- Importeer NOOIT uit "@/integrations/supabase/client": dat bestand wordt door
|
|
34
|
+
de Supabase-integratie automatisch gegenereerd en overschreven met een
|
|
35
|
+
vastgezette project-ref, wat in een andere shell naar de verkeerde database
|
|
36
|
+
schrijft. Zet je eigen client in bijvoorbeeld
|
|
37
|
+
"@/integrations/supabase/moduleClient" en sluit het gegenereerde bestand uit
|
|
38
|
+
van je library-build.
|
|
39
|
+
|
|
40
|
+
De Engine beslist alles over buffering, belading, picken, controle, printen en
|
|
41
|
+
transport. Deze module voert alleen nog taken uit en beslist zelf niets meer.
|
|
42
|
+
|
|
43
|
+
--- Gebeurtenis melden: RPC logistics_emit_event (idempotent) ---
|
|
44
|
+
const { data } = await supabase.rpc("logistics_emit_event", {
|
|
45
|
+
p_source_module: "${key}",
|
|
46
|
+
p_event_type: "order.received", // of order.changed, stock.changed
|
|
47
|
+
p_order_ref: "SO-12345",
|
|
48
|
+
p_payload: {
|
|
49
|
+
checkinAt: "2026-08-01T10:00:00Z",
|
|
50
|
+
pickupAt: "2026-08-01T14:00:00Z",
|
|
51
|
+
customerRef: "CUST-1",
|
|
52
|
+
deliveryLocationRef: "LOC-1",
|
|
53
|
+
bufferRef: null,
|
|
54
|
+
loadCarriers: [{ type: "trolley", count: 3 }],
|
|
55
|
+
ruleVersion: null, // optioneel: plan op een vastgelegde regelversie
|
|
56
|
+
},
|
|
57
|
+
p_strategy_id: null, // uuid van logistics_strategies indien bekend
|
|
58
|
+
p_shadow: true,
|
|
59
|
+
p_idempotency_key: "${key}:SO-12345:order.received:v1",
|
|
60
|
+
});
|
|
61
|
+
// data = { eventId, planRunId, status, duplicate }
|
|
62
|
+
Geef ALTIJD een p_idempotency_key mee die uniek is per gebeurtenis. Stuur je
|
|
63
|
+
dezelfde melding twee keer (retry, dubbele webhook), dan plant de Engine maar
|
|
64
|
+
één keer en krijg je duplicate: true terug.
|
|
65
|
+
De Engine pakt de rij direct op (status pending -> processed), plant de keten en
|
|
66
|
+
zet plan_run_id en error terug op dezelfde rij.
|
|
67
|
+
|
|
68
|
+
--- Taken ophalen: SELECT op public.logistics_tasks ---
|
|
69
|
+
const { data } = await supabase
|
|
70
|
+
.from("logistics_tasks")
|
|
71
|
+
.select("*")
|
|
72
|
+
.eq("owner_module", "${key}")
|
|
73
|
+
.eq("status", "planned")
|
|
74
|
+
.order("planned_start", { ascending: true });
|
|
75
|
+
Kolommen: order_ref, buffer_ref, task_type, sequence, depends_on,
|
|
76
|
+
planned_start, planned_end, due_at, status, shadow, payload, result,
|
|
77
|
+
rule_version, claimed_by, claimed_at, error.
|
|
78
|
+
|
|
79
|
+
Realtime kan gewoon met supabase.channel() op logistics_tasks (in useEffect,
|
|
80
|
+
met removeChannel in de cleanup).
|
|
81
|
+
|
|
82
|
+
--- Taak claimen: ALTIJD via RPC, nooit met een eigen UPDATE ---
|
|
83
|
+
const { data: taak } = await supabase.rpc("logistics_claim_task", {
|
|
84
|
+
p_task_id: taskId, p_worker: "station-3",
|
|
85
|
+
});
|
|
86
|
+
if (!taak) { /* al door iemand anders geclaimd */ }
|
|
87
|
+
|
|
88
|
+
// of automatisch de eerstvolgende taak van deze module:
|
|
89
|
+
const { data: volgende } = await supabase.rpc("logistics_claim_next_task", {
|
|
90
|
+
p_owner_module: "${key}", p_worker: "station-3",
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
--- Taak afmelden: ook via RPC ---
|
|
94
|
+
await supabase.rpc("logistics_complete_task", { p_task_id: taskId, p_result: { ... } });
|
|
95
|
+
await supabase.rpc("logistics_fail_task", { p_task_id: taskId, p_error: "reden" });
|
|
96
|
+
|
|
97
|
+
--- Order annuleren ---
|
|
98
|
+
await supabase.rpc("logistics_emit_event", {
|
|
99
|
+
p_source_module: "${key}",
|
|
100
|
+
p_event_type: "order.cancelled",
|
|
101
|
+
p_order_ref: "SO-12345",
|
|
102
|
+
p_payload: { reason: "klant belde af" },
|
|
103
|
+
p_idempotency_key: "${key}:SO-12345:cancel:v1",
|
|
104
|
+
});
|
|
105
|
+
Al afgeronde taken blijven staan. Annuleer nooit zelf met een eigen UPDATE.
|
|
106
|
+
|
|
107
|
+
--- Order splitsen ---
|
|
108
|
+
await supabase.rpc("logistics_emit_event", {
|
|
109
|
+
p_source_module: "${key}",
|
|
110
|
+
p_event_type: "order.split",
|
|
111
|
+
p_order_ref: "SO-12345",
|
|
112
|
+
p_payload: {
|
|
113
|
+
checkinAt: "...", pickupAt: "...",
|
|
114
|
+
children: [
|
|
115
|
+
{ orderRef: "SO-12345-A", loadCarriers: [{ type: "trolley", count: 1 }] },
|
|
116
|
+
{ orderRef: "SO-12345-B", loadCarriers: [{ type: "trolley", count: 2 }] },
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
p_idempotency_key: "${key}:SO-12345:split:v1",
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
--- Spoed / prioriteit ---
|
|
123
|
+
await supabase.rpc("logistics_set_order_priority", {
|
|
124
|
+
p_order_ref: "SO-12345", p_priority: 100,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
--- Instellingen inzien (nooit zelf beslissen) ---
|
|
128
|
+
public.logistics_strategies de logistieke strategieën
|
|
129
|
+
public.logistics_rule_configs settings (jsonb) per strategie + current_version
|
|
130
|
+
public.logistics_plan_runs momentopname van de instellingen per planronde
|
|
131
|
+
Alleen lezen, en alleen om te tonen.
|
|
132
|
+
|
|
133
|
+
Ladingdragers: trolley, danish_container, euro_rolcontainer, pallet, euro_pallet, loose
|
|
134
|
+
Taakstatussen: planned, claimed, in_progress, done, skipped, cancelled,
|
|
135
|
+
superseded, failed
|
|
136
|
+
|
|
137
|
+
Eigenaarschap: meldingen, planruns en taken hebben een kolom user_id die de
|
|
138
|
+
database automatisch vult met het ingelogde account.
|
|
139
|
+
|
|
140
|
+
Start in schaduwmodus (shadow: true): eigen logica blijft draaien, Engine-taken
|
|
141
|
+
worden alleen getoond en vergeleken. Elke taak draagt rule_version — een lopende
|
|
142
142
|
order verandert nooit stilletjes mee als de Rule Engine wijzigt.`;
|
|
143
143
|
}
|
|
144
|
-
const STOCK_CONTRACT = `De Engine bepaalt of een bestelling met producten die niet op voorraad zijn
|
|
145
|
-
überhaupt aangemaakt mag worden. Die keuze staat in de Rule Engine
|
|
146
|
-
(Order verwerking -> "Bestellingen uitleveren wanneer een product niet op
|
|
147
|
-
voorraad is"). Beslis dit NOOIT zelf.
|
|
148
|
-
|
|
149
|
-
Roep vóór het opslaan van een nieuwe order (of het wijzigen van de aantallen)
|
|
150
|
-
altijd deze RPC aan:
|
|
151
|
-
|
|
152
|
-
const { data: check } = await supabase.rpc("logistics_check_order_allowed", {
|
|
153
|
-
p_lines: [
|
|
154
|
-
{ productId: "<uuid of artikelnummer of barcode of floriday trade item id>", quantity: 12 },
|
|
155
|
-
],
|
|
156
|
-
p_strategy_id: null, // uuid van logistics_strategies indien bekend
|
|
157
|
-
});
|
|
158
|
-
// check = { allowed, allowBackorder, shortages: [{ productId, product, wanted, available, missing }], reason }
|
|
159
|
-
|
|
160
|
-
Regels:
|
|
161
|
-
- allowed === false -> blokkeer het aanmaken/opslaan van de order volledig en
|
|
162
|
-
toon per regel uit check.shortages:
|
|
163
|
-
"<product>: besteld <wanted>, beschikbaar <available>, tekort <missing>".
|
|
164
|
-
Geen omweg, geen "toch doorgaan"-knop. reason = "insufficient_stock".
|
|
165
|
-
- allowed === true en shortages niet leeg -> order mag wél aangemaakt worden
|
|
166
|
-
(uitleveren zonder voorraad staat aan); de Engine maakt zelf de melding en/of
|
|
167
|
-
e-mail aan. Toon de tekorten alleen ter informatie.
|
|
168
|
-
- Alleen de instelling opvragen (bv. live waarschuwing tijdens typen):
|
|
169
|
-
const { data: mag } = await supabase.rpc("logistics_backorder_allowed", { p_strategy_id: null });
|
|
144
|
+
const STOCK_CONTRACT = `De Engine bepaalt of een bestelling met producten die niet op voorraad zijn
|
|
145
|
+
überhaupt aangemaakt mag worden. Die keuze staat in de Rule Engine
|
|
146
|
+
(Order verwerking -> "Bestellingen uitleveren wanneer een product niet op
|
|
147
|
+
voorraad is"). Beslis dit NOOIT zelf.
|
|
148
|
+
|
|
149
|
+
Roep vóór het opslaan van een nieuwe order (of het wijzigen van de aantallen)
|
|
150
|
+
altijd deze RPC aan:
|
|
151
|
+
|
|
152
|
+
const { data: check } = await supabase.rpc("logistics_check_order_allowed", {
|
|
153
|
+
p_lines: [
|
|
154
|
+
{ productId: "<uuid of artikelnummer of barcode of floriday trade item id>", quantity: 12 },
|
|
155
|
+
],
|
|
156
|
+
p_strategy_id: null, // uuid van logistics_strategies indien bekend
|
|
157
|
+
});
|
|
158
|
+
// check = { allowed, allowBackorder, shortages: [{ productId, product, wanted, available, missing }], reason }
|
|
159
|
+
|
|
160
|
+
Regels:
|
|
161
|
+
- allowed === false -> blokkeer het aanmaken/opslaan van de order volledig en
|
|
162
|
+
toon per regel uit check.shortages:
|
|
163
|
+
"<product>: besteld <wanted>, beschikbaar <available>, tekort <missing>".
|
|
164
|
+
Geen omweg, geen "toch doorgaan"-knop. reason = "insufficient_stock".
|
|
165
|
+
- allowed === true en shortages niet leeg -> order mag wél aangemaakt worden
|
|
166
|
+
(uitleveren zonder voorraad staat aan); de Engine maakt zelf de melding en/of
|
|
167
|
+
e-mail aan. Toon de tekorten alleen ter informatie.
|
|
168
|
+
- Alleen de instelling opvragen (bv. live waarschuwing tijdens typen):
|
|
169
|
+
const { data: mag } = await supabase.rpc("logistics_backorder_allowed", { p_strategy_id: null });
|
|
170
170
|
- Cache het antwoord niet: de instelling kan op elk moment wijzigen.`;
|
|
171
171
|
const MODULES = {
|
|
172
172
|
verkoop: {
|
|
@@ -179,16 +179,16 @@ const MODULES = {
|
|
|
179
179
|
date: "2026-07-24",
|
|
180
180
|
summary: "Orderbufferlogica eruit, events en taken via Supabase.",
|
|
181
181
|
withSharedContract: true,
|
|
182
|
-
body: `Haal weg: alle eigen orderbufferlogica, eigen samenvoegregels en alle
|
|
183
|
-
fetch-calls naar een Engine-URL plus eventuele secrets.
|
|
184
|
-
|
|
185
|
-
Bouw:
|
|
186
|
-
- Bij nieuwe/gewijzigde order een gebeurtenis melden via logistics_emit_event
|
|
187
|
-
(event_type order.received of order.changed).
|
|
188
|
-
- Taken van type buffer.close lezen uit logistics_tasks (owner_module "verkoop"),
|
|
189
|
-
uitvoeren en afmelden via logistics_claim_task + logistics_complete_task.
|
|
190
|
-
- Buffer-samenstelling tonen zoals die in payload staat (matchCriteria, release).
|
|
191
|
-
- release "manual" -> knop Vrijgeven. release "none" -> alleen tonen, niets doen.
|
|
182
|
+
body: `Haal weg: alle eigen orderbufferlogica, eigen samenvoegregels en alle
|
|
183
|
+
fetch-calls naar een Engine-URL plus eventuele secrets.
|
|
184
|
+
|
|
185
|
+
Bouw:
|
|
186
|
+
- Bij nieuwe/gewijzigde order een gebeurtenis melden via logistics_emit_event
|
|
187
|
+
(event_type order.received of order.changed).
|
|
188
|
+
- Taken van type buffer.close lezen uit logistics_tasks (owner_module "verkoop"),
|
|
189
|
+
uitvoeren en afmelden via logistics_claim_task + logistics_complete_task.
|
|
190
|
+
- Buffer-samenstelling tonen zoals die in payload staat (matchCriteria, release).
|
|
191
|
+
- release "manual" -> knop Vrijgeven. release "none" -> alleen tonen, niets doen.
|
|
192
192
|
- In schaduwmodus: Engine-buffersluittijd naast de eigen berekening tonen.`,
|
|
193
193
|
},
|
|
194
194
|
{
|
|
@@ -196,16 +196,16 @@ Bouw:
|
|
|
196
196
|
title: "Voorraadcontrole vóór het aanmaken van een order",
|
|
197
197
|
date: "2026-07-31",
|
|
198
198
|
summary: "Nieuwe eis bovenop prompt 1: order blokkeren als een product niet op voorraad is.",
|
|
199
|
-
body: `AANVULLING op koppelprompt 1 (die blijft gewoon geldig, niets terugdraaien).
|
|
200
|
-
|
|
201
|
-
Nieuwe verplichting: vóór het aanmaken of wijzigen van een order eerst de
|
|
202
|
-
voorraadcontrole van de Engine aanroepen.
|
|
203
|
-
|
|
204
|
-
${STOCK_CONTRACT}
|
|
205
|
-
|
|
206
|
-
In de Verkoop-module concreet:
|
|
207
|
-
- Blokkeer de opslaan-knop van de order zolang allowed false is.
|
|
208
|
-
- Toon de tekorten in het orderscherm, per regel bij het product.
|
|
199
|
+
body: `AANVULLING op koppelprompt 1 (die blijft gewoon geldig, niets terugdraaien).
|
|
200
|
+
|
|
201
|
+
Nieuwe verplichting: vóór het aanmaken of wijzigen van een order eerst de
|
|
202
|
+
voorraadcontrole van de Engine aanroepen.
|
|
203
|
+
|
|
204
|
+
${STOCK_CONTRACT}
|
|
205
|
+
|
|
206
|
+
In de Verkoop-module concreet:
|
|
207
|
+
- Blokkeer de opslaan-knop van de order zolang allowed false is.
|
|
208
|
+
- Toon de tekorten in het orderscherm, per regel bij het product.
|
|
209
209
|
- Doe de controle ook opnieuw bij het wijzigen van aantallen of regels.`,
|
|
210
210
|
},
|
|
211
211
|
{
|
|
@@ -213,51 +213,51 @@ In de Verkoop-module concreet:
|
|
|
213
213
|
title: "Bufferen mag alleen als de Engine dat zegt",
|
|
214
214
|
date: "2026-07-31",
|
|
215
215
|
summary: "Nieuwe eis bovenop prompt 1 en 2: geen eigen bufferbesluit meer, altijd eerst logistics_buffer_decision aanroepen.",
|
|
216
|
-
body: `AANVULLING op koppelprompt 1 en 2 (die blijven gewoon geldig).
|
|
217
|
-
|
|
218
|
-
Probleem: er stonden orders in een orderbuffer terwijl bufferen in de Rule Engine
|
|
219
|
-
UIT stond. De Verkoop-module beslist dat dus nog zelf. Dat moet eruit.
|
|
220
|
-
|
|
221
|
-
Haal weg: elke eigen regel, instelling of code die bepaalt of een order in een
|
|
222
|
-
orderbuffer / gecombineerde order terechtkomt, inclusief automatisch aanmaken of
|
|
223
|
-
toewijzen van een buffer bij het opslaan van een order.
|
|
224
|
-
|
|
225
|
-
Nieuwe verplichting: vraag het per order aan de Engine.
|
|
226
|
-
|
|
227
|
-
const { data: besluit } = await supabase.rpc("logistics_buffer_decision", {
|
|
228
|
-
p_order: {
|
|
229
|
-
orderRef: "SO-12345",
|
|
230
|
-
checkinAt: "2026-08-01T10:00:00Z",
|
|
231
|
-
customerRef: "CUST-1",
|
|
232
|
-
floridayCustomerRef: "FLOR-1",
|
|
233
|
-
bvoCustomerRef: "BVO-1",
|
|
234
|
-
deliveryLocationRef: "LOC-1",
|
|
235
|
-
deliveryDate: "2026-08-01",
|
|
236
|
-
carrierRef: "TRANS-1",
|
|
237
|
-
loadCarrierType: "trolley",
|
|
238
|
-
orderType: "standaard",
|
|
239
|
-
},
|
|
240
|
-
p_strategy_id: null, // uuid van logistics_strategies indien bekend
|
|
241
|
-
});
|
|
242
|
-
// besluit = { buffer, reason, bufferRef, bufferKey, matchCriteria,
|
|
243
|
-
// closeBeforeMinutes, bufferCloseAt, release }
|
|
244
|
-
|
|
245
|
-
Regels:
|
|
246
|
-
- besluit.buffer === false (reason "buffering_disabled") -> de order gaat LOS door.
|
|
247
|
-
Geen buffer aanmaken, geen bestaande buffer toewijzen, geen buffer tonen.
|
|
248
|
-
- besluit.buffer === true -> gebruik exact besluit.bufferRef als buffersleutel.
|
|
249
|
-
Orders met dezelfde bufferRef horen in dezelfde gecombineerde order. Bepaal die
|
|
250
|
-
groepering nooit zelf op eigen criteria.
|
|
251
|
-
- Toon buffersluittijd uit besluit.bufferCloseAt, en de vrijgave uit
|
|
252
|
-
besluit.release ("auto" | "manual" | "none"). Bij "manual" een knop Vrijgeven,
|
|
253
|
-
bij "none" alleen tonen.
|
|
254
|
-
- Cache het antwoord niet: de instelling kan op elk moment wijzigen. Vraag het
|
|
255
|
-
opnieuw bij elke wijziging van de order (aanmeldtijd, klant, locatie, aantallen).
|
|
256
|
-
- Stuur bufferRef mee in de payload van logistics_emit_event (veld bufferRef),
|
|
257
|
-
zodat de Engine en de Verkoop-module dezelfde buffer bedoelen.
|
|
258
|
-
|
|
259
|
-
Eenmalige opschoning: haal bij bestaande, nog niet afgehandelde orders de
|
|
260
|
-
bufferkoppeling weg zodra logistics_buffer_decision voor die order buffer=false
|
|
216
|
+
body: `AANVULLING op koppelprompt 1 en 2 (die blijven gewoon geldig).
|
|
217
|
+
|
|
218
|
+
Probleem: er stonden orders in een orderbuffer terwijl bufferen in de Rule Engine
|
|
219
|
+
UIT stond. De Verkoop-module beslist dat dus nog zelf. Dat moet eruit.
|
|
220
|
+
|
|
221
|
+
Haal weg: elke eigen regel, instelling of code die bepaalt of een order in een
|
|
222
|
+
orderbuffer / gecombineerde order terechtkomt, inclusief automatisch aanmaken of
|
|
223
|
+
toewijzen van een buffer bij het opslaan van een order.
|
|
224
|
+
|
|
225
|
+
Nieuwe verplichting: vraag het per order aan de Engine.
|
|
226
|
+
|
|
227
|
+
const { data: besluit } = await supabase.rpc("logistics_buffer_decision", {
|
|
228
|
+
p_order: {
|
|
229
|
+
orderRef: "SO-12345",
|
|
230
|
+
checkinAt: "2026-08-01T10:00:00Z",
|
|
231
|
+
customerRef: "CUST-1",
|
|
232
|
+
floridayCustomerRef: "FLOR-1",
|
|
233
|
+
bvoCustomerRef: "BVO-1",
|
|
234
|
+
deliveryLocationRef: "LOC-1",
|
|
235
|
+
deliveryDate: "2026-08-01",
|
|
236
|
+
carrierRef: "TRANS-1",
|
|
237
|
+
loadCarrierType: "trolley",
|
|
238
|
+
orderType: "standaard",
|
|
239
|
+
},
|
|
240
|
+
p_strategy_id: null, // uuid van logistics_strategies indien bekend
|
|
241
|
+
});
|
|
242
|
+
// besluit = { buffer, reason, bufferRef, bufferKey, matchCriteria,
|
|
243
|
+
// closeBeforeMinutes, bufferCloseAt, release }
|
|
244
|
+
|
|
245
|
+
Regels:
|
|
246
|
+
- besluit.buffer === false (reason "buffering_disabled") -> de order gaat LOS door.
|
|
247
|
+
Geen buffer aanmaken, geen bestaande buffer toewijzen, geen buffer tonen.
|
|
248
|
+
- besluit.buffer === true -> gebruik exact besluit.bufferRef als buffersleutel.
|
|
249
|
+
Orders met dezelfde bufferRef horen in dezelfde gecombineerde order. Bepaal die
|
|
250
|
+
groepering nooit zelf op eigen criteria.
|
|
251
|
+
- Toon buffersluittijd uit besluit.bufferCloseAt, en de vrijgave uit
|
|
252
|
+
besluit.release ("auto" | "manual" | "none"). Bij "manual" een knop Vrijgeven,
|
|
253
|
+
bij "none" alleen tonen.
|
|
254
|
+
- Cache het antwoord niet: de instelling kan op elk moment wijzigen. Vraag het
|
|
255
|
+
opnieuw bij elke wijziging van de order (aanmeldtijd, klant, locatie, aantallen).
|
|
256
|
+
- Stuur bufferRef mee in de payload van logistics_emit_event (veld bufferRef),
|
|
257
|
+
zodat de Engine en de Verkoop-module dezelfde buffer bedoelen.
|
|
258
|
+
|
|
259
|
+
Eenmalige opschoning: haal bij bestaande, nog niet afgehandelde orders de
|
|
260
|
+
bufferkoppeling weg zodra logistics_buffer_decision voor die order buffer=false
|
|
261
261
|
teruggeeft. Al verwerkte/verzonden orders laat je met rust.`,
|
|
262
262
|
},
|
|
263
263
|
{
|
|
@@ -265,33 +265,33 @@ teruggeeft. Al verwerkte/verzonden orders laat je met rust.`,
|
|
|
265
265
|
title: "Correctie bufferbesluit: nieuwe velden en uitleg",
|
|
266
266
|
date: "2026-08-02",
|
|
267
267
|
summary: "Nieuwe eis bovenop prompt 3: logistics_buffer_decision is gecorrigeerd, stuur alle matchvelden mee en gebruik de uitleg (trace).",
|
|
268
|
-
body: `AANVULLING op koppelprompt 1, 2 en 3 (die blijven gewoon geldig).
|
|
269
|
-
|
|
270
|
-
Wat er is gewijzigd aan de Engine-kant:
|
|
271
|
-
- logistics_buffer_decision las de Rule Engine-instellingen fout uit en negeerde de
|
|
272
|
-
aangevinkte criteria. Dat is opgelost: de gekozen criteria worden nu echt vergeleken.
|
|
273
|
-
- De buffersleutel bevat niet langer het exacte sluitmoment. Orders met dezelfde
|
|
274
|
-
gegevens maar een iets andere aanmeldtijd komen nu wél in dezelfde buffer.
|
|
275
|
-
- De functie heeft een derde parameter p_user_id (laat die weg of op null staan).
|
|
276
|
-
- Het antwoord bevat nu ook een veld trace: per criterium waarom het klopt of niet.
|
|
277
|
-
|
|
278
|
-
Wat de Verkoop-module moet doen:
|
|
279
|
-
1. Stuur bij elke aanroep ALLE velden mee die als criterium gekozen kunnen zijn.
|
|
280
|
-
Ontbreekt een waarde van een aangevinkt criterium, dan combineert de Engine de
|
|
281
|
-
order bewust NIET (reason "buffering_enabled_missing_data").
|
|
282
|
-
Verplichte velden in p_order:
|
|
283
|
-
orderRef, checkinAt, deliveryDate, customerRef, floridayCustomerRef,
|
|
284
|
-
bvoCustomerRef, deliveryLocationRef, carrierRef, loadCarrierType, orderType
|
|
285
|
-
deliveryLocationRef moet een stabiele sleutel zijn van het afleveradres
|
|
286
|
-
(locatie-id of genormaliseerd adres), niet een vrije tekst die per order verschilt.
|
|
287
|
-
2. Toon in het orderscherm de reden uit besluit.reason en, bij twijfel, de regels uit
|
|
288
|
-
besluit.trace ("waarom zit deze order niet bij die andere order?").
|
|
289
|
-
3. Vraag het besluit opnieuw op zodra een van bovenstaande velden wijzigt, en
|
|
290
|
-
verplaats de order dan naar de nieuwe bufferRef.
|
|
291
|
-
4. Bepaal nooit zelf of twee orders bij elkaar horen; vergelijk alleen bufferRef.
|
|
292
|
-
|
|
293
|
-
Eenmalige opschoning: haal voor alle nog niet verwerkte orders opnieuw het besluit op
|
|
294
|
-
en werk de bufferkoppeling bij. Orders die volgens de Engine samen horen, moeten daarna
|
|
268
|
+
body: `AANVULLING op koppelprompt 1, 2 en 3 (die blijven gewoon geldig).
|
|
269
|
+
|
|
270
|
+
Wat er is gewijzigd aan de Engine-kant:
|
|
271
|
+
- logistics_buffer_decision las de Rule Engine-instellingen fout uit en negeerde de
|
|
272
|
+
aangevinkte criteria. Dat is opgelost: de gekozen criteria worden nu echt vergeleken.
|
|
273
|
+
- De buffersleutel bevat niet langer het exacte sluitmoment. Orders met dezelfde
|
|
274
|
+
gegevens maar een iets andere aanmeldtijd komen nu wél in dezelfde buffer.
|
|
275
|
+
- De functie heeft een derde parameter p_user_id (laat die weg of op null staan).
|
|
276
|
+
- Het antwoord bevat nu ook een veld trace: per criterium waarom het klopt of niet.
|
|
277
|
+
|
|
278
|
+
Wat de Verkoop-module moet doen:
|
|
279
|
+
1. Stuur bij elke aanroep ALLE velden mee die als criterium gekozen kunnen zijn.
|
|
280
|
+
Ontbreekt een waarde van een aangevinkt criterium, dan combineert de Engine de
|
|
281
|
+
order bewust NIET (reason "buffering_enabled_missing_data").
|
|
282
|
+
Verplichte velden in p_order:
|
|
283
|
+
orderRef, checkinAt, deliveryDate, customerRef, floridayCustomerRef,
|
|
284
|
+
bvoCustomerRef, deliveryLocationRef, carrierRef, loadCarrierType, orderType
|
|
285
|
+
deliveryLocationRef moet een stabiele sleutel zijn van het afleveradres
|
|
286
|
+
(locatie-id of genormaliseerd adres), niet een vrije tekst die per order verschilt.
|
|
287
|
+
2. Toon in het orderscherm de reden uit besluit.reason en, bij twijfel, de regels uit
|
|
288
|
+
besluit.trace ("waarom zit deze order niet bij die andere order?").
|
|
289
|
+
3. Vraag het besluit opnieuw op zodra een van bovenstaande velden wijzigt, en
|
|
290
|
+
verplaats de order dan naar de nieuwe bufferRef.
|
|
291
|
+
4. Bepaal nooit zelf of twee orders bij elkaar horen; vergelijk alleen bufferRef.
|
|
292
|
+
|
|
293
|
+
Eenmalige opschoning: haal voor alle nog niet verwerkte orders opnieuw het besluit op
|
|
294
|
+
en werk de bufferkoppeling bij. Orders die volgens de Engine samen horen, moeten daarna
|
|
295
295
|
dezelfde bufferRef hebben.`,
|
|
296
296
|
},
|
|
297
297
|
{
|
|
@@ -299,44 +299,44 @@ dezelfde bufferRef hebben.`,
|
|
|
299
299
|
title: "Alleen ladingdragers tonen die de Engine toestaat",
|
|
300
300
|
date: "2026-08-03",
|
|
301
301
|
summary: "Nieuwe eis bovenop prompt 1 t/m 4: uitgeschakelde ladingdragers mogen niet meer kiesbaar zijn.",
|
|
302
|
-
body: `AANVULLING op koppelprompt 1, 2, 3 en 4 (die blijven gewoon geldig).
|
|
303
|
-
|
|
304
|
-
In de Rule Engine (stap Beladingindeling) staat welke ladingdragers zijn toegestaan.
|
|
305
|
-
Staat een ladingdrager uit, dan mag die in de Verkoop-module nergens meer te kiezen
|
|
306
|
-
zijn.
|
|
307
|
-
|
|
308
|
-
Haal weg: elke eigen, vaste lijst met ladingdragers / verzendmethodes in de code,
|
|
309
|
-
in constanten, in dropdowns of in filters.
|
|
310
|
-
|
|
311
|
-
Nieuwe verplichting: haal de lijst op bij de Engine.
|
|
312
|
-
|
|
313
|
-
const { data: dragers } = await supabase.rpc("logistics_allowed_load_carriers", {
|
|
314
|
-
p_strategy_id: null, // uuid van logistics_strategies indien bekend
|
|
315
|
-
});
|
|
316
|
-
// dragers = {
|
|
317
|
-
// allowed: ["trolley","pallet"],
|
|
318
|
-
// default: "trolley",
|
|
319
|
-
// carriers: [{ code, label, enabled, isDefault }, ...]
|
|
320
|
-
// }
|
|
321
|
-
|
|
322
|
-
Codes en namen (gebruik exact deze codes):
|
|
323
|
-
trolley Stapelwagen
|
|
324
|
-
danish_container Deense container
|
|
325
|
-
euro_rolcontainer Euro-rolcontainer
|
|
326
|
-
pallet Pallet
|
|
327
|
-
euro_pallet Euro-pallet
|
|
328
|
-
loose Geen ladingdrager
|
|
329
|
-
|
|
330
|
-
Regels:
|
|
331
|
-
- Toon in elk keuzeveld (order, orderregel, verzendmethode, filter) alleen de
|
|
332
|
-
dragers met enabled === true. Uitgeschakelde dragers niet grijs tonen: weglaten.
|
|
333
|
-
- Voorselectie = dragers.default.
|
|
334
|
-
- Blokkeer opslaan als een order een ladingdrager heeft die niet in allowed staat,
|
|
335
|
-
met melding: "Deze ladingdrager is uitgeschakeld in de Logistics Engine."
|
|
336
|
-
- Cache de lijst niet langer dan één schermsessie; de instelling kan wijzigen.
|
|
337
|
-
- Bestaande, nog niet verwerkte orders met een inmiddels uitgeschakelde drager:
|
|
338
|
-
markeer die in het overzicht zodat een medewerker een andere drager kiest.
|
|
339
|
-
- Stuur loadCarrierType in logistics_emit_event en logistics_buffer_decision altijd
|
|
302
|
+
body: `AANVULLING op koppelprompt 1, 2, 3 en 4 (die blijven gewoon geldig).
|
|
303
|
+
|
|
304
|
+
In de Rule Engine (stap Beladingindeling) staat welke ladingdragers zijn toegestaan.
|
|
305
|
+
Staat een ladingdrager uit, dan mag die in de Verkoop-module nergens meer te kiezen
|
|
306
|
+
zijn.
|
|
307
|
+
|
|
308
|
+
Haal weg: elke eigen, vaste lijst met ladingdragers / verzendmethodes in de code,
|
|
309
|
+
in constanten, in dropdowns of in filters.
|
|
310
|
+
|
|
311
|
+
Nieuwe verplichting: haal de lijst op bij de Engine.
|
|
312
|
+
|
|
313
|
+
const { data: dragers } = await supabase.rpc("logistics_allowed_load_carriers", {
|
|
314
|
+
p_strategy_id: null, // uuid van logistics_strategies indien bekend
|
|
315
|
+
});
|
|
316
|
+
// dragers = {
|
|
317
|
+
// allowed: ["trolley","pallet"],
|
|
318
|
+
// default: "trolley",
|
|
319
|
+
// carriers: [{ code, label, enabled, isDefault }, ...]
|
|
320
|
+
// }
|
|
321
|
+
|
|
322
|
+
Codes en namen (gebruik exact deze codes):
|
|
323
|
+
trolley Stapelwagen
|
|
324
|
+
danish_container Deense container
|
|
325
|
+
euro_rolcontainer Euro-rolcontainer
|
|
326
|
+
pallet Pallet
|
|
327
|
+
euro_pallet Euro-pallet
|
|
328
|
+
loose Geen ladingdrager
|
|
329
|
+
|
|
330
|
+
Regels:
|
|
331
|
+
- Toon in elk keuzeveld (order, orderregel, verzendmethode, filter) alleen de
|
|
332
|
+
dragers met enabled === true. Uitgeschakelde dragers niet grijs tonen: weglaten.
|
|
333
|
+
- Voorselectie = dragers.default.
|
|
334
|
+
- Blokkeer opslaan als een order een ladingdrager heeft die niet in allowed staat,
|
|
335
|
+
met melding: "Deze ladingdrager is uitgeschakeld in de Logistics Engine."
|
|
336
|
+
- Cache de lijst niet langer dan één schermsessie; de instelling kan wijzigen.
|
|
337
|
+
- Bestaande, nog niet verwerkte orders met een inmiddels uitgeschakelde drager:
|
|
338
|
+
markeer die in het overzicht zodat een medewerker een andere drager kiest.
|
|
339
|
+
- Stuur loadCarrierType in logistics_emit_event en logistics_buffer_decision altijd
|
|
340
340
|
met een van bovenstaande codes mee, nooit met een eigen naam of vrije tekst.`,
|
|
341
341
|
},
|
|
342
342
|
{
|
|
@@ -344,55 +344,55 @@ Regels:
|
|
|
344
344
|
title: "Karindeling: eigen planner eruit, Engine-planner erin",
|
|
345
345
|
date: "2026-08-27",
|
|
346
346
|
summary: "Nieuwe eis bovenop prompt 1 t/m 5: /api/public/cron/replan-carts schrijft nog eigen karren met algorithm_version 1 en valt terug op 1×1×1.",
|
|
347
|
-
body: `AANVULLING op koppelprompt 1 t/m 5 (die blijven gewoon geldig).
|
|
348
|
-
|
|
349
|
-
GEMETEN PROBLEEM (Mathot productie, 27-08-2026)
|
|
350
|
-
public.order_carts bevat 11.560 rijen met algorithm_version = 1, nog steeds
|
|
351
|
-
groeiend (laatste 13:12:59). Zetten we cron 113 (elke minuut naar
|
|
352
|
-
/api/public/cron/replan-carts) uit, dan stopt de aanwas onmiddellijk. De
|
|
353
|
-
schrijver is dus de Verkoop-module.
|
|
354
|
-
|
|
355
|
-
Bewijs in de Verkoop-module:
|
|
356
|
-
- src/lib/cart-replan.functions.ts, regel ~178-190: INSERT in order_carts met
|
|
357
|
-
algorithm_version: CART_PLANNER_VERSION.
|
|
358
|
-
- src/lib/cart-planner.ts, regel 14: export const CART_PLANNER_VERSION = 1.
|
|
359
|
-
- src/lib/cart-replan.functions.ts, regel ~208: INSERT in order_cart_items.
|
|
360
|
-
- src/lib/create-order.functions.ts, regel ~1196 + ~1203 en ~1296 + ~1313:
|
|
361
|
-
INSERTs die algorithm_version en source helemaal niet zetten, dus de
|
|
362
|
-
kolomdefaults ('auto', 1) gebruiken.
|
|
363
|
-
- Dit pad rekent zélf (planCarts uit src/lib/cart-planner.ts). Het roept de
|
|
364
|
-
gedeelde Engine-planner (loadCarrierPlanning / planByFloridayPacking,
|
|
365
|
-
LOAD_CARRIER_PLANNER_VERSION = 3) NIET aan.
|
|
366
|
-
- Terugval bij ontbrekende belading: in de mapping naar PlannerInputItem staat
|
|
367
|
-
overal \`?? 1\` (plants_per_crate, crates_per_layer, layers_per_cart). Bij een
|
|
368
|
-
order zonder bekende belading levert dat stilzwijgend 1×1×1 op — precies wat de
|
|
369
|
-
beslisregel van 26-08 verbiedt. De guard (B1/B2/B3) zit niet in dit pad.
|
|
370
|
-
|
|
371
|
-
WAT ER MOET GEBEUREN — voorkeur A, minimaal B.
|
|
372
|
-
|
|
373
|
-
A (voorkeur). Laat /api/public/cron/replan-carts niet meer zelf rekenen.
|
|
374
|
-
Roep de gedeelde planner van de Logistics Engine aan
|
|
375
|
-
(@flowselections/logistiek-engine → loadCarrierPlanning /
|
|
376
|
-
planByFloridayPacking) en schrijf uitsluitend het resultaat weg. Verwijder
|
|
377
|
-
src/lib/cart-planner.ts als schrijfpad. Reden: één rekenhart, dus geen derde
|
|
378
|
-
afwijkende indeling naast TS en SQL.
|
|
379
|
-
|
|
380
|
-
B (alleen als A nu te groot is, en dan als tussenstap):
|
|
381
|
-
- Zet in ELKE INSERT in order_carts expliciet
|
|
382
|
-
algorithm_version: LOAD_CARRIER_PLANNER_VERSION (nu 3) en source
|
|
383
|
-
('auto' | 'manual' | 'floriday'). Ook in create-order.functions.ts regel
|
|
384
|
-
~1196 en ~1296. Vertrouw nooit op de kolomdefault.
|
|
385
|
-
- Neem dezelfde guard over als de Engine: is de belading van een orderregel
|
|
386
|
-
onbekend (geen plants_per_crate / crates_per_layer / layers_per_cart op de
|
|
387
|
-
regel én niet op het product), dan wordt die regel NIET ingedeeld. Geen
|
|
388
|
-
\`?? 1\`, nooit terugvallen op 1×1×1. Meld het als blokkade op de order,
|
|
389
|
-
zodat een medewerker de belading invult.
|
|
390
|
-
- Verwijder alle bestaande rijen met algorithm_version < 3 pas nadat A of B
|
|
391
|
-
live is; anders komen ze binnen een minuut terug.
|
|
392
|
-
|
|
393
|
-
NIET DOEN
|
|
394
|
-
- De kolomdefaults van order_carts niet weghalen en algorithm_version niet
|
|
395
|
-
NOT NULL maken; dat kan pas als alle schrijfpaden de kolom zetten.
|
|
347
|
+
body: `AANVULLING op koppelprompt 1 t/m 5 (die blijven gewoon geldig).
|
|
348
|
+
|
|
349
|
+
GEMETEN PROBLEEM (Mathot productie, 27-08-2026)
|
|
350
|
+
public.order_carts bevat 11.560 rijen met algorithm_version = 1, nog steeds
|
|
351
|
+
groeiend (laatste 13:12:59). Zetten we cron 113 (elke minuut naar
|
|
352
|
+
/api/public/cron/replan-carts) uit, dan stopt de aanwas onmiddellijk. De
|
|
353
|
+
schrijver is dus de Verkoop-module.
|
|
354
|
+
|
|
355
|
+
Bewijs in de Verkoop-module:
|
|
356
|
+
- src/lib/cart-replan.functions.ts, regel ~178-190: INSERT in order_carts met
|
|
357
|
+
algorithm_version: CART_PLANNER_VERSION.
|
|
358
|
+
- src/lib/cart-planner.ts, regel 14: export const CART_PLANNER_VERSION = 1.
|
|
359
|
+
- src/lib/cart-replan.functions.ts, regel ~208: INSERT in order_cart_items.
|
|
360
|
+
- src/lib/create-order.functions.ts, regel ~1196 + ~1203 en ~1296 + ~1313:
|
|
361
|
+
INSERTs die algorithm_version en source helemaal niet zetten, dus de
|
|
362
|
+
kolomdefaults ('auto', 1) gebruiken.
|
|
363
|
+
- Dit pad rekent zélf (planCarts uit src/lib/cart-planner.ts). Het roept de
|
|
364
|
+
gedeelde Engine-planner (loadCarrierPlanning / planByFloridayPacking,
|
|
365
|
+
LOAD_CARRIER_PLANNER_VERSION = 3) NIET aan.
|
|
366
|
+
- Terugval bij ontbrekende belading: in de mapping naar PlannerInputItem staat
|
|
367
|
+
overal \`?? 1\` (plants_per_crate, crates_per_layer, layers_per_cart). Bij een
|
|
368
|
+
order zonder bekende belading levert dat stilzwijgend 1×1×1 op — precies wat de
|
|
369
|
+
beslisregel van 26-08 verbiedt. De guard (B1/B2/B3) zit niet in dit pad.
|
|
370
|
+
|
|
371
|
+
WAT ER MOET GEBEUREN — voorkeur A, minimaal B.
|
|
372
|
+
|
|
373
|
+
A (voorkeur). Laat /api/public/cron/replan-carts niet meer zelf rekenen.
|
|
374
|
+
Roep de gedeelde planner van de Logistics Engine aan
|
|
375
|
+
(@flowselections/logistiek-engine → loadCarrierPlanning /
|
|
376
|
+
planByFloridayPacking) en schrijf uitsluitend het resultaat weg. Verwijder
|
|
377
|
+
src/lib/cart-planner.ts als schrijfpad. Reden: één rekenhart, dus geen derde
|
|
378
|
+
afwijkende indeling naast TS en SQL.
|
|
379
|
+
|
|
380
|
+
B (alleen als A nu te groot is, en dan als tussenstap):
|
|
381
|
+
- Zet in ELKE INSERT in order_carts expliciet
|
|
382
|
+
algorithm_version: LOAD_CARRIER_PLANNER_VERSION (nu 3) en source
|
|
383
|
+
('auto' | 'manual' | 'floriday'). Ook in create-order.functions.ts regel
|
|
384
|
+
~1196 en ~1296. Vertrouw nooit op de kolomdefault.
|
|
385
|
+
- Neem dezelfde guard over als de Engine: is de belading van een orderregel
|
|
386
|
+
onbekend (geen plants_per_crate / crates_per_layer / layers_per_cart op de
|
|
387
|
+
regel én niet op het product), dan wordt die regel NIET ingedeeld. Geen
|
|
388
|
+
\`?? 1\`, nooit terugvallen op 1×1×1. Meld het als blokkade op de order,
|
|
389
|
+
zodat een medewerker de belading invult.
|
|
390
|
+
- Verwijder alle bestaande rijen met algorithm_version < 3 pas nadat A of B
|
|
391
|
+
live is; anders komen ze binnen een minuut terug.
|
|
392
|
+
|
|
393
|
+
NIET DOEN
|
|
394
|
+
- De kolomdefaults van order_carts niet weghalen en algorithm_version niet
|
|
395
|
+
NOT NULL maken; dat kan pas als alle schrijfpaden de kolom zetten.
|
|
396
396
|
- De beslisregel van 26-08 (B1/B2/B3) niet wijzigen — alleen overnemen.`,
|
|
397
397
|
},
|
|
398
398
|
{
|
|
@@ -400,40 +400,40 @@ NIET DOEN
|
|
|
400
400
|
title: "Orderoverzicht uit de Engine: één waarheid voor alle modules",
|
|
401
401
|
date: "2026-09-01",
|
|
402
402
|
summary: "De verkooplijst toont karren, planten en pickdag uit logistics_order_overview, zodat Verkoop, Afhandeling en Pick exact dezelfde cijfers laten zien.",
|
|
403
|
-
body: `AANVULLING op koppelprompt 1 t/m 6 (die blijven geldig).
|
|
404
|
-
|
|
405
|
-
WAAROM
|
|
406
|
-
Elke module telde tot nu toe zelf karren: de pick agenda telde payload-velden van
|
|
407
|
-
taken (3517 karren), Controle karren telde cart_numbers (27) en Verkoop telde
|
|
408
|
-
order_carts. Drie tellingen, drie antwoorden. De Engine heeft nu één index:
|
|
409
|
-
public.logistics_cart_index. Alle schermen lezen daaruit.
|
|
410
|
-
|
|
411
|
-
BOUW DIT
|
|
412
|
-
- Haal de orderlijst op met:
|
|
413
|
-
|
|
414
|
-
const { data, error } = await supabase.rpc("logistics_order_overview", {
|
|
415
|
-
p_from: null, p_to: null,
|
|
416
|
-
});
|
|
417
|
-
if (error) throw new Error(error.message);
|
|
418
|
-
const orders = Array.isArray(data) ? data : [];
|
|
419
|
-
|
|
420
|
-
- Kolommen: order_uuid, order_number, customer_name, order_source,
|
|
421
|
-
delivery_date, status, pick_date, cart_count, plant_count, shifted,
|
|
422
|
-
printed_at.
|
|
423
|
-
- Toon cart_count en plant_count exact zoals ze binnenkomen; niet zelf
|
|
424
|
-
hertellen uit order_carts of order_items.
|
|
425
|
-
- pick_date is de pickdag van de Engine; die ligt nooit in het verleden.
|
|
426
|
-
- shifted = true toont het label "te laat aangemeld".
|
|
427
|
-
- printed_at gevuld = de order is al uitgeprint.
|
|
428
|
-
|
|
429
|
-
NIET DOEN
|
|
430
|
-
- Geen eigen count op order_carts / order_cart_items voor weergave.
|
|
431
|
-
- Geen eigen pickdagberekening uit delivery_date.
|
|
432
|
-
- Geen datum, project-ref of Supabase-URL hardcoden.
|
|
433
|
-
|
|
434
|
-
CONTROLELIJST
|
|
435
|
-
[ ] Karrenaantal in Verkoop is gelijk aan dat in de pick agenda en in Controle.
|
|
436
|
-
[ ] Een gemengde kar telt bij elke deelnemende order mee, maar per dag één keer.
|
|
403
|
+
body: `AANVULLING op koppelprompt 1 t/m 6 (die blijven geldig).
|
|
404
|
+
|
|
405
|
+
WAAROM
|
|
406
|
+
Elke module telde tot nu toe zelf karren: de pick agenda telde payload-velden van
|
|
407
|
+
taken (3517 karren), Controle karren telde cart_numbers (27) en Verkoop telde
|
|
408
|
+
order_carts. Drie tellingen, drie antwoorden. De Engine heeft nu één index:
|
|
409
|
+
public.logistics_cart_index. Alle schermen lezen daaruit.
|
|
410
|
+
|
|
411
|
+
BOUW DIT
|
|
412
|
+
- Haal de orderlijst op met:
|
|
413
|
+
|
|
414
|
+
const { data, error } = await supabase.rpc("logistics_order_overview", {
|
|
415
|
+
p_from: null, p_to: null,
|
|
416
|
+
});
|
|
417
|
+
if (error) throw new Error(error.message);
|
|
418
|
+
const orders = Array.isArray(data) ? data : [];
|
|
419
|
+
|
|
420
|
+
- Kolommen: order_uuid, order_number, customer_name, order_source,
|
|
421
|
+
delivery_date, status, pick_date, cart_count, plant_count, shifted,
|
|
422
|
+
printed_at.
|
|
423
|
+
- Toon cart_count en plant_count exact zoals ze binnenkomen; niet zelf
|
|
424
|
+
hertellen uit order_carts of order_items.
|
|
425
|
+
- pick_date is de pickdag van de Engine; die ligt nooit in het verleden.
|
|
426
|
+
- shifted = true toont het label "te laat aangemeld".
|
|
427
|
+
- printed_at gevuld = de order is al uitgeprint.
|
|
428
|
+
|
|
429
|
+
NIET DOEN
|
|
430
|
+
- Geen eigen count op order_carts / order_cart_items voor weergave.
|
|
431
|
+
- Geen eigen pickdagberekening uit delivery_date.
|
|
432
|
+
- Geen datum, project-ref of Supabase-URL hardcoden.
|
|
433
|
+
|
|
434
|
+
CONTROLELIJST
|
|
435
|
+
[ ] Karrenaantal in Verkoop is gelijk aan dat in de pick agenda en in Controle.
|
|
436
|
+
[ ] Een gemengde kar telt bij elke deelnemende order mee, maar per dag één keer.
|
|
437
437
|
[ ] Verwijderde orders verdwijnen uit de lijst zonder losse taken achter te laten.`,
|
|
438
438
|
},
|
|
439
439
|
{
|
|
@@ -441,29 +441,29 @@ CONTROLELIJST
|
|
|
441
441
|
title: "Statusvelden en leverdatum in het orderoverzicht",
|
|
442
442
|
date: "2026-09-01",
|
|
443
443
|
summary: "logistics_order_overview blijft de enige lijst; de karindex levert nu ook aangemeld/geprint/gecontroleerd en de leverdatum.",
|
|
444
|
-
body: `AANVULLING op prompt 1 t/m 7 (die blijven geldig).
|
|
445
|
-
|
|
446
|
-
WAT ER VERANDERT
|
|
447
|
-
public.logistics_cart_index geeft per (order, kar) nu ook:
|
|
448
|
-
delivery_date, is_announced, is_printed, is_controlled.
|
|
449
|
-
Daarop draaien logistics_pick_agenda, logistics_delivery_agenda,
|
|
450
|
-
control_get_todays_carts, logistics_order_overview en het Picking Station.
|
|
451
|
-
|
|
452
|
-
BOUW DIT
|
|
453
|
-
- Blijf de orderlijst uitsluitend uit logistics_order_overview halen.
|
|
454
|
-
- Wil je voortgang per order tonen, lees dan de statusvelden uit de index of
|
|
455
|
-
uit logistics_delivery_agenda; bereken zelf niets bij.
|
|
456
|
-
- Een filter op status (bijv. "alleen nog niet geprint") mag regels verbergen,
|
|
457
|
-
maar nooit het totaal aan karren veranderen.
|
|
458
|
-
|
|
459
|
-
CONTROLE OP AFWIJKING
|
|
460
|
-
const { data } = await supabase.rpc("logistics_consistency_check");
|
|
461
|
-
Velden: agenda_carts, control_carts, raw_carts, delivery_carts, station_carts,
|
|
462
|
-
sales_carts, announced_carts, orphan_tasks, ok.
|
|
463
|
-
Is ok === false, toon een discrete melding en corrigeer niets zelf.
|
|
464
|
-
|
|
465
|
-
CONTROLELIJST
|
|
466
|
-
[ ] Verkoop, pick agenda, lever agenda, controle en picking station tonen hetzelfde aantal.
|
|
444
|
+
body: `AANVULLING op prompt 1 t/m 7 (die blijven geldig).
|
|
445
|
+
|
|
446
|
+
WAT ER VERANDERT
|
|
447
|
+
public.logistics_cart_index geeft per (order, kar) nu ook:
|
|
448
|
+
delivery_date, is_announced, is_printed, is_controlled.
|
|
449
|
+
Daarop draaien logistics_pick_agenda, logistics_delivery_agenda,
|
|
450
|
+
control_get_todays_carts, logistics_order_overview en het Picking Station.
|
|
451
|
+
|
|
452
|
+
BOUW DIT
|
|
453
|
+
- Blijf de orderlijst uitsluitend uit logistics_order_overview halen.
|
|
454
|
+
- Wil je voortgang per order tonen, lees dan de statusvelden uit de index of
|
|
455
|
+
uit logistics_delivery_agenda; bereken zelf niets bij.
|
|
456
|
+
- Een filter op status (bijv. "alleen nog niet geprint") mag regels verbergen,
|
|
457
|
+
maar nooit het totaal aan karren veranderen.
|
|
458
|
+
|
|
459
|
+
CONTROLE OP AFWIJKING
|
|
460
|
+
const { data } = await supabase.rpc("logistics_consistency_check");
|
|
461
|
+
Velden: agenda_carts, control_carts, raw_carts, delivery_carts, station_carts,
|
|
462
|
+
sales_carts, announced_carts, orphan_tasks, ok.
|
|
463
|
+
Is ok === false, toon een discrete melding en corrigeer niets zelf.
|
|
464
|
+
|
|
465
|
+
CONTROLELIJST
|
|
466
|
+
[ ] Verkoop, pick agenda, lever agenda, controle en picking station tonen hetzelfde aantal.
|
|
467
467
|
[ ] Geen eigen kartelling meer in de verkoopcode.`,
|
|
468
468
|
},
|
|
469
469
|
{
|
|
@@ -471,31 +471,244 @@ CONTROLELIJST
|
|
|
471
471
|
title: "Stamgegevens voor indelen op afmetingen",
|
|
472
472
|
date: "2026-09-03",
|
|
473
473
|
summary: "Producten krijgen een fusttype en een planthoogte, zodat de Engine op fysieke afmetingen kan indelen.",
|
|
474
|
-
body: `AANVULLING op prompt 1 t/m 8 (die blijven geldig).
|
|
475
|
-
|
|
476
|
-
WAT ER VERANDERT
|
|
477
|
-
De Logistiek Engine kent één globale instelling "Methode voor karrenindeling":
|
|
478
|
-
"belading" (huidig gedrag) of "afmetingen". Bij "afmetingen" rekent de Engine
|
|
479
|
-
met echte maten en verzint hij niets.
|
|
480
|
-
|
|
481
|
-
WAT JIJ BOUWT
|
|
482
|
-
1. In het productbeheer twee velden tonen en opslaan op public.products:
|
|
483
|
-
- fust_type_id -> keuzelijst uit public.fust_types (naam tonen)
|
|
484
|
-
- plant_height_cm -> hoogte van de plant boven het fust, in centimeters
|
|
485
|
-
Beide mogen leeg blijven; ze zijn alleen nodig bij methode "afmetingen".
|
|
486
|
-
2. Toon per product een discrete markering "afmetingen onvolledig" wanneer
|
|
487
|
-
fust_type_id of plant_height_cm leeg is. Geen standaardwaarde invullen.
|
|
488
|
-
3. Verzin nooit maten en kopieer ze niet van een ander product.
|
|
489
|
-
|
|
490
|
-
WAT JE NIET DOET
|
|
491
|
-
- Geen keuze per order voor de indelingsmethode: die staat alleen in de Engine.
|
|
492
|
-
- Geen eigen karrenberekening; de Engine blijft de enige bron.
|
|
493
|
-
|
|
494
|
-
CONTROLELIJST
|
|
495
|
-
[ ] Fusttype en planthoogte zijn per product in te vullen en op te slaan.
|
|
496
|
-
[ ] Producten met ontbrekende maten zijn herkenbaar in de lijst.
|
|
474
|
+
body: `AANVULLING op prompt 1 t/m 8 (die blijven geldig).
|
|
475
|
+
|
|
476
|
+
WAT ER VERANDERT
|
|
477
|
+
De Logistiek Engine kent één globale instelling "Methode voor karrenindeling":
|
|
478
|
+
"belading" (huidig gedrag) of "afmetingen". Bij "afmetingen" rekent de Engine
|
|
479
|
+
met echte maten en verzint hij niets.
|
|
480
|
+
|
|
481
|
+
WAT JIJ BOUWT
|
|
482
|
+
1. In het productbeheer twee velden tonen en opslaan op public.products:
|
|
483
|
+
- fust_type_id -> keuzelijst uit public.fust_types (naam tonen)
|
|
484
|
+
- plant_height_cm -> hoogte van de plant boven het fust, in centimeters
|
|
485
|
+
Beide mogen leeg blijven; ze zijn alleen nodig bij methode "afmetingen".
|
|
486
|
+
2. Toon per product een discrete markering "afmetingen onvolledig" wanneer
|
|
487
|
+
fust_type_id of plant_height_cm leeg is. Geen standaardwaarde invullen.
|
|
488
|
+
3. Verzin nooit maten en kopieer ze niet van een ander product.
|
|
489
|
+
|
|
490
|
+
WAT JE NIET DOET
|
|
491
|
+
- Geen keuze per order voor de indelingsmethode: die staat alleen in de Engine.
|
|
492
|
+
- Geen eigen karrenberekening; de Engine blijft de enige bron.
|
|
493
|
+
|
|
494
|
+
CONTROLELIJST
|
|
495
|
+
[ ] Fusttype en planthoogte zijn per product in te vullen en op te slaan.
|
|
496
|
+
[ ] Producten met ontbrekende maten zijn herkenbaar in de lijst.
|
|
497
497
|
[ ] Geen standaardwaardes of gekopieerde maten.`,
|
|
498
498
|
},
|
|
499
|
+
{
|
|
500
|
+
number: 10,
|
|
501
|
+
title: "Gesloten orderbuffer neemt geen orders meer op",
|
|
502
|
+
date: "2026-09-03",
|
|
503
|
+
summary: "De Engine sluit een gecombineerde order op het ingestelde moment; daarna start een nieuwe combinatie.",
|
|
504
|
+
body: `AANVULLING op prompt 1 t/m 9 (die blijven geldig).
|
|
505
|
+
|
|
506
|
+
WAT ER VERANDERT
|
|
507
|
+
In de Rule Engine staat nu waar het sluitmoment vandaan komt: de aanmeldtijd of
|
|
508
|
+
de start van het picken. Zodra dat moment is bereikt — of de order al richting
|
|
509
|
+
het pickstation is — is de buffer gesloten. Een nieuwe order krijgt dan een
|
|
510
|
+
nieuwe combinatie in plaats van de gesloten buffer.
|
|
511
|
+
|
|
512
|
+
WAT JIJ BOUWT
|
|
513
|
+
1. Toon per order het sluitmoment uit het bufferbesluit: velden bufferCloseAt,
|
|
514
|
+
closeBeforeMinutes en closeReference ("checkin" of "pick_start").
|
|
515
|
+
2. Toon "Buffer gesloten" zodra bufferCloseAt is gepasseerd, en meld dat de order
|
|
516
|
+
in een nieuwe combinatie komt. Nooit zelf een order aan een gesloten buffer
|
|
517
|
+
toevoegen of het sluitmoment zelf berekenen.
|
|
518
|
+
3. Blijf het besluit ophalen bij de Engine (logistics_buffer_decision of /decision).
|
|
519
|
+
|
|
520
|
+
CONTROLELIJST
|
|
521
|
+
[ ] Sluitmoment en de reden ervan zijn zichtbaar bij de order.
|
|
522
|
+
[ ] Na sluiting komen nieuwe orders zichtbaar in een nieuwe combinatie.
|
|
523
|
+
[ ] Geen eigen berekening van het sluitmoment.`,
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
number: 11,
|
|
527
|
+
title: "Afmetingen komen uit de Engine — handmatig invullen is optioneel",
|
|
528
|
+
date: "2026-09-03",
|
|
529
|
+
summary: "Fusttype en planthoogte leidt de Engine zelf af uit Floriday of uit de belading; Verkoop toont alleen de herkomst.",
|
|
530
|
+
body: `AANVULLING op prompt 1 t/m 10 (die blijven geldig). Dit vervangt de
|
|
531
|
+
verplichting uit prompt 9: fusttype en planthoogte hoeven niet meer handmatig
|
|
532
|
+
te worden ingevuld.
|
|
533
|
+
|
|
534
|
+
WAT ER VERANDERT
|
|
535
|
+
De Engine bepaalt de afmetingen per product zelf, in deze vaste volgorde:
|
|
536
|
+
1. Handmatig ingevuld op het product (products.fust_type_id, products.plant_height_cm).
|
|
537
|
+
2. Uit Floriday: verpakkingscode van het handelsitem -> fusttype; kenmerk S15
|
|
538
|
+
(transporthoogte), anders S02, als planthoogte.
|
|
539
|
+
3. Afgeleid uit de belading: bruikbare hoogte van de ladingdrager gedeeld door
|
|
540
|
+
het aantal lagen per ladingdrager, min de fusthoogte.
|
|
541
|
+
Levert geen van de drie een bruikbare waarde op, dan wordt die kar bewust niet
|
|
542
|
+
ingedeeld en volgt een leesbare reden.
|
|
543
|
+
|
|
544
|
+
WAT JIJ BOUWT
|
|
545
|
+
1. Lees per product public.logistics_product_dimensions (alleen-lezen):
|
|
546
|
+
fust_type_id, fust_name, fust_length_mm, fust_width_mm, fust_height_mm,
|
|
547
|
+
plant_height_cm, fust_source, height_source, dimension_source, missing_reason.
|
|
548
|
+
2. Toon bij het product de herkomst in gewone taal: "handmatig", "uit Floriday"
|
|
549
|
+
of "afgeleid uit de belading". Bij missing_reason die tekst letterlijk tonen.
|
|
550
|
+
3. De velden fust_type_id en plant_height_cm blijven bestaan als handmatige
|
|
551
|
+
correctie, maar zijn niet langer verplicht en niet langer als waarschuwing
|
|
552
|
+
markeren zolang de Engine een waarde levert.
|
|
553
|
+
|
|
554
|
+
WAT JE NIET DOET
|
|
555
|
+
- Zelf een hoogte of fustmaat berekenen, afronden of kopiëren van een ander product.
|
|
556
|
+
- De afgeleide hoogte wegschrijven naar products.plant_height_cm.
|
|
557
|
+
- Een keuze per order voor de indelingsmethode; die staat alleen in de Engine.
|
|
558
|
+
|
|
559
|
+
CONTROLELIJST
|
|
560
|
+
[ ] Bij elk product is zichtbaar waar fust en planthoogte vandaan komen.
|
|
561
|
+
[ ] Producten zonder bruikbare maten tonen de reden uit missing_reason.
|
|
562
|
+
[ ] Geen eigen berekening en geen wegschrijven van afgeleide waarden.`,
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
number: 12,
|
|
566
|
+
title: "Laagindeling netjes tekenen — coördinaten één op één overnemen",
|
|
567
|
+
date: "2026-09-03",
|
|
568
|
+
summary: "De Engine levert niet-overlappende posities in millimeters; Verkoop schaalt ze alleen en draait niets meer zelf.",
|
|
569
|
+
body: `AANVULLING op prompt 1 t/m 11 (die blijven geldig).
|
|
570
|
+
|
|
571
|
+
WAT ER VERANDERT
|
|
572
|
+
De Engine legt de fusten nu per artikel in uitgelijnde rijen. De opgeslagen
|
|
573
|
+
breedte en hoogte zijn al de daadwerkelijke maten in de gekozen stand; het veld
|
|
574
|
+
rotation is daarom altijd 0. Alle posities liggen binnen de laag en overlappen
|
|
575
|
+
nooit (gecontroleerd in de database).
|
|
576
|
+
|
|
577
|
+
WAT JIJ BOUWT
|
|
578
|
+
1. Lees public.order_cart_layer_positions per kar: layer, keg_id, x, y, width,
|
|
579
|
+
height, layer_width, layer_height, label, product_id, order_item_id.
|
|
580
|
+
2. Teken per laag één rechthoek met vaste verhouding layer_width : layer_height
|
|
581
|
+
en plaats elk fust met factor = tekenbreedte / layer_width. Dus:
|
|
582
|
+
left = x * factor, top = y * factor, width = width * factor,
|
|
583
|
+
height = height * factor. Geen extra marges, geen eigen uitlijning.
|
|
584
|
+
3. Draai NIETS meer: pas geen transform: rotate toe op basis van rotation.
|
|
585
|
+
Een gedraaid fust zit al in de opgeslagen breedte en hoogte.
|
|
586
|
+
4. Rustige weergave: dunne rand, zachte vulkleur per product uit de eigen
|
|
587
|
+
designtokens, label alleen als het fust groot genoeg is, anders in een tooltip.
|
|
588
|
+
Lagen onder elkaar met een kop "Laag 1", "Laag 2", enzovoort.
|
|
589
|
+
5. Zijn er voor een kar geen rijen, toon dan één korte melding met de reden uit
|
|
590
|
+
logistics_product_dimensions.missing_reason. Nooit een lege gekleurde kaart.
|
|
591
|
+
|
|
592
|
+
WAT JE NIET DOET
|
|
593
|
+
- Zelf posities berekenen, verschuiven, sorteren of fusten samenvoegen.
|
|
594
|
+
- Rotatie of spiegeling toepassen.
|
|
595
|
+
- Vaste pixelmaten of hardgecodeerde kleuren gebruiken.
|
|
596
|
+
|
|
597
|
+
VEELGEMAAKTE FOUTEN (dit gaat nu mis in de weergave)
|
|
598
|
+
- Elk fust als eigen blok in een verticale lijst of flex-kolom zetten. Daardoor
|
|
599
|
+
wordt één fust van 400x300 mm zo groot als de hele laag. Fusten zijn absoluut
|
|
600
|
+
gepositioneerde kinderen (position: absolute) van één laagvlak met
|
|
601
|
+
position: relative.
|
|
602
|
+
- Een min-height, aspect-square, flex-1 of grid-rij op het fust zetten. De hoogte
|
|
603
|
+
komt uitsluitend uit height * factor.
|
|
604
|
+
- Een eigen schaal per fust berekenen. Er is één factor per laag.
|
|
605
|
+
- Reuzelabels: het label is klein en secundair, niet het grootste element in beeld.
|
|
606
|
+
Toon "F2" alleen als bijschrift, niet als display-tekst.
|
|
607
|
+
- Het venster laten scrollen tot buiten beeld. Het laagvlak past binnen de
|
|
608
|
+
breedte van het venster; lagen staan onder elkaar met normale tussenruimte.
|
|
609
|
+
|
|
610
|
+
MINIMALE STRUCTUUR
|
|
611
|
+
<div style="position:relative;width:100%;aspect-ratio:{layer_width}/{layer_height}">
|
|
612
|
+
{posities.map(p => (
|
|
613
|
+
<div style="position:absolute;
|
|
614
|
+
left:{p.x/layer_width*100}%; top:{p.y/layer_height*100}%;
|
|
615
|
+
width:{p.width/layer_width*100}%; height:{p.height/layer_height*100}%" />
|
|
616
|
+
))}
|
|
617
|
+
</div>
|
|
618
|
+
|
|
619
|
+
CONTROLELIJST
|
|
620
|
+
[ ] Geen enkel fust overlapt of steekt buiten de laag.
|
|
621
|
+
[ ] De laagverhouding klopt met layer_width en layer_height.
|
|
622
|
+
[ ] Een laag met 25 fusten toont ook echt 25 kleine vakjes naast en onder elkaar.
|
|
623
|
+
[ ] Labels zijn klein; het laagvlak is het grootste element.
|
|
624
|
+
[ ] Karren zonder maten tonen één leesbare reden.`,
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
number: 13,
|
|
628
|
+
title: "Karnummer per order: cart_seq en cart_number tonen",
|
|
629
|
+
date: "2026-09-03",
|
|
630
|
+
summary: "Karnummers komen uit de Engine: toon cart_seq en cart_number, nooit cart_index, en reken zelf niets om.",
|
|
631
|
+
body: `AANVULLING op de eerdere prompts (die blijven geldig).
|
|
632
|
+
|
|
633
|
+
WAT ER VERANDERT
|
|
634
|
+
De Engine levert vanaf nu per kar een stabiel karnummer. Modules rekenen zelf
|
|
635
|
+
NIETS meer om en hernummeren niet.
|
|
636
|
+
|
|
637
|
+
VELDEN (uit de Engine-RPC's)
|
|
638
|
+
- cart_seq : stabiel, 1-gebaseerd volgnummer van de kar binnen zijn order.
|
|
639
|
+
Identiek aan het nummer op de pakbon in de verkoopmodule. Verandert niet als
|
|
640
|
+
karren op verschillende dagen gepickt of gecontroleerd worden, en niet als een
|
|
641
|
+
deel van de karren al is afgehandeld.
|
|
642
|
+
- cart_number : het definitieve karnummer-label (bijv. het toegewezen
|
|
643
|
+
karnummer uit de karnummering). Toon dit als label.
|
|
644
|
+
- cart_total : het aantal karren van die order ("Kar X van Y" = cart_seq van
|
|
645
|
+
cart_total).
|
|
646
|
+
- cart_index : INTERN. Technische index, niet gedefinieerd als 0- of
|
|
647
|
+
1-gebaseerd. NOOIT tonen en nooit als basis voor eigen nummering gebruiken.
|
|
648
|
+
|
|
649
|
+
WAAR STAAN DE VELDEN
|
|
650
|
+
control_get_todays_carts(), logistics_pick_agenda(p_from, p_to) (per order in
|
|
651
|
+
cartList), logistics_cart_index(p_from, p_to), logistics_control_scan_lookup(
|
|
652
|
+
p_barcode) (cartSeq / cartNumber / cartTotal) en
|
|
653
|
+
logistics_control_scan_overview(p_scanner_id, p_date).
|
|
654
|
+
|
|
655
|
+
GEBRUIK IN DEZE MODULE
|
|
656
|
+
Het nummer op de pakbon is cart_seq; het label is cart_number. Ditzelfde
|
|
657
|
+
nummer zien alle andere modules.
|
|
658
|
+
|
|
659
|
+
NIET DOEN
|
|
660
|
+
- Niet zelf nummeren, sorteren op index, of +1 optellen bij cart_index.
|
|
661
|
+
- Geen aparte nummering per dag, per pickronde of per controlesessie.
|
|
662
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
663
|
+
|
|
664
|
+
CONTROLELIJST
|
|
665
|
+
[ ] Elk karnummer in het scherm komt uit cart_seq / cart_number.
|
|
666
|
+
[ ] "Kar X van Y" gebruikt cart_seq en cart_total.
|
|
667
|
+
[ ] Een order met 4 karren toont 1 t/m 4, ook als er al karren afgehandeld zijn.
|
|
668
|
+
[ ] Het getoonde nummer is gelijk aan het nummer op de pakbon.
|
|
669
|
+
[ ] cart_index komt nergens in de weergave voor.`,
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
number: 14,
|
|
673
|
+
title: "Laagindeling alleen tonen bij indelen op afmetingen",
|
|
674
|
+
date: "2026-09-05",
|
|
675
|
+
summary: "Bij indelen op belading rekent de Engine geen fustposities uit; verberg dan de hele laagindeling in plaats van een lege kaart of melding.",
|
|
676
|
+
body: `AANVULLING op prompt 12 (die blijft geldig voor de tekening zelf).
|
|
677
|
+
|
|
678
|
+
WAT ER VERANDERT
|
|
679
|
+
De methode voor karrenindeling is een globale instelling van de Engine:
|
|
680
|
+
- "Indelen op belading": de Engine berekent GEEN fustposities. Er is dus geen
|
|
681
|
+
laagindeling en die hoort ook niet in beeld te komen.
|
|
682
|
+
- "Indelen op afmetingen": de Engine levert wel posities per laag en die worden
|
|
683
|
+
in deze module getoond zoals beschreven in prompt 12.
|
|
684
|
+
|
|
685
|
+
WAT JIJ BOUWT
|
|
686
|
+
1. Lees de methode op met de RPC public.logistics_cart_layout_method().
|
|
687
|
+
Die geeft { layoutMethod: 'belading' | 'afmetingen', showLayerLayout: boolean }.
|
|
688
|
+
2. showLayerLayout = false → laat het hele blok "Laagindeling" weg: geen kaart,
|
|
689
|
+
geen tabs, geen melding "nog geen laagindeling". De rest van het orderdetail
|
|
690
|
+
blijft ongewijzigd.
|
|
691
|
+
3. showLayerLayout = true → toon de laagindeling per kar uit
|
|
692
|
+
public.order_cart_layer_positions volgens prompt 12, en toon per kar zonder
|
|
693
|
+
posities één korte reden uit logistics_product_dimensions.missing_reason.
|
|
694
|
+
4. Ververs de methode bij het openen van het scherm en na een wijziging in de
|
|
695
|
+
Engine-instellingen; cache hem niet langer dan de sessie.
|
|
696
|
+
|
|
697
|
+
WAT JE NIET DOET
|
|
698
|
+
- Zelf posities of laagverdelingen berekenen wanneer de Engine ze niet levert.
|
|
699
|
+
- De laagindeling tonen op basis van alleen de aanwezigheid van rijen: bij
|
|
700
|
+
belading kunnen oude rijen zijn opgeruimd, de instelling is leidend.
|
|
701
|
+
- Terugvallen op 'afmetingen' als de RPC faalt. Bij een fout: blok verbergen.
|
|
702
|
+
|
|
703
|
+
NIET DOEN (algemeen)
|
|
704
|
+
Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
705
|
+
|
|
706
|
+
CONTROLELIJST
|
|
707
|
+
[ ] Bij "indelen op belading" is nergens een laagindeling of lege kaart zichtbaar.
|
|
708
|
+
[ ] Bij "indelen op afmetingen" verschijnt de tekening met de posities van de Engine.
|
|
709
|
+
[ ] Omschakelen van methode is na verversen direct zichtbaar.
|
|
710
|
+
[ ] Bij een fout in de RPC blijft het blok verborgen, zonder foutmelding in beeld.`,
|
|
711
|
+
},
|
|
499
712
|
],
|
|
500
713
|
},
|
|
501
714
|
afhandeling: {
|
|
@@ -508,15 +721,15 @@ CONTROLELIJST
|
|
|
508
721
|
date: "2026-07-24",
|
|
509
722
|
summary: "Eigen beladings- en documentlogica eruit, taken uitvoeren.",
|
|
510
723
|
withSharedContract: true,
|
|
511
|
-
body: `Haal weg: eigen beladingindeling, eigen documentmomenten, eigen controle-instellingen.
|
|
512
|
-
|
|
513
|
-
Consumeer deze taaktypes:
|
|
514
|
-
- load.compose payload: loadCarriers, fillMode (generated | manual_scan)
|
|
515
|
-
- control.execute payload: controlMode (paper), noticeAt
|
|
516
|
-
- print.control_note payload: printItems (control_note | control_note_and_shipping)
|
|
517
|
-
- print.shipping_note payload: moment (with_packing_slip | with_control | after_control | after_scan)
|
|
518
|
-
- transport.dispatch
|
|
519
|
-
|
|
724
|
+
body: `Haal weg: eigen beladingindeling, eigen documentmomenten, eigen controle-instellingen.
|
|
725
|
+
|
|
726
|
+
Consumeer deze taaktypes:
|
|
727
|
+
- load.compose payload: loadCarriers, fillMode (generated | manual_scan)
|
|
728
|
+
- control.execute payload: controlMode (paper), noticeAt
|
|
729
|
+
- print.control_note payload: printItems (control_note | control_note_and_shipping)
|
|
730
|
+
- print.shipping_note payload: moment (with_packing_slip | with_control | after_control | after_scan)
|
|
731
|
+
- transport.dispatch
|
|
732
|
+
|
|
520
733
|
Wat er geprint wordt en wanneer komt volledig uit de taak-payload. Geen eigen keuzes meer.`,
|
|
521
734
|
},
|
|
522
735
|
{
|
|
@@ -524,28 +737,28 @@ Wat er geprint wordt en wanneer komt volledig uit de taak-payload. Geen eigen ke
|
|
|
524
737
|
title: "Documentvrijgave komt volledig van de Engine",
|
|
525
738
|
date: "2026-08-03",
|
|
526
739
|
summary: "Pakbon, stickers, verzendbrief en productiebon alleen nog via Engine-taken.",
|
|
527
|
-
body: `Deze prompt vervangt niets uit prompt 1; hij komt er bovenop.
|
|
528
|
-
|
|
529
|
-
Haal weg: elke eigen regel over wanneer een pakbon, sticker, verzendbrief of
|
|
530
|
-
productiebon wordt vrijgegeven of geprint. De Logistics Engine beslist dit nu.
|
|
531
|
-
|
|
532
|
-
Nieuwe taaktypes die je moet verwerken (tabel logistics_tasks):
|
|
533
|
-
- print.packing_slip payload: release (with_pick_release | hours_before_pick),
|
|
534
|
-
pickStationId, pickStationTypeId, requiresApproval
|
|
535
|
-
- print.sticker payload: idem als print.packing_slip
|
|
536
|
-
- print.shipping_note payload: release (after_checkin | after_scan |
|
|
537
|
-
with_packing_slip | manual_approval), pickStationId,
|
|
538
|
-
pickStationTypeId, requiresApproval
|
|
539
|
-
- print.production_note payload: release (on_stock_upgrade |
|
|
540
|
-
manual_approval_after_upgrade), trigger, pickStationId,
|
|
541
|
-
pickStationTypeId, requiresApproval
|
|
542
|
-
|
|
543
|
-
Regels:
|
|
544
|
-
- planned_start van de taak is het vrijgavemoment. Nooit eerder printen.
|
|
545
|
-
- pickStationId verwijst naar public.pick_stations.id; pickStationTypeId naar
|
|
546
|
-
public.pick_station_types.id. Stuur het document uitsluitend naar dat station.
|
|
547
|
-
- requiresApproval = true: het document blijft in de wachtrij tot iemand het op
|
|
548
|
-
het pickstation goedkeurt. Meld de goedkeuring met logistics_complete_task.
|
|
740
|
+
body: `Deze prompt vervangt niets uit prompt 1; hij komt er bovenop.
|
|
741
|
+
|
|
742
|
+
Haal weg: elke eigen regel over wanneer een pakbon, sticker, verzendbrief of
|
|
743
|
+
productiebon wordt vrijgegeven of geprint. De Logistics Engine beslist dit nu.
|
|
744
|
+
|
|
745
|
+
Nieuwe taaktypes die je moet verwerken (tabel logistics_tasks):
|
|
746
|
+
- print.packing_slip payload: release (with_pick_release | hours_before_pick),
|
|
747
|
+
pickStationId, pickStationTypeId, requiresApproval
|
|
748
|
+
- print.sticker payload: idem als print.packing_slip
|
|
749
|
+
- print.shipping_note payload: release (after_checkin | after_scan |
|
|
750
|
+
with_packing_slip | manual_approval), pickStationId,
|
|
751
|
+
pickStationTypeId, requiresApproval
|
|
752
|
+
- print.production_note payload: release (on_stock_upgrade |
|
|
753
|
+
manual_approval_after_upgrade), trigger, pickStationId,
|
|
754
|
+
pickStationTypeId, requiresApproval
|
|
755
|
+
|
|
756
|
+
Regels:
|
|
757
|
+
- planned_start van de taak is het vrijgavemoment. Nooit eerder printen.
|
|
758
|
+
- pickStationId verwijst naar public.pick_stations.id; pickStationTypeId naar
|
|
759
|
+
public.pick_station_types.id. Stuur het document uitsluitend naar dat station.
|
|
760
|
+
- requiresApproval = true: het document blijft in de wachtrij tot iemand het op
|
|
761
|
+
het pickstation goedkeurt. Meld de goedkeuring met logistics_complete_task.
|
|
549
762
|
- Is er geen taak voor een document, dan wordt dat document niet geprint.`,
|
|
550
763
|
},
|
|
551
764
|
{
|
|
@@ -553,53 +766,53 @@ Regels:
|
|
|
553
766
|
title: "Order- en karindeling altijd via de Logistics Engine",
|
|
554
767
|
date: "2026-08-04",
|
|
555
768
|
summary: "Nieuwe eis bovenop prompt 1 en 2: geen eigen indeling van orders en karren meer; stap 3 'Order picken' van de Rule Engine is leidend.",
|
|
556
|
-
body: `Deze prompt vervangt niets uit prompt 1 en 2; hij komt er bovenop.
|
|
557
|
-
|
|
558
|
-
Geconstateerd probleem: deze module deelt orders en karren nog zelf in en houdt
|
|
559
|
-
zich daardoor niet aan stap 3 "Order picken" van de Rule Engine. Dat moet stoppen.
|
|
560
|
-
|
|
561
|
-
Haal weg: elke eigen berekening van
|
|
562
|
-
- welke orders samen op één belading/kar komen,
|
|
563
|
-
- hoeveel orders, klanten, lagen of dozen er op een drager passen,
|
|
564
|
-
- wanneer er met picken gestart wordt,
|
|
565
|
-
- of er met of zonder scanner gewerkt wordt.
|
|
566
|
-
|
|
567
|
-
Zo werkt het vanaf nu:
|
|
568
|
-
|
|
569
|
-
1) Vraag altijd eerst het besluit op voordat je iets indeelt:
|
|
570
|
-
const { data: besluit } = await supabase.rpc("logistics_buffer_decision", {
|
|
571
|
-
p_order_ref: "SO-12345",
|
|
572
|
-
p_customer_ref: "CUST-1",
|
|
573
|
-
p_delivery_location_ref: "LOC-1",
|
|
574
|
-
p_checkin_at: "2026-08-01T10:00:00Z",
|
|
575
|
-
p_pickup_at: "2026-08-01T14:00:00Z",
|
|
576
|
-
p_load_carrier_type: "trolley",
|
|
577
|
-
p_strategy_id: null,
|
|
578
|
-
});
|
|
579
|
-
// besluit = { buffer, bufferRef, matchCriteria, release, trace }
|
|
580
|
-
Deel de order uitsluitend in bij bufferRef. Is buffer=false, dan blijft de order
|
|
581
|
-
los staan: nooit zelf alsnog samenvoegen.
|
|
582
|
-
|
|
583
|
-
2) De feitelijke belading komt uit de taak load.compose in logistics_tasks
|
|
584
|
-
(owner_module = "afhandeling"). De payload bevat loadCarriers, fillMode
|
|
585
|
-
(generated | manual_scan) en de picksettings uit stap 3: pickMode,
|
|
586
|
-
pickStartMode, pickMinutes, staff, reserveMinutes, scanner.
|
|
587
|
-
- fillMode = generated: neem de indeling exact over zoals aangeleverd.
|
|
588
|
-
- fillMode = manual_scan: laat de medewerker scannen en meld het resultaat
|
|
589
|
-
terug; corrigeer de indeling niet zelf.
|
|
590
|
-
- scanner = required: geen afronding zonder scan.
|
|
591
|
-
|
|
592
|
-
3) planned_start en planned_end van de taak zijn leidend voor het pickmoment.
|
|
593
|
-
Herbereken die nooit zelf, ook niet bij drukte.
|
|
594
|
-
|
|
595
|
-
4) Is er nog geen load.compose taak voor een order, dan meld je dat met
|
|
596
|
-
logistics_emit_event (order.received of order.changed) en wacht je op de taak.
|
|
597
|
-
Zelf alvast indelen is niet toegestaan.
|
|
598
|
-
|
|
599
|
-
5) Elke taak draagt rule_version. Rond een lopende belading altijd af op de
|
|
600
|
-
rule_version van de taak, ook als de Rule Engine intussen is gewijzigd.
|
|
601
|
-
|
|
602
|
-
Meld afwijkingen terug met logistics_fail_task inclusief toelichting, zodat de
|
|
769
|
+
body: `Deze prompt vervangt niets uit prompt 1 en 2; hij komt er bovenop.
|
|
770
|
+
|
|
771
|
+
Geconstateerd probleem: deze module deelt orders en karren nog zelf in en houdt
|
|
772
|
+
zich daardoor niet aan stap 3 "Order picken" van de Rule Engine. Dat moet stoppen.
|
|
773
|
+
|
|
774
|
+
Haal weg: elke eigen berekening van
|
|
775
|
+
- welke orders samen op één belading/kar komen,
|
|
776
|
+
- hoeveel orders, klanten, lagen of dozen er op een drager passen,
|
|
777
|
+
- wanneer er met picken gestart wordt,
|
|
778
|
+
- of er met of zonder scanner gewerkt wordt.
|
|
779
|
+
|
|
780
|
+
Zo werkt het vanaf nu:
|
|
781
|
+
|
|
782
|
+
1) Vraag altijd eerst het besluit op voordat je iets indeelt:
|
|
783
|
+
const { data: besluit } = await supabase.rpc("logistics_buffer_decision", {
|
|
784
|
+
p_order_ref: "SO-12345",
|
|
785
|
+
p_customer_ref: "CUST-1",
|
|
786
|
+
p_delivery_location_ref: "LOC-1",
|
|
787
|
+
p_checkin_at: "2026-08-01T10:00:00Z",
|
|
788
|
+
p_pickup_at: "2026-08-01T14:00:00Z",
|
|
789
|
+
p_load_carrier_type: "trolley",
|
|
790
|
+
p_strategy_id: null,
|
|
791
|
+
});
|
|
792
|
+
// besluit = { buffer, bufferRef, matchCriteria, release, trace }
|
|
793
|
+
Deel de order uitsluitend in bij bufferRef. Is buffer=false, dan blijft de order
|
|
794
|
+
los staan: nooit zelf alsnog samenvoegen.
|
|
795
|
+
|
|
796
|
+
2) De feitelijke belading komt uit de taak load.compose in logistics_tasks
|
|
797
|
+
(owner_module = "afhandeling"). De payload bevat loadCarriers, fillMode
|
|
798
|
+
(generated | manual_scan) en de picksettings uit stap 3: pickMode,
|
|
799
|
+
pickStartMode, pickMinutes, staff, reserveMinutes, scanner.
|
|
800
|
+
- fillMode = generated: neem de indeling exact over zoals aangeleverd.
|
|
801
|
+
- fillMode = manual_scan: laat de medewerker scannen en meld het resultaat
|
|
802
|
+
terug; corrigeer de indeling niet zelf.
|
|
803
|
+
- scanner = required: geen afronding zonder scan.
|
|
804
|
+
|
|
805
|
+
3) planned_start en planned_end van de taak zijn leidend voor het pickmoment.
|
|
806
|
+
Herbereken die nooit zelf, ook niet bij drukte.
|
|
807
|
+
|
|
808
|
+
4) Is er nog geen load.compose taak voor een order, dan meld je dat met
|
|
809
|
+
logistics_emit_event (order.received of order.changed) en wacht je op de taak.
|
|
810
|
+
Zelf alvast indelen is niet toegestaan.
|
|
811
|
+
|
|
812
|
+
5) Elke taak draagt rule_version. Rond een lopende belading altijd af op de
|
|
813
|
+
rule_version van de taak, ook als de Rule Engine intussen is gewijzigd.
|
|
814
|
+
|
|
815
|
+
Meld afwijkingen terug met logistics_fail_task inclusief toelichting, zodat de
|
|
603
816
|
Engine kan herplannen. Val nooit terug op eigen logica.`,
|
|
604
817
|
},
|
|
605
818
|
{
|
|
@@ -607,50 +820,50 @@ Engine kan herplannen. Val nooit terug op eigen logica.`,
|
|
|
607
820
|
title: "Karren verdelen over meerdere ophaalmomenten",
|
|
608
821
|
date: "2026-08-04",
|
|
609
822
|
summary: "Nieuwe eis bovenop prompt 1 t/m 4: de Engine verdeelt complete karren over de ophaalmomenten van een dag; deze module toont dat en verzet nooit zelf.",
|
|
610
|
-
body: `LEES DIT EERST — hoe je deze prompt uitvoert
|
|
611
|
-
|
|
612
|
-
Alles uit prompt 1 t/m 4 blijft gelden. Hier komt er één ding bij: een dag kan
|
|
613
|
-
MEERDERE ophaalmomenten hebben, en de Logistics Engine bepaalt welke kar bij
|
|
614
|
-
welk ophaalmoment hoort. Jij rekent NIETS zelf uit en verplaatst NOOIT zelf een
|
|
615
|
-
kar op basis van eigen logica.
|
|
616
|
-
|
|
617
|
-
1) Ophaalmomenten lezen
|
|
618
|
-
Tabel: public.logistics_pickup_moments
|
|
619
|
-
Kolommen: id, moment_date, sequence, label, pickup_time, carrier_ref
|
|
620
|
-
Toon per dag de ophaalmomenten op volgorde van sequence/pickup_time.
|
|
621
|
-
|
|
622
|
-
2) Karren per ophaalmoment
|
|
623
|
-
Tabel public.order_carts heeft nieuwe kolommen:
|
|
624
|
-
- pickup_moment_id → bij welk ophaalmoment de kar hoort
|
|
625
|
-
- moved_from_moment_id → het ophaalmoment waar de kar oorspronkelijk stond
|
|
626
|
-
- moved_reason → 'capacity_shift' als de Engine hem doorschoof
|
|
627
|
-
- moved_at → wanneer dat gebeurde
|
|
628
|
-
- pickup_locked → true = deze kar mag NIET doorgeschoven worden
|
|
629
|
-
|
|
630
|
-
Groepeer de pickagenda en de leveringsplanning voortaan op pickup_moment_id,
|
|
631
|
-
niet meer alleen op de dag. Een kar met moved_reason = 'capacity_shift' toon
|
|
632
|
-
je met een duidelijk label "doorgeschoven vanaf <label vorig moment>".
|
|
633
|
-
|
|
634
|
-
3) Regels die je moet respecteren
|
|
635
|
-
- Alleen COMPLETE karren wisselen van ophaalmoment. Splits nooit een kar en
|
|
636
|
-
verplaats nooit losse orderregels naar een ander moment.
|
|
637
|
-
- Karren uit een buffer mogen mee, maar alleen als geheel.
|
|
638
|
-
- Wil een gebruiker een kar vastzetten op een moment, zet dan
|
|
639
|
-
pickup_locked = true. Meer doe je niet; de Engine slaat die kar over.
|
|
640
|
-
|
|
641
|
-
4) Herberekenen
|
|
642
|
-
Na elke wijziging die de planning raakt (nieuwe order, annulering, andere
|
|
643
|
-
ophaaltijd, andere kar-indeling) roep je aan:
|
|
644
|
-
await supabase.rpc("logistics_capacity_plan_day", { p_date: "2026-08-04" })
|
|
645
|
-
De functie geeft per ophaalmoment terug: requiredMinutes, availableMinutes,
|
|
646
|
-
feasible en movedCarts. Toon die uitkomst; verzin geen eigen berekening.
|
|
647
|
-
|
|
648
|
-
5) Tekort tonen
|
|
649
|
-
Tabel public.logistics_capacity_alerts bevat per dag/ophaalmoment het tekort
|
|
650
|
-
(shortage_minutes, carts_short, moved_carts, unplanned_carts). Staat er een
|
|
651
|
-
rij met status = 'open', toon dan bij dat ophaalmoment een rode waarschuwing
|
|
652
|
-
met het tekort en het aantal karren dat niet op tijd verwerkt kan worden.
|
|
653
|
-
|
|
823
|
+
body: `LEES DIT EERST — hoe je deze prompt uitvoert
|
|
824
|
+
|
|
825
|
+
Alles uit prompt 1 t/m 4 blijft gelden. Hier komt er één ding bij: een dag kan
|
|
826
|
+
MEERDERE ophaalmomenten hebben, en de Logistics Engine bepaalt welke kar bij
|
|
827
|
+
welk ophaalmoment hoort. Jij rekent NIETS zelf uit en verplaatst NOOIT zelf een
|
|
828
|
+
kar op basis van eigen logica.
|
|
829
|
+
|
|
830
|
+
1) Ophaalmomenten lezen
|
|
831
|
+
Tabel: public.logistics_pickup_moments
|
|
832
|
+
Kolommen: id, moment_date, sequence, label, pickup_time, carrier_ref
|
|
833
|
+
Toon per dag de ophaalmomenten op volgorde van sequence/pickup_time.
|
|
834
|
+
|
|
835
|
+
2) Karren per ophaalmoment
|
|
836
|
+
Tabel public.order_carts heeft nieuwe kolommen:
|
|
837
|
+
- pickup_moment_id → bij welk ophaalmoment de kar hoort
|
|
838
|
+
- moved_from_moment_id → het ophaalmoment waar de kar oorspronkelijk stond
|
|
839
|
+
- moved_reason → 'capacity_shift' als de Engine hem doorschoof
|
|
840
|
+
- moved_at → wanneer dat gebeurde
|
|
841
|
+
- pickup_locked → true = deze kar mag NIET doorgeschoven worden
|
|
842
|
+
|
|
843
|
+
Groepeer de pickagenda en de leveringsplanning voortaan op pickup_moment_id,
|
|
844
|
+
niet meer alleen op de dag. Een kar met moved_reason = 'capacity_shift' toon
|
|
845
|
+
je met een duidelijk label "doorgeschoven vanaf <label vorig moment>".
|
|
846
|
+
|
|
847
|
+
3) Regels die je moet respecteren
|
|
848
|
+
- Alleen COMPLETE karren wisselen van ophaalmoment. Splits nooit een kar en
|
|
849
|
+
verplaats nooit losse orderregels naar een ander moment.
|
|
850
|
+
- Karren uit een buffer mogen mee, maar alleen als geheel.
|
|
851
|
+
- Wil een gebruiker een kar vastzetten op een moment, zet dan
|
|
852
|
+
pickup_locked = true. Meer doe je niet; de Engine slaat die kar over.
|
|
853
|
+
|
|
854
|
+
4) Herberekenen
|
|
855
|
+
Na elke wijziging die de planning raakt (nieuwe order, annulering, andere
|
|
856
|
+
ophaaltijd, andere kar-indeling) roep je aan:
|
|
857
|
+
await supabase.rpc("logistics_capacity_plan_day", { p_date: "2026-08-04" })
|
|
858
|
+
De functie geeft per ophaalmoment terug: requiredMinutes, availableMinutes,
|
|
859
|
+
feasible en movedCarts. Toon die uitkomst; verzin geen eigen berekening.
|
|
860
|
+
|
|
861
|
+
5) Tekort tonen
|
|
862
|
+
Tabel public.logistics_capacity_alerts bevat per dag/ophaalmoment het tekort
|
|
863
|
+
(shortage_minutes, carts_short, moved_carts, unplanned_carts). Staat er een
|
|
864
|
+
rij met status = 'open', toon dan bij dat ophaalmoment een rode waarschuwing
|
|
865
|
+
met het tekort en het aantal karren dat niet op tijd verwerkt kan worden.
|
|
866
|
+
|
|
654
867
|
Val nooit terug op eigen logica. Wat de Engine teruggeeft, is leidend.`,
|
|
655
868
|
},
|
|
656
869
|
{
|
|
@@ -658,131 +871,131 @@ Val nooit terug op eigen logica. Wat de Engine teruggeeft, is leidend.`,
|
|
|
658
871
|
title: "Order handmatig verzetten en ophaaltijd wijzigen",
|
|
659
872
|
date: "2026-08-04",
|
|
660
873
|
summary: "Nieuwe eis bovenop prompt 1 t/m 3: een medewerker mag een order handmatig naar een andere dag en/of ophaaltijd zetten, via twee vaste RPC's van de Engine.",
|
|
661
|
-
body: `LEES DIT EERST — hoe je deze prompt uitvoert
|
|
662
|
-
|
|
663
|
-
Deze prompt beschrijft één nieuwe functie in de Afhandeling-module: "Order
|
|
664
|
-
verzetten". Je bouwt hem volledig, niet gedeeltelijk. Alles wat hieronder staat
|
|
665
|
-
is verplicht. Er is GEEN eigen rekenwerk: de Logistics Engine levert twee kant-en-
|
|
666
|
-
klare database-functies, jij bouwt alleen het scherm eromheen en toont wat de
|
|
667
|
-
Engine teruggeeft.
|
|
668
|
-
|
|
669
|
-
Concreet ben je klaar als dit alle vier waar is:
|
|
670
|
-
1. Er is een knop "Verzetten" bij een order (planning-/agenda-/leverscherm).
|
|
671
|
-
2. Het dialoogvenster toont een DAGKEUZE en een OPHAALTIJD (van/tot).
|
|
672
|
-
3. Voor het opslaan is logistics_reschedule_preview aangeroepen en wordt de
|
|
673
|
-
uitkomst daarvan letterlijk aan de gebruiker getoond.
|
|
674
|
-
4. Opslaan gebeurt uitsluitend met logistics_reschedule_order.
|
|
675
|
-
|
|
676
|
-
------------------------------------------------------------------
|
|
677
|
-
DE TWEE REGELS DIE DE GEBRUIKER WIL
|
|
678
|
-
------------------------------------------------------------------
|
|
679
|
-
|
|
680
|
-
A. Order gaat NAAR VOREN (nieuwe ophaaldag is eerder dan de huidige)
|
|
681
|
-
-> Het AFLEVERMOMENT (leverdatum naar de klant) blijft ONGEWIJZIGD.
|
|
682
|
-
De order wordt dus eerder klaargemaakt en opgehaald, maar de klant krijgt
|
|
683
|
-
hem op dezelfde dag als afgesproken. Je verandert de leverdatum NIET.
|
|
684
|
-
Er gaat GEEN melding naar de klant.
|
|
685
|
-
|
|
686
|
-
B. Order gaat NAAR ACHTEREN (nieuwe ophaaldag is later)
|
|
687
|
-
-> Het aflevermoment schuift mee.
|
|
688
|
-
-> De gebruiker MOET in het dialoogvenster de keuze krijgen:
|
|
689
|
-
"Klant informeren over de nieuwe leverdatum" (aan/uit) plus een reden.
|
|
690
|
-
Staat het aan, dan zorgt de Engine voor de klantmelding. Bouw daar zelf
|
|
691
|
-
geen mailflow voor.
|
|
692
|
-
|
|
693
|
-
C. Alleen de OPHAALTIJD wijzigen (zelfde dag, andere van/tot-tijd) mag altijd
|
|
694
|
-
en geldt niet als verzetten: geen klantmelding, leverdatum blijft gelijk.
|
|
695
|
-
|
|
696
|
-
------------------------------------------------------------------
|
|
697
|
-
STAP 1 — VOORVERTONING (verplicht vóór opslaan)
|
|
698
|
-
------------------------------------------------------------------
|
|
699
|
-
const { data: preview } = await supabase.rpc("logistics_reschedule_preview", {
|
|
700
|
-
p_order_ref: "SO-12345", // orders.order_number
|
|
701
|
-
p_pickup_date: "2026-08-07", // nieuwe ophaaldag (YYYY-MM-DD), null = ongewijzigd
|
|
702
|
-
p_pickup_from: "06:00", // nieuwe starttijd, null = ongewijzigd
|
|
703
|
-
p_pickup_to: "09:00", // nieuwe eindtijd, null = ongewijzigd
|
|
704
|
-
});
|
|
705
|
-
|
|
706
|
-
preview bevat:
|
|
707
|
-
{
|
|
708
|
-
ok: true,
|
|
709
|
-
orderRef, orderId, bufferId, planLocked,
|
|
710
|
-
current: { pickupDate, pickupFrom, pickupTo, deliveryDate },
|
|
711
|
-
next: { pickupDate, pickupFrom, pickupTo, deliveryDate },
|
|
712
|
-
direction: "earlier" | "later" | "same",
|
|
713
|
-
dayShift: -2, // aantal dagen verschil
|
|
714
|
-
timeChanged: true,
|
|
715
|
-
keepDeliveryMoment: true, // true bij naar voren: leverdatum blijft
|
|
716
|
-
customerNoticeRequired: true, // true bij naar achteren: toon de klantoptie
|
|
717
|
-
affectedTasks: 8 // aantal taken dat opnieuw wordt ingepland
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
Wat je met deze velden DOET in het scherm:
|
|
721
|
-
- ok === false -> toon preview.error en blokkeer opslaan.
|
|
722
|
-
- direction === "earlier" -> toon: "Order wordt X dag(en) eerder opgehaald. Het
|
|
723
|
-
aflevermoment blijft {current.deliveryDate}." Verberg de klantoptie.
|
|
724
|
-
- direction === "later" -> toon: "Order wordt X dag(en) later. Nieuwe leverdatum:
|
|
725
|
-
{next.deliveryDate}." Toon de schakelaar "Klant informeren" (standaard AAN) en
|
|
726
|
-
een verplicht redenveld.
|
|
727
|
-
- direction === "same" && timeChanged -> toon alleen de nieuwe ophaaltijd.
|
|
728
|
-
- Toon altijd affectedTasks: "X taken worden opnieuw ingepland."
|
|
729
|
-
|
|
730
|
-
------------------------------------------------------------------
|
|
731
|
-
STAP 2 — OPSLAAN
|
|
732
|
-
------------------------------------------------------------------
|
|
733
|
-
const { data: result } = await supabase.rpc("logistics_reschedule_order", {
|
|
734
|
-
p_order_ref: "SO-12345",
|
|
735
|
-
p_pickup_date: "2026-08-07",
|
|
736
|
-
p_pickup_from: "06:00",
|
|
737
|
-
p_pickup_to: "09:00",
|
|
738
|
-
p_notify_customer: true, // alleen relevant bij direction "later"
|
|
739
|
-
p_reason: "Aanvoer bloemen vertraagd",
|
|
740
|
-
p_source_module: "afhandeling",
|
|
741
|
-
p_user_id: null,
|
|
742
|
-
});
|
|
743
|
-
// result = preview-velden + { applied: true, rescheduleId, delayAlertId,
|
|
744
|
-
// customerNotified, pickupMoment }
|
|
745
|
-
|
|
746
|
-
De Engine doet hierbij zelf al ALLES hieronder — doe dit dus niet nogmaals:
|
|
747
|
-
- orders.custom_fields.pickup_moment bijwerken ("YYYY-MM-DD|van|tot");
|
|
748
|
-
- leverdatum alleen aanpassen bij naar achteren;
|
|
749
|
-
- de order uit zijn orderbuffer halen zodat hij niet aan de oude dag vastzit;
|
|
750
|
-
- de klantmelding aanmaken als p_notify_customer true is;
|
|
751
|
-
- een order.changed-melding sturen en de hele takenketen (buffer, pick, controle,
|
|
752
|
-
printen, transport) opnieuw inplannen met logistics_schedule_tasks;
|
|
753
|
-
- het verzetten vastleggen in public.logistics_reschedules.
|
|
754
|
-
|
|
755
|
-
------------------------------------------------------------------
|
|
756
|
-
WAT JE ABSOLUUT NIET DOET
|
|
757
|
-
------------------------------------------------------------------
|
|
758
|
-
- Geen eigen UPDATE op orders, order_buffers, order_carts of logistics_tasks om
|
|
759
|
-
een datum of tijd te verzetten. Uitsluitend via de twee RPC's hierboven.
|
|
760
|
-
- Zelf planned_start / planned_end / due_at van taken herberekenen. Na het
|
|
761
|
-
opslaan lees je de taken gewoon opnieuw; ze staan dan al goed.
|
|
762
|
-
- Bij naar voren de leverdatum meeschuiven. Dat is expliciet fout.
|
|
763
|
-
- Bij naar achteren de klant informeren zonder dat de gebruiker dat heeft
|
|
764
|
-
aangevinkt, of een eigen mail sturen buiten de Engine om.
|
|
765
|
-
|
|
766
|
-
------------------------------------------------------------------
|
|
767
|
-
NA HET OPSLAAN
|
|
768
|
-
------------------------------------------------------------------
|
|
769
|
-
1. Herlaad de taken van deze order uit logistics_tasks (planned_start bepaalt
|
|
770
|
-
waar de order in de pickagenda en het leverscherm verschijnt).
|
|
771
|
-
2. Toon een bevestiging met de nieuwe ophaaldag, de ophaaltijd, de leverdatum en
|
|
772
|
-
of de klant is geïnformeerd (result.customerNotified).
|
|
773
|
-
3. De verzetgeschiedenis kun je tonen met:
|
|
774
|
-
supabase.from("logistics_reschedules").select("*").eq("order_ref", ref)
|
|
775
|
-
.order("created_at", { ascending: false });
|
|
776
|
-
|
|
777
|
-
------------------------------------------------------------------
|
|
778
|
-
CONTROLELIJST VOOR JEZELF (loop deze af voor je klaar meldt)
|
|
779
|
-
------------------------------------------------------------------
|
|
780
|
-
[ ] Knop "Verzetten" bestaat bij een order.
|
|
781
|
-
[ ] Dagkeuze én ophaaltijd van/tot zijn in te vullen.
|
|
782
|
-
[ ] preview wordt live aangeroepen bij elke wijziging in het formulier.
|
|
783
|
-
[ ] Naar voren: leverdatum ongewijzigd, geen klantoptie zichtbaar.
|
|
784
|
-
[ ] Naar achteren: nieuwe leverdatum zichtbaar + klantoptie + reden.
|
|
785
|
-
[ ] Opslaan gaat via logistics_reschedule_order, nergens een eigen UPDATE.
|
|
874
|
+
body: `LEES DIT EERST — hoe je deze prompt uitvoert
|
|
875
|
+
|
|
876
|
+
Deze prompt beschrijft één nieuwe functie in de Afhandeling-module: "Order
|
|
877
|
+
verzetten". Je bouwt hem volledig, niet gedeeltelijk. Alles wat hieronder staat
|
|
878
|
+
is verplicht. Er is GEEN eigen rekenwerk: de Logistics Engine levert twee kant-en-
|
|
879
|
+
klare database-functies, jij bouwt alleen het scherm eromheen en toont wat de
|
|
880
|
+
Engine teruggeeft.
|
|
881
|
+
|
|
882
|
+
Concreet ben je klaar als dit alle vier waar is:
|
|
883
|
+
1. Er is een knop "Verzetten" bij een order (planning-/agenda-/leverscherm).
|
|
884
|
+
2. Het dialoogvenster toont een DAGKEUZE en een OPHAALTIJD (van/tot).
|
|
885
|
+
3. Voor het opslaan is logistics_reschedule_preview aangeroepen en wordt de
|
|
886
|
+
uitkomst daarvan letterlijk aan de gebruiker getoond.
|
|
887
|
+
4. Opslaan gebeurt uitsluitend met logistics_reschedule_order.
|
|
888
|
+
|
|
889
|
+
------------------------------------------------------------------
|
|
890
|
+
DE TWEE REGELS DIE DE GEBRUIKER WIL
|
|
891
|
+
------------------------------------------------------------------
|
|
892
|
+
|
|
893
|
+
A. Order gaat NAAR VOREN (nieuwe ophaaldag is eerder dan de huidige)
|
|
894
|
+
-> Het AFLEVERMOMENT (leverdatum naar de klant) blijft ONGEWIJZIGD.
|
|
895
|
+
De order wordt dus eerder klaargemaakt en opgehaald, maar de klant krijgt
|
|
896
|
+
hem op dezelfde dag als afgesproken. Je verandert de leverdatum NIET.
|
|
897
|
+
Er gaat GEEN melding naar de klant.
|
|
898
|
+
|
|
899
|
+
B. Order gaat NAAR ACHTEREN (nieuwe ophaaldag is later)
|
|
900
|
+
-> Het aflevermoment schuift mee.
|
|
901
|
+
-> De gebruiker MOET in het dialoogvenster de keuze krijgen:
|
|
902
|
+
"Klant informeren over de nieuwe leverdatum" (aan/uit) plus een reden.
|
|
903
|
+
Staat het aan, dan zorgt de Engine voor de klantmelding. Bouw daar zelf
|
|
904
|
+
geen mailflow voor.
|
|
905
|
+
|
|
906
|
+
C. Alleen de OPHAALTIJD wijzigen (zelfde dag, andere van/tot-tijd) mag altijd
|
|
907
|
+
en geldt niet als verzetten: geen klantmelding, leverdatum blijft gelijk.
|
|
908
|
+
|
|
909
|
+
------------------------------------------------------------------
|
|
910
|
+
STAP 1 — VOORVERTONING (verplicht vóór opslaan)
|
|
911
|
+
------------------------------------------------------------------
|
|
912
|
+
const { data: preview } = await supabase.rpc("logistics_reschedule_preview", {
|
|
913
|
+
p_order_ref: "SO-12345", // orders.order_number
|
|
914
|
+
p_pickup_date: "2026-08-07", // nieuwe ophaaldag (YYYY-MM-DD), null = ongewijzigd
|
|
915
|
+
p_pickup_from: "06:00", // nieuwe starttijd, null = ongewijzigd
|
|
916
|
+
p_pickup_to: "09:00", // nieuwe eindtijd, null = ongewijzigd
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
preview bevat:
|
|
920
|
+
{
|
|
921
|
+
ok: true,
|
|
922
|
+
orderRef, orderId, bufferId, planLocked,
|
|
923
|
+
current: { pickupDate, pickupFrom, pickupTo, deliveryDate },
|
|
924
|
+
next: { pickupDate, pickupFrom, pickupTo, deliveryDate },
|
|
925
|
+
direction: "earlier" | "later" | "same",
|
|
926
|
+
dayShift: -2, // aantal dagen verschil
|
|
927
|
+
timeChanged: true,
|
|
928
|
+
keepDeliveryMoment: true, // true bij naar voren: leverdatum blijft
|
|
929
|
+
customerNoticeRequired: true, // true bij naar achteren: toon de klantoptie
|
|
930
|
+
affectedTasks: 8 // aantal taken dat opnieuw wordt ingepland
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
Wat je met deze velden DOET in het scherm:
|
|
934
|
+
- ok === false -> toon preview.error en blokkeer opslaan.
|
|
935
|
+
- direction === "earlier" -> toon: "Order wordt X dag(en) eerder opgehaald. Het
|
|
936
|
+
aflevermoment blijft {current.deliveryDate}." Verberg de klantoptie.
|
|
937
|
+
- direction === "later" -> toon: "Order wordt X dag(en) later. Nieuwe leverdatum:
|
|
938
|
+
{next.deliveryDate}." Toon de schakelaar "Klant informeren" (standaard AAN) en
|
|
939
|
+
een verplicht redenveld.
|
|
940
|
+
- direction === "same" && timeChanged -> toon alleen de nieuwe ophaaltijd.
|
|
941
|
+
- Toon altijd affectedTasks: "X taken worden opnieuw ingepland."
|
|
942
|
+
|
|
943
|
+
------------------------------------------------------------------
|
|
944
|
+
STAP 2 — OPSLAAN
|
|
945
|
+
------------------------------------------------------------------
|
|
946
|
+
const { data: result } = await supabase.rpc("logistics_reschedule_order", {
|
|
947
|
+
p_order_ref: "SO-12345",
|
|
948
|
+
p_pickup_date: "2026-08-07",
|
|
949
|
+
p_pickup_from: "06:00",
|
|
950
|
+
p_pickup_to: "09:00",
|
|
951
|
+
p_notify_customer: true, // alleen relevant bij direction "later"
|
|
952
|
+
p_reason: "Aanvoer bloemen vertraagd",
|
|
953
|
+
p_source_module: "afhandeling",
|
|
954
|
+
p_user_id: null,
|
|
955
|
+
});
|
|
956
|
+
// result = preview-velden + { applied: true, rescheduleId, delayAlertId,
|
|
957
|
+
// customerNotified, pickupMoment }
|
|
958
|
+
|
|
959
|
+
De Engine doet hierbij zelf al ALLES hieronder — doe dit dus niet nogmaals:
|
|
960
|
+
- orders.custom_fields.pickup_moment bijwerken ("YYYY-MM-DD|van|tot");
|
|
961
|
+
- leverdatum alleen aanpassen bij naar achteren;
|
|
962
|
+
- de order uit zijn orderbuffer halen zodat hij niet aan de oude dag vastzit;
|
|
963
|
+
- de klantmelding aanmaken als p_notify_customer true is;
|
|
964
|
+
- een order.changed-melding sturen en de hele takenketen (buffer, pick, controle,
|
|
965
|
+
printen, transport) opnieuw inplannen met logistics_schedule_tasks;
|
|
966
|
+
- het verzetten vastleggen in public.logistics_reschedules.
|
|
967
|
+
|
|
968
|
+
------------------------------------------------------------------
|
|
969
|
+
WAT JE ABSOLUUT NIET DOET
|
|
970
|
+
------------------------------------------------------------------
|
|
971
|
+
- Geen eigen UPDATE op orders, order_buffers, order_carts of logistics_tasks om
|
|
972
|
+
een datum of tijd te verzetten. Uitsluitend via de twee RPC's hierboven.
|
|
973
|
+
- Zelf planned_start / planned_end / due_at van taken herberekenen. Na het
|
|
974
|
+
opslaan lees je de taken gewoon opnieuw; ze staan dan al goed.
|
|
975
|
+
- Bij naar voren de leverdatum meeschuiven. Dat is expliciet fout.
|
|
976
|
+
- Bij naar achteren de klant informeren zonder dat de gebruiker dat heeft
|
|
977
|
+
aangevinkt, of een eigen mail sturen buiten de Engine om.
|
|
978
|
+
|
|
979
|
+
------------------------------------------------------------------
|
|
980
|
+
NA HET OPSLAAN
|
|
981
|
+
------------------------------------------------------------------
|
|
982
|
+
1. Herlaad de taken van deze order uit logistics_tasks (planned_start bepaalt
|
|
983
|
+
waar de order in de pickagenda en het leverscherm verschijnt).
|
|
984
|
+
2. Toon een bevestiging met de nieuwe ophaaldag, de ophaaltijd, de leverdatum en
|
|
985
|
+
of de klant is geïnformeerd (result.customerNotified).
|
|
986
|
+
3. De verzetgeschiedenis kun je tonen met:
|
|
987
|
+
supabase.from("logistics_reschedules").select("*").eq("order_ref", ref)
|
|
988
|
+
.order("created_at", { ascending: false });
|
|
989
|
+
|
|
990
|
+
------------------------------------------------------------------
|
|
991
|
+
CONTROLELIJST VOOR JEZELF (loop deze af voor je klaar meldt)
|
|
992
|
+
------------------------------------------------------------------
|
|
993
|
+
[ ] Knop "Verzetten" bestaat bij een order.
|
|
994
|
+
[ ] Dagkeuze én ophaaltijd van/tot zijn in te vullen.
|
|
995
|
+
[ ] preview wordt live aangeroepen bij elke wijziging in het formulier.
|
|
996
|
+
[ ] Naar voren: leverdatum ongewijzigd, geen klantoptie zichtbaar.
|
|
997
|
+
[ ] Naar achteren: nieuwe leverdatum zichtbaar + klantoptie + reden.
|
|
998
|
+
[ ] Opslaan gaat via logistics_reschedule_order, nergens een eigen UPDATE.
|
|
786
999
|
[ ] Na opslaan worden de taken opnieuw geladen en klopt de agenda.`,
|
|
787
1000
|
},
|
|
788
1001
|
{
|
|
@@ -790,40 +1003,40 @@ CONTROLELIJST VOOR JEZELF (loop deze af voor je klaar meldt)
|
|
|
790
1003
|
title: "Capaciteitswaarschuwing tonen in de pick agenda",
|
|
791
1004
|
date: "2026-08-04",
|
|
792
1005
|
summary: "Nieuwe eis bovenop prompt 1 t/m 5: als er op een dag meer karren gepland staan dan er met het beschikbare personeel gepickt kunnen worden, moet de planning dat zichtbaar waarschuwen.",
|
|
793
|
-
body: `LEES DIT EERST
|
|
794
|
-
|
|
795
|
-
De Logistics Engine rekent per pickdag uit hoeveel picktijd alle geplande karren
|
|
796
|
-
kosten en hoeveel picktijd er beschikbaar is (aantal medewerkers x werktijden uit
|
|
797
|
-
"4. Pickstations"). Jij rekent NIETS zelf uit; je toont alleen wat de Engine geeft.
|
|
798
|
-
|
|
799
|
-
STAP 1 — BEREKENEN (bij het openen van een week/dag)
|
|
800
|
-
const { data: dagen } = await supabase.rpc("logistics_capacity_day_check", {
|
|
801
|
-
p_from: "2026-08-03", // eerste dag van de getoonde periode
|
|
802
|
-
p_to: "2026-08-09", // laatste dag
|
|
803
|
-
});
|
|
804
|
-
|
|
805
|
-
dagen is een array met per dag:
|
|
806
|
-
{ date, carts, requiredMinutes, availableMinutes, shortageMinutes, staff }
|
|
807
|
-
|
|
808
|
-
STAP 2 — OPEN WAARSCHUWINGEN LEZEN
|
|
809
|
-
const { data: alerts } = await supabase
|
|
810
|
-
.from("logistics_capacity_alerts")
|
|
811
|
-
.select("plan_date, required_minutes, available_minutes, shortage_minutes, carts_total, carts_short")
|
|
812
|
-
.eq("status", "open");
|
|
813
|
-
|
|
814
|
-
STAP 3 — TONEN (verplicht)
|
|
815
|
-
- Weekoverzicht: elke dag met shortageMinutes > 0 krijgt een duidelijk zichtbare
|
|
816
|
-
waarschuwing (amber/rood) met de tekst:
|
|
817
|
-
"Te weinig capaciteit: {carts} karren vragen {requiredMinutes} min picktijd,
|
|
818
|
-
beschikbaar is {availableMinutes} min ({staff} medewerkers).
|
|
819
|
-
Circa {carts_short} karren passen niet op deze dag."
|
|
820
|
-
- Dagdetails: dezelfde waarschuwing bovenaan het dagscherm.
|
|
821
|
-
- Dagen zonder tekort krijgen GEEN waarschuwing.
|
|
822
|
-
- Verzin geen eigen drempels, kleuren-logica of eigen berekening van picktijd.
|
|
823
|
-
|
|
824
|
-
CONTROLELIJST
|
|
825
|
-
[ ] logistics_capacity_day_check wordt aangeroepen bij elke periodewissel.
|
|
826
|
-
[ ] Dagen met tekort tonen de waarschuwing in het weekoverzicht én in dagdetails.
|
|
1006
|
+
body: `LEES DIT EERST
|
|
1007
|
+
|
|
1008
|
+
De Logistics Engine rekent per pickdag uit hoeveel picktijd alle geplande karren
|
|
1009
|
+
kosten en hoeveel picktijd er beschikbaar is (aantal medewerkers x werktijden uit
|
|
1010
|
+
"4. Pickstations"). Jij rekent NIETS zelf uit; je toont alleen wat de Engine geeft.
|
|
1011
|
+
|
|
1012
|
+
STAP 1 — BEREKENEN (bij het openen van een week/dag)
|
|
1013
|
+
const { data: dagen } = await supabase.rpc("logistics_capacity_day_check", {
|
|
1014
|
+
p_from: "2026-08-03", // eerste dag van de getoonde periode
|
|
1015
|
+
p_to: "2026-08-09", // laatste dag
|
|
1016
|
+
});
|
|
1017
|
+
|
|
1018
|
+
dagen is een array met per dag:
|
|
1019
|
+
{ date, carts, requiredMinutes, availableMinutes, shortageMinutes, staff }
|
|
1020
|
+
|
|
1021
|
+
STAP 2 — OPEN WAARSCHUWINGEN LEZEN
|
|
1022
|
+
const { data: alerts } = await supabase
|
|
1023
|
+
.from("logistics_capacity_alerts")
|
|
1024
|
+
.select("plan_date, required_minutes, available_minutes, shortage_minutes, carts_total, carts_short")
|
|
1025
|
+
.eq("status", "open");
|
|
1026
|
+
|
|
1027
|
+
STAP 3 — TONEN (verplicht)
|
|
1028
|
+
- Weekoverzicht: elke dag met shortageMinutes > 0 krijgt een duidelijk zichtbare
|
|
1029
|
+
waarschuwing (amber/rood) met de tekst:
|
|
1030
|
+
"Te weinig capaciteit: {carts} karren vragen {requiredMinutes} min picktijd,
|
|
1031
|
+
beschikbaar is {availableMinutes} min ({staff} medewerkers).
|
|
1032
|
+
Circa {carts_short} karren passen niet op deze dag."
|
|
1033
|
+
- Dagdetails: dezelfde waarschuwing bovenaan het dagscherm.
|
|
1034
|
+
- Dagen zonder tekort krijgen GEEN waarschuwing.
|
|
1035
|
+
- Verzin geen eigen drempels, kleuren-logica of eigen berekening van picktijd.
|
|
1036
|
+
|
|
1037
|
+
CONTROLELIJST
|
|
1038
|
+
[ ] logistics_capacity_day_check wordt aangeroepen bij elke periodewissel.
|
|
1039
|
+
[ ] Dagen met tekort tonen de waarschuwing in het weekoverzicht én in dagdetails.
|
|
827
1040
|
[ ] De getoonde cijfers komen letterlijk uit de Engine.`,
|
|
828
1041
|
},
|
|
829
1042
|
{
|
|
@@ -831,31 +1044,31 @@ CONTROLELIJST
|
|
|
831
1044
|
title: "Geen capaciteitsmeldingen in Planning en leveringen",
|
|
832
1045
|
date: "2026-08-04",
|
|
833
1046
|
summary: "Nieuwe eis bovenop prompt 1 t/m 6: verwijder alle capaciteits- en foutmeldingen uit de agenda Planning en leveringen; de Engine blijft op de achtergrond controleren.",
|
|
834
|
-
body: `AANVULLING op prompt 1 t/m 6. Deze nieuwste eis vervangt uitsluitend de
|
|
835
|
-
zichtbare meldingen uit prompt 5 en 6 binnen het scherm "Planning en leveringen".
|
|
836
|
-
|
|
837
|
-
Verwijder uit het weekoverzicht en de dagdetails van "Planning en leveringen":
|
|
838
|
-
- de melding "Te weinig capaciteit";
|
|
839
|
-
- aantallen tekortkomende minuten, medewerkers of karren;
|
|
840
|
-
- rode, amberkleurige of andere fout-/waarschuwingsblokken uit
|
|
841
|
-
public.logistics_capacity_alerts;
|
|
842
|
-
- foutmeldingen die afkomstig zijn van logistics_capacity_day_check.
|
|
843
|
-
|
|
844
|
-
De agenda toont alleen de planning, bestellingen, karren, planten en statussen.
|
|
845
|
-
Een tekort mag de agenda niet visueel blokkeren of als foutmelding worden getoond.
|
|
846
|
-
|
|
847
|
-
BELANGRIJK — alleen de zichtbaarheid vervalt:
|
|
848
|
-
- Blijf logistics_capacity_day_check en logistics_capacity_plan_day uitvoeren waar
|
|
849
|
-
dat nodig is voor de planning en automatische herverdeling.
|
|
850
|
-
- Verwijder of sluit public.logistics_capacity_alerts niet.
|
|
851
|
-
- Capaciteitsmeldingen blijven beschikbaar in het Regieoverzicht van de Logistics
|
|
852
|
-
Engine en in het centrale Meldingencentrum.
|
|
853
|
-
- Verberg echte technische fouten niet: een mislukte laad- of opslagactie mag nog
|
|
854
|
-
steeds via een normale toast worden gemeld, maar niet als melding in de agenda.
|
|
855
|
-
|
|
856
|
-
CONTROLELIJST
|
|
857
|
-
[ ] In Planning en leveringen staat bij geen enkele dag een capaciteitsmelding.
|
|
858
|
-
[ ] Het openen en wisselen van weken blijft de Engine-berekening uitvoeren.
|
|
1047
|
+
body: `AANVULLING op prompt 1 t/m 6. Deze nieuwste eis vervangt uitsluitend de
|
|
1048
|
+
zichtbare meldingen uit prompt 5 en 6 binnen het scherm "Planning en leveringen".
|
|
1049
|
+
|
|
1050
|
+
Verwijder uit het weekoverzicht en de dagdetails van "Planning en leveringen":
|
|
1051
|
+
- de melding "Te weinig capaciteit";
|
|
1052
|
+
- aantallen tekortkomende minuten, medewerkers of karren;
|
|
1053
|
+
- rode, amberkleurige of andere fout-/waarschuwingsblokken uit
|
|
1054
|
+
public.logistics_capacity_alerts;
|
|
1055
|
+
- foutmeldingen die afkomstig zijn van logistics_capacity_day_check.
|
|
1056
|
+
|
|
1057
|
+
De agenda toont alleen de planning, bestellingen, karren, planten en statussen.
|
|
1058
|
+
Een tekort mag de agenda niet visueel blokkeren of als foutmelding worden getoond.
|
|
1059
|
+
|
|
1060
|
+
BELANGRIJK — alleen de zichtbaarheid vervalt:
|
|
1061
|
+
- Blijf logistics_capacity_day_check en logistics_capacity_plan_day uitvoeren waar
|
|
1062
|
+
dat nodig is voor de planning en automatische herverdeling.
|
|
1063
|
+
- Verwijder of sluit public.logistics_capacity_alerts niet.
|
|
1064
|
+
- Capaciteitsmeldingen blijven beschikbaar in het Regieoverzicht van de Logistics
|
|
1065
|
+
Engine en in het centrale Meldingencentrum.
|
|
1066
|
+
- Verberg echte technische fouten niet: een mislukte laad- of opslagactie mag nog
|
|
1067
|
+
steeds via een normale toast worden gemeld, maar niet als melding in de agenda.
|
|
1068
|
+
|
|
1069
|
+
CONTROLELIJST
|
|
1070
|
+
[ ] In Planning en leveringen staat bij geen enkele dag een capaciteitsmelding.
|
|
1071
|
+
[ ] Het openen en wisselen van weken blijft de Engine-berekening uitvoeren.
|
|
859
1072
|
[ ] Het Regieoverzicht kan de capaciteitsmeldingen nog steeds tonen.`,
|
|
860
1073
|
},
|
|
861
1074
|
{
|
|
@@ -863,28 +1076,28 @@ CONTROLELIJST
|
|
|
863
1076
|
title: "Tekort in medewerkers tonen in de capaciteitswaarschuwing",
|
|
864
1077
|
date: "2026-08-04",
|
|
865
1078
|
summary: "Nieuwe eis bovenop prompt 1 t/m 7: elke capaciteitswaarschuwing vermeldt hoeveel medewerkers er tekort zijn, niet alleen minuten en karren.",
|
|
866
|
-
body: `AANVULLING op prompt 6. De waarschuwing blijft weg uit "Planning en
|
|
867
|
-
leveringen" (prompt 7); overal waar je hem WEL toont (Regieoverzicht,
|
|
868
|
-
Meldingencentrum, dagdetails buiten de agenda) geldt onderstaande tekst.
|
|
869
|
-
|
|
870
|
-
BEREKENING (verplicht, geen eigen variant)
|
|
871
|
-
minutenPerMedewerker = availableMinutes / staff // staff > 0
|
|
872
|
-
medewerkersTekort = Math.ceil(shortageMinutes / minutenPerMedewerker)
|
|
873
|
-
Is staff 0 of availableMinutes 0, toon dan geen aantal maar de tekst
|
|
874
|
-
"vul het gemiddeld aantal medewerkers in bij 3. Order picken".
|
|
875
|
-
|
|
876
|
-
TEKST
|
|
877
|
-
"Te weinig capaciteit: {carts} karren vragen {requiredMinutes} min picktijd,
|
|
878
|
-
beschikbaar is {availableMinutes} min ({staff} medewerkers).
|
|
879
|
-
Je komt {medewerkersTekort} medewerker(s) tekort — samen
|
|
880
|
-
{staff + medewerkersTekort} nodig. Circa {carts_short} karren passen niet
|
|
881
|
-
op deze dag."
|
|
882
|
-
|
|
883
|
-
Gebruik enkelvoud "medewerker" bij 1, anders "medewerkers".
|
|
884
|
-
|
|
885
|
-
CONTROLELIJST
|
|
886
|
-
[ ] Elke zichtbare capaciteitswaarschuwing noemt het tekort in medewerkers.
|
|
887
|
-
[ ] Het aantal komt uit de formule hierboven, niet uit een eigen aanname.
|
|
1079
|
+
body: `AANVULLING op prompt 6. De waarschuwing blijft weg uit "Planning en
|
|
1080
|
+
leveringen" (prompt 7); overal waar je hem WEL toont (Regieoverzicht,
|
|
1081
|
+
Meldingencentrum, dagdetails buiten de agenda) geldt onderstaande tekst.
|
|
1082
|
+
|
|
1083
|
+
BEREKENING (verplicht, geen eigen variant)
|
|
1084
|
+
minutenPerMedewerker = availableMinutes / staff // staff > 0
|
|
1085
|
+
medewerkersTekort = Math.ceil(shortageMinutes / minutenPerMedewerker)
|
|
1086
|
+
Is staff 0 of availableMinutes 0, toon dan geen aantal maar de tekst
|
|
1087
|
+
"vul het gemiddeld aantal medewerkers in bij 3. Order picken".
|
|
1088
|
+
|
|
1089
|
+
TEKST
|
|
1090
|
+
"Te weinig capaciteit: {carts} karren vragen {requiredMinutes} min picktijd,
|
|
1091
|
+
beschikbaar is {availableMinutes} min ({staff} medewerkers).
|
|
1092
|
+
Je komt {medewerkersTekort} medewerker(s) tekort — samen
|
|
1093
|
+
{staff + medewerkersTekort} nodig. Circa {carts_short} karren passen niet
|
|
1094
|
+
op deze dag."
|
|
1095
|
+
|
|
1096
|
+
Gebruik enkelvoud "medewerker" bij 1, anders "medewerkers".
|
|
1097
|
+
|
|
1098
|
+
CONTROLELIJST
|
|
1099
|
+
[ ] Elke zichtbare capaciteitswaarschuwing noemt het tekort in medewerkers.
|
|
1100
|
+
[ ] Het aantal komt uit de formule hierboven, niet uit een eigen aanname.
|
|
888
1101
|
[ ] Zonder ingevuld personeel toont de melding de invulhint in plaats van 0.`,
|
|
889
1102
|
},
|
|
890
1103
|
{
|
|
@@ -893,23 +1106,23 @@ CONTROLELIJST
|
|
|
893
1106
|
date: "2026-08-19",
|
|
894
1107
|
summary: "Nieuwe orders worden binnen seconden automatisch ingedeeld door de Engine.",
|
|
895
1108
|
withSharedContract: false,
|
|
896
|
-
body: `De Logistics Engine deelt nieuwe en gewijzigde orders voortaan automatisch in.
|
|
897
|
-
Een order komt bij binnenkomst in de wachtrij public.logistics_plan_queue en wordt
|
|
898
|
-
direct verwerkt (doorgaans binnen enkele seconden, uiterlijk binnen 2 minuten).
|
|
899
|
-
|
|
900
|
-
REGELS
|
|
901
|
-
- Deel NOOIT zelf orders in en maak geen eigen taken aan als er nog geen indeling is.
|
|
902
|
-
- Toon de melding "wacht op een indeling van de Logistics Engine" pas als de order
|
|
903
|
-
langer dan 2 minuten geleden is aangemaakt/gewijzigd EN er nog geen taken zijn.
|
|
904
|
-
Binnen die marge toon je niets — dat is normale verwerkingstijd.
|
|
905
|
-
- Ververs de weergave automatisch (realtime of polling) zodra taken verschijnen,
|
|
906
|
-
zodat de gebruiker niets hoeft te doen.
|
|
907
|
-
- Reserveringen (orders.is_reservation = true) en vastgezette orders
|
|
908
|
-
(orders.plan_locked_at gevuld) tel je nooit mee in deze melding.
|
|
909
|
-
|
|
910
|
-
CONTROLELIJST
|
|
911
|
-
[ ] Geen melding binnen 2 minuten na aanmaken/wijzigen van een order.
|
|
912
|
-
[ ] Geen eigen indeling of eigen taken als fallback.
|
|
1109
|
+
body: `De Logistics Engine deelt nieuwe en gewijzigde orders voortaan automatisch in.
|
|
1110
|
+
Een order komt bij binnenkomst in de wachtrij public.logistics_plan_queue en wordt
|
|
1111
|
+
direct verwerkt (doorgaans binnen enkele seconden, uiterlijk binnen 2 minuten).
|
|
1112
|
+
|
|
1113
|
+
REGELS
|
|
1114
|
+
- Deel NOOIT zelf orders in en maak geen eigen taken aan als er nog geen indeling is.
|
|
1115
|
+
- Toon de melding "wacht op een indeling van de Logistics Engine" pas als de order
|
|
1116
|
+
langer dan 2 minuten geleden is aangemaakt/gewijzigd EN er nog geen taken zijn.
|
|
1117
|
+
Binnen die marge toon je niets — dat is normale verwerkingstijd.
|
|
1118
|
+
- Ververs de weergave automatisch (realtime of polling) zodra taken verschijnen,
|
|
1119
|
+
zodat de gebruiker niets hoeft te doen.
|
|
1120
|
+
- Reserveringen (orders.is_reservation = true) en vastgezette orders
|
|
1121
|
+
(orders.plan_locked_at gevuld) tel je nooit mee in deze melding.
|
|
1122
|
+
|
|
1123
|
+
CONTROLELIJST
|
|
1124
|
+
[ ] Geen melding binnen 2 minuten na aanmaken/wijzigen van een order.
|
|
1125
|
+
[ ] Geen eigen indeling of eigen taken als fallback.
|
|
913
1126
|
[ ] Weergave werkt bij zonder handmatig verversen.`,
|
|
914
1127
|
},
|
|
915
1128
|
{
|
|
@@ -917,72 +1130,72 @@ CONTROLELIJST
|
|
|
917
1130
|
title: "Instellingen opschonen: planning en printen komen van de Engine/Layout maker",
|
|
918
1131
|
date: "2026-08-27",
|
|
919
1132
|
summary: "Nieuwe eis bovenop prompt 1 t/m 9: de settingscard 'Afhandeling — Planning' wordt opgeruimd.",
|
|
920
|
-
body: `AANVULLING op prompt 1 t/m 9 (die blijven gewoon geldig).
|
|
921
|
-
|
|
922
|
-
De settingscard "Afhandeling — Planning" bevat een aantal velden die inmiddels
|
|
923
|
-
worden bepaald door de Logistics Engine of de Layout maker. Deze module mag die
|
|
924
|
-
velden niet meer zelf uitlezen of tonen.
|
|
925
|
-
|
|
926
|
-
Haal weg uit de settingscard en bijbehorende schermen:
|
|
927
|
-
|
|
928
|
-
1. "Aantal pickdagen (werkdagen vóór ophaaldag)"
|
|
929
|
-
2. "Extra pickdagen bij stickers"
|
|
930
|
-
3. "Orderpickdagen (werkdagen)"
|
|
931
|
-
4. "Pickverdeling over werkdagen"
|
|
932
|
-
5. "Automatische Floriday-verwerking pauzeren"
|
|
933
|
-
6. "Afleverbrief automatisch printen"
|
|
934
|
-
7. "Werkplek (voor printen)"
|
|
935
|
-
|
|
936
|
-
Waarom deze velden overbodig zijn:
|
|
937
|
-
- Aantal pickdagen, extra pickdagen, orderpickdagen en pickverdeling worden
|
|
938
|
-
volledig bepaald door de Logistics Engine (stap 3 "Order picken" en
|
|
939
|
-
ophaalmomenten). De Engine plant planned_start en planned_end per taak.
|
|
940
|
-
- "Automatische Floriday-verwerking pauzeren" heeft geen lezer meer in deze
|
|
941
|
-
module.
|
|
942
|
-
- "Afleverbrief automatisch printen" is geen printerkeuze maar een trigger.
|
|
943
|
-
De Logistics Engine neemt die trigger over: Afhandeling maakt zelf geen
|
|
944
|
-
printopdrachten meer aan voor afleverbrieven, maar consumeert
|
|
945
|
-
print.shipping_note-taken uit public.logistics_tasks. De Engine bepaalt of
|
|
946
|
-
en wanneer een afleverbrief wordt vrijgegeven voor printen.
|
|
947
|
-
- "Werkplek (voor printen)" is overbodig omdat locatiegebonden printen het
|
|
948
|
-
domein is van de Logistics Engine (via print_plek_id in de taak-payload).
|
|
949
|
-
Zonder werkplek en zonder print_plek_id valt de Layout maker terug op de
|
|
950
|
-
standaardlayout of standaardregels voor documenttype "afleverbrief".
|
|
951
|
-
|
|
952
|
-
Printer-beslisvolgorde in de Layout maker:
|
|
953
|
-
|
|
954
|
-
1. printer_id op de opdracht (expliciet meegegeven)
|
|
955
|
-
2. print_plek_id -> regel van de printplek
|
|
956
|
-
3. werkplek -> printplek van die computer, dan werkplek-uitzondering
|
|
957
|
-
4. printer gekoppeld aan de (standaard)layout van het documenttype
|
|
958
|
-
5. standaardregel: documenttype + papierformaat
|
|
959
|
-
6. standaardregel: documenttype alleen
|
|
960
|
-
|
|
961
|
-
Zonder werkplek en zonder print_plek_id slaat een afleverbrief-print stap 1-3
|
|
962
|
-
over en komt hij op de printer van de standaardlayout of de standaardregels
|
|
963
|
-
uit. Wil men locatiegebonden printen, dan moet dat via de Logistics Engine
|
|
964
|
-
(print_plek_id) of een expliciete printer_id op de opdracht.
|
|
965
|
-
|
|
966
|
-
Wat blijft staan:
|
|
967
|
-
- "Aanmeldmail vervoerders" (+ minuten vóór aanmelddeadline en e-mail-doeleinde)
|
|
968
|
-
blijft bestaan. Dat is eigen functionaliteit van de Afhandeling-module.
|
|
969
|
-
|
|
970
|
-
Voorwaarde:
|
|
971
|
-
Er moet minstens één printer voor documenttype "afleverbrief" zijn ingesteld
|
|
972
|
-
in de Layout maker: hetzij aan de standaardlayout, hetzij via
|
|
973
|
-
Layouts en printers -> Standaardregels. Ontbreekt die, dan mislukt de
|
|
974
|
-
automatische print met de leesbare foutmelding:
|
|
975
|
-
"Geen printer voor afleverbrief — stel dit in bij Layouts en printers → Routering".
|
|
976
|
-
|
|
977
|
-
Database:
|
|
978
|
-
- Droppen geen kolommen of rijen. De kolommen in afhandeling_settings blijven
|
|
979
|
-
staan, maar worden niet meer gelezen of getoond.
|
|
980
|
-
|
|
981
|
-
CONTROLELIJST
|
|
982
|
-
[ ] Alle zeven velden zijn verwijderd uit de settingscard.
|
|
983
|
-
[ ] Aanmeldmail-instellingen zijn nog zichtbaar en werken nog.
|
|
984
|
-
[ ] Er worden geen eigen planningsberekeningen meer gedaan; alles komt uit public.logistics_tasks.
|
|
985
|
-
[ ] Afleverbrieven worden alleen nog aangemaakt via print.shipping_note-taken, niet spontaan.
|
|
1133
|
+
body: `AANVULLING op prompt 1 t/m 9 (die blijven gewoon geldig).
|
|
1134
|
+
|
|
1135
|
+
De settingscard "Afhandeling — Planning" bevat een aantal velden die inmiddels
|
|
1136
|
+
worden bepaald door de Logistics Engine of de Layout maker. Deze module mag die
|
|
1137
|
+
velden niet meer zelf uitlezen of tonen.
|
|
1138
|
+
|
|
1139
|
+
Haal weg uit de settingscard en bijbehorende schermen:
|
|
1140
|
+
|
|
1141
|
+
1. "Aantal pickdagen (werkdagen vóór ophaaldag)"
|
|
1142
|
+
2. "Extra pickdagen bij stickers"
|
|
1143
|
+
3. "Orderpickdagen (werkdagen)"
|
|
1144
|
+
4. "Pickverdeling over werkdagen"
|
|
1145
|
+
5. "Automatische Floriday-verwerking pauzeren"
|
|
1146
|
+
6. "Afleverbrief automatisch printen"
|
|
1147
|
+
7. "Werkplek (voor printen)"
|
|
1148
|
+
|
|
1149
|
+
Waarom deze velden overbodig zijn:
|
|
1150
|
+
- Aantal pickdagen, extra pickdagen, orderpickdagen en pickverdeling worden
|
|
1151
|
+
volledig bepaald door de Logistics Engine (stap 3 "Order picken" en
|
|
1152
|
+
ophaalmomenten). De Engine plant planned_start en planned_end per taak.
|
|
1153
|
+
- "Automatische Floriday-verwerking pauzeren" heeft geen lezer meer in deze
|
|
1154
|
+
module.
|
|
1155
|
+
- "Afleverbrief automatisch printen" is geen printerkeuze maar een trigger.
|
|
1156
|
+
De Logistics Engine neemt die trigger over: Afhandeling maakt zelf geen
|
|
1157
|
+
printopdrachten meer aan voor afleverbrieven, maar consumeert
|
|
1158
|
+
print.shipping_note-taken uit public.logistics_tasks. De Engine bepaalt of
|
|
1159
|
+
en wanneer een afleverbrief wordt vrijgegeven voor printen.
|
|
1160
|
+
- "Werkplek (voor printen)" is overbodig omdat locatiegebonden printen het
|
|
1161
|
+
domein is van de Logistics Engine (via print_plek_id in de taak-payload).
|
|
1162
|
+
Zonder werkplek en zonder print_plek_id valt de Layout maker terug op de
|
|
1163
|
+
standaardlayout of standaardregels voor documenttype "afleverbrief".
|
|
1164
|
+
|
|
1165
|
+
Printer-beslisvolgorde in de Layout maker:
|
|
1166
|
+
|
|
1167
|
+
1. printer_id op de opdracht (expliciet meegegeven)
|
|
1168
|
+
2. print_plek_id -> regel van de printplek
|
|
1169
|
+
3. werkplek -> printplek van die computer, dan werkplek-uitzondering
|
|
1170
|
+
4. printer gekoppeld aan de (standaard)layout van het documenttype
|
|
1171
|
+
5. standaardregel: documenttype + papierformaat
|
|
1172
|
+
6. standaardregel: documenttype alleen
|
|
1173
|
+
|
|
1174
|
+
Zonder werkplek en zonder print_plek_id slaat een afleverbrief-print stap 1-3
|
|
1175
|
+
over en komt hij op de printer van de standaardlayout of de standaardregels
|
|
1176
|
+
uit. Wil men locatiegebonden printen, dan moet dat via de Logistics Engine
|
|
1177
|
+
(print_plek_id) of een expliciete printer_id op de opdracht.
|
|
1178
|
+
|
|
1179
|
+
Wat blijft staan:
|
|
1180
|
+
- "Aanmeldmail vervoerders" (+ minuten vóór aanmelddeadline en e-mail-doeleinde)
|
|
1181
|
+
blijft bestaan. Dat is eigen functionaliteit van de Afhandeling-module.
|
|
1182
|
+
|
|
1183
|
+
Voorwaarde:
|
|
1184
|
+
Er moet minstens één printer voor documenttype "afleverbrief" zijn ingesteld
|
|
1185
|
+
in de Layout maker: hetzij aan de standaardlayout, hetzij via
|
|
1186
|
+
Layouts en printers -> Standaardregels. Ontbreekt die, dan mislukt de
|
|
1187
|
+
automatische print met de leesbare foutmelding:
|
|
1188
|
+
"Geen printer voor afleverbrief — stel dit in bij Layouts en printers → Routering".
|
|
1189
|
+
|
|
1190
|
+
Database:
|
|
1191
|
+
- Droppen geen kolommen of rijen. De kolommen in afhandeling_settings blijven
|
|
1192
|
+
staan, maar worden niet meer gelezen of getoond.
|
|
1193
|
+
|
|
1194
|
+
CONTROLELIJST
|
|
1195
|
+
[ ] Alle zeven velden zijn verwijderd uit de settingscard.
|
|
1196
|
+
[ ] Aanmeldmail-instellingen zijn nog zichtbaar en werken nog.
|
|
1197
|
+
[ ] Er worden geen eigen planningsberekeningen meer gedaan; alles komt uit public.logistics_tasks.
|
|
1198
|
+
[ ] Afleverbrieven worden alleen nog aangemaakt via print.shipping_note-taken, niet spontaan.
|
|
986
1199
|
[ ] De kolommen in afhandeling_settings zijn niet gedropt.`,
|
|
987
1200
|
},
|
|
988
1201
|
{
|
|
@@ -990,51 +1203,51 @@ CONTROLELIJST
|
|
|
990
1203
|
title: "Controle karren rechtstreeks uit de agenda van de Engine",
|
|
991
1204
|
date: "2026-09-01",
|
|
992
1205
|
summary: "De controlepagina toont alle karren van de pickagenda van vandaag, inclusief gemengde, ongeprinte en nog niet ingedeelde karren.",
|
|
993
|
-
body: `AANVULLING op prompt 1 t/m 10 (die blijven geldig).
|
|
994
|
-
|
|
995
|
-
GEMETEN PROBLEEM
|
|
996
|
-
Het scherm "Controle karren" blijft leeg doordat cartControl.functions.ts zelf
|
|
997
|
-
alleen logistics_tasks van type load.compose leest, met owner_module =
|
|
998
|
-
"afhandeling" en een beperkte statuslijst. De pickagenda wordt echter bepaald
|
|
999
|
-
door pick.execute. Daardoor kan de agenda wel orders tonen terwijl de controlelijst
|
|
1000
|
-
0 karren toont.
|
|
1001
|
-
|
|
1002
|
-
BOUW DIT
|
|
1003
|
-
- Verwijder loadEngineCartsForToday en de lokale datum-/taakfilter als bron voor
|
|
1004
|
-
de controlelijst.
|
|
1005
|
-
- Laat getTodaysControlCarts rechtstreeks deze RPC aanroepen:
|
|
1006
|
-
|
|
1007
|
-
const { data, error } = await supabase.rpc("control_get_todays_carts");
|
|
1008
|
-
if (error) throw new Error(error.message);
|
|
1009
|
-
|
|
1010
|
-
- Map iedere RPC-rij naar ControlCart. Gebruik cart_number_id als stabiele sleutel,
|
|
1011
|
-
order_id, order_source, cart_index, pick_date, status, printed_at en
|
|
1012
|
-
printed_today letterlijk uit het resultaat.
|
|
1013
|
-
- De RPC is de enige bron voor welke karren vandaag zichtbaar zijn. Voeg in de
|
|
1014
|
-
frontend geen extra filter toe op load.compose, owner_module, taskstatus,
|
|
1015
|
-
orderstatus of printedCount.
|
|
1016
|
-
- De RPC bevat bewust:
|
|
1017
|
-
1. alle pick.execute-taken met planned_start vandaag in Europe/Amsterdam;
|
|
1018
|
-
2. alle orders die vandaag zijn aangemeld of uitgeprint;
|
|
1019
|
-
3. normale én gemengde karren via order_cart_items -> order_items;
|
|
1020
|
-
4. tijdelijke regels voor agenda-orders die nog geen order_carts hebben.
|
|
1021
|
-
- Gebruik printed_today voor de kolom "Uitgeprint". Een kar hoeft niet geprint te
|
|
1022
|
-
zijn om zichtbaar en goed te keuren te zijn.
|
|
1023
|
-
- Ververs bij wijzigingen in logistics_tasks, pick_queue, print_jobs, order_carts,
|
|
1024
|
-
order_cart_items en cart_numbers, plus de bestaande polling.
|
|
1025
|
-
- Gebruik dezelfde RPC-uitkomst ook als basis voor submitControlSession, zodat de
|
|
1026
|
-
getoonde en afgemelde verzameling nooit van elkaar afwijkt.
|
|
1027
|
-
|
|
1028
|
-
NIET DOEN
|
|
1029
|
-
- Niet terugvallen op loadTodaysPickstationOrders als de RPC nul regels geeft.
|
|
1030
|
-
- Niet zelf kar-aantallen herberekenen.
|
|
1031
|
-
- Geen project-ref, Supabase-URL of datum hardcoden.
|
|
1032
|
-
|
|
1033
|
-
CONTROLELIJST
|
|
1034
|
-
[ ] Een ongeprinte kar op de pickagenda van vandaag staat in Controle karren.
|
|
1035
|
-
[ ] Een vandaag geprinte kar met een oudere pickdatum blijft zichtbaar.
|
|
1036
|
-
[ ] Een gemengde kar verschijnt zonder dubbele regels.
|
|
1037
|
-
[ ] De teller en tabel gebruiken exact dezelfde RPC-data.
|
|
1206
|
+
body: `AANVULLING op prompt 1 t/m 10 (die blijven geldig).
|
|
1207
|
+
|
|
1208
|
+
GEMETEN PROBLEEM
|
|
1209
|
+
Het scherm "Controle karren" blijft leeg doordat cartControl.functions.ts zelf
|
|
1210
|
+
alleen logistics_tasks van type load.compose leest, met owner_module =
|
|
1211
|
+
"afhandeling" en een beperkte statuslijst. De pickagenda wordt echter bepaald
|
|
1212
|
+
door pick.execute. Daardoor kan de agenda wel orders tonen terwijl de controlelijst
|
|
1213
|
+
0 karren toont.
|
|
1214
|
+
|
|
1215
|
+
BOUW DIT
|
|
1216
|
+
- Verwijder loadEngineCartsForToday en de lokale datum-/taakfilter als bron voor
|
|
1217
|
+
de controlelijst.
|
|
1218
|
+
- Laat getTodaysControlCarts rechtstreeks deze RPC aanroepen:
|
|
1219
|
+
|
|
1220
|
+
const { data, error } = await supabase.rpc("control_get_todays_carts");
|
|
1221
|
+
if (error) throw new Error(error.message);
|
|
1222
|
+
|
|
1223
|
+
- Map iedere RPC-rij naar ControlCart. Gebruik cart_number_id als stabiele sleutel,
|
|
1224
|
+
order_id, order_source, cart_index, pick_date, status, printed_at en
|
|
1225
|
+
printed_today letterlijk uit het resultaat.
|
|
1226
|
+
- De RPC is de enige bron voor welke karren vandaag zichtbaar zijn. Voeg in de
|
|
1227
|
+
frontend geen extra filter toe op load.compose, owner_module, taskstatus,
|
|
1228
|
+
orderstatus of printedCount.
|
|
1229
|
+
- De RPC bevat bewust:
|
|
1230
|
+
1. alle pick.execute-taken met planned_start vandaag in Europe/Amsterdam;
|
|
1231
|
+
2. alle orders die vandaag zijn aangemeld of uitgeprint;
|
|
1232
|
+
3. normale én gemengde karren via order_cart_items -> order_items;
|
|
1233
|
+
4. tijdelijke regels voor agenda-orders die nog geen order_carts hebben.
|
|
1234
|
+
- Gebruik printed_today voor de kolom "Uitgeprint". Een kar hoeft niet geprint te
|
|
1235
|
+
zijn om zichtbaar en goed te keuren te zijn.
|
|
1236
|
+
- Ververs bij wijzigingen in logistics_tasks, pick_queue, print_jobs, order_carts,
|
|
1237
|
+
order_cart_items en cart_numbers, plus de bestaande polling.
|
|
1238
|
+
- Gebruik dezelfde RPC-uitkomst ook als basis voor submitControlSession, zodat de
|
|
1239
|
+
getoonde en afgemelde verzameling nooit van elkaar afwijkt.
|
|
1240
|
+
|
|
1241
|
+
NIET DOEN
|
|
1242
|
+
- Niet terugvallen op loadTodaysPickstationOrders als de RPC nul regels geeft.
|
|
1243
|
+
- Niet zelf kar-aantallen herberekenen.
|
|
1244
|
+
- Geen project-ref, Supabase-URL of datum hardcoden.
|
|
1245
|
+
|
|
1246
|
+
CONTROLELIJST
|
|
1247
|
+
[ ] Een ongeprinte kar op de pickagenda van vandaag staat in Controle karren.
|
|
1248
|
+
[ ] Een vandaag geprinte kar met een oudere pickdatum blijft zichtbaar.
|
|
1249
|
+
[ ] Een gemengde kar verschijnt zonder dubbele regels.
|
|
1250
|
+
[ ] De teller en tabel gebruiken exact dezelfde RPC-data.
|
|
1038
1251
|
[ ] Goedkeuren verwerkt exact de zichtbare verzameling.`,
|
|
1039
1252
|
},
|
|
1040
1253
|
{
|
|
@@ -1042,50 +1255,50 @@ CONTROLELIJST
|
|
|
1042
1255
|
title: "Pick agenda: nooit een pickdag in het verleden",
|
|
1043
1256
|
date: "2026-09-01",
|
|
1044
1257
|
summary: "De weekagenda leest de pickdagen uit de Engine; orders met een verstreken pickmoment staan automatisch op vandaag.",
|
|
1045
|
-
body: `AANVULLING op prompt 1 t/m 11 (die blijven geldig).
|
|
1046
|
-
|
|
1047
|
-
GEMETEN PROBLEEM
|
|
1048
|
-
De weekagenda toont orders op maandag 31 aug terwijl het dinsdag 1 sep is. In
|
|
1049
|
-
public.logistics_tasks staat geen enkele open pick.execute-taak in het verleden:
|
|
1050
|
-
de Engine klemt planned_start al op nu. De agenda rekent dus nog zelf een pickdag
|
|
1051
|
-
uit (delivery_date minus pick_days), en die kan in het verleden liggen.
|
|
1052
|
-
|
|
1053
|
-
BOUW DIT
|
|
1054
|
-
- Verwijder de eigen pickdagberekening uit de weekagenda (delivery_date,
|
|
1055
|
-
pick_days_before_transport, max_workdays_earlier_pick, pick_weekdays).
|
|
1056
|
-
- Haal de agenda op met:
|
|
1057
|
-
|
|
1058
|
-
const { data, error } = await supabase.rpc("logistics_pick_agenda", {
|
|
1059
|
-
p_from: weekStartIso, // yyyy-mm-dd
|
|
1060
|
-
p_to: weekEndIso,
|
|
1061
|
-
});
|
|
1062
|
-
if (error) throw new Error(error.message);
|
|
1063
|
-
const dagen = Array.isArray(data) ? data : [];
|
|
1064
|
-
|
|
1065
|
-
- Kolommen per dag: pick_date, order_count, cart_count, plant_count,
|
|
1066
|
-
in_preparation, ready, shifted_count, orders (jsonb array met taskId, orderRef,
|
|
1067
|
-
status, carts, plants, shifted).
|
|
1068
|
-
- Vul de tegels "bestellingen", "karren" en "planten" met order_count, cart_count
|
|
1069
|
-
en plant_count. "In voorbereiding" = in_preparation, "Verzendklaar" = ready.
|
|
1070
|
-
- Toon bij shifted_count > 0 op die dag het label "te laat aangemeld" (zelfde
|
|
1071
|
-
betekenis als in de Regie-pagina van de Engine).
|
|
1072
|
-
- Dagen zonder rij tonen simpelweg nullen; niet zelf aanvullen met eigen data.
|
|
1073
|
-
- Ververs bij realtime-wijzigingen op logistics_tasks.
|
|
1074
|
-
|
|
1075
|
-
REGEL
|
|
1076
|
-
Een order kan nooit in het verleden gepickt worden. Elke open pick.execute-taak
|
|
1077
|
-
met een planning vóór vandaag wordt door de Engine (en nogmaals door deze RPC)
|
|
1078
|
-
op vandaag getoond. Bouw dus geen eigen "inhaal"- of "achterstand"-dag.
|
|
1079
|
-
|
|
1080
|
-
NIET DOEN
|
|
1081
|
-
- Geen eigen datumafronding, werkdagenlogica of tijdzoneconversie meer.
|
|
1082
|
-
- Geen orders uit de agenda filteren op status buiten wat de RPC teruggeeft.
|
|
1083
|
-
- Geen datum, project-ref of Supabase-URL hardcoden.
|
|
1084
|
-
|
|
1085
|
-
CONTROLELIJST
|
|
1086
|
-
[ ] De agenda toont geen enkele dag vóór vandaag met openstaande orders.
|
|
1087
|
-
[ ] Een gisteren aangemelde, nog niet gepickte order staat vandaag in de agenda.
|
|
1088
|
-
[ ] Tegels boven de agenda tellen exact op met de dagregels van de RPC.
|
|
1258
|
+
body: `AANVULLING op prompt 1 t/m 11 (die blijven geldig).
|
|
1259
|
+
|
|
1260
|
+
GEMETEN PROBLEEM
|
|
1261
|
+
De weekagenda toont orders op maandag 31 aug terwijl het dinsdag 1 sep is. In
|
|
1262
|
+
public.logistics_tasks staat geen enkele open pick.execute-taak in het verleden:
|
|
1263
|
+
de Engine klemt planned_start al op nu. De agenda rekent dus nog zelf een pickdag
|
|
1264
|
+
uit (delivery_date minus pick_days), en die kan in het verleden liggen.
|
|
1265
|
+
|
|
1266
|
+
BOUW DIT
|
|
1267
|
+
- Verwijder de eigen pickdagberekening uit de weekagenda (delivery_date,
|
|
1268
|
+
pick_days_before_transport, max_workdays_earlier_pick, pick_weekdays).
|
|
1269
|
+
- Haal de agenda op met:
|
|
1270
|
+
|
|
1271
|
+
const { data, error } = await supabase.rpc("logistics_pick_agenda", {
|
|
1272
|
+
p_from: weekStartIso, // yyyy-mm-dd
|
|
1273
|
+
p_to: weekEndIso,
|
|
1274
|
+
});
|
|
1275
|
+
if (error) throw new Error(error.message);
|
|
1276
|
+
const dagen = Array.isArray(data) ? data : [];
|
|
1277
|
+
|
|
1278
|
+
- Kolommen per dag: pick_date, order_count, cart_count, plant_count,
|
|
1279
|
+
in_preparation, ready, shifted_count, orders (jsonb array met taskId, orderRef,
|
|
1280
|
+
status, carts, plants, shifted).
|
|
1281
|
+
- Vul de tegels "bestellingen", "karren" en "planten" met order_count, cart_count
|
|
1282
|
+
en plant_count. "In voorbereiding" = in_preparation, "Verzendklaar" = ready.
|
|
1283
|
+
- Toon bij shifted_count > 0 op die dag het label "te laat aangemeld" (zelfde
|
|
1284
|
+
betekenis als in de Regie-pagina van de Engine).
|
|
1285
|
+
- Dagen zonder rij tonen simpelweg nullen; niet zelf aanvullen met eigen data.
|
|
1286
|
+
- Ververs bij realtime-wijzigingen op logistics_tasks.
|
|
1287
|
+
|
|
1288
|
+
REGEL
|
|
1289
|
+
Een order kan nooit in het verleden gepickt worden. Elke open pick.execute-taak
|
|
1290
|
+
met een planning vóór vandaag wordt door de Engine (en nogmaals door deze RPC)
|
|
1291
|
+
op vandaag getoond. Bouw dus geen eigen "inhaal"- of "achterstand"-dag.
|
|
1292
|
+
|
|
1293
|
+
NIET DOEN
|
|
1294
|
+
- Geen eigen datumafronding, werkdagenlogica of tijdzoneconversie meer.
|
|
1295
|
+
- Geen orders uit de agenda filteren op status buiten wat de RPC teruggeeft.
|
|
1296
|
+
- Geen datum, project-ref of Supabase-URL hardcoden.
|
|
1297
|
+
|
|
1298
|
+
CONTROLELIJST
|
|
1299
|
+
[ ] De agenda toont geen enkele dag vóór vandaag met openstaande orders.
|
|
1300
|
+
[ ] Een gisteren aangemelde, nog niet gepickte order staat vandaag in de agenda.
|
|
1301
|
+
[ ] Tegels boven de agenda tellen exact op met de dagregels van de RPC.
|
|
1089
1302
|
[ ] Verschoven orders krijgen het label "te laat aangemeld".`,
|
|
1090
1303
|
},
|
|
1091
1304
|
{
|
|
@@ -1093,40 +1306,40 @@ CONTROLELIJST
|
|
|
1093
1306
|
title: "Karrentelling: alles uit de gedeelde karindex",
|
|
1094
1307
|
date: "2026-09-01",
|
|
1095
1308
|
summary: "Agenda en Controle karren tellen karren uit logistics_cart_index; payload-velden zoals cartCount worden niet meer gebruikt.",
|
|
1096
|
-
body: `AANVULLING op prompt 1 t/m 12 (die blijven geldig).
|
|
1097
|
-
|
|
1098
|
-
GEMETEN PROBLEEM
|
|
1099
|
-
De pick agenda toonde 3517 karren voor vandaag terwijl Controle karren er 27
|
|
1100
|
-
toonde. Oorzaak: de agenda telde payload->>'cartCount' van taken op (dubbeltelling
|
|
1101
|
-
over meerdere taken per order), Controle telde cart_numbers. Beide waren fout.
|
|
1102
|
-
|
|
1103
|
-
WAT DE ENGINE NU LEVERT
|
|
1104
|
-
public.logistics_cart_index(p_from, p_to) — één rij per (order, kar):
|
|
1105
|
-
pick_date, order_uuid, order_number, order_source, cart_id, cart_index,
|
|
1106
|
-
cart_label, is_shared, task_status, shifted, printed_at.
|
|
1107
|
-
Daarop draaien logistics_pick_agenda en control_get_todays_carts.
|
|
1108
|
-
|
|
1109
|
-
BOUW DIT
|
|
1110
|
-
- Gebruik uitsluitend cart_count uit logistics_pick_agenda voor de dagtegels.
|
|
1111
|
-
Een gemengde kar telt per dag één keer, ook als meerdere orders erin zitten.
|
|
1112
|
-
- In een orderregel toont "carts" uit de orders-array het aantal karren waarin
|
|
1113
|
-
die order zit (gedeelde karren tellen daar wél mee).
|
|
1114
|
-
- Gebruik voor de controlelijst alleen control_get_todays_carts; die geeft nu
|
|
1115
|
-
cart_id als cart_number_id terug, ook voor karren zonder karnummer.
|
|
1116
|
-
- Verwijder elke lezing van payload->>'cartCount' en elke eigen count op
|
|
1117
|
-
order_carts.
|
|
1118
|
-
|
|
1119
|
-
CONTROLE OP AFWIJKING
|
|
1120
|
-
Roep bij het laden van de agenda eenmalig aan:
|
|
1121
|
-
|
|
1122
|
-
const { data } = await supabase.rpc("logistics_consistency_check");
|
|
1123
|
-
|
|
1124
|
-
Is ok === false, toon dan een discrete waarschuwing "aantallen worden opnieuw
|
|
1125
|
-
uitgelijnd" en niets meer. Niet zelf corrigeren.
|
|
1126
|
-
|
|
1127
|
-
CONTROLELIJST
|
|
1128
|
-
[ ] Agenda-karren van vandaag = karren in Controle karren.
|
|
1129
|
-
[ ] Geen enkel scherm leest nog cartCount uit een taak-payload.
|
|
1309
|
+
body: `AANVULLING op prompt 1 t/m 12 (die blijven geldig).
|
|
1310
|
+
|
|
1311
|
+
GEMETEN PROBLEEM
|
|
1312
|
+
De pick agenda toonde 3517 karren voor vandaag terwijl Controle karren er 27
|
|
1313
|
+
toonde. Oorzaak: de agenda telde payload->>'cartCount' van taken op (dubbeltelling
|
|
1314
|
+
over meerdere taken per order), Controle telde cart_numbers. Beide waren fout.
|
|
1315
|
+
|
|
1316
|
+
WAT DE ENGINE NU LEVERT
|
|
1317
|
+
public.logistics_cart_index(p_from, p_to) — één rij per (order, kar):
|
|
1318
|
+
pick_date, order_uuid, order_number, order_source, cart_id, cart_index,
|
|
1319
|
+
cart_label, is_shared, task_status, shifted, printed_at.
|
|
1320
|
+
Daarop draaien logistics_pick_agenda en control_get_todays_carts.
|
|
1321
|
+
|
|
1322
|
+
BOUW DIT
|
|
1323
|
+
- Gebruik uitsluitend cart_count uit logistics_pick_agenda voor de dagtegels.
|
|
1324
|
+
Een gemengde kar telt per dag één keer, ook als meerdere orders erin zitten.
|
|
1325
|
+
- In een orderregel toont "carts" uit de orders-array het aantal karren waarin
|
|
1326
|
+
die order zit (gedeelde karren tellen daar wél mee).
|
|
1327
|
+
- Gebruik voor de controlelijst alleen control_get_todays_carts; die geeft nu
|
|
1328
|
+
cart_id als cart_number_id terug, ook voor karren zonder karnummer.
|
|
1329
|
+
- Verwijder elke lezing van payload->>'cartCount' en elke eigen count op
|
|
1330
|
+
order_carts.
|
|
1331
|
+
|
|
1332
|
+
CONTROLE OP AFWIJKING
|
|
1333
|
+
Roep bij het laden van de agenda eenmalig aan:
|
|
1334
|
+
|
|
1335
|
+
const { data } = await supabase.rpc("logistics_consistency_check");
|
|
1336
|
+
|
|
1337
|
+
Is ok === false, toon dan een discrete waarschuwing "aantallen worden opnieuw
|
|
1338
|
+
uitgelijnd" en niets meer. Niet zelf corrigeren.
|
|
1339
|
+
|
|
1340
|
+
CONTROLELIJST
|
|
1341
|
+
[ ] Agenda-karren van vandaag = karren in Controle karren.
|
|
1342
|
+
[ ] Geen enkel scherm leest nog cartCount uit een taak-payload.
|
|
1130
1343
|
[ ] Orders van verwijderde bestellingen verschijnen nergens meer.`,
|
|
1131
1344
|
},
|
|
1132
1345
|
{
|
|
@@ -1134,44 +1347,232 @@ CONTROLELIJST
|
|
|
1134
1347
|
title: "Lever agenda uit dezelfde karindex als de pick agenda",
|
|
1135
1348
|
date: "2026-09-01",
|
|
1136
1349
|
summary: "De lever agenda leest logistics_delivery_agenda; geen eigen telling meer op orders of order_carts.",
|
|
1137
|
-
body: `AANVULLING op prompt 1 t/m 13 (die blijven geldig).
|
|
1138
|
-
|
|
1139
|
-
WAAROM
|
|
1140
|
-
Pick agenda, Controle karren en Verkoop tellen al uit dezelfde karindex. De
|
|
1141
|
-
lever agenda telde nog zelf. Daardoor konden dezelfde orders op twee schermen
|
|
1142
|
-
een ander aantal karren tonen.
|
|
1143
|
-
|
|
1144
|
-
WAT DE ENGINE LEVERT
|
|
1145
|
-
public.logistics_delivery_agenda(p_from date, p_to date) — één rij per leverdag:
|
|
1146
|
-
delivery_date, order_count, cart_count, plant_count, announced_count,
|
|
1147
|
-
printed_count, controlled_count, orders (jsonb array met order_uuid,
|
|
1148
|
-
order_number, pick_date, cart_count, plant_count, announced, printed,
|
|
1149
|
-
controlled).
|
|
1150
|
-
|
|
1151
|
-
Zelfde telbron als logistics_pick_agenda; alleen gegroepeerd op leverdatum in
|
|
1152
|
-
plaats van pickdag.
|
|
1153
|
-
|
|
1154
|
-
BOUW DIT
|
|
1155
|
-
- Haal de lever agenda op met:
|
|
1156
|
-
|
|
1157
|
-
const { data } = await supabase.rpc("logistics_delivery_agenda", {
|
|
1158
|
-
p_from: vanDatum, p_to: totDatum,
|
|
1159
|
-
});
|
|
1160
|
-
const dagen = Array.isArray(data) ? data : [];
|
|
1161
|
-
|
|
1162
|
-
- Toon cart_count en plant_count exact zoals teruggegeven; niets optellen of
|
|
1163
|
-
omrekenen.
|
|
1164
|
-
- Statusfilters (aangemeld / geprint / gecontroleerd) filteren regels; ze mogen
|
|
1165
|
-
het totaal nooit herberekenen.
|
|
1166
|
-
|
|
1167
|
-
NIET DOEN
|
|
1168
|
-
- Geen eigen query op orders, order_carts of de Floriday-cache voor aantallen.
|
|
1169
|
-
- Geen datums, project-refs of URL's hardcoden.
|
|
1170
|
-
|
|
1171
|
-
CONTROLELIJST
|
|
1172
|
-
[ ] Een order toont in de lever agenda hetzelfde aantal karren als in de pick agenda.
|
|
1350
|
+
body: `AANVULLING op prompt 1 t/m 13 (die blijven geldig).
|
|
1351
|
+
|
|
1352
|
+
WAAROM
|
|
1353
|
+
Pick agenda, Controle karren en Verkoop tellen al uit dezelfde karindex. De
|
|
1354
|
+
lever agenda telde nog zelf. Daardoor konden dezelfde orders op twee schermen
|
|
1355
|
+
een ander aantal karren tonen.
|
|
1356
|
+
|
|
1357
|
+
WAT DE ENGINE LEVERT
|
|
1358
|
+
public.logistics_delivery_agenda(p_from date, p_to date) — één rij per leverdag:
|
|
1359
|
+
delivery_date, order_count, cart_count, plant_count, announced_count,
|
|
1360
|
+
printed_count, controlled_count, orders (jsonb array met order_uuid,
|
|
1361
|
+
order_number, pick_date, cart_count, plant_count, announced, printed,
|
|
1362
|
+
controlled).
|
|
1363
|
+
|
|
1364
|
+
Zelfde telbron als logistics_pick_agenda; alleen gegroepeerd op leverdatum in
|
|
1365
|
+
plaats van pickdag.
|
|
1366
|
+
|
|
1367
|
+
BOUW DIT
|
|
1368
|
+
- Haal de lever agenda op met:
|
|
1369
|
+
|
|
1370
|
+
const { data } = await supabase.rpc("logistics_delivery_agenda", {
|
|
1371
|
+
p_from: vanDatum, p_to: totDatum,
|
|
1372
|
+
});
|
|
1373
|
+
const dagen = Array.isArray(data) ? data : [];
|
|
1374
|
+
|
|
1375
|
+
- Toon cart_count en plant_count exact zoals teruggegeven; niets optellen of
|
|
1376
|
+
omrekenen.
|
|
1377
|
+
- Statusfilters (aangemeld / geprint / gecontroleerd) filteren regels; ze mogen
|
|
1378
|
+
het totaal nooit herberekenen.
|
|
1379
|
+
|
|
1380
|
+
NIET DOEN
|
|
1381
|
+
- Geen eigen query op orders, order_carts of de Floriday-cache voor aantallen.
|
|
1382
|
+
- Geen datums, project-refs of URL's hardcoden.
|
|
1383
|
+
|
|
1384
|
+
CONTROLELIJST
|
|
1385
|
+
[ ] Een order toont in de lever agenda hetzelfde aantal karren als in de pick agenda.
|
|
1173
1386
|
[ ] Geen eigen kartelling meer in de leveringencode.`,
|
|
1174
1387
|
},
|
|
1388
|
+
{
|
|
1389
|
+
number: 15,
|
|
1390
|
+
title: "Scancontrole: pakbon scannen, goedkeuren en afleverbrief printen",
|
|
1391
|
+
date: "2026-09-03",
|
|
1392
|
+
summary: "Het controlescherm scant pakbonnen via de Engine-RPC's; de Engine bepaalt FO of niet-FO en zet de afleverbrief klaar op de gekozen printer.",
|
|
1393
|
+
body: `AANVULLING op prompt 1 t/m 14 (die blijven geldig).
|
|
1394
|
+
|
|
1395
|
+
WAT ER VERANDERT
|
|
1396
|
+
In de Logistiek Engine, stap 6 "Controle", kiest de gebruiker bij "Scancontrole"
|
|
1397
|
+
nu ook een scanner (control_scanner_id) en een printer (control_printer_id).
|
|
1398
|
+
Die keuze staat in de werkwijze in de database. Afhandeling kiest zelf geen
|
|
1399
|
+
scanner, printer, layout of documentsoort meer.
|
|
1400
|
+
|
|
1401
|
+
WAT DE ENGINE LEVERT (alles via supabase.rpc)
|
|
1402
|
+
- logistics_control_settings() -> { controlMode, scannerId, printerId }
|
|
1403
|
+
De ingestelde controlepost. Ontbreekt scannerId of printerId, toon dan een
|
|
1404
|
+
duidelijke melding en scan niet verder; niet zelf een apparaat kiezen.
|
|
1405
|
+
- logistics_control_scan_lookup(p_barcode text)
|
|
1406
|
+
Herkent aan de barcode/QR op de pakbon: order, kar ("Kar X van Y"), de
|
|
1407
|
+
belading van die kar, de klant, of het een Floriday-order is (isFloriday /
|
|
1408
|
+
salesOrderId) en of deze kar al eerder gescand is (scan, alreadyControlled).
|
|
1409
|
+
Onbekende barcode geeft ok:false met een leesbare tekst; toon die letterlijk.
|
|
1410
|
+
- logistics_control_scan_approve(p_barcode, p_scanner_id, p_printer_id,
|
|
1411
|
+
p_allow_reprint boolean default false)
|
|
1412
|
+
Keurt de gescande pakbon goed. Niet-Floriday: de eigen afleverbrief wordt
|
|
1413
|
+
direct als printjob klaargezet op de gekozen printer. Floriday: de definitieve
|
|
1414
|
+
belading gaat naar Floriday, de Engine haalt daarna de officiële Floriday-
|
|
1415
|
+
afleverbrief op en print die. Dubbel scannen geeft ok:false met errorCode
|
|
1416
|
+
"al_gecontroleerd"; alleen bij een bewuste keuze opnieuw printen mag je
|
|
1417
|
+
p_allow_reprint = true meesturen.
|
|
1418
|
+
- logistics_control_scan_overview(p_scanner_id uuid, p_date date)
|
|
1419
|
+
Alle scans van vandaag met hun status, voor de statuslijst in het scherm.
|
|
1420
|
+
- logistics_control_scan_retry(p_id uuid)
|
|
1421
|
+
Opnieuw proberen na een mislukte Floriday-afleverbrief.
|
|
1422
|
+
|
|
1423
|
+
STATUSSEN (letterlijk tonen, niet hertalen naar eigen statussen)
|
|
1424
|
+
gescand -> goedgekeurd -> afleverbrief_aangevraagd -> geprint, of mislukt.
|
|
1425
|
+
Zolang een Floriday-order op de afleverbrief wacht blijft de status
|
|
1426
|
+
afleverbrief_aangevraagd; hij mag dan NIET als afgerond gelden.
|
|
1427
|
+
|
|
1428
|
+
BOUW DIT
|
|
1429
|
+
- Een scanscherm bij de controlepost: invoerveld/scanner-invoer -> lookup tonen
|
|
1430
|
+
ter controle (order, kar, belading, FO of niet) -> knop "Goedkeuren" die
|
|
1431
|
+
approve aanroept. Meerdere pakbonnen achter elkaar scannen moet kunnen.
|
|
1432
|
+
- Een lijst met de scans van vandaag uit logistics_control_scan_overview, met
|
|
1433
|
+
status, foutmelding en bij "mislukt" een knop "Opnieuw proberen" (retry).
|
|
1434
|
+
- Blokkeer de goedkeurknop zolang een aanroep loopt, zodat dubbelklikken geen
|
|
1435
|
+
tweede afleverbrief oplevert. De database blokkeert dubbel scannen ook, maar
|
|
1436
|
+
de melding moet zichtbaar zijn.
|
|
1437
|
+
- Ververs op wijzigingen in logistics_control_scan.
|
|
1438
|
+
|
|
1439
|
+
NIET DOEN
|
|
1440
|
+
- Geen eigen afleverbrief maken voor een Floriday-order; die komt altijd uit
|
|
1441
|
+
Floriday via de Engine.
|
|
1442
|
+
- Geen eigen printjobs aanmaken, geen layout kiezen, geen printer raden.
|
|
1443
|
+
- Geen order of kar als afgerond markeren zolang de afleverbrief niet geprint is.
|
|
1444
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste apparaat-id's in code.
|
|
1445
|
+
|
|
1446
|
+
CONTROLELIJST
|
|
1447
|
+
[ ] Scannen van een pakbon toont order, kar, belading en of het een FO-order is.
|
|
1448
|
+
[ ] Goedkeuren van een niet-FO-kar levert direct een afleverbrief op de gekozen printer.
|
|
1449
|
+
[ ] Goedkeuren van een FO-kar levert de Floriday-afleverbrief op, niet de eigen.
|
|
1450
|
+
[ ] Tweede scan van dezelfde kar geeft een melding en maakt geen tweede brief.
|
|
1451
|
+
[ ] Een mislukte Floriday-afleverbrief is zichtbaar en opnieuw te proberen.`,
|
|
1452
|
+
},
|
|
1453
|
+
{
|
|
1454
|
+
number: 16,
|
|
1455
|
+
title: "Karnummer per order: cart_seq en cart_number tonen",
|
|
1456
|
+
date: "2026-09-03",
|
|
1457
|
+
summary: "Karnummers komen uit de Engine: toon cart_seq en cart_number, nooit cart_index, en reken zelf niets om.",
|
|
1458
|
+
body: `AANVULLING op de eerdere prompts (die blijven geldig).
|
|
1459
|
+
|
|
1460
|
+
WAT ER VERANDERT
|
|
1461
|
+
De Engine levert vanaf nu per kar een stabiel karnummer. Modules rekenen zelf
|
|
1462
|
+
NIETS meer om en hernummeren niet.
|
|
1463
|
+
|
|
1464
|
+
VELDEN (uit de Engine-RPC's)
|
|
1465
|
+
- cart_seq : stabiel, 1-gebaseerd volgnummer van de kar binnen zijn order.
|
|
1466
|
+
Identiek aan het nummer op de pakbon in de verkoopmodule. Verandert niet als
|
|
1467
|
+
karren op verschillende dagen gepickt of gecontroleerd worden, en niet als een
|
|
1468
|
+
deel van de karren al is afgehandeld.
|
|
1469
|
+
- cart_number : het definitieve karnummer-label (bijv. het toegewezen
|
|
1470
|
+
karnummer uit de karnummering). Toon dit als label.
|
|
1471
|
+
- cart_total : het aantal karren van die order ("Kar X van Y" = cart_seq van
|
|
1472
|
+
cart_total).
|
|
1473
|
+
- cart_index : INTERN. Technische index, niet gedefinieerd als 0- of
|
|
1474
|
+
1-gebaseerd. NOOIT tonen en nooit als basis voor eigen nummering gebruiken.
|
|
1475
|
+
|
|
1476
|
+
WAAR STAAN DE VELDEN
|
|
1477
|
+
control_get_todays_carts(), logistics_pick_agenda(p_from, p_to) (per order in
|
|
1478
|
+
cartList), logistics_cart_index(p_from, p_to), logistics_control_scan_lookup(
|
|
1479
|
+
p_barcode) (cartSeq / cartNumber / cartTotal) en
|
|
1480
|
+
logistics_control_scan_overview(p_scanner_id, p_date).
|
|
1481
|
+
|
|
1482
|
+
GEBRUIK IN DEZE MODULE
|
|
1483
|
+
Karrencontrole toont het karnummer uit control_get_todays_carts (cart_seq,
|
|
1484
|
+
cart_number, cart_total). De eerdere eigen hernummering vervalt.
|
|
1485
|
+
|
|
1486
|
+
NIET DOEN
|
|
1487
|
+
- Niet zelf nummeren, sorteren op index, of +1 optellen bij cart_index.
|
|
1488
|
+
- Geen aparte nummering per dag, per pickronde of per controlesessie.
|
|
1489
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
1490
|
+
|
|
1491
|
+
CONTROLELIJST
|
|
1492
|
+
[ ] Elk karnummer in het scherm komt uit cart_seq / cart_number.
|
|
1493
|
+
[ ] "Kar X van Y" gebruikt cart_seq en cart_total.
|
|
1494
|
+
[ ] Een order met 4 karren toont 1 t/m 4, ook als er al karren afgehandeld zijn.
|
|
1495
|
+
[ ] Het getoonde nummer is gelijk aan het nummer op de pakbon.
|
|
1496
|
+
[ ] cart_index komt nergens in de weergave voor.`,
|
|
1497
|
+
},
|
|
1498
|
+
{
|
|
1499
|
+
number: 17,
|
|
1500
|
+
title: "Controle karren alleen tonen bij picken per kar",
|
|
1501
|
+
date: "2026-09-04",
|
|
1502
|
+
summary: "De submodule Controle karren staat alleen in de balk als de actieve werkwijze picken per kar gebruikt.",
|
|
1503
|
+
body: `AANVULLING op de eerdere prompts (die blijven geldig).
|
|
1504
|
+
|
|
1505
|
+
WAT ER VERANDERT
|
|
1506
|
+
Karrencontrole hoort alleen bij de pickmethode "Picken per kar". Bij elke andere
|
|
1507
|
+
pickmethode (per order, kleinste telt, per orderbuffer) bestaat er geen
|
|
1508
|
+
karcontrolestap en mag de submodule "Controle karren" niet in de balk staan.
|
|
1509
|
+
|
|
1510
|
+
BRON — DE ENGINE BESLIST
|
|
1511
|
+
Nieuwe RPC:
|
|
1512
|
+
|
|
1513
|
+
select public.logistics_pick_mode();
|
|
1514
|
+
|
|
1515
|
+
Geeft terug:
|
|
1516
|
+
- pickMode : 'order' | 'cart' | 'smallest' | 'buffer' | null
|
|
1517
|
+
- showCartControl : true alleen bij pickMode = 'cart'
|
|
1518
|
+
|
|
1519
|
+
GEBRUIK IN DEZE MODULE
|
|
1520
|
+
- Roep de RPC aan bij het opbouwen van de navigatie.
|
|
1521
|
+
- showCartControl = true -> menu-item "Controle karren" tonen.
|
|
1522
|
+
- showCartControl = false -> menu-item weglaten en de route afschermen
|
|
1523
|
+
(direct benaderen leidt terug naar het overzicht).
|
|
1524
|
+
- Is de RPC nog niet geladen of geeft hij een fout, toon het item dan NIET
|
|
1525
|
+
(fail closed) en geen eigen aanname over de pickmethode.
|
|
1526
|
+
- Ververs bij het wisselen van werkwijze, zodat de balk direct meeloopt.
|
|
1527
|
+
|
|
1528
|
+
NIET DOEN
|
|
1529
|
+
- Niet zelf de rule-config uitlezen of de pickmethode afleiden uit karren die
|
|
1530
|
+
je toevallig ziet.
|
|
1531
|
+
- Geen eigen instelling of schakelaar voor het tonen van Controle karren.
|
|
1532
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
1533
|
+
|
|
1534
|
+
CONTROLELIJST
|
|
1535
|
+
[ ] Bij "Picken per kar" staat Controle karren in de balk en werkt hij.
|
|
1536
|
+
[ ] Bij elke andere pickmethode staat Controle karren niet in de balk.
|
|
1537
|
+
[ ] De route is ook rechtstreeks niet bereikbaar als hij verborgen is.
|
|
1538
|
+
[ ] Zonder antwoord van de RPC blijft het item verborgen.`,
|
|
1539
|
+
},
|
|
1540
|
+
{
|
|
1541
|
+
number: 18,
|
|
1542
|
+
title: "Een bufferorder is één order in Afhandeling",
|
|
1543
|
+
date: "2026-09-05",
|
|
1544
|
+
summary: "Pick agenda, Lever agenda en Karrencontrole tonen orders uit één orderbuffer als één order met één karrenindeling.",
|
|
1545
|
+
body: `AANVULLING op de eerdere prompts (die blijven geldig).
|
|
1546
|
+
|
|
1547
|
+
WAT ER VERANDERT
|
|
1548
|
+
Orders die samen in één orderbuffer zitten, zijn logistiek één order. De Engine
|
|
1549
|
+
levert ze als één eenheid aan onder het leidende ordernummer (unit_ref).
|
|
1550
|
+
|
|
1551
|
+
BRON
|
|
1552
|
+
- logistics_pick_agenda(p_from, p_to) -> orders[]: orderRef is de eenheid, met
|
|
1553
|
+
isBuffer en bufferOrders[] erbij; carts/cartList/cartTotal gelden voor de hele
|
|
1554
|
+
eenheid.
|
|
1555
|
+
- logistics_delivery_agenda(p_from, p_to) -> orders[]: order_number is de
|
|
1556
|
+
eenheid, met is_buffer en buffer_orders[].
|
|
1557
|
+
- control_get_todays_carts(): order_number is de eenheid, cart_seq/cart_total
|
|
1558
|
+
lopen door over alle karren van die eenheid.
|
|
1559
|
+
- logistics_cart_units(p_from, p_to) is de onderliggende karindex per eenheid.
|
|
1560
|
+
|
|
1561
|
+
GEBRUIK IN DEZE MODULE
|
|
1562
|
+
- Tel en toon per eenheid, nooit per los bufferlid.
|
|
1563
|
+
- Toon bij isBuffer de losse ordernummers als toelichting, niet als eigen regel.
|
|
1564
|
+
- Karrencontrole vinkt af per kar van de eenheid; een kar komt maar één keer voor.
|
|
1565
|
+
|
|
1566
|
+
NIET DOEN
|
|
1567
|
+
- Geen eigen query op order_carts of orders om karren te tellen.
|
|
1568
|
+
- Niet hernummeren per los ordernummer.
|
|
1569
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
1570
|
+
|
|
1571
|
+
CONTROLELIJST
|
|
1572
|
+
[ ] Een buffer met twee orders telt als één order op de pick agenda.
|
|
1573
|
+
[ ] Dezelfde eenheid en hetzelfde karrenaantal staan op de lever agenda.
|
|
1574
|
+
[ ] Karrencontrole toont elke kar precies één keer, onder de eenheid.`,
|
|
1575
|
+
},
|
|
1175
1576
|
],
|
|
1176
1577
|
},
|
|
1177
1578
|
pickschermen: {
|
|
@@ -1184,12 +1585,12 @@ CONTROLELIJST
|
|
|
1184
1585
|
date: "2026-07-24",
|
|
1185
1586
|
summary: "Pick-taken tonen en terugmelden.",
|
|
1186
1587
|
withSharedContract: true,
|
|
1187
|
-
body: `Haal weg: eigen pickvolgorde en eigen bepaling van de starttijd.
|
|
1188
|
-
|
|
1189
|
-
Bouw:
|
|
1190
|
-
- pick.execute taken tonen, gesorteerd op planned_start.
|
|
1191
|
-
- Payload: pickMode, pickStartMode, pickMinutes, staff, reserveMinutes, scanner, loadCarriers.
|
|
1192
|
-
- Voortgang terugmelden via RPC: logistics_claim_task bij starten, logistics_complete_task bij afronden.
|
|
1588
|
+
body: `Haal weg: eigen pickvolgorde en eigen bepaling van de starttijd.
|
|
1589
|
+
|
|
1590
|
+
Bouw:
|
|
1591
|
+
- pick.execute taken tonen, gesorteerd op planned_start.
|
|
1592
|
+
- Payload: pickMode, pickStartMode, pickMinutes, staff, reserveMinutes, scanner, loadCarriers.
|
|
1593
|
+
- Voortgang terugmelden via RPC: logistics_claim_task bij starten, logistics_complete_task bij afronden.
|
|
1193
1594
|
- Te-laat-dreigende belading markeren op basis van planned_end; niet zelf herrekenen.`,
|
|
1194
1595
|
},
|
|
1195
1596
|
{
|
|
@@ -1197,26 +1598,26 @@ Bouw:
|
|
|
1197
1598
|
title: "Documenten per pickstation vanuit de Engine",
|
|
1198
1599
|
date: "2026-08-03",
|
|
1199
1600
|
summary: "Documenttaken tonen op het juiste pickstation, inclusief goedkeuring.",
|
|
1200
|
-
body: `Deze prompt vervangt niets uit prompt 1; hij komt er bovenop.
|
|
1201
|
-
|
|
1202
|
-
Haal weg: eigen logica over welk document op welk pickstation verschijnt en
|
|
1203
|
-
wanneer. De Logistics Engine bepaalt dit volledig.
|
|
1204
|
-
|
|
1205
|
-
Verwerk deze taaktypes uit logistics_tasks:
|
|
1206
|
-
- print.packing_slip, print.sticker, print.shipping_note, print.production_note
|
|
1207
|
-
|
|
1208
|
-
Payload per taak:
|
|
1209
|
-
- release wanneer het document vrijkomt
|
|
1210
|
-
- pickStationId public.pick_stations.id waar het document heen moet
|
|
1211
|
-
- pickStationTypeId public.pick_station_types.id dat het document mag ontvangen
|
|
1212
|
-
- requiresApproval true = eerst handmatige goedkeuring op het pickstation
|
|
1213
|
-
|
|
1214
|
-
Regels:
|
|
1215
|
-
- Toon een document pas vanaf planned_start van de taak.
|
|
1216
|
-
- Filter de wachtrij van een pickstation op pickStationId; is die leeg, gebruik
|
|
1217
|
-
dan pickStationTypeId. Toon nooit documenten van een ander station.
|
|
1218
|
-
- requiresApproval = true: toon een goedkeurknop; pas na goedkeuren printen en
|
|
1219
|
-
daarna logistics_complete_task aanroepen (bij weigeren logistics_fail_task).
|
|
1601
|
+
body: `Deze prompt vervangt niets uit prompt 1; hij komt er bovenop.
|
|
1602
|
+
|
|
1603
|
+
Haal weg: eigen logica over welk document op welk pickstation verschijnt en
|
|
1604
|
+
wanneer. De Logistics Engine bepaalt dit volledig.
|
|
1605
|
+
|
|
1606
|
+
Verwerk deze taaktypes uit logistics_tasks:
|
|
1607
|
+
- print.packing_slip, print.sticker, print.shipping_note, print.production_note
|
|
1608
|
+
|
|
1609
|
+
Payload per taak:
|
|
1610
|
+
- release wanneer het document vrijkomt
|
|
1611
|
+
- pickStationId public.pick_stations.id waar het document heen moet
|
|
1612
|
+
- pickStationTypeId public.pick_station_types.id dat het document mag ontvangen
|
|
1613
|
+
- requiresApproval true = eerst handmatige goedkeuring op het pickstation
|
|
1614
|
+
|
|
1615
|
+
Regels:
|
|
1616
|
+
- Toon een document pas vanaf planned_start van de taak.
|
|
1617
|
+
- Filter de wachtrij van een pickstation op pickStationId; is die leeg, gebruik
|
|
1618
|
+
dan pickStationTypeId. Toon nooit documenten van een ander station.
|
|
1619
|
+
- requiresApproval = true: toon een goedkeurknop; pas na goedkeuren printen en
|
|
1620
|
+
daarna logistics_complete_task aanroepen (bij weigeren logistics_fail_task).
|
|
1220
1621
|
- Bepaal nooit zelf een vrijgavemoment en print nooit vooruit.`,
|
|
1221
1622
|
},
|
|
1222
1623
|
{
|
|
@@ -1224,32 +1625,32 @@ Regels:
|
|
|
1224
1625
|
title: "Documenten ophalen via de Floriday-gateway",
|
|
1225
1626
|
date: "2026-08-04",
|
|
1226
1627
|
summary: "Geen eigen Floriday-token of florydayFetch meer; gebundeld printen per kar.",
|
|
1227
|
-
body: `Deze prompt vervangt niets uit prompt 1 en 2; hij komt er bovenop.
|
|
1228
|
-
|
|
1229
|
-
Haal weg: eigen Floriday-tokenlogica, eigen florydayFetch, eigen keuze van
|
|
1230
|
-
staging/live en eigen HTTP-aanroepen naar de Floriday-gateway.
|
|
1231
|
-
|
|
1232
|
-
Alle modules draaien in dezelfde shell op dezelfde database. Importeer de
|
|
1233
|
-
gateway daarom rechtstreeks en geef de service-role supabase-client van de
|
|
1234
|
-
shell mee:
|
|
1235
|
-
|
|
1236
|
-
import {
|
|
1237
|
-
runActiveEnvironment,
|
|
1238
|
-
runPdf,
|
|
1239
|
-
runPdfBulkMerged,
|
|
1240
|
-
} from "@flowselections/floriday-authenticatie-module/gateway";
|
|
1241
|
-
|
|
1242
|
-
Regels:
|
|
1243
|
-
- De omgeving komt altijd uit runActiveEnvironment(supabase). Nooit zelf kiezen.
|
|
1244
|
-
- Eén document (print.packing_slip, print.sticker, print.shipping_note,
|
|
1245
|
-
print.production_note): runPdf.
|
|
1246
|
-
- Trigger "kar afgemeld" of "kar-scan": bundel alle regels van die kar en roep
|
|
1247
|
-
runPdfBulkMerged aan, zodat het pickstation één printjob krijgt in plaats van
|
|
1248
|
-
losse documenten.
|
|
1249
|
-
- Toon bovenin het scherm welke koppeling actief is (label, GLN, staging/live).
|
|
1250
|
-
- Print nooit twee keer hetzelfde: controleer public.logistics_document_prints
|
|
1251
|
-
op (order_ref, document_type, trigger) voordat je print.
|
|
1252
|
-
- Trigger en pickstation blijven van de Logistics Engine; de gateway levert
|
|
1628
|
+
body: `Deze prompt vervangt niets uit prompt 1 en 2; hij komt er bovenop.
|
|
1629
|
+
|
|
1630
|
+
Haal weg: eigen Floriday-tokenlogica, eigen florydayFetch, eigen keuze van
|
|
1631
|
+
staging/live en eigen HTTP-aanroepen naar de Floriday-gateway.
|
|
1632
|
+
|
|
1633
|
+
Alle modules draaien in dezelfde shell op dezelfde database. Importeer de
|
|
1634
|
+
gateway daarom rechtstreeks en geef de service-role supabase-client van de
|
|
1635
|
+
shell mee:
|
|
1636
|
+
|
|
1637
|
+
import {
|
|
1638
|
+
runActiveEnvironment,
|
|
1639
|
+
runPdf,
|
|
1640
|
+
runPdfBulkMerged,
|
|
1641
|
+
} from "@flowselections/floriday-authenticatie-module/gateway";
|
|
1642
|
+
|
|
1643
|
+
Regels:
|
|
1644
|
+
- De omgeving komt altijd uit runActiveEnvironment(supabase). Nooit zelf kiezen.
|
|
1645
|
+
- Eén document (print.packing_slip, print.sticker, print.shipping_note,
|
|
1646
|
+
print.production_note): runPdf.
|
|
1647
|
+
- Trigger "kar afgemeld" of "kar-scan": bundel alle regels van die kar en roep
|
|
1648
|
+
runPdfBulkMerged aan, zodat het pickstation één printjob krijgt in plaats van
|
|
1649
|
+
losse documenten.
|
|
1650
|
+
- Toon bovenin het scherm welke koppeling actief is (label, GLN, staging/live).
|
|
1651
|
+
- Print nooit twee keer hetzelfde: controleer public.logistics_document_prints
|
|
1652
|
+
op (order_ref, document_type, trigger) voordat je print.
|
|
1653
|
+
- Trigger en pickstation blijven van de Logistics Engine; de gateway levert
|
|
1253
1654
|
alleen het PDF-bestand.`,
|
|
1254
1655
|
},
|
|
1255
1656
|
{
|
|
@@ -1257,29 +1658,29 @@ Regels:
|
|
|
1257
1658
|
title: "Strikte documentroutering per pickstation",
|
|
1258
1659
|
date: "2026-08-04",
|
|
1259
1660
|
summary: "Een pickstation toont uitsluitend de documentsoorten die eraan gekoppeld zijn.",
|
|
1260
|
-
body: `Deze prompt vervangt niets uit prompt 1 t/m 3; hij komt er bovenop.
|
|
1261
|
-
|
|
1262
|
-
Probleem: op "Pickstation Orders" verschenen naast pakbonnen ook veilingbrieven
|
|
1263
|
-
en transportbrieven. Dat mag nooit.
|
|
1264
|
-
|
|
1265
|
-
Haal weg: elke query die de wachtrij alleen op station_id filtert, en elke
|
|
1266
|
-
fallback die "overige documenten" toch ergens toont.
|
|
1267
|
-
|
|
1268
|
-
Regels:
|
|
1269
|
-
- Filter de wachtrij ALTIJD op screen_id van het geopende scherm, niet op
|
|
1270
|
-
station_id. Elk scherm heeft via public.pick_screen_document_types precies de
|
|
1271
|
-
documenttypes die het mag tonen.
|
|
1272
|
-
- Toon nooit een document waarvan het document_type_id niet aan dat scherm is
|
|
1273
|
-
gekoppeld. Geen "rest"-categorie, geen samengevoegde stationweergave.
|
|
1274
|
-
- De koppeling documentsoort -> pickstation komt uit de Logistiek Engine
|
|
1275
|
-
(Rule Engine, stap "Pickstations"). In de database is dat opvraagbaar met
|
|
1276
|
-
select public.logistics_document_station('pakbon').
|
|
1277
|
-
- De printwachtrij public.pick_queue heeft een trigger die station_id en
|
|
1278
|
-
screen_id herschrijft volgens die instelling. Schrijf zelf nooit een
|
|
1279
|
-
station_id dat daarvan afwijkt; dat wordt overschreven of geweigerd.
|
|
1280
|
-
- Taken uit logistics_tasks dragen payload.documentType en payload.pickStationId.
|
|
1281
|
-
Gebruik die twee samen; nooit alleen het taaktype.
|
|
1282
|
-
- Standaardweergave is "documenten van vandaag". Oudere, niet-geprinte regels
|
|
1661
|
+
body: `Deze prompt vervangt niets uit prompt 1 t/m 3; hij komt er bovenop.
|
|
1662
|
+
|
|
1663
|
+
Probleem: op "Pickstation Orders" verschenen naast pakbonnen ook veilingbrieven
|
|
1664
|
+
en transportbrieven. Dat mag nooit.
|
|
1665
|
+
|
|
1666
|
+
Haal weg: elke query die de wachtrij alleen op station_id filtert, en elke
|
|
1667
|
+
fallback die "overige documenten" toch ergens toont.
|
|
1668
|
+
|
|
1669
|
+
Regels:
|
|
1670
|
+
- Filter de wachtrij ALTIJD op screen_id van het geopende scherm, niet op
|
|
1671
|
+
station_id. Elk scherm heeft via public.pick_screen_document_types precies de
|
|
1672
|
+
documenttypes die het mag tonen.
|
|
1673
|
+
- Toon nooit een document waarvan het document_type_id niet aan dat scherm is
|
|
1674
|
+
gekoppeld. Geen "rest"-categorie, geen samengevoegde stationweergave.
|
|
1675
|
+
- De koppeling documentsoort -> pickstation komt uit de Logistiek Engine
|
|
1676
|
+
(Rule Engine, stap "Pickstations"). In de database is dat opvraagbaar met
|
|
1677
|
+
select public.logistics_document_station('pakbon').
|
|
1678
|
+
- De printwachtrij public.pick_queue heeft een trigger die station_id en
|
|
1679
|
+
screen_id herschrijft volgens die instelling. Schrijf zelf nooit een
|
|
1680
|
+
station_id dat daarvan afwijkt; dat wordt overschreven of geweigerd.
|
|
1681
|
+
- Taken uit logistics_tasks dragen payload.documentType en payload.pickStationId.
|
|
1682
|
+
Gebruik die twee samen; nooit alleen het taaktype.
|
|
1683
|
+
- Standaardweergave is "documenten van vandaag". Oudere, niet-geprinte regels
|
|
1283
1684
|
horen in een apart tabblad, niet in de dagwachtrij.`,
|
|
1284
1685
|
},
|
|
1285
1686
|
{
|
|
@@ -1287,41 +1688,41 @@ Regels:
|
|
|
1287
1688
|
title: "Documenten altijd renderen met de layout uit de Layout maker",
|
|
1288
1689
|
date: "2026-08-04",
|
|
1289
1690
|
summary: "Geen eigen pakbon-opmaak meer; de layout komt uit public.document_layouts.",
|
|
1290
|
-
body: `Deze prompt vervangt niets uit prompt 1 t/m 4; hij komt er bovenop.
|
|
1291
|
-
|
|
1292
|
-
Probleem: het pickstation print een eigen, hardgecodeerde pakbon. De pakbon die
|
|
1293
|
-
in de module "Layout maker (pakbonnen, verzendbrieven, extra)" is ontworpen
|
|
1294
|
-
wordt genegeerd.
|
|
1295
|
-
|
|
1296
|
-
Haal weg: elke eigen HTML/PDF-opmaak van pakbonnen, verzendbrieven, stickers,
|
|
1297
|
-
productiebonnen en controlelijsten. Ook alle vaste kolommen, logo's, marges en
|
|
1298
|
-
papierformaten die in de pickstation-code staan.
|
|
1299
|
-
|
|
1300
|
-
Regels:
|
|
1301
|
-
- De opmaak komt ALTIJD uit public.document_layouts (+ document_layout_elements,
|
|
1302
|
-
document_layout_variables, document_layout_versions, layout_logos). Nooit een
|
|
1303
|
-
eigen sjabloon, ook niet als fallback.
|
|
1304
|
-
- Welke layout bij een documentsoort hoort, bepaal je niet zelf. Gebruik:
|
|
1305
|
-
select public.logistics_document_layout('pakbon');
|
|
1306
|
-
Dat geeft { layoutId, layoutName, layoutVersion, layoutDocumentType } van de
|
|
1307
|
-
actieve layout (voorkeur: is_standaard).
|
|
1308
|
-
- Elke regel in public.pick_queue draagt deze gegevens al mee in payload:
|
|
1309
|
-
documentType, layoutId, layoutName, layoutVersion. Gebruik payload.layoutId
|
|
1310
|
-
als die er staat; val alleen terug op de functie hierboven als hij ontbreekt.
|
|
1311
|
-
- Render met de renderer van de Layout maker, niet met eigen code. Papierformaat,
|
|
1312
|
-
oriëntatie en marges komen uit de layoutrij (papierformaat, breedte_mm,
|
|
1313
|
-
hoogte_mm, marge_*, orientatie, page_settings).
|
|
1314
|
-
- Ontbreekt er een actieve layout voor een documentsoort? Print dan niet, maar
|
|
1315
|
-
toon "Geen layout ingesteld voor <documentsoort>" met een verwijzing naar de
|
|
1316
|
-
Layout maker. Nooit stilzwijgend een eigen pakbon printen.
|
|
1317
|
-
- Floriday-documenten (prompt 3) blijven via de gateway lopen; alles wat we zelf
|
|
1318
|
-
opmaken loopt via de Layout maker.
|
|
1319
|
-
- Log bij het afronden van de taak welke layoutId en layoutVersion zijn gebruikt
|
|
1320
|
-
in het result van logistics_complete_task.
|
|
1321
|
-
|
|
1322
|
-
CONTROLELIJST
|
|
1323
|
-
[ ] Geen enkel eigen documentsjabloon meer in de code.
|
|
1324
|
-
[ ] Pakbon in het pickstation is visueel identiek aan de preview in de Layout maker.
|
|
1691
|
+
body: `Deze prompt vervangt niets uit prompt 1 t/m 4; hij komt er bovenop.
|
|
1692
|
+
|
|
1693
|
+
Probleem: het pickstation print een eigen, hardgecodeerde pakbon. De pakbon die
|
|
1694
|
+
in de module "Layout maker (pakbonnen, verzendbrieven, extra)" is ontworpen
|
|
1695
|
+
wordt genegeerd.
|
|
1696
|
+
|
|
1697
|
+
Haal weg: elke eigen HTML/PDF-opmaak van pakbonnen, verzendbrieven, stickers,
|
|
1698
|
+
productiebonnen en controlelijsten. Ook alle vaste kolommen, logo's, marges en
|
|
1699
|
+
papierformaten die in de pickstation-code staan.
|
|
1700
|
+
|
|
1701
|
+
Regels:
|
|
1702
|
+
- De opmaak komt ALTIJD uit public.document_layouts (+ document_layout_elements,
|
|
1703
|
+
document_layout_variables, document_layout_versions, layout_logos). Nooit een
|
|
1704
|
+
eigen sjabloon, ook niet als fallback.
|
|
1705
|
+
- Welke layout bij een documentsoort hoort, bepaal je niet zelf. Gebruik:
|
|
1706
|
+
select public.logistics_document_layout('pakbon');
|
|
1707
|
+
Dat geeft { layoutId, layoutName, layoutVersion, layoutDocumentType } van de
|
|
1708
|
+
actieve layout (voorkeur: is_standaard).
|
|
1709
|
+
- Elke regel in public.pick_queue draagt deze gegevens al mee in payload:
|
|
1710
|
+
documentType, layoutId, layoutName, layoutVersion. Gebruik payload.layoutId
|
|
1711
|
+
als die er staat; val alleen terug op de functie hierboven als hij ontbreekt.
|
|
1712
|
+
- Render met de renderer van de Layout maker, niet met eigen code. Papierformaat,
|
|
1713
|
+
oriëntatie en marges komen uit de layoutrij (papierformaat, breedte_mm,
|
|
1714
|
+
hoogte_mm, marge_*, orientatie, page_settings).
|
|
1715
|
+
- Ontbreekt er een actieve layout voor een documentsoort? Print dan niet, maar
|
|
1716
|
+
toon "Geen layout ingesteld voor <documentsoort>" met een verwijzing naar de
|
|
1717
|
+
Layout maker. Nooit stilzwijgend een eigen pakbon printen.
|
|
1718
|
+
- Floriday-documenten (prompt 3) blijven via de gateway lopen; alles wat we zelf
|
|
1719
|
+
opmaken loopt via de Layout maker.
|
|
1720
|
+
- Log bij het afronden van de taak welke layoutId en layoutVersion zijn gebruikt
|
|
1721
|
+
in het result van logistics_complete_task.
|
|
1722
|
+
|
|
1723
|
+
CONTROLELIJST
|
|
1724
|
+
[ ] Geen enkel eigen documentsjabloon meer in de code.
|
|
1725
|
+
[ ] Pakbon in het pickstation is visueel identiek aan de preview in de Layout maker.
|
|
1325
1726
|
[ ] Ontbrekende layout geeft een duidelijke melding in plaats van een print.`,
|
|
1326
1727
|
},
|
|
1327
1728
|
{
|
|
@@ -1329,50 +1730,50 @@ CONTROLELIJST
|
|
|
1329
1730
|
title: "Sectie-layouts uit de Layout maker correct printen",
|
|
1330
1731
|
date: "2026-08-04",
|
|
1331
1732
|
summary: "Een geldige pakbon in document_layouts.config mag nooit als ontbrekende layout worden afgewezen.",
|
|
1332
|
-
body: `Deze prompt vervangt niets uit prompt 1 t/m 5; hij komt er bovenop.
|
|
1333
|
-
|
|
1334
|
-
Probleem: de gekoppelde layout "packbon hoofd" is een geldige sectie-layout.
|
|
1335
|
-
De opbouw staat in public.document_layouts.config.pakbon.secties en niet in
|
|
1336
|
-
public.document_layout_elements. Het pickstation ondersteunt nu alleen
|
|
1337
|
-
canvas-elementen en toont daardoor ten onrechte "Geen layout ingesteld".
|
|
1338
|
-
|
|
1339
|
-
Haal weg:
|
|
1340
|
-
- elke controle die een layout als ontbrekend beschouwt wanneer
|
|
1341
|
-
document_layout_elements leeg is;
|
|
1342
|
-
- elke renderer die uitsluitend document_layout_elements ondersteunt;
|
|
1343
|
-
- de algemene MissingLayoutError voor een wel bestaande, actieve layoutrij.
|
|
1344
|
-
|
|
1345
|
-
Regels:
|
|
1346
|
-
- Een layout ontbreekt uitsluitend als public.document_layouts geen actieve rij
|
|
1347
|
-
voor het door de Engine aangeleverde layoutId bevat. Nul canvas-elementen is
|
|
1348
|
-
geen ontbrekende layout.
|
|
1349
|
-
- Lees eerst payload.layoutId (of payload.layout_id) uit public.pick_queue.
|
|
1350
|
-
De huidige pakbonnen verwijzen daarmee naar de gekoppelde layoutrij.
|
|
1351
|
-
- Kies daarna de renderer op basis van de opgeslagen layoutvorm:
|
|
1352
|
-
1. config.pakbon.secties is een array: gebruik dezelfde sectie-/pakbonrenderer
|
|
1353
|
-
en dezelfde datamapping als de preview van de Layout maker;
|
|
1354
|
-
2. document_layout_elements bevat rijen: gebruik de canvasrenderer;
|
|
1355
|
-
3. geen van beide bevat inhoud: meld "Layout heeft nog geen inhoud", niet
|
|
1356
|
-
"Geen layout ingesteld".
|
|
1357
|
-
- Importeer de renderer en bijbehorende types bij voorkeur rechtstreeks uit de
|
|
1358
|
-
Layout maker-module. Kopieer geen pakbonsjabloon naar deze module. Als de
|
|
1359
|
-
Layout maker de renderer nog niet exporteert, voeg daar named exports toe voor
|
|
1360
|
-
de sectierenderer en de order-naar-pakbon-datamapping en gebruik die hier.
|
|
1361
|
-
- Respecteer config.pakbon.secties volledig: volgorde, zichtbaar, condities,
|
|
1362
|
-
opties, karren, lagen, producten, totalen en logo. Respecteer daarnaast
|
|
1363
|
-
papierformaat, oriëntatie, marges en page_settings van document_layouts.
|
|
1364
|
-
- Vul vóór renderen de volledige ordercontext voor payload.orderId of
|
|
1365
|
-
order_number: order, klant, afleveradres, orderregels, karren, lagen,
|
|
1366
|
-
producten en fusten. De wachtrijregel alleen bevat hiervoor onvoldoende data.
|
|
1367
|
-
- Markeer de wachtrijregel pas als geprint nadat renderen is gelukt en de
|
|
1368
|
-
printdialoog is geopend. Laat de regel bij een renderfout in de wachtrij staan.
|
|
1369
|
-
|
|
1370
|
-
CONTROLELIJST
|
|
1371
|
-
[ ] "packbon hoofd" opent vanuit Pickstation Orders zonder MissingLayoutError.
|
|
1372
|
-
[ ] De afdruk is visueel gelijk aan de preview in de Layout maker.
|
|
1373
|
-
[ ] Karren, lagen en producten van de gekozen order staan op de pakbon.
|
|
1374
|
-
[ ] Een lege layout geeft "Layout heeft nog geen inhoud".
|
|
1375
|
-
[ ] Een werkelijk ontbrekende/inactieve layoutrij geeft pas "Geen layout ingesteld".
|
|
1733
|
+
body: `Deze prompt vervangt niets uit prompt 1 t/m 5; hij komt er bovenop.
|
|
1734
|
+
|
|
1735
|
+
Probleem: de gekoppelde layout "packbon hoofd" is een geldige sectie-layout.
|
|
1736
|
+
De opbouw staat in public.document_layouts.config.pakbon.secties en niet in
|
|
1737
|
+
public.document_layout_elements. Het pickstation ondersteunt nu alleen
|
|
1738
|
+
canvas-elementen en toont daardoor ten onrechte "Geen layout ingesteld".
|
|
1739
|
+
|
|
1740
|
+
Haal weg:
|
|
1741
|
+
- elke controle die een layout als ontbrekend beschouwt wanneer
|
|
1742
|
+
document_layout_elements leeg is;
|
|
1743
|
+
- elke renderer die uitsluitend document_layout_elements ondersteunt;
|
|
1744
|
+
- de algemene MissingLayoutError voor een wel bestaande, actieve layoutrij.
|
|
1745
|
+
|
|
1746
|
+
Regels:
|
|
1747
|
+
- Een layout ontbreekt uitsluitend als public.document_layouts geen actieve rij
|
|
1748
|
+
voor het door de Engine aangeleverde layoutId bevat. Nul canvas-elementen is
|
|
1749
|
+
geen ontbrekende layout.
|
|
1750
|
+
- Lees eerst payload.layoutId (of payload.layout_id) uit public.pick_queue.
|
|
1751
|
+
De huidige pakbonnen verwijzen daarmee naar de gekoppelde layoutrij.
|
|
1752
|
+
- Kies daarna de renderer op basis van de opgeslagen layoutvorm:
|
|
1753
|
+
1. config.pakbon.secties is een array: gebruik dezelfde sectie-/pakbonrenderer
|
|
1754
|
+
en dezelfde datamapping als de preview van de Layout maker;
|
|
1755
|
+
2. document_layout_elements bevat rijen: gebruik de canvasrenderer;
|
|
1756
|
+
3. geen van beide bevat inhoud: meld "Layout heeft nog geen inhoud", niet
|
|
1757
|
+
"Geen layout ingesteld".
|
|
1758
|
+
- Importeer de renderer en bijbehorende types bij voorkeur rechtstreeks uit de
|
|
1759
|
+
Layout maker-module. Kopieer geen pakbonsjabloon naar deze module. Als de
|
|
1760
|
+
Layout maker de renderer nog niet exporteert, voeg daar named exports toe voor
|
|
1761
|
+
de sectierenderer en de order-naar-pakbon-datamapping en gebruik die hier.
|
|
1762
|
+
- Respecteer config.pakbon.secties volledig: volgorde, zichtbaar, condities,
|
|
1763
|
+
opties, karren, lagen, producten, totalen en logo. Respecteer daarnaast
|
|
1764
|
+
papierformaat, oriëntatie, marges en page_settings van document_layouts.
|
|
1765
|
+
- Vul vóór renderen de volledige ordercontext voor payload.orderId of
|
|
1766
|
+
order_number: order, klant, afleveradres, orderregels, karren, lagen,
|
|
1767
|
+
producten en fusten. De wachtrijregel alleen bevat hiervoor onvoldoende data.
|
|
1768
|
+
- Markeer de wachtrijregel pas als geprint nadat renderen is gelukt en de
|
|
1769
|
+
printdialoog is geopend. Laat de regel bij een renderfout in de wachtrij staan.
|
|
1770
|
+
|
|
1771
|
+
CONTROLELIJST
|
|
1772
|
+
[ ] "packbon hoofd" opent vanuit Pickstation Orders zonder MissingLayoutError.
|
|
1773
|
+
[ ] De afdruk is visueel gelijk aan de preview in de Layout maker.
|
|
1774
|
+
[ ] Karren, lagen en producten van de gekozen order staan op de pakbon.
|
|
1775
|
+
[ ] Een lege layout geeft "Layout heeft nog geen inhoud".
|
|
1776
|
+
[ ] Een werkelijk ontbrekende/inactieve layoutrij geeft pas "Geen layout ingesteld".
|
|
1376
1777
|
[ ] De wachtrij wordt alleen afgerond na een geslaagde render/printactie.`,
|
|
1377
1778
|
},
|
|
1378
1779
|
{
|
|
@@ -1380,37 +1781,37 @@ CONTROLELIJST
|
|
|
1380
1781
|
title: "Altijd de actuele layout, behalve bij kant-en-klare PDF's",
|
|
1381
1782
|
date: "2026-08-14",
|
|
1382
1783
|
summary: "Layout wint boven meegestuurde HTML; klantstickers en Floriday-documenten gaan als bestaande PDF ongewijzigd naar de printer.",
|
|
1383
|
-
body: `Deze prompt vervangt niets uit prompt 1 t/m 6; hij komt er bovenop.
|
|
1384
|
-
|
|
1385
|
-
Uitgangspunt: wat er geprint wordt is ALTIJD de actuele layout uit de Layout
|
|
1386
|
-
maker, gevuld met de echte gegevens van de order en de klant. Enige uitzondering:
|
|
1387
|
-
documenten die al als kant-en-klare PDF bestaan (klantstickers en
|
|
1388
|
-
Floriday-documenten). Die worden ongewijzigd doorgestuurd.
|
|
1389
|
-
|
|
1390
|
-
Volgorde van beslissen bij een printopdracht in public.print_jobs:
|
|
1391
|
-
1. Is er een kant-en-klare PDF meegegeven (pdf-veld op de opdracht / bron uit
|
|
1392
|
-
floriday_customer_sticker_pdfs_cache): die PDF ongewijzigd naar de printer.
|
|
1393
|
-
Niet opnieuw opmaken, niet renderen.
|
|
1394
|
-
2. Is print_jobs.layout_id gevuld: die layout wint. Negeer een eventueel
|
|
1395
|
-
meegestuurde render_html en render vers uit public.document_layouts.
|
|
1396
|
-
3. Pas als beide leeg zijn: meegestuurde render_html, en anders de actieve
|
|
1397
|
-
layout bij het documenttype.
|
|
1398
|
-
|
|
1399
|
-
Haal weg:
|
|
1400
|
-
- elke eigen HTML-sjabloon die om de layout heen print;
|
|
1401
|
-
- elke gecachte kopie van een layout; de layout wordt per opdracht live gelezen.
|
|
1402
|
-
|
|
1403
|
-
Regels:
|
|
1404
|
-
- layout_id en printer_id komen uit de Engine (public.pick_enqueue_print_job).
|
|
1405
|
-
Kies zelf nooit een andere layout of printer wanneer die velden gevuld zijn.
|
|
1406
|
-
- Statussen blijven binnen de enum print_job_status: wachtend, bezig, voltooid,
|
|
1407
|
-
mislukt, geannuleerd. Andere modules luisteren daarop.
|
|
1408
|
-
- Geen PDF én geen layout: markeer de opdracht als mislukt met een leesbare
|
|
1409
|
-
reden in foutmelding. Nooit blanco printen.
|
|
1410
|
-
|
|
1411
|
-
CONTROLELIJST
|
|
1412
|
-
[ ] Layout aangepast in de Layout maker -> eerstvolgende print toont de wijziging.
|
|
1413
|
-
[ ] Klantsticker en Floriday-document komen er exact uit zoals aangeleverd.
|
|
1784
|
+
body: `Deze prompt vervangt niets uit prompt 1 t/m 6; hij komt er bovenop.
|
|
1785
|
+
|
|
1786
|
+
Uitgangspunt: wat er geprint wordt is ALTIJD de actuele layout uit de Layout
|
|
1787
|
+
maker, gevuld met de echte gegevens van de order en de klant. Enige uitzondering:
|
|
1788
|
+
documenten die al als kant-en-klare PDF bestaan (klantstickers en
|
|
1789
|
+
Floriday-documenten). Die worden ongewijzigd doorgestuurd.
|
|
1790
|
+
|
|
1791
|
+
Volgorde van beslissen bij een printopdracht in public.print_jobs:
|
|
1792
|
+
1. Is er een kant-en-klare PDF meegegeven (pdf-veld op de opdracht / bron uit
|
|
1793
|
+
floriday_customer_sticker_pdfs_cache): die PDF ongewijzigd naar de printer.
|
|
1794
|
+
Niet opnieuw opmaken, niet renderen.
|
|
1795
|
+
2. Is print_jobs.layout_id gevuld: die layout wint. Negeer een eventueel
|
|
1796
|
+
meegestuurde render_html en render vers uit public.document_layouts.
|
|
1797
|
+
3. Pas als beide leeg zijn: meegestuurde render_html, en anders de actieve
|
|
1798
|
+
layout bij het documenttype.
|
|
1799
|
+
|
|
1800
|
+
Haal weg:
|
|
1801
|
+
- elke eigen HTML-sjabloon die om de layout heen print;
|
|
1802
|
+
- elke gecachte kopie van een layout; de layout wordt per opdracht live gelezen.
|
|
1803
|
+
|
|
1804
|
+
Regels:
|
|
1805
|
+
- layout_id en printer_id komen uit de Engine (public.pick_enqueue_print_job).
|
|
1806
|
+
Kies zelf nooit een andere layout of printer wanneer die velden gevuld zijn.
|
|
1807
|
+
- Statussen blijven binnen de enum print_job_status: wachtend, bezig, voltooid,
|
|
1808
|
+
mislukt, geannuleerd. Andere modules luisteren daarop.
|
|
1809
|
+
- Geen PDF én geen layout: markeer de opdracht als mislukt met een leesbare
|
|
1810
|
+
reden in foutmelding. Nooit blanco printen.
|
|
1811
|
+
|
|
1812
|
+
CONTROLELIJST
|
|
1813
|
+
[ ] Layout aangepast in de Layout maker -> eerstvolgende print toont de wijziging.
|
|
1814
|
+
[ ] Klantsticker en Floriday-document komen er exact uit zoals aangeleverd.
|
|
1414
1815
|
[ ] Geen enkele printer- of layoutnaam hardcoded in deze module.`,
|
|
1415
1816
|
},
|
|
1416
1817
|
{
|
|
@@ -1418,38 +1819,38 @@ CONTROLELIJST
|
|
|
1418
1819
|
title: "Pickstation koppelen aan een printplek",
|
|
1419
1820
|
date: "2026-08-25",
|
|
1420
1821
|
summary: "Elk pickstation krijgt een printplek uit de Layout maker; de Engine stuurt die printplek mee en kiest zelf geen printer meer.",
|
|
1421
|
-
body: `Deze prompt vervangt niets uit prompt 1 t/m 7; hij komt er bovenop.
|
|
1422
|
-
|
|
1423
|
-
Wat er verandert in de Logistiek Engine: public.pick_enqueue_print_job kiest
|
|
1424
|
-
geen printer meer. De opdracht krijgt de printplek van het pickstation mee
|
|
1425
|
-
(top-level in payload.print_plek_id en in payload.data.print_plek_id) en gaat
|
|
1426
|
-
altijd als status 'wachtend' de wachtrij in. De Layout maker bepaalt daarna de
|
|
1427
|
-
printer: printplek -> bedrijfsbrede standaardregel, en meldt zelf de reden als
|
|
1428
|
-
dat niet lukt.
|
|
1429
|
-
|
|
1430
|
-
Wat deze module moet doen:
|
|
1431
|
-
- Beheer per pickstation de koppeling naar een printplek in
|
|
1432
|
-
public.print_plek_koppelingen met bron = 'pickstation', bron_id =
|
|
1433
|
-
public.pick_stations.id als tekst, print_plek_id = de gekozen rij uit
|
|
1434
|
-
public.print_plekken. Eén actieve koppeling per pickstation.
|
|
1435
|
-
- Toon bij het aanmaken en wijzigen van een pickstation een keuzelijst met
|
|
1436
|
-
actieve printplekken uit public.print_plekken (naam + omschrijving).
|
|
1437
|
-
Verwijder je een pickstation, verwijder dan ook de koppelrij.
|
|
1438
|
-
- Hardcode nooit een printplek-, printer- of stationsnaam of -id; alles komt
|
|
1439
|
-
uit de database.
|
|
1440
|
-
- Geef _printer_id alleen mee aan pick_enqueue_print_job wanneer een gebruiker
|
|
1441
|
-
bewust handmatig een printer kiest (bijvoorbeeld opnieuw printen). Anders
|
|
1442
|
-
leeg laten.
|
|
1443
|
-
- Een pickstation zonder printplek: toon een duidelijke waarschuwing
|
|
1444
|
-
("Nog geen printplek gekoppeld — de opdracht blijft in de wachtrij staan")
|
|
1445
|
-
in plaats van zelf een printer te kiezen.
|
|
1446
|
-
- Blijf de status van public.print_jobs volgen (wachtend, bezig, voltooid,
|
|
1447
|
-
mislukt, geannuleerd) en toon foutmelding van de Layout maker met een knop
|
|
1448
|
-
"opnieuw printen".
|
|
1449
|
-
|
|
1450
|
-
CONTROLELIJST
|
|
1451
|
-
[ ] Elk pickstation heeft een rij in print_plek_koppelingen.
|
|
1452
|
-
[ ] Nieuwe printopdrachten bevatten payload.print_plek_id.
|
|
1822
|
+
body: `Deze prompt vervangt niets uit prompt 1 t/m 7; hij komt er bovenop.
|
|
1823
|
+
|
|
1824
|
+
Wat er verandert in de Logistiek Engine: public.pick_enqueue_print_job kiest
|
|
1825
|
+
geen printer meer. De opdracht krijgt de printplek van het pickstation mee
|
|
1826
|
+
(top-level in payload.print_plek_id en in payload.data.print_plek_id) en gaat
|
|
1827
|
+
altijd als status 'wachtend' de wachtrij in. De Layout maker bepaalt daarna de
|
|
1828
|
+
printer: printplek -> bedrijfsbrede standaardregel, en meldt zelf de reden als
|
|
1829
|
+
dat niet lukt.
|
|
1830
|
+
|
|
1831
|
+
Wat deze module moet doen:
|
|
1832
|
+
- Beheer per pickstation de koppeling naar een printplek in
|
|
1833
|
+
public.print_plek_koppelingen met bron = 'pickstation', bron_id =
|
|
1834
|
+
public.pick_stations.id als tekst, print_plek_id = de gekozen rij uit
|
|
1835
|
+
public.print_plekken. Eén actieve koppeling per pickstation.
|
|
1836
|
+
- Toon bij het aanmaken en wijzigen van een pickstation een keuzelijst met
|
|
1837
|
+
actieve printplekken uit public.print_plekken (naam + omschrijving).
|
|
1838
|
+
Verwijder je een pickstation, verwijder dan ook de koppelrij.
|
|
1839
|
+
- Hardcode nooit een printplek-, printer- of stationsnaam of -id; alles komt
|
|
1840
|
+
uit de database.
|
|
1841
|
+
- Geef _printer_id alleen mee aan pick_enqueue_print_job wanneer een gebruiker
|
|
1842
|
+
bewust handmatig een printer kiest (bijvoorbeeld opnieuw printen). Anders
|
|
1843
|
+
leeg laten.
|
|
1844
|
+
- Een pickstation zonder printplek: toon een duidelijke waarschuwing
|
|
1845
|
+
("Nog geen printplek gekoppeld — de opdracht blijft in de wachtrij staan")
|
|
1846
|
+
in plaats van zelf een printer te kiezen.
|
|
1847
|
+
- Blijf de status van public.print_jobs volgen (wachtend, bezig, voltooid,
|
|
1848
|
+
mislukt, geannuleerd) en toon foutmelding van de Layout maker met een knop
|
|
1849
|
+
"opnieuw printen".
|
|
1850
|
+
|
|
1851
|
+
CONTROLELIJST
|
|
1852
|
+
[ ] Elk pickstation heeft een rij in print_plek_koppelingen.
|
|
1853
|
+
[ ] Nieuwe printopdrachten bevatten payload.print_plek_id.
|
|
1453
1854
|
[ ] Deze module kiest nergens zelf een printer.`,
|
|
1454
1855
|
},
|
|
1455
1856
|
{
|
|
@@ -1457,29 +1858,29 @@ CONTROLELIJST
|
|
|
1457
1858
|
title: "Layout per ordersoort uit de Engine, anders de actieve layout",
|
|
1458
1859
|
date: "2026-08-26",
|
|
1459
1860
|
summary: "De Engine stuurt per werkwijze (ordersoort) een layout mee; is dat veld leeg, dan wint de actieve layout uit de Layout maker.",
|
|
1460
|
-
body: `Deze prompt vervangt niets uit prompt 1 t/m 8; hij komt er bovenop.
|
|
1461
|
-
|
|
1462
|
-
Wat er verandert in de Logistiek Engine: per werkwijze (ordersoort) kan een
|
|
1463
|
-
gebruiker voor pakbon, sticker, verzendbrief en productiebon kiezen welke
|
|
1464
|
-
layout gebruikt wordt. Kiest hij "Automatisch", dan blijft print_jobs.layout_id
|
|
1465
|
-
leeg. Dat is een geldige situatie, geen fout.
|
|
1466
|
-
|
|
1467
|
-
Vaste volgorde bij het bepalen van wat er geprint wordt:
|
|
1468
|
-
1. Kant-en-klare PDF (pdf_url / pdf_base64, bijvoorbeeld Floriday- of
|
|
1469
|
-
klantstickers): ongewijzigd printen, layout negeren.
|
|
1470
|
-
2. print_jobs.layout_id gevuld: exact die layout renderen.
|
|
1471
|
-
3. Layout_id leeg: de layout die bij dat documenttype op actief staat.
|
|
1472
|
-
4. Geen van alle: opdracht op mislukt met de leesbare reden
|
|
1473
|
-
"Maak een layout aan en zet die op actief."
|
|
1474
|
-
|
|
1475
|
-
Regels:
|
|
1476
|
-
- Kies nooit zelf een andere layout wanneer layout_id gevuld is.
|
|
1477
|
-
- Verander de meegestuurde printplek niet; de printer komt uit de Layout maker.
|
|
1478
|
-
- Hardcode geen layout-, printer- of documenttypenamen.
|
|
1479
|
-
|
|
1480
|
-
CONTROLELIJST
|
|
1481
|
-
[ ] Order met meegestuurde layout gebruikt exact die layout.
|
|
1482
|
-
[ ] Order zonder layout gebruikt de actieve layout van dat documenttype.
|
|
1861
|
+
body: `Deze prompt vervangt niets uit prompt 1 t/m 8; hij komt er bovenop.
|
|
1862
|
+
|
|
1863
|
+
Wat er verandert in de Logistiek Engine: per werkwijze (ordersoort) kan een
|
|
1864
|
+
gebruiker voor pakbon, sticker, verzendbrief en productiebon kiezen welke
|
|
1865
|
+
layout gebruikt wordt. Kiest hij "Automatisch", dan blijft print_jobs.layout_id
|
|
1866
|
+
leeg. Dat is een geldige situatie, geen fout.
|
|
1867
|
+
|
|
1868
|
+
Vaste volgorde bij het bepalen van wat er geprint wordt:
|
|
1869
|
+
1. Kant-en-klare PDF (pdf_url / pdf_base64, bijvoorbeeld Floriday- of
|
|
1870
|
+
klantstickers): ongewijzigd printen, layout negeren.
|
|
1871
|
+
2. print_jobs.layout_id gevuld: exact die layout renderen.
|
|
1872
|
+
3. Layout_id leeg: de layout die bij dat documenttype op actief staat.
|
|
1873
|
+
4. Geen van alle: opdracht op mislukt met de leesbare reden
|
|
1874
|
+
"Maak een layout aan en zet die op actief."
|
|
1875
|
+
|
|
1876
|
+
Regels:
|
|
1877
|
+
- Kies nooit zelf een andere layout wanneer layout_id gevuld is.
|
|
1878
|
+
- Verander de meegestuurde printplek niet; de printer komt uit de Layout maker.
|
|
1879
|
+
- Hardcode geen layout-, printer- of documenttypenamen.
|
|
1880
|
+
|
|
1881
|
+
CONTROLELIJST
|
|
1882
|
+
[ ] Order met meegestuurde layout gebruikt exact die layout.
|
|
1883
|
+
[ ] Order zonder layout gebruikt de actieve layout van dat documenttype.
|
|
1483
1884
|
[ ] Floriday-PDF wordt ongewijzigd geprint.`,
|
|
1484
1885
|
},
|
|
1485
1886
|
{
|
|
@@ -1487,41 +1888,41 @@ CONTROLELIJST
|
|
|
1487
1888
|
title: "Karren en orders uit de gedeelde karindex van de Engine",
|
|
1488
1889
|
date: "2026-09-01",
|
|
1489
1890
|
summary: "pickstation_get_orders_raw geeft nu een veld 'engine' met de canonieke karlijst; die is leidend boven de eigen berekening.",
|
|
1490
|
-
body: `AANVULLING op prompt 1 t/m 9 (die blijven geldig).
|
|
1491
|
-
|
|
1492
|
-
GEMETEN PROBLEEM
|
|
1493
|
-
Het Picking Station bouwde zijn lijst zelf op uit floriday_salesorders_cache en
|
|
1494
|
-
kwam voor vandaag op 2 karren, terwijl de Engine er 38 gepland had staan. Twee
|
|
1495
|
-
schermen, twee verhalen.
|
|
1496
|
-
|
|
1497
|
-
WAT ER VERANDERT
|
|
1498
|
-
public.pickstation_get_orders_raw() geeft dezelfde velden als voorheen
|
|
1499
|
-
(floriday, manual, overrides, print_counts) plus twee nieuwe:
|
|
1500
|
-
|
|
1501
|
-
engine array met één object per (order, kar):
|
|
1502
|
-
pick_date, delivery_date, order_uuid, order_number,
|
|
1503
|
-
order_source, cart_id, cart_index, cart_label, is_shared,
|
|
1504
|
-
task_status, shifted, announced, printed, controlled
|
|
1505
|
-
engine_window { from, to, today } — het venster en de dag volgens de Engine
|
|
1506
|
-
|
|
1507
|
-
BOUW DIT
|
|
1508
|
-
- Is 'engine' gevuld, gebruik die array als enige bron voor de orderlijst en de
|
|
1509
|
-
karrentelling. Geen eigen indeling of telling meer uit de Floriday-cache.
|
|
1510
|
-
- Gebruik engine_window.today als "vandaag"; niet de lokale browserklok.
|
|
1511
|
-
- Statusvelden gebruiken om te filteren of te kleuren:
|
|
1512
|
-
announced = staat in de pickwachtrij, printed = al geprint,
|
|
1513
|
-
controlled = al gecontroleerd. Een filter verandert nooit het totaal.
|
|
1514
|
-
- Gedeelde kar (is_shared true) telt per dag één keer, maar hoort bij elke
|
|
1515
|
-
order waarin hij zit.
|
|
1516
|
-
|
|
1517
|
-
NIET DOEN
|
|
1518
|
-
- Geen eigen kartelling uit salesorders, order_carts of taak-payloads.
|
|
1519
|
-
- Geen eigen datumvenster of tijdzoneconversie.
|
|
1520
|
-
- Geen URL's, project-refs of sleutels hardcoden.
|
|
1521
|
-
|
|
1522
|
-
CONTROLELIJST
|
|
1523
|
-
[ ] Picking Station, Pick agenda en Controle karren tonen voor vandaag hetzelfde aantal karren.
|
|
1524
|
-
[ ] Een geplande maar nog niet aangemelde kar is zichtbaar met status "gepland".
|
|
1891
|
+
body: `AANVULLING op prompt 1 t/m 9 (die blijven geldig).
|
|
1892
|
+
|
|
1893
|
+
GEMETEN PROBLEEM
|
|
1894
|
+
Het Picking Station bouwde zijn lijst zelf op uit floriday_salesorders_cache en
|
|
1895
|
+
kwam voor vandaag op 2 karren, terwijl de Engine er 38 gepland had staan. Twee
|
|
1896
|
+
schermen, twee verhalen.
|
|
1897
|
+
|
|
1898
|
+
WAT ER VERANDERT
|
|
1899
|
+
public.pickstation_get_orders_raw() geeft dezelfde velden als voorheen
|
|
1900
|
+
(floriday, manual, overrides, print_counts) plus twee nieuwe:
|
|
1901
|
+
|
|
1902
|
+
engine array met één object per (order, kar):
|
|
1903
|
+
pick_date, delivery_date, order_uuid, order_number,
|
|
1904
|
+
order_source, cart_id, cart_index, cart_label, is_shared,
|
|
1905
|
+
task_status, shifted, announced, printed, controlled
|
|
1906
|
+
engine_window { from, to, today } — het venster en de dag volgens de Engine
|
|
1907
|
+
|
|
1908
|
+
BOUW DIT
|
|
1909
|
+
- Is 'engine' gevuld, gebruik die array als enige bron voor de orderlijst en de
|
|
1910
|
+
karrentelling. Geen eigen indeling of telling meer uit de Floriday-cache.
|
|
1911
|
+
- Gebruik engine_window.today als "vandaag"; niet de lokale browserklok.
|
|
1912
|
+
- Statusvelden gebruiken om te filteren of te kleuren:
|
|
1913
|
+
announced = staat in de pickwachtrij, printed = al geprint,
|
|
1914
|
+
controlled = al gecontroleerd. Een filter verandert nooit het totaal.
|
|
1915
|
+
- Gedeelde kar (is_shared true) telt per dag één keer, maar hoort bij elke
|
|
1916
|
+
order waarin hij zit.
|
|
1917
|
+
|
|
1918
|
+
NIET DOEN
|
|
1919
|
+
- Geen eigen kartelling uit salesorders, order_carts of taak-payloads.
|
|
1920
|
+
- Geen eigen datumvenster of tijdzoneconversie.
|
|
1921
|
+
- Geen URL's, project-refs of sleutels hardcoden.
|
|
1922
|
+
|
|
1923
|
+
CONTROLELIJST
|
|
1924
|
+
[ ] Picking Station, Pick agenda en Controle karren tonen voor vandaag hetzelfde aantal karren.
|
|
1925
|
+
[ ] Een geplande maar nog niet aangemelde kar is zichtbaar met status "gepland".
|
|
1525
1926
|
[ ] Geen enkele query meer rechtstreeks op floriday_salesorders_cache voor aantallen.`,
|
|
1526
1927
|
},
|
|
1527
1928
|
{
|
|
@@ -1529,34 +1930,34 @@ CONTROLELIJST
|
|
|
1529
1930
|
title: "Volle kar of deelorder: pickeenheid en pakbonvariant uit de taak",
|
|
1530
1931
|
date: "2026-09-03",
|
|
1531
1932
|
summary: "De Engine kent nu de werkwijze \"kleinste telt\" en zet pickUnit en slipVariant in de taak-payload; het pickscherm rekent niets zelf uit.",
|
|
1532
|
-
body: `AANVULLING op prompt 1 t/m 10 (die blijven geldig).
|
|
1533
|
-
|
|
1534
|
-
WAT ER VERANDERT
|
|
1535
|
-
In de Rule Engine kan als pickmethode "Picken per kar of order, kleinste telt"
|
|
1536
|
-
gekozen worden: past een order binnen één kar, dan is de order de pickeenheid;
|
|
1537
|
-
gaat hij over meerdere karren, dan wordt er per kar gepickt.
|
|
1538
|
-
|
|
1539
|
-
De Engine zet dit in de payload van pick.execute en print.packing_slip:
|
|
1540
|
-
|
|
1541
|
-
pickMode de ingestelde werkwijze (order | cart | smallest | buffer)
|
|
1542
|
-
pickUnit de werkelijke eenheid van deze opdracht: "order" of "cart"
|
|
1543
|
-
totalCarriers aantal ladingdragers van de order
|
|
1544
|
-
slipVariant "full_cart" of "partial_order"
|
|
1545
|
-
|
|
1546
|
-
BOUW DIT
|
|
1547
|
-
- Toon en groepeer pickopdrachten op basis van pickUnit, niet op pickMode.
|
|
1548
|
-
- Stuur slipVariant ongewijzigd mee bij het aanvragen of printen van de pakbon.
|
|
1549
|
-
- De layoutkeuze gebeurt in de database (logistics_document_layout_v2); het
|
|
1550
|
-
pickscherm kiest zelf geen layout en geen documenttype.
|
|
1551
|
-
|
|
1552
|
-
NIET DOEN
|
|
1553
|
-
- Niet zelf bepalen of een order een volle kar is.
|
|
1554
|
-
- Geen eigen kartelling; de karindex uit prompt 10 blijft de bron.
|
|
1555
|
-
- Geen URL's, project-refs, sleutels of klantnamen hardcoden.
|
|
1556
|
-
|
|
1557
|
-
CONTROLELIJST
|
|
1558
|
-
[ ] Order binnen één kar levert één pickopdracht per order op.
|
|
1559
|
-
[ ] Order over meerdere karren levert een opdracht per kar op.
|
|
1933
|
+
body: `AANVULLING op prompt 1 t/m 10 (die blijven geldig).
|
|
1934
|
+
|
|
1935
|
+
WAT ER VERANDERT
|
|
1936
|
+
In de Rule Engine kan als pickmethode "Picken per kar of order, kleinste telt"
|
|
1937
|
+
gekozen worden: past een order binnen één kar, dan is de order de pickeenheid;
|
|
1938
|
+
gaat hij over meerdere karren, dan wordt er per kar gepickt.
|
|
1939
|
+
|
|
1940
|
+
De Engine zet dit in de payload van pick.execute en print.packing_slip:
|
|
1941
|
+
|
|
1942
|
+
pickMode de ingestelde werkwijze (order | cart | smallest | buffer)
|
|
1943
|
+
pickUnit de werkelijke eenheid van deze opdracht: "order" of "cart"
|
|
1944
|
+
totalCarriers aantal ladingdragers van de order
|
|
1945
|
+
slipVariant "full_cart" of "partial_order"
|
|
1946
|
+
|
|
1947
|
+
BOUW DIT
|
|
1948
|
+
- Toon en groepeer pickopdrachten op basis van pickUnit, niet op pickMode.
|
|
1949
|
+
- Stuur slipVariant ongewijzigd mee bij het aanvragen of printen van de pakbon.
|
|
1950
|
+
- De layoutkeuze gebeurt in de database (logistics_document_layout_v2); het
|
|
1951
|
+
pickscherm kiest zelf geen layout en geen documenttype.
|
|
1952
|
+
|
|
1953
|
+
NIET DOEN
|
|
1954
|
+
- Niet zelf bepalen of een order een volle kar is.
|
|
1955
|
+
- Geen eigen kartelling; de karindex uit prompt 10 blijft de bron.
|
|
1956
|
+
- Geen URL's, project-refs, sleutels of klantnamen hardcoden.
|
|
1957
|
+
|
|
1958
|
+
CONTROLELIJST
|
|
1959
|
+
[ ] Order binnen één kar levert één pickopdracht per order op.
|
|
1960
|
+
[ ] Order over meerdere karren levert een opdracht per kar op.
|
|
1560
1961
|
[ ] De pakbon van een deelorder gebruikt de deelorder-layout als die ingesteld is.`,
|
|
1561
1962
|
},
|
|
1562
1963
|
{
|
|
@@ -1564,44 +1965,44 @@ CONTROLELIJST
|
|
|
1564
1965
|
title: "Eén order in beeld, picken per kar: \u201cKar X van Y\u201d en een pakbon per kar",
|
|
1565
1966
|
date: "2026-09-03",
|
|
1566
1967
|
summary: "Nieuwe eis bovenop prompt 1 t/m 11: de order blijft één geheel in het scherm, maar het picken en de pakbonnen lopen per kar via logistics_cart_slip_plan.",
|
|
1567
|
-
body: `AANVULLING op prompt 1 t/m 11 (die blijven geldig).
|
|
1568
|
-
|
|
1569
|
-
WAT ER VERANDERT
|
|
1570
|
-
Bij "kleinste telt" blijft een order in het Pick Station één order, ook als hij
|
|
1571
|
-
over meerdere karren gaat. Tijdens het picken moet zichtbaar zijn met welke kar
|
|
1572
|
-
de medewerker bezig is en welke regels bij die kar horen.
|
|
1573
|
-
|
|
1574
|
-
BRON — verplicht
|
|
1575
|
-
const { data } = await supabase.rpc("logistics_cart_slip_plan", { p_order_id });
|
|
1576
|
-
|
|
1577
|
-
Levert per order:
|
|
1578
|
-
cartTotal aantal karren van de order
|
|
1579
|
-
carts[].cartId unieke identificatie van de kar
|
|
1580
|
-
carts[].cartIndex / cartTotal voor "Kar 2 van 3"
|
|
1581
|
-
carts[].cartLabel kant-en-klare tekst "Kar 2 van 3"
|
|
1582
|
-
carts[].isFullCart volle kar of deelkar
|
|
1583
|
-
carts[].slipVariant "full_cart" of "partial_order"
|
|
1584
|
-
carts[].barcode vaste barcode van die kar
|
|
1585
|
-
carts[].items[] producten en aantallen VAN DIE KAR
|
|
1586
|
-
carts[].isShared gemengde kar (meerdere orders)
|
|
1587
|
-
|
|
1588
|
-
BOUW DIT
|
|
1589
|
-
- Toon de order als één regel/kaart met daarin de karren uit carts[].
|
|
1590
|
-
- Toon per kar de cartLabel en uitsluitend carts[].items van die kar.
|
|
1591
|
-
- Een kar kan afzonderlijk afgerond worden; de order is pas klaar als alle
|
|
1592
|
-
karren klaar zijn.
|
|
1593
|
-
- Bij printen van de pakbon stuur je cart_id mee in de payload van de
|
|
1594
|
-
wachtrijregel (veld "cartId" of "cart_id"). De database bepaalt daarmee
|
|
1595
|
-
automatisch de juiste pakbonvariant, "Kar X van Y" en de barcode.
|
|
1596
|
-
|
|
1597
|
-
NIET DOEN
|
|
1598
|
-
- Niet zelf verdelen over karren of aantallen per kar uitrekenen.
|
|
1599
|
-
- Niet zelf de layout of de pakbonvariant kiezen.
|
|
1600
|
-
- Geen URL's, project-refs, sleutels of klantnamen hardcoden.
|
|
1601
|
-
|
|
1602
|
-
CONTROLELIJST
|
|
1603
|
-
[ ] Een order van 3 karren staat als één order in beeld, met 3 karren eronder.
|
|
1604
|
-
[ ] Elke kar toont alleen zijn eigen producten en aantallen.
|
|
1968
|
+
body: `AANVULLING op prompt 1 t/m 11 (die blijven geldig).
|
|
1969
|
+
|
|
1970
|
+
WAT ER VERANDERT
|
|
1971
|
+
Bij "kleinste telt" blijft een order in het Pick Station één order, ook als hij
|
|
1972
|
+
over meerdere karren gaat. Tijdens het picken moet zichtbaar zijn met welke kar
|
|
1973
|
+
de medewerker bezig is en welke regels bij die kar horen.
|
|
1974
|
+
|
|
1975
|
+
BRON — verplicht
|
|
1976
|
+
const { data } = await supabase.rpc("logistics_cart_slip_plan", { p_order_id });
|
|
1977
|
+
|
|
1978
|
+
Levert per order:
|
|
1979
|
+
cartTotal aantal karren van de order
|
|
1980
|
+
carts[].cartId unieke identificatie van de kar
|
|
1981
|
+
carts[].cartIndex / cartTotal voor "Kar 2 van 3"
|
|
1982
|
+
carts[].cartLabel kant-en-klare tekst "Kar 2 van 3"
|
|
1983
|
+
carts[].isFullCart volle kar of deelkar
|
|
1984
|
+
carts[].slipVariant "full_cart" of "partial_order"
|
|
1985
|
+
carts[].barcode vaste barcode van die kar
|
|
1986
|
+
carts[].items[] producten en aantallen VAN DIE KAR
|
|
1987
|
+
carts[].isShared gemengde kar (meerdere orders)
|
|
1988
|
+
|
|
1989
|
+
BOUW DIT
|
|
1990
|
+
- Toon de order als één regel/kaart met daarin de karren uit carts[].
|
|
1991
|
+
- Toon per kar de cartLabel en uitsluitend carts[].items van die kar.
|
|
1992
|
+
- Een kar kan afzonderlijk afgerond worden; de order is pas klaar als alle
|
|
1993
|
+
karren klaar zijn.
|
|
1994
|
+
- Bij printen van de pakbon stuur je cart_id mee in de payload van de
|
|
1995
|
+
wachtrijregel (veld "cartId" of "cart_id"). De database bepaalt daarmee
|
|
1996
|
+
automatisch de juiste pakbonvariant, "Kar X van Y" en de barcode.
|
|
1997
|
+
|
|
1998
|
+
NIET DOEN
|
|
1999
|
+
- Niet zelf verdelen over karren of aantallen per kar uitrekenen.
|
|
2000
|
+
- Niet zelf de layout of de pakbonvariant kiezen.
|
|
2001
|
+
- Geen URL's, project-refs, sleutels of klantnamen hardcoden.
|
|
2002
|
+
|
|
2003
|
+
CONTROLELIJST
|
|
2004
|
+
[ ] Een order van 3 karren staat als één order in beeld, met 3 karren eronder.
|
|
2005
|
+
[ ] Elke kar toont alleen zijn eigen producten en aantallen.
|
|
1605
2006
|
[ ] Er komt één pakbon per kar; de laatste, niet-volle kar krijgt de deelkar-layout.`,
|
|
1606
2007
|
},
|
|
1607
2008
|
{
|
|
@@ -1609,51 +2010,322 @@ CONTROLELIJST
|
|
|
1609
2010
|
title: "Pakbon scannen levert de juiste verzendbrief",
|
|
1610
2011
|
date: "2026-09-03",
|
|
1611
2012
|
summary: "Nieuwe eis bovenop prompt 1 t/m 12: scan de barcode van de pakbon en laat de Engine de bijbehorende verzendbrief klaarzetten.",
|
|
1612
|
-
body: `AANVULLING op prompt 1 t/m 12 (die blijven geldig).
|
|
1613
|
-
|
|
1614
|
-
WERKWIJZE
|
|
1615
|
-
Picken -> pakbon printen -> barcode van de pakbon scannen -> verzendbrief.
|
|
1616
|
-
|
|
1617
|
-
STAP 1 — opzoeken (leest alleen, maakt niets aan)
|
|
1618
|
-
const { data } = await supabase.rpc("logistics_barcode_lookup", { p_barcode });
|
|
1619
|
-
Antwoord bij succes: ok true, orderId, order.orderNumber, order.customerName,
|
|
1620
|
-
cart (met cartLabel, items, slipVariant) en alreadyPrinted/printCount.
|
|
1621
|
-
Antwoord bij een probleem: ok false met errorCode
|
|
1622
|
-
(leeg | ongeldig | onbekend | geen_order) en een kant-en-klare Nederlandse tekst
|
|
1623
|
-
in "error". Toon die tekst letterlijk; verzin geen eigen melding.
|
|
1624
|
-
|
|
1625
|
-
STAP 2 — bevestigen en aanmaken
|
|
1626
|
-
Laat de gevonden order en kar eerst ter controle zien. Pas na een expliciete
|
|
1627
|
-
bevestiging:
|
|
1628
|
-
const { data } = await supabase.rpc("logistics_shipping_note_from_barcode", {
|
|
1629
|
-
p_barcode, p_allow_reprint: false, p_station_id: <pickstation of null>
|
|
1630
|
-
});
|
|
1631
|
-
Is er al eerder een verzendbrief voor deze kar gemaakt, dan komt errorCode
|
|
1632
|
-
"al_geprint" terug. Alleen als de medewerker daarna bewust kiest voor opnieuw
|
|
1633
|
-
printen roep je dezelfde RPC aan met p_allow_reprint: true.
|
|
1634
|
-
|
|
1635
|
-
De RPC zet zelf een printopdracht klaar (print_jobs, status wachtend) met de
|
|
1636
|
-
juiste layout en printplek. Ontbreekt de layout, dan staat dat leesbaar in
|
|
1637
|
-
"warning" en blijft de job wachten — toon die waarschuwing.
|
|
1638
|
-
|
|
1639
|
-
NIET DOEN
|
|
1640
|
-
- Nooit een verzendbrief aanmaken zonder bevestigde lookup.
|
|
1641
|
-
- Niet zelf print_jobs vullen of zelf een layout kiezen.
|
|
1642
|
-
- Geen tweede verzendbrief bij een dubbele scan zonder bewuste keuze.
|
|
1643
|
-
- Geen URL's, project-refs, sleutels of klantnamen hardcoden.
|
|
1644
|
-
|
|
1645
|
-
LAYOUT MAKER
|
|
1646
|
-
Op de pakbon-template hoort een barcode-element met als waarde het veld
|
|
1647
|
-
"barcode" uit de meegeleverde printgegevens (ook beschikbaar als
|
|
1648
|
-
payload.data.cart.barcode). Positie en weergave bepaal je in de template zelf.
|
|
1649
|
-
Er zijn twee pakbonvarianten: volledige kar en resterende order / deelkar.
|
|
1650
|
-
|
|
1651
|
-
CONTROLELIJST
|
|
1652
|
-
[ ] Scannen van een pakbon toont eerst order, kar en aantallen.
|
|
1653
|
-
[ ] Na bevestigen staat er een verzendbrief klaar bij de juiste printer.
|
|
1654
|
-
[ ] Een onbekende barcode geeft de melding uit de RPC en maakt niets aan.
|
|
2013
|
+
body: `AANVULLING op prompt 1 t/m 12 (die blijven geldig).
|
|
2014
|
+
|
|
2015
|
+
WERKWIJZE
|
|
2016
|
+
Picken -> pakbon printen -> barcode van de pakbon scannen -> verzendbrief.
|
|
2017
|
+
|
|
2018
|
+
STAP 1 — opzoeken (leest alleen, maakt niets aan)
|
|
2019
|
+
const { data } = await supabase.rpc("logistics_barcode_lookup", { p_barcode });
|
|
2020
|
+
Antwoord bij succes: ok true, orderId, order.orderNumber, order.customerName,
|
|
2021
|
+
cart (met cartLabel, items, slipVariant) en alreadyPrinted/printCount.
|
|
2022
|
+
Antwoord bij een probleem: ok false met errorCode
|
|
2023
|
+
(leeg | ongeldig | onbekend | geen_order) en een kant-en-klare Nederlandse tekst
|
|
2024
|
+
in "error". Toon die tekst letterlijk; verzin geen eigen melding.
|
|
2025
|
+
|
|
2026
|
+
STAP 2 — bevestigen en aanmaken
|
|
2027
|
+
Laat de gevonden order en kar eerst ter controle zien. Pas na een expliciete
|
|
2028
|
+
bevestiging:
|
|
2029
|
+
const { data } = await supabase.rpc("logistics_shipping_note_from_barcode", {
|
|
2030
|
+
p_barcode, p_allow_reprint: false, p_station_id: <pickstation of null>
|
|
2031
|
+
});
|
|
2032
|
+
Is er al eerder een verzendbrief voor deze kar gemaakt, dan komt errorCode
|
|
2033
|
+
"al_geprint" terug. Alleen als de medewerker daarna bewust kiest voor opnieuw
|
|
2034
|
+
printen roep je dezelfde RPC aan met p_allow_reprint: true.
|
|
2035
|
+
|
|
2036
|
+
De RPC zet zelf een printopdracht klaar (print_jobs, status wachtend) met de
|
|
2037
|
+
juiste layout en printplek. Ontbreekt de layout, dan staat dat leesbaar in
|
|
2038
|
+
"warning" en blijft de job wachten — toon die waarschuwing.
|
|
2039
|
+
|
|
2040
|
+
NIET DOEN
|
|
2041
|
+
- Nooit een verzendbrief aanmaken zonder bevestigde lookup.
|
|
2042
|
+
- Niet zelf print_jobs vullen of zelf een layout kiezen.
|
|
2043
|
+
- Geen tweede verzendbrief bij een dubbele scan zonder bewuste keuze.
|
|
2044
|
+
- Geen URL's, project-refs, sleutels of klantnamen hardcoden.
|
|
2045
|
+
|
|
2046
|
+
LAYOUT MAKER
|
|
2047
|
+
Op de pakbon-template hoort een barcode-element met als waarde het veld
|
|
2048
|
+
"barcode" uit de meegeleverde printgegevens (ook beschikbaar als
|
|
2049
|
+
payload.data.cart.barcode). Positie en weergave bepaal je in de template zelf.
|
|
2050
|
+
Er zijn twee pakbonvarianten: volledige kar en resterende order / deelkar.
|
|
2051
|
+
|
|
2052
|
+
CONTROLELIJST
|
|
2053
|
+
[ ] Scannen van een pakbon toont eerst order, kar en aantallen.
|
|
2054
|
+
[ ] Na bevestigen staat er een verzendbrief klaar bij de juiste printer.
|
|
2055
|
+
[ ] Een onbekende barcode geeft de melding uit de RPC en maakt niets aan.
|
|
1655
2056
|
[ ] Een tweede scan waarschuwt en print pas na een bewuste keuze opnieuw.`,
|
|
1656
2057
|
},
|
|
2058
|
+
{
|
|
2059
|
+
number: 14,
|
|
2060
|
+
title: "Stickers printen automatisch mee met de pakbon",
|
|
2061
|
+
date: "2026-09-03",
|
|
2062
|
+
summary: "Nieuwe eis bovenop prompt 1 t/m 13: bij de instelling \u201cgelijk met de bijbehorende pakbon\u201d maakt de Engine de stickerprintopdracht zelf aan.",
|
|
2063
|
+
body: `AANVULLING op prompt 1 t/m 13 (die blijven geldig).
|
|
2064
|
+
|
|
2065
|
+
WAT ER VERANDERT
|
|
2066
|
+
Staat in de Logistiek Engine bij Stickers de keuze "Gelijk met de bijbehorende
|
|
2067
|
+
pakbon" aan, dan zet pick_enqueue_print_job naast de pakbon meteen ook een
|
|
2068
|
+
stickerprintopdracht klaar. Dat gebeurt in de database, dus voor elk pickstation
|
|
2069
|
+
precies hetzelfde. Het pickscherm hoeft daar niets extra's voor te doen.
|
|
2070
|
+
|
|
2071
|
+
REGELS
|
|
2072
|
+
- Roep gewoon pick_enqueue_print_job aan zoals nu; niet zelf een tweede
|
|
2073
|
+
printopdracht voor stickers aanmaken.
|
|
2074
|
+
- De sticker krijgt dezelfde printplek als de pakbon (het pickstation van de
|
|
2075
|
+
regel) en de stickerlayout uit de Engine-instelling.
|
|
2076
|
+
- Herken de bijbehorende stickerjob aan payload.trigger = "with_packing_slip"
|
|
2077
|
+
en payload.packing_slip_job_id; toon hem bij de pakbon in de statusweergave.
|
|
2078
|
+
- Ontbreekt er een actieve stickerlayout, dan blijft de job op "wachtend" staan
|
|
2079
|
+
met een leesbare foutmelding; toon die melding.
|
|
2080
|
+
- Geen eigen stationkeuze voor stickers meer: die volgt de pakbon.
|
|
2081
|
+
|
|
2082
|
+
CONTROLELIJST
|
|
2083
|
+
[ ] Eén druk op "uitprinten" levert pakbon en sticker samen.
|
|
2084
|
+
[ ] Beide jobs staan op dezelfde printplek.
|
|
2085
|
+
[ ] Zonder stickerlayout is de reden zichtbaar in het scherm.`,
|
|
2086
|
+
},
|
|
2087
|
+
{
|
|
2088
|
+
number: 15,
|
|
2089
|
+
title: "Afgehandelde karren en orders verdwijnen uit het pickscherm",
|
|
2090
|
+
date: "2026-09-03",
|
|
2091
|
+
summary: "Nieuwe eis bovenop prompt 1 t/m 14: wat bij Karrencontrole is afgemeld, wordt niet meer getoond in het pickingscherm.",
|
|
2092
|
+
body: `AANVULLING op prompt 1 t/m 14 (die blijven geldig).
|
|
2093
|
+
|
|
2094
|
+
WAT ER VERANDERT
|
|
2095
|
+
Zodra een kar bij Karrencontrole in de Afhandelmodule is afgemeld (goedgekeurd
|
|
2096
|
+
of afgeleverd), is die kar "afgehandeld". Is elke kar van een order afgehandeld,
|
|
2097
|
+
dan is de hele order afgehandeld. De Engine haalt die karren en orders zelf weg:
|
|
2098
|
+
|
|
2099
|
+
- public.logistics_cart_handled(order_id, cart_index) - is deze kar afgehandeld?
|
|
2100
|
+
- public.logistics_order_handled(order_uuid) - is de hele order afgehandeld?
|
|
2101
|
+
- pickstation_get_orders_raw levert afgehandelde karren en volledig afgehandelde
|
|
2102
|
+
orders niet meer terug (ook niet in de floriday- en handmatige lijst).
|
|
2103
|
+
- pick_queue-regels van een volledig afgehandelde order worden direct verwijderd,
|
|
2104
|
+
ook tijdens de pickdag.
|
|
2105
|
+
|
|
2106
|
+
REGELS
|
|
2107
|
+
- Bouw geen eigen "verbergen"-logica en filter niet zelf op controlestatus;
|
|
2108
|
+
wat de RPC teruggeeft is de volledige werkvoorraad.
|
|
2109
|
+
- Een kar die verdwijnt terwijl het scherm openstaat is normaal: ververs op de
|
|
2110
|
+
gebruikelijke manier en toon geen foutmelding.
|
|
2111
|
+
- Reeds geprinte documenten blijven geldig; herprinten van een afgehandelde kar
|
|
2112
|
+
gebeurt niet meer vanuit het pickscherm.
|
|
2113
|
+
- Geen omgevingswaarden of klantspecifieke ID's in code.
|
|
2114
|
+
|
|
2115
|
+
CONTROLELIJST
|
|
2116
|
+
[ ] Kar afmelden bij Karrencontrole -> kar weg uit het pickscherm.
|
|
2117
|
+
[ ] Laatste kar van een order afmelden -> hele order weg uit het pickscherm.
|
|
2118
|
+
[ ] Nog niet afgehandelde karren blijven gewoon zichtbaar.`,
|
|
2119
|
+
},
|
|
2120
|
+
{
|
|
2121
|
+
number: 16,
|
|
2122
|
+
title: "Karnummer per order: cart_seq en cart_number tonen",
|
|
2123
|
+
date: "2026-09-03",
|
|
2124
|
+
summary: "Karnummers komen uit de Engine: toon cart_seq en cart_number, nooit cart_index, en reken zelf niets om.",
|
|
2125
|
+
body: `AANVULLING op de eerdere prompts (die blijven geldig).
|
|
2126
|
+
|
|
2127
|
+
WAT ER VERANDERT
|
|
2128
|
+
De Engine levert vanaf nu per kar een stabiel karnummer. Modules rekenen zelf
|
|
2129
|
+
NIETS meer om en hernummeren niet.
|
|
2130
|
+
|
|
2131
|
+
VELDEN (uit de Engine-RPC's)
|
|
2132
|
+
- cart_seq : stabiel, 1-gebaseerd volgnummer van de kar binnen zijn order.
|
|
2133
|
+
Identiek aan het nummer op de pakbon in de verkoopmodule. Verandert niet als
|
|
2134
|
+
karren op verschillende dagen gepickt of gecontroleerd worden, en niet als een
|
|
2135
|
+
deel van de karren al is afgehandeld.
|
|
2136
|
+
- cart_number : het definitieve karnummer-label (bijv. het toegewezen
|
|
2137
|
+
karnummer uit de karnummering). Toon dit als label.
|
|
2138
|
+
- cart_total : het aantal karren van die order ("Kar X van Y" = cart_seq van
|
|
2139
|
+
cart_total).
|
|
2140
|
+
- cart_index : INTERN. Technische index, niet gedefinieerd als 0- of
|
|
2141
|
+
1-gebaseerd. NOOIT tonen en nooit als basis voor eigen nummering gebruiken.
|
|
2142
|
+
|
|
2143
|
+
WAAR STAAN DE VELDEN
|
|
2144
|
+
control_get_todays_carts(), logistics_pick_agenda(p_from, p_to) (per order in
|
|
2145
|
+
cartList), logistics_cart_index(p_from, p_to), logistics_control_scan_lookup(
|
|
2146
|
+
p_barcode) (cartSeq / cartNumber / cartTotal) en
|
|
2147
|
+
logistics_control_scan_overview(p_scanner_id, p_date).
|
|
2148
|
+
|
|
2149
|
+
GEBRUIK IN DEZE MODULE
|
|
2150
|
+
Het pickstation toont per kar "Kar cart_seq van cart_total" en het label
|
|
2151
|
+
cart_number, gelijk aan de pakbon.
|
|
2152
|
+
|
|
2153
|
+
NIET DOEN
|
|
2154
|
+
- Niet zelf nummeren, sorteren op index, of +1 optellen bij cart_index.
|
|
2155
|
+
- Geen aparte nummering per dag, per pickronde of per controlesessie.
|
|
2156
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
2157
|
+
|
|
2158
|
+
CONTROLELIJST
|
|
2159
|
+
[ ] Elk karnummer in het scherm komt uit cart_seq / cart_number.
|
|
2160
|
+
[ ] "Kar X van Y" gebruikt cart_seq en cart_total.
|
|
2161
|
+
[ ] Een order met 4 karren toont 1 t/m 4, ook als er al karren afgehandeld zijn.
|
|
2162
|
+
[ ] Het getoonde nummer is gelijk aan het nummer op de pakbon.
|
|
2163
|
+
[ ] cart_index komt nergens in de weergave voor.`,
|
|
2164
|
+
},
|
|
2165
|
+
{
|
|
2166
|
+
number: 17,
|
|
2167
|
+
title: "Een bufferorder is één order op het pickscherm",
|
|
2168
|
+
date: "2026-09-05",
|
|
2169
|
+
summary: "Orders die samen in een orderbuffer zitten, tonen als één order met één gezamenlijke karrenindeling.",
|
|
2170
|
+
body: `AANVULLING op de eerdere prompts (die blijven geldig).
|
|
2171
|
+
|
|
2172
|
+
WAT ER VERANDERT
|
|
2173
|
+
Orders die samen in één orderbuffer zitten, zijn logistiek één order. De Engine
|
|
2174
|
+
levert ze vanaf nu ook als één eenheid aan. Het pickscherm toont ze dus als ÉÉN
|
|
2175
|
+
order met ÉÉN karrenindeling, niet als losse orders met elk hun eigen karren.
|
|
2176
|
+
|
|
2177
|
+
BRON
|
|
2178
|
+
- pickstation_get_orders_raw() -> engine[]: per kar met
|
|
2179
|
+
order_number (= unit_ref, het leidende ordernummer van de eenheid),
|
|
2180
|
+
unit_ref, is_buffer, buffer_id, buffer_orders[] (alle ordernummers in de
|
|
2181
|
+
buffer), member_order_number (intern), cart_id, cart_seq, cart_number,
|
|
2182
|
+
cart_total.
|
|
2183
|
+
- Dezelfde eenheid staat in logistics_cart_units(p_from, p_to),
|
|
2184
|
+
logistics_pick_agenda() en control_get_todays_carts().
|
|
2185
|
+
- pickstation_get_orders_raw().units is een map ordernummer -> eenheid, om een
|
|
2186
|
+
losse order naar zijn eenheid te vertalen.
|
|
2187
|
+
|
|
2188
|
+
GEBRUIK IN DEZE MODULE
|
|
2189
|
+
- Groepeer alles op unit_ref. Toon één regel/kaart per eenheid.
|
|
2190
|
+
- Karnummering loopt door over de hele eenheid: cart_seq 1..cart_total.
|
|
2191
|
+
- Is is_buffer waar, toon dan de losse ordernummers uit buffer_orders als
|
|
2192
|
+
subregel ("bevat: HO-... , HO-..."), maar nooit als aparte pickorders.
|
|
2193
|
+
- De pakbon komt op het leidende ordernummer (PB-<unit_ref>); er is per eenheid
|
|
2194
|
+
één pakbonregel in pick_queue.
|
|
2195
|
+
|
|
2196
|
+
NIET DOEN
|
|
2197
|
+
- Niet groeperen op member_order_number of op de losse orders uit manual[].
|
|
2198
|
+
- Niet zelf karren optellen of hernummeren per losse order.
|
|
2199
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
2200
|
+
|
|
2201
|
+
CONTROLELIJST
|
|
2202
|
+
[ ] Twee orders in dezelfde buffer staan als één order op het scherm.
|
|
2203
|
+
[ ] De karren van beide orders staan onder één doorlopende nummering.
|
|
2204
|
+
[ ] Er is één pakbon per eenheid, niet één per losse order.
|
|
2205
|
+
[ ] Losse orders zonder buffer werken exact zoals voorheen.`,
|
|
2206
|
+
},
|
|
2207
|
+
{
|
|
2208
|
+
number: 18,
|
|
2209
|
+
title: "Ook bij handmatig kiezen van een pickdag één bufferregel",
|
|
2210
|
+
date: "2026-09-05",
|
|
2211
|
+
summary: "Voorkom dat het laden van een gekozen pickdag de losse leden van een buffer opnieuw als aparte pakbonregels toevoegt.",
|
|
2212
|
+
body: `AANVULLING op prompt 17 (die blijft geldig).
|
|
2213
|
+
|
|
2214
|
+
PROBLEEM
|
|
2215
|
+
De algemene Engine-synchronisatie groepeert een buffer correct, maar
|
|
2216
|
+
pick_sync_pick_day(_day) kan de leden opnieuw afzonderlijk in public.pick_queue
|
|
2217
|
+
zetten. Daardoor verschijnen na het kiezen van een datum toch twee regels.
|
|
2218
|
+
|
|
2219
|
+
VASTE WERKWIJZE
|
|
2220
|
+
- Gebruik public.logistics_pick_units() als leidende vertaling van order_number
|
|
2221
|
+
naar unit_ref, unit_buffer, is_buffer en unit_orders.
|
|
2222
|
+
- Verwerk bij het laden van een pickdag één keer per unit_ref, nooit één keer
|
|
2223
|
+
per los ordernummer.
|
|
2224
|
+
- Schrijf de pakbonregel op het leidende unit_ref met documentnummer
|
|
2225
|
+
PB-<unit_ref>.
|
|
2226
|
+
- Tel line_count over alle order-id's uit de eenheid en tel alle unieke karren
|
|
2227
|
+
van de orders én de gezamenlijke buffer.
|
|
2228
|
+
- Neem in payload altijd unitRef, bufferId, isBuffer, bufferOrders en orderIds
|
|
2229
|
+
op. Gebruik geen stil alternatief op basis van het losse ordernummer.
|
|
2230
|
+
- Ruim vóór het tonen niet-leidende, nog niet afgeronde bufferregels op via
|
|
2231
|
+
public.logistics_prune_buffer_member_queue().
|
|
2232
|
+
|
|
2233
|
+
WEERGAVE
|
|
2234
|
+
- Groepeer de zichtbare wachtrij aanvullend op payload.unitRef; gebruik bij
|
|
2235
|
+
oudere rijen de units-map uit pickstation_get_orders_raw() om order_number
|
|
2236
|
+
eerst naar unit_ref te vertalen.
|
|
2237
|
+
- Toon bufferOrders alleen als subregel en nooit als losse tabelregels.
|
|
2238
|
+
|
|
2239
|
+
NIET DOEN
|
|
2240
|
+
- pick_sync_pick_day niet rechtstreeks gebruiken zonder bovenstaande
|
|
2241
|
+
buffer-normalisatie.
|
|
2242
|
+
- Niet groeperen op order_number, document_number of payload.orderId.
|
|
2243
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
2244
|
+
|
|
2245
|
+
CONTROLELIJST
|
|
2246
|
+
[ ] Een buffer met twee orders levert na datum wisselen precies één regel op.
|
|
2247
|
+
[ ] De regel bevat het totaal van alle orderregels en alle unieke bufferkarren.
|
|
2248
|
+
[ ] Terugschakelen van dag of verversen maakt geen tweede regel aan.
|
|
2249
|
+
[ ] Een al geprinte historische regel blijft bewaard, maar is niet opnieuw zichtbaar.`,
|
|
2250
|
+
},
|
|
2251
|
+
{
|
|
2252
|
+
number: 19,
|
|
2253
|
+
title: "Bufferorder tonen als bufferorder, ook bij printopdrachten",
|
|
2254
|
+
date: "2026-09-05",
|
|
2255
|
+
summary: "Toon nooit de losse ordernummers van een buffer; gebruik het bufferlabel en negeer geannuleerde printopdrachten van bufferleden.",
|
|
2256
|
+
body: `AANVULLING op prompt 17 en 18 (die blijven geldig).
|
|
2257
|
+
|
|
2258
|
+
PROBLEEM
|
|
2259
|
+
De wachtrij toonde de buffer één keer, maar het scherm vult zichzelf ook aan
|
|
2260
|
+
met wachtende rijen uit public.print_jobs. Van een meelopend bufferlid stond
|
|
2261
|
+
daar nog een wachtende pakbon, waardoor de buffer alsnog als twee losse orders
|
|
2262
|
+
(PB-HO-... en PB-HO-...) op het scherm kwam.
|
|
2263
|
+
|
|
2264
|
+
VASTE WERKWIJZE
|
|
2265
|
+
- Toon uitsluitend printopdrachten met status 'wachtend'; opdrachten met status
|
|
2266
|
+
'geannuleerd' verdwijnen direct uit de lijst.
|
|
2267
|
+
- Vertaal het ordernummer van elke printopdracht eerst via
|
|
2268
|
+
public.logistics_pick_units() naar unit_ref en toon maximaal één regel per
|
|
2269
|
+
unit_ref per documentsoort.
|
|
2270
|
+
- Gebruik als zichtbare titel payload.unitLabel wanneer die aanwezig is
|
|
2271
|
+
(bijvoorbeeld "Bufferorder <unit_ref> (2 orders)"). Toon de losse
|
|
2272
|
+
ordernummers uit bufferOrders alleen als subregel onder die ene regel.
|
|
2273
|
+
- De Engine annuleert wachtende printopdrachten van niet-leidende bufferleden
|
|
2274
|
+
bij elke opruimronde; maak zelf nooit een nieuwe aan voor een meelopend lid.
|
|
2275
|
+
|
|
2276
|
+
NIET DOEN
|
|
2277
|
+
- Geen regel tonen op basis van alleen print_jobs.payload.order_number.
|
|
2278
|
+
- Geen eigen documentnummer of ordernummer verzinnen voor een buffer.
|
|
2279
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
2280
|
+
|
|
2281
|
+
CONTROLELIJST
|
|
2282
|
+
[ ] Een buffer met twee orders geeft precies één regel, met bufferlabel.
|
|
2283
|
+
[ ] Geannuleerde printopdrachten van bufferleden zijn niet meer zichtbaar.
|
|
2284
|
+
[ ] De subregels tonen de losse ordernummers van de buffer.`,
|
|
2285
|
+
},
|
|
2286
|
+
{
|
|
2287
|
+
number: 20,
|
|
2288
|
+
title: "Karplanning opvragen bij de Engine, nooit zelf bepalen",
|
|
2289
|
+
date: "2026-09-05",
|
|
2290
|
+
summary: "Eén vraag aan de Engine bepaalt of het karplan klaar is en of de order vrijgegeven is; alleen dan een seintje sturen.",
|
|
2291
|
+
body: `AANVULLING op prompt 17 t/m 19 (die blijven geldig).
|
|
2292
|
+
|
|
2293
|
+
PROBLEEM
|
|
2294
|
+
Het pickscherm meldt "karplanning nog niet klaar" terwijl de Engine wél een
|
|
2295
|
+
sluitend karplan heeft vastgelegd. Het scherm zoekt zelf naar karren bij een
|
|
2296
|
+
pakbonnummer en concludeert bij een misser onterecht dat het plan ontbreekt.
|
|
2297
|
+
Daarnaast verschijnen orders die door de Engine nog niet zijn vrijgegeven.
|
|
2298
|
+
|
|
2299
|
+
VASTE WERKWIJZE
|
|
2300
|
+
- Vraag per order of pakbon exact één keer:
|
|
2301
|
+
select public.logistics_cart_plan_status('<ordernummer of PB-nummer>')
|
|
2302
|
+
De uitkomst is één JSON-object met:
|
|
2303
|
+
ready, reason, orderId, orderRef, released, cartTotal en
|
|
2304
|
+
carts[] met cartId, cartNumber, cartSeq, cartTotal, cartLabel, barcode,
|
|
2305
|
+
isShared, isFullCart, slipVariant.
|
|
2306
|
+
- ready = true: gebruik uitsluitend deze karren, karnummers, labels en
|
|
2307
|
+
barcodes. Nooit zelf tellen, nummeren of een barcode afleiden.
|
|
2308
|
+
- ready = false: toon reason letterlijk als reden en stuur pas dán het seintje
|
|
2309
|
+
cartplan.missing in public.logistics_events (zoals in de bestaande afspraak).
|
|
2310
|
+
- released = false: toon de order nog niet als te printen of te picken. Het
|
|
2311
|
+
vrijgavemoment komt van de Engine (logistics_order_released), niet van de
|
|
2312
|
+
leverdatum of de pickdag.
|
|
2313
|
+
- Voor een bufferorder geeft elk lid via zijn eigen order-UUID hetzelfde plan
|
|
2314
|
+
met dezelfde cartId's en hetzelfde totaal; toon één regel per unit_ref.
|
|
2315
|
+
|
|
2316
|
+
NIET DOEN
|
|
2317
|
+
- Geen eigen zoekopdracht op order_carts of print_jobs om te bepalen of er een
|
|
2318
|
+
karplan bestaat.
|
|
2319
|
+
- Geen "voorlopig één pakbon als één document" fallback bij ready = false;
|
|
2320
|
+
fail closed met de reden uit de Engine.
|
|
2321
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
2322
|
+
|
|
2323
|
+
CONTROLELIJST
|
|
2324
|
+
[ ] Een order met een bestaand plan toont nooit meer "karplanning nog niet klaar".
|
|
2325
|
+
[ ] Een niet-vrijgegeven order staat niet op het pickscherm.
|
|
2326
|
+
[ ] Karnummers, labels en barcodes komen letterlijk uit de Engine.
|
|
2327
|
+
[ ] Bij ready = false gaat er één seintje cartplan.missing uit, met de reden.`,
|
|
2328
|
+
},
|
|
1657
2329
|
],
|
|
1658
2330
|
},
|
|
1659
2331
|
scanners: {
|
|
@@ -1666,14 +2338,236 @@ CONTROLELIJST
|
|
|
1666
2338
|
date: "2026-07-24",
|
|
1667
2339
|
summary: "Scan- en controletaken uitvoeren.",
|
|
1668
2340
|
withSharedContract: true,
|
|
1669
|
-
body: `Haal weg: eigen aannames over wat en wanneer er gescand moet worden.
|
|
1670
|
-
|
|
1671
|
-
Bouw:
|
|
1672
|
-
- scan.verify taken; payload reason = pick_scanner_required of kar_vullen_manual_scan.
|
|
1673
|
-
- control.execute taken met controlMode "scanner" = de scancontrole.
|
|
1674
|
-
- Scanresultaat meesturen in logistics_complete_task (p_result).
|
|
2341
|
+
body: `Haal weg: eigen aannames over wat en wanneer er gescand moet worden.
|
|
2342
|
+
|
|
2343
|
+
Bouw:
|
|
2344
|
+
- scan.verify taken; payload reason = pick_scanner_required of kar_vullen_manual_scan.
|
|
2345
|
+
- control.execute taken met controlMode "scanner" = de scancontrole.
|
|
2346
|
+
- Scanresultaat meesturen in logistics_complete_task (p_result).
|
|
1675
2347
|
- Bij afwijking logistics_fail_task met toelichting.`,
|
|
1676
2348
|
},
|
|
2349
|
+
{
|
|
2350
|
+
number: 2,
|
|
2351
|
+
title: "Een gescande code eerst door de Engine laten herkennen",
|
|
2352
|
+
date: "2026-09-03",
|
|
2353
|
+
summary: "Nieuwe eis bovenop prompt 1: pakbon-/karbarcodes niet meer als onbekend product melden, maar opzoeken via logistics_scan_resolve.",
|
|
2354
|
+
body: `AANVULLING op koppelprompt 1 (die blijft gewoon geldig).
|
|
2355
|
+
|
|
2356
|
+
Probleem: een barcode van een pakbon (formaat LC + 16 tekens, bijvoorbeeld
|
|
2357
|
+
LC5E28A9B4B9124ED1) werd afgewezen met "Onbekend product". Die code hoort niet
|
|
2358
|
+
bij een product maar bij een kar en de pakbon van die kar.
|
|
2359
|
+
|
|
2360
|
+
Bouw:
|
|
2361
|
+
- Elke gescande of ingetypte code die niet als product wordt herkend, eerst
|
|
2362
|
+
door de Engine laten herkennen:
|
|
2363
|
+
|
|
2364
|
+
const { data } = await supabase.rpc("logistics_scan_resolve", { p_code: code });
|
|
2365
|
+
|
|
2366
|
+
Losse spaties, kleine letters of extra tekens rond de code hoeven niet zelf
|
|
2367
|
+
te worden opgeschoond; dat doet de RPC.
|
|
2368
|
+
|
|
2369
|
+
- data.kind = "kar_pakbon" en data.ok = true -> toon:
|
|
2370
|
+
data.order.orderNumber, data.order.customerName, data.order.deliveryDate
|
|
2371
|
+
data.cart.cartNumber, data.cart.cartIndex / data.cart.cartTotal
|
|
2372
|
+
data.packingSlip.documentName (het pakbonnummer, kan null zijn)
|
|
2373
|
+
data.alreadyPrinted / data.printCount (al eerder gescand)
|
|
2374
|
+
data.warning (indien gevuld: tonen als waarschuwing, niet als fout)
|
|
2375
|
+
Ga daarna verder in de karflow; behandel dit NOOIT als productscan.
|
|
2376
|
+
|
|
2377
|
+
- data.ok = false -> toon data.error letterlijk. Verzin geen eigen tekst.
|
|
2378
|
+
errorCode "kar_vervallen" betekent: de pakbon is verouderd, de kar is opnieuw
|
|
2379
|
+
ingedeeld; toon de order erbij en vraag om een nieuwe pakbon te printen.
|
|
2380
|
+
errorCode "onbekend"/"ongeldig" -> pas dan mag de melding "Onbekend product".
|
|
2381
|
+
|
|
2382
|
+
- Doe zelf geen lookup op order_carts, logistics_cart_barcode of op stukjes van
|
|
2383
|
+
een uuid. De koppeling barcode -> kar -> pakbon is van de Engine.`,
|
|
2384
|
+
},
|
|
2385
|
+
{
|
|
2386
|
+
number: 3,
|
|
2387
|
+
title: "Gedrukte pakbon is leidend bij het scannen",
|
|
2388
|
+
date: "2026-09-03",
|
|
2389
|
+
summary: "Pakbonbarcodes worden vóór productcodes opgezocht in de blijvende pakbonregistratie, ook wanneer de oorspronkelijke kar opnieuw is ingedeeld.",
|
|
2390
|
+
body: `AANVULLING op koppelprompt 1 en 2 (die blijven geldig, niets samenvoegen
|
|
2391
|
+
of terugdraaien).
|
|
2392
|
+
|
|
2393
|
+
BEVESTIGD PROBLEEM
|
|
2394
|
+
Een pakbonbarcode staat blijvend in pakbon_barcode_inhoud, maar de tijdelijke
|
|
2395
|
+
order_carts-rij kan na een herindeling zijn verwijderd. De code is dan nog
|
|
2396
|
+
steeds een geldige pakbonbarcode en mag nooit als "Onbekend product" worden
|
|
2397
|
+
behandeld.
|
|
2398
|
+
|
|
2399
|
+
BOUW DIT
|
|
2400
|
+
- Herken het formaat LC + 16 hextekens direct na de camerascan, vóór iedere
|
|
2401
|
+
productlookup. Stuur zo'n code altijd eerst naar de Engine:
|
|
2402
|
+
|
|
2403
|
+
const { data } = await supabase.rpc("logistics_scan_resolve", {
|
|
2404
|
+
p_code: gescandeCode,
|
|
2405
|
+
});
|
|
2406
|
+
|
|
2407
|
+
- data.kind = "kar_pakbon" betekent dat dit de pakbon-/karflow is. Stuur deze
|
|
2408
|
+
code nooit daarna nog door naar de productlookup.
|
|
2409
|
+
- data.ok = true: toon exact de meegeleverde packingSlip, orders, klant,
|
|
2410
|
+
cartLabel/cartIndex/cartTotal en regels/belading.
|
|
2411
|
+
- data.stale = true of data.processingAllowed = false: de barcode is wel als
|
|
2412
|
+
pakbon herkend, maar de indeling is gewijzigd. Toon data.warning of
|
|
2413
|
+
data.error letterlijk en blokkeer goedkeuren. Bied alleen "Pakbon opnieuw
|
|
2414
|
+
printen" aan via de bestaande Engine-flow.
|
|
2415
|
+
- data.ok = false en errorCode = "onbekend" of "ongeldig": pas dan mag de
|
|
2416
|
+
bestaande productlookup volgen. Alleen wanneer ook die lookup niets vindt,
|
|
2417
|
+
toon je "Onbekend product".
|
|
2418
|
+
- Ondersteun meerdere orders in data.orders; kies of raad nooit zelf één order
|
|
2419
|
+
bij een gedeelde kar.
|
|
2420
|
+
- Blokkeer de actieknop tijdens de RPC en verwerk één camerascan maar één keer.
|
|
2421
|
+
|
|
2422
|
+
NIET DOEN
|
|
2423
|
+
- Niet eisen dat de oorspronkelijke order_carts-rij nog bestaat om een
|
|
2424
|
+
gedrukte pakbon te herkennen.
|
|
2425
|
+
- Geen eigen query op pakbon_barcode_inhoud, logistics_cart_barcode,
|
|
2426
|
+
order_carts, print_jobs of uuid-fragmenten.
|
|
2427
|
+
- Geen eigen pakbon-, order- of kargegevens samenstellen.
|
|
2428
|
+
- Geen URL's, sleutels, project-refs, klantnamen of apparaat-ID's hardcoden.
|
|
2429
|
+
|
|
2430
|
+
CONTROLELIJST
|
|
2431
|
+
[ ] Een actuele LC-code opent direct de juiste pakbon-/karflow.
|
|
2432
|
+
[ ] Een LC-code van vóór een herindeling wordt als verouderde pakbon herkend,
|
|
2433
|
+
niet als onbekend product.
|
|
2434
|
+
[ ] Pakbonnummer, order(s), klant, Kar X van Y en belading komen uit de Engine.
|
|
2435
|
+
[ ] Een gedeelde kar toont alle gekoppelde orders.
|
|
2436
|
+
[ ] Een dubbele camerascan start geen dubbele controle of afleverbrief.`,
|
|
2437
|
+
},
|
|
2438
|
+
{
|
|
2439
|
+
number: 4,
|
|
2440
|
+
title: "Alleen echte geprinte pakbonnen tonen",
|
|
2441
|
+
date: "2026-09-03",
|
|
2442
|
+
summary: "Vervang demo- en lokale pakbonlijsten door het canonieke overzicht van werkelijk voltooide pakbonprints uit de Engine.",
|
|
2443
|
+
body: `AANVULLING op koppelprompt 1 t/m 3 (die blijven geldig, niets
|
|
2444
|
+
samenvoegen of terugdraaien).
|
|
2445
|
+
|
|
2446
|
+
BEVESTIGD PROBLEEM
|
|
2447
|
+
De zichtbare voorbeeldkaarten kwamen uit oude demodata in scan_pakbonnen. De
|
|
2448
|
+
echte pakbonnen worden bij het printen
|
|
2449
|
+
blijvend geregistreerd in pakbon_barcode_inhoud. De Scanner-module mag daarom
|
|
2450
|
+
geen lokale voorbeeldlijst, seed of directe query op scan_pakbonnen meer gebruiken.
|
|
2451
|
+
|
|
2452
|
+
BOUW DIT
|
|
2453
|
+
- Haal de lijst "Open pakbonnen" uitsluitend op via:
|
|
2454
|
+
|
|
2455
|
+
const { data, error } = await supabase.rpc("scan_open_pakbonnen", {
|
|
2456
|
+
p_dagen: 1,
|
|
2457
|
+
});
|
|
2458
|
+
|
|
2459
|
+
- Bewaak serverdata altijd voordat je erover itereert:
|
|
2460
|
+
|
|
2461
|
+
const openPakbonnen = Array.isArray(data) ? data : [];
|
|
2462
|
+
|
|
2463
|
+
- De RPC levert alleen werkelijk voltooide pakbonprints en restpakbonnen die nog
|
|
2464
|
+
verwerkt moeten worden. Gebruik de velden letterlijk uit het resultaat:
|
|
2465
|
+
barcode, order_number, order_ref, klant_naam, cart_label, cart_index,
|
|
2466
|
+
cart_total, soort, bron en created_at.
|
|
2467
|
+
- Gebruik barcode als duurzame selectie-identiteit. Gebruik NOOIT een zelf
|
|
2468
|
+
verzonnen UUID of een id uit scan_pakbonnen voor een gewone geprinte pakbon.
|
|
2469
|
+
- Start/vervolg de verwerking van een gekozen kaart via dezelfde barcodeflow:
|
|
2470
|
+
|
|
2471
|
+
const { data: toegevoegd } = await supabase.rpc("scan_pakbon_toevoegen", {
|
|
2472
|
+
p_scanner_id: scannerId,
|
|
2473
|
+
p_barcode: pakbon.barcode,
|
|
2474
|
+
p_regels: null,
|
|
2475
|
+
p_medewerker: medewerkerNaam ?? null,
|
|
2476
|
+
});
|
|
2477
|
+
|
|
2478
|
+
Gebruik scan_start_kar(p_pakbon_ids) NIET voor deze kaarten; die oude functie
|
|
2479
|
+
verwacht UUID's uit scan_pakbonnen en hoort niet bij het duurzame contract.
|
|
2480
|
+
- Een klik op een kaart en een camera-/handscan moeten exact dezelfde pakbonflow
|
|
2481
|
+
openen. Een LC-code gaat altijd eerst naar:
|
|
2482
|
+
|
|
2483
|
+
const { data: resolved } = await supabase.rpc("logistics_scan_resolve", {
|
|
2484
|
+
p_code: barcode,
|
|
2485
|
+
});
|
|
2486
|
+
|
|
2487
|
+
- Toon alleen gegevens die de Engine teruggeeft. Als een veld ontbreekt, laat de
|
|
2488
|
+
betreffende regel weg; gebruik geen vaste aantallen of verzonnen buffernaam.
|
|
2489
|
+
- Gebruik voor status, regels, meerdere orders en de beslissing of verwerken is
|
|
2490
|
+
toegestaan uitsluitend het resultaat van logistics_scan_resolve. Bij
|
|
2491
|
+
resolved.stale = true of resolved.processingAllowed = false: toon de pakbon
|
|
2492
|
+
met de waarschuwing van de Engine, maar blokkeer "Volgende" en goedkeuren.
|
|
2493
|
+
- Een gedeelde kar kan meerdere orders bevatten. Toon alle resolved.orders en
|
|
2494
|
+
kies of raad nooit zelf één order.
|
|
2495
|
+
- Na printen, vergrendelen, scannen en afhandelen moet de lijst direct opnieuw
|
|
2496
|
+
worden opgehaald. Een Realtime-subscription mag alleen in useEffect worden
|
|
2497
|
+
gemaakt en moet in de cleanup via supabase.removeChannel(channel) verdwijnen.
|
|
2498
|
+
- Is openPakbonnen leeg, toon dan alleen de lege staat "Geen open pakbonnen".
|
|
2499
|
+
Voeg NOOIT demo-, mock- of fallbackpakbonnen toe.
|
|
2500
|
+
- Blokkeer knoppen tijdens een lopende RPC. Eén barcode, dubbelklik of dubbele
|
|
2501
|
+
cameradetectie mag nooit twee sessies, controles of documenten aanmaken.
|
|
2502
|
+
|
|
2503
|
+
VERWIJDER UIT DE MODULE
|
|
2504
|
+
- Alle arrays, fixtures, voorbeeldorders, voorbeeldklanten en voorbeeldbuffers.
|
|
2505
|
+
- Iedere directe .from("scan_pakbonnen")-query voor de open lijst.
|
|
2506
|
+
- Iedere aanroep van scan_start_kar met ids van kaarten uit scan_open_pakbonnen.
|
|
2507
|
+
- Iedere terugval op voorbeelddata wanneer de database leeg is of een fout geeft.
|
|
2508
|
+
|
|
2509
|
+
FOUTAFHANDELING
|
|
2510
|
+
- Bij een RPC-fout: toon een leesbare fout en een knop "Opnieuw proberen"; toon
|
|
2511
|
+
nooit oude of voorbeelddata als vervanging.
|
|
2512
|
+
- Gebruik voor scannen en verwerken uitsluitend de status, warning, error en
|
|
2513
|
+
errorCode die de Engine teruggeeft.
|
|
2514
|
+
- Hardcodeer geen URL's, sleutels, project-refs, klantnamen, orders, database-ID's
|
|
2515
|
+
of apparaat-ID's.
|
|
2516
|
+
|
|
2517
|
+
CONTROLELIJST
|
|
2518
|
+
[ ] Voorbeeldpakbonnen en voorbeeldorders zijn nergens zichtbaar.
|
|
2519
|
+
[ ] Een nieuw voltooide pakbonprint verschijnt in de lijst.
|
|
2520
|
+
[ ] Een herprint geeft geen dubbele kaart.
|
|
2521
|
+
[ ] Kaartselectie en LC-scan openen dezelfde pakbon.
|
|
2522
|
+
[ ] Pakbonnummer, klant, order(s), Kar X van Y en aantallen komen uit de Engine.
|
|
2523
|
+
[ ] Een afgehandelde kar verdwijnt direct.
|
|
2524
|
+
[ ] Een lege database toont geen demo-fallback.`,
|
|
2525
|
+
},
|
|
2526
|
+
{
|
|
2527
|
+
number: 5,
|
|
2528
|
+
title: "Karnummer per order: cart_seq en cart_number tonen",
|
|
2529
|
+
date: "2026-09-03",
|
|
2530
|
+
summary: "Karnummers komen uit de Engine: toon cart_seq en cart_number, nooit cart_index, en reken zelf niets om.",
|
|
2531
|
+
body: `AANVULLING op de eerdere prompts (die blijven geldig).
|
|
2532
|
+
|
|
2533
|
+
WAT ER VERANDERT
|
|
2534
|
+
De Engine levert vanaf nu per kar een stabiel karnummer. Modules rekenen zelf
|
|
2535
|
+
NIETS meer om en hernummeren niet.
|
|
2536
|
+
|
|
2537
|
+
VELDEN (uit de Engine-RPC's)
|
|
2538
|
+
- cart_seq : stabiel, 1-gebaseerd volgnummer van de kar binnen zijn order.
|
|
2539
|
+
Identiek aan het nummer op de pakbon in de verkoopmodule. Verandert niet als
|
|
2540
|
+
karren op verschillende dagen gepickt of gecontroleerd worden, en niet als een
|
|
2541
|
+
deel van de karren al is afgehandeld.
|
|
2542
|
+
- cart_number : het definitieve karnummer-label (bijv. het toegewezen
|
|
2543
|
+
karnummer uit de karnummering). Toon dit als label.
|
|
2544
|
+
- cart_total : het aantal karren van die order ("Kar X van Y" = cart_seq van
|
|
2545
|
+
cart_total).
|
|
2546
|
+
- cart_index : INTERN. Technische index, niet gedefinieerd als 0- of
|
|
2547
|
+
1-gebaseerd. NOOIT tonen en nooit als basis voor eigen nummering gebruiken.
|
|
2548
|
+
|
|
2549
|
+
WAAR STAAN DE VELDEN
|
|
2550
|
+
control_get_todays_carts(), logistics_pick_agenda(p_from, p_to) (per order in
|
|
2551
|
+
cartList), logistics_cart_index(p_from, p_to), logistics_control_scan_lookup(
|
|
2552
|
+
p_barcode) (cartSeq / cartNumber / cartTotal) en
|
|
2553
|
+
logistics_control_scan_overview(p_scanner_id, p_date).
|
|
2554
|
+
|
|
2555
|
+
GEBRUIK IN DEZE MODULE
|
|
2556
|
+
Zowel de open-pakbonlijst als het scanresultaat tonen het karnummer uit de
|
|
2557
|
+
Engine. Sorteer een order op cart_seq.
|
|
2558
|
+
|
|
2559
|
+
NIET DOEN
|
|
2560
|
+
- Niet zelf nummeren, sorteren op index, of +1 optellen bij cart_index.
|
|
2561
|
+
- Geen aparte nummering per dag, per pickronde of per controlesessie.
|
|
2562
|
+
- Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
|
|
2563
|
+
|
|
2564
|
+
CONTROLELIJST
|
|
2565
|
+
[ ] Elk karnummer in het scherm komt uit cart_seq / cart_number.
|
|
2566
|
+
[ ] "Kar X van Y" gebruikt cart_seq en cart_total.
|
|
2567
|
+
[ ] Een order met 4 karren toont 1 t/m 4, ook als er al karren afgehandeld zijn.
|
|
2568
|
+
[ ] Het getoonde nummer is gelijk aan het nummer op de pakbon.
|
|
2569
|
+
[ ] cart_index komt nergens in de weergave voor.`,
|
|
2570
|
+
},
|
|
1677
2571
|
],
|
|
1678
2572
|
},
|
|
1679
2573
|
voorraad: {
|
|
@@ -1686,11 +2580,11 @@ Bouw:
|
|
|
1686
2580
|
date: "2026-07-24",
|
|
1687
2581
|
summary: "Reserveringstaken uitvoeren en voorraadwijzigingen melden.",
|
|
1688
2582
|
withSharedContract: true,
|
|
1689
|
-
body: `Haal weg: eigen beslissing wanneer er gereserveerd of afgeboekt wordt.
|
|
1690
|
-
|
|
1691
|
-
Bouw:
|
|
1692
|
-
- stock.reserve taken uitvoeren; payload bevat loadCarriers.
|
|
1693
|
-
- Bij relevante voorraadwijziging een gebeurtenis melden met event_type
|
|
2583
|
+
body: `Haal weg: eigen beslissing wanneer er gereserveerd of afgeboekt wordt.
|
|
2584
|
+
|
|
2585
|
+
Bouw:
|
|
2586
|
+
- stock.reserve taken uitvoeren; payload bevat loadCarriers.
|
|
2587
|
+
- Bij relevante voorraadwijziging een gebeurtenis melden met event_type
|
|
1694
2588
|
stock.changed en dezelfde order_ref, zodat de Engine kan herplannen.`,
|
|
1695
2589
|
},
|
|
1696
2590
|
],
|
|
@@ -1705,10 +2599,10 @@ Bouw:
|
|
|
1705
2599
|
date: "2026-07-24",
|
|
1706
2600
|
summary: "Strategie koppelen aan klant en klantgroep.",
|
|
1707
2601
|
withSharedContract: true,
|
|
1708
|
-
body: `Bouw:
|
|
1709
|
-
- Per klant en per klantgroep een koppelveld naar de logistieke strategie
|
|
1710
|
-
(logistics_strategies.id), zodat de Engine weet welke rule config geldt.
|
|
1711
|
-
- Dit veld meegeven als strategy_id bij logistics_emit_event, of beschikbaar
|
|
2602
|
+
body: `Bouw:
|
|
2603
|
+
- Per klant en per klantgroep een koppelveld naar de logistieke strategie
|
|
2604
|
+
(logistics_strategies.id), zodat de Engine weet welke rule config geldt.
|
|
2605
|
+
- Dit veld meegeven als strategy_id bij logistics_emit_event, of beschikbaar
|
|
1712
2606
|
maken zodat de Verkoop-module het kan meegeven.`,
|
|
1713
2607
|
},
|
|
1714
2608
|
],
|
|
@@ -1723,18 +2617,18 @@ Bouw:
|
|
|
1723
2617
|
date: "2026-07-31",
|
|
1724
2618
|
summary: "Eerste koppelprompt: mail alleen omzetten naar order als de Engine dat toestaat.",
|
|
1725
2619
|
withSharedContract: true,
|
|
1726
|
-
body: `Haal weg: eigen aannames over of een bestelling met te weinig voorraad
|
|
1727
|
-
toch mag worden aangemaakt.
|
|
1728
|
-
|
|
1729
|
-
${STOCK_CONTRACT}
|
|
1730
|
-
|
|
1731
|
-
In de Mailbox-module concreet:
|
|
1732
|
-
- Vóór het omzetten van een mail naar een bestelling altijd
|
|
1733
|
-
logistics_check_order_allowed aanroepen met alle orderregels.
|
|
1734
|
-
- allowed = false -> maak de bestelling NIET aan. Zet de mail op status
|
|
1735
|
-
"geblokkeerd - onvoldoende voorraad" en toon per product wanted/available/missing
|
|
1736
|
-
uit check.shortages, zodat een medewerker het handmatig kan oplossen.
|
|
1737
|
-
- allowed = true -> bestelling normaal aanmaken en daarna de gebeurtenis melden
|
|
2620
|
+
body: `Haal weg: eigen aannames over of een bestelling met te weinig voorraad
|
|
2621
|
+
toch mag worden aangemaakt.
|
|
2622
|
+
|
|
2623
|
+
${STOCK_CONTRACT}
|
|
2624
|
+
|
|
2625
|
+
In de Mailbox-module concreet:
|
|
2626
|
+
- Vóór het omzetten van een mail naar een bestelling altijd
|
|
2627
|
+
logistics_check_order_allowed aanroepen met alle orderregels.
|
|
2628
|
+
- allowed = false -> maak de bestelling NIET aan. Zet de mail op status
|
|
2629
|
+
"geblokkeerd - onvoldoende voorraad" en toon per product wanted/available/missing
|
|
2630
|
+
uit check.shortages, zodat een medewerker het handmatig kan oplossen.
|
|
2631
|
+
- allowed = true -> bestelling normaal aanmaken en daarna de gebeurtenis melden
|
|
1738
2632
|
via logistics_emit_event (order.received) met een unieke p_idempotency_key.`,
|
|
1739
2633
|
},
|
|
1740
2634
|
{
|
|
@@ -1742,39 +2636,39 @@ In de Mailbox-module concreet:
|
|
|
1742
2636
|
title: "Bufferbesluit altijd bij de Engine opvragen",
|
|
1743
2637
|
date: "2026-08-02",
|
|
1744
2638
|
summary: "Nieuwe eis bovenop prompt 1: geen eigen bufferlogica; bufferRef komt uit logistics_buffer_decision.",
|
|
1745
|
-
body: `AANVULLING op koppelprompt 1 (die blijft gewoon geldig).
|
|
1746
|
-
|
|
1747
|
-
Haal weg: elke eigen regel of aanname over het samenvoegen van bestellingen uit
|
|
1748
|
-
dezelfde mail, dezelfde afzender of hetzelfde afleveradres.
|
|
1749
|
-
|
|
1750
|
-
Nieuwe verplichting: vraag na de voorraadcontrole, vóór het aanmaken van de
|
|
1751
|
-
bestelling, het bufferbesluit op bij de Engine:
|
|
1752
|
-
|
|
1753
|
-
const { data: besluit } = await supabase.rpc("logistics_buffer_decision", {
|
|
1754
|
-
p_order: {
|
|
1755
|
-
orderRef: "MAIL-12345",
|
|
1756
|
-
checkinAt: "2026-08-03T09:00:00Z",
|
|
1757
|
-
deliveryDate: "2026-08-03",
|
|
1758
|
-
customerRef: "CUST-1",
|
|
1759
|
-
floridayCustomerRef: "FLOR-1",
|
|
1760
|
-
bvoCustomerRef: "BVO-1",
|
|
1761
|
-
deliveryLocationRef: "LOC-1",
|
|
1762
|
-
carrierRef: "TRANS-1",
|
|
1763
|
-
loadCarrierType: "trolley",
|
|
1764
|
-
orderType: "standaard",
|
|
1765
|
-
},
|
|
1766
|
-
p_strategy_id: null,
|
|
1767
|
-
});
|
|
1768
|
-
// besluit = { buffer, reason, bufferRef, bufferKey, matchCriteria,
|
|
1769
|
-
// closeBeforeMinutes, bufferCloseAt, release, trace }
|
|
1770
|
-
|
|
1771
|
-
Regels:
|
|
1772
|
-
- besluit.buffer === false -> bestelling los aanmaken, geen buffer toewijzen.
|
|
1773
|
-
- besluit.buffer === true -> gebruik exact besluit.bufferRef en stuur die mee in de
|
|
1774
|
-
payload van logistics_emit_event.
|
|
1775
|
-
- Ontbrekende velden zorgen ervoor dat de Engine NIET combineert; vul daarom altijd
|
|
1776
|
-
alle bovenstaande velden zo compleet mogelijk uit de mail/klantgegevens.
|
|
1777
|
-
- Toon besluit.reason en besluit.trace in het mailscherm, zodat een medewerker ziet
|
|
2639
|
+
body: `AANVULLING op koppelprompt 1 (die blijft gewoon geldig).
|
|
2640
|
+
|
|
2641
|
+
Haal weg: elke eigen regel of aanname over het samenvoegen van bestellingen uit
|
|
2642
|
+
dezelfde mail, dezelfde afzender of hetzelfde afleveradres.
|
|
2643
|
+
|
|
2644
|
+
Nieuwe verplichting: vraag na de voorraadcontrole, vóór het aanmaken van de
|
|
2645
|
+
bestelling, het bufferbesluit op bij de Engine:
|
|
2646
|
+
|
|
2647
|
+
const { data: besluit } = await supabase.rpc("logistics_buffer_decision", {
|
|
2648
|
+
p_order: {
|
|
2649
|
+
orderRef: "MAIL-12345",
|
|
2650
|
+
checkinAt: "2026-08-03T09:00:00Z",
|
|
2651
|
+
deliveryDate: "2026-08-03",
|
|
2652
|
+
customerRef: "CUST-1",
|
|
2653
|
+
floridayCustomerRef: "FLOR-1",
|
|
2654
|
+
bvoCustomerRef: "BVO-1",
|
|
2655
|
+
deliveryLocationRef: "LOC-1",
|
|
2656
|
+
carrierRef: "TRANS-1",
|
|
2657
|
+
loadCarrierType: "trolley",
|
|
2658
|
+
orderType: "standaard",
|
|
2659
|
+
},
|
|
2660
|
+
p_strategy_id: null,
|
|
2661
|
+
});
|
|
2662
|
+
// besluit = { buffer, reason, bufferRef, bufferKey, matchCriteria,
|
|
2663
|
+
// closeBeforeMinutes, bufferCloseAt, release, trace }
|
|
2664
|
+
|
|
2665
|
+
Regels:
|
|
2666
|
+
- besluit.buffer === false -> bestelling los aanmaken, geen buffer toewijzen.
|
|
2667
|
+
- besluit.buffer === true -> gebruik exact besluit.bufferRef en stuur die mee in de
|
|
2668
|
+
payload van logistics_emit_event.
|
|
2669
|
+
- Ontbrekende velden zorgen ervoor dat de Engine NIET combineert; vul daarom altijd
|
|
2670
|
+
alle bovenstaande velden zo compleet mogelijk uit de mail/klantgegevens.
|
|
2671
|
+
- Toon besluit.reason en besluit.trace in het mailscherm, zodat een medewerker ziet
|
|
1778
2672
|
waarom een bestelling wel of niet is samengevoegd.`,
|
|
1779
2673
|
},
|
|
1780
2674
|
{
|
|
@@ -1782,39 +2676,39 @@ Regels:
|
|
|
1782
2676
|
title: "Alleen ladingdragers gebruiken die de Engine toestaat",
|
|
1783
2677
|
date: "2026-08-03",
|
|
1784
2678
|
summary: "Nieuwe eis bovenop prompt 1 en 2: uitgeschakelde ladingdragers mogen niet meer worden gekozen of ingelezen.",
|
|
1785
|
-
body: `AANVULLING op koppelprompt 1 en 2 (die blijven gewoon geldig).
|
|
1786
|
-
|
|
1787
|
-
In de Rule Engine (stap Beladingindeling) staat welke ladingdragers zijn toegestaan.
|
|
1788
|
-
Staat een ladingdrager uit, dan mag de Mailbox-module die niet meer kiezen of
|
|
1789
|
-
automatisch invullen.
|
|
1790
|
-
|
|
1791
|
-
Haal weg: elke eigen lijst met ladingdragers / verzendmethodes en elke eigen
|
|
1792
|
-
vertaling van tekst uit een mail naar een ladingdrager die niet uit de Engine komt.
|
|
1793
|
-
|
|
1794
|
-
Nieuwe verplichting: haal de lijst op bij de Engine.
|
|
1795
|
-
|
|
1796
|
-
const { data: dragers } = await supabase.rpc("logistics_allowed_load_carriers", {
|
|
1797
|
-
p_strategy_id: null,
|
|
1798
|
-
});
|
|
1799
|
-
// dragers = { allowed: [...], default: "trolley",
|
|
1800
|
-
// carriers: [{ code, label, enabled, isDefault }, ...] }
|
|
1801
|
-
|
|
1802
|
-
Codes en namen (gebruik exact deze codes):
|
|
1803
|
-
trolley Stapelwagen
|
|
1804
|
-
danish_container Deense container
|
|
1805
|
-
euro_rolcontainer Euro-rolcontainer
|
|
1806
|
-
pallet Pallet
|
|
1807
|
-
euro_pallet Euro-pallet
|
|
1808
|
-
loose Geen ladingdrager
|
|
1809
|
-
|
|
1810
|
-
Regels:
|
|
1811
|
-
- In het mailscherm alleen dragers met enabled === true tonen; de rest weglaten.
|
|
1812
|
-
- Herkent de mail een ladingdrager die niet in allowed staat, maak de bestelling dan
|
|
1813
|
-
NIET automatisch aan. Zet de mail op "handmatig controleren - ladingdrager
|
|
1814
|
-
uitgeschakeld" en toon welke drager in de mail stond.
|
|
1815
|
-
- Is er niets herkend, gebruik dan dragers.default.
|
|
1816
|
-
- Stuur loadCarrierType in logistics_check_order_allowed, logistics_buffer_decision
|
|
1817
|
-
en logistics_emit_event altijd met een van bovenstaande codes mee.
|
|
2679
|
+
body: `AANVULLING op koppelprompt 1 en 2 (die blijven gewoon geldig).
|
|
2680
|
+
|
|
2681
|
+
In de Rule Engine (stap Beladingindeling) staat welke ladingdragers zijn toegestaan.
|
|
2682
|
+
Staat een ladingdrager uit, dan mag de Mailbox-module die niet meer kiezen of
|
|
2683
|
+
automatisch invullen.
|
|
2684
|
+
|
|
2685
|
+
Haal weg: elke eigen lijst met ladingdragers / verzendmethodes en elke eigen
|
|
2686
|
+
vertaling van tekst uit een mail naar een ladingdrager die niet uit de Engine komt.
|
|
2687
|
+
|
|
2688
|
+
Nieuwe verplichting: haal de lijst op bij de Engine.
|
|
2689
|
+
|
|
2690
|
+
const { data: dragers } = await supabase.rpc("logistics_allowed_load_carriers", {
|
|
2691
|
+
p_strategy_id: null,
|
|
2692
|
+
});
|
|
2693
|
+
// dragers = { allowed: [...], default: "trolley",
|
|
2694
|
+
// carriers: [{ code, label, enabled, isDefault }, ...] }
|
|
2695
|
+
|
|
2696
|
+
Codes en namen (gebruik exact deze codes):
|
|
2697
|
+
trolley Stapelwagen
|
|
2698
|
+
danish_container Deense container
|
|
2699
|
+
euro_rolcontainer Euro-rolcontainer
|
|
2700
|
+
pallet Pallet
|
|
2701
|
+
euro_pallet Euro-pallet
|
|
2702
|
+
loose Geen ladingdrager
|
|
2703
|
+
|
|
2704
|
+
Regels:
|
|
2705
|
+
- In het mailscherm alleen dragers met enabled === true tonen; de rest weglaten.
|
|
2706
|
+
- Herkent de mail een ladingdrager die niet in allowed staat, maak de bestelling dan
|
|
2707
|
+
NIET automatisch aan. Zet de mail op "handmatig controleren - ladingdrager
|
|
2708
|
+
uitgeschakeld" en toon welke drager in de mail stond.
|
|
2709
|
+
- Is er niets herkend, gebruik dan dragers.default.
|
|
2710
|
+
- Stuur loadCarrierType in logistics_check_order_allowed, logistics_buffer_decision
|
|
2711
|
+
en logistics_emit_event altijd met een van bovenstaande codes mee.
|
|
1818
2712
|
- Cache de lijst niet; de instelling kan op elk moment wijzigen.`,
|
|
1819
2713
|
},
|
|
1820
2714
|
],
|
|
@@ -1829,56 +2723,56 @@ Regels:
|
|
|
1829
2723
|
date: "2026-08-04",
|
|
1830
2724
|
withSharedContract: true,
|
|
1831
2725
|
summary: "Deze module schrijft de dagbezetting weg en toont per dag of de Logistics Engine alle ophaalmomenten haalt.",
|
|
1832
|
-
body: `LEES DIT EERST — hoe je deze prompt uitvoert
|
|
1833
|
-
|
|
1834
|
-
Deze module is de bron van de bezetting. De Logistics Engine rekent daarmee uit
|
|
1835
|
-
of alle karren voor ieder ophaalmoment op tijd gepickt kunnen worden. Je bouwt
|
|
1836
|
-
twee dingen: wegschrijven van de planning, en het tonen van de waarschuwing.
|
|
1837
|
-
Zelf rekenen doe je niet.
|
|
1838
|
-
|
|
1839
|
-
1) Dagbezetting wegschrijven
|
|
1840
|
-
Tabel: public.logistics_staff_planning
|
|
1841
|
-
Kolommen: plan_date (date), staff_count (aantal medewerkers),
|
|
1842
|
-
start_time, end_time (werktijden), source_module, note.
|
|
1843
|
-
Eén rij per dag (uniek op gebruiker + plan_date). Schrijf of update deze rij
|
|
1844
|
-
telkens wanneer de gebruiker de bezetting of de werktijden van een dag
|
|
1845
|
-
wijzigt:
|
|
1846
|
-
|
|
1847
|
-
await supabase.from("logistics_staff_planning").upsert({
|
|
1848
|
-
plan_date: "2026-08-04",
|
|
1849
|
-
staff_count: 7,
|
|
1850
|
-
start_time: "06:00",
|
|
1851
|
-
end_time: "16:00",
|
|
1852
|
-
source_module: "personeelsplanning",
|
|
1853
|
-
}, { onConflict: "user_id,plan_date" })
|
|
1854
|
-
|
|
1855
|
-
2) Direct laten herrekenen
|
|
1856
|
-
Roep na iedere wijziging aan:
|
|
1857
|
-
await supabase.rpc("logistics_capacity_plan_day", { p_date: "2026-08-04" })
|
|
1858
|
-
De Engine berekent dan opnieuw of alle ophaalmomenten haalbaar zijn en
|
|
1859
|
-
verplaatst waar nodig automatisch COMPLETE karren naar een later
|
|
1860
|
-
ophaalmoment. Jij verplaatst zelf nooit karren.
|
|
1861
|
-
|
|
1862
|
-
3) Rode waarschuwing tonen
|
|
1863
|
-
Tabel: public.logistics_capacity_alerts, filter op plan_date en
|
|
1864
|
-
status = 'open'. Toon op de betreffende dag een duidelijk rode melding met:
|
|
1865
|
-
- shortage_minutes → hoeveel capaciteit tekort is (toon in uren + minuten)
|
|
1866
|
-
- pickup_label / pickup_time → welk ophaalmoment niet gehaald wordt
|
|
1867
|
-
- carts_short → hoeveel karren niet op tijd verwerkt kunnen worden
|
|
1868
|
-
- moved_carts → welke karren automatisch zijn doorgeschoven
|
|
1869
|
-
- unplanned_carts → welke karren nog steeds niet ingepland kunnen worden
|
|
1870
|
-
Zijn er geen open rijen, toon dan géén waarschuwing (groen/neutraal).
|
|
1871
|
-
|
|
1872
|
-
4) Ophaalmomenten
|
|
1873
|
-
Tabel public.logistics_pickup_moments bevat per dag de ophaalmomenten
|
|
1874
|
-
(sequence, label, pickup_time). Gebruik die om de waarschuwing per
|
|
1875
|
-
ophaalmoment te tonen. Aanmaken of wijzigen van ophaalmomenten mag alleen
|
|
1876
|
-
als de gebruiker daar in deze module om vraagt; anders alleen lezen.
|
|
1877
|
-
|
|
1878
|
-
5) Wat je NIET doet
|
|
1879
|
-
- Geen eigen capaciteitsberekening of eigen picktijden.
|
|
1880
|
-
- Geen karren splitsen of verplaatsen.
|
|
1881
|
-
- Geen eigen mail sturen bij een tekort; de Engine regelt e-mail en het
|
|
2726
|
+
body: `LEES DIT EERST — hoe je deze prompt uitvoert
|
|
2727
|
+
|
|
2728
|
+
Deze module is de bron van de bezetting. De Logistics Engine rekent daarmee uit
|
|
2729
|
+
of alle karren voor ieder ophaalmoment op tijd gepickt kunnen worden. Je bouwt
|
|
2730
|
+
twee dingen: wegschrijven van de planning, en het tonen van de waarschuwing.
|
|
2731
|
+
Zelf rekenen doe je niet.
|
|
2732
|
+
|
|
2733
|
+
1) Dagbezetting wegschrijven
|
|
2734
|
+
Tabel: public.logistics_staff_planning
|
|
2735
|
+
Kolommen: plan_date (date), staff_count (aantal medewerkers),
|
|
2736
|
+
start_time, end_time (werktijden), source_module, note.
|
|
2737
|
+
Eén rij per dag (uniek op gebruiker + plan_date). Schrijf of update deze rij
|
|
2738
|
+
telkens wanneer de gebruiker de bezetting of de werktijden van een dag
|
|
2739
|
+
wijzigt:
|
|
2740
|
+
|
|
2741
|
+
await supabase.from("logistics_staff_planning").upsert({
|
|
2742
|
+
plan_date: "2026-08-04",
|
|
2743
|
+
staff_count: 7,
|
|
2744
|
+
start_time: "06:00",
|
|
2745
|
+
end_time: "16:00",
|
|
2746
|
+
source_module: "personeelsplanning",
|
|
2747
|
+
}, { onConflict: "user_id,plan_date" })
|
|
2748
|
+
|
|
2749
|
+
2) Direct laten herrekenen
|
|
2750
|
+
Roep na iedere wijziging aan:
|
|
2751
|
+
await supabase.rpc("logistics_capacity_plan_day", { p_date: "2026-08-04" })
|
|
2752
|
+
De Engine berekent dan opnieuw of alle ophaalmomenten haalbaar zijn en
|
|
2753
|
+
verplaatst waar nodig automatisch COMPLETE karren naar een later
|
|
2754
|
+
ophaalmoment. Jij verplaatst zelf nooit karren.
|
|
2755
|
+
|
|
2756
|
+
3) Rode waarschuwing tonen
|
|
2757
|
+
Tabel: public.logistics_capacity_alerts, filter op plan_date en
|
|
2758
|
+
status = 'open'. Toon op de betreffende dag een duidelijk rode melding met:
|
|
2759
|
+
- shortage_minutes → hoeveel capaciteit tekort is (toon in uren + minuten)
|
|
2760
|
+
- pickup_label / pickup_time → welk ophaalmoment niet gehaald wordt
|
|
2761
|
+
- carts_short → hoeveel karren niet op tijd verwerkt kunnen worden
|
|
2762
|
+
- moved_carts → welke karren automatisch zijn doorgeschoven
|
|
2763
|
+
- unplanned_carts → welke karren nog steeds niet ingepland kunnen worden
|
|
2764
|
+
Zijn er geen open rijen, toon dan géén waarschuwing (groen/neutraal).
|
|
2765
|
+
|
|
2766
|
+
4) Ophaalmomenten
|
|
2767
|
+
Tabel public.logistics_pickup_moments bevat per dag de ophaalmomenten
|
|
2768
|
+
(sequence, label, pickup_time). Gebruik die om de waarschuwing per
|
|
2769
|
+
ophaalmoment te tonen. Aanmaken of wijzigen van ophaalmomenten mag alleen
|
|
2770
|
+
als de gebruiker daar in deze module om vraagt; anders alleen lezen.
|
|
2771
|
+
|
|
2772
|
+
5) Wat je NIET doet
|
|
2773
|
+
- Geen eigen capaciteitsberekening of eigen picktijden.
|
|
2774
|
+
- Geen karren splitsen of verplaatsen.
|
|
2775
|
+
- Geen eigen mail sturen bij een tekort; de Engine regelt e-mail en het
|
|
1882
2776
|
Meldingencentrum via de instellingen in de Rule Engine.`,
|
|
1883
2777
|
},
|
|
1884
2778
|
],
|
|
@@ -1893,38 +2787,38 @@ Zelf rekenen doe je niet.
|
|
|
1893
2787
|
date: "2026-09-03",
|
|
1894
2788
|
withSharedContract: true,
|
|
1895
2789
|
summary: "Vaste rolverdeling: de Engine bepaalt documentsoort, variant, layout en printplek; de Layout maker rendert en print.",
|
|
1896
|
-
body: `ROLVERDELING
|
|
1897
|
-
De Logistics Engine beslist WELK document, in WELKE variant, met WELKE layout,
|
|
1898
|
-
op WELKE printplek gedrukt wordt. De Layout maker maakt en rendert de layouts.
|
|
1899
|
-
|
|
1900
|
-
WAT DE ENGINE AANLEVERT
|
|
1901
|
-
Een printopdracht komt binnen als rij in public.print_jobs met status
|
|
1902
|
-
"wachtend". In de payload staan onder meer:
|
|
1903
|
-
|
|
1904
|
-
document_code pakbon | verzendbrief | afleverbrief | veilingbrief | sticker |
|
|
1905
|
-
controlelijst | productiebon
|
|
1906
|
-
layout_id de door de Engine gekozen layout (mag je NIET overrulen)
|
|
1907
|
-
layout_variant "full_cart" of "partial_order" bij een pakbon
|
|
1908
|
-
print_plek_id de plek waar het document uit moet komen
|
|
1909
|
-
is_herprint true bij handmatig opnieuw printen
|
|
1910
|
-
data de gegevens van het document
|
|
1911
|
-
|
|
1912
|
-
BOUW DIT
|
|
1913
|
-
- Neem layout_id, print_plek_id en document_code over zoals ze binnenkomen.
|
|
1914
|
-
- Kun je niet renderen, zet de job dan op "mislukt" met een leesbare
|
|
1915
|
-
Nederlandse foutmelding in het foutveld; verzin geen vervangende layout.
|
|
1916
|
-
- Ontbreekt layout_id, laat de job dan op "wachtend" staan met de melding die de
|
|
1917
|
-
Engine heeft meegegeven; de gebruiker moet de layout in de Rule Engine kiezen.
|
|
1918
|
-
|
|
1919
|
-
NIET DOEN
|
|
1920
|
-
- Nooit zelf de actieve layout pakken als de Engine er één meestuurt.
|
|
1921
|
-
- Nooit zelf een printer of printplek kiezen als print_plek_id gevuld is.
|
|
1922
|
-
- Geen URL's, project-refs, sleutels of klantnamen hardcoden; alles uit env
|
|
1923
|
-
en uit de database.
|
|
1924
|
-
|
|
1925
|
-
CONTROLELIJST
|
|
1926
|
-
[ ] Een job met layout_id gebruikt exact die layout.
|
|
1927
|
-
[ ] Een job zonder layout blijft wachten met een leesbare melding.
|
|
2790
|
+
body: `ROLVERDELING
|
|
2791
|
+
De Logistics Engine beslist WELK document, in WELKE variant, met WELKE layout,
|
|
2792
|
+
op WELKE printplek gedrukt wordt. De Layout maker maakt en rendert de layouts.
|
|
2793
|
+
|
|
2794
|
+
WAT DE ENGINE AANLEVERT
|
|
2795
|
+
Een printopdracht komt binnen als rij in public.print_jobs met status
|
|
2796
|
+
"wachtend". In de payload staan onder meer:
|
|
2797
|
+
|
|
2798
|
+
document_code pakbon | verzendbrief | afleverbrief | veilingbrief | sticker |
|
|
2799
|
+
controlelijst | productiebon
|
|
2800
|
+
layout_id de door de Engine gekozen layout (mag je NIET overrulen)
|
|
2801
|
+
layout_variant "full_cart" of "partial_order" bij een pakbon
|
|
2802
|
+
print_plek_id de plek waar het document uit moet komen
|
|
2803
|
+
is_herprint true bij handmatig opnieuw printen
|
|
2804
|
+
data de gegevens van het document
|
|
2805
|
+
|
|
2806
|
+
BOUW DIT
|
|
2807
|
+
- Neem layout_id, print_plek_id en document_code over zoals ze binnenkomen.
|
|
2808
|
+
- Kun je niet renderen, zet de job dan op "mislukt" met een leesbare
|
|
2809
|
+
Nederlandse foutmelding in het foutveld; verzin geen vervangende layout.
|
|
2810
|
+
- Ontbreekt layout_id, laat de job dan op "wachtend" staan met de melding die de
|
|
2811
|
+
Engine heeft meegegeven; de gebruiker moet de layout in de Rule Engine kiezen.
|
|
2812
|
+
|
|
2813
|
+
NIET DOEN
|
|
2814
|
+
- Nooit zelf de actieve layout pakken als de Engine er één meestuurt.
|
|
2815
|
+
- Nooit zelf een printer of printplek kiezen als print_plek_id gevuld is.
|
|
2816
|
+
- Geen URL's, project-refs, sleutels of klantnamen hardcoden; alles uit env
|
|
2817
|
+
en uit de database.
|
|
2818
|
+
|
|
2819
|
+
CONTROLELIJST
|
|
2820
|
+
[ ] Een job met layout_id gebruikt exact die layout.
|
|
2821
|
+
[ ] Een job zonder layout blijft wachten met een leesbare melding.
|
|
1928
2822
|
[ ] Herprints gebruiken dezelfde layout als de oorspronkelijke print.`,
|
|
1929
2823
|
},
|
|
1930
2824
|
{
|
|
@@ -1932,39 +2826,119 @@ CONTROLELIJST
|
|
|
1932
2826
|
title: "Twee pakbonvarianten en een barcode op de pakbon",
|
|
1933
2827
|
date: "2026-09-03",
|
|
1934
2828
|
summary: "Nieuwe eis bovenop prompt 1: aparte templates voor een volle kar en een deelkar, plus een barcode-element dat de verzendbrief-scan mogelijk maakt.",
|
|
1935
|
-
body: `AANVULLING op prompt 1 (die blijft geldig).
|
|
1936
|
-
|
|
1937
|
-
TWEE PAKBONVARIANTEN
|
|
1938
|
-
De Engine kent twee pakbon-instellingen:
|
|
1939
|
-
"Pakbon volledige kar" → layout_variant "full_cart"
|
|
1940
|
-
"Pakbon resterende order / deelkar" → layout_variant "partial_order"
|
|
1941
|
-
De Engine stuurt de bijbehorende layout_id mee. De Layout maker hoeft alleen te
|
|
1942
|
-
zorgen dat beide layouts als documenttype "pakbon" te kiezen zijn. Toon
|
|
1943
|
-
layout_variant desgewenst in de voorvertoning, maar kies er niets mee.
|
|
1944
|
-
|
|
1945
|
-
BARCODE-ELEMENT OP DE PAKBON
|
|
1946
|
-
Voeg aan de pakbon-template een barcode-element toe waarvan de gebruiker zelf
|
|
1947
|
-
positie, formaat en weergave bepaalt. De waarde komt UIT de printgegevens:
|
|
1948
|
-
|
|
1949
|
-
payload.barcode de vaste barcode van deze kar
|
|
1950
|
-
payload.data.cart.barcode zelfde waarde, in het karblok
|
|
1951
|
-
|
|
1952
|
-
Genereer die waarde nooit zelf en tel er niets bij op: de barcode hoort bij
|
|
1953
|
-
precies één kar van precies één order en blijft gelijk bij een herprint. De
|
|
1954
|
-
verzendbrief wordt later gemaakt door deze barcode te scannen.
|
|
1955
|
-
|
|
1956
|
-
KARGEGEVENS DIE JE KUNT AFDRUKKEN
|
|
1957
|
-
cart_label bijvoorbeeld "Kar 2 van 3"
|
|
1958
|
-
cart_index / cart_total
|
|
1959
|
-
cart_items producten en aantallen VAN DIE KAR
|
|
1960
|
-
cart_id interne identificatie
|
|
1961
|
-
|
|
1962
|
-
CONTROLELIJST
|
|
1963
|
-
[ ] Beide pakbonvarianten zijn als aparte layout aan te maken en te kiezen.
|
|
1964
|
-
[ ] De barcode op de afdruk is scanbaar en gelijk aan payload.barcode.
|
|
1965
|
-
[ ] Een herprint levert dezelfde barcode op.
|
|
2829
|
+
body: `AANVULLING op prompt 1 (die blijft geldig).
|
|
2830
|
+
|
|
2831
|
+
TWEE PAKBONVARIANTEN
|
|
2832
|
+
De Engine kent twee pakbon-instellingen:
|
|
2833
|
+
"Pakbon volledige kar" → layout_variant "full_cart"
|
|
2834
|
+
"Pakbon resterende order / deelkar" → layout_variant "partial_order"
|
|
2835
|
+
De Engine stuurt de bijbehorende layout_id mee. De Layout maker hoeft alleen te
|
|
2836
|
+
zorgen dat beide layouts als documenttype "pakbon" te kiezen zijn. Toon
|
|
2837
|
+
layout_variant desgewenst in de voorvertoning, maar kies er niets mee.
|
|
2838
|
+
|
|
2839
|
+
BARCODE-ELEMENT OP DE PAKBON
|
|
2840
|
+
Voeg aan de pakbon-template een barcode-element toe waarvan de gebruiker zelf
|
|
2841
|
+
positie, formaat en weergave bepaalt. De waarde komt UIT de printgegevens:
|
|
2842
|
+
|
|
2843
|
+
payload.barcode de vaste barcode van deze kar
|
|
2844
|
+
payload.data.cart.barcode zelfde waarde, in het karblok
|
|
2845
|
+
|
|
2846
|
+
Genereer die waarde nooit zelf en tel er niets bij op: de barcode hoort bij
|
|
2847
|
+
precies één kar van precies één order en blijft gelijk bij een herprint. De
|
|
2848
|
+
verzendbrief wordt later gemaakt door deze barcode te scannen.
|
|
2849
|
+
|
|
2850
|
+
KARGEGEVENS DIE JE KUNT AFDRUKKEN
|
|
2851
|
+
cart_label bijvoorbeeld "Kar 2 van 3"
|
|
2852
|
+
cart_index / cart_total
|
|
2853
|
+
cart_items producten en aantallen VAN DIE KAR
|
|
2854
|
+
cart_id interne identificatie
|
|
2855
|
+
|
|
2856
|
+
CONTROLELIJST
|
|
2857
|
+
[ ] Beide pakbonvarianten zijn als aparte layout aan te maken en te kiezen.
|
|
2858
|
+
[ ] De barcode op de afdruk is scanbaar en gelijk aan payload.barcode.
|
|
2859
|
+
[ ] Een herprint levert dezelfde barcode op.
|
|
1966
2860
|
[ ] "Kar X van Y" en de karregels staan op de juiste pakbon.`,
|
|
1967
2861
|
},
|
|
2862
|
+
{
|
|
2863
|
+
number: 3,
|
|
2864
|
+
title: "Eén pakbonlayout: bundelen, barcode en variant horen bij de Layout maker",
|
|
2865
|
+
date: "2026-09-03",
|
|
2866
|
+
summary: "De Engine kiest nog maar één pakbonlayout. Of gelijke karren gebundeld worden, of de barcode zichtbaar is en hoe een volle kar en een deelkar eruitzien, bepaalt de Layout maker binnen die layout.",
|
|
2867
|
+
body: `AANVULLING op prompt 1 en 2 (die blijven geldig, met één correctie).
|
|
2868
|
+
|
|
2869
|
+
WAT ER VERANDERT
|
|
2870
|
+
De Logistiek Engine heeft de dubbele instellingen laten vervallen:
|
|
2871
|
+
- "Gelijke karren op één pakbon" → vervalt in de Engine
|
|
2872
|
+
- "Barcode op de pakbon" (aan/uit) → vervalt in de Engine
|
|
2873
|
+
- "Pakbon resterende order / deelkar" → vervalt als apart layoutveld
|
|
2874
|
+
|
|
2875
|
+
Er is nog één instelling: "Pakbon layout". Die layout_id stuurt de Engine bij
|
|
2876
|
+
elke printopdracht mee.
|
|
2877
|
+
|
|
2878
|
+
WAT DE ENGINE BLIJFT LEVEREN
|
|
2879
|
+
layout_id de gekozen pakbonlayout
|
|
2880
|
+
layout_variant "full_cart" of "partial_order" (per opdracht)
|
|
2881
|
+
payload.barcode en payload.data.cart.barcode (alleen bij pickmethode
|
|
2882
|
+
"kleinste telt"; waarde is vast en blijft gelijk bij herprint)
|
|
2883
|
+
cart_label, cart_index, cart_total, cart_items, cart_id
|
|
2884
|
+
|
|
2885
|
+
WAT DE LAYOUT MAKER BEPAALT
|
|
2886
|
+
- bundelen van identieke karren (optie "bundel_identiek")
|
|
2887
|
+
- of en waar de barcode wordt afgedrukt
|
|
2888
|
+
- hoe een volle kar en een deelkar binnen dezelfde layout worden getoond
|
|
2889
|
+
(pickmethode "beide": full_cart toont de karindeling, partial_order alleen
|
|
2890
|
+
de te verzamelen fusten)
|
|
2891
|
+
|
|
2892
|
+
Blijft een bestaande installatie twee losse layouts gebruiken, dan blijft dat
|
|
2893
|
+
werken: de Engine valt bij een deelkar terug op de enige ingestelde layout.
|
|
2894
|
+
|
|
2895
|
+
CONTROLELIJST
|
|
2896
|
+
[ ] Eén pakbonlayout van de Engine is genoeg voor beide varianten.
|
|
2897
|
+
[ ] De layout bepaalt zelf of gelijke karren gebundeld worden.
|
|
2898
|
+
[ ] De barcode wordt alleen afgedrukt als de layout hem bevat én de opdracht een
|
|
2899
|
+
waarde meestuurt; de Layout maker genereert nooit zelf een waarde.
|
|
2900
|
+
[ ] Ontbreekt layout_variant bij een layout met methode "beide", dan blijft de
|
|
2901
|
+
job wachten met een leesbare melding.`,
|
|
2902
|
+
},
|
|
2903
|
+
{
|
|
2904
|
+
number: 4,
|
|
2905
|
+
title: "Herprint van Engine-pakbonnen altijd via de Engine",
|
|
2906
|
+
date: "2026-09-04",
|
|
2907
|
+
summary: "Voorkomt orderbrede herprints zonder kar-ID: de knop Opnieuw vraagt de Engine om actuele, afzonderlijke karopdrachten.",
|
|
2908
|
+
body: `AANVULLING op prompt 1 t/m 3; voeg deze eis als afzonderlijke wijziging toe.
|
|
2909
|
+
|
|
2910
|
+
PROBLEEM
|
|
2911
|
+
De knop "Opnieuw" in de Printwachtrij kopieert nu rechtstreeks een bestaande
|
|
2912
|
+
rij uit public.print_jobs. Bij een pakbon van de Logistics Engine kan dat een
|
|
2913
|
+
oude orderopdracht zonder cart_id kopiëren. De Layout maker blokkeert die daarna
|
|
2914
|
+
terecht, omdat één barcode nooit voor meerdere karren gebruikt mag worden.
|
|
2915
|
+
|
|
2916
|
+
HERPRINTREGEL
|
|
2917
|
+
Herken een Engine-pickdocument aan payload.queue_item_id in combinatie met
|
|
2918
|
+
payload.source = "pickstation" of payload.data.source = "logistiek-engine".
|
|
2919
|
+
|
|
2920
|
+
- Roep voor zo'n document public.pick_reprint_document aan met:
|
|
2921
|
+
_queue_item_id = payload.queue_item_id
|
|
2922
|
+
_session_id = een unieke waarde voor deze gebruikersactie
|
|
2923
|
+
- Voeg voor dit pad NOOIT rechtstreeks een kopie toe aan public.print_jobs.
|
|
2924
|
+
- De Engine leest de actuele karindeling en maakt per kar precies één job met
|
|
2925
|
+
een eigen cart_id en vaste barcode.
|
|
2926
|
+
- Toon de herprint als geslaagd wanneer de RPC zonder fout afrondt en ververs
|
|
2927
|
+
daarna de wachtrij.
|
|
2928
|
+
- Toon de letterlijke RPC-fout wanneer de order, wachtrijregel of karindeling
|
|
2929
|
+
niet meer bestaat; maak dan geen vervangende orderbrede job.
|
|
2930
|
+
|
|
2931
|
+
NORMALE DOCUMENTEN
|
|
2932
|
+
Alleen documenten zonder Engine queue_item_id mogen de bestaande algemene
|
|
2933
|
+
maakPrintJob-kopieerroute blijven gebruiken.
|
|
2934
|
+
|
|
2935
|
+
CONTROLELIJST
|
|
2936
|
+
[ ] Een Engine-pakbon met twee karren levert na "Opnieuw" twee karjobs op.
|
|
2937
|
+
[ ] Iedere karjob heeft payload.cart_id en een eigen payload.barcode.
|
|
2938
|
+
[ ] Er ontstaat nooit een nieuwe Engine-pakbonjob met cart_id null.
|
|
2939
|
+
[ ] Een oude of vervallen order geeft een leesbare fout en geen lege job.
|
|
2940
|
+
[ ] Geen URL's, sleutels, project-refs, klantnamen of vaste database-id's.`,
|
|
2941
|
+
},
|
|
1968
2942
|
],
|
|
1969
2943
|
},
|
|
1970
2944
|
};
|
|
@@ -1981,16 +2955,16 @@ export const MODULE_PROMPTS = Object.keys(MODULES)
|
|
|
1981
2955
|
export function buildRevisionPrompt(prompt, revision) {
|
|
1982
2956
|
const shared = revision.withSharedContract
|
|
1983
2957
|
? `\n## Gedeeld contract\n\n${sharedBlock(prompt.moduleKey)}\n`
|
|
1984
|
-
: `\n(Deze prompt is een aanvulling. Het gedeelde contract uit koppelprompt 1 blijft
|
|
2958
|
+
: `\n(Deze prompt is een aanvulling. Het gedeelde contract uit koppelprompt 1 blijft
|
|
1985
2959
|
onverkort gelden — niets terugdraaien.)\n`;
|
|
1986
|
-
return `# Koppelprompt ${revision.number} — ${prompt.label}
|
|
1987
|
-
## ${revision.title} (${revision.date})
|
|
1988
|
-
|
|
1989
|
-
${revision.summary}
|
|
1990
|
-
${shared}
|
|
1991
|
-
## Wat deze module moet doen
|
|
1992
|
-
|
|
1993
|
-
${revision.body}
|
|
2960
|
+
return `# Koppelprompt ${revision.number} — ${prompt.label}
|
|
2961
|
+
## ${revision.title} (${revision.date})
|
|
2962
|
+
|
|
2963
|
+
${revision.summary}
|
|
2964
|
+
${shared}
|
|
2965
|
+
## Wat deze module moet doen
|
|
2966
|
+
|
|
2967
|
+
${revision.body}
|
|
1994
2968
|
`;
|
|
1995
2969
|
}
|
|
1996
2970
|
export function buildModulePrompt(prompt) {
|
|
@@ -1998,18 +2972,18 @@ export function buildModulePrompt(prompt) {
|
|
|
1998
2972
|
}
|
|
1999
2973
|
/** Alle modules, met per module de volledige promptgeschiedenis. */
|
|
2000
2974
|
export function buildAllModulePrompts() {
|
|
2001
|
-
const sections = MODULE_PROMPTS.map((p) => `# ${p.order}. ${p.label} (module: ${p.moduleKey})
|
|
2002
|
-
|
|
2003
|
-
${p.summary}
|
|
2004
|
-
|
|
2975
|
+
const sections = MODULE_PROMPTS.map((p) => `# ${p.order}. ${p.label} (module: ${p.moduleKey})
|
|
2976
|
+
|
|
2977
|
+
${p.summary}
|
|
2978
|
+
|
|
2005
2979
|
${p.revisions.map((r) => buildRevisionPrompt(p, r)).join("\n---\n\n")}`).join("\n\n====================\n\n");
|
|
2006
|
-
return `# Koppelprompts voor de aangesloten modules
|
|
2007
|
-
|
|
2008
|
-
Per module staan de prompts op volgorde. Een nieuwe eis komt er altijd als
|
|
2009
|
-
NIEUWE prompt bij; eerdere prompts blijven geldig en worden niet herschreven.
|
|
2010
|
-
Er worden geen secrets gebruikt: alle communicatie loopt via de gedeelde
|
|
2011
|
-
Supabase-database.
|
|
2012
|
-
|
|
2980
|
+
return `# Koppelprompts voor de aangesloten modules
|
|
2981
|
+
|
|
2982
|
+
Per module staan de prompts op volgorde. Een nieuwe eis komt er altijd als
|
|
2983
|
+
NIEUWE prompt bij; eerdere prompts blijven geldig en worden niet herschreven.
|
|
2984
|
+
Er worden geen secrets gebruikt: alle communicatie loopt via de gedeelde
|
|
2985
|
+
Supabase-database.
|
|
2986
|
+
|
|
2013
2987
|
${sections}`;
|
|
2014
2988
|
}
|
|
2015
2989
|
export function modulePromptFilename(moduleKey, revisionNumber) {
|