@open-mercato/core 0.6.7-develop.6669.1.40b669666b → 0.6.7-develop.6670.1.4efa7961c6

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 (473) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/inventory_balance/index.js +21 -0
  3. package/dist/generated/entities/inventory_balance/index.js.map +7 -0
  4. package/dist/generated/entities/inventory_lot/index.js +19 -0
  5. package/dist/generated/entities/inventory_lot/index.js.map +7 -0
  6. package/dist/generated/entities/inventory_movement/index.js +35 -0
  7. package/dist/generated/entities/inventory_movement/index.js.map +7 -0
  8. package/dist/generated/entities/inventory_reservation/index.js +23 -0
  9. package/dist/generated/entities/inventory_reservation/index.js.map +7 -0
  10. package/dist/generated/entities/product_inventory_profile/index.js +21 -0
  11. package/dist/generated/entities/product_inventory_profile/index.js.map +7 -0
  12. package/dist/generated/entities/sales_order_warehouse_assignment/index.js +11 -0
  13. package/dist/generated/entities/sales_order_warehouse_assignment/index.js.map +7 -0
  14. package/dist/generated/entities/warehouse/index.js +25 -0
  15. package/dist/generated/entities/warehouse/index.js.map +7 -0
  16. package/dist/generated/entities/warehouse_location/index.js +21 -0
  17. package/dist/generated/entities/warehouse_location/index.js.map +7 -0
  18. package/dist/generated/entities/warehouse_zone/index.js +11 -0
  19. package/dist/generated/entities/warehouse_zone/index.js.map +7 -0
  20. package/dist/generated/entities.ids.generated.js +12 -0
  21. package/dist/generated/entities.ids.generated.js.map +2 -2
  22. package/dist/generated/entity-fields-registry.js +98 -0
  23. package/dist/generated/entity-fields-registry.js.map +2 -2
  24. package/dist/modules/auth/backend/roles/page.js +12 -4
  25. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  26. package/dist/modules/auth/lib/backendChrome.js +1 -0
  27. package/dist/modules/auth/lib/backendChrome.js.map +2 -2
  28. package/dist/modules/auth/services/rbacService.js +16 -17
  29. package/dist/modules/auth/services/rbacService.js.map +2 -2
  30. package/dist/modules/catalog/api/products/route.js +3 -0
  31. package/dist/modules/catalog/api/products/route.js.map +2 -2
  32. package/dist/modules/catalog/api/variants/route.js +3 -0
  33. package/dist/modules/catalog/api/variants/route.js.map +2 -2
  34. package/dist/modules/query_index/lib/engine.js +6 -6
  35. package/dist/modules/query_index/lib/engine.js.map +2 -2
  36. package/dist/modules/sales/api/documents/factory.js +1 -0
  37. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  38. package/dist/modules/sales/commands/documents.js +53 -0
  39. package/dist/modules/sales/commands/documents.js.map +2 -2
  40. package/dist/modules/sales/components/documents/ItemsSection.js +51 -2
  41. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  42. package/dist/modules/sales/events.js +2 -0
  43. package/dist/modules/sales/events.js.map +2 -2
  44. package/dist/modules/sales/widgets/injection/order-items-context.js +11 -0
  45. package/dist/modules/sales/widgets/injection/order-items-context.js.map +7 -0
  46. package/dist/modules/wms/acl.js +18 -0
  47. package/dist/modules/wms/acl.js.map +7 -0
  48. package/dist/modules/wms/analytics.js +11 -0
  49. package/dist/modules/wms/analytics.js.map +7 -0
  50. package/dist/modules/wms/api/dashboard/operational/route.js +80 -0
  51. package/dist/modules/wms/api/dashboard/operational/route.js.map +7 -0
  52. package/dist/modules/wms/api/interceptors.js +90 -0
  53. package/dist/modules/wms/api/interceptors.js.map +7 -0
  54. package/dist/modules/wms/api/inventory/adjust/route.js +51 -0
  55. package/dist/modules/wms/api/inventory/adjust/route.js.map +7 -0
  56. package/dist/modules/wms/api/inventory/allocate/route.js +51 -0
  57. package/dist/modules/wms/api/inventory/allocate/route.js.map +7 -0
  58. package/dist/modules/wms/api/inventory/balances/route.js +172 -0
  59. package/dist/modules/wms/api/inventory/balances/route.js.map +7 -0
  60. package/dist/modules/wms/api/inventory/cycle-count/route.js +52 -0
  61. package/dist/modules/wms/api/inventory/cycle-count/route.js.map +7 -0
  62. package/dist/modules/wms/api/inventory/helpers.js +113 -0
  63. package/dist/modules/wms/api/inventory/helpers.js.map +7 -0
  64. package/dist/modules/wms/api/inventory/import/apply/route.js +46 -0
  65. package/dist/modules/wms/api/inventory/import/apply/route.js.map +7 -0
  66. package/dist/modules/wms/api/inventory/import/helpers.js +195 -0
  67. package/dist/modules/wms/api/inventory/import/helpers.js.map +7 -0
  68. package/dist/modules/wms/api/inventory/import/template/route.js +32 -0
  69. package/dist/modules/wms/api/inventory/import/template/route.js.map +7 -0
  70. package/dist/modules/wms/api/inventory/import/validate/route.js +54 -0
  71. package/dist/modules/wms/api/inventory/import/validate/route.js.map +7 -0
  72. package/dist/modules/wms/api/inventory/move/route.js +51 -0
  73. package/dist/modules/wms/api/inventory/move/route.js.map +7 -0
  74. package/dist/modules/wms/api/inventory/movements/route.js +164 -0
  75. package/dist/modules/wms/api/inventory/movements/route.js.map +7 -0
  76. package/dist/modules/wms/api/inventory/receive/route.js +50 -0
  77. package/dist/modules/wms/api/inventory/receive/route.js.map +7 -0
  78. package/dist/modules/wms/api/inventory/release/route.js +44 -0
  79. package/dist/modules/wms/api/inventory/release/route.js.map +7 -0
  80. package/dist/modules/wms/api/inventory/reservations/route.js +128 -0
  81. package/dist/modules/wms/api/inventory/reservations/route.js.map +7 -0
  82. package/dist/modules/wms/api/inventory/reserve/route.js +59 -0
  83. package/dist/modules/wms/api/inventory/reserve/route.js.map +7 -0
  84. package/dist/modules/wms/api/inventory-profiles/route.js +178 -0
  85. package/dist/modules/wms/api/inventory-profiles/route.js.map +7 -0
  86. package/dist/modules/wms/api/listEnrichers.js +181 -0
  87. package/dist/modules/wms/api/listEnrichers.js.map +7 -0
  88. package/dist/modules/wms/api/listSearch.js +77 -0
  89. package/dist/modules/wms/api/listSearch.js.map +7 -0
  90. package/dist/modules/wms/api/locations/route.js +172 -0
  91. package/dist/modules/wms/api/locations/route.js.map +7 -0
  92. package/dist/modules/wms/api/lots/route.js +204 -0
  93. package/dist/modules/wms/api/lots/route.js.map +7 -0
  94. package/dist/modules/wms/api/openapi.js +27 -0
  95. package/dist/modules/wms/api/openapi.js.map +7 -0
  96. package/dist/modules/wms/api/sales-orders/[salesOrderId]/re-run-reservation/route.js +54 -0
  97. package/dist/modules/wms/api/sales-orders/[salesOrderId]/re-run-reservation/route.js.map +7 -0
  98. package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js +279 -0
  99. package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js.map +7 -0
  100. package/dist/modules/wms/api/sales-orders/assign-warehouse/route.js +56 -0
  101. package/dist/modules/wms/api/sales-orders/assign-warehouse/route.js.map +7 -0
  102. package/dist/modules/wms/api/sales-orders/unassign-warehouse/route.js +43 -0
  103. package/dist/modules/wms/api/sales-orders/unassign-warehouse/route.js.map +7 -0
  104. package/dist/modules/wms/api/warehouses/route.js +181 -0
  105. package/dist/modules/wms/api/warehouses/route.js.map +7 -0
  106. package/dist/modules/wms/api/zones/route.js +159 -0
  107. package/dist/modules/wms/api/zones/route.js.map +7 -0
  108. package/dist/modules/wms/backend/config/wms/page.js +9 -0
  109. package/dist/modules/wms/backend/config/wms/page.js.map +7 -0
  110. package/dist/modules/wms/backend/config/wms/page.meta.js +18 -0
  111. package/dist/modules/wms/backend/config/wms/page.meta.js.map +7 -0
  112. package/dist/modules/wms/backend/page.js +9 -0
  113. package/dist/modules/wms/backend/page.js.map +7 -0
  114. package/dist/modules/wms/backend/page.meta.js +16 -0
  115. package/dist/modules/wms/backend/page.meta.js.map +7 -0
  116. package/dist/modules/wms/backend/wms/inventory/page.js +9 -0
  117. package/dist/modules/wms/backend/wms/inventory/page.js.map +7 -0
  118. package/dist/modules/wms/backend/wms/inventory/page.meta.js +18 -0
  119. package/dist/modules/wms/backend/wms/inventory/page.meta.js.map +7 -0
  120. package/dist/modules/wms/backend/wms/location/[id]/page.js +9 -0
  121. package/dist/modules/wms/backend/wms/location/[id]/page.js.map +7 -0
  122. package/dist/modules/wms/backend/wms/location/[id]/page.meta.js +18 -0
  123. package/dist/modules/wms/backend/wms/location/[id]/page.meta.js.map +7 -0
  124. package/dist/modules/wms/backend/wms/locations/page.js +10 -0
  125. package/dist/modules/wms/backend/wms/locations/page.js.map +7 -0
  126. package/dist/modules/wms/backend/wms/locations/page.meta.js +18 -0
  127. package/dist/modules/wms/backend/wms/locations/page.meta.js.map +7 -0
  128. package/dist/modules/wms/backend/wms/lot/[id]/page.js +9 -0
  129. package/dist/modules/wms/backend/wms/lot/[id]/page.js.map +7 -0
  130. package/dist/modules/wms/backend/wms/lot/[id]/page.meta.js +18 -0
  131. package/dist/modules/wms/backend/wms/lot/[id]/page.meta.js.map +7 -0
  132. package/dist/modules/wms/backend/wms/lots/page.js +9 -0
  133. package/dist/modules/wms/backend/wms/lots/page.js.map +7 -0
  134. package/dist/modules/wms/backend/wms/lots/page.meta.js +18 -0
  135. package/dist/modules/wms/backend/wms/lots/page.meta.js.map +7 -0
  136. package/dist/modules/wms/backend/wms/movements/page.js +22 -0
  137. package/dist/modules/wms/backend/wms/movements/page.js.map +7 -0
  138. package/dist/modules/wms/backend/wms/movements/page.meta.js +18 -0
  139. package/dist/modules/wms/backend/wms/movements/page.meta.js.map +7 -0
  140. package/dist/modules/wms/backend/wms/reservations/page.js +23 -0
  141. package/dist/modules/wms/backend/wms/reservations/page.js.map +7 -0
  142. package/dist/modules/wms/backend/wms/reservations/page.meta.js +18 -0
  143. package/dist/modules/wms/backend/wms/reservations/page.meta.js.map +7 -0
  144. package/dist/modules/wms/backend/wms/sku/[id]/page.js +9 -0
  145. package/dist/modules/wms/backend/wms/sku/[id]/page.js.map +7 -0
  146. package/dist/modules/wms/backend/wms/sku/[id]/page.meta.js +18 -0
  147. package/dist/modules/wms/backend/wms/sku/[id]/page.meta.js.map +7 -0
  148. package/dist/modules/wms/backend/wms/warehouses/page.js +10 -0
  149. package/dist/modules/wms/backend/wms/warehouses/page.js.map +7 -0
  150. package/dist/modules/wms/backend/wms/warehouses/page.meta.js +18 -0
  151. package/dist/modules/wms/backend/wms/warehouses/page.meta.js.map +7 -0
  152. package/dist/modules/wms/backend/wms/zones/page.js +10 -0
  153. package/dist/modules/wms/backend/wms/zones/page.js.map +7 -0
  154. package/dist/modules/wms/backend/wms/zones/page.meta.js +18 -0
  155. package/dist/modules/wms/backend/wms/zones/page.meta.js.map +7 -0
  156. package/dist/modules/wms/ce.js +80 -0
  157. package/dist/modules/wms/ce.js.map +7 -0
  158. package/dist/modules/wms/cli.js +83 -0
  159. package/dist/modules/wms/cli.js.map +7 -0
  160. package/dist/modules/wms/commands/configuration.js +1519 -0
  161. package/dist/modules/wms/commands/configuration.js.map +7 -0
  162. package/dist/modules/wms/commands/index.js +4 -0
  163. package/dist/modules/wms/commands/index.js.map +7 -0
  164. package/dist/modules/wms/commands/inventory-actions.js +1539 -0
  165. package/dist/modules/wms/commands/inventory-actions.js.map +7 -0
  166. package/dist/modules/wms/commands/sales-order-assignment.js +277 -0
  167. package/dist/modules/wms/commands/sales-order-assignment.js.map +7 -0
  168. package/dist/modules/wms/commands/shared.js +82 -0
  169. package/dist/modules/wms/commands/shared.js.map +7 -0
  170. package/dist/modules/wms/components/backend/AdjustInventoryDialog.js +755 -0
  171. package/dist/modules/wms/components/backend/AdjustInventoryDialog.js.map +7 -0
  172. package/dist/modules/wms/components/backend/ChangeLotStatusDialog.js +269 -0
  173. package/dist/modules/wms/components/backend/ChangeLotStatusDialog.js.map +7 -0
  174. package/dist/modules/wms/components/backend/CycleCountWizardDialog.js +1783 -0
  175. package/dist/modules/wms/components/backend/CycleCountWizardDialog.js.map +7 -0
  176. package/dist/modules/wms/components/backend/ImportInventoryDialog.js +766 -0
  177. package/dist/modules/wms/components/backend/ImportInventoryDialog.js.map +7 -0
  178. package/dist/modules/wms/components/backend/InventoryOperationsSection.js +119 -0
  179. package/dist/modules/wms/components/backend/InventoryOperationsSection.js.map +7 -0
  180. package/dist/modules/wms/components/backend/LocationEditDialog.js +140 -0
  181. package/dist/modules/wms/components/backend/LocationEditDialog.js.map +7 -0
  182. package/dist/modules/wms/components/backend/MoveInventoryDialog.js +791 -0
  183. package/dist/modules/wms/components/backend/MoveInventoryDialog.js.map +7 -0
  184. package/dist/modules/wms/components/backend/ReceiveInventoryDialog.js +656 -0
  185. package/dist/modules/wms/components/backend/ReceiveInventoryDialog.js.map +7 -0
  186. package/dist/modules/wms/components/backend/ReleaseReservationDialog.js +344 -0
  187. package/dist/modules/wms/components/backend/ReleaseReservationDialog.js.map +7 -0
  188. package/dist/modules/wms/components/backend/ReserveInventoryDialog.js +475 -0
  189. package/dist/modules/wms/components/backend/ReserveInventoryDialog.js.map +7 -0
  190. package/dist/modules/wms/components/backend/WmsConfigurationPage.js +1112 -0
  191. package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +7 -0
  192. package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +908 -0
  193. package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +7 -0
  194. package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +1015 -0
  195. package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +7 -0
  196. package/dist/modules/wms/components/backend/WmsLotDetailPage.js +1049 -0
  197. package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +7 -0
  198. package/dist/modules/wms/components/backend/WmsLotsListPage.js +297 -0
  199. package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +7 -0
  200. package/dist/modules/wms/components/backend/WmsOperationalDashboardPage.js +757 -0
  201. package/dist/modules/wms/components/backend/WmsOperationalDashboardPage.js.map +7 -0
  202. package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +975 -0
  203. package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +7 -0
  204. package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +710 -0
  205. package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +7 -0
  206. package/dist/modules/wms/components/backend/useWmsInventoryMutationAccess.js +79 -0
  207. package/dist/modules/wms/components/backend/useWmsInventoryMutationAccess.js.map +7 -0
  208. package/dist/modules/wms/components/backend/useWmsInventoryScopeFromSearchParams.js +24 -0
  209. package/dist/modules/wms/components/backend/useWmsInventoryScopeFromSearchParams.js.map +7 -0
  210. package/dist/modules/wms/components/backend/wmsLookupLoaders.js +55 -0
  211. package/dist/modules/wms/components/backend/wmsLookupLoaders.js.map +7 -0
  212. package/dist/modules/wms/data/enrichers.js +501 -0
  213. package/dist/modules/wms/data/enrichers.js.map +7 -0
  214. package/dist/modules/wms/data/entities.js +467 -0
  215. package/dist/modules/wms/data/entities.js.map +7 -0
  216. package/dist/modules/wms/data/validators.js +399 -0
  217. package/dist/modules/wms/data/validators.js.map +7 -0
  218. package/dist/modules/wms/di.js +27 -0
  219. package/dist/modules/wms/di.js.map +7 -0
  220. package/dist/modules/wms/events.js +42 -0
  221. package/dist/modules/wms/events.js.map +7 -0
  222. package/dist/modules/wms/index.js +17 -0
  223. package/dist/modules/wms/index.js.map +7 -0
  224. package/dist/modules/wms/lib/catalogInventoryProfileIntent.js +54 -0
  225. package/dist/modules/wms/lib/catalogInventoryProfileIntent.js.map +7 -0
  226. package/dist/modules/wms/lib/catalogInventoryProfileSync.js +144 -0
  227. package/dist/modules/wms/lib/catalogInventoryProfileSync.js.map +7 -0
  228. package/dist/modules/wms/lib/expiry.js +29 -0
  229. package/dist/modules/wms/lib/expiry.js.map +7 -0
  230. package/dist/modules/wms/lib/flashMutationError.js +51 -0
  231. package/dist/modules/wms/lib/flashMutationError.js.map +7 -0
  232. package/dist/modules/wms/lib/inventoryDisplayUi.js +188 -0
  233. package/dist/modules/wms/lib/inventoryDisplayUi.js.map +7 -0
  234. package/dist/modules/wms/lib/inventoryIdempotency.js +37 -0
  235. package/dist/modules/wms/lib/inventoryIdempotency.js.map +7 -0
  236. package/dist/modules/wms/lib/inventoryImportCsv.js +173 -0
  237. package/dist/modules/wms/lib/inventoryImportCsv.js.map +7 -0
  238. package/dist/modules/wms/lib/inventoryImportService.js +468 -0
  239. package/dist/modules/wms/lib/inventoryImportService.js.map +7 -0
  240. package/dist/modules/wms/lib/inventoryMutationUi.js +25 -0
  241. package/dist/modules/wms/lib/inventoryMutationUi.js.map +7 -0
  242. package/dist/modules/wms/lib/inventoryPolicy.js +61 -0
  243. package/dist/modules/wms/lib/inventoryPolicy.js.map +7 -0
  244. package/dist/modules/wms/lib/inventoryReconciliation.js +193 -0
  245. package/dist/modules/wms/lib/inventoryReconciliation.js.map +7 -0
  246. package/dist/modules/wms/lib/inventoryTrackingValidation.js +13 -0
  247. package/dist/modules/wms/lib/inventoryTrackingValidation.js.map +7 -0
  248. package/dist/modules/wms/lib/loadOperationalDashboard.js +580 -0
  249. package/dist/modules/wms/lib/loadOperationalDashboard.js.map +7 -0
  250. package/dist/modules/wms/lib/lowStockBalanceFilter.js +49 -0
  251. package/dist/modules/wms/lib/lowStockBalanceFilter.js.map +7 -0
  252. package/dist/modules/wms/lib/primaryWarehousePolicy.js +32 -0
  253. package/dist/modules/wms/lib/primaryWarehousePolicy.js.map +7 -0
  254. package/dist/modules/wms/lib/roleFeatures.js +30 -0
  255. package/dist/modules/wms/lib/roleFeatures.js.map +7 -0
  256. package/dist/modules/wms/lib/salesOrderInventoryAutomation.js +291 -0
  257. package/dist/modules/wms/lib/salesOrderInventoryAutomation.js.map +7 -0
  258. package/dist/modules/wms/lib/salesOrderWarehouseAssignment.js +54 -0
  259. package/dist/modules/wms/lib/salesOrderWarehouseAssignment.js.map +7 -0
  260. package/dist/modules/wms/lib/wmsIntegrationToggles.js +71 -0
  261. package/dist/modules/wms/lib/wmsIntegrationToggles.js.map +7 -0
  262. package/dist/modules/wms/migrations/Migration20260428110546.js +78 -0
  263. package/dist/modules/wms/migrations/Migration20260428110546.js.map +7 -0
  264. package/dist/modules/wms/migrations/Migration20260527120000.js +15 -0
  265. package/dist/modules/wms/migrations/Migration20260527120000.js.map +7 -0
  266. package/dist/modules/wms/migrations/Migration20260527140000.js +37 -0
  267. package/dist/modules/wms/migrations/Migration20260527140000.js.map +7 -0
  268. package/dist/modules/wms/migrations/Migration20260613120000.js +23 -0
  269. package/dist/modules/wms/migrations/Migration20260613120000.js.map +7 -0
  270. package/dist/modules/wms/migrations/Migration20260616090000.js +13 -0
  271. package/dist/modules/wms/migrations/Migration20260616090000.js.map +7 -0
  272. package/dist/modules/wms/migrations/Migration20260707180000.js +15 -0
  273. package/dist/modules/wms/migrations/Migration20260707180000.js.map +7 -0
  274. package/dist/modules/wms/notifications.client.js +18 -0
  275. package/dist/modules/wms/notifications.client.js.map +7 -0
  276. package/dist/modules/wms/notifications.js +53 -0
  277. package/dist/modules/wms/notifications.js.map +7 -0
  278. package/dist/modules/wms/search.js +196 -0
  279. package/dist/modules/wms/search.js.map +7 -0
  280. package/dist/modules/wms/setup.js +30 -0
  281. package/dist/modules/wms/setup.js.map +7 -0
  282. package/dist/modules/wms/subscribers/low-stock-notification.js +40 -0
  283. package/dist/modules/wms/subscribers/low-stock-notification.js.map +7 -0
  284. package/dist/modules/wms/subscribers/reservation-shortfall-notification.js +69 -0
  285. package/dist/modules/wms/subscribers/reservation-shortfall-notification.js.map +7 -0
  286. package/dist/modules/wms/subscribers/sales-order-cancelled-release.js +14 -0
  287. package/dist/modules/wms/subscribers/sales-order-cancelled-release.js.map +7 -0
  288. package/dist/modules/wms/subscribers/sales-order-confirmed-reserve.js +14 -0
  289. package/dist/modules/wms/subscribers/sales-order-confirmed-reserve.js.map +7 -0
  290. package/dist/modules/wms/translations.js +10 -0
  291. package/dist/modules/wms/translations.js.map +7 -0
  292. package/dist/modules/wms/vector.js +9 -0
  293. package/dist/modules/wms/vector.js.map +7 -0
  294. package/dist/modules/wms/widgets/injection/catalog-inventory-profile/widget.js +200 -0
  295. package/dist/modules/wms/widgets/injection/catalog-inventory-profile/widget.js.map +7 -0
  296. package/dist/modules/wms/widgets/injection/order-items-stock-column/widget.js +104 -0
  297. package/dist/modules/wms/widgets/injection/order-items-stock-column/widget.js.map +7 -0
  298. package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.client.js +389 -0
  299. package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.client.js.map +7 -0
  300. package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.js +16 -0
  301. package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.js.map +7 -0
  302. package/dist/modules/wms/widgets/injection-table.js +36 -0
  303. package/dist/modules/wms/widgets/injection-table.js.map +7 -0
  304. package/dist/modules/wms/widgets/notifications/WmsLowStockRenderer.js +150 -0
  305. package/dist/modules/wms/widgets/notifications/WmsLowStockRenderer.js.map +7 -0
  306. package/dist/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.js +186 -0
  307. package/dist/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.js.map +7 -0
  308. package/dist/modules/wms/widgets/notifications/index.js +7 -0
  309. package/dist/modules/wms/widgets/notifications/index.js.map +7 -0
  310. package/generated/entities/inventory_balance/index.ts +9 -0
  311. package/generated/entities/inventory_lot/index.ts +8 -0
  312. package/generated/entities/inventory_movement/index.ts +16 -0
  313. package/generated/entities/inventory_reservation/index.ts +10 -0
  314. package/generated/entities/product_inventory_profile/index.ts +9 -0
  315. package/generated/entities/sales_order_warehouse_assignment/index.ts +4 -0
  316. package/generated/entities/warehouse/index.ts +11 -0
  317. package/generated/entities/warehouse_location/index.ts +9 -0
  318. package/generated/entities/warehouse_zone/index.ts +4 -0
  319. package/generated/entities.ids.generated.ts +12 -0
  320. package/generated/entity-fields-registry.ts +98 -0
  321. package/package.json +7 -7
  322. package/src/modules/auth/backend/roles/page.tsx +13 -4
  323. package/src/modules/auth/i18n/de.json +2 -0
  324. package/src/modules/auth/i18n/en.json +2 -0
  325. package/src/modules/auth/i18n/es.json +2 -0
  326. package/src/modules/auth/i18n/pl.json +2 -0
  327. package/src/modules/auth/lib/backendChrome.tsx +1 -0
  328. package/src/modules/auth/services/rbacService.ts +25 -21
  329. package/src/modules/catalog/api/products/route.ts +3 -0
  330. package/src/modules/catalog/api/variants/route.ts +3 -0
  331. package/src/modules/query_index/lib/engine.ts +18 -6
  332. package/src/modules/sales/api/documents/factory.ts +1 -0
  333. package/src/modules/sales/commands/documents.ts +71 -0
  334. package/src/modules/sales/components/documents/ItemsSection.tsx +58 -0
  335. package/src/modules/sales/events.ts +2 -0
  336. package/src/modules/sales/widgets/injection/order-items-context.ts +15 -0
  337. package/src/modules/wms/acl.ts +14 -0
  338. package/src/modules/wms/analytics.ts +9 -0
  339. package/src/modules/wms/api/dashboard/operational/route.ts +83 -0
  340. package/src/modules/wms/api/interceptors.ts +108 -0
  341. package/src/modules/wms/api/inventory/adjust/route.ts +50 -0
  342. package/src/modules/wms/api/inventory/allocate/route.ts +50 -0
  343. package/src/modules/wms/api/inventory/balances/route.ts +178 -0
  344. package/src/modules/wms/api/inventory/cycle-count/route.ts +51 -0
  345. package/src/modules/wms/api/inventory/helpers.ts +128 -0
  346. package/src/modules/wms/api/inventory/import/apply/route.ts +47 -0
  347. package/src/modules/wms/api/inventory/import/helpers.ts +223 -0
  348. package/src/modules/wms/api/inventory/import/template/route.ts +31 -0
  349. package/src/modules/wms/api/inventory/import/validate/route.ts +56 -0
  350. package/src/modules/wms/api/inventory/move/route.ts +50 -0
  351. package/src/modules/wms/api/inventory/movements/route.ts +164 -0
  352. package/src/modules/wms/api/inventory/receive/route.ts +49 -0
  353. package/src/modules/wms/api/inventory/release/route.ts +43 -0
  354. package/src/modules/wms/api/inventory/reservations/route.ts +128 -0
  355. package/src/modules/wms/api/inventory/reserve/route.ts +59 -0
  356. package/src/modules/wms/api/inventory-profiles/route.ts +177 -0
  357. package/src/modules/wms/api/listEnrichers.ts +312 -0
  358. package/src/modules/wms/api/listSearch.ts +121 -0
  359. package/src/modules/wms/api/locations/route.ts +171 -0
  360. package/src/modules/wms/api/lots/route.ts +205 -0
  361. package/src/modules/wms/api/openapi.ts +28 -0
  362. package/src/modules/wms/api/sales-orders/[salesOrderId]/re-run-reservation/route.ts +58 -0
  363. package/src/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.ts +306 -0
  364. package/src/modules/wms/api/sales-orders/assign-warehouse/route.ts +57 -0
  365. package/src/modules/wms/api/sales-orders/unassign-warehouse/route.ts +43 -0
  366. package/src/modules/wms/api/warehouses/route.ts +181 -0
  367. package/src/modules/wms/api/zones/route.ts +158 -0
  368. package/src/modules/wms/backend/config/wms/page.meta.ts +14 -0
  369. package/src/modules/wms/backend/config/wms/page.tsx +5 -0
  370. package/src/modules/wms/backend/page.meta.ts +12 -0
  371. package/src/modules/wms/backend/page.tsx +5 -0
  372. package/src/modules/wms/backend/wms/inventory/page.meta.ts +14 -0
  373. package/src/modules/wms/backend/wms/inventory/page.tsx +5 -0
  374. package/src/modules/wms/backend/wms/location/[id]/page.meta.ts +14 -0
  375. package/src/modules/wms/backend/wms/location/[id]/page.tsx +5 -0
  376. package/src/modules/wms/backend/wms/locations/page.meta.ts +14 -0
  377. package/src/modules/wms/backend/wms/locations/page.tsx +12 -0
  378. package/src/modules/wms/backend/wms/lot/[id]/page.meta.ts +14 -0
  379. package/src/modules/wms/backend/wms/lot/[id]/page.tsx +5 -0
  380. package/src/modules/wms/backend/wms/lots/page.meta.ts +14 -0
  381. package/src/modules/wms/backend/wms/lots/page.tsx +5 -0
  382. package/src/modules/wms/backend/wms/movements/page.meta.ts +14 -0
  383. package/src/modules/wms/backend/wms/movements/page.tsx +23 -0
  384. package/src/modules/wms/backend/wms/reservations/page.meta.ts +14 -0
  385. package/src/modules/wms/backend/wms/reservations/page.tsx +24 -0
  386. package/src/modules/wms/backend/wms/sku/[id]/page.meta.ts +14 -0
  387. package/src/modules/wms/backend/wms/sku/[id]/page.tsx +5 -0
  388. package/src/modules/wms/backend/wms/warehouses/page.meta.ts +14 -0
  389. package/src/modules/wms/backend/wms/warehouses/page.tsx +12 -0
  390. package/src/modules/wms/backend/wms/zones/page.meta.ts +14 -0
  391. package/src/modules/wms/backend/wms/zones/page.tsx +12 -0
  392. package/src/modules/wms/ce.ts +76 -0
  393. package/src/modules/wms/cli.ts +96 -0
  394. package/src/modules/wms/commands/configuration.ts +1844 -0
  395. package/src/modules/wms/commands/index.ts +3 -0
  396. package/src/modules/wms/commands/inventory-actions.ts +1866 -0
  397. package/src/modules/wms/commands/sales-order-assignment.ts +346 -0
  398. package/src/modules/wms/commands/shared.ts +90 -0
  399. package/src/modules/wms/components/backend/AdjustInventoryDialog.tsx +820 -0
  400. package/src/modules/wms/components/backend/ChangeLotStatusDialog.tsx +312 -0
  401. package/src/modules/wms/components/backend/CycleCountWizardDialog.tsx +2007 -0
  402. package/src/modules/wms/components/backend/ImportInventoryDialog.tsx +1018 -0
  403. package/src/modules/wms/components/backend/InventoryOperationsSection.tsx +159 -0
  404. package/src/modules/wms/components/backend/LocationEditDialog.tsx +185 -0
  405. package/src/modules/wms/components/backend/MoveInventoryDialog.tsx +907 -0
  406. package/src/modules/wms/components/backend/ReceiveInventoryDialog.tsx +695 -0
  407. package/src/modules/wms/components/backend/ReleaseReservationDialog.tsx +424 -0
  408. package/src/modules/wms/components/backend/ReserveInventoryDialog.tsx +511 -0
  409. package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +1340 -0
  410. package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +1132 -0
  411. package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +1310 -0
  412. package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +1355 -0
  413. package/src/modules/wms/components/backend/WmsLotsListPage.tsx +359 -0
  414. package/src/modules/wms/components/backend/WmsOperationalDashboardPage.tsx +958 -0
  415. package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +1245 -0
  416. package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +960 -0
  417. package/src/modules/wms/components/backend/useWmsInventoryMutationAccess.ts +89 -0
  418. package/src/modules/wms/components/backend/useWmsInventoryScopeFromSearchParams.ts +32 -0
  419. package/src/modules/wms/components/backend/wmsLookupLoaders.ts +78 -0
  420. package/src/modules/wms/data/enrichers.ts +718 -0
  421. package/src/modules/wms/data/entities.ts +436 -0
  422. package/src/modules/wms/data/validators.ts +463 -0
  423. package/src/modules/wms/di.ts +25 -0
  424. package/src/modules/wms/events.ts +41 -0
  425. package/src/modules/wms/i18n/de.json +1051 -0
  426. package/src/modules/wms/i18n/en.json +1051 -0
  427. package/src/modules/wms/i18n/es.json +1051 -0
  428. package/src/modules/wms/i18n/pl.json +1051 -0
  429. package/src/modules/wms/index.ts +15 -0
  430. package/src/modules/wms/lib/catalogInventoryProfileIntent.ts +65 -0
  431. package/src/modules/wms/lib/catalogInventoryProfileSync.ts +199 -0
  432. package/src/modules/wms/lib/expiry.ts +30 -0
  433. package/src/modules/wms/lib/flashMutationError.ts +74 -0
  434. package/src/modules/wms/lib/inventoryDisplayUi.ts +249 -0
  435. package/src/modules/wms/lib/inventoryIdempotency.ts +54 -0
  436. package/src/modules/wms/lib/inventoryImportCsv.ts +212 -0
  437. package/src/modules/wms/lib/inventoryImportService.ts +629 -0
  438. package/src/modules/wms/lib/inventoryMutationUi.ts +21 -0
  439. package/src/modules/wms/lib/inventoryPolicy.ts +111 -0
  440. package/src/modules/wms/lib/inventoryReconciliation.ts +263 -0
  441. package/src/modules/wms/lib/inventoryTrackingValidation.ts +23 -0
  442. package/src/modules/wms/lib/loadOperationalDashboard.ts +776 -0
  443. package/src/modules/wms/lib/lowStockBalanceFilter.ts +74 -0
  444. package/src/modules/wms/lib/primaryWarehousePolicy.ts +46 -0
  445. package/src/modules/wms/lib/roleFeatures.ts +32 -0
  446. package/src/modules/wms/lib/salesOrderInventoryAutomation.ts +390 -0
  447. package/src/modules/wms/lib/salesOrderWarehouseAssignment.ts +78 -0
  448. package/src/modules/wms/lib/wmsIntegrationToggles.ts +81 -0
  449. package/src/modules/wms/migrations/.snapshot-open-mercato.json +2880 -0
  450. package/src/modules/wms/migrations/Migration20260428110546.ts +91 -0
  451. package/src/modules/wms/migrations/Migration20260527120000.ts +15 -0
  452. package/src/modules/wms/migrations/Migration20260527140000.ts +35 -0
  453. package/src/modules/wms/migrations/Migration20260613120000.ts +21 -0
  454. package/src/modules/wms/migrations/Migration20260616090000.ts +11 -0
  455. package/src/modules/wms/migrations/Migration20260707180000.ts +13 -0
  456. package/src/modules/wms/notifications.client.ts +18 -0
  457. package/src/modules/wms/notifications.ts +51 -0
  458. package/src/modules/wms/search.ts +230 -0
  459. package/src/modules/wms/setup.ts +29 -0
  460. package/src/modules/wms/subscribers/low-stock-notification.ts +54 -0
  461. package/src/modules/wms/subscribers/reservation-shortfall-notification.ts +98 -0
  462. package/src/modules/wms/subscribers/sales-order-cancelled-release.ts +21 -0
  463. package/src/modules/wms/subscribers/sales-order-confirmed-reserve.ts +21 -0
  464. package/src/modules/wms/translations.ts +6 -0
  465. package/src/modules/wms/vector.ts +7 -0
  466. package/src/modules/wms/widgets/injection/catalog-inventory-profile/widget.ts +238 -0
  467. package/src/modules/wms/widgets/injection/order-items-stock-column/widget.tsx +153 -0
  468. package/src/modules/wms/widgets/injection/sales-order-stock-context/widget.client.tsx +476 -0
  469. package/src/modules/wms/widgets/injection/sales-order-stock-context/widget.ts +15 -0
  470. package/src/modules/wms/widgets/injection-table.ts +34 -0
  471. package/src/modules/wms/widgets/notifications/WmsLowStockRenderer.tsx +153 -0
  472. package/src/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.tsx +194 -0
  473. package/src/modules/wms/widgets/notifications/index.ts +2 -0
