@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,91 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+
3
+ export class Migration20260428110546_wms extends Migration {
4
+
5
+ override up(): void | Promise<void> {
6
+ this.addSql(`create table "wms_inventory_lots" ("id" uuid not null default gen_random_uuid(), "organization_id" uuid not null, "tenant_id" uuid not null, "metadata" jsonb null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, "catalog_variant_id" uuid not null, "sku" text not null, "lot_number" text not null, "batch_number" text null, "manufactured_at" timestamptz null, "best_before_at" timestamptz null, "expires_at" timestamptz null, "status" text not null default 'available', primary key ("id"));`);
7
+ this.addSql(`create unique index "wms_inventory_lots_variant_lot_unique_idx" on "wms_inventory_lots" ("organization_id", "catalog_variant_id", "lot_number") where deleted_at is null;`);
8
+ this.addSql(`create index "wms_inventory_lots_variant_idx" on "wms_inventory_lots" ("catalog_variant_id");`);
9
+ this.addSql(`create index "wms_inventory_lots_org_tenant_idx" on "wms_inventory_lots" ("organization_id", "tenant_id");`);
10
+
11
+ this.addSql(`create table "wms_product_inventory_profiles" ("id" uuid not null default gen_random_uuid(), "organization_id" uuid not null, "tenant_id" uuid not null, "metadata" jsonb null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, "catalog_product_id" uuid not null, "catalog_variant_id" uuid null, "default_uom" text not null, "track_lot" boolean not null default false, "track_serial" boolean not null default false, "track_expiration" boolean not null default false, "default_strategy" text not null, "reorder_point" numeric(16,4) not null default '0', "safety_stock" numeric(16,4) not null default '0', primary key ("id"));`);
12
+ this.addSql(`create unique index "wms_inventory_profiles_product_unique_idx" on "wms_product_inventory_profiles" ("organization_id", "catalog_product_id") where deleted_at is null and catalog_variant_id is null;`);
13
+ this.addSql(`create unique index "wms_inventory_profiles_variant_unique_idx" on "wms_product_inventory_profiles" ("organization_id", "catalog_variant_id") where deleted_at is null and catalog_variant_id is not null;`);
14
+ this.addSql(`create index "wms_inventory_profiles_org_tenant_idx" on "wms_product_inventory_profiles" ("organization_id", "tenant_id");`);
15
+
16
+ this.addSql(`create table "wms_warehouses" ("id" uuid not null default gen_random_uuid(), "organization_id" uuid not null, "tenant_id" uuid not null, "metadata" jsonb null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, "name" text not null, "code" text not null, "is_active" boolean not null default true, "address_line1" text null, "city" text null, "postal_code" text null, "country" text null, "timezone" text null, primary key ("id"));`);
17
+ this.addSql(`create unique index "wms_warehouses_org_code_unique_idx" on "wms_warehouses" ("organization_id", "code") where deleted_at is null;`);
18
+ this.addSql(`create index "wms_warehouses_org_tenant_idx" on "wms_warehouses" ("organization_id", "tenant_id");`);
19
+
20
+ this.addSql(`create table "wms_inventory_reservations" ("id" uuid not null default gen_random_uuid(), "organization_id" uuid not null, "tenant_id" uuid not null, "metadata" jsonb null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, "warehouse_id" uuid not null, "catalog_variant_id" uuid not null, "lot_id" uuid null, "serial_number" text null, "quantity" numeric(16,4) not null, "source_type" text not null, "source_id" uuid not null, "expires_at" timestamptz null, "status" text not null default 'active', primary key ("id"));`);
21
+ this.addSql(`create index "wms_inventory_reservations_status_idx" on "wms_inventory_reservations" ("organization_id", "warehouse_id", "catalog_variant_id", "status");`);
22
+ this.addSql(`create index "wms_inventory_reservations_source_idx" on "wms_inventory_reservations" ("organization_id", "source_type", "source_id");`);
23
+ this.addSql(`create index "wms_inventory_reservations_org_tenant_idx" on "wms_inventory_reservations" ("organization_id", "tenant_id");`);
24
+
25
+ this.addSql(`create table "wms_warehouse_locations" ("id" uuid not null default gen_random_uuid(), "organization_id" uuid not null, "tenant_id" uuid not null, "metadata" jsonb null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, "warehouse_id" uuid not null, "code" text not null, "type" text not null, "parent_id" uuid null, "is_active" boolean not null default true, "capacity_units" numeric(16,4) null, "capacity_weight" numeric(16,4) null, "constraints" jsonb null, primary key ("id"));`);
26
+ this.addSql(`create unique index "wms_warehouse_locations_warehouse_code_unique_idx" on "wms_warehouse_locations" ("warehouse_id", "code") where deleted_at is null;`);
27
+ this.addSql(`create index "wms_warehouse_locations_parent_idx" on "wms_warehouse_locations" ("parent_id");`);
28
+ this.addSql(`create index "wms_warehouse_locations_warehouse_idx" on "wms_warehouse_locations" ("warehouse_id");`);
29
+ this.addSql(`create index "wms_warehouse_locations_org_tenant_idx" on "wms_warehouse_locations" ("organization_id", "tenant_id");`);
30
+
31
+ this.addSql(`create table "wms_inventory_movements" ("id" uuid not null default gen_random_uuid(), "organization_id" uuid not null, "tenant_id" uuid not null, "metadata" jsonb null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, "warehouse_id" uuid not null, "location_from_id" uuid null, "location_to_id" uuid null, "catalog_variant_id" uuid not null, "lot_id" uuid null, "serial_number" text null, "quantity" numeric(16,4) not null, "type" text not null, "reference_type" text not null, "reference_id" uuid not null, "performed_by" uuid not null, "performed_at" timestamptz not null, "received_at" timestamptz not null, "reason" text null, primary key ("id"));`);
32
+ this.addSql(`create index "wms_inventory_movements_warehouse_performed_at_idx" on "wms_inventory_movements" ("organization_id", "warehouse_id", "performed_at" desc) where deleted_at is null;`);
33
+ this.addSql(`create index "wms_inventory_movements_reference_idx" on "wms_inventory_movements" ("organization_id", "reference_type", "reference_id");`);
34
+ this.addSql(`create index "wms_inventory_movements_variant_received_at_idx" on "wms_inventory_movements" ("organization_id", "catalog_variant_id", "received_at" desc) where deleted_at is null;`);
35
+ this.addSql(`create index "wms_inventory_movements_org_tenant_idx" on "wms_inventory_movements" ("organization_id", "tenant_id");`);
36
+
37
+ this.addSql(`create table "wms_inventory_balances" ("id" uuid not null default gen_random_uuid(), "organization_id" uuid not null, "tenant_id" uuid not null, "metadata" jsonb null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, "warehouse_id" uuid not null, "location_id" uuid not null, "catalog_variant_id" uuid not null, "lot_id" uuid null, "serial_number" text null, "quantity_on_hand" numeric(16,4) not null default '0', "quantity_reserved" numeric(16,4) not null default '0', "quantity_allocated" numeric(16,4) not null default '0', primary key ("id"));`);
38
+ this.addSql(`create unique index "wms_inventory_balances_serial_unique_idx" on "wms_inventory_balances" ("organization_id", "warehouse_id", "location_id", "catalog_variant_id", "serial_number") where serial_number is not null and deleted_at is null;`);
39
+ this.addSql(`create index "wms_inventory_balances_org_lot_idx" on "wms_inventory_balances" ("organization_id", "lot_id") where lot_id is not null and deleted_at is null;`);
40
+ this.addSql(`create index "wms_inventory_balances_org_location_variant_idx" on "wms_inventory_balances" ("organization_id", "location_id", "catalog_variant_id");`);
41
+ this.addSql(`create index "wms_inventory_balances_org_warehouse_variant_idx" on "wms_inventory_balances" ("organization_id", "warehouse_id", "catalog_variant_id");`);
42
+ this.addSql(`create index "wms_inventory_balances_org_tenant_idx" on "wms_inventory_balances" ("organization_id", "tenant_id");`);
43
+
44
+ this.addSql(`create table "wms_warehouse_zones" ("id" uuid not null default gen_random_uuid(), "organization_id" uuid not null, "tenant_id" uuid not null, "metadata" jsonb null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, "warehouse_id" uuid not null, "code" text not null, "name" text not null, "priority" int not null default 0, primary key ("id"));`);
45
+ this.addSql(`create unique index "wms_warehouse_zones_warehouse_code_unique_idx" on "wms_warehouse_zones" ("warehouse_id", "code") where deleted_at is null;`);
46
+ this.addSql(`create index "wms_warehouse_zones_warehouse_idx" on "wms_warehouse_zones" ("warehouse_id");`);
47
+ this.addSql(`create index "wms_warehouse_zones_org_tenant_idx" on "wms_warehouse_zones" ("organization_id", "tenant_id");`);
48
+
49
+ this.addSql(`alter table "wms_inventory_reservations" add constraint "wms_inventory_reservations_warehouse_id_foreign" foreign key ("warehouse_id") references "wms_warehouses" ("id");`);
50
+ this.addSql(`alter table "wms_inventory_reservations" add constraint "wms_inventory_reservations_lot_id_foreign" foreign key ("lot_id") references "wms_inventory_lots" ("id") on delete set null;`);
51
+
52
+ this.addSql(`alter table "wms_warehouse_locations" add constraint "wms_warehouse_locations_warehouse_id_foreign" foreign key ("warehouse_id") references "wms_warehouses" ("id");`);
53
+ this.addSql(`alter table "wms_warehouse_locations" add constraint "wms_warehouse_locations_parent_id_foreign" foreign key ("parent_id") references "wms_warehouse_locations" ("id") on delete set null;`);
54
+
55
+ this.addSql(`alter table "wms_inventory_movements" add constraint "wms_inventory_movements_warehouse_id_foreign" foreign key ("warehouse_id") references "wms_warehouses" ("id");`);
56
+ this.addSql(`alter table "wms_inventory_movements" add constraint "wms_inventory_movements_location_from_id_foreign" foreign key ("location_from_id") references "wms_warehouse_locations" ("id") on delete set null;`);
57
+ this.addSql(`alter table "wms_inventory_movements" add constraint "wms_inventory_movements_location_to_id_foreign" foreign key ("location_to_id") references "wms_warehouse_locations" ("id") on delete set null;`);
58
+ this.addSql(`alter table "wms_inventory_movements" add constraint "wms_inventory_movements_lot_id_foreign" foreign key ("lot_id") references "wms_inventory_lots" ("id") on delete set null;`);
59
+
60
+ this.addSql(`alter table "wms_inventory_balances" add constraint "wms_inventory_balances_warehouse_id_foreign" foreign key ("warehouse_id") references "wms_warehouses" ("id");`);
61
+ this.addSql(`alter table "wms_inventory_balances" add constraint "wms_inventory_balances_location_id_foreign" foreign key ("location_id") references "wms_warehouse_locations" ("id");`);
62
+ this.addSql(`alter table "wms_inventory_balances" add constraint "wms_inventory_balances_lot_id_foreign" foreign key ("lot_id") references "wms_inventory_lots" ("id") on delete set null;`);
63
+
64
+ this.addSql(`alter table "wms_warehouse_zones" add constraint "wms_warehouse_zones_warehouse_id_foreign" foreign key ("warehouse_id") references "wms_warehouses" ("id");`);
65
+ }
66
+
67
+ override down(): void | Promise<void> {
68
+ this.addSql(`alter table "wms_inventory_reservations" drop constraint if exists "wms_inventory_reservations_lot_id_foreign";`);
69
+ this.addSql(`alter table "wms_inventory_movements" drop constraint if exists "wms_inventory_movements_lot_id_foreign";`);
70
+ this.addSql(`alter table "wms_inventory_balances" drop constraint if exists "wms_inventory_balances_lot_id_foreign";`);
71
+ this.addSql(`alter table "wms_inventory_reservations" drop constraint if exists "wms_inventory_reservations_warehouse_id_foreign";`);
72
+ this.addSql(`alter table "wms_warehouse_locations" drop constraint if exists "wms_warehouse_locations_warehouse_id_foreign";`);
73
+ this.addSql(`alter table "wms_inventory_movements" drop constraint if exists "wms_inventory_movements_warehouse_id_foreign";`);
74
+ this.addSql(`alter table "wms_inventory_balances" drop constraint if exists "wms_inventory_balances_warehouse_id_foreign";`);
75
+ this.addSql(`alter table "wms_warehouse_zones" drop constraint if exists "wms_warehouse_zones_warehouse_id_foreign";`);
76
+ this.addSql(`alter table "wms_warehouse_locations" drop constraint if exists "wms_warehouse_locations_parent_id_foreign";`);
77
+ this.addSql(`alter table "wms_inventory_movements" drop constraint if exists "wms_inventory_movements_location_from_id_foreign";`);
78
+ this.addSql(`alter table "wms_inventory_movements" drop constraint if exists "wms_inventory_movements_location_to_id_foreign";`);
79
+ this.addSql(`alter table "wms_inventory_balances" drop constraint if exists "wms_inventory_balances_location_id_foreign";`);
80
+
81
+ this.addSql(`drop table if exists "wms_warehouse_zones" cascade;`);
82
+ this.addSql(`drop table if exists "wms_inventory_balances" cascade;`);
83
+ this.addSql(`drop table if exists "wms_inventory_movements" cascade;`);
84
+ this.addSql(`drop table if exists "wms_warehouse_locations" cascade;`);
85
+ this.addSql(`drop table if exists "wms_inventory_reservations" cascade;`);
86
+ this.addSql(`drop table if exists "wms_warehouses" cascade;`);
87
+ this.addSql(`drop table if exists "wms_product_inventory_profiles" cascade;`);
88
+ this.addSql(`drop table if exists "wms_inventory_lots" cascade;`);
89
+ }
90
+
91
+ }
@@ -0,0 +1,15 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+
3
+ export class Migration20260527120000_wms extends Migration {
4
+
5
+ override up(): void | Promise<void> {
6
+ this.addSql(`alter table "wms_warehouses" add column "is_primary" boolean not null default false;`);
7
+ this.addSql(`create unique index "wms_warehouses_org_primary_unique_idx" on "wms_warehouses" ("organization_id") where deleted_at is null and is_primary = true;`);
8
+ }
9
+
10
+ override down(): void | Promise<void> {
11
+ this.addSql(`drop index if exists "wms_warehouses_org_primary_unique_idx";`);
12
+ this.addSql(`alter table "wms_warehouses" drop column if exists "is_primary";`);
13
+ }
14
+
15
+ }
@@ -0,0 +1,35 @@
1
+ import { Migration } from '@mikro-orm/migrations'
2
+
3
+ export class Migration20260527140000_wms extends Migration {
4
+ override up(): void | Promise<void> {
5
+ this.addSql(`
6
+ create table "wms_sales_order_warehouse_assignments" (
7
+ "id" uuid not null default gen_random_uuid(),
8
+ "organization_id" uuid not null,
9
+ "tenant_id" uuid not null,
10
+ "sales_order_id" uuid not null,
11
+ "warehouse_id" uuid not null,
12
+ "assigned_by" uuid,
13
+ "notes" text,
14
+ "metadata" jsonb,
15
+ "created_at" timestamptz not null default now(),
16
+ "updated_at" timestamptz not null default now(),
17
+ "deleted_at" timestamptz,
18
+ constraint "wms_sowa_pkey" primary key ("id")
19
+ );
20
+ `)
21
+ this.addSql(
22
+ `create index "wms_sowa_org_tenant_idx" on "wms_sales_order_warehouse_assignments" ("organization_id", "tenant_id");`,
23
+ )
24
+ this.addSql(
25
+ `create index "wms_sowa_warehouse_idx" on "wms_sales_order_warehouse_assignments" ("warehouse_id");`,
26
+ )
27
+ this.addSql(
28
+ `create unique index "wms_sowa_org_order_unique_idx" on "wms_sales_order_warehouse_assignments" ("organization_id", "sales_order_id") where deleted_at is null;`,
29
+ )
30
+ }
31
+
32
+ override down(): void | Promise<void> {
33
+ this.addSql(`drop table if exists "wms_sales_order_warehouse_assignments";`)
34
+ }
35
+ }
@@ -0,0 +1,21 @@
1
+ import { Migration } from '@mikro-orm/migrations'
2
+
3
+ export class Migration20260613120000_wms extends Migration {
4
+ override up(): void | Promise<void> {
5
+ this.addSql(`alter table "wms_inventory_movements" add column "idempotency_key" text null;`)
6
+ this.addSql(`alter table "wms_inventory_reservations" add column "idempotency_key" text null;`)
7
+ this.addSql(
8
+ `create unique index "wms_inventory_movements_idempotency_unique_idx" on "wms_inventory_movements" ("organization_id", "idempotency_key") where idempotency_key is not null and deleted_at is null;`,
9
+ )
10
+ this.addSql(
11
+ `create unique index "wms_inventory_reservations_idempotency_unique_idx" on "wms_inventory_reservations" ("organization_id", "idempotency_key") where idempotency_key is not null and deleted_at is null and status = 'active';`,
12
+ )
13
+ }
14
+
15
+ override down(): void | Promise<void> {
16
+ this.addSql(`drop index if exists "wms_inventory_reservations_idempotency_unique_idx";`)
17
+ this.addSql(`drop index if exists "wms_inventory_movements_idempotency_unique_idx";`)
18
+ this.addSql(`alter table "wms_inventory_reservations" drop column if exists "idempotency_key";`)
19
+ this.addSql(`alter table "wms_inventory_movements" drop column if exists "idempotency_key";`)
20
+ }
21
+ }
@@ -0,0 +1,11 @@
1
+ import { Migration } from '@mikro-orm/migrations'
2
+
3
+ export class Migration20260616090000_wms extends Migration {
4
+ override up(): void | Promise<void> {
5
+ this.addSql(`alter table "wms_inventory_movements" add column "reason_code" text null;`)
6
+ }
7
+
8
+ override down(): void | Promise<void> {
9
+ this.addSql(`alter table "wms_inventory_movements" drop column if exists "reason_code";`)
10
+ }
11
+ }
@@ -0,0 +1,13 @@
1
+ import { Migration } from '@mikro-orm/migrations'
2
+
3
+ export class Migration20260707180000_wms extends Migration {
4
+ override up(): void | Promise<void> {
5
+ this.addSql(
6
+ `alter table "wms_inventory_balances" add column "quantity_available" numeric(16,4) generated always as ("quantity_on_hand" - "quantity_reserved" - "quantity_allocated") stored not null;`,
7
+ )
8
+ }
9
+
10
+ override down(): void | Promise<void> {
11
+ this.addSql(`alter table "wms_inventory_balances" drop column if exists "quantity_available";`)
12
+ }
13
+ }
@@ -0,0 +1,18 @@
1
+ 'use client'
2
+
3
+ import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'
4
+ import { notificationTypes } from './notifications'
5
+ import { WmsLowStockRenderer } from './widgets/notifications/WmsLowStockRenderer'
6
+ import { WmsReservationShortfallRenderer } from './widgets/notifications/WmsReservationShortfallRenderer'
7
+
8
+ const rendererMap: Record<string, NotificationTypeDefinition['Renderer']> = {
9
+ 'wms.inventory.low_stock': WmsLowStockRenderer,
10
+ 'wms.inventory.reservation_shortfall': WmsReservationShortfallRenderer,
11
+ }
12
+
13
+ export const wmsNotificationTypes: NotificationTypeDefinition[] = notificationTypes.map((type) => ({
14
+ ...type,
15
+ Renderer: rendererMap[type.type],
16
+ }))
17
+
18
+ export default wmsNotificationTypes
@@ -0,0 +1,51 @@
1
+ import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'
2
+
3
+ export const notificationTypes: NotificationTypeDefinition[] = [
4
+ {
5
+ type: 'wms.inventory.low_stock',
6
+ module: 'wms',
7
+ titleKey: 'wms.notifications.lowStock.title',
8
+ bodyKey: 'wms.notifications.lowStock.body',
9
+ icon: 'alert-triangle',
10
+ severity: 'warning',
11
+ actions: [
12
+ {
13
+ id: 'view',
14
+ labelKey: 'wms.notifications.lowStock.renderer.viewInventory',
15
+ variant: 'outline',
16
+ href: '/backend/wms/inventory',
17
+ icon: 'external-link',
18
+ },
19
+ ],
20
+ linkHref: '/backend/wms/inventory',
21
+ expiresAfterHours: 72,
22
+ },
23
+ {
24
+ type: 'wms.inventory.reservation_shortfall',
25
+ module: 'wms',
26
+ titleKey: 'wms.notifications.reservationShortfall.title',
27
+ bodyKey: 'wms.notifications.reservationShortfall.body',
28
+ icon: 'alert-triangle',
29
+ severity: 'warning',
30
+ actions: [
31
+ {
32
+ id: 'view-order',
33
+ labelKey: 'wms.notifications.reservationShortfall.renderer.viewOrder',
34
+ variant: 'outline',
35
+ href: '/backend/sales/orders/{sourceEntityId}',
36
+ icon: 'external-link',
37
+ },
38
+ {
39
+ id: 'view-inventory',
40
+ labelKey: 'wms.notifications.reservationShortfall.renderer.viewInventory',
41
+ variant: 'outline',
42
+ href: '/backend/wms/inventory',
43
+ icon: 'external-link',
44
+ },
45
+ ],
46
+ linkHref: '/backend/sales/orders/{sourceEntityId}',
47
+ expiresAfterHours: 72,
48
+ },
49
+ ]
50
+
51
+ export default notificationTypes
@@ -0,0 +1,230 @@
1
+ import type {
2
+ SearchBuildContext,
3
+ SearchIndexSource,
4
+ SearchModuleConfig,
5
+ SearchResultPresenter,
6
+ } from '@open-mercato/shared/modules/search'
7
+ import type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'
8
+ import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
9
+ import { E } from '#generated/entities.ids.generated'
10
+
11
+ const WMS_ROOT_URL = '/backend/wms'
12
+ const WMS_INVENTORY_URL = '/backend/wms/inventory'
13
+ const WMS_CONFIG_URL = '/backend/config/wms'
14
+
15
+ function pickString(...candidates: Array<unknown>): string | null {
16
+ for (const candidate of candidates) {
17
+ if (typeof candidate !== 'string') continue
18
+ const trimmed = candidate.trim()
19
+ if (trimmed.length > 0) return trimmed
20
+ }
21
+ return null
22
+ }
23
+
24
+ function appendLine(lines: string[], label: string, value: unknown) {
25
+ if (value === null || value === undefined) return
26
+ const text = Array.isArray(value)
27
+ ? value.map((item) => (item == null ? '' : String(item))).filter(Boolean).join(', ')
28
+ : typeof value === 'object'
29
+ ? JSON.stringify(value)
30
+ : String(value)
31
+ if (!text.trim()) return
32
+ lines.push(`${label}: ${text}`)
33
+ }
34
+
35
+ function formatSubtitle(...parts: Array<unknown>): string | undefined {
36
+ const values = parts
37
+ .map((part) => (part == null ? '' : String(part)).trim())
38
+ .filter(Boolean)
39
+ if (!values.length) return undefined
40
+ return values.join(' · ')
41
+ }
42
+
43
+ function buildIndexSource(
44
+ ctx: SearchBuildContext,
45
+ presenter: SearchResultPresenter,
46
+ lines: string[],
47
+ ): SearchIndexSource | null {
48
+ for (const [key, value] of Object.entries(ctx.customFields)) {
49
+ appendLine(lines, key.replace(/^cf:/, ''), value)
50
+ }
51
+ if (!lines.length) return null
52
+ return {
53
+ text: lines,
54
+ presenter,
55
+ checksumSource: { record: ctx.record, customFields: ctx.customFields },
56
+ }
57
+ }
58
+
59
+ function buildWarehousePresenter(
60
+ t: TranslateFn,
61
+ record: Record<string, unknown>,
62
+ ): SearchResultPresenter {
63
+ const label = t('wms.search.badge.warehouse', 'Warehouse')
64
+ const title = pickString(record.name, record.code, record.id) ?? label
65
+ const subtitle = formatSubtitle(record.code, record.city, record.country)
66
+ return { title, subtitle, icon: 'warehouse', badge: label }
67
+ }
68
+
69
+ function buildLocationPresenter(
70
+ t: TranslateFn,
71
+ record: Record<string, unknown>,
72
+ ): SearchResultPresenter {
73
+ const label = t('wms.search.badge.location', 'Location')
74
+ const title = pickString(record.code, record.id) ?? label
75
+ const subtitle = formatSubtitle(record.type, record.warehouse_id ?? record.warehouseId)
76
+ return { title, subtitle, icon: 'map-pinned', badge: label }
77
+ }
78
+
79
+ function buildInventoryProfilePresenter(
80
+ t: TranslateFn,
81
+ record: Record<string, unknown>,
82
+ ): SearchResultPresenter {
83
+ const label = t('wms.search.badge.inventoryProfile', 'Inventory profile')
84
+ const productId = pickString(record.catalog_product_id, record.catalogProductId)
85
+ const variantId = pickString(record.catalog_variant_id, record.catalogVariantId)
86
+ const title = variantId || productId || pickString(record.id) || label
87
+ const subtitle = formatSubtitle(
88
+ record.default_strategy ?? record.defaultStrategy,
89
+ record.default_uom ?? record.defaultUom,
90
+ variantId ? t('wms.search.profile.variantScoped', 'Variant-scoped') : t('wms.search.profile.productScoped', 'Product-scoped'),
91
+ )
92
+ return { title, subtitle, icon: 'boxes', badge: label }
93
+ }
94
+
95
+ function buildLotPresenter(
96
+ t: TranslateFn,
97
+ record: Record<string, unknown>,
98
+ ): SearchResultPresenter {
99
+ const label = t('wms.search.badge.lot', 'Inventory lot')
100
+ const title = pickString(record.lot_number, record.lotNumber, record.batch_number, record.batchNumber, record.id) ?? label
101
+ const subtitle = formatSubtitle(record.catalog_variant_id ?? record.catalogVariantId, record.status, record.expires_at ?? record.expiresAt)
102
+ return { title, subtitle, icon: 'package-search', badge: label }
103
+ }
104
+
105
+ export const searchConfig: SearchModuleConfig = {
106
+ entities: [
107
+ {
108
+ entityId: E.wms.warehouse,
109
+ enabled: true,
110
+ priority: 8,
111
+ buildSource: async (ctx) => {
112
+ const { t } = await resolveTranslations()
113
+ const record = ctx.record
114
+ const lines: string[] = []
115
+ appendLine(lines, 'Name', record.name)
116
+ appendLine(lines, 'Code', record.code)
117
+ appendLine(lines, 'City', record.city)
118
+ appendLine(lines, 'Country', record.country)
119
+ appendLine(lines, 'Timezone', record.timezone)
120
+ return buildIndexSource(ctx, buildWarehousePresenter(t, record), lines)
121
+ },
122
+ formatResult: async (ctx) => {
123
+ const { t } = await resolveTranslations()
124
+ return buildWarehousePresenter(t, ctx.record)
125
+ },
126
+ resolveUrl: async () => WMS_CONFIG_URL,
127
+ fieldPolicy: {
128
+ searchable: ['name', 'code', 'city', 'country', 'timezone'],
129
+ },
130
+ },
131
+ {
132
+ entityId: E.wms.warehouse_location,
133
+ enabled: true,
134
+ priority: 7,
135
+ buildSource: async (ctx) => {
136
+ const { t } = await resolveTranslations()
137
+ const record = ctx.record
138
+ const lines: string[] = []
139
+ appendLine(lines, 'Code', record.code)
140
+ appendLine(lines, 'Type', record.type)
141
+ appendLine(lines, 'Warehouse', record.warehouse_id ?? record.warehouseId)
142
+ appendLine(lines, 'Parent', record.parent_id ?? record.parentId)
143
+ appendLine(lines, 'Capacity units', record.capacity_units ?? record.capacityUnits)
144
+ appendLine(lines, 'Capacity weight', record.capacity_weight ?? record.capacityWeight)
145
+ return buildIndexSource(ctx, buildLocationPresenter(t, record), lines)
146
+ },
147
+ formatResult: async (ctx) => {
148
+ const { t } = await resolveTranslations()
149
+ return buildLocationPresenter(t, ctx.record)
150
+ },
151
+ resolveUrl: async () => WMS_CONFIG_URL,
152
+ fieldPolicy: {
153
+ searchable: ['code', 'type', 'warehouse_id', 'parent_id', 'capacity_units', 'capacity_weight'],
154
+ },
155
+ },
156
+ {
157
+ entityId: E.wms.product_inventory_profile,
158
+ enabled: true,
159
+ priority: 8,
160
+ buildSource: async (ctx) => {
161
+ const { t } = await resolveTranslations()
162
+ const record = ctx.record
163
+ const lines: string[] = []
164
+ appendLine(lines, 'Product', record.catalog_product_id ?? record.catalogProductId)
165
+ appendLine(lines, 'Variant', record.catalog_variant_id ?? record.catalogVariantId)
166
+ appendLine(lines, 'Default UOM', record.default_uom ?? record.defaultUom)
167
+ appendLine(lines, 'Strategy', record.default_strategy ?? record.defaultStrategy)
168
+ appendLine(lines, 'Reorder point', record.reorder_point ?? record.reorderPoint)
169
+ appendLine(lines, 'Safety stock', record.safety_stock ?? record.safetyStock)
170
+ appendLine(lines, 'Track lot', record.track_lot ?? record.trackLot)
171
+ appendLine(lines, 'Track serial', record.track_serial ?? record.trackSerial)
172
+ appendLine(lines, 'Track expiration', record.track_expiration ?? record.trackExpiration)
173
+ return buildIndexSource(ctx, buildInventoryProfilePresenter(t, record), lines)
174
+ },
175
+ formatResult: async (ctx) => {
176
+ const { t } = await resolveTranslations()
177
+ return buildInventoryProfilePresenter(t, ctx.record)
178
+ },
179
+ resolveUrl: async (ctx) => {
180
+ const variantId = pickString(ctx.record.catalog_variant_id, ctx.record.catalogVariantId)
181
+ if (variantId) return `${WMS_ROOT_URL}/sku/${variantId}`
182
+ return WMS_CONFIG_URL
183
+ },
184
+ resolveLinks: async () => [{ href: WMS_INVENTORY_URL, label: 'Inventory console', kind: 'secondary' }],
185
+ fieldPolicy: {
186
+ searchable: [
187
+ 'catalog_product_id',
188
+ 'catalog_variant_id',
189
+ 'default_uom',
190
+ 'default_strategy',
191
+ 'reorder_point',
192
+ 'safety_stock',
193
+ ],
194
+ },
195
+ },
196
+ {
197
+ entityId: E.wms.inventory_lot,
198
+ enabled: true,
199
+ priority: 6,
200
+ buildSource: async (ctx) => {
201
+ const { t } = await resolveTranslations()
202
+ const record = ctx.record
203
+ const lines: string[] = []
204
+ appendLine(lines, 'Lot number', record.lot_number ?? record.lotNumber)
205
+ appendLine(lines, 'Batch number', record.batch_number ?? record.batchNumber)
206
+ appendLine(lines, 'SKU', record.sku)
207
+ appendLine(lines, 'Variant', record.catalog_variant_id ?? record.catalogVariantId)
208
+ appendLine(lines, 'Status', record.status)
209
+ appendLine(lines, 'Expires at', record.expires_at ?? record.expiresAt)
210
+ return buildIndexSource(ctx, buildLotPresenter(t, record), lines)
211
+ },
212
+ formatResult: async (ctx) => {
213
+ const { t } = await resolveTranslations()
214
+ return buildLotPresenter(t, ctx.record)
215
+ },
216
+ resolveUrl: async (ctx) => {
217
+ const id = pickString(ctx.record.id)
218
+ if (id) return `${WMS_ROOT_URL}/lot/${id}`
219
+ return WMS_ROOT_URL
220
+ },
221
+ resolveLinks: async () => [{ href: WMS_CONFIG_URL, label: 'WMS configuration', kind: 'secondary' }],
222
+ fieldPolicy: {
223
+ searchable: ['lot_number', 'batch_number', 'sku', 'catalog_variant_id', 'status', 'expires_at'],
224
+ },
225
+ },
226
+ ],
227
+ }
228
+
229
+ export default searchConfig
230
+ export const config = searchConfig
@@ -0,0 +1,29 @@
1
+ import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
2
+ import { ensureRoles } from '@open-mercato/core/modules/auth/lib/setup-app'
3
+ import {
4
+ WMS_CUSTOM_ROLE_NAMES,
5
+ WMS_OPERATOR_FEATURES,
6
+ WMS_OPERATOR_ROLE,
7
+ WMS_SUPERVISOR_FEATURES,
8
+ WMS_SUPERVISOR_ROLE,
9
+ } from './lib/roleFeatures'
10
+ import { seedWmsIntegrationToggles } from './lib/wmsIntegrationToggles'
11
+
12
+ async function seedWmsRoles(em: Parameters<typeof ensureRoles>[0], tenantId: string): Promise<void> {
13
+ await ensureRoles(em, { tenantId, roleNames: [...WMS_CUSTOM_ROLE_NAMES] })
14
+ }
15
+
16
+ export const setup: ModuleSetupConfig = {
17
+ seedDefaults: async (ctx) => {
18
+ await seedWmsIntegrationToggles(ctx.em)
19
+ await seedWmsRoles(ctx.em, ctx.tenantId)
20
+ },
21
+ defaultRoleFeatures: {
22
+ admin: ['wms.*'],
23
+ employee: ['wms.view'],
24
+ [WMS_OPERATOR_ROLE]: [...WMS_OPERATOR_FEATURES],
25
+ [WMS_SUPERVISOR_ROLE]: [...WMS_SUPERVISOR_FEATURES],
26
+ },
27
+ }
28
+
29
+ export default setup
@@ -0,0 +1,54 @@
1
+ import { resolveNotificationService } from '../../notifications/lib/notificationService'
2
+ import { buildFeatureNotificationFromType } from '../../notifications/lib/notificationBuilder'
3
+ import { notificationTypes } from '../notifications'
4
+ import { createLogger } from '@open-mercato/shared/lib/logger'
5
+
6
+ const logger = createLogger('wms')
7
+
8
+ export const metadata = {
9
+ event: 'wms.inventory.low_stock',
10
+ persistent: true,
11
+ id: 'wms:low-stock-notification',
12
+ }
13
+
14
+ type LowStockPayload = {
15
+ catalogVariantId: string
16
+ availableQuantity: number
17
+ reorderPoint: number
18
+ safetyStock: number
19
+ state: 'below_safety_stock' | 'below_reorder_point'
20
+ tenantId: string
21
+ organizationId?: string | null
22
+ }
23
+
24
+ type ResolverContext = {
25
+ resolve: <T = unknown>(name: string) => T
26
+ }
27
+
28
+ export default async function handle(payload: LowStockPayload, ctx: ResolverContext) {
29
+ try {
30
+ const notificationService = resolveNotificationService(ctx)
31
+ const typeDef = notificationTypes.find((type) => type.type === 'wms.inventory.low_stock')
32
+ if (!typeDef) return
33
+
34
+ const notificationInput = buildFeatureNotificationFromType(typeDef, {
35
+ requiredFeature: 'wms.view',
36
+ bodyVariables: {
37
+ availableQuantity: String(payload.availableQuantity),
38
+ reorderPoint: String(payload.reorderPoint),
39
+ safetyStock: String(payload.safetyStock),
40
+ state: payload.state,
41
+ },
42
+ sourceEntityType: 'wms:inventory_balance',
43
+ sourceEntityId: payload.catalogVariantId,
44
+ linkHref: `/backend/wms/sku/${encodeURIComponent(payload.catalogVariantId)}`,
45
+ })
46
+
47
+ await notificationService.createForFeature(notificationInput, {
48
+ tenantId: payload.tenantId,
49
+ organizationId: payload.organizationId ?? null,
50
+ })
51
+ } catch (err) {
52
+ logger.error('Failed to create notification', { subscriber: 'low-stock-notification', err })
53
+ }
54
+ }