@flowselections/floriday-authenticatie-module 1.0.62 → 1.0.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/integrations/supabase/types.d.ts +331 -3
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/floriday-auto-process.server.d.ts.map +1 -1
- package/dist-lib/lib/floriday-auto-process.server.js +12 -64
- package/dist-lib/lib/floriday-cart-approval.server.d.ts.map +1 -1
- package/dist-lib/lib/floriday-cart-approval.server.js +30 -16
- package/dist-lib/lib/floriday-order-stage.d.ts +31 -0
- package/dist-lib/lib/floriday-order-stage.d.ts.map +1 -0
- package/dist-lib/lib/floriday-order-stage.js +77 -0
- package/dist-lib/lib/floriday-sync.functions.d.ts +1 -0
- package/dist-lib/lib/floriday-sync.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-sync.functions.js +32 -1
- package/dist-lib/lib/gateway/fulfillment-order-body.d.ts +2 -0
- package/dist-lib/lib/gateway/fulfillment-order-body.d.ts.map +1 -1
- package/dist-lib/lib/gateway/fulfillment-order-body.js +6 -1
- package/dist-lib/lib/gateway/fulfillment-order-send.d.ts.map +1 -1
- package/dist-lib/lib/gateway/fulfillment-order-send.js +57 -4
- package/dist-lib/lib/gateway/fulfillment-order-status.d.ts +10 -0
- package/dist-lib/lib/gateway/fulfillment-order-status.d.ts.map +1 -1
- package/dist-lib/lib/gateway/fulfillment-order-status.js +107 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floriday-auto-process.server.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-auto-process.server.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAC;AAKjC,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,oBAAoB,GACpB,4BAA4B,GAC5B,qBAAqB,GACrB,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,iBAAiB,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAsHD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE;IACL,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,mBAAmB,CAAC;CACnC,GACA,OAAO,CAAC,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"floriday-auto-process.server.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-auto-process.server.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAC;AAKjC,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,oBAAoB,GACpB,4BAA4B,GAC5B,qBAAqB,GACrB,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,iBAAiB,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAsHD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE;IACL,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,mBAAmB,CAAC;CACnC,GACA,OAAO,CAAC,kBAAkB,CAAC,CAkI7B;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B,CAAC,CA4ED"}
|
|
@@ -198,74 +198,22 @@ export async function runAutoProcess(supabase, input) {
|
|
|
198
198
|
reason: "auto_process_paused",
|
|
199
199
|
};
|
|
200
200
|
}
|
|
201
|
-
// ─
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
deliveryOrderId,
|
|
211
|
-
fulfillmentRequestIds: requestIds,
|
|
212
|
-
}, "auto-process");
|
|
213
|
-
const payload = sent.payload ?? {};
|
|
214
|
-
// Karren nog niet gecontroleerd → niet versturen, zichtbaar loggen, later opnieuw.
|
|
215
|
-
if (payload.code === "carts_not_controlled") {
|
|
216
|
-
const reason = payload.error ?? "Karren nog niet gecontroleerd door de logistiek-engine";
|
|
217
|
-
await logPhase(supabase, conn.id, salesOrderId, "waiting", {
|
|
218
|
-
code: "carts_not_controlled",
|
|
219
|
-
reason,
|
|
220
|
-
});
|
|
221
|
-
return {
|
|
222
|
-
ok: true,
|
|
223
|
-
status: "waiting",
|
|
224
|
-
salesOrderId,
|
|
225
|
-
deliveryOrderId,
|
|
226
|
-
code: "carts_not_controlled",
|
|
227
|
-
reason,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
if (payload.ok && payload.code === "already_fulfilled") {
|
|
231
|
-
await logPhase(supabase, conn.id, salesOrderId, "done", {
|
|
232
|
-
code: "already_fulfilled",
|
|
233
|
-
source: payload.source,
|
|
234
|
-
fulfillmentOrderId: payload.fulfillmentOrderId,
|
|
235
|
-
});
|
|
236
|
-
return {
|
|
237
|
-
ok: true,
|
|
238
|
-
status: "done",
|
|
239
|
-
salesOrderId,
|
|
240
|
-
deliveryOrderId,
|
|
241
|
-
code: "already_fulfilled",
|
|
242
|
-
reason: "already_fulfilled_at_floriday",
|
|
243
|
-
fulfillmentOrderId: payload.fulfillmentOrderId,
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
if (!payload.ok) {
|
|
247
|
-
const error = payload.error ?? "Versturen fulfillment-order mislukt";
|
|
248
|
-
await logPhase(supabase, conn.id, salesOrderId, "error", {
|
|
249
|
-
code: payload.code,
|
|
250
|
-
error,
|
|
251
|
-
});
|
|
252
|
-
return {
|
|
253
|
-
ok: false,
|
|
254
|
-
status: "error",
|
|
255
|
-
salesOrderId,
|
|
256
|
-
deliveryOrderId,
|
|
257
|
-
code: payload.code,
|
|
258
|
-
error,
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
const fulfillmentOrderId = payload.fulfillmentOrderId;
|
|
262
|
-
await logPhase(supabase, conn.id, salesOrderId, "done", { fulfillmentOrderId });
|
|
201
|
+
// ─ Klaar voor belading (1.0.64) ──────────────────────────────────────────
|
|
202
|
+
// auto-process verstuurt NOOIT zelf belading en neemt niets aan bij Floriday
|
|
203
|
+
// (Floriday zet de order zelf op COMMITTED). De belading komt uitsluitend van
|
|
204
|
+
// Afhandeling via fulfillment-order/send met karren (indeling van de Engine).
|
|
205
|
+
const reason = "Klaar voor belading; belading volgt via Afhandeling (fulfillment-order/send).";
|
|
206
|
+
await logPhase(supabase, conn.id, salesOrderId, "waiting", {
|
|
207
|
+
code: "waiting_for_afhandeling",
|
|
208
|
+
reason,
|
|
209
|
+
});
|
|
263
210
|
return {
|
|
264
211
|
ok: true,
|
|
265
|
-
status: "
|
|
212
|
+
status: "waiting",
|
|
266
213
|
salesOrderId,
|
|
267
214
|
deliveryOrderId,
|
|
268
|
-
|
|
215
|
+
code: "waiting_for_afhandeling",
|
|
216
|
+
reason,
|
|
269
217
|
};
|
|
270
218
|
}
|
|
271
219
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floriday-cart-approval.server.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-cart-approval.server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"floriday-cart-approval.server.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-cart-approval.server.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GACxB,YAAY,GACZ,qBAAqB,GACrB,kBAAkB,GAClB,qBAAqB,CAAC;AAE1B,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,gBAAgB,CAAC;IACvB,0DAA0D;IAC1D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mDAAmD;IACnD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,oEAAoE;IACpE,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAClE;AA4FD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE;IACL,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,OAAO,CAAC,oBAAoB,CAAC,CAmF/B"}
|
|
@@ -11,11 +11,13 @@
|
|
|
11
11
|
//
|
|
12
12
|
// `_order_ref` is het ordernummer (public.orders.order_number).
|
|
13
13
|
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
14
|
+
// Wat telt als "gecontroleerd": elke kar van de order (public.order_carts,
|
|
15
|
+
// ook gedeelde karren via order_cart_items) heeft een afgemelde scan aan de
|
|
16
|
+
// controlebalie: public.logistics_control_scan.approved_at IS NOT NULL.
|
|
17
|
+
//
|
|
18
|
+
// Altijd fail closed (sinds 1.0.64): ontbreekt de controle in de Shell, is
|
|
19
|
+
// hij onleesbaar of zijn niet alle karren afgemeld, dan gaat er niets naar
|
|
20
|
+
// Floriday.
|
|
19
21
|
// ============================================================================
|
|
20
22
|
const ALLOWED = {
|
|
21
23
|
allowed: true,
|
|
@@ -94,22 +96,34 @@ export async function checkCartApproval(supabase, input) {
|
|
|
94
96
|
if (salesOrderIds.length === 0 && deliveryOrderId) {
|
|
95
97
|
salesOrderIds = await salesOrderIdsForDeliveryOrder(supabase, input.connectionId, deliveryOrderId);
|
|
96
98
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
// Fail closed (1.0.64): zonder controle gaat er niets naar Floriday.
|
|
100
|
+
const unavailable = async (reason, refs = []) => {
|
|
101
|
+
await logRefusal(supabase, refs[0] ?? null, reason, module);
|
|
102
|
+
return { allowed: false, code: "geen_karrencontrole", reason, orderRefs: refs, details: [] };
|
|
103
|
+
};
|
|
104
|
+
if (salesOrderIds.length === 0) {
|
|
105
|
+
return unavailable("Geen verkooporder bij deze afleveropdracht gevonden; karrencontrole niet mogelijk.");
|
|
106
|
+
}
|
|
99
107
|
const { refs, missingModule } = await orderRefsForSalesOrders(supabase, salesOrderIds);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
if (missingModule) {
|
|
109
|
+
return unavailable("Geen karrencontrole in deze Shell (orders/controlescan ontbreekt); er wordt niet verstuurd.");
|
|
110
|
+
}
|
|
111
|
+
if (refs.length === 0) {
|
|
112
|
+
return {
|
|
113
|
+
allowed: false,
|
|
114
|
+
code: "niet_goedgekeurd",
|
|
115
|
+
reason: "Order nog niet bekend in Afhandeling; er zijn nog geen karren ingedeeld of afgemeld.",
|
|
116
|
+
orderRefs: [],
|
|
117
|
+
details: [],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
106
120
|
const details = [];
|
|
107
121
|
for (const orderRef of refs) {
|
|
108
122
|
const { data, error } = await supabase.rpc("logistics_order_cart_approval", { _order_ref: orderRef });
|
|
109
123
|
if (error) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
124
|
+
if (isMissingObject(error)) {
|
|
125
|
+
return unavailable("Karrencontrole-functie ontbreekt in deze Shell; er wordt niet verstuurd.", refs);
|
|
126
|
+
}
|
|
113
127
|
const reason = "De karrencontrole kan niet gelezen worden; er wordt geen fulfillment-order naar Floriday gestuurd.";
|
|
114
128
|
await logRefusal(supabase, orderRef, reason, module);
|
|
115
129
|
return {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type FloridayStage = "open" | "fulfilled" | "cancelled" | "expired" | "unknown";
|
|
2
|
+
export declare function deriveFloridayStage(salesOrderStatus: string | null | undefined, fulfillmentStatuses: Array<string | null | undefined>): FloridayStage;
|
|
3
|
+
/** Incoterm: lege waarde = niet opgegeven (in 2026v2 altijd aanwezig). */
|
|
4
|
+
export declare function readIncoterm(salesOrder: any): string | null;
|
|
5
|
+
export type LoadIssue = {
|
|
6
|
+
code: "missing_fulfillment_order_id" | "missing_load_carrier_reference" | "load_carrier_item_id_missing" | "load_carriers_missing";
|
|
7
|
+
severity: "error" | "warning";
|
|
8
|
+
cartIndex?: number;
|
|
9
|
+
lineIndex?: number;
|
|
10
|
+
fulfillmentRequestId?: string;
|
|
11
|
+
message: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Controle van de belading van Afhandeling. De module maakt nooit zelf een
|
|
15
|
+
* kenmerk aan: fulfillmentOrderId en loadCarrierReference zijn verplicht,
|
|
16
|
+
* loadCarrierItemId mag in 2026v1 ontbreken (waarschuwing).
|
|
17
|
+
*/
|
|
18
|
+
export declare function checkAfhandelingLoad(body: any): {
|
|
19
|
+
errors: LoadIssue[];
|
|
20
|
+
warnings: LoadIssue[];
|
|
21
|
+
};
|
|
22
|
+
/** Verzendbrief is pas betrouwbaar op te halen bij ACCEPTED of DELIVERED. */
|
|
23
|
+
export declare function isDeliveryNoteReady(fulfillmentStatus: string | null | undefined): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Beleid voor send zonder karren van Afhandeling. Standaard (schakelaar uit)
|
|
26
|
+
* gaat het door met een waarschuwing; met `require_load_carriers` aan = 400.
|
|
27
|
+
*/
|
|
28
|
+
export declare function decideLoadCarriersPolicy(hasCartLoad: boolean, required: boolean): "ok" | "warn" | "reject";
|
|
29
|
+
/** Vertaal de uitkomst van de karrencontrole naar de gateway-code. */
|
|
30
|
+
export declare function cartApprovalGatewayCode(code: "toegestaan" | "geen_karrencontrole" | "niet_goedgekeurd" | "controle_onleesbaar"): null | "carts_not_controlled" | "cart_check_unavailable";
|
|
31
|
+
//# sourceMappingURL=floriday-order-stage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floriday-order-stage.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-order-stage.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAIvF,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC3C,mBAAmB,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GACpD,aAAa,CAQf;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,UAAU,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI,CAG3D;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EACA,8BAA8B,GAC9B,gCAAgC,GAChC,8BAA8B,GAC9B,uBAAuB,CAAC;IAC5B,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,GAAG,GAAG;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,QAAQ,EAAE,SAAS,EAAE,CAAA;CAAE,CAyB9F;AAED,6EAA6E;AAC7E,wBAAgB,mBAAmB,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEzF;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,OAAO,EACpB,QAAQ,EAAE,OAAO,GAChB,IAAI,GAAG,MAAM,GAAG,QAAQ,CAG1B;AAED,sEAAsE;AACtE,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,YAAY,GAAG,qBAAqB,GAAG,kBAAkB,GAAG,qBAAqB,GACtF,IAAI,GAAG,sBAAsB,GAAG,wBAAwB,CAI1D"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Pure afleiding van de Floriday-voortgang van één verkooporder.
|
|
2
|
+
//
|
|
3
|
+
// Een Floriday SalesOrder blijft op COMMITTED staan, ook na levering. De
|
|
4
|
+
// echte voortgang staat in de uitlevering (fulfillment-order) die de
|
|
5
|
+
// fulfillmentRequests van de order claimt. Daarom kijken we naar beide.
|
|
6
|
+
// Bron: Suppliers API 2026v1 Swagger (SalesOrderStatus, FulfillmentStatus).
|
|
7
|
+
const FULFILLED = new Set(["ACCEPTED", "DELIVERED"]);
|
|
8
|
+
export function deriveFloridayStage(salesOrderStatus, fulfillmentStatuses) {
|
|
9
|
+
const so = String(salesOrderStatus ?? "").toUpperCase();
|
|
10
|
+
if (!so)
|
|
11
|
+
return "unknown";
|
|
12
|
+
if (so === "CANCELLED" || so === "REJECTED" || so === "UNFULFILLABLE")
|
|
13
|
+
return "cancelled";
|
|
14
|
+
if (so === "EXPIRED")
|
|
15
|
+
return "expired";
|
|
16
|
+
const fo = fulfillmentStatuses.map((s) => String(s ?? "").toUpperCase()).filter(Boolean);
|
|
17
|
+
if (fo.some((s) => FULFILLED.has(s)))
|
|
18
|
+
return "fulfilled";
|
|
19
|
+
return "open";
|
|
20
|
+
}
|
|
21
|
+
/** Incoterm: lege waarde = niet opgegeven (in 2026v2 altijd aanwezig). */
|
|
22
|
+
export function readIncoterm(salesOrder) {
|
|
23
|
+
const v = salesOrder?.delivery?.incoterm;
|
|
24
|
+
return typeof v === "string" && v.trim() ? v.trim() : null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Controle van de belading van Afhandeling. De module maakt nooit zelf een
|
|
28
|
+
* kenmerk aan: fulfillmentOrderId en loadCarrierReference zijn verplicht,
|
|
29
|
+
* loadCarrierItemId mag in 2026v1 ontbreken (waarschuwing).
|
|
30
|
+
*/
|
|
31
|
+
export function checkAfhandelingLoad(body) {
|
|
32
|
+
const errors = [];
|
|
33
|
+
const warnings = [];
|
|
34
|
+
const foId = typeof body?.fulfillmentOrderId === "string" ? body.fulfillmentOrderId.trim() : "";
|
|
35
|
+
if (!foId) {
|
|
36
|
+
errors.push({ code: "missing_fulfillment_order_id", severity: "error",
|
|
37
|
+
message: "fulfillmentOrderId ontbreekt; Afhandeling moet dit vaste kenmerk meesturen." });
|
|
38
|
+
}
|
|
39
|
+
const carts = Array.isArray(body?.loadCarriers) ? body.loadCarriers : [];
|
|
40
|
+
carts.forEach((cart, ci) => {
|
|
41
|
+
const ref = typeof cart?.loadCarrierReference === "string" ? cart.loadCarrierReference.trim() : "";
|
|
42
|
+
if (!ref) {
|
|
43
|
+
errors.push({ code: "missing_load_carrier_reference", severity: "error", cartIndex: ci,
|
|
44
|
+
message: `Kar ${ci + 1} mist loadCarrierReference.` });
|
|
45
|
+
}
|
|
46
|
+
(Array.isArray(cart?.items) ? cart.items : []).forEach((line, li) => {
|
|
47
|
+
const id = typeof line?.loadCarrierItemId === "string" ? line.loadCarrierItemId.trim() : "";
|
|
48
|
+
if (!id) {
|
|
49
|
+
warnings.push({ code: "load_carrier_item_id_missing", severity: "warning", cartIndex: ci, lineIndex: li,
|
|
50
|
+
fulfillmentRequestId: line?.fulfillmentRequestId ? String(line.fulfillmentRequestId) : undefined,
|
|
51
|
+
message: `Kar ${ci + 1}, regel ${li + 1} mist loadCarrierItemId (in 2026v1 toegestaan, vanaf 2026v2 verplicht).` });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
return { errors, warnings };
|
|
56
|
+
}
|
|
57
|
+
/** Verzendbrief is pas betrouwbaar op te halen bij ACCEPTED of DELIVERED. */
|
|
58
|
+
export function isDeliveryNoteReady(fulfillmentStatus) {
|
|
59
|
+
return FULFILLED.has(String(fulfillmentStatus ?? "").toUpperCase());
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Beleid voor send zonder karren van Afhandeling. Standaard (schakelaar uit)
|
|
63
|
+
* gaat het door met een waarschuwing; met `require_load_carriers` aan = 400.
|
|
64
|
+
*/
|
|
65
|
+
export function decideLoadCarriersPolicy(hasCartLoad, required) {
|
|
66
|
+
if (hasCartLoad)
|
|
67
|
+
return "ok";
|
|
68
|
+
return required ? "reject" : "warn";
|
|
69
|
+
}
|
|
70
|
+
/** Vertaal de uitkomst van de karrencontrole naar de gateway-code. */
|
|
71
|
+
export function cartApprovalGatewayCode(code) {
|
|
72
|
+
if (code === "toegestaan")
|
|
73
|
+
return null;
|
|
74
|
+
if (code === "niet_goedgekeurd")
|
|
75
|
+
return "carts_not_controlled";
|
|
76
|
+
return "cart_check_unavailable";
|
|
77
|
+
}
|
|
@@ -11,6 +11,7 @@ export declare function toNetworkRow(item: any, connectionId: string): {
|
|
|
11
11
|
data: any;
|
|
12
12
|
fetched_at: string;
|
|
13
13
|
} | null;
|
|
14
|
+
export declare function ensureBuyersInNetwork(supabase: any, connectionId: string, buyerIds: Array<string | null | undefined>): Promise<any>;
|
|
14
15
|
export declare function backfillNetworkFromCustomersCache(supabase: any, connectionId: string, deadlineMs: number): Promise<{
|
|
15
16
|
copied: number;
|
|
16
17
|
done: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floriday-sync.functions.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-sync.functions.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAS5D,OAAO,EAOL,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAC;AAkDjC,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,cAAc,GACd,wBAAwB,GACxB,UAAU,GACV,oBAAoB,GACpB,mBAAmB,GACnB,YAAY,GACZ,UAAU,GACV,oBAAoB,GACpB,gBAAgB,GAChB,iBAAiB,GACjB,gBAAgB,GAChB,WAAW,GACX,gBAAgB,GAEhB,qBAAqB,GACrB,0BAA0B,GAC1B,aAAa,GACb,cAAc,GACd,gBAAgB,GAEhB,yBAAyB,GACzB,kBAAkB,GAClB,YAAY,GACZ,4BAA4B,GAE5B,0BAA0B,CAAC;AA+B/B,wBAAgB,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM;;;;;;;;;SA8B3D;AAWD,wBAAsB,iCAAiC,CACrD,QAAQ,EAAE,GAAG,EACb,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CA6B5C;
|
|
1
|
+
{"version":3,"file":"floriday-sync.functions.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-sync.functions.ts"],"names":[],"mappings":"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"}
|
|
@@ -88,6 +88,30 @@ async function upsertNetworkRows(supabase, connectionId, items) {
|
|
|
88
88
|
return;
|
|
89
89
|
await upsertInChunks(supabase, "floriday_network_cache", rows, "connection_id,organization_id", "network");
|
|
90
90
|
}
|
|
91
|
+
// Kopers die op een order staan maar nog niet in het netwerk staan, aanvullen
|
|
92
|
+
// vanuit de klantcache — uitsluitend op organisatie-id, nooit op naam.
|
|
93
|
+
// Bestaande netwerkrijen blijven ongemoeid.
|
|
94
|
+
export async function ensureBuyersInNetwork(supabase, connectionId, buyerIds) {
|
|
95
|
+
const ids = Array.from(new Set(buyerIds.filter(Boolean).map(String)));
|
|
96
|
+
if (ids.length === 0)
|
|
97
|
+
return 0;
|
|
98
|
+
const { data: present } = await supabase.from("floriday_network_cache")
|
|
99
|
+
.select("organization_id").eq("connection_id", connectionId).in("organization_id", ids);
|
|
100
|
+
const have = new Set((present ?? []).map((r) => String(r.organization_id)));
|
|
101
|
+
const missing = ids.filter((id) => !have.has(id));
|
|
102
|
+
if (missing.length === 0)
|
|
103
|
+
return 0;
|
|
104
|
+
const { data: customers } = await supabase.from("floriday_customers_cache")
|
|
105
|
+
.select("organization_id, data").in("organization_id", missing);
|
|
106
|
+
const rows = (customers ?? []).map((c) => toNetworkRow({ ...(c.data ?? {}), organizationId: c.organization_id, organizationType: c.data?.organizationType ?? "CUSTOMER" }, connectionId)).filter(Boolean);
|
|
107
|
+
if (rows.length === 0)
|
|
108
|
+
return 0;
|
|
109
|
+
const { error } = await supabase.from("floriday_network_cache")
|
|
110
|
+
.upsert(rows, { onConflict: "connection_id,organization_id", ignoreDuplicates: true });
|
|
111
|
+
if (error)
|
|
112
|
+
throw error;
|
|
113
|
+
return rows.length;
|
|
114
|
+
}
|
|
91
115
|
// Eenmalige aanvulling: de sequence-cursor van customer-organizations staat al
|
|
92
116
|
// voorbij de bestaande organisaties, dus kopiëren we die per portie uit
|
|
93
117
|
// floriday_customers_cache (zelfde Floriday-objecten) tot het netwerk gevuld is.
|
|
@@ -165,7 +189,8 @@ const RESOURCE_CONFIG = {
|
|
|
165
189
|
return {
|
|
166
190
|
connection_id: connectionId,
|
|
167
191
|
floriday_id: String(fid),
|
|
168
|
-
|
|
192
|
+
// Swagger 2026v1: de koper heet customerOrganizationId.
|
|
193
|
+
buyer_organization_id: item?.customerOrganizationId ?? item?.buyerOrganizationId ?? null,
|
|
169
194
|
status: item?.status ?? null,
|
|
170
195
|
is_deleted: Boolean(item?.isDeleted),
|
|
171
196
|
sequence_number: Number(item?.sequenceNumber ?? 0),
|
|
@@ -177,6 +202,12 @@ const RESOURCE_CONFIG = {
|
|
|
177
202
|
if (rows.length === 0)
|
|
178
203
|
return;
|
|
179
204
|
await upsertInChunks(supabase, "floriday_salesorders_cache", rows, "connection_id,floriday_id", "sales-orders");
|
|
205
|
+
try {
|
|
206
|
+
await ensureBuyersInNetwork(supabase, connectionId, rows.map((r) => r.buyer_organization_id));
|
|
207
|
+
}
|
|
208
|
+
catch (e) {
|
|
209
|
+
console.warn("[sales-orders] kopers aanvullen in netwerk mislukt:", e?.message ?? e);
|
|
210
|
+
}
|
|
180
211
|
},
|
|
181
212
|
},
|
|
182
213
|
"customer-organizations": {
|
|
@@ -67,6 +67,8 @@ export interface BuildFulfillmentOrderBodyInput {
|
|
|
67
67
|
logisticHub?: string | null;
|
|
68
68
|
deliveryLocationGln?: string | null;
|
|
69
69
|
oneLabelOnly?: boolean;
|
|
70
|
+
/** Vast kenmerk van Afhandeling; wordt nooit vervangen. */
|
|
71
|
+
fulfillmentOrderId?: string | null;
|
|
70
72
|
}
|
|
71
73
|
export type FulfillmentDetectionSource = "delivery_order_claims" | "fulfillment_orders_cache";
|
|
72
74
|
export type FulfillmentDetection = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fulfillment-order-body.d.ts","sourceRoot":"","sources":["../../../src/lib/gateway/fulfillment-order-body.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAqD5D,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEjF;AAWD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI,CAO3D;AAMD,MAAM,WAAW,yBAAyB;IACxC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,MAAM,EAAE,mBAAmB,GAAG,iBAAiB,CAAC;CACjD;AAED,MAAM,MAAM,+BAA+B,GACvC;IACE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,EAAE,yBAAyB,EAAE,CAAC;CACtC,GACD;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,MAAM,EAAE,0BAA0B,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,yBAAyB,EAAE,CAAC;CACtC,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEN;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wCAAwC;IACxC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kDAAkD;IAClD,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;QACX,oBAAoB,EAAE,MAAM,CAAC;QAC7B,sDAAsD;QACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,0BAA0B,CAAC,EAAE,MAAM,CAAC;QACpC,0BAA0B,CAAC,EAAE,MAAM,CAAC;QACpC,sBAAsB,CAAC,EAAE,MAAM,CAAC;KACjC,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,8BAA8B;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,iBAAiB,EAAE,GAAG,CAAC;IACvB,8DAA8D;IAC9D,qBAAqB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxC;;;OAGG;IACH,YAAY,CAAC,EAAE,oBAAoB,EAAE,GAAG,IAAI,CAAC;IAC7C,4DAA4D;IAC5D,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"fulfillment-order-body.d.ts","sourceRoot":"","sources":["../../../src/lib/gateway/fulfillment-order-body.ts"],"names":[],"mappings":"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"}
|
|
@@ -392,7 +392,12 @@ export async function buildFulfillmentOrderBody(supabase, input) {
|
|
|
392
392
|
});
|
|
393
393
|
}
|
|
394
394
|
}
|
|
395
|
-
|
|
395
|
+
// Afhandeling levert een vast kenmerk mee; dat geven we ongewijzigd door.
|
|
396
|
+
// Alleen het eigen auto-process-pad (zonder belading van Afhandeling) leidt
|
|
397
|
+
// het deterministisch af.
|
|
398
|
+
const fulfillmentOrderId = typeof input.fulfillmentOrderId === "string" && input.fulfillmentOrderId.trim()
|
|
399
|
+
? input.fulfillmentOrderId.trim()
|
|
400
|
+
: await deriveFulfillmentOrderId(deliveryOrderId);
|
|
396
401
|
const body = {
|
|
397
402
|
fulfillmentOrderId,
|
|
398
403
|
oneLabelOnly: input.oneLabelOnly ?? false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fulfillment-order-send.d.ts","sourceRoot":"","sources":["../../../src/lib/gateway/fulfillment-order-send.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"fulfillment-order-send.d.ts","sourceRoot":"","sources":["../../../src/lib/gateway/fulfillment-order-send.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAyB5D,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,0BAA0B,CAAC,CAmOrC;AAeD,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,CAmCnB"}
|
|
@@ -4,6 +4,17 @@ import { resolveGatewayEnvironment } from "./shared.js";
|
|
|
4
4
|
import { florydayWrite, getActiveFlorydayCredentials } from "../floriday.functions.js";
|
|
5
5
|
import { buildFulfillmentOrderBody, detectFulfillmentState, } from "./fulfillment-order-body.js";
|
|
6
6
|
import { checkCartApproval } from "../floriday-cart-approval.server.js";
|
|
7
|
+
import { cartApprovalGatewayCode, checkAfhandelingLoad, decideLoadCarriersPolicy, } from "../floriday-order-stage.js";
|
|
8
|
+
async function readRequireLoadCarriers(supabase) {
|
|
9
|
+
try {
|
|
10
|
+
const { data } = await supabase
|
|
11
|
+
.from("module_runtime_config").select("value").eq("key", "require_load_carriers").maybeSingle();
|
|
12
|
+
return String(data?.value ?? "").trim().toLowerCase() === "true";
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
7
18
|
export async function runFulfillmentOrderSend(supabase, body, caller) {
|
|
8
19
|
const deliveryOrderId = String(body?.deliveryOrderId ?? "").trim();
|
|
9
20
|
const explicitLoadCarrierItems = Array.isArray(body?.loadCarrierItems)
|
|
@@ -56,6 +67,35 @@ export async function runFulfillmentOrderSend(supabase, body, caller) {
|
|
|
56
67
|
},
|
|
57
68
|
};
|
|
58
69
|
}
|
|
70
|
+
// Belading van Afhandeling (loadCarriers): vaste kenmerken controleren.
|
|
71
|
+
// De module maakt nooit zelf een kenmerk aan.
|
|
72
|
+
const hasCartLoad = Array.isArray(body?.loadCarriers) && body.loadCarriers.length > 0;
|
|
73
|
+
let warnings = [];
|
|
74
|
+
if (hasCartLoad) {
|
|
75
|
+
const check = checkAfhandelingLoad(body);
|
|
76
|
+
warnings = check.warnings;
|
|
77
|
+
if (check.errors.length > 0) {
|
|
78
|
+
return {
|
|
79
|
+
status: 400,
|
|
80
|
+
payload: { ok: false, code: check.errors[0].code, errors: check.errors, warnings,
|
|
81
|
+
error: check.errors.map((e) => e.message).join(" ") },
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Zonder karren van Afhandeling: standaard waarschuwing, met de schakelaar
|
|
86
|
+
// `require_load_carriers` (module_runtime_config, standaard uit) een 400.
|
|
87
|
+
const policy = decideLoadCarriersPolicy(hasCartLoad, await readRequireLoadCarriers(supabase));
|
|
88
|
+
if (policy === "reject") {
|
|
89
|
+
return {
|
|
90
|
+
status: 400,
|
|
91
|
+
payload: { ok: false, code: "load_carriers_required",
|
|
92
|
+
error: "Belading zonder karren van Afhandeling wordt niet meer geaccepteerd; stuur loadCarriers mee." },
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (policy === "warn") {
|
|
96
|
+
warnings.push({ code: "load_carriers_missing", severity: "warning",
|
|
97
|
+
message: `Belading zonder karren van Afhandeling (aanroeper: ${caller}); de module stelt de indeling en het fulfillmentOrderId zelf samen. Dit wordt later geweigerd.` });
|
|
98
|
+
}
|
|
59
99
|
// Body opbouwen — hetzij passthrough (caller geeft zelf loadCarrierItems),
|
|
60
100
|
// hetzij via de gedeelde bodybouwer vanuit de cache.
|
|
61
101
|
let writeBody;
|
|
@@ -86,11 +126,12 @@ export async function runFulfillmentOrderSend(supabase, body, caller) {
|
|
|
86
126
|
deliveryOrderData: doRow.data,
|
|
87
127
|
fulfillmentRequestIds,
|
|
88
128
|
// Definitieve karrenindeling uit ons systeem (optioneel).
|
|
89
|
-
loadCarriers:
|
|
129
|
+
loadCarriers: hasCartLoad ? body.loadCarriers : null,
|
|
90
130
|
carrierOrganizationId: body?.carrierOrganizationId ?? null,
|
|
91
131
|
logisticHub: body?.logisticHub ?? null,
|
|
92
132
|
deliveryLocationGln: body?.deliveryLocationGln ?? null,
|
|
93
133
|
oneLabelOnly: Boolean(body?.oneLabelOnly),
|
|
134
|
+
fulfillmentOrderId: hasCartLoad ? String(body.fulfillmentOrderId) : null,
|
|
94
135
|
});
|
|
95
136
|
if (built.kind === "already_fulfilled") {
|
|
96
137
|
return {
|
|
@@ -103,6 +144,7 @@ export async function runFulfillmentOrderSend(supabase, body, caller) {
|
|
|
103
144
|
reason: built.message,
|
|
104
145
|
fulfillmentOrderId: built.fulfillmentOrderId,
|
|
105
146
|
skippedRequests: built.skipped,
|
|
147
|
+
warnings,
|
|
106
148
|
},
|
|
107
149
|
};
|
|
108
150
|
}
|
|
@@ -115,7 +157,7 @@ export async function runFulfillmentOrderSend(supabase, body, caller) {
|
|
|
115
157
|
writeBody = built.body;
|
|
116
158
|
skipped = built.skipped;
|
|
117
159
|
}
|
|
118
|
-
// Laatste poort: zijn alle karren van de order
|
|
160
|
+
// Laatste poort: zijn alle karren van de order afgemeld aan de controlebalie?
|
|
119
161
|
const approval = await checkCartApproval(supabase, {
|
|
120
162
|
connectionId: conn.id,
|
|
121
163
|
deliveryOrderId,
|
|
@@ -126,7 +168,7 @@ export async function runFulfillmentOrderSend(supabase, body, caller) {
|
|
|
126
168
|
status: 409,
|
|
127
169
|
payload: {
|
|
128
170
|
ok: false,
|
|
129
|
-
code: "carts_not_controlled",
|
|
171
|
+
code: cartApprovalGatewayCode(approval.code) ?? "carts_not_controlled",
|
|
130
172
|
skipped: true,
|
|
131
173
|
blockedBy: approval.code,
|
|
132
174
|
orderRefs: approval.orderRefs,
|
|
@@ -147,7 +189,16 @@ export async function runFulfillmentOrderSend(supabase, body, caller) {
|
|
|
147
189
|
: undefined,
|
|
148
190
|
caller,
|
|
149
191
|
});
|
|
150
|
-
|
|
192
|
+
if (warnings.length > 0) {
|
|
193
|
+
await supabase.from("floriday_write_log").insert({
|
|
194
|
+
connection_id: conn.id, module: "gateway", action: "fulfillment-order-load-warnings",
|
|
195
|
+
resource: "gateway", floriday_id: deliveryOrderId || null, request: { warnings },
|
|
196
|
+
response: null, http_status: 0, ok: true, error: warnings.map((w) => w.message).join(" ").slice(0, 500),
|
|
197
|
+
idempotency_key: null, caller,
|
|
198
|
+
}).then(() => undefined, () => undefined);
|
|
199
|
+
}
|
|
200
|
+
const fulfillmentOrderId = writeBody?.fulfillmentOrderId ??
|
|
201
|
+
result.data?.fulfillmentOrderId ??
|
|
151
202
|
result.data?.id ??
|
|
152
203
|
result.data?.floridayId;
|
|
153
204
|
if (result.ok) {
|
|
@@ -160,6 +211,7 @@ export async function runFulfillmentOrderSend(supabase, body, caller) {
|
|
|
160
211
|
skipped: false,
|
|
161
212
|
skippedRequests: skipped,
|
|
162
213
|
fulfillmentOrderId,
|
|
214
|
+
warnings,
|
|
163
215
|
},
|
|
164
216
|
};
|
|
165
217
|
}
|
|
@@ -171,6 +223,7 @@ export async function runFulfillmentOrderSend(supabase, body, caller) {
|
|
|
171
223
|
skipped: false,
|
|
172
224
|
skippedRequests: skipped,
|
|
173
225
|
fulfillmentOrderId,
|
|
226
|
+
warnings,
|
|
174
227
|
error: result.error,
|
|
175
228
|
},
|
|
176
229
|
};
|
|
@@ -3,6 +3,16 @@ export interface FulfillmentOrderStatusResult {
|
|
|
3
3
|
status: number;
|
|
4
4
|
payload: unknown;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Statusoverzicht per verkooporder, alleen uit de caches (geen Floriday-
|
|
8
|
+
* aanroep): orderstatus, uitleveringen, fulfillmentRequestIds, floridayStage
|
|
9
|
+
* en de ordervelden. Een order die niet in de cache staat krijgt stage
|
|
10
|
+
* "unknown" — geen fout. Wijzigt nooit een orderstatus.
|
|
11
|
+
*/
|
|
12
|
+
export declare function runSalesOrderStatusOverview(supabase: SupabaseClient, input: {
|
|
13
|
+
salesOrderIds: string[];
|
|
14
|
+
environment?: "staging" | "live";
|
|
15
|
+
}): Promise<FulfillmentOrderStatusResult>;
|
|
6
16
|
export declare function runFulfillmentOrderStatus(supabase: SupabaseClient, input: {
|
|
7
17
|
fulfillmentOrderId: string;
|
|
8
18
|
environment?: "staging" | "live";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fulfillment-order-status.d.ts","sourceRoot":"","sources":["../../../src/lib/gateway/fulfillment-order-status.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"fulfillment-order-status.d.ts","sourceRoot":"","sources":["../../../src/lib/gateway/fulfillment-order-status.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK5D,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAID;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE;IAAE,aAAa,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GACnE,OAAO,CAAC,4BAA4B,CAAC,CAuFvC;AAED,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE;IAAE,kBAAkB,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GACtE,OAAO,CAAC,4BAA4B,CAAC,CA6CvC;AAcD,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,CA4CnB"}
|