@@ -0,0 +1,49 @@
1
+ async function resolveLowStockVariantIds(em, scope, mode) {
2
+ const params = [scope.organizationId, scope.tenantId];
3
+ let warehouseJoin = "";
4
+ if (scope.warehouseId) {
5
+ warehouseJoin = " and b.warehouse_id = ?";
6
+ params.push(scope.warehouseId);
7
+ }
8
+ const thresholdExpr = mode === "belowSafety" ? "coalesce(p.safety_stock, 0)" : "coalesce(p.reorder_point, 0)";
9
+ const thresholdGuard = mode === "belowSafety" ? "coalesce(p.safety_stock, 0) > 0" : "(coalesce(p.reorder_point, 0) > 0 or coalesce(p.safety_stock, 0) > 0)";
10
+ params.push(scope.organizationId, scope.tenantId);
11
+ const sql = `
12
+ select distinct p.catalog_variant_id as catalog_variant_id
13
+ from wms_product_inventory_profiles p
14
+ join (
15
+ select
16
+ b.catalog_variant_id,
17
+ b.warehouse_id,
18
+ sum(
19
+ coalesce(b.quantity_on_hand, 0)
20
+ - coalesce(b.quantity_reserved, 0)
21
+ - coalesce(b.quantity_allocated, 0)
22
+ ) as available
23
+ from wms_inventory_balances b
24
+ where b.organization_id = ?
25
+ and b.tenant_id = ?
26
+ and b.deleted_at is null
27
+ ${warehouseJoin}
28
+ group by b.catalog_variant_id, b.warehouse_id
29
+ ) availability
30
+ on availability.catalog_variant_id = p.catalog_variant_id
31
+ where p.organization_id = ?
32
+ and p.tenant_id = ?
33
+ and p.deleted_at is null
34
+ and p.catalog_variant_id is not null
35
+ and ${thresholdGuard}
36
+ and availability.available <= ${thresholdExpr}
37
+ `;
38
+ const rows = await em.getConnection().execute(sql, params);
39
+ return rows.map((row) => row.catalog_variant_id?.trim()).filter((value) => Boolean(value));
40
+ }
41
+ const NO_MATCH_UUID = "00000000-0000-4000-8000-000000000000";
42
+ function formatLowStockVariantIdsForFilter(variantIds) {
43
+ return variantIds.length > 0 ? variantIds : [NO_MATCH_UUID];
44
+ }
45
+ export {
46
+ formatLowStockVariantIdsForFilter,
47
+ resolveLowStockVariantIds
48
+ };
49
+ //# sourceMappingURL=lowStockBalanceFilter.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/wms/lib/lowStockBalanceFilter.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\n\nexport type LowStockBalanceFilterMode = 'belowReorder' | 'belowSafety'\n\ntype LowStockScope = {\n organizationId: string\n tenantId: string\n warehouseId?: string | null\n}\n\nexport async function resolveLowStockVariantIds(\n em: EntityManager,\n scope: LowStockScope,\n mode: LowStockBalanceFilterMode,\n): Promise<string[]> {\n const params: unknown[] = [scope.organizationId, scope.tenantId]\n let warehouseJoin = ''\n if (scope.warehouseId) {\n warehouseJoin = ' and b.warehouse_id = ?'\n params.push(scope.warehouseId)\n }\n\n const thresholdExpr =\n mode === 'belowSafety'\n ? 'coalesce(p.safety_stock, 0)'\n : 'coalesce(p.reorder_point, 0)'\n\n const thresholdGuard =\n mode === 'belowSafety'\n ? 'coalesce(p.safety_stock, 0) > 0'\n : '(coalesce(p.reorder_point, 0) > 0 or coalesce(p.safety_stock, 0) > 0)'\n\n params.push(scope.organizationId, scope.tenantId)\n\n const sql = `\n select distinct p.catalog_variant_id as catalog_variant_id\n from wms_product_inventory_profiles p\n join (\n select\n b.catalog_variant_id,\n b.warehouse_id,\n sum(\n coalesce(b.quantity_on_hand, 0)\n - coalesce(b.quantity_reserved, 0)\n - coalesce(b.quantity_allocated, 0)\n ) as available\n from wms_inventory_balances b\n where b.organization_id = ?\n and b.tenant_id = ?\n and b.deleted_at is null\n ${warehouseJoin}\n group by b.catalog_variant_id, b.warehouse_id\n ) availability\n on availability.catalog_variant_id = p.catalog_variant_id\n where p.organization_id = ?\n and p.tenant_id = ?\n and p.deleted_at is null\n and p.catalog_variant_id is not null\n and ${thresholdGuard}\n and availability.available <= ${thresholdExpr}\n `\n\n const rows = await em.getConnection().execute<Array<{ catalog_variant_id: string }>>(sql, params)\n return rows\n .map((row) => row.catalog_variant_id?.trim())\n .filter((value): value is string => Boolean(value))\n}\n\n/** Sentinel UUID that never matches a real entity \u2014 forces zero results when a low-stock filter returns an empty variant set. */\nconst NO_MATCH_UUID = '00000000-0000-4000-8000-000000000000'\n\nexport function formatLowStockVariantIdsForFilter(variantIds: string[]): string[] {\n return variantIds.length > 0 ? variantIds : [NO_MATCH_UUID]\n}\n"],
5
+ "mappings": "AAUA,eAAsB,0BACpB,IACA,OACA,MACmB;AACnB,QAAM,SAAoB,CAAC,MAAM,gBAAgB,MAAM,QAAQ;AAC/D,MAAI,gBAAgB;AACpB,MAAI,MAAM,aAAa;AACrB,oBAAgB;AAChB,WAAO,KAAK,MAAM,WAAW;AAAA,EAC/B;AAEA,QAAM,gBACJ,SAAS,gBACL,gCACA;AAEN,QAAM,iBACJ,SAAS,gBACL,oCACA;AAEN,SAAO,KAAK,MAAM,gBAAgB,MAAM,QAAQ;AAEhD,QAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAgBJ,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAQX,cAAc;AAAA,sCACY,aAAa;AAAA;AAGjD,QAAM,OAAO,MAAM,GAAG,cAAc,EAAE,QAA+C,KAAK,MAAM;AAChG,SAAO,KACJ,IAAI,CAAC,QAAQ,IAAI,oBAAoB,KAAK,CAAC,EAC3C,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC;AACtD;AAGA,MAAM,gBAAgB;AAEf,SAAS,kCAAkC,YAAgC;AAChF,SAAO,WAAW,SAAS,IAAI,aAAa,CAAC,aAAa;AAC5D;",
6
+ "names": []
7
+ }
@@ -0,0 +1,32 @@
1
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
2
+ import { Warehouse } from "../data/entities.js";
3
+ async function resolvePrimaryWarehouseId(em, scope) {
4
+ const warehouse = await findOneWithDecryption(
5
+ em,
6
+ Warehouse,
7
+ {
8
+ organizationId: scope.organizationId,
9
+ isPrimary: true,
10
+ isActive: true,
11
+ deletedAt: null
12
+ },
13
+ void 0,
14
+ scope
15
+ );
16
+ return warehouse?.id ?? null;
17
+ }
18
+ function sortWarehouseAvailabilityForReservation(warehouses, primaryWarehouseId) {
19
+ return [...warehouses].sort((left, right) => {
20
+ if (primaryWarehouseId) {
21
+ const leftPrimary = left.warehouseId === primaryWarehouseId ? 1 : 0;
22
+ const rightPrimary = right.warehouseId === primaryWarehouseId ? 1 : 0;
23
+ if (leftPrimary !== rightPrimary) return rightPrimary - leftPrimary;
24
+ }
25
+ return right.available - left.available;
26
+ });
27
+ }
28
+ export {
29
+ resolvePrimaryWarehouseId,
30
+ sortWarehouseAvailabilityForReservation
31
+ };
32
+ //# sourceMappingURL=primaryWarehousePolicy.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/wms/lib/primaryWarehousePolicy.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { Warehouse } from '../data/entities'\n\ntype Scope = {\n tenantId: string\n organizationId: string\n}\n\nexport type WarehouseAvailability = {\n warehouseId: string\n available: number\n}\n\nexport async function resolvePrimaryWarehouseId(\n em: EntityManager,\n scope: Scope,\n): Promise<string | null> {\n const warehouse = await findOneWithDecryption(\n em,\n Warehouse,\n {\n organizationId: scope.organizationId,\n isPrimary: true,\n isActive: true,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n return warehouse?.id ?? null\n}\n\nexport function sortWarehouseAvailabilityForReservation(\n warehouses: WarehouseAvailability[],\n primaryWarehouseId: string | null,\n): WarehouseAvailability[] {\n return [...warehouses].sort((left, right) => {\n if (primaryWarehouseId) {\n const leftPrimary = left.warehouseId === primaryWarehouseId ? 1 : 0\n const rightPrimary = right.warehouseId === primaryWarehouseId ? 1 : 0\n if (leftPrimary !== rightPrimary) return rightPrimary - leftPrimary\n }\n return right.available - left.available\n })\n}\n"],
5
+ "mappings": "AACA,SAAS,6BAA6B;AACtC,SAAS,iBAAiB;AAY1B,eAAsB,0BACpB,IACA,OACwB;AACxB,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,MACE,gBAAgB,MAAM;AAAA,MACtB,WAAW;AAAA,MACX,UAAU;AAAA,MACV,WAAW;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,WAAW,MAAM;AAC1B;AAEO,SAAS,wCACd,YACA,oBACyB;AACzB,SAAO,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,MAAM,UAAU;AAC3C,QAAI,oBAAoB;AACtB,YAAM,cAAc,KAAK,gBAAgB,qBAAqB,IAAI;AAClE,YAAM,eAAe,MAAM,gBAAgB,qBAAqB,IAAI;AACpE,UAAI,gBAAgB,aAAc,QAAO,eAAe;AAAA,IAC1D;AACA,WAAO,MAAM,YAAY,KAAK;AAAA,EAChC,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -0,0 +1,30 @@
1
+ const WMS_OPERATOR_ROLE = "operator";
2
+ const WMS_SUPERVISOR_ROLE = "supervisor";
3
+ const WMS_CUSTOM_ROLE_NAMES = [WMS_OPERATOR_ROLE, WMS_SUPERVISOR_ROLE];
4
+ const WMS_OPERATOR_FEATURES = [
5
+ "wms.view",
6
+ "wms.adjust_inventory",
7
+ "wms.receive_inventory",
8
+ "wms.cycle_count"
9
+ ];
10
+ const WMS_MANAGE_FEATURES = [
11
+ "wms.manage_warehouses",
12
+ "wms.manage_zones",
13
+ "wms.manage_locations",
14
+ "wms.manage_inventory",
15
+ "wms.manage_reservations"
16
+ ];
17
+ const WMS_SUPERVISOR_FEATURES = [
18
+ ...WMS_OPERATOR_FEATURES,
19
+ "wms.import",
20
+ ...WMS_MANAGE_FEATURES
21
+ ];
22
+ export {
23
+ WMS_CUSTOM_ROLE_NAMES,
24
+ WMS_MANAGE_FEATURES,
25
+ WMS_OPERATOR_FEATURES,
26
+ WMS_OPERATOR_ROLE,
27
+ WMS_SUPERVISOR_FEATURES,
28
+ WMS_SUPERVISOR_ROLE
29
+ };
30
+ //# sourceMappingURL=roleFeatures.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/wms/lib/roleFeatures.ts"],
4
+ "sourcesContent": ["/**\n * Reserved tenant role names seeded by WMS `setup.ts` via `ensureRoles`.\n * Other modules MUST NOT reuse `operator` or `supervisor` without coordinating ACL grants and i18n labels.\n */\nexport const WMS_OPERATOR_ROLE = 'operator' as const\nexport const WMS_SUPERVISOR_ROLE = 'supervisor' as const\n\nexport const WMS_CUSTOM_ROLE_NAMES = [WMS_OPERATOR_ROLE, WMS_SUPERVISOR_ROLE] as const\n\nexport const WMS_OPERATOR_FEATURES = [\n 'wms.view',\n 'wms.adjust_inventory',\n 'wms.receive_inventory',\n 'wms.cycle_count',\n] as const\n\nexport const WMS_MANAGE_FEATURES = [\n 'wms.manage_warehouses',\n 'wms.manage_zones',\n 'wms.manage_locations',\n 'wms.manage_inventory',\n 'wms.manage_reservations',\n] as const\n\nexport const WMS_SUPERVISOR_FEATURES = [\n ...WMS_OPERATOR_FEATURES,\n 'wms.import',\n ...WMS_MANAGE_FEATURES,\n] as const\n\nexport type WmsOperatorFeature = (typeof WMS_OPERATOR_FEATURES)[number]\nexport type WmsSupervisorFeature = (typeof WMS_SUPERVISOR_FEATURES)[number]\n"],
5
+ "mappings": "AAIO,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB;AAE5B,MAAM,wBAAwB,CAAC,mBAAmB,mBAAmB;AAErE,MAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,sBAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,0BAA0B;AAAA,EACrC,GAAG;AAAA,EACH;AAAA,EACA,GAAG;AACL;",
6
+ "names": []
7
+ }
@@ -0,0 +1,291 @@
1
+ import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
2
+ import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
3
+ import { E } from "../../../generated/entities.ids.generated.js";
4
+ import { InventoryBalance, InventoryReservation } from "../data/entities.js";
5
+ import { emitWmsEvent } from "../events.js";
6
+ import { loadExplicitWarehouseIdForOrder } from "./salesOrderWarehouseAssignment.js";
7
+ import {
8
+ resolvePrimaryWarehouseId,
9
+ sortWarehouseAvailabilityForReservation
10
+ } from "./primaryWarehousePolicy.js";
11
+ import { resolveWmsIntegrationToggleEnabled } from "./wmsIntegrationToggles.js";
12
+ function isInsufficientStockError(error) {
13
+ return error instanceof CrudHttpError && error.status === 409 && error.body?.error === "insufficient_stock";
14
+ }
15
+ function isBalanceIntegrityViolationError(error) {
16
+ return error instanceof CrudHttpError && error.status === 409 && error.body?.error === "balance_integrity_violation";
17
+ }
18
+ function toNumber(value) {
19
+ if (typeof value === "number" && Number.isFinite(value)) return value;
20
+ if (typeof value === "string" && value.trim().length > 0) {
21
+ const parsed = Number(value);
22
+ if (Number.isFinite(parsed)) return parsed;
23
+ }
24
+ return 0;
25
+ }
26
+ function getWarehouseId(balance) {
27
+ const relation = balance.warehouse;
28
+ if (typeof relation === "string") return relation;
29
+ return typeof relation?.id === "string" ? relation.id : null;
30
+ }
31
+ function buildCommandContext(ctx, scope) {
32
+ return {
33
+ container: {
34
+ resolve: ctx.resolve
35
+ },
36
+ auth: null,
37
+ organizationScope: null,
38
+ selectedOrganizationId: scope.organizationId,
39
+ organizationIds: [scope.organizationId]
40
+ };
41
+ }
42
+ async function isInventoryAutomationEnabled(ctx, tenantId) {
43
+ try {
44
+ const featureTogglesService = ctx.resolve("featureTogglesService");
45
+ const em = ctx.resolve("em");
46
+ return resolveWmsIntegrationToggleEnabled(
47
+ featureTogglesService,
48
+ em,
49
+ "wms_integration_sales_order_inventory",
50
+ tenantId
51
+ );
52
+ } catch {
53
+ return true;
54
+ }
55
+ }
56
+ async function loadOrderViaQueryEngine(ctx, orderId, scope) {
57
+ const queryEngine = ctx.resolve("queryEngine");
58
+ const result = await queryEngine.query(E.sales.sales_order, {
59
+ tenantId: scope.tenantId,
60
+ organizationId: scope.organizationId,
61
+ filters: { id: { $eq: orderId } },
62
+ fields: ["id", "order_number", "tenant_id", "organization_id"],
63
+ page: { page: 1, pageSize: 1 }
64
+ });
65
+ return result.items[0] ?? null;
66
+ }
67
+ async function loadOrderLinesViaQueryEngine(ctx, orderId, scope) {
68
+ const queryEngine = ctx.resolve("queryEngine");
69
+ const result = await queryEngine.query(E.sales.sales_order_line, {
70
+ tenantId: scope.tenantId,
71
+ organizationId: scope.organizationId,
72
+ filters: { order_id: { $eq: orderId } },
73
+ fields: ["id", "kind", "product_variant_id", "quantity", "line_number"],
74
+ sort: [{ field: "line_number", dir: "asc" }],
75
+ page: { page: 1, pageSize: 1e3 }
76
+ });
77
+ return result.items;
78
+ }
79
+ async function loadActiveReservations(em, orderId, scope) {
80
+ return findWithDecryption(
81
+ em,
82
+ InventoryReservation,
83
+ {
84
+ sourceType: "order",
85
+ sourceId: orderId,
86
+ status: "active",
87
+ tenantId: scope.tenantId,
88
+ organizationId: scope.organizationId,
89
+ deletedAt: null
90
+ },
91
+ { orderBy: { createdAt: "asc" } },
92
+ scope
93
+ );
94
+ }
95
+ async function loadBalances(em, variantIds, scope) {
96
+ if (variantIds.length === 0) return [];
97
+ return findWithDecryption(
98
+ em,
99
+ InventoryBalance,
100
+ {
101
+ catalogVariantId: { $in: variantIds },
102
+ tenantId: scope.tenantId,
103
+ organizationId: scope.organizationId,
104
+ deletedAt: null
105
+ },
106
+ void 0,
107
+ scope
108
+ );
109
+ }
110
+ function buildRequiredQuantityByVariant(lines) {
111
+ const quantities = /* @__PURE__ */ new Map();
112
+ for (const line of lines) {
113
+ if (line.kind !== "product" || !line.product_variant_id) continue;
114
+ const quantity = toNumber(line.quantity);
115
+ if (quantity <= 0) continue;
116
+ quantities.set(
117
+ line.product_variant_id,
118
+ (quantities.get(line.product_variant_id) ?? 0) + quantity
119
+ );
120
+ }
121
+ return quantities;
122
+ }
123
+ function buildReservedQuantityByVariant(reservations) {
124
+ const quantities = /* @__PURE__ */ new Map();
125
+ for (const reservation of reservations) {
126
+ quantities.set(
127
+ reservation.catalogVariantId,
128
+ (quantities.get(reservation.catalogVariantId) ?? 0) + toNumber(reservation.quantity)
129
+ );
130
+ }
131
+ return quantities;
132
+ }
133
+ function buildWarehouseAvailability(balances) {
134
+ const byVariant = /* @__PURE__ */ new Map();
135
+ for (const balance of balances) {
136
+ const warehouseId = getWarehouseId(balance);
137
+ if (!warehouseId) continue;
138
+ const available = toNumber(balance.quantityOnHand) - toNumber(balance.quantityReserved) - toNumber(balance.quantityAllocated);
139
+ if (available <= 0) continue;
140
+ const warehouseMap = byVariant.get(balance.catalogVariantId) ?? /* @__PURE__ */ new Map();
141
+ warehouseMap.set(warehouseId, (warehouseMap.get(warehouseId) ?? 0) + available);
142
+ byVariant.set(balance.catalogVariantId, warehouseMap);
143
+ }
144
+ const result = /* @__PURE__ */ new Map();
145
+ for (const [variantId, warehouseMap] of byVariant.entries()) {
146
+ result.set(
147
+ variantId,
148
+ Array.from(warehouseMap.entries()).map(([warehouseId, available]) => ({ warehouseId, available }))
149
+ );
150
+ }
151
+ return result;
152
+ }
153
+ async function reserveInventoryForConfirmedOrder(payload, ctx) {
154
+ if (!payload.orderId || !payload.tenantId || !payload.organizationId) return;
155
+ if (!await isInventoryAutomationEnabled(ctx, payload.tenantId)) return;
156
+ const scope = {
157
+ tenantId: payload.tenantId,
158
+ organizationId: payload.organizationId
159
+ };
160
+ const em = ctx.resolve("em").fork();
161
+ const commandBus = ctx.resolve("commandBus");
162
+ const commandCtx = buildCommandContext(ctx, scope);
163
+ const order = await loadOrderViaQueryEngine(ctx, payload.orderId, scope);
164
+ if (!order || typeof order.id !== "string") return;
165
+ const orderId = order.id;
166
+ const orderNumber = typeof order.order_number === "string" ? order.order_number : null;
167
+ const [lines, activeReservations] = await Promise.all([
168
+ loadOrderLinesViaQueryEngine(ctx, orderId, scope),
169
+ loadActiveReservations(em, orderId, scope)
170
+ ]);
171
+ const requiredByVariant = buildRequiredQuantityByVariant(lines);
172
+ if (requiredByVariant.size === 0) return;
173
+ const reservedByVariant = buildReservedQuantityByVariant(activeReservations);
174
+ const balances = await loadBalances(em, Array.from(requiredByVariant.keys()), scope);
175
+ const availabilityByVariant = buildWarehouseAvailability(balances);
176
+ const [primaryWarehouseId, assignedWarehouseId] = await Promise.all([
177
+ resolvePrimaryWarehouseId(em, scope),
178
+ loadExplicitWarehouseIdForOrder(em, orderId, scope)
179
+ ]);
180
+ const preferredWarehouseId = assignedWarehouseId ?? primaryWarehouseId;
181
+ const shortfalls = [];
182
+ for (const [variantId, requiredQuantity] of requiredByVariant.entries()) {
183
+ let remainingQuantity = requiredQuantity - (reservedByVariant.get(variantId) ?? 0);
184
+ if (remainingQuantity <= 0) continue;
185
+ let variantBuckets = availabilityByVariant.get(variantId) ?? [];
186
+ if (assignedWarehouseId) {
187
+ variantBuckets = variantBuckets.filter(
188
+ (bucket) => bucket.warehouseId === assignedWarehouseId
189
+ );
190
+ }
191
+ const warehouseAvailability = sortWarehouseAvailabilityForReservation(
192
+ variantBuckets,
193
+ preferredWarehouseId
194
+ );
195
+ let reservedForVariant = 0;
196
+ try {
197
+ for (const bucket of warehouseAvailability) {
198
+ if (remainingQuantity <= 0) break;
199
+ const reserveQuantity = Math.min(remainingQuantity, bucket.available);
200
+ if (reserveQuantity <= 0) continue;
201
+ await commandBus.execute("wms.inventory.reserve", {
202
+ input: {
203
+ tenantId: scope.tenantId,
204
+ organizationId: scope.organizationId,
205
+ warehouseId: bucket.warehouseId,
206
+ catalogVariantId: variantId,
207
+ quantity: reserveQuantity,
208
+ sourceType: "order",
209
+ sourceId: orderId,
210
+ metadata: {
211
+ automation: "sales.order.confirmed",
212
+ orderId,
213
+ orderNumber,
214
+ catalogVariantId: variantId
215
+ }
216
+ },
217
+ ctx: commandCtx
218
+ });
219
+ remainingQuantity -= reserveQuantity;
220
+ reservedForVariant += reserveQuantity;
221
+ bucket.available -= reserveQuantity;
222
+ }
223
+ } catch (error) {
224
+ if (!isInsufficientStockError(error)) throw error;
225
+ }
226
+ if (remainingQuantity > 1e-6) {
227
+ shortfalls.push({
228
+ catalogVariantId: variantId,
229
+ requiredQuantity,
230
+ reservedQuantity: reservedForVariant + (reservedByVariant.get(variantId) ?? 0),
231
+ shortfallQuantity: remainingQuantity
232
+ });
233
+ }
234
+ }
235
+ if (shortfalls.length > 0) {
236
+ await emitWmsEvent("wms.inventory.reservation_shortfall", {
237
+ id: orderId,
238
+ orderId,
239
+ orderNumber,
240
+ shortfalls,
241
+ tenantId: scope.tenantId,
242
+ organizationId: scope.organizationId
243
+ });
244
+ }
245
+ }
246
+ async function releaseInventoryForCancelledOrder(payload, ctx) {
247
+ if (!payload.orderId || !payload.tenantId || !payload.organizationId) return;
248
+ if (!await isInventoryAutomationEnabled(ctx, payload.tenantId)) return;
249
+ const scope = {
250
+ tenantId: payload.tenantId,
251
+ organizationId: payload.organizationId
252
+ };
253
+ const em = ctx.resolve("em").fork();
254
+ const commandBus = ctx.resolve("commandBus");
255
+ const commandCtx = buildCommandContext(ctx, scope);
256
+ const activeReservations = await loadActiveReservations(em, payload.orderId, scope);
257
+ for (const reservation of activeReservations) {
258
+ try {
259
+ await commandBus.execute("wms.inventory.release", {
260
+ input: {
261
+ tenantId: scope.tenantId,
262
+ organizationId: scope.organizationId,
263
+ reservationId: reservation.id,
264
+ reason: "sales.order.cancelled",
265
+ metadata: {
266
+ automation: "sales.order.cancelled",
267
+ orderId: payload.orderId
268
+ }
269
+ },
270
+ ctx: commandCtx
271
+ });
272
+ } catch (error) {
273
+ if (!isBalanceIntegrityViolationError(error)) throw error;
274
+ void emitWmsEvent("wms.inventory.balance_drift", {
275
+ id: reservation.id,
276
+ balanceId: reservation.id,
277
+ reservationId: reservation.id,
278
+ field: "quantityReserved",
279
+ attemptedValue: null,
280
+ clampedValue: null,
281
+ tenantId: scope.tenantId,
282
+ organizationId: scope.organizationId
283
+ }).catch(() => void 0);
284
+ }
285
+ }
286
+ }
287
+ export {
288
+ releaseInventoryForCancelledOrder,
289
+ reserveInventoryForConfirmedOrder
290
+ };
291
+ //# sourceMappingURL=salesOrderInventoryAutomation.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/wms/lib/salesOrderInventoryAutomation.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { FeatureTogglesService } from '@open-mercato/core/modules/feature_toggles/lib/feature-flag-check'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { InventoryBalance, InventoryReservation } from '../data/entities'\nimport { emitWmsEvent } from '../events'\nimport { loadExplicitWarehouseIdForOrder } from './salesOrderWarehouseAssignment'\nimport {\n resolvePrimaryWarehouseId,\n sortWarehouseAvailabilityForReservation,\n type WarehouseAvailability,\n} from './primaryWarehousePolicy'\nimport { resolveWmsIntegrationToggleEnabled } from './wmsIntegrationToggles'\n\ntype EventContext = {\n resolve: <T = unknown>(name: string) => T\n}\n\ntype SalesOrderLifecyclePayload = {\n orderId?: string | null\n tenantId?: string | null\n organizationId?: string | null\n}\n\ntype Scope = {\n tenantId: string\n organizationId: string\n}\n\ntype ReservationShortfallLine = {\n catalogVariantId: string\n requiredQuantity: number\n reservedQuantity: number\n shortfallQuantity: number\n}\n\nfunction isInsufficientStockError(error: unknown): boolean {\n return error instanceof CrudHttpError && error.status === 409 && error.body?.error === 'insufficient_stock'\n}\n\nfunction isBalanceIntegrityViolationError(error: unknown): boolean {\n return error instanceof CrudHttpError && error.status === 409 && error.body?.error === 'balance_integrity_violation'\n}\n\ntype SalesOrderRow = {\n id?: string\n order_number?: string | null\n tenant_id?: string | null\n organization_id?: string | null\n}\n\ntype SalesOrderLineRow = {\n id?: string\n kind?: string | null\n product_variant_id?: string | null\n quantity?: string | number | null\n line_number?: number | null\n}\n\nfunction toNumber(value: unknown): number {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string' && value.trim().length > 0) {\n const parsed = Number(value)\n if (Number.isFinite(parsed)) return parsed\n }\n return 0\n}\n\nfunction getWarehouseId(balance: InventoryBalance): string | null {\n const relation = balance.warehouse as { id?: string } | string | undefined\n if (typeof relation === 'string') return relation\n return typeof relation?.id === 'string' ? relation.id : null\n}\n\nfunction buildCommandContext(ctx: EventContext, scope: Scope): CommandRuntimeContext {\n return {\n container: {\n resolve: ctx.resolve,\n } as CommandRuntimeContext['container'],\n auth: null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: [scope.organizationId],\n }\n}\n\nasync function isInventoryAutomationEnabled(ctx: EventContext, tenantId: string): Promise<boolean> {\n try {\n const featureTogglesService = ctx.resolve<FeatureTogglesService>('featureTogglesService')\n const em = ctx.resolve<EntityManager>('em')\n return resolveWmsIntegrationToggleEnabled(\n featureTogglesService,\n em,\n 'wms_integration_sales_order_inventory',\n tenantId,\n )\n } catch {\n return true\n }\n}\n\nasync function loadOrderViaQueryEngine(\n ctx: EventContext,\n orderId: string,\n scope: Scope,\n): Promise<SalesOrderRow | null> {\n // Read sales orders/lines via QueryEngine instead of importing the sales ORM\n // entity classes \u2014 keeps the WMS module decoupled from sales internals.\n // Sales mutations also flush their CRUD side effects synchronously through\n // the command bus before this subscriber fires, so the query_index/base\n // table is consistent at this point.\n const queryEngine = ctx.resolve<QueryEngine>('queryEngine')\n const result = await queryEngine.query<SalesOrderRow>(E.sales.sales_order, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n filters: { id: { $eq: orderId } },\n fields: ['id', 'order_number', 'tenant_id', 'organization_id'],\n page: { page: 1, pageSize: 1 },\n })\n return result.items[0] ?? null\n}\n\nasync function loadOrderLinesViaQueryEngine(\n ctx: EventContext,\n orderId: string,\n scope: Scope,\n): Promise<SalesOrderLineRow[]> {\n const queryEngine = ctx.resolve<QueryEngine>('queryEngine')\n const result = await queryEngine.query<SalesOrderLineRow>(E.sales.sales_order_line, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n filters: { order_id: { $eq: orderId } },\n fields: ['id', 'kind', 'product_variant_id', 'quantity', 'line_number'],\n sort: [{ field: 'line_number', dir: 'asc' as never }],\n page: { page: 1, pageSize: 1000 },\n })\n return result.items\n}\n\nasync function loadActiveReservations(\n em: EntityManager,\n orderId: string,\n scope: Scope,\n): Promise<InventoryReservation[]> {\n return findWithDecryption(\n em,\n InventoryReservation,\n {\n sourceType: 'order',\n sourceId: orderId,\n status: 'active',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n { orderBy: { createdAt: 'asc' } },\n scope,\n )\n}\n\nasync function loadBalances(\n em: EntityManager,\n variantIds: string[],\n scope: Scope,\n): Promise<InventoryBalance[]> {\n if (variantIds.length === 0) return []\n return findWithDecryption(\n em,\n InventoryBalance,\n {\n catalogVariantId: { $in: variantIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n}\n\nfunction buildRequiredQuantityByVariant(lines: SalesOrderLineRow[]): Map<string, number> {\n const quantities = new Map<string, number>()\n for (const line of lines) {\n if (line.kind !== 'product' || !line.product_variant_id) continue\n const quantity = toNumber(line.quantity)\n if (quantity <= 0) continue\n quantities.set(\n line.product_variant_id,\n (quantities.get(line.product_variant_id) ?? 0) + quantity,\n )\n }\n return quantities\n}\n\nfunction buildReservedQuantityByVariant(reservations: InventoryReservation[]): Map<string, number> {\n const quantities = new Map<string, number>()\n for (const reservation of reservations) {\n quantities.set(\n reservation.catalogVariantId,\n (quantities.get(reservation.catalogVariantId) ?? 0) + toNumber(reservation.quantity),\n )\n }\n return quantities\n}\n\nfunction buildWarehouseAvailability(\n balances: InventoryBalance[],\n): Map<string, WarehouseAvailability[]> {\n const byVariant = new Map<string, Map<string, number>>()\n for (const balance of balances) {\n const warehouseId = getWarehouseId(balance)\n if (!warehouseId) continue\n const available =\n toNumber(balance.quantityOnHand) -\n toNumber(balance.quantityReserved) -\n toNumber(balance.quantityAllocated)\n if (available <= 0) continue\n\n const warehouseMap = byVariant.get(balance.catalogVariantId) ?? new Map<string, number>()\n warehouseMap.set(warehouseId, (warehouseMap.get(warehouseId) ?? 0) + available)\n byVariant.set(balance.catalogVariantId, warehouseMap)\n }\n\n const result = new Map<string, WarehouseAvailability[]>()\n for (const [variantId, warehouseMap] of byVariant.entries()) {\n result.set(\n variantId,\n Array.from(warehouseMap.entries()).map(([warehouseId, available]) => ({ warehouseId, available })),\n )\n }\n return result\n}\n\nexport async function reserveInventoryForConfirmedOrder(\n payload: SalesOrderLifecyclePayload,\n ctx: EventContext,\n): Promise<void> {\n if (!payload.orderId || !payload.tenantId || !payload.organizationId) return\n if (!(await isInventoryAutomationEnabled(ctx, payload.tenantId))) return\n\n const scope: Scope = {\n tenantId: payload.tenantId,\n organizationId: payload.organizationId,\n }\n const em = ctx.resolve<EntityManager>('em').fork()\n const commandBus = ctx.resolve<CommandBus>('commandBus')\n const commandCtx = buildCommandContext(ctx, scope)\n const order = await loadOrderViaQueryEngine(ctx, payload.orderId, scope)\n if (!order || typeof order.id !== 'string') return\n\n const orderId = order.id\n const orderNumber = typeof order.order_number === 'string' ? order.order_number : null\n\n const [lines, activeReservations] = await Promise.all([\n loadOrderLinesViaQueryEngine(ctx, orderId, scope),\n loadActiveReservations(em, orderId, scope),\n ])\n const requiredByVariant = buildRequiredQuantityByVariant(lines)\n if (requiredByVariant.size === 0) return\n\n const reservedByVariant = buildReservedQuantityByVariant(activeReservations)\n const balances = await loadBalances(em, Array.from(requiredByVariant.keys()), scope)\n const availabilityByVariant = buildWarehouseAvailability(balances)\n const [primaryWarehouseId, assignedWarehouseId] = await Promise.all([\n resolvePrimaryWarehouseId(em, scope),\n loadExplicitWarehouseIdForOrder(em, orderId, scope),\n ])\n const preferredWarehouseId = assignedWarehouseId ?? primaryWarehouseId\n const shortfalls: ReservationShortfallLine[] = []\n\n for (const [variantId, requiredQuantity] of requiredByVariant.entries()) {\n let remainingQuantity = requiredQuantity - (reservedByVariant.get(variantId) ?? 0)\n if (remainingQuantity <= 0) continue\n\n let variantBuckets = availabilityByVariant.get(variantId) ?? []\n if (assignedWarehouseId) {\n variantBuckets = variantBuckets.filter(\n (bucket) => bucket.warehouseId === assignedWarehouseId,\n )\n }\n\n const warehouseAvailability = sortWarehouseAvailabilityForReservation(\n variantBuckets,\n preferredWarehouseId,\n )\n let reservedForVariant = 0\n try {\n for (const bucket of warehouseAvailability) {\n if (remainingQuantity <= 0) break\n const reserveQuantity = Math.min(remainingQuantity, bucket.available)\n if (reserveQuantity <= 0) continue\n\n await commandBus.execute('wms.inventory.reserve', {\n input: {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n warehouseId: bucket.warehouseId,\n catalogVariantId: variantId,\n quantity: reserveQuantity,\n sourceType: 'order',\n sourceId: orderId,\n metadata: {\n automation: 'sales.order.confirmed',\n orderId,\n orderNumber,\n catalogVariantId: variantId,\n },\n },\n ctx: commandCtx,\n })\n\n remainingQuantity -= reserveQuantity\n reservedForVariant += reserveQuantity\n bucket.available -= reserveQuantity\n }\n } catch (error) {\n if (!isInsufficientStockError(error)) throw error\n }\n\n if (remainingQuantity > 0.000001) {\n shortfalls.push({\n catalogVariantId: variantId,\n requiredQuantity,\n reservedQuantity: reservedForVariant + (reservedByVariant.get(variantId) ?? 0),\n shortfallQuantity: remainingQuantity,\n })\n }\n }\n\n if (shortfalls.length > 0) {\n await emitWmsEvent('wms.inventory.reservation_shortfall', {\n id: orderId,\n orderId,\n orderNumber,\n shortfalls,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n }\n}\n\nexport async function releaseInventoryForCancelledOrder(\n payload: SalesOrderLifecyclePayload,\n ctx: EventContext,\n): Promise<void> {\n if (!payload.orderId || !payload.tenantId || !payload.organizationId) return\n if (!(await isInventoryAutomationEnabled(ctx, payload.tenantId))) return\n\n const scope: Scope = {\n tenantId: payload.tenantId,\n organizationId: payload.organizationId,\n }\n const em = ctx.resolve<EntityManager>('em').fork()\n const commandBus = ctx.resolve<CommandBus>('commandBus')\n const commandCtx = buildCommandContext(ctx, scope)\n const activeReservations = await loadActiveReservations(em, payload.orderId, scope)\n\n for (const reservation of activeReservations) {\n try {\n await commandBus.execute('wms.inventory.release', {\n input: {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n reservationId: reservation.id,\n reason: 'sales.order.cancelled',\n metadata: {\n automation: 'sales.order.cancelled',\n orderId: payload.orderId,\n },\n },\n ctx: commandCtx,\n })\n } catch (error) {\n if (!isBalanceIntegrityViolationError(error)) throw error\n void emitWmsEvent('wms.inventory.balance_drift', {\n id: reservation.id,\n balanceId: reservation.id,\n reservationId: reservation.id,\n field: 'quantityReserved',\n attemptedValue: null,\n clampedValue: null,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n }).catch(() => undefined)\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,54 @@
1
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
2
+ import { SalesOrderWarehouseAssignment } from "../data/entities.js";
3
+ function resolveWarehouseId(assignment) {
4
+ const warehouseRel = assignment.warehouse;
5
+ return typeof warehouseRel?.id === "string" ? warehouseRel.id : null;
6
+ }
7
+ async function loadExplicitWarehouseIdForOrder(em, salesOrderId, scope) {
8
+ const assignment = await findOneWithDecryption(
9
+ em,
10
+ SalesOrderWarehouseAssignment,
11
+ {
12
+ salesOrderId,
13
+ organizationId: scope.organizationId,
14
+ tenantId: scope.tenantId,
15
+ deletedAt: null
16
+ },
17
+ { populate: ["warehouse"] },
18
+ scope
19
+ );
20
+ if (!assignment) return null;
21
+ return resolveWarehouseId(assignment);
22
+ }
23
+ async function loadSalesOrderWarehouseAssignmentView(em, salesOrderId, scope) {
24
+ const assignment = await findOneWithDecryption(
25
+ em,
26
+ SalesOrderWarehouseAssignment,
27
+ {
28
+ salesOrderId,
29
+ organizationId: scope.organizationId,
30
+ tenantId: scope.tenantId,
31
+ deletedAt: null
32
+ },
33
+ { populate: ["warehouse"] },
34
+ scope
35
+ );
36
+ if (!assignment) return null;
37
+ const warehouseId = resolveWarehouseId(assignment);
38
+ if (!warehouseId) return null;
39
+ const warehouse = assignment.warehouse;
40
+ return {
41
+ id: assignment.id,
42
+ salesOrderId: assignment.salesOrderId,
43
+ warehouseId,
44
+ warehouseName: warehouse?.name ?? null,
45
+ warehouseCode: warehouse?.code ?? null,
46
+ notes: assignment.notes ?? null,
47
+ assignedBy: assignment.assignedBy ?? null
48
+ };
49
+ }
50
+ export {
51
+ loadExplicitWarehouseIdForOrder,
52
+ loadSalesOrderWarehouseAssignmentView
53
+ };
54
+ //# sourceMappingURL=salesOrderWarehouseAssignment.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/wms/lib/salesOrderWarehouseAssignment.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { SalesOrderWarehouseAssignment, Warehouse } from '../data/entities'\n\ntype Scope = {\n tenantId: string\n organizationId: string\n}\n\nexport type SalesOrderWarehouseAssignmentView = {\n id: string\n salesOrderId: string\n warehouseId: string\n warehouseName: string | null\n warehouseCode: string | null\n notes: string | null\n assignedBy: string | null\n}\n\nfunction resolveWarehouseId(assignment: SalesOrderWarehouseAssignment): string | null {\n const warehouseRel = assignment.warehouse as { id?: string } | undefined\n return typeof warehouseRel?.id === 'string' ? warehouseRel.id : null\n}\n\nexport async function loadExplicitWarehouseIdForOrder(\n em: EntityManager,\n salesOrderId: string,\n scope: Scope,\n): Promise<string | null> {\n const assignment = await findOneWithDecryption(\n em,\n SalesOrderWarehouseAssignment,\n {\n salesOrderId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n { populate: ['warehouse'] },\n scope,\n )\n if (!assignment) return null\n return resolveWarehouseId(assignment)\n}\n\nexport async function loadSalesOrderWarehouseAssignmentView(\n em: EntityManager,\n salesOrderId: string,\n scope: Scope,\n): Promise<SalesOrderWarehouseAssignmentView | null> {\n const assignment = await findOneWithDecryption(\n em,\n SalesOrderWarehouseAssignment,\n {\n salesOrderId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n { populate: ['warehouse'] },\n scope,\n )\n if (!assignment) return null\n\n const warehouseId = resolveWarehouseId(assignment)\n if (!warehouseId) return null\n\n const warehouse = assignment.warehouse as Warehouse | undefined\n return {\n id: assignment.id,\n salesOrderId: assignment.salesOrderId,\n warehouseId,\n warehouseName: warehouse?.name ?? null,\n warehouseCode: warehouse?.code ?? null,\n notes: assignment.notes ?? null,\n assignedBy: assignment.assignedBy ?? null,\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,6BAA6B;AACtC,SAAS,qCAAgD;AAiBzD,SAAS,mBAAmB,YAA0D;AACpF,QAAM,eAAe,WAAW;AAChC,SAAO,OAAO,cAAc,OAAO,WAAW,aAAa,KAAK;AAClE;AAEA,eAAsB,gCACpB,IACA,cACA,OACwB;AACxB,QAAM,aAAa,MAAM;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,MACE;AAAA,MACA,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,WAAW;AAAA,IACb;AAAA,IACA,EAAE,UAAU,CAAC,WAAW,EAAE;AAAA,IAC1B;AAAA,EACF;AACA,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,mBAAmB,UAAU;AACtC;AAEA,eAAsB,sCACpB,IACA,cACA,OACmD;AACnD,QAAM,aAAa,MAAM;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,MACE;AAAA,MACA,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,WAAW;AAAA,IACb;AAAA,IACA,EAAE,UAAU,CAAC,WAAW,EAAE;AAAA,IAC1B;AAAA,EACF;AACA,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,cAAc,mBAAmB,UAAU;AACjD,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,YAAY,WAAW;AAC7B,SAAO;AAAA,IACL,IAAI,WAAW;AAAA,IACf,cAAc,WAAW;AAAA,IACzB;AAAA,IACA,eAAe,WAAW,QAAQ;AAAA,IAClC,eAAe,WAAW,QAAQ;AAAA,IAClC,OAAO,WAAW,SAAS;AAAA,IAC3B,YAAY,WAAW,cAAc;AAAA,EACvC;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,71 @@
1
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
2
+ import { FeatureToggle } from "@open-mercato/core/modules/feature_toggles/data/entities";
3
+ const WMS_INTEGRATION_TOGGLES = [
4
+ {
5
+ identifier: "wms_integration_sales_order_inventory",
6
+ name: "Sales Order Inventory Reservation",
7
+ description: "Allows WMS to reserve and release inventory from sales order lifecycle events.",
8
+ category: "wms",
9
+ type: "boolean",
10
+ defaultValue: true
11
+ },
12
+ {
13
+ identifier: "wms_integration_shipping_shipments",
14
+ name: "Shipping Shipment Coordination",
15
+ description: "Allows WMS to react to shipping shipment lifecycle events when shipment orchestration is enabled.",
16
+ category: "wms",
17
+ type: "boolean",
18
+ defaultValue: true
19
+ },
20
+ {
21
+ identifier: "wms_integration_procurement_goods_receipt",
22
+ name: "Procurement Goods Receipt Bridge",
23
+ description: "Reserved toggle for future procurement-driven receiving integration.",
24
+ category: "wms",
25
+ type: "boolean",
26
+ defaultValue: false
27
+ }
28
+ ];
29
+ function findWmsIntegrationToggleDefinition(identifier) {
30
+ return WMS_INTEGRATION_TOGGLES.find((toggle) => toggle.identifier === identifier) ?? null;
31
+ }
32
+ async function seedWmsIntegrationToggles(em) {
33
+ for (const toggle of WMS_INTEGRATION_TOGGLES) {
34
+ const existing = await findOneWithDecryption(em, FeatureToggle, {
35
+ identifier: toggle.identifier,
36
+ deletedAt: null
37
+ });
38
+ if (existing) continue;
39
+ em.persist(
40
+ em.create(FeatureToggle, {
41
+ identifier: toggle.identifier,
42
+ name: toggle.name,
43
+ description: toggle.description,
44
+ category: toggle.category,
45
+ type: toggle.type,
46
+ defaultValue: toggle.defaultValue
47
+ })
48
+ );
49
+ }
50
+ await em.flush();
51
+ }
52
+ async function resolveWmsIntegrationToggleEnabled(featureTogglesService, em, identifier, tenantId) {
53
+ const definition = findWmsIntegrationToggleDefinition(identifier);
54
+ const fallback = definition?.defaultValue ?? true;
55
+ const result = await featureTogglesService.getBoolConfig(identifier, tenantId);
56
+ if (result.ok) return result.value;
57
+ if (result.error?.code !== "MISSING_TOGGLE" || !definition) {
58
+ return fallback;
59
+ }
60
+ await seedWmsIntegrationToggles(em);
61
+ await featureTogglesService.invalidateIsEnabledCacheByKey(identifier, tenantId);
62
+ const retried = await featureTogglesService.getBoolConfig(identifier, tenantId);
63
+ return retried.ok ? retried.value : fallback;
64
+ }
65
+ export {
66
+ WMS_INTEGRATION_TOGGLES,
67
+ findWmsIntegrationToggleDefinition,
68
+ resolveWmsIntegrationToggleEnabled,
69
+ seedWmsIntegrationToggles
70
+ };
71
+ //# sourceMappingURL=wmsIntegrationToggles.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/wms/lib/wmsIntegrationToggles.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { FeatureToggle } from '@open-mercato/core/modules/feature_toggles/data/entities'\nimport type { FeatureTogglesService } from '@open-mercato/core/modules/feature_toggles/lib/feature-flag-check'\n\nexport const WMS_INTEGRATION_TOGGLES = [\n {\n identifier: 'wms_integration_sales_order_inventory',\n name: 'Sales Order Inventory Reservation',\n description: 'Allows WMS to reserve and release inventory from sales order lifecycle events.',\n category: 'wms',\n type: 'boolean' as const,\n defaultValue: true,\n },\n {\n identifier: 'wms_integration_shipping_shipments',\n name: 'Shipping Shipment Coordination',\n description: 'Allows WMS to react to shipping shipment lifecycle events when shipment orchestration is enabled.',\n category: 'wms',\n type: 'boolean' as const,\n defaultValue: true,\n },\n {\n identifier: 'wms_integration_procurement_goods_receipt',\n name: 'Procurement Goods Receipt Bridge',\n description: 'Reserved toggle for future procurement-driven receiving integration.',\n category: 'wms',\n type: 'boolean' as const,\n defaultValue: false,\n },\n] as const\n\nexport type WmsIntegrationToggleIdentifier = (typeof WMS_INTEGRATION_TOGGLES)[number]['identifier']\n\nexport function findWmsIntegrationToggleDefinition(identifier: string) {\n return WMS_INTEGRATION_TOGGLES.find((toggle) => toggle.identifier === identifier) ?? null\n}\n\nexport async function seedWmsIntegrationToggles(em: EntityManager): Promise<void> {\n for (const toggle of WMS_INTEGRATION_TOGGLES) {\n const existing = await findOneWithDecryption(em, FeatureToggle, {\n identifier: toggle.identifier,\n deletedAt: null,\n })\n if (existing) continue\n em.persist(\n em.create(FeatureToggle, {\n identifier: toggle.identifier,\n name: toggle.name,\n description: toggle.description,\n category: toggle.category,\n type: toggle.type,\n defaultValue: toggle.defaultValue,\n }),\n )\n }\n await em.flush()\n}\n\nexport async function resolveWmsIntegrationToggleEnabled(\n featureTogglesService: FeatureTogglesService,\n em: EntityManager,\n identifier: WmsIntegrationToggleIdentifier,\n tenantId: string,\n): Promise<boolean> {\n const definition = findWmsIntegrationToggleDefinition(identifier)\n const fallback = definition?.defaultValue ?? true\n\n const result = await featureTogglesService.getBoolConfig(identifier, tenantId)\n if (result.ok) return result.value\n\n if (result.error?.code !== 'MISSING_TOGGLE' || !definition) {\n return fallback\n }\n\n await seedWmsIntegrationToggles(em)\n await featureTogglesService.invalidateIsEnabledCacheByKey(identifier, tenantId)\n\n const retried = await featureTogglesService.getBoolConfig(identifier, tenantId)\n return retried.ok ? retried.value : fallback\n}\n"],
5
+ "mappings": "AACA,SAAS,6BAA6B;AACtC,SAAS,qBAAqB;AAGvB,MAAM,0BAA0B;AAAA,EACrC;AAAA,IACE,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AACF;AAIO,SAAS,mCAAmC,YAAoB;AACrE,SAAO,wBAAwB,KAAK,CAAC,WAAW,OAAO,eAAe,UAAU,KAAK;AACvF;AAEA,eAAsB,0BAA0B,IAAkC;AAChF,aAAW,UAAU,yBAAyB;AAC5C,UAAM,WAAW,MAAM,sBAAsB,IAAI,eAAe;AAAA,MAC9D,YAAY,OAAO;AAAA,MACnB,WAAW;AAAA,IACb,CAAC;AACD,QAAI,SAAU;AACd,OAAG;AAAA,MACD,GAAG,OAAO,eAAe;AAAA,QACvB,YAAY,OAAO;AAAA,QACnB,MAAM,OAAO;AAAA,QACb,aAAa,OAAO;AAAA,QACpB,UAAU,OAAO;AAAA,QACjB,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACA,QAAM,GAAG,MAAM;AACjB;AAEA,eAAsB,mCACpB,uBACA,IACA,YACA,UACkB;AAClB,QAAM,aAAa,mCAAmC,UAAU;AAChE,QAAM,WAAW,YAAY,gBAAgB;AAE7C,QAAM,SAAS,MAAM,sBAAsB,cAAc,YAAY,QAAQ;AAC7E,MAAI,OAAO,GAAI,QAAO,OAAO;AAE7B,MAAI,OAAO,OAAO,SAAS,oBAAoB,CAAC,YAAY;AAC1D,WAAO;AAAA,EACT;AAEA,QAAM,0BAA0B,EAAE;AAClC,QAAM,sBAAsB,8BAA8B,YAAY,QAAQ;AAE9E,QAAM,UAAU,MAAM,sBAAsB,cAAc,YAAY,QAAQ;AAC9E,SAAO,QAAQ,KAAK,QAAQ,QAAQ;AACtC;",
6
+ "names": []
7
+ }