@flowselections/logistiek-engine 1.0.123 → 1.0.126

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.
@@ -40,6 +40,18 @@ export type CartCarriersResult = {
40
40
  code: string;
41
41
  error: string;
42
42
  };
43
+ /**
44
+ * Groepeert karregels (met geneste `order_carts`) per kar en houdt alleen de
45
+ * regels van de eigen orderregels over. Werkt ook voor een gedeelde bufferkar
46
+ * (order_carts.order_id leeg). Een set is één karregel; die telt als geheel mee.
47
+ */
48
+ export declare function groupOwnCartLines(lines: Array<Record<string, unknown>>, ownItemIds: string[]): Array<{
49
+ id: string;
50
+ cart_number: number | null;
51
+ carrier_type: string | null;
52
+ total_layers_used: number | null;
53
+ order_cart_items: Array<Record<string, unknown>>;
54
+ }>;
43
55
  export declare function buildCartCarriers(carts: CartInput[], requests: DeliveryRequestInput[]): CartCarriersResult;
44
56
  export type FulfillmentDecision = {
45
57
  kind: "klaar";
@@ -1 +1 @@
1
- {"version":3,"file":"floridayCartCarriers.d.ts","sourceRoot":"","sources":["../../src/lib/floridayCartCarriers.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,KAAK,CAAC;QAAE,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC9E;AAED,MAAM,WAAW,oBAAoB;IACnC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,0BAA0B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,wBAAwB,EAAE,MAAM,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,WAAW,EAAE,CAAA;CAAE,GACzC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,EAAE,EAClB,QAAQ,EAAE,oBAAoB,EAAE,GAC/B,kBAAkB,CAuEpB;AAMD,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC;AAElF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,mBAAmB,CA0B5E"}
1
+ {"version":3,"file":"floridayCartCarriers.d.ts","sourceRoot":"","sources":["../../src/lib/floridayCartCarriers.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,38 @@
7
7
  // niet met de delivery-order, dan wordt er niets opgebouwd en komt er een
8
8
  // duidelijke reden terug. Er wordt nooit stil teruggevallen op 0 lagen.
9
9
  // ============================================================================
10
+ /**
11
+ * Groepeert karregels (met geneste `order_carts`) per kar en houdt alleen de
12
+ * regels van de eigen orderregels over. Werkt ook voor een gedeelde bufferkar
13
+ * (order_carts.order_id leeg). Een set is één karregel; die telt als geheel mee.
14
+ */
15
+ export function groupOwnCartLines(lines, ownItemIds) {
16
+ const own = new Set(ownItemIds.map(String));
17
+ const carts = new Map();
18
+ for (const line of Array.isArray(lines) ? lines : []) {
19
+ if (!own.has(String(line["order_item_id"] ?? "")))
20
+ continue;
21
+ const rawCart = line["order_carts"];
22
+ const cart = (Array.isArray(rawCart) ? rawCart[0] : rawCart);
23
+ const id = String(cart?.["id"] ?? line["cart_id"] ?? "");
24
+ if (!id)
25
+ continue;
26
+ let entry = carts.get(id);
27
+ if (!entry) {
28
+ entry = {
29
+ id,
30
+ cart_number: cart?.["cart_number"] ?? null,
31
+ carrier_type: cart?.["carrier_type"] ?? null,
32
+ total_layers_used: cart?.["total_layers_used"] ?? null,
33
+ order_cart_items: [],
34
+ };
35
+ carts.set(id, entry);
36
+ }
37
+ const { order_carts: _skip, ...rest } = line;
38
+ entry.order_cart_items.push(rest);
39
+ }
40
+ return [...carts.values()].sort((a, b) => (a.cart_number ?? 0) - (b.cart_number ?? 0) || a.id.localeCompare(b.id));
41
+ }
10
42
  export function buildCartCarriers(carts, requests) {
11
43
  if (carts.length === 0) {
12
44
  return { ok: false, code: "geen_karindeling", error: "Er is nog geen karindeling voor deze order." };
@@ -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,CAwL1B;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,CAiItB;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"}
@@ -133,20 +133,49 @@ export async function buildFloridayPayload(sb, orderRef) {
133
133
  // Wachttoestand, geen mislukking: de delivery-order kan later binnenkomen.
134
134
  return { ok: false, code: found.code, error: found.error, permanent: false };
135
135
  }
136
- const { data: carts, error: cartsError } = await sb
137
- .from("order_carts")
138
- .select("id, cart_number, carrier_type, total_layers_used, max_layers, occupancy_pct, weight_kg, order_cart_items(product_id, product_name, crates, boxes, plants_per_crate, order_item_id)")
136
+ // Orderregel → Floriday fulfillmentRequest (order_items.source_line_key).
137
+ const { data: orderItems, error: itemsError } = await sb
138
+ .from("order_items")
139
+ .select("id, source_line_key")
139
140
  .eq("order_id", row["id"])
140
- .order("cart_number", { ascending: true });
141
- if (cartsError) {
141
+ // Regels in quarantaine (Verkoop-herstel) gaan niet mee naar Floriday.
142
+ .is("quarantined_at", null);
143
+ if (itemsError) {
142
144
  return {
143
145
  ok: false,
144
- code: "db_error_carts",
145
- error: `Karindeling niet leesbaar: ${cartsError.message}`,
146
+ code: "db_error_order_items",
147
+ error: `Orderregels niet leesbaar: ${itemsError.message}`,
146
148
  permanent: false,
147
149
  };
148
150
  }
149
- const cartRows = (Array.isArray(carts) ? carts : []);
151
+ const requestByItem = new Map();
152
+ const ownItemIds = [];
153
+ for (const it of (Array.isArray(orderItems) ? orderItems : [])) {
154
+ ownItemIds.push(String(it["id"]));
155
+ const key = String(it["source_line_key"] ?? "").trim();
156
+ if (key)
157
+ requestByItem.set(String(it["id"]), key);
158
+ }
159
+ // Karren via de eigen orderregels, niet via order_carts.order_id: een gedeelde
160
+ // bufferkar staat op naam van de buffer. Alleen de eigen regels gaan mee.
161
+ let lineRows = [];
162
+ if (ownItemIds.length > 0) {
163
+ const { data: lines, error: cartsError } = await sb
164
+ .from("order_cart_items")
165
+ .select("cart_id, order_item_id, product_id, product_name, crates, boxes, plants_per_crate, order_carts!inner(id, cart_number, carrier_type, total_layers_used)")
166
+ .in("order_item_id", ownItemIds);
167
+ if (cartsError) {
168
+ return {
169
+ ok: false,
170
+ code: "db_error_carts",
171
+ error: `Karindeling niet leesbaar: ${cartsError.message}`,
172
+ permanent: false,
173
+ };
174
+ }
175
+ lineRows = (Array.isArray(lines) ? lines : []);
176
+ }
177
+ const { groupOwnCartLines } = await import("./floridayCartCarriers.js");
178
+ const cartRows = groupOwnCartLines(lineRows, ownItemIds);
150
179
  const indeling = cartRows.map((cart) => {
151
180
  const items = Array.isArray(cart["order_cart_items"])
152
181
  ? cart["order_cart_items"]
@@ -164,27 +193,6 @@ export async function buildFloridayPayload(sb, orderRef) {
164
193
  .sort((a, b) => String(a.productId).localeCompare(String(b.productId))),
165
194
  };
166
195
  });
167
- // Orderregel → Floriday fulfillmentRequest (order_items.source_line_key).
168
- const { data: orderItems, error: itemsError } = await sb
169
- .from("order_items")
170
- .select("id, source_line_key")
171
- .eq("order_id", row["id"])
172
- // Regels in quarantaine (Verkoop-herstel) gaan niet mee naar Floriday.
173
- .is("quarantined_at", null);
174
- if (itemsError) {
175
- return {
176
- ok: false,
177
- code: "db_error_order_items",
178
- error: `Orderregels niet leesbaar: ${itemsError.message}`,
179
- permanent: false,
180
- };
181
- }
182
- const requestByItem = new Map();
183
- for (const it of (Array.isArray(orderItems) ? orderItems : [])) {
184
- const key = String(it["source_line_key"] ?? "").trim();
185
- if (key)
186
- requestByItem.set(String(it["id"]), key);
187
- }
188
196
  const { buildCartCarriers } = await import("./floridayCartCarriers.js");
189
197
  const carriers = buildCartCarriers(cartRows.map((cart) => ({
190
198
  cartNumber: cart["cart_number"] ?? null,
@@ -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;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"}
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;AAqzJD,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"}
@@ -1917,6 +1917,34 @@ CONTROLELIJST
1917
1917
  [ ] Een order op een gedeelde bufferkar toont "Ingedeeld", niet "geen kar".
1918
1918
  `,
1919
1919
  },
1920
+ {
1921
+ number: 21,
1922
+ title: "Scanbron meesturen bij Controle uitvoeren in bulk",
1923
+ date: "2026-10-13",
1924
+ summary: "Bij \"Controle uitvoeren\" in bulk per kar afmeld_bron = 'bulk' meesturen.",
1925
+ body: `AANVULLING op de eerdere prompts (die blijven geldig).
1926
+
1927
+ WAT ER VERANDERT
1928
+ Afmelden in bulk legt nu ook per kar één goedgekeurde controlescan vast, net als
1929
+ de scanner. Eén definitie van "gecontroleerd": een kar met een goedgekeurde
1930
+ controlescan; elke order met regels op die kar telt als gecontroleerd.
1931
+
1932
+ WAT JE DOET
1933
+ - In de aanroep van control_mark_carts_delivered_detail (of
1934
+ control_mark_carts_delivered) vanuit "Controle uitvoeren" zet je in ELK item
1935
+ van de jsonb-lijst het veld afmeld_bron = 'bulk'.
1936
+ - Toon het resultaat zoals nu; er komt geen nieuw scherm.
1937
+
1938
+ NIET DOEN
1939
+ - Geen eigen telling van "gecontroleerd"; de Engine bepaalt dat.
1940
+ - Geen terugwerkende goedkeuring van oude afmeldingen (zou belading van oude
1941
+ karren naar Floriday in gang zetten).
1942
+ - Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
1943
+
1944
+ CONTROLELIJST
1945
+ [ ] Na bulkcontrole staat in logistics_control_scan bron = 'bulk' voor elke kar.
1946
+ [ ] Een kar die al met de scanner is afgemeld, krijgt geen tweede scan.`,
1947
+ },
1920
1948
  ],
1921
1949
  },
1922
1950
  pickschermen: {
@@ -3574,6 +3602,51 @@ CONTROLELIJST
3574
3602
  [ ] isSet true zonder onderdelen: "onderdelen onbekend", afvinken werkt; isSet false: gewone rij.
3575
3603
  [ ] Typecheck en build:lib geslaagd; meld terug met je pakketversie.`,
3576
3604
  },
3605
+ {
3606
+ number: 42,
3607
+ title: "Gedeelde bufferkar: karplanmelding en verversen bij een vervangen rij",
3608
+ date: "2026-10-13",
3609
+ withSharedContract: false,
3610
+ summary: "pick_report_missing_cart_plan telt gedeelde bufferkarren mee en meldt idempotent; het pickscherm ververst bij een pickrij die niet meer bestaat.",
3611
+ body: `WAAROM
3612
+ Shell-test 13-10 (FO-2601401 t/m -404, één gedeelde kar): het pickscherm hield een
3613
+ verouderde rij vast. pick_queue_cart_plan gaf "Dit document bestaat niet meer" (500)
3614
+ en pick_report_missing_cart_plan gaf 409 (duplicate idempotency key).
3615
+ De Engine heeft de oorzaak aan haar kant hersteld (een gedeelde kar blijft bevroren voor
3616
+ alle orders erop; afmelden geldt voor alle orders op de kar). Deze prompt regelt de
3617
+ kant van Pickschermen.
3618
+
3619
+ 1. pick_report_missing_cart_plan (functie van Pickschermen)
3620
+ - Tel een order als "heeft karplan" als er een kar is met order_id = de order
3621
+ OF een gedeelde kar (order_id leeg, buffer_id gevuld) met een regel van die order:
3622
+ EXISTS (SELECT 1 FROM order_cart_items ci
3623
+ JOIN order_items oi ON oi.id = ci.order_item_id
3624
+ WHERE oi.order_id = ANY(<leden>))
3625
+ Nu telt alleen c.order_id = ANY(<leden>); een gedeelde kar wordt dan ten onrechte
3626
+ als "geen karplan" gemeld.
3627
+ - Maak het aanmaken van de melding idempotent: INSERT ... ON CONFLICT (idempotency_key)
3628
+ DO NOTHING. Nu wordt alleen op open meldingen (processed_at IS NULL) gecontroleerd;
3629
+ bestaat er al een afgehandelde melding met dezelfde sleutel, dan volgt 409.
3630
+ - Beveiliging, search_path en rechten gelijk laten; volledige letterlijke definitie.
3631
+
3632
+ 2. Verversen bij een rij die niet meer bestaat
3633
+ - pick_queue_cart_plan geeft bij een verdwenen rij nu foutcode P0002 met de tekst
3634
+ "Deze pickrij bestaat niet meer (vervangen of afgehandeld); ververs de pickwachtrij."
3635
+ - Vang P0002 (of HTTP 404/500 met die tekst) af: geen rode fout, wel de wachtrij opnieuw
3636
+ laden en de gebruiker de tekst tonen. Een geprinte rij nooit lokaal blijven tonen als
3637
+ hij niet meer in pick_queue staat.
3638
+
3639
+ REGELS
3640
+ - Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code of migraties.
3641
+ - Geen DELETE of UPDATE zonder WHERE.
3642
+ - Test teruggedraaid (safeupdate eerst aantonen), niets printen.
3643
+
3644
+ CONTROLELIJST
3645
+ [ ] Order op een gedeelde kar geeft geen "cartplan.missing"-melding.
3646
+ [ ] Twee keer aanroepen, ook na een afgehandelde melding: geen 409.
3647
+ [ ] Verdwenen rij: wachtrij ververst, duidelijke tekst, geen 500 in beeld.
3648
+ [ ] Meld terug met je pakketversie.`,
3649
+ },
3577
3650
  ],
3578
3651
  },
3579
3652
  scanners: {
@@ -3866,6 +3939,34 @@ CONTROLELIJST
3866
3939
  [ ] Bij scan_only wordt er nergens een printjob aangemaakt.
3867
3940
  [ ] Foutteksten komen letterlijk van de Engine.`,
3868
3941
  },
3942
+ {
3943
+ number: 6,
3944
+ title: "Scanbron meesturen bij afmelden op de controlepost",
3945
+ date: "2026-10-13",
3946
+ summary: "Bij \"Kar afgehandeld bij de Logistiek Engine\" per kar afmeld_bron = 'scanner' meesturen.",
3947
+ body: `AANVULLING op de eerdere prompts (die blijven geldig).
3948
+
3949
+ WAT ER VERANDERT
3950
+ Bij het afmelden legt de Engine per kar één goedgekeurde controlescan vast
3951
+ (logistics_control_scan, approved_at gevuld) met een bron. Zonder bron staat er
3952
+ 'onbekend'. De eindcontrole-scanner moet de bron meesturen.
3953
+
3954
+ WAT JE DOET
3955
+ - In de aanroep van control_mark_carts_delivered_detail (of
3956
+ control_mark_carts_delivered) zet je in ELK item van de jsonb-lijst het veld
3957
+ afmeld_bron = 'scanner'.
3958
+ - Verder verandert er niets aan de aanroep of aan de afhandeling van het antwoord.
3959
+
3960
+ NIET DOEN
3961
+ - Geen eigen telling van "gecontroleerd"; de Engine bepaalt dat (een kar met een
3962
+ goedgekeurde controlescan).
3963
+ - Geen terugwerkende goedkeuring van oude afmeldingen.
3964
+ - Geen URL's, sleutels, project-refs, klantnamen of vaste id's in code.
3965
+
3966
+ CONTROLELIJST
3967
+ [ ] Na een scan staat in logistics_control_scan bron = 'scanner' voor die kar.
3968
+ [ ] Twee keer scannen geeft nog steeds één controlescan.`,
3969
+ },
3869
3970
  ],
3870
3971
  },
3871
3972
  voorraad: {
@@ -1,2 +1,2 @@
1
- export declare const MODULE_VERSION = "1.0.123";
1
+ export declare const MODULE_VERSION = "1.0.126";
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.123";
2
+ export const MODULE_VERSION = "1.0.126";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowselections/logistiek-engine",
3
- "version": "1.0.123",
3
+ "version": "1.0.126",
4
4
  "flowselections": {
5
5
  "moduleId": "logistiek-engine",
6
6
  "pages": [