@flowselections/floriday-verkoop-module 1.0.94 → 1.0.100

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 (185) hide show
  1. package/dist-lib/components/verkoop/AnalyticsCards.d.ts +1 -1
  2. package/dist-lib/components/verkoop/AnalyticsCards.d.ts.map +1 -1
  3. package/dist-lib/components/verkoop/CartAssignmentWizard.d.ts +1 -1
  4. package/dist-lib/components/verkoop/CartAssignmentWizard.d.ts.map +1 -1
  5. package/dist-lib/components/verkoop/CartLayersDialog.d.ts +1 -1
  6. package/dist-lib/components/verkoop/CartLayersDialog.d.ts.map +1 -1
  7. package/dist-lib/components/verkoop/ConfirmDialog.d.ts +11 -0
  8. package/dist-lib/components/verkoop/ConfirmDialog.d.ts.map +1 -0
  9. package/dist-lib/components/verkoop/ConfirmDialog.js +10 -0
  10. package/dist-lib/components/verkoop/CreateOrderPage.d.ts +1 -1
  11. package/dist-lib/components/verkoop/CreateOrderPage.d.ts.map +1 -1
  12. package/dist-lib/components/verkoop/CreateOrderPage.js +111 -48
  13. package/dist-lib/components/verkoop/DiagnoseConnectionDialog.d.ts +1 -1
  14. package/dist-lib/components/verkoop/DiagnoseConnectionDialog.d.ts.map +1 -1
  15. package/dist-lib/components/verkoop/EditLocalOrderDialog.d.ts +1 -1
  16. package/dist-lib/components/verkoop/EditLocalOrderDialog.d.ts.map +1 -1
  17. package/dist-lib/components/verkoop/EngineBufferCard.d.ts +1 -1
  18. package/dist-lib/components/verkoop/EngineBufferCard.d.ts.map +1 -1
  19. package/dist-lib/components/verkoop/FloridayStageLine.d.ts +2 -2
  20. package/dist-lib/components/verkoop/FloridayStageLine.d.ts.map +1 -1
  21. package/dist-lib/components/verkoop/InvoiceTimingSettings.d.ts +1 -1
  22. package/dist-lib/components/verkoop/InvoiceTimingSettings.d.ts.map +1 -1
  23. package/dist-lib/components/verkoop/OrderAfleverbrievenCard.d.ts +1 -1
  24. package/dist-lib/components/verkoop/OrderAfleverbrievenCard.d.ts.map +1 -1
  25. package/dist-lib/components/verkoop/OrderCarrierPicker.d.ts +1 -1
  26. package/dist-lib/components/verkoop/OrderCarrierPicker.d.ts.map +1 -1
  27. package/dist-lib/components/verkoop/OrderControlStatusCard.d.ts +1 -1
  28. package/dist-lib/components/verkoop/OrderControlStatusCard.d.ts.map +1 -1
  29. package/dist-lib/components/verkoop/OrderKarindelingCard.d.ts +1 -1
  30. package/dist-lib/components/verkoop/OrderKarindelingCard.d.ts.map +1 -1
  31. package/dist-lib/components/verkoop/OrderKarindelingCard.js +28 -2
  32. package/dist-lib/components/verkoop/OrderLinePackingCard.d.ts +1 -1
  33. package/dist-lib/components/verkoop/OrderLinePackingCard.d.ts.map +1 -1
  34. package/dist-lib/components/verkoop/OrderPickupMomentPicker.d.ts +1 -1
  35. package/dist-lib/components/verkoop/OrderPickupMomentPicker.d.ts.map +1 -1
  36. package/dist-lib/components/verkoop/OrderPickupMomentPicker.js +2 -1
  37. package/dist-lib/components/verkoop/OrderShipmentsCard.d.ts +1 -1
  38. package/dist-lib/components/verkoop/OrderShipmentsCard.d.ts.map +1 -1
  39. package/dist-lib/components/verkoop/OrderShipmentsCard.js +16 -13
  40. package/dist-lib/components/verkoop/PlanCoverageBadge.d.ts +1 -1
  41. package/dist-lib/components/verkoop/PlanCoverageBadge.d.ts.map +1 -1
  42. package/dist-lib/components/verkoop/PlanCoverageBadge.js +7 -5
  43. package/dist-lib/components/verkoop/ProductDimensionsSettings.d.ts +1 -1
  44. package/dist-lib/components/verkoop/ProductDimensionsSettings.d.ts.map +1 -1
  45. package/dist-lib/components/verkoop/SalesOrderDetailPage.d.ts +1 -1
  46. package/dist-lib/components/verkoop/SalesOrderDetailPage.d.ts.map +1 -1
  47. package/dist-lib/components/verkoop/SalesOrderDetailPage.js +6 -6
  48. package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts +1 -1
  49. package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts.map +1 -1
  50. package/dist-lib/components/verkoop/SalesOrderDetailView.js +2 -1
  51. package/dist-lib/components/verkoop/SalesOrdersFilterPanel.d.ts +1 -1
  52. package/dist-lib/components/verkoop/SalesOrdersFilterPanel.d.ts.map +1 -1
  53. package/dist-lib/components/verkoop/SalesOrdersFilters.d.ts +1 -1
  54. package/dist-lib/components/verkoop/SalesOrdersFilters.d.ts.map +1 -1
  55. package/dist-lib/components/verkoop/SalesOrdersTable.d.ts +2 -1
  56. package/dist-lib/components/verkoop/SalesOrdersTable.d.ts.map +1 -1
  57. package/dist-lib/components/verkoop/SalesOrdersTable.js +1 -1
  58. package/dist-lib/components/verkoop/SearchableSelect.d.ts +1 -1
  59. package/dist-lib/components/verkoop/SearchableSelect.d.ts.map +1 -1
  60. package/dist-lib/components/verkoop/StockConsumptionAlertsBanner.d.ts +1 -1
  61. package/dist-lib/components/verkoop/StockConsumptionAlertsBanner.d.ts.map +1 -1
  62. package/dist-lib/components/verkoop/VerkoopOrdersPage.d.ts +1 -1
  63. package/dist-lib/components/verkoop/VerkoopOrdersPage.d.ts.map +1 -1
  64. package/dist-lib/components/verkoop/WeekCalendar.d.ts +1 -1
  65. package/dist-lib/components/verkoop/WeekCalendar.d.ts.map +1 -1
  66. package/dist-lib/integrations/supabase/client.js +1 -1
  67. package/dist-lib/integrations/supabase/client.server.js +1 -1
  68. package/dist-lib/integrations/supabase/types.d.ts +352 -0
  69. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  70. package/dist-lib/lib/carrier-availability.d.ts +0 -28
  71. package/dist-lib/lib/carrier-availability.d.ts.map +1 -1
  72. package/dist-lib/lib/carrier-availability.js +3 -141
  73. package/dist-lib/lib/cart-replan.functions.d.ts +5 -0
  74. package/dist-lib/lib/cart-replan.functions.d.ts.map +1 -1
  75. package/dist-lib/lib/cart-replan.functions.js +25 -1
  76. package/dist-lib/lib/create-order.functions.d.ts +8 -0
  77. package/dist-lib/lib/create-order.functions.d.ts.map +1 -1
  78. package/dist-lib/lib/create-order.functions.js +110 -54
  79. package/dist-lib/lib/departure-preview.check.d.ts +2 -0
  80. package/dist-lib/lib/departure-preview.check.d.ts.map +1 -0
  81. package/dist-lib/lib/departure-preview.check.js +60 -0
  82. package/dist-lib/lib/departure-preview.d.ts +71 -0
  83. package/dist-lib/lib/departure-preview.d.ts.map +1 -0
  84. package/dist-lib/lib/departure-preview.functions.d.ts +14 -0
  85. package/dist-lib/lib/departure-preview.functions.d.ts.map +1 -0
  86. package/dist-lib/lib/departure-preview.functions.js +18 -0
  87. package/dist-lib/lib/departure-preview.js +133 -0
  88. package/dist-lib/lib/departure-preview.server.d.ts +11 -0
  89. package/dist-lib/lib/departure-preview.server.d.ts.map +1 -0
  90. package/dist-lib/lib/departure-preview.server.js +32 -0
  91. package/dist-lib/lib/floriday-external-fulfillment.check.d.ts +2 -0
  92. package/dist-lib/lib/floriday-external-fulfillment.check.d.ts.map +1 -0
  93. package/dist-lib/lib/floriday-external-fulfillment.check.js +21 -0
  94. package/dist-lib/lib/floriday-external-fulfillment.d.ts +19 -0
  95. package/dist-lib/lib/floriday-external-fulfillment.d.ts.map +1 -0
  96. package/dist-lib/lib/floriday-external-fulfillment.js +24 -0
  97. package/dist-lib/lib/floriday-external-fulfillment.server.d.ts +5 -0
  98. package/dist-lib/lib/floriday-external-fulfillment.server.d.ts.map +1 -0
  99. package/dist-lib/lib/floriday-external-fulfillment.server.js +110 -0
  100. package/dist-lib/lib/floriday-fulfillment-status.server.d.ts +2 -0
  101. package/dist-lib/lib/floriday-fulfillment-status.server.d.ts.map +1 -1
  102. package/dist-lib/lib/floriday-fulfillment-status.server.js +3 -0
  103. package/dist-lib/lib/floriday-line-key.check.d.ts +2 -0
  104. package/dist-lib/lib/floriday-line-key.check.d.ts.map +1 -0
  105. package/dist-lib/lib/floriday-line-key.check.js +31 -0
  106. package/dist-lib/lib/floriday-line-key.d.ts +12 -0
  107. package/dist-lib/lib/floriday-line-key.d.ts.map +1 -0
  108. package/dist-lib/lib/floriday-line-key.js +20 -0
  109. package/dist-lib/lib/floriday-mirror.functions.d.ts.map +1 -1
  110. package/dist-lib/lib/floriday-mirror.functions.js +38 -2
  111. package/dist-lib/lib/invoice-timing.server.d.ts +3 -1
  112. package/dist-lib/lib/invoice-timing.server.d.ts.map +1 -1
  113. package/dist-lib/lib/invoice-timing.server.js +3 -2
  114. package/dist-lib/lib/logistics-engine.functions.d.ts +1 -1
  115. package/dist-lib/lib/module-version.d.ts +2 -0
  116. package/dist-lib/lib/module-version.d.ts.map +1 -0
  117. package/dist-lib/lib/module-version.js +3 -0
  118. package/dist-lib/lib/order-cart-count.server.d.ts +8 -0
  119. package/dist-lib/lib/order-cart-count.server.d.ts.map +1 -0
  120. package/dist-lib/lib/order-cart-count.server.js +69 -0
  121. package/dist-lib/lib/order-departure.server.d.ts +1 -0
  122. package/dist-lib/lib/order-departure.server.d.ts.map +1 -1
  123. package/dist-lib/lib/order-departure.server.js +16 -4
  124. package/dist-lib/lib/order-pickup.functions.d.ts +4 -0
  125. package/dist-lib/lib/order-pickup.functions.d.ts.map +1 -1
  126. package/dist-lib/lib/order-pickup.functions.js +7 -0
  127. package/dist-lib/lib/plan-coverage.d.ts +13 -1
  128. package/dist-lib/lib/plan-coverage.d.ts.map +1 -1
  129. package/dist-lib/lib/plan-coverage.js +20 -1
  130. package/dist-lib/lib/salesorders-list.server.d.ts.map +1 -1
  131. package/dist-lib/lib/salesorders-list.server.js +8 -7
  132. package/dist-lib/lib/salesorders-mapping.d.ts +7 -0
  133. package/dist-lib/lib/salesorders-mapping.d.ts.map +1 -1
  134. package/dist-lib/lib/salesorders.functions.d.ts.map +1 -1
  135. package/dist-lib/lib/salesorders.functions.js +10 -0
  136. package/dist-lib/lib/tradeitems.functions.d.ts +1117 -12
  137. package/dist-lib/lib/tradeitems.functions.d.ts.map +1 -1
  138. package/dist-lib/lib/useBufferEvents.d.ts +2 -2
  139. package/dist-lib/lib/useBufferEvents.d.ts.map +1 -1
  140. package/dist-lib/lib/useLocalSalesOrderDetailQuery.d.ts +2 -2
  141. package/dist-lib/lib/useLocalSalesOrderDetailQuery.d.ts.map +1 -1
  142. package/dist-lib/lib/useSalesOrderDetailQuery.d.ts +1 -1
  143. package/dist-lib/lib/useSalesOrderDetailQuery.d.ts.map +1 -1
  144. package/dist-lib/lib/useSalesOrdersQuery.d.ts +1 -1
  145. package/dist-lib/lib/useSalesOrdersQuery.d.ts.map +1 -1
  146. package/package.json +1 -1
  147. package/dist-lib/components/floriday/FlorydaySyncHealthBanner.d.ts +0 -9
  148. package/dist-lib/components/floriday/FlorydaySyncHealthBanner.d.ts.map +0 -1
  149. package/dist-lib/components/floriday/FlorydaySyncHealthBanner.js +0 -26
  150. package/dist-lib/components/karindeling/AfmetingenTab.d.ts +0 -6
  151. package/dist-lib/components/karindeling/AfmetingenTab.d.ts.map +0 -1
  152. package/dist-lib/components/karindeling/AfmetingenTab.js +0 -128
  153. package/dist-lib/components/karindeling/KarindelingPage.d.ts +0 -2
  154. package/dist-lib/components/karindeling/KarindelingPage.d.ts.map +0 -1
  155. package/dist-lib/components/karindeling/KarindelingPage.js +0 -102
  156. package/dist-lib/components/ui/dropdown-menu.d.ts +0 -9
  157. package/dist-lib/components/ui/dropdown-menu.d.ts.map +0 -1
  158. package/dist-lib/components/ui/dropdown-menu.js +0 -14
  159. package/dist-lib/components/verkoop/AutoFulfillmentStatusCard.d.ts +0 -4
  160. package/dist-lib/components/verkoop/AutoFulfillmentStatusCard.d.ts.map +0 -1
  161. package/dist-lib/components/verkoop/AutoFulfillmentStatusCard.js +0 -95
  162. package/dist-lib/components/verkoop/CreateOrderDialog.d.ts +0 -5
  163. package/dist-lib/components/verkoop/CreateOrderDialog.d.ts.map +0 -1
  164. package/dist-lib/components/verkoop/CreateOrderDialog.js +0 -33
  165. package/dist-lib/lib/cron/mirror-floriday-orders.d.ts +0 -4
  166. package/dist-lib/lib/cron/mirror-floriday-orders.d.ts.map +0 -1
  167. package/dist-lib/lib/cron/mirror-floriday-orders.js +0 -23
  168. package/dist-lib/lib/cron/push-order-statuses.d.ts +0 -4
  169. package/dist-lib/lib/cron/push-order-statuses.d.ts.map +0 -1
  170. package/dist-lib/lib/cron/push-order-statuses.js +0 -23
  171. package/dist-lib/lib/floriday/floriday.server.d.ts +0 -14
  172. package/dist-lib/lib/floriday/floriday.server.d.ts.map +0 -1
  173. package/dist-lib/lib/floriday/floriday.server.js +0 -92
  174. package/dist-lib/lib/floriday/sales-orders.functions.d.ts +0 -4736
  175. package/dist-lib/lib/floriday/sales-orders.functions.d.ts.map +0 -1
  176. package/dist-lib/lib/floriday/sales-orders.functions.js +0 -193
  177. package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts +0 -77581
  178. package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts.map +0 -1
  179. package/dist-lib/lib/floriday-auto-fulfillment.functions.js +0 -65
  180. package/dist-lib/lib/floriday-auto-fulfillment.server.d.ts +0 -21
  181. package/dist-lib/lib/floriday-auto-fulfillment.server.d.ts.map +0 -1
  182. package/dist-lib/lib/floriday-auto-fulfillment.server.js +0 -352
  183. package/dist-lib/lib/floriday-status-sync.server.d.ts +0 -14
  184. package/dist-lib/lib/floriday-status-sync.server.d.ts.map +0 -1
  185. package/dist-lib/lib/floriday-status-sync.server.js +0 -130
