@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,1112 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import Link from "next/link";
5
+ import { useRouter } from "next/navigation";
6
+ import { z } from "zod";
7
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
8
+ import { Page, PageBody } from "@open-mercato/ui/backend/Page";
9
+ import { DataTable } from "@open-mercato/ui/backend/DataTable";
10
+ import { EmptyState } from "@open-mercato/ui/backend/EmptyState";
11
+ import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
12
+ import { flash } from "@open-mercato/ui/backend/FlashMessages";
13
+ import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuardedMutation";
14
+ import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
15
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
16
+ import { raiseCrudError } from "@open-mercato/ui/backend/utils/serverErrors";
17
+ import { Button } from "@open-mercato/ui/primitives/button";
18
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@open-mercato/ui/primitives/dialog";
19
+ import { RowActions } from "@open-mercato/ui/backend/RowActions";
20
+ import { useLocale, useT } from "@open-mercato/shared/lib/i18n/context";
21
+ import { Boxes, Layers, MapPinned, Warehouse } from "lucide-react";
22
+ import { E } from "../../../../generated/entities.ids.generated.js";
23
+ import {
24
+ buildQuery,
25
+ loadCatalogVariantOptions,
26
+ loadWarehouseOptions
27
+ } from "./wmsLookupLoaders.js";
28
+ import {
29
+ createInventoryQuantityFormatter,
30
+ formatCatalogProductLabel,
31
+ formatCatalogVariantLabel,
32
+ formatInventoryQuantity,
33
+ inventoryRotationStrategyLabel
34
+ } from "../../lib/inventoryDisplayUi.js";
35
+ import { LocationEditDialog } from "./LocationEditDialog.js";
36
+ import { useWmsInventoryMutationAccess } from "./useWmsInventoryMutationAccess.js";
37
+ import { flashMutationError } from "../../lib/flashMutationError.js";
38
+ const warehouseFormSchema = z.object({
39
+ name: z.string().trim().min(1),
40
+ code: z.string().trim().min(1),
41
+ city: z.string().trim().optional(),
42
+ country: z.string().trim().optional(),
43
+ timezone: z.string().trim().optional(),
44
+ isActive: z.boolean().default(true),
45
+ isPrimary: z.boolean().default(false)
46
+ });
47
+ const zoneFormSchema = z.object({
48
+ warehouseId: z.string().uuid(),
49
+ code: z.string().trim().min(1).max(80),
50
+ name: z.string().trim().min(1).max(200),
51
+ priority: z.coerce.number().int().min(0).optional()
52
+ });
53
+ function buildInventoryProfileFormSchema(fefoRequiredMsg) {
54
+ return z.object({
55
+ catalogProductId: z.string().uuid(),
56
+ catalogVariantId: z.string().uuid().optional().or(z.literal("")),
57
+ defaultUom: z.string().trim().min(1),
58
+ defaultStrategy: z.enum(["fifo", "lifo", "fefo"]),
59
+ trackLot: z.boolean().default(false),
60
+ trackSerial: z.boolean().default(false),
61
+ trackExpiration: z.boolean().default(false),
62
+ reorderPoint: z.coerce.number().min(0).optional(),
63
+ safetyStock: z.coerce.number().min(0).optional()
64
+ }).superRefine((payload, ctx) => {
65
+ if (payload.trackExpiration && payload.defaultStrategy !== "fefo") {
66
+ ctx.addIssue({
67
+ code: z.ZodIssueCode.custom,
68
+ path: ["defaultStrategy"],
69
+ message: fefoRequiredMsg
70
+ });
71
+ }
72
+ });
73
+ }
74
+ const STRATEGY_OPTIONS = [
75
+ { value: "fifo", label: "FIFO" },
76
+ { value: "lifo", label: "LIFO" },
77
+ { value: "fefo", label: "FEFO" }
78
+ ];
79
+ function mergeCreatedWarehouseIntoWarehousesCaches(queryClient, newId, values) {
80
+ const row = {
81
+ id: newId,
82
+ name: values.name,
83
+ code: values.code,
84
+ city: values.city || null,
85
+ country: values.country || null,
86
+ timezone: values.timezone || null,
87
+ is_active: values.isActive,
88
+ is_primary: values.isPrimary
89
+ };
90
+ const haystack = `${values.name}
91
+ ${values.code}`.toLowerCase();
92
+ const entries = queryClient.getQueriesData({
93
+ queryKey: ["wms-config", "warehouses"],
94
+ exact: false
95
+ });
96
+ for (const [key, old] of entries) {
97
+ if (!old || !Array.isArray(old.items)) continue;
98
+ if (old.items.some((r) => r.id === newId)) continue;
99
+ const paramStr = Array.isArray(key) && typeof key[2] === "string" ? key[2] : "";
100
+ const sp = new URLSearchParams(paramStr);
101
+ const searchTerm = (sp.get("search") || "").trim().toLowerCase();
102
+ if (searchTerm && !haystack.includes(searchTerm)) continue;
103
+ const pageSize = typeof old.pageSize === "number" && old.pageSize > 0 ? old.pageSize : 10;
104
+ const nextTotal = (old.total ?? 0) + 1;
105
+ queryClient.setQueryData(key, {
106
+ ...old,
107
+ items: [row, ...old.items.filter((r) => r.id !== newId)].slice(0, pageSize),
108
+ total: nextTotal,
109
+ totalPages: Math.max(1, Math.ceil(nextTotal / pageSize))
110
+ });
111
+ }
112
+ }
113
+ async function loadCatalogProductOptions(query) {
114
+ const params = buildQuery({ page: 1, pageSize: 25, search: query?.trim() || void 0 });
115
+ const call = await apiCall(`/api/catalog/products?${params}`);
116
+ if (!call.ok) return [];
117
+ return (call.result?.items ?? []).map((item) => {
118
+ const value = typeof item.id === "string" ? item.id : null;
119
+ if (!value) return null;
120
+ const label = item.title || item.sku || value;
121
+ return { value, label };
122
+ }).filter((option) => option !== null);
123
+ }
124
+ function SectionCard({
125
+ title,
126
+ description,
127
+ icon,
128
+ viewAllHref,
129
+ viewAllLabel,
130
+ children
131
+ }) {
132
+ return /* @__PURE__ */ jsxs("section", { className: "rounded-lg border bg-card p-5 text-card-foreground shadow-sm", children: [
133
+ /* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-start gap-3", children: [
134
+ /* @__PURE__ */ jsx("div", { className: "rounded-md border bg-muted/40 p-2 text-muted-foreground", children: icon }),
135
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-1 items-start justify-between gap-2", children: [
136
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
137
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold", children: title }),
138
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: description })
139
+ ] }),
140
+ viewAllHref && /* @__PURE__ */ jsx(Link, { href: viewAllHref, className: "shrink-0 text-sm font-medium text-primary hover:underline", children: viewAllLabel })
141
+ ] })
142
+ ] }),
143
+ children
144
+ ] });
145
+ }
146
+ function WarehouseSection({ viewAllHref } = {}) {
147
+ const t = useT();
148
+ const queryClient = useQueryClient();
149
+ const { confirm, ConfirmDialogElement } = useConfirmDialog();
150
+ const { runMutation } = useGuardedMutation({ contextId: "wms-config-warehouses" });
151
+ const access = useWmsInventoryMutationAccess();
152
+ const [page, setPage] = React.useState(1);
153
+ const [search, setSearch] = React.useState("");
154
+ const [sorting, setSorting] = React.useState([{ id: "updatedAt", desc: true }]);
155
+ const [submitting, setSubmitting] = React.useState(false);
156
+ const [dialog, setDialog] = React.useState(null);
157
+ const handleSortingChange = React.useCallback((nextSorting) => {
158
+ setSorting(nextSorting);
159
+ setPage(1);
160
+ }, []);
161
+ const params = React.useMemo(() => {
162
+ const sortCol = sorting[0];
163
+ return buildQuery({
164
+ page,
165
+ pageSize: 10,
166
+ search: search.trim() || void 0,
167
+ sortField: sortCol ? sortCol.id : "updatedAt",
168
+ sortDir: sortCol ? sortCol.desc ? "desc" : "asc" : "desc"
169
+ });
170
+ }, [page, search, sorting]);
171
+ const query = useQuery({
172
+ queryKey: ["wms-config", "warehouses", params],
173
+ queryFn: async () => {
174
+ const call = await apiCall(`/api/wms/warehouses?${params}`, {
175
+ cache: "no-store"
176
+ });
177
+ if (!call.ok) {
178
+ await raiseCrudError(call.response, t("wms.backend.config.warehouses.errors.load", "Failed to load warehouses."));
179
+ }
180
+ return call.result ?? { items: [], total: 0, totalPages: 1 };
181
+ }
182
+ });
183
+ const fields = React.useMemo(() => [
184
+ { id: "name", type: "text", label: t("wms.backend.config.warehouses.form.name", "Name"), required: true },
185
+ { id: "code", type: "text", label: t("wms.backend.config.warehouses.form.code", "Code"), required: true },
186
+ { id: "city", type: "text", label: t("wms.backend.config.warehouses.form.city", "City") },
187
+ { id: "country", type: "text", label: t("wms.backend.config.warehouses.form.country", "Country") },
188
+ { id: "timezone", type: "text", label: t("wms.backend.config.warehouses.form.timezone", "Timezone") },
189
+ { id: "isPrimary", type: "checkbox", label: t("wms.backend.config.warehouses.form.primary", "Primary warehouse") },
190
+ { id: "isActive", type: "checkbox", label: t("wms.backend.config.warehouses.form.active", "Active") }
191
+ ], [t]);
192
+ const columns = React.useMemo(() => [
193
+ {
194
+ accessorKey: "name",
195
+ header: t("wms.backend.config.warehouses.columns.name", "Warehouse"),
196
+ enableSorting: true,
197
+ cell: ({ row }) => row.original.name || row.original.code || row.original.id
198
+ },
199
+ { accessorKey: "code", header: t("wms.backend.config.warehouses.columns.code", "Code"), enableSorting: true },
200
+ { accessorKey: "city", header: t("wms.backend.config.warehouses.columns.city", "City"), cell: ({ row }) => row.original.city || "\u2014" },
201
+ { accessorKey: "country", header: t("wms.backend.config.warehouses.columns.country", "Country"), cell: ({ row }) => row.original.country || "\u2014" },
202
+ {
203
+ accessorKey: "is_primary",
204
+ header: t("wms.backend.config.warehouses.columns.primary", "Primary"),
205
+ cell: ({ row }) => row.original.is_primary ? t("wms.backend.config.warehouses.primary.yes", "Primary") : "\u2014"
206
+ },
207
+ {
208
+ accessorKey: "is_active",
209
+ header: t("wms.backend.config.warehouses.columns.status", "Status"),
210
+ cell: ({ row }) => row.original.is_active === false ? t("wms.common.inactive", "Inactive") : t("wms.common.active", "Active")
211
+ }
212
+ ], [t]);
213
+ const initialValues = React.useMemo(() => {
214
+ if (dialog?.mode === "edit") {
215
+ return {
216
+ name: dialog.row.name || "",
217
+ code: dialog.row.code || "",
218
+ city: dialog.row.city || "",
219
+ country: dialog.row.country || "",
220
+ timezone: dialog.row.timezone || "",
221
+ isActive: dialog.row.is_active !== false,
222
+ isPrimary: dialog.row.is_primary === true
223
+ };
224
+ }
225
+ return {
226
+ name: "",
227
+ code: "",
228
+ city: "",
229
+ country: "",
230
+ timezone: "",
231
+ isActive: true,
232
+ isPrimary: false
233
+ };
234
+ }, [dialog]);
235
+ const closeDialog = React.useCallback(() => {
236
+ setDialog(null);
237
+ setSubmitting(false);
238
+ }, []);
239
+ const refresh = React.useCallback(async () => {
240
+ await queryClient.cancelQueries({ queryKey: ["wms-config", "warehouses"] });
241
+ await queryClient.invalidateQueries({ queryKey: ["wms-config", "warehouses"] });
242
+ await queryClient.refetchQueries({ queryKey: ["wms-config", "warehouses"], type: "all" });
243
+ }, [queryClient]);
244
+ const handleSubmit = React.useCallback(async (values) => {
245
+ if (!dialog) return;
246
+ const submitMode = dialog.mode;
247
+ setSubmitting(true);
248
+ try {
249
+ const call = await runMutation({
250
+ operation: async () => {
251
+ const result = await apiCall(
252
+ "/api/wms/warehouses",
253
+ {
254
+ method: submitMode === "edit" ? "PUT" : "POST",
255
+ body: JSON.stringify(
256
+ submitMode === "edit" ? { id: dialog.row.id, ...values } : values
257
+ )
258
+ }
259
+ );
260
+ if (!result.ok) {
261
+ await raiseCrudError(result.response, t("wms.backend.config.warehouses.errors.save", "Failed to save warehouse."));
262
+ }
263
+ return result;
264
+ },
265
+ context: {},
266
+ mutationPayload: submitMode === "edit" ? { id: dialog.row.id, ...values } : values
267
+ });
268
+ flash(
269
+ submitMode === "edit" ? t("wms.backend.config.warehouses.flash.updated", "Warehouse updated") : t("wms.backend.config.warehouses.flash.created", "Warehouse created"),
270
+ "success"
271
+ );
272
+ const createdId = submitMode === "create" && call?.result && typeof call.result === "object" && typeof call.result.id === "string" ? call.result.id.trim() : null;
273
+ closeDialog();
274
+ if (submitMode === "create" && createdId) {
275
+ mergeCreatedWarehouseIntoWarehousesCaches(queryClient, createdId, values);
276
+ setSearch("");
277
+ setPage(1);
278
+ }
279
+ await refresh();
280
+ } catch (error) {
281
+ flashMutationError(error, t("wms.backend.config.warehouses.errors.save", "Failed to save warehouse."), t);
282
+ setSubmitting(false);
283
+ }
284
+ }, [closeDialog, dialog, queryClient, refresh, runMutation, t]);
285
+ const handleDelete = React.useCallback(async (row) => {
286
+ const confirmed = await confirm({
287
+ title: t("wms.backend.config.warehouses.confirmDelete", 'Archive warehouse "{name}"?', {
288
+ name: row.name || row.code || row.id
289
+ }),
290
+ variant: "destructive"
291
+ });
292
+ if (!confirmed) return;
293
+ try {
294
+ await runMutation({
295
+ operation: async () => {
296
+ const call = await apiCall(`/api/wms/warehouses?id=${encodeURIComponent(row.id)}`, { method: "DELETE" });
297
+ if (!call.ok) {
298
+ await raiseCrudError(call.response, t("wms.backend.config.warehouses.errors.delete", "Failed to archive warehouse."));
299
+ }
300
+ return call;
301
+ },
302
+ context: {},
303
+ mutationPayload: { id: row.id }
304
+ });
305
+ flash(t("wms.backend.config.warehouses.flash.deleted", "Warehouse archived"), "success");
306
+ await refresh();
307
+ } catch (error) {
308
+ flashMutationError(error, t("wms.backend.config.warehouses.errors.delete", "Failed to archive warehouse."), t);
309
+ }
310
+ }, [confirm, refresh, runMutation, t]);
311
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
312
+ /* @__PURE__ */ jsx(
313
+ SectionCard,
314
+ {
315
+ title: t("wms.backend.config.warehouses.title", "Warehouses"),
316
+ description: t("wms.backend.config.warehouses.description", "Manage the high-level warehouse nodes used by WMS reservations and inventory movements."),
317
+ icon: /* @__PURE__ */ jsx(Warehouse, { className: "size-5" }),
318
+ viewAllHref,
319
+ viewAllLabel: viewAllHref ? t("wms.backend.config.viewAll", "View all \u2192") : void 0,
320
+ children: /* @__PURE__ */ jsx(
321
+ DataTable,
322
+ {
323
+ embedded: true,
324
+ title: t("wms.backend.config.warehouses.title", "Warehouses"),
325
+ columns,
326
+ data: query.data?.items ?? [],
327
+ isLoading: query.isLoading,
328
+ error: query.isError ? t("wms.backend.config.warehouses.errors.load", "Failed to load warehouses.") : null,
329
+ entityId: E.wms.warehouse,
330
+ searchValue: search,
331
+ onSearchChange: (value) => {
332
+ setSearch(value);
333
+ setPage(1);
334
+ },
335
+ searchPlaceholder: t("wms.backend.config.warehouses.search", "Search warehouses"),
336
+ sorting,
337
+ onSortingChange: handleSortingChange,
338
+ sortable: true,
339
+ manualSorting: true,
340
+ actions: access.canManageWarehouses ? /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () => setDialog({ mode: "create" }), children: t("wms.backend.config.actions.addWarehouse", "Add warehouse") }) : null,
341
+ rowActions: (row) => /* @__PURE__ */ jsx(
342
+ RowActions,
343
+ {
344
+ items: [
345
+ { id: "edit", label: t("common.edit", "Edit"), onSelect: () => setDialog({ mode: "edit", row }) },
346
+ { id: "delete", label: t("common.delete", "Delete"), destructive: true, onSelect: () => {
347
+ void handleDelete(row);
348
+ } }
349
+ ]
350
+ }
351
+ ),
352
+ pagination: {
353
+ page,
354
+ pageSize: 10,
355
+ total: query.data?.total ?? 0,
356
+ totalPages: query.data?.totalPages ?? 1,
357
+ onPageChange: setPage
358
+ },
359
+ perspective: { tableId: "wms.config.warehouses" },
360
+ emptyState: /* @__PURE__ */ jsx(
361
+ EmptyState,
362
+ {
363
+ title: t("wms.backend.config.warehouses.empty.title", "No warehouses"),
364
+ description: t("wms.backend.config.warehouses.empty.description", "Create the first warehouse to expose topology and inventory assignment in WMS."),
365
+ action: access.canManageWarehouses ? { label: t("wms.backend.config.actions.addWarehouse", "Add warehouse"), onClick: () => setDialog({ mode: "create" }) } : void 0
366
+ }
367
+ )
368
+ }
369
+ )
370
+ }
371
+ ),
372
+ /* @__PURE__ */ jsx(Dialog, { open: dialog !== null, onOpenChange: (next) => !next && closeDialog(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-3xl", children: [
373
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: dialog?.mode === "edit" ? t("wms.backend.config.warehouses.dialog.edit", "Edit warehouse") : t("wms.backend.config.warehouses.dialog.create", "Create warehouse") }) }),
374
+ /* @__PURE__ */ jsx(
375
+ CrudForm,
376
+ {
377
+ schema: warehouseFormSchema,
378
+ fields,
379
+ entityId: E.wms.warehouse,
380
+ initialValues,
381
+ submitLabel: t("common.save", "Save"),
382
+ onSubmit: handleSubmit,
383
+ embedded: true,
384
+ isLoading: submitting,
385
+ twoColumn: true
386
+ }
387
+ )
388
+ ] }) }),
389
+ ConfirmDialogElement
390
+ ] });
391
+ }
392
+ function ZoneSection({ viewAllHref } = {}) {
393
+ const t = useT();
394
+ const queryClient = useQueryClient();
395
+ const { confirm, ConfirmDialogElement } = useConfirmDialog();
396
+ const { runMutation } = useGuardedMutation({ contextId: "wms-config-zones" });
397
+ const access = useWmsInventoryMutationAccess();
398
+ const [page, setPage] = React.useState(1);
399
+ const [search, setSearch] = React.useState("");
400
+ const [sorting, setSorting] = React.useState([{ id: "priority", desc: false }]);
401
+ const [submitting, setSubmitting] = React.useState(false);
402
+ const [dialog, setDialog] = React.useState(null);
403
+ const handleSortingChange = React.useCallback((nextSorting) => {
404
+ setSorting(nextSorting);
405
+ setPage(1);
406
+ }, []);
407
+ const params = React.useMemo(() => {
408
+ const sortCol = sorting[0];
409
+ return buildQuery({
410
+ page,
411
+ pageSize: 10,
412
+ search: search.trim() || void 0,
413
+ sortField: sortCol ? sortCol.id : "priority",
414
+ sortDir: sortCol ? sortCol.desc ? "desc" : "asc" : "asc"
415
+ });
416
+ }, [page, search, sorting]);
417
+ const query = useQuery({
418
+ queryKey: ["wms-config", "zones", params],
419
+ queryFn: async () => {
420
+ const call = await apiCall(`/api/wms/zones?${params}`, {
421
+ cache: "no-store"
422
+ });
423
+ if (!call.ok) {
424
+ await raiseCrudError(call.response, t("wms.backend.config.zones.errors.load", "Failed to load zones."));
425
+ }
426
+ return call.result ?? { items: [], total: 0, totalPages: 1 };
427
+ }
428
+ });
429
+ const fields = React.useMemo(() => [
430
+ {
431
+ id: "warehouseId",
432
+ type: "combobox",
433
+ label: t("wms.backend.config.zones.form.warehouse", "Warehouse"),
434
+ required: true,
435
+ loadOptions: loadWarehouseOptions,
436
+ allowCustomValues: false
437
+ },
438
+ { id: "code", type: "text", label: t("wms.backend.config.zones.form.code", "Code"), required: true },
439
+ { id: "name", type: "text", label: t("wms.backend.config.zones.form.name", "Name"), required: true },
440
+ { id: "priority", type: "number", label: t("wms.backend.config.zones.form.priority", "Priority") }
441
+ ], [t]);
442
+ const columns = React.useMemo(() => [
443
+ {
444
+ accessorKey: "name",
445
+ header: t("wms.backend.config.zones.columns.name", "Zone"),
446
+ enableSorting: true,
447
+ cell: ({ row }) => row.original.name || row.original.code || row.original.id
448
+ },
449
+ { accessorKey: "code", header: t("wms.backend.config.zones.columns.code", "Code"), enableSorting: true },
450
+ {
451
+ accessorKey: "warehouse_name",
452
+ header: t("wms.backend.config.zones.columns.warehouse", "Warehouse"),
453
+ enableSorting: false,
454
+ cell: ({ row }) => row.original.warehouse_name || row.original.warehouse_code || row.original.warehouse_id || "\u2014"
455
+ },
456
+ {
457
+ accessorKey: "priority",
458
+ header: t("wms.backend.config.zones.columns.priority", "Priority"),
459
+ enableSorting: true,
460
+ cell: ({ row }) => row.original.priority == null ? "\u2014" : String(row.original.priority)
461
+ }
462
+ ], [t]);
463
+ const initialValues = React.useMemo(() => {
464
+ if (dialog?.mode === "edit") {
465
+ return {
466
+ warehouseId: dialog.row.warehouse_id || "",
467
+ code: dialog.row.code || "",
468
+ name: dialog.row.name || "",
469
+ priority: dialog.row.priority == null ? void 0 : Number(dialog.row.priority)
470
+ };
471
+ }
472
+ return {
473
+ warehouseId: "",
474
+ code: "",
475
+ name: "",
476
+ priority: void 0
477
+ };
478
+ }, [dialog]);
479
+ const closeDialog = React.useCallback(() => {
480
+ setDialog(null);
481
+ setSubmitting(false);
482
+ }, []);
483
+ const refresh = React.useCallback(async () => {
484
+ await queryClient.invalidateQueries({ queryKey: ["wms-config", "zones"] });
485
+ }, [queryClient]);
486
+ const handleSubmit = React.useCallback(async (values) => {
487
+ if (!dialog) return;
488
+ const submitMode = dialog.mode;
489
+ setSubmitting(true);
490
+ try {
491
+ const payload = {
492
+ ...values,
493
+ priority: values.priority === void 0 || Number.isNaN(values.priority) ? void 0 : Number(values.priority)
494
+ };
495
+ await runMutation({
496
+ operation: async () => {
497
+ const call = await apiCall(
498
+ "/api/wms/zones",
499
+ {
500
+ method: submitMode === "edit" ? "PUT" : "POST",
501
+ body: JSON.stringify(submitMode === "edit" ? { id: dialog.row.id, ...payload } : payload)
502
+ }
503
+ );
504
+ if (!call.ok) {
505
+ await raiseCrudError(call.response, t("wms.backend.config.zones.errors.save", "Failed to save zone."));
506
+ }
507
+ return call;
508
+ },
509
+ context: {},
510
+ mutationPayload: submitMode === "edit" ? { id: dialog.row.id, ...payload } : payload
511
+ });
512
+ flash(
513
+ submitMode === "edit" ? t("wms.backend.config.zones.flash.updated", "Zone updated") : t("wms.backend.config.zones.flash.created", "Zone created"),
514
+ "success"
515
+ );
516
+ closeDialog();
517
+ await refresh();
518
+ } catch (error) {
519
+ flashMutationError(error, t("wms.backend.config.zones.errors.save", "Failed to save zone."), t);
520
+ setSubmitting(false);
521
+ }
522
+ }, [closeDialog, dialog, refresh, runMutation, t]);
523
+ const handleDelete = React.useCallback(async (row) => {
524
+ const confirmed = await confirm({
525
+ title: t("wms.backend.config.zones.confirmDelete", 'Archive zone "{name}"?', {
526
+ name: row.name || row.code || row.id
527
+ }),
528
+ variant: "destructive"
529
+ });
530
+ if (!confirmed) return;
531
+ try {
532
+ await runMutation({
533
+ operation: async () => {
534
+ const call = await apiCall(`/api/wms/zones?id=${encodeURIComponent(row.id)}`, { method: "DELETE" });
535
+ if (!call.ok) {
536
+ await raiseCrudError(call.response, t("wms.backend.config.zones.errors.delete", "Failed to archive zone."));
537
+ }
538
+ return call;
539
+ },
540
+ context: {},
541
+ mutationPayload: { id: row.id }
542
+ });
543
+ flash(t("wms.backend.config.zones.flash.deleted", "Zone archived"), "success");
544
+ await refresh();
545
+ } catch (error) {
546
+ flashMutationError(error, t("wms.backend.config.zones.errors.delete", "Failed to archive zone."), t);
547
+ }
548
+ }, [confirm, refresh, runMutation, t]);
549
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
550
+ /* @__PURE__ */ jsx(
551
+ SectionCard,
552
+ {
553
+ title: t("wms.backend.config.zones.title", "Zones"),
554
+ description: t("wms.backend.config.zones.description", "Group locations into functional zones (e.g. receiving, pick face, bulk) to drive routing and priority."),
555
+ icon: /* @__PURE__ */ jsx(Layers, { className: "size-5" }),
556
+ viewAllHref,
557
+ viewAllLabel: viewAllHref ? t("wms.backend.config.viewAll", "View all \u2192") : void 0,
558
+ children: /* @__PURE__ */ jsx(
559
+ DataTable,
560
+ {
561
+ embedded: true,
562
+ title: t("wms.backend.config.zones.title", "Zones"),
563
+ columns,
564
+ data: query.data?.items ?? [],
565
+ isLoading: query.isLoading,
566
+ error: query.isError ? t("wms.backend.config.zones.errors.load", "Failed to load zones.") : null,
567
+ entityId: E.wms.warehouse_zone,
568
+ searchValue: search,
569
+ onSearchChange: (value) => {
570
+ setSearch(value);
571
+ setPage(1);
572
+ },
573
+ searchPlaceholder: t("wms.backend.config.zones.search", "Search zones"),
574
+ sorting,
575
+ onSortingChange: handleSortingChange,
576
+ sortable: true,
577
+ manualSorting: true,
578
+ actions: access.canManageZones ? /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () => setDialog({ mode: "create" }), children: t("wms.backend.config.actions.addZone", "Add zone") }) : null,
579
+ rowActions: (row) => /* @__PURE__ */ jsx(
580
+ RowActions,
581
+ {
582
+ items: [
583
+ { id: "edit", label: t("common.edit", "Edit"), onSelect: () => setDialog({ mode: "edit", row }) },
584
+ { id: "delete", label: t("common.delete", "Delete"), destructive: true, onSelect: () => {
585
+ void handleDelete(row);
586
+ } }
587
+ ]
588
+ }
589
+ ),
590
+ pagination: {
591
+ page,
592
+ pageSize: 10,
593
+ total: query.data?.total ?? 0,
594
+ totalPages: query.data?.totalPages ?? 1,
595
+ onPageChange: setPage
596
+ },
597
+ perspective: { tableId: "wms.config.zones" },
598
+ emptyState: /* @__PURE__ */ jsx(
599
+ EmptyState,
600
+ {
601
+ title: t("wms.backend.config.zones.empty.title", "No zones"),
602
+ description: t("wms.backend.config.zones.empty.description", "Zones group locations into functional areas to drive picking priority and routing rules."),
603
+ action: access.canManageZones ? { label: t("wms.backend.config.actions.addZone", "Add zone"), onClick: () => setDialog({ mode: "create" }) } : void 0
604
+ }
605
+ )
606
+ }
607
+ )
608
+ }
609
+ ),
610
+ /* @__PURE__ */ jsx(Dialog, { open: dialog !== null, onOpenChange: (next) => !next && closeDialog(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-3xl", children: [
611
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: dialog?.mode === "edit" ? t("wms.backend.config.zones.dialog.edit", "Edit zone") : t("wms.backend.config.zones.dialog.create", "Create zone") }) }),
612
+ /* @__PURE__ */ jsx(
613
+ CrudForm,
614
+ {
615
+ schema: zoneFormSchema,
616
+ fields,
617
+ entityId: E.wms.warehouse_zone,
618
+ initialValues,
619
+ submitLabel: t("common.save", "Save"),
620
+ onSubmit: handleSubmit,
621
+ embedded: true,
622
+ isLoading: submitting,
623
+ twoColumn: true
624
+ }
625
+ )
626
+ ] }) }),
627
+ ConfirmDialogElement
628
+ ] });
629
+ }
630
+ function LocationSection({ viewAllHref } = {}) {
631
+ const t = useT();
632
+ const router = useRouter();
633
+ const queryClient = useQueryClient();
634
+ const { confirm, ConfirmDialogElement } = useConfirmDialog();
635
+ const { runMutation } = useGuardedMutation({ contextId: "wms-config-locations" });
636
+ const access = useWmsInventoryMutationAccess();
637
+ const [page, setPage] = React.useState(1);
638
+ const [search, setSearch] = React.useState("");
639
+ const [sorting, setSorting] = React.useState([{ id: "updatedAt", desc: true }]);
640
+ const [dialog, setDialog] = React.useState(null);
641
+ const handleSortingChange = React.useCallback((nextSorting) => {
642
+ setSorting(nextSorting);
643
+ setPage(1);
644
+ }, []);
645
+ const params = React.useMemo(() => {
646
+ const sortCol = sorting[0];
647
+ return buildQuery({
648
+ page,
649
+ pageSize: 10,
650
+ search: search.trim() || void 0,
651
+ sortField: sortCol ? sortCol.id : "updatedAt",
652
+ sortDir: sortCol ? sortCol.desc ? "desc" : "asc" : "desc"
653
+ });
654
+ }, [page, search, sorting]);
655
+ const query = useQuery({
656
+ queryKey: ["wms-config", "locations", params],
657
+ queryFn: async () => {
658
+ const call = await apiCall(`/api/wms/locations?${params}`);
659
+ if (!call.ok) {
660
+ await raiseCrudError(call.response, t("wms.backend.config.locations.errors.load", "Failed to load locations."));
661
+ }
662
+ return call.result ?? { items: [], total: 0, totalPages: 1 };
663
+ }
664
+ });
665
+ const columns = React.useMemo(() => [
666
+ {
667
+ accessorKey: "code",
668
+ header: t("wms.backend.config.locations.columns.code", "Location"),
669
+ enableSorting: true,
670
+ cell: ({ row }) => {
671
+ const locationId = row.original.id?.trim();
672
+ const code = row.original.code || "\u2014";
673
+ if (!locationId) return code;
674
+ return /* @__PURE__ */ jsx(
675
+ Link,
676
+ {
677
+ href: `/backend/wms/location/${encodeURIComponent(locationId)}`,
678
+ className: "font-medium text-primary hover:underline",
679
+ children: code
680
+ }
681
+ );
682
+ }
683
+ },
684
+ { accessorKey: "type", header: t("wms.backend.config.locations.columns.type", "Type"), enableSorting: true, cell: ({ row }) => row.original.type || "\u2014" },
685
+ {
686
+ accessorKey: "warehouse_name",
687
+ header: t("wms.backend.config.locations.columns.warehouse", "Warehouse"),
688
+ enableSorting: false,
689
+ cell: ({ row }) => row.original.warehouse_name || row.original.warehouse_code || row.original.warehouse_id || "\u2014"
690
+ },
691
+ { accessorKey: "capacity_units", header: t("wms.backend.config.locations.columns.capacityUnits", "Capacity units"), cell: ({ row }) => String(row.original.capacity_units ?? "\u2014") },
692
+ {
693
+ accessorKey: "is_active",
694
+ header: t("wms.backend.config.locations.columns.status", "Status"),
695
+ cell: ({ row }) => row.original.is_active === false ? t("wms.common.inactive", "Inactive") : t("wms.common.active", "Active")
696
+ }
697
+ ], [t]);
698
+ const closeDialog = React.useCallback(() => {
699
+ setDialog(null);
700
+ }, []);
701
+ const refresh = React.useCallback(async () => {
702
+ await queryClient.invalidateQueries({ queryKey: ["wms-config", "locations"] });
703
+ }, [queryClient]);
704
+ const handleDelete = React.useCallback(async (row) => {
705
+ const confirmed = await confirm({
706
+ title: t("wms.backend.config.locations.confirmDelete", 'Archive location "{code}"?', {
707
+ code: row.code || row.id
708
+ }),
709
+ variant: "destructive"
710
+ });
711
+ if (!confirmed) return;
712
+ try {
713
+ await runMutation({
714
+ operation: async () => {
715
+ const call = await apiCall(`/api/wms/locations?id=${encodeURIComponent(row.id)}`, { method: "DELETE" });
716
+ if (!call.ok) {
717
+ await raiseCrudError(call.response, t("wms.backend.config.locations.errors.delete", "Failed to archive location."));
718
+ }
719
+ return call;
720
+ },
721
+ context: {},
722
+ mutationPayload: { id: row.id }
723
+ });
724
+ flash(t("wms.backend.config.locations.flash.deleted", "Location archived"), "success");
725
+ await refresh();
726
+ } catch (error) {
727
+ flashMutationError(error, t("wms.backend.config.locations.errors.delete", "Failed to archive location."), t);
728
+ }
729
+ }, [confirm, refresh, runMutation, t]);
730
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
731
+ /* @__PURE__ */ jsx(
732
+ SectionCard,
733
+ {
734
+ title: t("wms.backend.config.locations.title", "Locations"),
735
+ description: t("wms.backend.config.locations.description", "Maintain aisle/bin/dock level topology buckets that hold operational inventory."),
736
+ icon: /* @__PURE__ */ jsx(MapPinned, { className: "size-5" }),
737
+ viewAllHref,
738
+ viewAllLabel: viewAllHref ? t("wms.backend.config.viewAll", "View all \u2192") : void 0,
739
+ children: /* @__PURE__ */ jsx(
740
+ DataTable,
741
+ {
742
+ embedded: true,
743
+ title: t("wms.backend.config.locations.title", "Locations"),
744
+ columns,
745
+ data: query.data?.items ?? [],
746
+ isLoading: query.isLoading,
747
+ error: query.isError ? t("wms.backend.config.locations.errors.load", "Failed to load locations.") : null,
748
+ entityId: E.wms.warehouse_location,
749
+ searchValue: search,
750
+ onSearchChange: (value) => {
751
+ setSearch(value);
752
+ setPage(1);
753
+ },
754
+ searchPlaceholder: t("wms.backend.config.locations.search", "Search locations"),
755
+ sorting,
756
+ onSortingChange: handleSortingChange,
757
+ sortable: true,
758
+ manualSorting: true,
759
+ actions: access.canManageLocations ? /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () => setDialog({ mode: "create" }), children: t("wms.backend.config.actions.addLocation", "Add location") }) : null,
760
+ onRowClick: (row) => {
761
+ const locationId = row.id?.trim();
762
+ if (locationId) {
763
+ router.push(`/backend/wms/location/${encodeURIComponent(locationId)}`);
764
+ }
765
+ },
766
+ rowActions: (row) => /* @__PURE__ */ jsx(
767
+ RowActions,
768
+ {
769
+ items: [
770
+ { id: "edit", label: t("common.edit", "Edit"), onSelect: () => setDialog({ mode: "edit", row }) },
771
+ { id: "delete", label: t("common.delete", "Delete"), destructive: true, onSelect: () => {
772
+ void handleDelete(row);
773
+ } }
774
+ ]
775
+ }
776
+ ),
777
+ pagination: {
778
+ page,
779
+ pageSize: 10,
780
+ total: query.data?.total ?? 0,
781
+ totalPages: query.data?.totalPages ?? 1,
782
+ onPageChange: setPage
783
+ },
784
+ perspective: { tableId: "wms.config.locations" },
785
+ emptyState: /* @__PURE__ */ jsx(
786
+ EmptyState,
787
+ {
788
+ title: t("wms.backend.config.locations.empty.title", "No locations"),
789
+ description: t("wms.backend.config.locations.empty.description", "Create locations to define the buckets used by balances, reservations, and movement ledger rows."),
790
+ action: access.canManageLocations ? { label: t("wms.backend.config.actions.addLocation", "Add location"), onClick: () => setDialog({ mode: "create" }) } : void 0
791
+ }
792
+ )
793
+ }
794
+ )
795
+ }
796
+ ),
797
+ /* @__PURE__ */ jsx(
798
+ LocationEditDialog,
799
+ {
800
+ open: dialog !== null,
801
+ onOpenChange: (next) => !next && closeDialog(),
802
+ mode: dialog?.mode ?? "create",
803
+ row: dialog?.mode === "edit" ? dialog.row : null,
804
+ onSaved: refresh
805
+ }
806
+ ),
807
+ ConfirmDialogElement
808
+ ] });
809
+ }
810
+ function InventoryProfilesSection() {
811
+ const t = useT();
812
+ const locale = useLocale();
813
+ const queryClient = useQueryClient();
814
+ const { confirm, ConfirmDialogElement } = useConfirmDialog();
815
+ const { runMutation } = useGuardedMutation({ contextId: "wms-config-profiles" });
816
+ const access = useWmsInventoryMutationAccess();
817
+ const [page, setPage] = React.useState(1);
818
+ const [sorting, setSorting] = React.useState([{ id: "updatedAt", desc: true }]);
819
+ const [submitting, setSubmitting] = React.useState(false);
820
+ const [dialog, setDialog] = React.useState(null);
821
+ const inventoryProfileFormSchema = React.useMemo(
822
+ () => buildInventoryProfileFormSchema(t("wms.backend.config.profiles.validation.fefoRequired", "FEFO is required when expiration tracking is enabled.")),
823
+ [t]
824
+ );
825
+ const handleSortingChange = React.useCallback((nextSorting) => {
826
+ setSorting(nextSorting);
827
+ setPage(1);
828
+ }, []);
829
+ const params = React.useMemo(() => {
830
+ const sortCol = sorting[0];
831
+ return buildQuery({
832
+ page,
833
+ pageSize: 10,
834
+ sortField: sortCol ? sortCol.id : "updatedAt",
835
+ sortDir: sortCol ? sortCol.desc ? "desc" : "asc" : "desc"
836
+ });
837
+ }, [page, sorting]);
838
+ const query = useQuery({
839
+ queryKey: ["wms-config", "inventory-profiles", params],
840
+ queryFn: async () => {
841
+ const call = await apiCall(`/api/wms/inventory-profiles?${params}`);
842
+ if (!call.ok) {
843
+ await raiseCrudError(call.response, t("wms.backend.config.profiles.errors.load", "Failed to load inventory profiles."));
844
+ }
845
+ return call.result ?? { items: [], total: 0, totalPages: 1 };
846
+ }
847
+ });
848
+ const fields = React.useMemo(() => [
849
+ {
850
+ id: "catalogProductId",
851
+ type: "combobox",
852
+ label: t("wms.backend.config.profiles.form.product", "Product"),
853
+ required: true,
854
+ loadOptions: loadCatalogProductOptions,
855
+ allowCustomValues: false
856
+ },
857
+ {
858
+ id: "catalogVariantId",
859
+ type: "combobox",
860
+ label: t("wms.backend.config.profiles.form.variant", "Variant"),
861
+ loadOptions: loadCatalogVariantOptions,
862
+ allowCustomValues: false
863
+ },
864
+ { id: "defaultUom", type: "text", label: t("wms.backend.config.profiles.form.uom", "Default UOM"), required: true },
865
+ {
866
+ id: "defaultStrategy",
867
+ type: "select",
868
+ label: t("wms.backend.config.profiles.form.strategy", "Rotation strategy"),
869
+ required: true,
870
+ options: STRATEGY_OPTIONS
871
+ },
872
+ { id: "reorderPoint", type: "number", label: t("wms.backend.config.profiles.form.reorderPoint", "Reorder point") },
873
+ { id: "safetyStock", type: "number", label: t("wms.backend.config.profiles.form.safetyStock", "Safety stock") },
874
+ { id: "trackLot", type: "checkbox", label: t("wms.backend.config.profiles.form.trackLot", "Track lots") },
875
+ { id: "trackSerial", type: "checkbox", label: t("wms.backend.config.profiles.form.trackSerial", "Track serials") },
876
+ { id: "trackExpiration", type: "checkbox", label: t("wms.backend.config.profiles.form.trackExpiration", "Track expiration") }
877
+ ], [t]);
878
+ const quantityFormatter = React.useMemo(
879
+ () => createInventoryQuantityFormatter(locale),
880
+ [locale]
881
+ );
882
+ const columns = React.useMemo(() => [
883
+ {
884
+ accessorKey: "catalog_product_id",
885
+ header: t("wms.backend.config.profiles.columns.product", "Product"),
886
+ cell: ({ row }) => formatCatalogProductLabel(row.original)
887
+ },
888
+ {
889
+ accessorKey: "catalog_variant_id",
890
+ header: t("wms.backend.config.profiles.columns.variant", "Variant"),
891
+ cell: ({ row }) => {
892
+ if (!row.original.catalog_variant_id?.trim()) {
893
+ return t("wms.backend.config.profiles.allVariants", "All variants");
894
+ }
895
+ return formatCatalogVariantLabel(row.original);
896
+ }
897
+ },
898
+ { accessorKey: "default_uom", header: t("wms.backend.config.profiles.columns.uom", "UOM"), cell: ({ row }) => row.original.default_uom || "\u2014" },
899
+ {
900
+ accessorKey: "default_strategy",
901
+ id: "defaultStrategy",
902
+ header: t("wms.backend.config.profiles.columns.strategy", "Strategy"),
903
+ enableSorting: true,
904
+ cell: ({ row }) => {
905
+ const strategy = row.original.default_strategy?.trim();
906
+ if (!strategy) return "\u2014";
907
+ return inventoryRotationStrategyLabel(strategy, t);
908
+ }
909
+ },
910
+ {
911
+ accessorKey: "reorder_point",
912
+ id: "reorderPoint",
913
+ header: t("wms.backend.config.profiles.columns.reorderPoint", "Reorder point"),
914
+ enableSorting: true,
915
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: formatInventoryQuantity(row.original.reorder_point, quantityFormatter) })
916
+ },
917
+ {
918
+ accessorKey: "safety_stock",
919
+ id: "safetyStock",
920
+ header: t("wms.backend.config.profiles.columns.safetyStock", "Safety stock"),
921
+ enableSorting: true,
922
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: formatInventoryQuantity(row.original.safety_stock, quantityFormatter) })
923
+ }
924
+ ], [quantityFormatter, t]);
925
+ const initialValues = React.useMemo(() => {
926
+ if (dialog?.mode === "edit") {
927
+ return {
928
+ catalogProductId: dialog.row.catalog_product_id || "",
929
+ catalogVariantId: dialog.row.catalog_variant_id || "",
930
+ defaultUom: dialog.row.default_uom || "",
931
+ defaultStrategy: dialog.row.default_strategy || "fifo",
932
+ trackLot: dialog.row.track_lot === true,
933
+ trackSerial: dialog.row.track_serial === true,
934
+ trackExpiration: dialog.row.track_expiration === true,
935
+ reorderPoint: dialog.row.reorder_point == null ? void 0 : Number(dialog.row.reorder_point),
936
+ safetyStock: dialog.row.safety_stock == null ? void 0 : Number(dialog.row.safety_stock)
937
+ };
938
+ }
939
+ return {
940
+ catalogProductId: "",
941
+ catalogVariantId: "",
942
+ defaultUom: "pcs",
943
+ defaultStrategy: "fifo",
944
+ trackLot: false,
945
+ trackSerial: false,
946
+ trackExpiration: false,
947
+ reorderPoint: 0,
948
+ safetyStock: 0
949
+ };
950
+ }, [dialog]);
951
+ const closeDialog = React.useCallback(() => {
952
+ setDialog(null);
953
+ setSubmitting(false);
954
+ }, []);
955
+ const refresh = React.useCallback(async () => {
956
+ await queryClient.invalidateQueries({ queryKey: ["wms-config", "inventory-profiles"] });
957
+ }, [queryClient]);
958
+ const handleSubmit = React.useCallback(async (values) => {
959
+ setSubmitting(true);
960
+ try {
961
+ const payload = {
962
+ ...values,
963
+ catalogVariantId: values.catalogVariantId?.trim() ? values.catalogVariantId : null
964
+ };
965
+ await runMutation({
966
+ operation: async () => {
967
+ const call = await apiCall(
968
+ "/api/wms/inventory-profiles",
969
+ {
970
+ method: dialog?.mode === "edit" ? "PUT" : "POST",
971
+ body: JSON.stringify(dialog?.mode === "edit" ? { id: dialog.row.id, ...payload } : payload)
972
+ }
973
+ );
974
+ if (!call.ok) {
975
+ await raiseCrudError(call.response, t("wms.backend.config.profiles.errors.save", "Failed to save inventory profile."));
976
+ }
977
+ return call;
978
+ },
979
+ context: {},
980
+ mutationPayload: dialog?.mode === "edit" ? { id: dialog.row.id, ...payload } : payload
981
+ });
982
+ flash(
983
+ dialog?.mode === "edit" ? t("wms.backend.config.profiles.flash.updated", "Inventory profile updated") : t("wms.backend.config.profiles.flash.created", "Inventory profile created"),
984
+ "success"
985
+ );
986
+ closeDialog();
987
+ await refresh();
988
+ } catch (error) {
989
+ flashMutationError(error, t("wms.backend.config.profiles.errors.save", "Failed to save inventory profile."), t);
990
+ setSubmitting(false);
991
+ }
992
+ }, [closeDialog, dialog, refresh, runMutation, t]);
993
+ const handleDelete = React.useCallback(async (row) => {
994
+ const confirmed = await confirm({
995
+ title: t("wms.backend.config.profiles.confirmDelete", 'Archive inventory profile "{id}"?', {
996
+ id: row.id
997
+ }),
998
+ variant: "destructive"
999
+ });
1000
+ if (!confirmed) return;
1001
+ try {
1002
+ await runMutation({
1003
+ operation: async () => {
1004
+ const call = await apiCall(`/api/wms/inventory-profiles?id=${encodeURIComponent(row.id)}`, { method: "DELETE" });
1005
+ if (!call.ok) {
1006
+ await raiseCrudError(call.response, t("wms.backend.config.profiles.errors.delete", "Failed to archive inventory profile."));
1007
+ }
1008
+ return call;
1009
+ },
1010
+ context: {},
1011
+ mutationPayload: { id: row.id }
1012
+ });
1013
+ flash(t("wms.backend.config.profiles.flash.deleted", "Inventory profile archived"), "success");
1014
+ await refresh();
1015
+ } catch (error) {
1016
+ flashMutationError(error, t("wms.backend.config.profiles.errors.delete", "Failed to archive inventory profile."), t);
1017
+ }
1018
+ }, [confirm, refresh, runMutation, t]);
1019
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1020
+ /* @__PURE__ */ jsx(
1021
+ SectionCard,
1022
+ {
1023
+ title: t("wms.backend.config.profiles.title", "Inventory profiles"),
1024
+ description: t("wms.backend.config.profiles.description", "Configure tracking strategy, reorder thresholds, and lot/serial behavior per product scope."),
1025
+ icon: /* @__PURE__ */ jsx(Boxes, { className: "size-5" }),
1026
+ children: /* @__PURE__ */ jsx(
1027
+ DataTable,
1028
+ {
1029
+ embedded: true,
1030
+ title: t("wms.backend.config.profiles.title", "Inventory profiles"),
1031
+ columns,
1032
+ data: query.data?.items ?? [],
1033
+ isLoading: query.isLoading,
1034
+ error: query.isError ? t("wms.backend.config.profiles.errors.load", "Failed to load inventory profiles.") : null,
1035
+ entityId: E.wms.product_inventory_profile,
1036
+ sorting,
1037
+ onSortingChange: handleSortingChange,
1038
+ sortable: true,
1039
+ manualSorting: true,
1040
+ actions: access.canManage ? /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () => setDialog({ mode: "create" }), children: t("wms.backend.config.actions.addProfile", "Add profile") }) : null,
1041
+ rowActions: (row) => /* @__PURE__ */ jsx(
1042
+ RowActions,
1043
+ {
1044
+ items: [
1045
+ { id: "edit", label: t("common.edit", "Edit"), onSelect: () => setDialog({ mode: "edit", row }) },
1046
+ { id: "delete", label: t("common.delete", "Delete"), destructive: true, onSelect: () => {
1047
+ void handleDelete(row);
1048
+ } }
1049
+ ]
1050
+ }
1051
+ ),
1052
+ pagination: {
1053
+ page,
1054
+ pageSize: 10,
1055
+ total: query.data?.total ?? 0,
1056
+ totalPages: query.data?.totalPages ?? 1,
1057
+ onPageChange: setPage
1058
+ },
1059
+ perspective: { tableId: "wms.config.inventoryProfiles" },
1060
+ emptyState: /* @__PURE__ */ jsx(
1061
+ EmptyState,
1062
+ {
1063
+ title: t("wms.backend.config.profiles.empty.title", "No inventory profiles"),
1064
+ description: t("wms.backend.config.profiles.empty.description", "Create profiles to control reservation strategy, lot/serial tracking, and low-stock thresholds."),
1065
+ action: access.canManage ? { label: t("wms.backend.config.actions.addProfile", "Add profile"), onClick: () => setDialog({ mode: "create" }) } : void 0
1066
+ }
1067
+ )
1068
+ }
1069
+ )
1070
+ }
1071
+ ),
1072
+ /* @__PURE__ */ jsx(Dialog, { open: dialog !== null, onOpenChange: (next) => !next && closeDialog(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-3xl", children: [
1073
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: dialog?.mode === "edit" ? t("wms.backend.config.profiles.dialog.edit", "Edit inventory profile") : t("wms.backend.config.profiles.dialog.create", "Create inventory profile") }) }),
1074
+ /* @__PURE__ */ jsx(
1075
+ CrudForm,
1076
+ {
1077
+ schema: inventoryProfileFormSchema,
1078
+ fields,
1079
+ entityId: E.wms.product_inventory_profile,
1080
+ initialValues,
1081
+ submitLabel: t("common.save", "Save"),
1082
+ onSubmit: handleSubmit,
1083
+ embedded: true,
1084
+ isLoading: submitting,
1085
+ twoColumn: true
1086
+ }
1087
+ )
1088
+ ] }) }),
1089
+ ConfirmDialogElement
1090
+ ] });
1091
+ }
1092
+ function WmsConfigurationPage() {
1093
+ const t = useT();
1094
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
1095
+ /* @__PURE__ */ jsx("section", { className: "rounded-lg border bg-card p-5 text-card-foreground shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1096
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight", children: t("wms.backend.config.title", "WMS configuration") }),
1097
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("wms.backend.config.description", "Phase-1 operational configuration for warehouses, storage locations, and inventory tracking policies.") })
1098
+ ] }) }),
1099
+ /* @__PURE__ */ jsx(WarehouseSection, { viewAllHref: "/backend/wms/warehouses" }),
1100
+ /* @__PURE__ */ jsx(ZoneSection, { viewAllHref: "/backend/wms/zones" }),
1101
+ /* @__PURE__ */ jsx(LocationSection, { viewAllHref: "/backend/wms/locations" }),
1102
+ /* @__PURE__ */ jsx(InventoryProfilesSection, {})
1103
+ ] }) }) });
1104
+ }
1105
+ export {
1106
+ InventoryProfilesSection,
1107
+ LocationSection,
1108
+ WarehouseSection,
1109
+ ZoneSection,
1110
+ WmsConfigurationPage as default
1111
+ };
1112
+ //# sourceMappingURL=WmsConfigurationPage.js.map