@flowselections/logistiek-engine 1.0.119 → 1.0.123

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist-lib/components/BeheerPage.d.ts +2 -0
  2. package/dist-lib/components/BeheerPage.d.ts.map +1 -0
  3. package/dist-lib/components/BeheerPage.js +73 -0
  4. package/dist-lib/components/FlowPage.d.ts +1 -0
  5. package/dist-lib/components/FlowPage.d.ts.map +1 -1
  6. package/dist-lib/components/FlowPage.js +7 -1
  7. package/dist-lib/components/LogistiekEnginePage.d.ts.map +1 -1
  8. package/dist-lib/components/LogistiekEnginePage.js +14 -2
  9. package/dist-lib/components/ModulePromptsPage.d.ts +1 -0
  10. package/dist-lib/components/ModulePromptsPage.d.ts.map +1 -1
  11. package/dist-lib/components/ModulePromptsPage.js +7 -1
  12. package/dist-lib/components/RolPoort.d.ts +7 -0
  13. package/dist-lib/components/RolPoort.d.ts.map +1 -0
  14. package/dist-lib/components/RolPoort.js +12 -0
  15. package/dist-lib/components/RuleEnginePage.d.ts +2 -1
  16. package/dist-lib/components/RuleEnginePage.d.ts.map +1 -1
  17. package/dist-lib/components/RuleEnginePage.js +7 -1
  18. package/dist-lib/components/WerkwijzeHerindelingCard.d.ts.map +1 -1
  19. package/dist-lib/components/WerkwijzeHerindelingCard.js +2 -2
  20. package/dist-lib/hooks/useEngineRollen.d.ts +14 -0
  21. package/dist-lib/hooks/useEngineRollen.d.ts.map +1 -0
  22. package/dist-lib/hooks/useEngineRollen.js +50 -0
  23. package/dist-lib/index.d.ts +3 -0
  24. package/dist-lib/index.d.ts.map +1 -1
  25. package/dist-lib/index.js +3 -0
  26. package/dist-lib/integrations/supabase/types.d.ts +476 -3
  27. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  28. package/dist-lib/lib/floridayPush.server.d.ts.map +1 -1
  29. package/dist-lib/lib/floridayPush.server.js +10 -0
  30. package/dist-lib/lib/handlers/logistics-tick.server.js +13 -0
  31. package/dist-lib/lib/modulePrompts.d.ts.map +1 -1
  32. package/dist-lib/lib/modulePrompts.js +162 -0
  33. package/dist-lib/lib/moduleVersion.d.ts +1 -1
  34. package/dist-lib/lib/moduleVersion.js +1 -1
  35. package/dist-lib/lib/shippingNoteQueue.server.d.ts +5 -0
  36. package/dist-lib/lib/shippingNoteQueue.server.d.ts.map +1 -1
  37. package/dist-lib/lib/shippingNoteQueue.server.js +61 -0
  38. package/package.json +6 -1