@@ -1,65 +0,0 @@
1
- // Client-callable helpers around the auto-fulfillment log.
2
- import { createServerFn } from "@tanstack/react-start";
3
- import { z } from "zod";
4
- import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
5
- export const getPreferredWarehouseStatus = createServerFn({ method: "POST" })
6
- .middleware([requireSupabaseAuth])
7
- .handler(async ({ context }) => {
8
- const { supabase } = context;
9
- const { data } = await supabase
10
- .from("floriday_connections")
11
- .select("id, preferred_warehouse_id")
12
- .eq("is_active", true)
13
- .limit(1)
14
- .maybeSingle();
15
- return {
16
- hasPreferredWarehouse: Boolean(data?.preferred_warehouse_id),
17
- connectionId: data?.id ?? null,
18
- };
19
- });
20
- const SalesOrderSchema = z.object({ salesOrderId: z.string().min(1) });
21
- export const getAutoFulfillmentStatus = createServerFn({ method: "POST" })
22
- .middleware([requireSupabaseAuth])
23
- .inputValidator((d) => SalesOrderSchema.parse(d))
24
- .handler(async ({ data, context }) => {
25
- const { supabase } = context;
26
- const { data: row } = await supabase
27
- .from("floriday_auto_fulfillment_log")
28
- .select("status, reason, error, fulfillment_order_id, attempts, last_attempt_at, updated_at")
29
- .eq("sales_order_id", data.salesOrderId)
30
- .order("updated_at", { ascending: false })
31
- .limit(1)
32
- .maybeSingle();
33
- return { row: row ?? null };
34
- });
35
- export const retryAutoFulfillment = createServerFn({ method: "POST" })
36
- .middleware([requireSupabaseAuth])
37
- .inputValidator((d) => SalesOrderSchema.parse(d))
38
- .handler(async ({ data, context }) => {
39
- const { supabase, userId } = context;
40
- const { data: isAdmin } = await supabase.rpc("has_role", {
41
- _user_id: userId,
42
- _role: "admin",
43
- });
44
- if (!isAdmin)
45
- throw new Error("Alleen admins mogen fulfillment orders opnieuw aanmaken");
46
- const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
47
- const { processOrderForAutoFulfillment } = await import("./floriday-auto-fulfillment.server.js");
48
- const { data: order, error } = await supabaseAdmin
49
- .from("floriday_salesorders_cache")
50
- .select("connection_id, floriday_id, status, is_deleted, data")
51
- .eq("floriday_id", data.salesOrderId)
52
- .limit(1)
53
- .maybeSingle();
54
- if (error)
55
- throw new Error(`Salesorder ophalen faalde: ${error.message}`);
56
- if (!order)
57
- throw new Error("Salesorder niet gevonden in cache");
58
- // Force a fresh attempt: clear a prior 'created' guard so we re-run.
59
- await supabaseAdmin.from("floriday_auto_fulfillment_log")
60
- .update({ status: "pending", error: null })
61
- .eq("connection_id", order.connection_id)
62
- .eq("sales_order_id", order.floriday_id);
63
- const result = await processOrderForAutoFulfillment(supabaseAdmin, order);
64
- return result;
65
- });
@@ -1,21 +0,0 @@
1
- import type { SupabaseClient } from "@supabase/supabase-js";
2
- type SalesOrderRow = {
3
- connection_id: string;
4
- floriday_id: string;
5
- status: string | null;
6
- is_deleted: boolean | null;
7
- data: any;
8
- };
9
- export declare function processOrderForAutoFulfillment(supabase: SupabaseClient, order: SalesOrderRow): Promise<{
10
- status: "created" | "skipped" | "failed";
11
- reason?: string;
12
- fulfillmentOrderId?: string;
13
- }>;
14
- export declare function processRecentSalesOrders(supabase: SupabaseClient, connectionId: string, sinceIso: string): Promise<{
15
- processed: number;
16
- created: number;
17
- failed: number;
18
- skipped: number;
19
- }>;
20
- export {};
21
- //# sourceMappingURL=floriday-auto-fulfillment.server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"floriday-auto-fulfillment.server.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-auto-fulfillment.server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,KAAK,aAAa,GAAG;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,GAAG,CAAC;CACX,CAAC;AA4NF,wBAAsB,8BAA8B,CAClD,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,aAAa,GACnB,OAAO,CAAC;IAAE,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA+IrG;AAED,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,cAAc,EACxB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA2ElF"}
@@ -1,352 +0,0 @@
1
- import { florydayWrite } from "./floriday-gateway.server.js";
2
- async function loadConnectionMeta(supabase, connectionId) {
3
- const { data } = await supabase
4
- .from("floriday_connections")
5
- .select("id, environment, api_key, is_active, gln_code, preferred_warehouse_id")
6
- .eq("id", connectionId)
7
- .maybeSingle();
8
- return data ?? null;
9
- }
10
- async function loadProductPacking(supabase, tradeItemId) {
11
- if (!tradeItemId)
12
- return null;
13
- const { data } = await supabase
14
- .from("products")
15
- .select("plants_per_crate, crates_per_layer, layers_per_cart")
16
- .eq("trade_item_key", tradeItemId)
17
- .limit(1)
18
- .maybeSingle();
19
- if (!data)
20
- return null;
21
- return {
22
- plants_per_crate: Number(data.plants_per_crate) || 0,
23
- crates_per_layer: Number(data.crates_per_layer) || 0,
24
- layers_per_cart: Number(data.layers_per_cart) || 0,
25
- };
26
- }
27
- function upsertLog(supabase, connectionId, salesOrderId, patch) {
28
- return supabase.from("floriday_auto_fulfillment_log").upsert({
29
- connection_id: connectionId,
30
- sales_order_id: salesOrderId,
31
- last_attempt_at: new Date().toISOString(),
32
- ...patch,
33
- }, { onConflict: "connection_id,sales_order_id" });
34
- }
35
- async function existingFulfillmentForOrder(supabase, connectionId, salesOrderId) {
36
- // Scan the most recent fulfillment orders for this connection and look for
37
- // a nested loadCarrierItems entry referencing this sales order.
38
- const { data } = await supabase
39
- .from("floriday_fulfillment_orders_cache")
40
- .select("data")
41
- .eq("connection_id", connectionId)
42
- .order("fetched_at", { ascending: false })
43
- .limit(500);
44
- const rows = data ?? [];
45
- for (const row of rows) {
46
- const carriers = row?.data?.loadCarriers;
47
- if (!Array.isArray(carriers))
48
- continue;
49
- for (const c of carriers) {
50
- const items = c?.loadCarrierItems;
51
- if (!Array.isArray(items))
52
- continue;
53
- for (const it of items) {
54
- if (String(it?.salesOrderId ?? "") === salesOrderId)
55
- return true;
56
- }
57
- }
58
- }
59
- return false;
60
- }
61
- async function alreadyProcessed(supabase, connectionId, salesOrderId) {
62
- const { data } = await supabase
63
- .from("floriday_auto_fulfillment_log")
64
- .select("status")
65
- .eq("connection_id", connectionId)
66
- .eq("sales_order_id", salesOrderId)
67
- .maybeSingle();
68
- return data?.status === "created";
69
- }
70
- async function loadDeliveryContext(supabase, connectionId, salesOrderId) {
71
- const { data } = await supabase
72
- .from("floriday_delivery_orders_cache")
73
- .select("data")
74
- .eq("connection_id", connectionId)
75
- .eq("is_deleted", false)
76
- .order("fetched_at", { ascending: false })
77
- .limit(500);
78
- const rows = data ?? [];
79
- for (const row of rows) {
80
- const d = row?.data;
81
- const reqs = Array.isArray(d?.fulfillmentRequests) ? d.fulfillmentRequests : [];
82
- const matching = [];
83
- for (const r of reqs) {
84
- if (String(r?.salesOrderId ?? "") !== salesOrderId)
85
- continue;
86
- matching.push({
87
- fulfillmentRequestId: String(r?.fulfillmentRequestId ?? ""),
88
- salesOrderId: String(r?.salesOrderId ?? ""),
89
- loadCarrier: r?.loadCarrier ?? null,
90
- numberOfPackages: Number(r?.numberOfPackages ?? 0) || 0,
91
- deliveryRemarks: r?.deliveryRemarks ?? null,
92
- tradeItemId: r?.tradeItemId ?? null,
93
- });
94
- }
95
- if (matching.length > 0) {
96
- return {
97
- deliveryOrderId: String(d?.deliveryOrderId ?? ""),
98
- despatchWarehouseId: d?.despatchWarehouseId ?? null,
99
- destination: d?.destination ?? null,
100
- latestDeliveryDateTime: d?.deliveryDateTime ?? null,
101
- requests: matching,
102
- };
103
- }
104
- }
105
- return null;
106
- }
107
- function buildFulfillmentPayload(order, warehouseId, ctx) {
108
- const warnings = [];
109
- const supplierOrganizationId = String(order?.supplierOrganizationId ?? "");
110
- const customerOrganizationId = String(order?.customerOrganizationId ?? "");
111
- // Group requests by load-carrier type to build one loadCarrier per group.
112
- const byCarrier = new Map();
113
- for (const r of ctx.requests) {
114
- const key = r.loadCarrier ?? "DANISH_TROLLEY";
115
- if (!byCarrier.has(key))
116
- byCarrier.set(key, []);
117
- byCarrier.get(key).push(r);
118
- }
119
- const loadCarriers = [];
120
- let sortIndex = 1;
121
- for (const [carrier, requests] of byCarrier) {
122
- loadCarriers.push({
123
- sortIndex: sortIndex++,
124
- loadCarrierType: carrier === "NONE" ? "DANISH_TROLLEY" : carrier,
125
- numberOfAdditionalLayers: 0,
126
- loadCarrierItems: requests.map((r, idx) => {
127
- const item = {
128
- sortIndex: idx + 1,
129
- fulfillmentRequestId: r.fulfillmentRequestId,
130
- tradeItemId: r.tradeItemId ?? String(order?.tradeItemId ?? ""),
131
- salesOrderId: r.salesOrderId,
132
- numberOfPackages: r.numberOfPackages,
133
- };
134
- const remarks = (r.deliveryRemarks ?? "").toString().trim();
135
- if (remarks)
136
- item.deliveryRemarks = remarks;
137
- return item;
138
- }),
139
- });
140
- }
141
- const payload = {
142
- fulfillmentOrderId: crypto.randomUUID(),
143
- type: order?.tradeInstrument ?? "DIRECT_SALES",
144
- despatchWarehouseId: warehouseId,
145
- latestDeliveryDateTime: ctx.latestDeliveryDateTime ?? order?.delivery?.latestDeliveryDateTime ?? null,
146
- supplierOrganizationId,
147
- fulfillingOrganizationId: supplierOrganizationId,
148
- destination: ctx.destination ?? {
149
- organizationId: customerOrganizationId,
150
- location: order?.delivery?.location ?? null,
151
- warehouseId: null,
152
- },
153
- loadCarriers,
154
- oneLabelOnly: false,
155
- };
156
- return { payload, warnings };
157
- }
158
- const SKIPPABLE_STATUSES = new Set(["REJECTED", "CANCELLED", "CANCELED", "EXPIRED"]);
159
- export async function processOrderForAutoFulfillment(supabase, order) {
160
- const salesOrderId = order.floriday_id;
161
- const connectionId = order.connection_id;
162
- if (order.is_deleted) {
163
- await upsertLog(supabase, connectionId, salesOrderId, {
164
- status: "skipped",
165
- reason: "sales-order-deleted",
166
- });
167
- return { status: "skipped", reason: "sales-order-deleted" };
168
- }
169
- if (order.status && SKIPPABLE_STATUSES.has(String(order.status).toUpperCase())) {
170
- await upsertLog(supabase, connectionId, salesOrderId, {
171
- status: "skipped",
172
- reason: `status-${order.status}`,
173
- });
174
- return { status: "skipped", reason: `status-${order.status}` };
175
- }
176
- if (await alreadyProcessed(supabase, connectionId, salesOrderId)) {
177
- return { status: "skipped", reason: "already-created" };
178
- }
179
- if (await existingFulfillmentForOrder(supabase, connectionId, salesOrderId)) {
180
- await upsertLog(supabase, connectionId, salesOrderId, {
181
- status: "skipped",
182
- reason: "existing-fulfillment",
183
- });
184
- return { status: "skipped", reason: "existing-fulfillment" };
185
- }
186
- const conn = await loadConnectionMeta(supabase, connectionId);
187
- if (!conn) {
188
- await upsertLog(supabase, connectionId, salesOrderId, {
189
- status: "failed",
190
- error: "connection-not-found",
191
- });
192
- return { status: "failed", reason: "connection-not-found" };
193
- }
194
- // Warehouse fallback chain:
195
- // 1) connection.preferred_warehouse_id
196
- // 2) salesorder.data.despatchWarehouseId
197
- // 3) first non-deleted warehouse from floriday_warehouses_cache
198
- let warehouseId = conn.preferred_warehouse_id ?? null;
199
- let warehouseFallback = null;
200
- if (!warehouseId) {
201
- const orderWarehouse = String(order.data?.despatchWarehouseId ?? "").trim();
202
- if (orderWarehouse) {
203
- warehouseId = orderWarehouse;
204
- warehouseFallback = "warehouse-fallback:order";
205
- }
206
- }
207
- if (!warehouseId) {
208
- const { data: wh } = await supabase
209
- .from("floriday_warehouses_cache")
210
- .select("floriday_id, is_default")
211
- .eq("connection_id", connectionId)
212
- .eq("is_deleted", false)
213
- .order("is_default", { ascending: false })
214
- .limit(1)
215
- .maybeSingle();
216
- const cached = String(wh?.floriday_id ?? "").trim();
217
- if (cached) {
218
- warehouseId = cached;
219
- warehouseFallback = "warehouse-fallback:cache";
220
- }
221
- }
222
- if (!warehouseId) {
223
- await upsertLog(supabase, connectionId, salesOrderId, {
224
- status: "skipped",
225
- reason: "no-warehouse",
226
- });
227
- return { status: "skipped", reason: "no-warehouse" };
228
- }
229
- // Load Floriday-issued fulfillment requests from the matching delivery order.
230
- const deliveryCtx = await loadDeliveryContext(supabase, connectionId, salesOrderId);
231
- if (!deliveryCtx || deliveryCtx.requests.length === 0) {
232
- await upsertLog(supabase, connectionId, salesOrderId, {
233
- status: "skipped",
234
- reason: "no-delivery-order",
235
- });
236
- return { status: "skipped", reason: "no-delivery-order" };
237
- }
238
- // Prefer the delivery order's despatchWarehouseId when Floriday supplies it.
239
- const effectiveWarehouseId = deliveryCtx.despatchWarehouseId || warehouseId;
240
- const { payload, warnings } = buildFulfillmentPayload(order.data, effectiveWarehouseId, deliveryCtx);
241
- if (warehouseFallback && !deliveryCtx.despatchWarehouseId)
242
- warnings.push(warehouseFallback);
243
- // Increment attempts.
244
- const { data: existing } = await supabase
245
- .from("floriday_auto_fulfillment_log")
246
- .select("attempts")
247
- .eq("connection_id", connectionId)
248
- .eq("sales_order_id", salesOrderId)
249
- .maybeSingle();
250
- const attempts = Number(existing?.attempts ?? 0) + 1;
251
- const env = (conn.environment === "production" || conn.environment === "live" ? "live" : "staging");
252
- const result = await florydayWrite(supabase, env, {
253
- module: "warehouse",
254
- action: "add-fulfillment-order",
255
- method: "POST",
256
- path: "/fulfillment-orders",
257
- referenceId: salesOrderId,
258
- body: payload,
259
- }, null);
260
- if (!result.ok) {
261
- await upsertLog(supabase, connectionId, salesOrderId, {
262
- status: "failed",
263
- attempts,
264
- error: (result.error ?? `HTTP ${result.status}`).slice(0, 500),
265
- reason: warnings.join(",") || null,
266
- });
267
- return { status: "failed", reason: result.error };
268
- }
269
- const fulfillmentOrderId = String(result.data?.fulfillmentOrderId ?? result.data?.id ?? payload.fulfillmentOrderId ?? "");
270
- await upsertLog(supabase, connectionId, salesOrderId, {
271
- status: "created",
272
- attempts,
273
- fulfillment_order_id: fulfillmentOrderId || null,
274
- error: null,
275
- reason: warnings.join(",") || null,
276
- });
277
- return { status: "created", fulfillmentOrderId };
278
- }
279
- export async function processRecentSalesOrders(supabase, connectionId, sinceIso) {
280
- // 1) Recently synced / updated sales orders in this cycle.
281
- const { data: recent } = await supabase
282
- .from("floriday_salesorders_cache")
283
- .select("connection_id, floriday_id, status, is_deleted, data, updated_at")
284
- .eq("connection_id", connectionId)
285
- .gte("updated_at", sinceIso)
286
- .limit(200);
287
- const rowMap = new Map();
288
- for (const r of (recent ?? [])) {
289
- rowMap.set(r.floriday_id, r);
290
- }
291
- // 2) Backlog: sales orders that never got a log row, or were previously
292
- // skipped/failed because the preferred warehouse wasn't set yet.
293
- const { data: allOrders } = await supabase
294
- .from("floriday_salesorders_cache")
295
- .select("connection_id, floriday_id, status, is_deleted, data")
296
- .eq("connection_id", connectionId)
297
- .eq("is_deleted", false)
298
- .limit(500);
299
- const orderList = allOrders ?? [];
300
- if (orderList.length > 0) {
301
- const ids = orderList.map((o) => o.floriday_id);
302
- const { data: logs } = await supabase
303
- .from("floriday_auto_fulfillment_log")
304
- .select("sales_order_id, status, reason")
305
- .eq("connection_id", connectionId)
306
- .in("sales_order_id", ids);
307
- const logMap = new Map();
308
- for (const l of (logs ?? [])) {
309
- logMap.set(l.sales_order_id, { status: l.status, reason: l.reason });
310
- }
311
- for (const o of orderList) {
312
- const existing = logMap.get(o.floriday_id);
313
- if (!existing) {
314
- rowMap.set(o.floriday_id, o);
315
- continue;
316
- }
317
- if (existing.status === "failed") {
318
- rowMap.set(o.floriday_id, o);
319
- continue;
320
- }
321
- if (existing.status === "skipped" &&
322
- (existing.reason === "no-preferred-warehouse" ||
323
- existing.reason === "no-warehouse" ||
324
- existing.reason === "no-delivery-order")) {
325
- rowMap.set(o.floriday_id, o);
326
- }
327
- }
328
- }
329
- const rows = Array.from(rowMap.values());
330
- let created = 0;
331
- let failed = 0;
332
- let skipped = 0;
333
- for (const row of rows) {
334
- try {
335
- const r = await processOrderForAutoFulfillment(supabase, row);
336
- if (r.status === "created")
337
- created++;
338
- else if (r.status === "failed")
339
- failed++;
340
- else
341
- skipped++;
342
- }
343
- catch (err) {
344
- failed++;
345
- await upsertLog(supabase, row.connection_id, row.floriday_id, {
346
- status: "failed",
347
- error: err.message?.slice(0, 500) ?? "unknown error",
348
- });
349
- }
350
- }
351
- return { processed: rows.length, created, failed, skipped };
352
- }
@@ -1,14 +0,0 @@
1
- type SyncAction = "commit" | "cancel" | null;
2
- /** Welke Floriday-actie hoort bij onze opgeslagen status? */
3
- export declare function actionForStatus(status: string): SyncAction;
4
- export interface StatusPushResult {
5
- ok: boolean;
6
- processed: number;
7
- pushed: number;
8
- skipped: number;
9
- failed: number;
10
- errors: string[];
11
- }
12
- export declare function pushOrderStatusesToFloriday(limit?: number): Promise<StatusPushResult>;
13
- export {};
14
- //# sourceMappingURL=floriday-status-sync.server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"floriday-status-sync.server.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-status-sync.server.ts"],"names":[],"mappings":"AAWA,KAAK,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC;AAW7C,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAM1D;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,SAAM,GACV,OAAO,CAAC,gBAAgB,CAAC,CAuH3B"}
@@ -1,130 +0,0 @@
1
- // Statuswijzigingen uit ons ERP doorzetten naar Floriday.
2
- //
3
- // Floriday kent voor een verkooporder maar twee schrijfacties op de status:
4
- // PATCH /sales-orders/{id}/commit (ACCEPTED -> COMMITTED)
5
- // PATCH /sales-orders/{id}/cancel (ACCEPTED -> CANCELLED)
6
- // Verzending/levering gaat in Floriday niet via de verkooporder maar via
7
- // fulfillment-orders (afleverbrieven); dat blijft de bestaande route.
8
- //
9
- // Geen omgevingswaarden in deze module: environment en sleutels komen uit
10
- // floriday_connections / de centrale auth-module.
11
- const CANCEL_STATUSES = new Set([
12
- "geannuleerd",
13
- "cancelled",
14
- "canceled",
15
- "vervallen",
16
- "afgewezen",
17
- "rejected",
18
- ]);
19
- /** Welke Floriday-actie hoort bij onze opgeslagen status? */
20
- export function actionForStatus(status) {
21
- const s = String(status ?? "").trim().toLowerCase();
22
- if (CANCEL_STATUSES.has(s))
23
- return "cancel";
24
- // Alle overige werkstatussen betekenen: wij gaan hem leveren.
25
- if (s.length === 0)
26
- return null;
27
- return "commit";
28
- }
29
- export async function pushOrderStatusesToFloriday(limit = 100) {
30
- const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
31
- const { florydayWrite } = await import("./floriday-gateway.server.js");
32
- const result = {
33
- ok: true,
34
- processed: 0,
35
- pushed: 0,
36
- skipped: 0,
37
- failed: 0,
38
- errors: [],
39
- };
40
- const { data: queue, error: qErr } = await supabaseAdmin
41
- .from("floriday_status_sync_queue")
42
- .select("order_id, floriday_sales_order_id, target_status, attempts")
43
- .eq("state", "pending")
44
- .order("requested_at", { ascending: true })
45
- .limit(Math.min(500, Math.max(1, limit)));
46
- if (qErr)
47
- throw new Error(`statuswachtrij lezen faalde: ${qErr.message}`);
48
- if (!queue || queue.length === 0)
49
- return result;
50
- // Actieve Floriday-connectie bepaalt de omgeving. Ontbreekt die, dan stoppen
51
- // we bewust met een duidelijke fout in plaats van een aanname.
52
- const { data: conn } = await supabaseAdmin
53
- .from("floriday_connections")
54
- .select("environment")
55
- .eq("is_active", true)
56
- .limit(1)
57
- .maybeSingle();
58
- const environment = conn?.environment
59
- ? String(conn.environment).toLowerCase() === "production" ||
60
- String(conn.environment).toLowerCase() === "live"
61
- ? "live"
62
- : "staging"
63
- : null;
64
- if (!environment) {
65
- throw new Error("Geen actieve Floriday-connectie gevonden; statuswijzigingen worden niet verstuurd.");
66
- }
67
- const salesOrderIds = queue.map((q) => String(q.floriday_sales_order_id));
68
- const { data: cached } = await supabaseAdmin
69
- .from("floriday_salesorders_cache")
70
- .select("sales_order_id, data")
71
- .in("sales_order_id", salesOrderIds);
72
- const floridayStatusById = new Map();
73
- for (const row of cached ?? []) {
74
- const status = String((row.data ?? {})?.status ?? "").toUpperCase();
75
- floridayStatusById.set(String(row.sales_order_id), status);
76
- }
77
- for (const item of queue) {
78
- result.processed += 1;
79
- const orderId = String(item.order_id);
80
- const salesOrderId = String(item.floriday_sales_order_id);
81
- const action = actionForStatus(String(item.target_status ?? ""));
82
- const currentFloriday = floridayStatusById.get(salesOrderId) ?? "";
83
- const markDone = async (state, error) => {
84
- await supabaseAdmin.from("floriday_status_sync_queue")
85
- .update({
86
- state,
87
- error,
88
- attempts: Number(item.attempts ?? 0) + 1,
89
- processed_at: new Date().toISOString(),
90
- })
91
- .eq("order_id", orderId);
92
- };
93
- if (!action) {
94
- result.skipped += 1;
95
- await markDone("skipped", "Geen Floriday-actie voor deze status");
96
- continue;
97
- }
98
- // Floriday accepteert commit/cancel alleen vanuit ACCEPTED. Staat de order
99
- // daar al verder, dan is er niets te doen (en is dat geen fout).
100
- if (currentFloriday && currentFloriday !== "ACCEPTED") {
101
- const alreadyThere = (action === "cancel" && currentFloriday === "CANCELLED") ||
102
- (action === "commit" && currentFloriday === "COMMITTED");
103
- result.skipped += 1;
104
- await markDone(alreadyThere ? "done" : "skipped", alreadyThere
105
- ? null
106
- : `Floriday-status is ${currentFloriday}; ${action} is daar niet meer toegestaan`);
107
- continue;
108
- }
109
- const res = await florydayWrite(supabaseAdmin, environment, {
110
- module: "sales",
111
- action: `sales-order-${action}`,
112
- method: "PATCH",
113
- path: `/sales-orders/${encodeURIComponent(salesOrderId)}/${action}`,
114
- referenceId: salesOrderId,
115
- }, null);
116
- if (res.ok) {
117
- result.pushed += 1;
118
- await markDone("done", null);
119
- }
120
- else {
121
- result.failed += 1;
122
- const msg = `${salesOrderId}: ${res.error ?? `HTTP ${res.status}`}`;
123
- result.errors.push(msg);
124
- await markDone("failed", msg.slice(0, 500));
125
- }
126
- }
127
- if (result.failed > 0)
128
- result.ok = false;
129
- return result;
130
- }