@@ -1 +1 @@
1
- {"version":3,"file":"floridayPush.server.d.ts","sourceRoot":"","sources":["../../src/lib/floridayPush.server.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAc/C,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUlD;AAaD,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,YAAY,EAAE,OAAO,2BAA2B,EAAE,WAAW,EAAE,CAAC;CACjE;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC;AAUnE;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,cAAc,EAClB,YAAY,EAAE,MAAM,GACnB,OAAO,CACN;IACE,EAAE,EAAE,IAAI,CAAC;IACT,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,cAAc,EAAE,OAAO,2BAA2B,EAAE,oBAAoB,EAAE,CAAC;IAC3E,OAAO,EAAE,MAAM,CAAC;CACjB,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAC7C,CAoEA;AAED,8CAA8C;AAC9C,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CAyHtB;AAQD,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW3F;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG;AA6BD;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,OAAO,GAAG,mBAAmB,GAAG,gBAAgB,CAAC;AAElF,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;CACjB;AAYD,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,eAAe,CAAC,CA+K1B;AAQD,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,SAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAS3F"}
1
+ {"version":3,"file":"floridayPush.server.d.ts","sourceRoot":"","sources":["../../src/lib/floridayPush.server.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAc/C,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUlD;AAaD,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,YAAY,EAAE,OAAO,2BAA2B,EAAE,WAAW,EAAE,CAAC;CACjE;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC;AAUnE;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,cAAc,EAClB,YAAY,EAAE,MAAM,GACnB,OAAO,CACN;IACE,EAAE,EAAE,IAAI,CAAC;IACT,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,cAAc,EAAE,OAAO,2BAA2B,EAAE,oBAAoB,EAAE,CAAC;IAC3E,OAAO,EAAE,MAAM,CAAC;CACjB,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAC7C,CAoEA;AAED,8CAA8C;AAC9C,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CAyHtB;AAQD,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW3F;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG;AA6BD;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,OAAO,GAAG,mBAAmB,GAAG,gBAAgB,CAAC;AAElF,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;CACjB;AAYD,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,eAAe,CAAC,CAwL1B;AAQD,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,SAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAS3F"}
@@ -280,6 +280,16 @@ export async function runFloridayPushQueue(sb, opts = {}) {
280
280
  notApplicable: 0,
281
281
  unknown: 0,
282
282
  };
283
+ // Poort 0: alleen als de Engine de belading verstuurt (instelling
284
+ // belading_verstuurder = engine). Ontbreekt of anders: niets versturen.
285
+ try {
286
+ const { data } = await sb.rpc("logistics_belading_verstuurder");
287
+ if (data !== "engine")
288
+ return out;
289
+ }
290
+ catch {
291
+ return out;
292
+ }
283
293
  // Poort 1: staat de schakelaar uit, dan verwerken we de wachtrij niet.
284
294
  // Fail closed: onleesbaar betekent niet versturen.
285
295
  try {
@@ -139,6 +139,19 @@ async function runTickRound(supabase, tickJob, ident) {
139
139
  try {
140
140
  const { runPlanQueue, prunePlanQueue } = await import("../planQueue.server.js");
141
141
  plan = await runPlanQueue(supabase, { deadlineAt: Date.now() + 15000 });
142
+ // M12: een wek-aanroep kan net vóór de order zichtbaar of vrij is binnenkomen
143
+ // (rij nog vergrendeld door de aanmaakende transactie). Dan kort nawachten
144
+ // in plaats van tot de volgende minuutronde te wachten. Begrensd: max. 3 x.
145
+ for (let poging = 0; poging < 3; poging++) {
146
+ const claimed = Number(plan?.claimed ?? 0);
147
+ if (claimed > 0)
148
+ break;
149
+ const { data: due, error: dueError } = await supabase.rpc("logistics_plan_due_count");
150
+ if (dueError || Number(due ?? 0) === 0)
151
+ break;
152
+ await new Promise((r) => setTimeout(r, 1500));
153
+ plan = await runPlanQueue(supabase, { deadlineAt: Date.now() + 15000 });
154
+ }
142
155
  await prunePlanQueue(supabase);
143
156
  }
144
157
  catch (e) {
@@ -1 +1 @@
1
- {"version":3,"file":"modulePrompts.d.ts","sourceRoot":"","sources":["../../src/lib/modulePrompts.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;CAIvB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,oBAAoB,CAAC;AAKhE,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,eAAe,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,oBAAoB,EAAE,CAAC;CACnC;AAuiJD,eAAO,MAAM,cAAc,EAAE,YAAY,EAUL,CAAC;AAErC,gEAAgE;AAChE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,oBAAoB,GAC7B,MAAM,CAmBR;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAE9D;AAED,oEAAoE;AACpE,wBAAgB,qBAAqB,IAAI,MAAM,CAiB9C;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,eAAe,EAC1B,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,CAIR"}
1
+ {"version":3,"file":"modulePrompts.d.ts","sourceRoot":"","sources":["../../src/lib/modulePrompts.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;CAIvB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,oBAAoB,CAAC;AAKhE,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,eAAe,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,oBAAoB,EAAE,CAAC;CACnC;AA6sJD,eAAO,MAAM,cAAc,EAAE,YAAY,EAUL,CAAC;AAErC,gEAAgE;AAChE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,oBAAoB,GAC7B,MAAM,CAmBR;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAE9D;AAED,oEAAoE;AACpE,wBAAgB,qBAAqB,IAAI,MAAM,CAiB9C;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,eAAe,EAC1B,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,CAIR"}
@@ -905,6 +905,79 @@ CONTROLELIJST
905
905
  [ ] Een order zonder bufferpartners telt nog net zo als voorheen.
906
906
  [ ] "Geen kar" verschijnt alleen als geen actieve regel op een kar ligt.`,
907
907
  },
908
+ {
909
+ number: 20,
910
+ title: "Indelingsstatus per order tonen (Geen indeling)",
911
+ date: "2026-10-12",
912
+ withSharedContract: false,
913
+ summary: "Toon per order de indelingsstatus uit logistics_order_plan_coverage, ook voor orders op een gedeelde bufferkar.",
914
+ body: `WAAROM
915
+ Een order kan op een gedeelde bufferkar staan; de kar hangt dan aan de buffer
916
+ en niet aan de order. Tellen via order_carts.order_id geeft dan ten onrechte
917
+ "geen kar". De Engine levert nu per order één leesfunctie die dit wél goed doet.
918
+
919
+ WAT JE GEBRUIKT
920
+ select public.logistics_order_plan_coverage(<order-id>)
921
+
922
+ Antwoord (jsonb):
923
+ - state: ingedeeld | deels | geen_indeling | geen_regels; label in gewone taal
924
+ ("Ingedeeld", "Deels ingedeeld", "Geen indeling").
925
+ - progressPct en reason.
926
+ - carts[]: cartId, cartNumber, bufferId, shared (gedeelde bufferkar),
927
+ carrierType, lines[] met alleen de regels van DEZE order (orderItemId,
928
+ productId, productName, crates, boxes).
929
+ - pickRows[]: queueItemId, documentNumber, cartId, printedAt, completedAt.
930
+ - pickStatus: geen_pickrij | open | bezig | gepickt; pickedAt bij gepickt.
931
+
932
+ REGELS
933
+ - Alleen voor ingelogde gebruikers (niet anoniem).
934
+ - Lees nooit zelf order_carts of order_cart_items; gebruik deze functie.
935
+ - Velden kunnen ontbreken of leeg zijn: altijd Array.isArray-controle.
936
+ - Geen URL's, sleutels, project-refs, klantnamen of vaste database-id's in code
937
+ of migraties.
938
+
939
+ CONTROLELIJST
940
+ [ ] Verkoop toont per order het label; bij Geen indeling in rood met de reden.
941
+ [ ] Een order op een gedeelde bufferkar toont "Ingedeeld", niet "geen kar".
942
+ `,
943
+ },
944
+ {
945
+ number: 21,
946
+ title: "Indelingsstatus voor een lijst orders in één aanroep",
947
+ date: "2026-10-13",
948
+ withSharedContract: false,
949
+ summary: "Laad de indelingsstatus van een overzicht van orders met één aanroep van logistics_order_plan_coverage_list in plaats van één aanroep per order.",
950
+ body: `WAAROM
951
+ Prompt 20 levert de status per order. Een overzicht van honderden orders met
952
+ honderden losse aanroepen is traag (gemeten: 90 orders los ruim 15 seconden).
953
+ De lijstversie geeft dezelfde status voor maximaal 1.000 orders in één aanroep
954
+ (gemeten: 500 order-id's in circa 0,3 seconde).
955
+
956
+ WAT JE GEBRUIKT
957
+ supabase.rpc('logistics_order_plan_coverage_list', { p_order_ids: [<order-id>, ...] })
958
+
959
+ Antwoord: één rij per gevraagde order:
960
+ - order_id, order_number, buffer_id
961
+ - state: ingedeeld | deels | geen_indeling | geen_regels | onbekend
962
+ - label ("Ingedeeld", "Deels ingedeeld", "Geen indeling", "Geen regels", "Onbekend")
963
+ - progress_pct, reason (gewone taal, leeg bij Ingedeeld)
964
+ - cart_count, pick_row_count
965
+ - pick_status: geen_pickrij | open | bezig | gepickt; picked_at bij gepickt
966
+ Geen karren of regels; die haal je bij het openen van één order met prompt 20.
967
+
968
+ REGELS
969
+ - Alleen voor ingelogde gebruikers (niet anoniem).
970
+ - Maximaal 1.000 order-id's per aanroep; meer geeft een foutmelding. Splits in
971
+ stukken van hooguit 1.000.
972
+ - Altijd Array.isArray-controle op het antwoord.
973
+ - Geen URL's, sleutels, project-refs, klantnamen of vaste database-id's in code.
974
+
975
+ CONTROLELIJST
976
+ [ ] Het orderoverzicht doet één aanroep per (stuk van) 1.000 orders.
977
+ [ ] Labels en status gelijk aan prompt 20 voor dezelfde order.
978
+ [ ] Geen indeling in rood met de reden.
979
+ `,
980
+ },
908
981
  ],
909
982
  },
910
983
  afhandeling: {
@@ -1808,6 +1881,42 @@ CONTROLELIJST
1808
1881
  [ ] Een losgekoppelde order staat als aparte regel met eigen karren in de agenda's.
1809
1882
  [ ] Afgehandelde karren houden hun nummer en blijven zichtbaar in de historie.`,
1810
1883
  },
1884
+ {
1885
+ number: 20,
1886
+ title: "Karren, regels en pickstatus per order voor belading",
1887
+ date: "2026-10-12",
1888
+ withSharedContract: false,
1889
+ summary: "Gebruik logistics_order_plan_coverage voor karren, eigen regels, pickrij en gepickt-tijdstip per order (ook in een buffer).",
1890
+ body: `WAAROM
1891
+ Een order kan op een gedeelde bufferkar staan; de kar hangt dan aan de buffer
1892
+ en niet aan de order. Tellen via order_carts.order_id geeft dan ten onrechte
1893
+ "geen kar". De Engine levert nu per order één leesfunctie die dit wél goed doet.
1894
+
1895
+ WAT JE GEBRUIKT
1896
+ select public.logistics_order_plan_coverage(<order-id>)
1897
+
1898
+ Antwoord (jsonb):
1899
+ - state: ingedeeld | deels | geen_indeling | geen_regels; label in gewone taal
1900
+ ("Ingedeeld", "Deels ingedeeld", "Geen indeling").
1901
+ - progressPct en reason.
1902
+ - carts[]: cartId, cartNumber, bufferId, shared (gedeelde bufferkar),
1903
+ carrierType, lines[] met alleen de regels van DEZE order (orderItemId,
1904
+ productId, productName, crates, boxes).
1905
+ - pickRows[]: queueItemId, documentNumber, cartId, printedAt, completedAt.
1906
+ - pickStatus: geen_pickrij | open | bezig | gepickt; pickedAt bij gepickt.
1907
+
1908
+ REGELS
1909
+ - Alleen voor ingelogde gebruikers (niet anoniem).
1910
+ - Lees nooit zelf order_carts of order_cart_items; gebruik deze functie.
1911
+ - Velden kunnen ontbreken of leeg zijn: altijd Array.isArray-controle.
1912
+ - Geen URL's, sleutels, project-refs, klantnamen of vaste database-id's in code
1913
+ of migraties.
1914
+
1915
+ CONTROLELIJST
1916
+ [ ] Belading per verkooporder gebruikt carts[].lines van deze order, ook in een buffer.
1917
+ [ ] Een order op een gedeelde bufferkar toont "Ingedeeld", niet "geen kar".
1918
+ `,
1919
+ },
1811
1920
  ],
1812
1921
  },
1813
1922
  pickschermen: {
@@ -4511,6 +4620,59 @@ CONTROLELIJST
4511
4620
  [ ] Een samengevoegde order wordt nooit opnieuw aangemaakt of bijgewerkt.
4512
4621
  [ ] Elke Floriday-order houdt zijn eigen floriday_sales_order_id.`,
4513
4622
  },
4623
+ {
4624
+ number: 3,
4625
+ title: "Shell-adres vastleggen in module_runtime_config.shell_base_url",
4626
+ date: "2026-10-12",
4627
+ withSharedContract: false,
4628
+ summary: "Leg per omgeving het adres van de eigen Shell vast in shell_base_url, zodat de minuutronde van de Logistiek Engine de planner in de Shell aanroept in plaats van een losse modulesite.",
4629
+ body: `WAAROM
4630
+ De minuutronde van de Logistiek Engine roept elke minuut de planner aan. Welk
4631
+ adres daarvoor wordt gebruikt, staat in module_runtime_config onder
4632
+ logistics_tick_base_url. Die sleutel wijst nu naar de losse site van de
4633
+ Engine-module, en niet naar de Shell. Daardoor plant een oudere Engine-versie
4634
+ dan de versie die in de Shell is geïnstalleerd.
4635
+ De Engine stapt zelf over naar de Shell. Daarvoor heeft hij het adres van de
4636
+ Shell nodig in de sleutel shell_base_url, en die is nooit gevuld. Elk uur meldt
4637
+ de controle "shell_adres_onbekend". Deze koppelmodule is eigenaar van
4638
+ shell_base_url, want het adres komt uit Central Auth.
4639
+
4640
+ WAT JE BOUWT
4641
+ Schrijf bij het starten van de Shell, en bij elke wijziging van het adres in
4642
+ Central Auth, het publieke basisadres van de eigen Shell weg:
4643
+
4644
+ insert into public.module_runtime_config (key, value)
4645
+ values ('shell_base_url', <adres uit Central Auth>)
4646
+ on conflict (key) do update set value = excluded.value;
4647
+
4648
+ Eisen aan de waarde:
4649
+ - Het volledige https-basisadres van de gepubliceerde Shell van deze omgeving:
4650
+ alleen schema en host, zonder pad, zonder afsluitende schuine streep en
4651
+ zonder querystring.
4652
+ - Altijd de Shell van de eigen omgeving, nooit die van een andere klant.
4653
+
4654
+ REGELS
4655
+ - De waarde komt tijdens het draaien uit Central Auth of uit de omgeving. Een
4656
+ vast adres in code, in een migratie of in een INSERT die via de schemasync
4657
+ meereist, mag niet. Elke klant heeft een eigen Shell en een eigen database.
4658
+ - Is het adres onbekend of ongeldig, dan niets wegschrijven (fail closed) en
4659
+ dat melden. Schrijf nooit een standaard- of voorbeeldadres weg.
4660
+ - Raak logistics_tick_base_url, logistics_tick_apikey en logistics_tick_path
4661
+ niet aan. Die beheert de Engine.
4662
+ - De Engine stapt pas over als zowel de testroute als de echte route van de
4663
+ Shell antwoordt met engine = "logistiek-engine". Een onjuist adres doet dus
4664
+ niets, maar levert een melding op.
4665
+ - Geen URL's, sleutels, project-refs, klantnamen of vaste database-id's in code
4666
+ of migraties.
4667
+
4668
+ CONTROLELIJST
4669
+ [ ] shell_base_url bevat na het starten het https-basisadres van de eigen Shell,
4670
+ zonder pad en zonder afsluitende schuine streep.
4671
+ [ ] Er staat nergens een vast adres in code of migraties.
4672
+ [ ] Bij een onbekend adres wordt er niets weggeschreven, en dat wordt gemeld.
4673
+ [ ] Binnen een uur staat in logistics_base_url_checks een regel met status
4674
+ "geslaagd". Daarna toont de minuutronde de Engine-versie uit de Shell.`,
4675
+ },
4514
4676
  ],
4515
4677
  },
4516
4678
  };
@@ -1,2 +1,2 @@
1
- export declare const MODULE_VERSION = "1.0.119";
1
+ export declare const MODULE_VERSION = "1.0.123";
2
2
  //# sourceMappingURL=moduleVersion.d.ts.map
@@ -1,2 +1,2 @@
1
1
  // Automatisch gegenereerd door prebuild:lib; niet handmatig aanpassen.
2
- export const MODULE_VERSION = "1.0.119";
2
+ export const MODULE_VERSION = "1.0.123";
@@ -15,4 +15,9 @@ export interface ShippingNoteRun {
15
15
  export declare function runShippingNoteQueue(sb: SupabaseClient, options?: {
16
16
  limit?: number;
17
17
  }): Promise<ShippingNoteRun>;
18
+ export type BeladingVerstuurder = "engine" | "afhandeling" | null;
19
+ /** Leest module_runtime_config.belading_verstuurder. Onleesbaar of ongeldig = null (fail closed). */
20
+ export declare function leesBeladingVerstuurder(sb: SupabaseClient): Promise<BeladingVerstuurder>;
21
+ export declare function parseBeladingVerstuurder(value: unknown): BeladingVerstuurder;
22
+ export declare function beladingWachtReden(verstuurder: BeladingVerstuurder): string;
18
23
  //# sourceMappingURL=shippingNoteQueue.server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shippingNoteQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/shippingNoteQueue.server.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAO5D,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAoCD,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CAiZ1B"}
1
+ {"version":3,"file":"shippingNoteQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/shippingNoteQueue.server.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAO5D,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAoCD,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CA2b1B;AAMD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,aAAa,GAAG,IAAI,CAAC;AAElE,qGAAqG;AACrG,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAQ9F;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAG5E;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,mBAAmB,GAAG,MAAM,CAI3E"}
@@ -123,6 +123,20 @@ export async function runShippingNoteQueue(sb, options = {}) {
123
123
  nextStep: "Gaat vanzelf verder na een goedgekeurde controlescan met de poort open",
124
124
  });
125
125
  };
126
+ // Belading is (nog) niet door Afhandeling verstuurd: wachten zonder poging.
127
+ const houdVastBelading = async (reden) => {
128
+ await sb.rpc("logistics_slip_note_hold_belading", { _id: row.id, _reason: reden });
129
+ run.waiting++;
130
+ await trace(sb, {
131
+ ...basis,
132
+ step: "Wacht op belading door Afhandeling",
133
+ status: "wachtend",
134
+ decision: "wacht_op_belading",
135
+ reason: reden,
136
+ rule: "De Engine verstuurt geen belading; Afhandeling doet dat (instelling belading_verstuurder)",
137
+ nextStep: "Over 2 minuten opnieuw kijken of Floriday de verzendbrief heeft",
138
+ });
139
+ };
126
140
  const wacht = async (reden, klasse) => {
127
141
  const code = definitieveFout(reden);
128
142
  if (code) {
@@ -196,7 +210,28 @@ export async function runShippingNoteQueue(sb, options = {}) {
196
210
  // al een fulfillment-order voor deze pakbon, dan wordt er geen tweede
197
211
  // aangemaakt.
198
212
  let bestaandeFo = String(row.fulfillment_order_id ?? "").trim() || null;
213
+ // Wie verstuurt de belading (fulfillment-order)? Alleen bij 'engine' doet
214
+ // de Engine stap 1. Ontbreekt of ongeldig: fail closed, niets versturen.
215
+ let wachtOpBelading = null;
199
216
  if (!bestaandeFo) {
217
+ const verstuurder = await leesBeladingVerstuurder(sb);
218
+ if (verstuurder !== "engine") {
219
+ wachtOpBelading = beladingWachtReden(verstuurder);
220
+ }
221
+ }
222
+ if (!bestaandeFo && wachtOpBelading) {
223
+ // Goedgekeurde controlescan blijft vereist (ook Floriday-authenticatie eist hem).
224
+ const { data: goedgekeurd } = await sb.rpc("logistics_floriday_order_approved", {
225
+ _order_ref: row.order_number,
226
+ });
227
+ if (goedgekeurd !== true) {
228
+ await houdVast("Wacht op een goedgekeurde controlescan; daarna verstuurt Afhandeling de belading.");
229
+ continue;
230
+ }
231
+ // Geen stap 1 en geen stap 2 zonder fulfillment-order: door naar stap 3
232
+ // (alleen lezen). Is de verzendbrief er nog niet, dan wachten zonder poging.
233
+ }
234
+ else if (!bestaandeFo) {
200
235
  // Pas ná een goedgekeurde controlescan laten aanmaken.
201
236
  const { data: goedgekeurd, error: goedError } = await sb.rpc("logistics_floriday_order_approved", {
202
237
  _order_ref: row.order_number,
@@ -290,6 +325,11 @@ export async function runShippingNoteQueue(sb, options = {}) {
290
325
  if (!doc["ok"]) {
291
326
  const message = String(doc["error"] ?? "") ||
292
327
  "Wachten op officiële Floriday-afleverbrief: Floriday heeft het document nog niet aangemaakt.";
328
+ if (wachtOpBelading) {
329
+ // Belading is van Afhandeling: wachten verbruikt geen pogingen.
330
+ await houdVastBelading(`${wachtOpBelading} Laatste antwoord van Floriday: ${message}`);
331
+ continue;
332
+ }
293
333
  await wacht(message, classifyFloridayReason(message));
294
334
  continue;
295
335
  }
@@ -378,3 +418,24 @@ export async function runShippingNoteQueue(sb, options = {}) {
378
418
  }
379
419
  return run;
380
420
  }
421
+ /** Leest module_runtime_config.belading_verstuurder. Onleesbaar of ongeldig = null (fail closed). */
422
+ export async function leesBeladingVerstuurder(sb) {
423
+ try {
424
+ const { data, error } = await sb.rpc("logistics_belading_verstuurder");
425
+ if (error)
426
+ return null;
427
+ return parseBeladingVerstuurder(data);
428
+ }
429
+ catch {
430
+ return null;
431
+ }
432
+ }
433
+ export function parseBeladingVerstuurder(value) {
434
+ const v = typeof value === "string" ? value.trim().toLowerCase() : "";
435
+ return v === "engine" || v === "afhandeling" ? v : null;
436
+ }
437
+ export function beladingWachtReden(verstuurder) {
438
+ return verstuurder === "afhandeling"
439
+ ? "Wacht op belading door Afhandeling."
440
+ : "De instelling belading_verstuurder ontbreekt of is ongeldig; de Engine verstuurt geen belading.";
441
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowselections/logistiek-engine",
3
- "version": "1.0.119",
3
+ "version": "1.0.123",
4
4
  "flowselections": {
5
5
  "moduleId": "logistiek-engine",
6
6
  "pages": [
@@ -47,6 +47,11 @@
47
47
  "export": "PlanWachtrijPage",
48
48
  "route": "logistiek-engine/wachtrij",
49
49
  "title": "Wachtrij"
50
+ },
51
+ {
52
+ "export": "BeheerPage",
53
+ "route": "logistiek-engine/beheer",
54
+ "title": "Beheer"
50
55
  }
51
56
  ],
52
57
  "serverRoutes": [