@open-mercato/core 0.6.7-develop.6661.1.0043ed1d03 → 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 (494) 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/customer_accounts/migrations/Migration20260724120000_customer_accounts.js +56 -0
  35. package/dist/modules/customer_accounts/migrations/Migration20260724120000_customer_accounts.js.map +7 -0
  36. package/dist/modules/directory/api/organizations/route.js +1 -1
  37. package/dist/modules/directory/api/organizations/route.js.map +1 -1
  38. package/dist/modules/entities/api/definitions.js +2 -0
  39. package/dist/modules/entities/api/definitions.js.map +2 -2
  40. package/dist/modules/entities/lib/helpers.js +1 -0
  41. package/dist/modules/entities/lib/helpers.js.map +2 -2
  42. package/dist/modules/query_index/lib/engine.js +6 -6
  43. package/dist/modules/query_index/lib/engine.js.map +2 -2
  44. package/dist/modules/sales/api/documents/factory.js +1 -0
  45. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  46. package/dist/modules/sales/api/quotes/accept/route.js +7 -2
  47. package/dist/modules/sales/api/quotes/accept/route.js.map +2 -2
  48. package/dist/modules/sales/api/quotes/public/[token]/route.js +2 -1
  49. package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
  50. package/dist/modules/sales/commands/documents.js +53 -0
  51. package/dist/modules/sales/commands/documents.js.map +2 -2
  52. package/dist/modules/sales/components/documents/ItemsSection.js +51 -2
  53. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  54. package/dist/modules/sales/events.js +2 -0
  55. package/dist/modules/sales/events.js.map +2 -2
  56. package/dist/modules/sales/lib/publicQuoteTenantScope.js +24 -0
  57. package/dist/modules/sales/lib/publicQuoteTenantScope.js.map +7 -0
  58. package/dist/modules/sales/widgets/injection/order-items-context.js +11 -0
  59. package/dist/modules/sales/widgets/injection/order-items-context.js.map +7 -0
  60. package/dist/modules/wms/acl.js +18 -0
  61. package/dist/modules/wms/acl.js.map +7 -0
  62. package/dist/modules/wms/analytics.js +11 -0
  63. package/dist/modules/wms/analytics.js.map +7 -0
  64. package/dist/modules/wms/api/dashboard/operational/route.js +80 -0
  65. package/dist/modules/wms/api/dashboard/operational/route.js.map +7 -0
  66. package/dist/modules/wms/api/interceptors.js +90 -0
  67. package/dist/modules/wms/api/interceptors.js.map +7 -0
  68. package/dist/modules/wms/api/inventory/adjust/route.js +51 -0
  69. package/dist/modules/wms/api/inventory/adjust/route.js.map +7 -0
  70. package/dist/modules/wms/api/inventory/allocate/route.js +51 -0
  71. package/dist/modules/wms/api/inventory/allocate/route.js.map +7 -0
  72. package/dist/modules/wms/api/inventory/balances/route.js +172 -0
  73. package/dist/modules/wms/api/inventory/balances/route.js.map +7 -0
  74. package/dist/modules/wms/api/inventory/cycle-count/route.js +52 -0
  75. package/dist/modules/wms/api/inventory/cycle-count/route.js.map +7 -0
  76. package/dist/modules/wms/api/inventory/helpers.js +113 -0
  77. package/dist/modules/wms/api/inventory/helpers.js.map +7 -0
  78. package/dist/modules/wms/api/inventory/import/apply/route.js +46 -0
  79. package/dist/modules/wms/api/inventory/import/apply/route.js.map +7 -0
  80. package/dist/modules/wms/api/inventory/import/helpers.js +195 -0
  81. package/dist/modules/wms/api/inventory/import/helpers.js.map +7 -0
  82. package/dist/modules/wms/api/inventory/import/template/route.js +32 -0
  83. package/dist/modules/wms/api/inventory/import/template/route.js.map +7 -0
  84. package/dist/modules/wms/api/inventory/import/validate/route.js +54 -0
  85. package/dist/modules/wms/api/inventory/import/validate/route.js.map +7 -0
  86. package/dist/modules/wms/api/inventory/move/route.js +51 -0
  87. package/dist/modules/wms/api/inventory/move/route.js.map +7 -0
  88. package/dist/modules/wms/api/inventory/movements/route.js +164 -0
  89. package/dist/modules/wms/api/inventory/movements/route.js.map +7 -0
  90. package/dist/modules/wms/api/inventory/receive/route.js +50 -0
  91. package/dist/modules/wms/api/inventory/receive/route.js.map +7 -0
  92. package/dist/modules/wms/api/inventory/release/route.js +44 -0
  93. package/dist/modules/wms/api/inventory/release/route.js.map +7 -0
  94. package/dist/modules/wms/api/inventory/reservations/route.js +128 -0
  95. package/dist/modules/wms/api/inventory/reservations/route.js.map +7 -0
  96. package/dist/modules/wms/api/inventory/reserve/route.js +59 -0
  97. package/dist/modules/wms/api/inventory/reserve/route.js.map +7 -0
  98. package/dist/modules/wms/api/inventory-profiles/route.js +178 -0
  99. package/dist/modules/wms/api/inventory-profiles/route.js.map +7 -0
  100. package/dist/modules/wms/api/listEnrichers.js +181 -0
  101. package/dist/modules/wms/api/listEnrichers.js.map +7 -0
  102. package/dist/modules/wms/api/listSearch.js +77 -0
  103. package/dist/modules/wms/api/listSearch.js.map +7 -0
  104. package/dist/modules/wms/api/locations/route.js +172 -0
  105. package/dist/modules/wms/api/locations/route.js.map +7 -0
  106. package/dist/modules/wms/api/lots/route.js +204 -0
  107. package/dist/modules/wms/api/lots/route.js.map +7 -0
  108. package/dist/modules/wms/api/openapi.js +27 -0
  109. package/dist/modules/wms/api/openapi.js.map +7 -0
  110. package/dist/modules/wms/api/sales-orders/[salesOrderId]/re-run-reservation/route.js +54 -0
  111. package/dist/modules/wms/api/sales-orders/[salesOrderId]/re-run-reservation/route.js.map +7 -0
  112. package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js +279 -0
  113. package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js.map +7 -0
  114. package/dist/modules/wms/api/sales-orders/assign-warehouse/route.js +56 -0
  115. package/dist/modules/wms/api/sales-orders/assign-warehouse/route.js.map +7 -0
  116. package/dist/modules/wms/api/sales-orders/unassign-warehouse/route.js +43 -0
  117. package/dist/modules/wms/api/sales-orders/unassign-warehouse/route.js.map +7 -0
  118. package/dist/modules/wms/api/warehouses/route.js +181 -0
  119. package/dist/modules/wms/api/warehouses/route.js.map +7 -0
  120. package/dist/modules/wms/api/zones/route.js +159 -0
  121. package/dist/modules/wms/api/zones/route.js.map +7 -0
  122. package/dist/modules/wms/backend/config/wms/page.js +9 -0
  123. package/dist/modules/wms/backend/config/wms/page.js.map +7 -0
  124. package/dist/modules/wms/backend/config/wms/page.meta.js +18 -0
  125. package/dist/modules/wms/backend/config/wms/page.meta.js.map +7 -0
  126. package/dist/modules/wms/backend/page.js +9 -0
  127. package/dist/modules/wms/backend/page.js.map +7 -0
  128. package/dist/modules/wms/backend/page.meta.js +16 -0
  129. package/dist/modules/wms/backend/page.meta.js.map +7 -0
  130. package/dist/modules/wms/backend/wms/inventory/page.js +9 -0
  131. package/dist/modules/wms/backend/wms/inventory/page.js.map +7 -0
  132. package/dist/modules/wms/backend/wms/inventory/page.meta.js +18 -0
  133. package/dist/modules/wms/backend/wms/inventory/page.meta.js.map +7 -0
  134. package/dist/modules/wms/backend/wms/location/[id]/page.js +9 -0
  135. package/dist/modules/wms/backend/wms/location/[id]/page.js.map +7 -0
  136. package/dist/modules/wms/backend/wms/location/[id]/page.meta.js +18 -0
  137. package/dist/modules/wms/backend/wms/location/[id]/page.meta.js.map +7 -0
  138. package/dist/modules/wms/backend/wms/locations/page.js +10 -0
  139. package/dist/modules/wms/backend/wms/locations/page.js.map +7 -0
  140. package/dist/modules/wms/backend/wms/locations/page.meta.js +18 -0
  141. package/dist/modules/wms/backend/wms/locations/page.meta.js.map +7 -0
  142. package/dist/modules/wms/backend/wms/lot/[id]/page.js +9 -0
  143. package/dist/modules/wms/backend/wms/lot/[id]/page.js.map +7 -0
  144. package/dist/modules/wms/backend/wms/lot/[id]/page.meta.js +18 -0
  145. package/dist/modules/wms/backend/wms/lot/[id]/page.meta.js.map +7 -0
  146. package/dist/modules/wms/backend/wms/lots/page.js +9 -0
  147. package/dist/modules/wms/backend/wms/lots/page.js.map +7 -0
  148. package/dist/modules/wms/backend/wms/lots/page.meta.js +18 -0
  149. package/dist/modules/wms/backend/wms/lots/page.meta.js.map +7 -0
  150. package/dist/modules/wms/backend/wms/movements/page.js +22 -0
  151. package/dist/modules/wms/backend/wms/movements/page.js.map +7 -0
  152. package/dist/modules/wms/backend/wms/movements/page.meta.js +18 -0
  153. package/dist/modules/wms/backend/wms/movements/page.meta.js.map +7 -0
  154. package/dist/modules/wms/backend/wms/reservations/page.js +23 -0
  155. package/dist/modules/wms/backend/wms/reservations/page.js.map +7 -0
  156. package/dist/modules/wms/backend/wms/reservations/page.meta.js +18 -0
  157. package/dist/modules/wms/backend/wms/reservations/page.meta.js.map +7 -0
  158. package/dist/modules/wms/backend/wms/sku/[id]/page.js +9 -0
  159. package/dist/modules/wms/backend/wms/sku/[id]/page.js.map +7 -0
  160. package/dist/modules/wms/backend/wms/sku/[id]/page.meta.js +18 -0
  161. package/dist/modules/wms/backend/wms/sku/[id]/page.meta.js.map +7 -0
  162. package/dist/modules/wms/backend/wms/warehouses/page.js +10 -0
  163. package/dist/modules/wms/backend/wms/warehouses/page.js.map +7 -0
  164. package/dist/modules/wms/backend/wms/warehouses/page.meta.js +18 -0
  165. package/dist/modules/wms/backend/wms/warehouses/page.meta.js.map +7 -0
  166. package/dist/modules/wms/backend/wms/zones/page.js +10 -0
  167. package/dist/modules/wms/backend/wms/zones/page.js.map +7 -0
  168. package/dist/modules/wms/backend/wms/zones/page.meta.js +18 -0
  169. package/dist/modules/wms/backend/wms/zones/page.meta.js.map +7 -0
  170. package/dist/modules/wms/ce.js +80 -0
  171. package/dist/modules/wms/ce.js.map +7 -0
  172. package/dist/modules/wms/cli.js +83 -0
  173. package/dist/modules/wms/cli.js.map +7 -0
  174. package/dist/modules/wms/commands/configuration.js +1519 -0
  175. package/dist/modules/wms/commands/configuration.js.map +7 -0
  176. package/dist/modules/wms/commands/index.js +4 -0
  177. package/dist/modules/wms/commands/index.js.map +7 -0
  178. package/dist/modules/wms/commands/inventory-actions.js +1539 -0
  179. package/dist/modules/wms/commands/inventory-actions.js.map +7 -0
  180. package/dist/modules/wms/commands/sales-order-assignment.js +277 -0
  181. package/dist/modules/wms/commands/sales-order-assignment.js.map +7 -0
  182. package/dist/modules/wms/commands/shared.js +82 -0
  183. package/dist/modules/wms/commands/shared.js.map +7 -0
  184. package/dist/modules/wms/components/backend/AdjustInventoryDialog.js +755 -0
  185. package/dist/modules/wms/components/backend/AdjustInventoryDialog.js.map +7 -0
  186. package/dist/modules/wms/components/backend/ChangeLotStatusDialog.js +269 -0
  187. package/dist/modules/wms/components/backend/ChangeLotStatusDialog.js.map +7 -0
  188. package/dist/modules/wms/components/backend/CycleCountWizardDialog.js +1783 -0
  189. package/dist/modules/wms/components/backend/CycleCountWizardDialog.js.map +7 -0
  190. package/dist/modules/wms/components/backend/ImportInventoryDialog.js +766 -0
  191. package/dist/modules/wms/components/backend/ImportInventoryDialog.js.map +7 -0
  192. package/dist/modules/wms/components/backend/InventoryOperationsSection.js +119 -0
  193. package/dist/modules/wms/components/backend/InventoryOperationsSection.js.map +7 -0
  194. package/dist/modules/wms/components/backend/LocationEditDialog.js +140 -0
  195. package/dist/modules/wms/components/backend/LocationEditDialog.js.map +7 -0
  196. package/dist/modules/wms/components/backend/MoveInventoryDialog.js +791 -0
  197. package/dist/modules/wms/components/backend/MoveInventoryDialog.js.map +7 -0
  198. package/dist/modules/wms/components/backend/ReceiveInventoryDialog.js +656 -0
  199. package/dist/modules/wms/components/backend/ReceiveInventoryDialog.js.map +7 -0
  200. package/dist/modules/wms/components/backend/ReleaseReservationDialog.js +344 -0
  201. package/dist/modules/wms/components/backend/ReleaseReservationDialog.js.map +7 -0
  202. package/dist/modules/wms/components/backend/ReserveInventoryDialog.js +475 -0
  203. package/dist/modules/wms/components/backend/ReserveInventoryDialog.js.map +7 -0
  204. package/dist/modules/wms/components/backend/WmsConfigurationPage.js +1112 -0
  205. package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +7 -0
  206. package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +908 -0
  207. package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +7 -0
  208. package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +1015 -0
  209. package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +7 -0
  210. package/dist/modules/wms/components/backend/WmsLotDetailPage.js +1049 -0
  211. package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +7 -0
  212. package/dist/modules/wms/components/backend/WmsLotsListPage.js +297 -0
  213. package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +7 -0
  214. package/dist/modules/wms/components/backend/WmsOperationalDashboardPage.js +757 -0
  215. package/dist/modules/wms/components/backend/WmsOperationalDashboardPage.js.map +7 -0
  216. package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +975 -0
  217. package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +7 -0
  218. package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +710 -0
  219. package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +7 -0
  220. package/dist/modules/wms/components/backend/useWmsInventoryMutationAccess.js +79 -0
  221. package/dist/modules/wms/components/backend/useWmsInventoryMutationAccess.js.map +7 -0
  222. package/dist/modules/wms/components/backend/useWmsInventoryScopeFromSearchParams.js +24 -0
  223. package/dist/modules/wms/components/backend/useWmsInventoryScopeFromSearchParams.js.map +7 -0
  224. package/dist/modules/wms/components/backend/wmsLookupLoaders.js +55 -0
  225. package/dist/modules/wms/components/backend/wmsLookupLoaders.js.map +7 -0
  226. package/dist/modules/wms/data/enrichers.js +501 -0
  227. package/dist/modules/wms/data/enrichers.js.map +7 -0
  228. package/dist/modules/wms/data/entities.js +467 -0
  229. package/dist/modules/wms/data/entities.js.map +7 -0
  230. package/dist/modules/wms/data/validators.js +399 -0
  231. package/dist/modules/wms/data/validators.js.map +7 -0
  232. package/dist/modules/wms/di.js +27 -0
  233. package/dist/modules/wms/di.js.map +7 -0
  234. package/dist/modules/wms/events.js +42 -0
  235. package/dist/modules/wms/events.js.map +7 -0
  236. package/dist/modules/wms/index.js +17 -0
  237. package/dist/modules/wms/index.js.map +7 -0
  238. package/dist/modules/wms/lib/catalogInventoryProfileIntent.js +54 -0
  239. package/dist/modules/wms/lib/catalogInventoryProfileIntent.js.map +7 -0
  240. package/dist/modules/wms/lib/catalogInventoryProfileSync.js +144 -0
  241. package/dist/modules/wms/lib/catalogInventoryProfileSync.js.map +7 -0
  242. package/dist/modules/wms/lib/expiry.js +29 -0
  243. package/dist/modules/wms/lib/expiry.js.map +7 -0
  244. package/dist/modules/wms/lib/flashMutationError.js +51 -0
  245. package/dist/modules/wms/lib/flashMutationError.js.map +7 -0
  246. package/dist/modules/wms/lib/inventoryDisplayUi.js +188 -0
  247. package/dist/modules/wms/lib/inventoryDisplayUi.js.map +7 -0
  248. package/dist/modules/wms/lib/inventoryIdempotency.js +37 -0
  249. package/dist/modules/wms/lib/inventoryIdempotency.js.map +7 -0
  250. package/dist/modules/wms/lib/inventoryImportCsv.js +173 -0
  251. package/dist/modules/wms/lib/inventoryImportCsv.js.map +7 -0
  252. package/dist/modules/wms/lib/inventoryImportService.js +468 -0
  253. package/dist/modules/wms/lib/inventoryImportService.js.map +7 -0
  254. package/dist/modules/wms/lib/inventoryMutationUi.js +25 -0
  255. package/dist/modules/wms/lib/inventoryMutationUi.js.map +7 -0
  256. package/dist/modules/wms/lib/inventoryPolicy.js +61 -0
  257. package/dist/modules/wms/lib/inventoryPolicy.js.map +7 -0
  258. package/dist/modules/wms/lib/inventoryReconciliation.js +193 -0
  259. package/dist/modules/wms/lib/inventoryReconciliation.js.map +7 -0
  260. package/dist/modules/wms/lib/inventoryTrackingValidation.js +13 -0
  261. package/dist/modules/wms/lib/inventoryTrackingValidation.js.map +7 -0
  262. package/dist/modules/wms/lib/loadOperationalDashboard.js +580 -0
  263. package/dist/modules/wms/lib/loadOperationalDashboard.js.map +7 -0
  264. package/dist/modules/wms/lib/lowStockBalanceFilter.js +49 -0
  265. package/dist/modules/wms/lib/lowStockBalanceFilter.js.map +7 -0
  266. package/dist/modules/wms/lib/primaryWarehousePolicy.js +32 -0
  267. package/dist/modules/wms/lib/primaryWarehousePolicy.js.map +7 -0
  268. package/dist/modules/wms/lib/roleFeatures.js +30 -0
  269. package/dist/modules/wms/lib/roleFeatures.js.map +7 -0
  270. package/dist/modules/wms/lib/salesOrderInventoryAutomation.js +291 -0
  271. package/dist/modules/wms/lib/salesOrderInventoryAutomation.js.map +7 -0
  272. package/dist/modules/wms/lib/salesOrderWarehouseAssignment.js +54 -0
  273. package/dist/modules/wms/lib/salesOrderWarehouseAssignment.js.map +7 -0
  274. package/dist/modules/wms/lib/wmsIntegrationToggles.js +71 -0
  275. package/dist/modules/wms/lib/wmsIntegrationToggles.js.map +7 -0
  276. package/dist/modules/wms/migrations/Migration20260428110546.js +78 -0
  277. package/dist/modules/wms/migrations/Migration20260428110546.js.map +7 -0
  278. package/dist/modules/wms/migrations/Migration20260527120000.js +15 -0
  279. package/dist/modules/wms/migrations/Migration20260527120000.js.map +7 -0
  280. package/dist/modules/wms/migrations/Migration20260527140000.js +37 -0
  281. package/dist/modules/wms/migrations/Migration20260527140000.js.map +7 -0
  282. package/dist/modules/wms/migrations/Migration20260613120000.js +23 -0
  283. package/dist/modules/wms/migrations/Migration20260613120000.js.map +7 -0
  284. package/dist/modules/wms/migrations/Migration20260616090000.js +13 -0
  285. package/dist/modules/wms/migrations/Migration20260616090000.js.map +7 -0
  286. package/dist/modules/wms/migrations/Migration20260707180000.js +15 -0
  287. package/dist/modules/wms/migrations/Migration20260707180000.js.map +7 -0
  288. package/dist/modules/wms/notifications.client.js +18 -0
  289. package/dist/modules/wms/notifications.client.js.map +7 -0
  290. package/dist/modules/wms/notifications.js +53 -0
  291. package/dist/modules/wms/notifications.js.map +7 -0
  292. package/dist/modules/wms/search.js +196 -0
  293. package/dist/modules/wms/search.js.map +7 -0
  294. package/dist/modules/wms/setup.js +30 -0
  295. package/dist/modules/wms/setup.js.map +7 -0
  296. package/dist/modules/wms/subscribers/low-stock-notification.js +40 -0
  297. package/dist/modules/wms/subscribers/low-stock-notification.js.map +7 -0
  298. package/dist/modules/wms/subscribers/reservation-shortfall-notification.js +69 -0
  299. package/dist/modules/wms/subscribers/reservation-shortfall-notification.js.map +7 -0
  300. package/dist/modules/wms/subscribers/sales-order-cancelled-release.js +14 -0
  301. package/dist/modules/wms/subscribers/sales-order-cancelled-release.js.map +7 -0
  302. package/dist/modules/wms/subscribers/sales-order-confirmed-reserve.js +14 -0
  303. package/dist/modules/wms/subscribers/sales-order-confirmed-reserve.js.map +7 -0
  304. package/dist/modules/wms/translations.js +10 -0
  305. package/dist/modules/wms/translations.js.map +7 -0
  306. package/dist/modules/wms/vector.js +9 -0
  307. package/dist/modules/wms/vector.js.map +7 -0
  308. package/dist/modules/wms/widgets/injection/catalog-inventory-profile/widget.js +200 -0
  309. package/dist/modules/wms/widgets/injection/catalog-inventory-profile/widget.js.map +7 -0
  310. package/dist/modules/wms/widgets/injection/order-items-stock-column/widget.js +104 -0
  311. package/dist/modules/wms/widgets/injection/order-items-stock-column/widget.js.map +7 -0
  312. package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.client.js +389 -0
  313. package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.client.js.map +7 -0
  314. package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.js +16 -0
  315. package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.js.map +7 -0
  316. package/dist/modules/wms/widgets/injection-table.js +36 -0
  317. package/dist/modules/wms/widgets/injection-table.js.map +7 -0
  318. package/dist/modules/wms/widgets/notifications/WmsLowStockRenderer.js +150 -0
  319. package/dist/modules/wms/widgets/notifications/WmsLowStockRenderer.js.map +7 -0
  320. package/dist/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.js +186 -0
  321. package/dist/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.js.map +7 -0
  322. package/dist/modules/wms/widgets/notifications/index.js +7 -0
  323. package/dist/modules/wms/widgets/notifications/index.js.map +7 -0
  324. package/generated/entities/inventory_balance/index.ts +9 -0
  325. package/generated/entities/inventory_lot/index.ts +8 -0
  326. package/generated/entities/inventory_movement/index.ts +16 -0
  327. package/generated/entities/inventory_reservation/index.ts +10 -0
  328. package/generated/entities/product_inventory_profile/index.ts +9 -0
  329. package/generated/entities/sales_order_warehouse_assignment/index.ts +4 -0
  330. package/generated/entities/warehouse/index.ts +11 -0
  331. package/generated/entities/warehouse_location/index.ts +9 -0
  332. package/generated/entities/warehouse_zone/index.ts +4 -0
  333. package/generated/entities.ids.generated.ts +12 -0
  334. package/generated/entity-fields-registry.ts +98 -0
  335. package/package.json +7 -7
  336. package/src/modules/auth/backend/roles/page.tsx +13 -4
  337. package/src/modules/auth/i18n/de.json +2 -0
  338. package/src/modules/auth/i18n/en.json +2 -0
  339. package/src/modules/auth/i18n/es.json +2 -0
  340. package/src/modules/auth/i18n/pl.json +2 -0
  341. package/src/modules/auth/lib/backendChrome.tsx +1 -0
  342. package/src/modules/auth/services/rbacService.ts +25 -21
  343. package/src/modules/catalog/api/products/route.ts +3 -0
  344. package/src/modules/catalog/api/variants/route.ts +3 -0
  345. package/src/modules/customer_accounts/migrations/Migration20260724120000_customer_accounts.ts +96 -0
  346. package/src/modules/directory/api/organizations/route.ts +1 -1
  347. package/src/modules/entities/api/definitions.ts +2 -0
  348. package/src/modules/entities/lib/helpers.ts +1 -0
  349. package/src/modules/query_index/lib/engine.ts +18 -6
  350. package/src/modules/sales/api/documents/factory.ts +1 -0
  351. package/src/modules/sales/api/quotes/accept/route.ts +9 -2
  352. package/src/modules/sales/api/quotes/public/[token]/route.ts +2 -1
  353. package/src/modules/sales/commands/documents.ts +71 -0
  354. package/src/modules/sales/components/documents/ItemsSection.tsx +58 -0
  355. package/src/modules/sales/events.ts +2 -0
  356. package/src/modules/sales/lib/publicQuoteTenantScope.ts +49 -0
  357. package/src/modules/sales/widgets/injection/order-items-context.ts +15 -0
  358. package/src/modules/wms/acl.ts +14 -0
  359. package/src/modules/wms/analytics.ts +9 -0
  360. package/src/modules/wms/api/dashboard/operational/route.ts +83 -0
  361. package/src/modules/wms/api/interceptors.ts +108 -0
  362. package/src/modules/wms/api/inventory/adjust/route.ts +50 -0
  363. package/src/modules/wms/api/inventory/allocate/route.ts +50 -0
  364. package/src/modules/wms/api/inventory/balances/route.ts +178 -0
  365. package/src/modules/wms/api/inventory/cycle-count/route.ts +51 -0
  366. package/src/modules/wms/api/inventory/helpers.ts +128 -0
  367. package/src/modules/wms/api/inventory/import/apply/route.ts +47 -0
  368. package/src/modules/wms/api/inventory/import/helpers.ts +223 -0
  369. package/src/modules/wms/api/inventory/import/template/route.ts +31 -0
  370. package/src/modules/wms/api/inventory/import/validate/route.ts +56 -0
  371. package/src/modules/wms/api/inventory/move/route.ts +50 -0
  372. package/src/modules/wms/api/inventory/movements/route.ts +164 -0
  373. package/src/modules/wms/api/inventory/receive/route.ts +49 -0
  374. package/src/modules/wms/api/inventory/release/route.ts +43 -0
  375. package/src/modules/wms/api/inventory/reservations/route.ts +128 -0
  376. package/src/modules/wms/api/inventory/reserve/route.ts +59 -0
  377. package/src/modules/wms/api/inventory-profiles/route.ts +177 -0
  378. package/src/modules/wms/api/listEnrichers.ts +312 -0
  379. package/src/modules/wms/api/listSearch.ts +121 -0
  380. package/src/modules/wms/api/locations/route.ts +171 -0
  381. package/src/modules/wms/api/lots/route.ts +205 -0
  382. package/src/modules/wms/api/openapi.ts +28 -0
  383. package/src/modules/wms/api/sales-orders/[salesOrderId]/re-run-reservation/route.ts +58 -0
  384. package/src/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.ts +306 -0
  385. package/src/modules/wms/api/sales-orders/assign-warehouse/route.ts +57 -0
  386. package/src/modules/wms/api/sales-orders/unassign-warehouse/route.ts +43 -0
  387. package/src/modules/wms/api/warehouses/route.ts +181 -0
  388. package/src/modules/wms/api/zones/route.ts +158 -0
  389. package/src/modules/wms/backend/config/wms/page.meta.ts +14 -0
  390. package/src/modules/wms/backend/config/wms/page.tsx +5 -0
  391. package/src/modules/wms/backend/page.meta.ts +12 -0
  392. package/src/modules/wms/backend/page.tsx +5 -0
  393. package/src/modules/wms/backend/wms/inventory/page.meta.ts +14 -0
  394. package/src/modules/wms/backend/wms/inventory/page.tsx +5 -0
  395. package/src/modules/wms/backend/wms/location/[id]/page.meta.ts +14 -0
  396. package/src/modules/wms/backend/wms/location/[id]/page.tsx +5 -0
  397. package/src/modules/wms/backend/wms/locations/page.meta.ts +14 -0
  398. package/src/modules/wms/backend/wms/locations/page.tsx +12 -0
  399. package/src/modules/wms/backend/wms/lot/[id]/page.meta.ts +14 -0
  400. package/src/modules/wms/backend/wms/lot/[id]/page.tsx +5 -0
  401. package/src/modules/wms/backend/wms/lots/page.meta.ts +14 -0
  402. package/src/modules/wms/backend/wms/lots/page.tsx +5 -0
  403. package/src/modules/wms/backend/wms/movements/page.meta.ts +14 -0
  404. package/src/modules/wms/backend/wms/movements/page.tsx +23 -0
  405. package/src/modules/wms/backend/wms/reservations/page.meta.ts +14 -0
  406. package/src/modules/wms/backend/wms/reservations/page.tsx +24 -0
  407. package/src/modules/wms/backend/wms/sku/[id]/page.meta.ts +14 -0
  408. package/src/modules/wms/backend/wms/sku/[id]/page.tsx +5 -0
  409. package/src/modules/wms/backend/wms/warehouses/page.meta.ts +14 -0
  410. package/src/modules/wms/backend/wms/warehouses/page.tsx +12 -0
  411. package/src/modules/wms/backend/wms/zones/page.meta.ts +14 -0
  412. package/src/modules/wms/backend/wms/zones/page.tsx +12 -0
  413. package/src/modules/wms/ce.ts +76 -0
  414. package/src/modules/wms/cli.ts +96 -0
  415. package/src/modules/wms/commands/configuration.ts +1844 -0
  416. package/src/modules/wms/commands/index.ts +3 -0
  417. package/src/modules/wms/commands/inventory-actions.ts +1866 -0
  418. package/src/modules/wms/commands/sales-order-assignment.ts +346 -0
  419. package/src/modules/wms/commands/shared.ts +90 -0
  420. package/src/modules/wms/components/backend/AdjustInventoryDialog.tsx +820 -0
  421. package/src/modules/wms/components/backend/ChangeLotStatusDialog.tsx +312 -0
  422. package/src/modules/wms/components/backend/CycleCountWizardDialog.tsx +2007 -0
  423. package/src/modules/wms/components/backend/ImportInventoryDialog.tsx +1018 -0
  424. package/src/modules/wms/components/backend/InventoryOperationsSection.tsx +159 -0
  425. package/src/modules/wms/components/backend/LocationEditDialog.tsx +185 -0
  426. package/src/modules/wms/components/backend/MoveInventoryDialog.tsx +907 -0
  427. package/src/modules/wms/components/backend/ReceiveInventoryDialog.tsx +695 -0
  428. package/src/modules/wms/components/backend/ReleaseReservationDialog.tsx +424 -0
  429. package/src/modules/wms/components/backend/ReserveInventoryDialog.tsx +511 -0
  430. package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +1340 -0
  431. package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +1132 -0
  432. package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +1310 -0
  433. package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +1355 -0
  434. package/src/modules/wms/components/backend/WmsLotsListPage.tsx +359 -0
  435. package/src/modules/wms/components/backend/WmsOperationalDashboardPage.tsx +958 -0
  436. package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +1245 -0
  437. package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +960 -0
  438. package/src/modules/wms/components/backend/useWmsInventoryMutationAccess.ts +89 -0
  439. package/src/modules/wms/components/backend/useWmsInventoryScopeFromSearchParams.ts +32 -0
  440. package/src/modules/wms/components/backend/wmsLookupLoaders.ts +78 -0
  441. package/src/modules/wms/data/enrichers.ts +718 -0
  442. package/src/modules/wms/data/entities.ts +436 -0
  443. package/src/modules/wms/data/validators.ts +463 -0
  444. package/src/modules/wms/di.ts +25 -0
  445. package/src/modules/wms/events.ts +41 -0
  446. package/src/modules/wms/i18n/de.json +1051 -0
  447. package/src/modules/wms/i18n/en.json +1051 -0
  448. package/src/modules/wms/i18n/es.json +1051 -0
  449. package/src/modules/wms/i18n/pl.json +1051 -0
  450. package/src/modules/wms/index.ts +15 -0
  451. package/src/modules/wms/lib/catalogInventoryProfileIntent.ts +65 -0
  452. package/src/modules/wms/lib/catalogInventoryProfileSync.ts +199 -0
  453. package/src/modules/wms/lib/expiry.ts +30 -0
  454. package/src/modules/wms/lib/flashMutationError.ts +74 -0
  455. package/src/modules/wms/lib/inventoryDisplayUi.ts +249 -0
  456. package/src/modules/wms/lib/inventoryIdempotency.ts +54 -0
  457. package/src/modules/wms/lib/inventoryImportCsv.ts +212 -0
  458. package/src/modules/wms/lib/inventoryImportService.ts +629 -0
  459. package/src/modules/wms/lib/inventoryMutationUi.ts +21 -0
  460. package/src/modules/wms/lib/inventoryPolicy.ts +111 -0
  461. package/src/modules/wms/lib/inventoryReconciliation.ts +263 -0
  462. package/src/modules/wms/lib/inventoryTrackingValidation.ts +23 -0
  463. package/src/modules/wms/lib/loadOperationalDashboard.ts +776 -0
  464. package/src/modules/wms/lib/lowStockBalanceFilter.ts +74 -0
  465. package/src/modules/wms/lib/primaryWarehousePolicy.ts +46 -0
  466. package/src/modules/wms/lib/roleFeatures.ts +32 -0
  467. package/src/modules/wms/lib/salesOrderInventoryAutomation.ts +390 -0
  468. package/src/modules/wms/lib/salesOrderWarehouseAssignment.ts +78 -0
  469. package/src/modules/wms/lib/wmsIntegrationToggles.ts +81 -0
  470. package/src/modules/wms/migrations/.snapshot-open-mercato.json +2880 -0
  471. package/src/modules/wms/migrations/Migration20260428110546.ts +91 -0
  472. package/src/modules/wms/migrations/Migration20260527120000.ts +15 -0
  473. package/src/modules/wms/migrations/Migration20260527140000.ts +35 -0
  474. package/src/modules/wms/migrations/Migration20260613120000.ts +21 -0
  475. package/src/modules/wms/migrations/Migration20260616090000.ts +11 -0
  476. package/src/modules/wms/migrations/Migration20260707180000.ts +13 -0
  477. package/src/modules/wms/notifications.client.ts +18 -0
  478. package/src/modules/wms/notifications.ts +51 -0
  479. package/src/modules/wms/search.ts +230 -0
  480. package/src/modules/wms/setup.ts +29 -0
  481. package/src/modules/wms/subscribers/low-stock-notification.ts +54 -0
  482. package/src/modules/wms/subscribers/reservation-shortfall-notification.ts +98 -0
  483. package/src/modules/wms/subscribers/sales-order-cancelled-release.ts +21 -0
  484. package/src/modules/wms/subscribers/sales-order-confirmed-reserve.ts +21 -0
  485. package/src/modules/wms/translations.ts +6 -0
  486. package/src/modules/wms/vector.ts +7 -0
  487. package/src/modules/wms/widgets/injection/catalog-inventory-profile/widget.ts +238 -0
  488. package/src/modules/wms/widgets/injection/order-items-stock-column/widget.tsx +153 -0
  489. package/src/modules/wms/widgets/injection/sales-order-stock-context/widget.client.tsx +476 -0
  490. package/src/modules/wms/widgets/injection/sales-order-stock-context/widget.ts +15 -0
  491. package/src/modules/wms/widgets/injection-table.ts +34 -0
  492. package/src/modules/wms/widgets/notifications/WmsLowStockRenderer.tsx +153 -0
  493. package/src/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.tsx +194 -0
  494. package/src/modules/wms/widgets/notifications/index.ts +2 -0
@@ -0,0 +1,695 @@
1
+ "use client"
2
+
3
+ import * as React from 'react'
4
+ import { z } from 'zod'
5
+ import { useQueryClient } from '@tanstack/react-query'
6
+ import { ArrowDown, Minus, Package, Plus } from 'lucide-react'
7
+ import { flash } from '@open-mercato/ui/backend/FlashMessages'
8
+ import { flashMutationError } from '../../lib/flashMutationError'
9
+ import { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'
10
+ import { ComboboxInput } from '@open-mercato/ui/backend/inputs/ComboboxInput'
11
+ import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
12
+ import { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'
13
+ import { Button } from '@open-mercato/ui/primitives/button'
14
+ import {
15
+ Dialog,
16
+ DialogContent,
17
+ DialogDescription,
18
+ DialogFooter,
19
+ DialogHeader,
20
+ DialogTitle,
21
+ } from '@open-mercato/ui/primitives/dialog'
22
+ import { FormField } from '@open-mercato/ui/primitives/form-field'
23
+ import { IconButton } from '@open-mercato/ui/primitives/icon-button'
24
+ import { Input } from '@open-mercato/ui/primitives/input'
25
+ import { KbdShortcut } from '@open-mercato/ui/primitives/kbd'
26
+ import {
27
+ Select,
28
+ SelectContent,
29
+ SelectItem,
30
+ SelectTrigger,
31
+ SelectValue,
32
+ } from '@open-mercato/ui/primitives/select'
33
+ import { Textarea } from '@open-mercato/ui/primitives/textarea'
34
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
35
+ import { buildInventoryMutationReferenceId } from '../../lib/inventoryMutationUi'
36
+ import {
37
+ loadCatalogVariantOptions,
38
+ loadInventoryProfileForVariant,
39
+ loadLocationOptions,
40
+ loadLotNumberOptions,
41
+ loadWarehouseOptions,
42
+ resolveCatalogVariantLabel,
43
+ resolveLocationLabel,
44
+ resolveLotNumberFromId,
45
+ resolveWarehouseLabel,
46
+ } from './inventoryMutationLoaders'
47
+ import type { useWmsInventoryMutationAccess } from './useWmsInventoryMutationAccess'
48
+
49
+ const RECEIVE_REFERENCE_TYPES = ['manual', 'po', 'so', 'rma', 'transfer', 'qc'] as const
50
+ type ReceiveReferenceType = (typeof RECEIVE_REFERENCE_TYPES)[number]
51
+
52
+ type ReceiveFormValues = {
53
+ catalogVariantId: string
54
+ warehouseId: string
55
+ locationId: string
56
+ lotNumber: string
57
+ quantity: number
58
+ referenceType: ReceiveReferenceType
59
+ notes: string
60
+ serialNumber: string
61
+ }
62
+
63
+ type ReceiveInventoryDialogProps = {
64
+ open: boolean
65
+ onOpenChange: (open: boolean) => void
66
+ access: ReturnType<typeof useWmsInventoryMutationAccess>
67
+ initialCatalogVariantId?: string
68
+ initialWarehouseId?: string
69
+ initialLocationId?: string
70
+ initialLotId?: string
71
+ onSuccess?: (ctx: { catalogVariantId: string; warehouseId: string; locationId: string; quantity: number }) => void
72
+ }
73
+
74
+ const EMPTY_FORM: ReceiveFormValues = {
75
+ catalogVariantId: '',
76
+ warehouseId: '',
77
+ locationId: '',
78
+ lotNumber: '',
79
+ quantity: 1,
80
+ referenceType: 'manual',
81
+ notes: '',
82
+ serialNumber: '',
83
+ }
84
+
85
+ export function ReceiveInventoryDialog({
86
+ open,
87
+ onOpenChange,
88
+ access,
89
+ initialCatalogVariantId,
90
+ initialWarehouseId,
91
+ initialLocationId,
92
+ initialLotId,
93
+ onSuccess,
94
+ }: ReceiveInventoryDialogProps) {
95
+ const t = useT()
96
+ const queryClient = useQueryClient()
97
+ const formRef = React.useRef<HTMLFormElement>(null)
98
+ const { runMutation, retryLastMutation } = useGuardedMutation<{
99
+ retryLastMutation: () => Promise<boolean>
100
+ }>({
101
+ contextId: 'wms-inventory-receive',
102
+ })
103
+ const mutationContext = React.useMemo(
104
+ () => ({ retryLastMutation }),
105
+ [retryLastMutation],
106
+ )
107
+
108
+ const receiveFormSchema = React.useMemo(
109
+ () =>
110
+ z.object({
111
+ catalogVariantId: z.string().uuid(),
112
+ warehouseId: z.string().uuid(),
113
+ locationId: z.string().uuid(),
114
+ lotNumber: z.string().trim().max(120).optional(),
115
+ quantity: z.coerce.number().positive({
116
+ message: t('wms.backend.inventory.receive.errors.quantityPositive', 'Quantity must be greater than zero.'),
117
+ }),
118
+ referenceType: z.enum(RECEIVE_REFERENCE_TYPES),
119
+ notes: z.string().trim().max(500).optional(),
120
+ serialNumber: z.string().trim().max(120).optional(),
121
+ }),
122
+ [t],
123
+ )
124
+
125
+ const [submitting, setSubmitting] = React.useState(false)
126
+ const [form, setForm] = React.useState<ReceiveFormValues>(EMPTY_FORM)
127
+ const [fieldErrors, setFieldErrors] = React.useState<Record<string, string>>({})
128
+ const [optionLabelByValue, setOptionLabelByValue] = React.useState<Record<string, string>>({})
129
+ const [trackingProfile, setTrackingProfile] = React.useState<{
130
+ trackLot: boolean
131
+ trackSerial: boolean
132
+ } | null>(null)
133
+
134
+ const registerOptionLabels = React.useCallback(
135
+ (options: Array<{ value: string; label: string }>) => {
136
+ setOptionLabelByValue((current) => {
137
+ let changed = false
138
+ const next = { ...current }
139
+ for (const option of options) {
140
+ const value = option.value.trim()
141
+ const label = option.label.trim()
142
+ if (!value || !label || next[value] === label) continue
143
+ next[value] = label
144
+ changed = true
145
+ }
146
+ return changed ? next : current
147
+ })
148
+ },
149
+ [],
150
+ )
151
+
152
+ const resolveOptionLabel = React.useCallback(
153
+ (value: string) => optionLabelByValue[value] ?? value,
154
+ [optionLabelByValue],
155
+ )
156
+ const optionLabelByValueRef = React.useRef(optionLabelByValue)
157
+ optionLabelByValueRef.current = optionLabelByValue
158
+
159
+ const resetDialog = React.useCallback(() => {
160
+ setForm(EMPTY_FORM)
161
+ setFieldErrors({})
162
+ setSubmitting(false)
163
+ setOptionLabelByValue({})
164
+ setTrackingProfile(null)
165
+ }, [])
166
+
167
+ const closeDialog = React.useCallback(() => {
168
+ onOpenChange(false)
169
+ resetDialog()
170
+ }, [onOpenChange, resetDialog])
171
+
172
+ const patchForm = React.useCallback((patch: Partial<ReceiveFormValues>) => {
173
+ setForm((current) => ({ ...current, ...patch }))
174
+ setFieldErrors({})
175
+ }, [])
176
+
177
+ React.useEffect(() => {
178
+ if (!open) return
179
+ const catalogVariantId = initialCatalogVariantId?.trim()
180
+ const warehouseId = initialWarehouseId?.trim()
181
+ const locationId = initialLocationId?.trim()
182
+ const lotId = initialLotId?.trim()
183
+ if (!catalogVariantId && !warehouseId && !locationId && !lotId) return
184
+ setForm((current) => ({
185
+ ...current,
186
+ ...(catalogVariantId ? { catalogVariantId } : {}),
187
+ ...(warehouseId ? { warehouseId, locationId: locationId ?? '' } : {}),
188
+ ...(locationId ? { locationId } : {}),
189
+ }))
190
+ if (!lotId) return
191
+ let cancelled = false
192
+ void resolveLotNumberFromId(lotId).then((lotNumber) => {
193
+ if (cancelled || !lotNumber) return
194
+ setForm((current) => ({ ...current, lotNumber }))
195
+ registerOptionLabels([{ value: lotNumber, label: lotNumber }])
196
+ })
197
+ return () => {
198
+ cancelled = true
199
+ }
200
+ }, [
201
+ initialCatalogVariantId,
202
+ initialLocationId,
203
+ initialLotId,
204
+ initialWarehouseId,
205
+ open,
206
+ registerOptionLabels,
207
+ ])
208
+
209
+ React.useEffect(() => {
210
+ if (!open) return
211
+ let cancelled = false
212
+
213
+ const ensureLabel = async (value: string, resolve: (id: string) => Promise<string | null>) => {
214
+ const id = value.trim()
215
+ if (!id || optionLabelByValueRef.current[id]) return
216
+ const label = await resolve(id)
217
+ if (cancelled || !label) return
218
+ registerOptionLabels([{ value: id, label }])
219
+ }
220
+
221
+ void Promise.all([
222
+ ensureLabel(form.catalogVariantId, resolveCatalogVariantLabel),
223
+ ensureLabel(form.warehouseId, resolveWarehouseLabel),
224
+ ensureLabel(form.locationId, resolveLocationLabel),
225
+ ])
226
+
227
+ return () => {
228
+ cancelled = true
229
+ }
230
+ }, [
231
+ form.catalogVariantId,
232
+ form.locationId,
233
+ form.warehouseId,
234
+ open,
235
+ registerOptionLabels,
236
+ ])
237
+
238
+ React.useEffect(() => {
239
+ if (!open || !form.catalogVariantId.trim()) {
240
+ setTrackingProfile(null)
241
+ return
242
+ }
243
+ let cancelled = false
244
+ void loadInventoryProfileForVariant(form.catalogVariantId.trim()).then((profile) => {
245
+ if (cancelled) return
246
+ if (!profile) {
247
+ setTrackingProfile(null)
248
+ return
249
+ }
250
+ setTrackingProfile({
251
+ trackLot: profile.track_lot === true,
252
+ trackSerial: profile.track_serial === true,
253
+ })
254
+ })
255
+ return () => {
256
+ cancelled = true
257
+ }
258
+ }, [form.catalogVariantId, open])
259
+
260
+ const referenceTypeLabel = React.useCallback(
261
+ (code: ReceiveReferenceType) => {
262
+ const fallbacks: Record<ReceiveReferenceType, string> = {
263
+ manual: 'Manual receipt',
264
+ po: 'Purchase order',
265
+ so: 'Sales return',
266
+ rma: 'RMA / return',
267
+ transfer: 'Transfer',
268
+ qc: 'QC release',
269
+ }
270
+ return t(`wms.backend.inventory.receive.referenceTypes.${code}`, fallbacks[code])
271
+ },
272
+ [t],
273
+ )
274
+
275
+ const handleSubmit = React.useCallback(
276
+ async (event?: React.FormEvent) => {
277
+ event?.preventDefault()
278
+ const parsed = receiveFormSchema.safeParse({
279
+ ...form,
280
+ lotNumber: form.lotNumber.trim() || undefined,
281
+ notes: form.notes.trim() || undefined,
282
+ serialNumber: form.serialNumber.trim() || undefined,
283
+ })
284
+ if (!parsed.success) {
285
+ const nextErrors: Record<string, string> = {}
286
+ for (const issue of parsed.error.issues) {
287
+ const key = String(issue.path[0] ?? 'form')
288
+ if (!nextErrors[key]) nextErrors[key] = issue.message
289
+ }
290
+ setFieldErrors(nextErrors)
291
+ return
292
+ }
293
+
294
+ if (!access.scopeReady || !access.organizationId || !access.tenantId || !access.userId) {
295
+ flash(
296
+ t(
297
+ 'wms.backend.inventory.mutations.errors.scope',
298
+ 'Select an organization and sign in before posting inventory changes.',
299
+ ),
300
+ 'error',
301
+ )
302
+ return
303
+ }
304
+
305
+ const lotNumber = parsed.data.lotNumber?.trim()
306
+ const serial = parsed.data.serialNumber?.trim()
307
+ const nextErrors: Record<string, string> = {}
308
+ if (trackingProfile?.trackLot && !lotNumber) {
309
+ nextErrors.lotNumber = t(
310
+ 'wms.backend.inventory.receive.errors.lotRequired',
311
+ 'Lot number is required for this variant.',
312
+ )
313
+ }
314
+ if (trackingProfile?.trackSerial && !serial) {
315
+ nextErrors.serialNumber = t(
316
+ 'wms.backend.inventory.receive.errors.serialRequired',
317
+ 'Serial number is required for this variant.',
318
+ )
319
+ }
320
+ if (Object.keys(nextErrors).length > 0) {
321
+ setFieldErrors(nextErrors)
322
+ return
323
+ }
324
+
325
+ setSubmitting(true)
326
+ try {
327
+ const payload: Record<string, unknown> = {
328
+ organizationId: access.organizationId,
329
+ tenantId: access.tenantId,
330
+ warehouseId: parsed.data.warehouseId,
331
+ locationId: parsed.data.locationId,
332
+ catalogVariantId: parsed.data.catalogVariantId,
333
+ quantity: parsed.data.quantity,
334
+ referenceType: parsed.data.referenceType,
335
+ referenceId: buildInventoryMutationReferenceId(),
336
+ performedBy: access.userId,
337
+ }
338
+ if (lotNumber) payload.lotNumber = lotNumber
339
+ if (serial) payload.serialNumber = serial
340
+ const notes = parsed.data.notes?.trim()
341
+ if (notes) payload.reason = notes
342
+
343
+ await runMutation({
344
+ operation: async () => {
345
+ const call = await apiCall<{ ok?: boolean; movementId?: string }>(
346
+ '/api/wms/inventory/receive',
347
+ {
348
+ method: 'POST',
349
+ headers: { 'content-type': 'application/json' },
350
+ body: JSON.stringify(payload),
351
+ },
352
+ )
353
+ if (!call.ok) {
354
+ await raiseCrudError(
355
+ call.response,
356
+ t('wms.backend.inventory.receive.errors.submit', 'Failed to receive inventory.'),
357
+ )
358
+ }
359
+ return call.result ?? {}
360
+ },
361
+ context: mutationContext,
362
+ mutationPayload: payload,
363
+ })
364
+
365
+ flash(t('wms.backend.inventory.receive.flash.success', 'Inventory received'), 'success')
366
+ await queryClient.invalidateQueries({ queryKey: ['wms-inventory-console'] })
367
+ await queryClient.invalidateQueries({ queryKey: ['wms-sku-detail'] })
368
+ onSuccess?.({
369
+ catalogVariantId: parsed.data.catalogVariantId,
370
+ warehouseId: parsed.data.warehouseId,
371
+ locationId: parsed.data.locationId,
372
+ quantity: parsed.data.quantity,
373
+ })
374
+ closeDialog()
375
+ } catch (error) {
376
+ flashMutationError(error, t('wms.backend.inventory.receive.errors.submit', 'Failed to receive inventory.'), t)
377
+ } finally {
378
+ setSubmitting(false)
379
+ }
380
+ },
381
+ [
382
+ access,
383
+ closeDialog,
384
+ form,
385
+ mutationContext,
386
+ onSuccess,
387
+ queryClient,
388
+ receiveFormSchema,
389
+ runMutation,
390
+ t,
391
+ trackingProfile,
392
+ ],
393
+ )
394
+
395
+ const handleDialogKeyDown = React.useCallback(
396
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
397
+ if (event.key === 'Escape') {
398
+ event.preventDefault()
399
+ closeDialog()
400
+ return
401
+ }
402
+ if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {
403
+ event.preventDefault()
404
+ if (!submitting) void handleSubmit()
405
+ }
406
+ },
407
+ [closeDialog, handleSubmit, submitting],
408
+ )
409
+
410
+ const adjustQuantity = React.useCallback((step: 1 | -1) => {
411
+ setForm((current) => {
412
+ const next = current.quantity + step
413
+ return { ...current, quantity: next < 1 ? 1 : next }
414
+ })
415
+ setFieldErrors({})
416
+ }, [])
417
+
418
+ return (
419
+ <Dialog open={open} onOpenChange={(next) => (next ? onOpenChange(true) : closeDialog())}>
420
+ <DialogContent
421
+ className="max-w-lg gap-0 overflow-hidden p-0"
422
+ onKeyDown={handleDialogKeyDown}
423
+ >
424
+ <div className="border-b px-6 py-4 pr-12">
425
+ <DialogHeader className="space-y-1 text-left">
426
+ <DialogTitle>
427
+ {t('wms.backend.inventory.receive.dialog.title', 'Receive inventory')}
428
+ </DialogTitle>
429
+ <DialogDescription>
430
+ {t(
431
+ 'wms.backend.inventory.receive.dialog.description',
432
+ 'Record inbound stock as a receipt movement',
433
+ )}
434
+ </DialogDescription>
435
+ </DialogHeader>
436
+ </div>
437
+
438
+ <form ref={formRef} onSubmit={handleSubmit} className="flex min-h-0 flex-1 flex-col">
439
+ <div className="flex flex-col gap-5 overflow-y-auto px-6 py-6">
440
+ <FormField
441
+ label={t('wms.backend.inventory.receive.form.variant', 'Variant')}
442
+ required
443
+ error={fieldErrors.catalogVariantId}
444
+ >
445
+ <div className="relative [&_input]:pl-9">
446
+ <Package
447
+ className="pointer-events-none absolute left-3 top-1/2 z-10 size-4 -translate-y-1/2 text-muted-foreground"
448
+ aria-hidden="true"
449
+ />
450
+ <ComboboxInput
451
+ value={form.catalogVariantId}
452
+ onChange={(next) => {
453
+ patchForm({
454
+ catalogVariantId: next.trim(),
455
+ lotNumber: '',
456
+ })
457
+ }}
458
+ loadSuggestions={async (query) => {
459
+ const options = await loadCatalogVariantOptions(query)
460
+ registerOptionLabels(options)
461
+ return options.map((option) => ({
462
+ value: option.value,
463
+ label: option.label,
464
+ description: option.description,
465
+ }))
466
+ }}
467
+ resolveLabel={resolveOptionLabel}
468
+ placeholder={t(
469
+ 'wms.backend.inventory.receive.form.variantPlaceholder',
470
+ 'Search variant or SKU',
471
+ )}
472
+ allowCustomValues={false}
473
+ disabled={submitting}
474
+ />
475
+ </div>
476
+ </FormField>
477
+
478
+ <div className="grid gap-5 sm:grid-cols-2">
479
+ <FormField
480
+ label={t('wms.backend.inventory.receive.form.warehouse', 'Warehouse')}
481
+ required
482
+ error={fieldErrors.warehouseId}
483
+ >
484
+ <ComboboxInput
485
+ value={form.warehouseId}
486
+ onChange={(next) => {
487
+ patchForm({
488
+ warehouseId: next.trim(),
489
+ locationId: '',
490
+ })
491
+ }}
492
+ loadSuggestions={async (query) => {
493
+ const options = await loadWarehouseOptions(query)
494
+ registerOptionLabels(options)
495
+ return options.map((option) => ({
496
+ value: option.value,
497
+ label: option.label,
498
+ }))
499
+ }}
500
+ resolveLabel={resolveOptionLabel}
501
+ placeholder={t(
502
+ 'wms.backend.inventory.receive.form.warehousePlaceholder',
503
+ 'Select warehouse',
504
+ )}
505
+ allowCustomValues={false}
506
+ disabled={submitting}
507
+ />
508
+ </FormField>
509
+
510
+ <FormField
511
+ label={t('wms.backend.inventory.receive.form.location', 'Location')}
512
+ required
513
+ error={fieldErrors.locationId}
514
+ >
515
+ <ComboboxInput
516
+ value={form.locationId}
517
+ onChange={(next) => patchForm({ locationId: next.trim() })}
518
+ loadSuggestions={async (query) => {
519
+ const options = await loadLocationOptions(form.warehouseId, query)
520
+ registerOptionLabels(options)
521
+ return options.map((option) => ({
522
+ value: option.value,
523
+ label: option.label,
524
+ }))
525
+ }}
526
+ resolveLabel={resolveOptionLabel}
527
+ placeholder={t(
528
+ 'wms.backend.inventory.receive.form.locationPlaceholder',
529
+ 'Select location',
530
+ )}
531
+ allowCustomValues={false}
532
+ disabled={submitting || !form.warehouseId}
533
+ />
534
+ </FormField>
535
+ </div>
536
+
537
+ <FormField
538
+ label={t('wms.backend.inventory.receive.form.lot', 'Lot')}
539
+ required={trackingProfile?.trackLot === true}
540
+ error={fieldErrors.lotNumber}
541
+ >
542
+ <ComboboxInput
543
+ value={form.lotNumber}
544
+ onChange={(next) => patchForm({ lotNumber: next.trim() })}
545
+ loadSuggestions={async (query) => {
546
+ const options = await loadLotNumberOptions(form.catalogVariantId, query)
547
+ registerOptionLabels(options)
548
+ return options.map((option) => ({
549
+ value: option.value,
550
+ label: option.label,
551
+ }))
552
+ }}
553
+ resolveLabel={resolveOptionLabel}
554
+ placeholder={t(
555
+ trackingProfile?.trackLot
556
+ ? 'wms.backend.inventory.receive.form.lotRequiredPlaceholder'
557
+ : 'wms.backend.inventory.receive.form.lotPlaceholder',
558
+ trackingProfile?.trackLot
559
+ ? 'Enter lot number'
560
+ : 'Select or create lot (optional)',
561
+ )}
562
+ allowCustomValues
563
+ disabled={submitting || !form.catalogVariantId}
564
+ />
565
+ </FormField>
566
+
567
+ <div className="grid gap-5 sm:grid-cols-2">
568
+ <FormField
569
+ label={t('wms.backend.inventory.receive.form.quantity', 'Quantity received')}
570
+ required
571
+ error={fieldErrors.quantity}
572
+ >
573
+ <div className="flex w-32 items-center gap-2 rounded-md border bg-background p-2 shadow-xs">
574
+ <IconButton
575
+ type="button"
576
+ variant="ghost"
577
+ size="sm"
578
+ aria-label={t('wms.backend.inventory.receive.form.decrease', 'Decrease quantity')}
579
+ onClick={() => adjustQuantity(-1)}
580
+ disabled={submitting || form.quantity <= 1}
581
+ >
582
+ <Minus className="size-4" />
583
+ </IconButton>
584
+ <Input
585
+ type="text"
586
+ inputMode="decimal"
587
+ value={String(form.quantity)}
588
+ onChange={(event) => {
589
+ const parsed = Number(event.target.value.trim())
590
+ if (Number.isFinite(parsed) && parsed > 0) {
591
+ patchForm({ quantity: parsed })
592
+ }
593
+ }}
594
+ className="h-8 w-auto min-w-0 flex-1 border-0 bg-transparent p-0 shadow-none focus-visible:ring-0"
595
+ inputClassName="text-center [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
596
+ disabled={submitting}
597
+ />
598
+ <IconButton
599
+ type="button"
600
+ variant="ghost"
601
+ size="sm"
602
+ aria-label={t('wms.backend.inventory.receive.form.increase', 'Increase quantity')}
603
+ onClick={() => adjustQuantity(1)}
604
+ disabled={submitting}
605
+ >
606
+ <Plus className="size-4" />
607
+ </IconButton>
608
+ </div>
609
+ </FormField>
610
+
611
+ <FormField
612
+ label={t('wms.backend.inventory.receive.form.referenceType', 'Receipt type')}
613
+ required
614
+ error={fieldErrors.referenceType}
615
+ >
616
+ <Select
617
+ value={form.referenceType}
618
+ onValueChange={(next) => patchForm({ referenceType: next as ReceiveReferenceType })}
619
+ disabled={submitting}
620
+ >
621
+ <SelectTrigger>
622
+ <SelectValue />
623
+ </SelectTrigger>
624
+ <SelectContent>
625
+ {RECEIVE_REFERENCE_TYPES.map((code) => (
626
+ <SelectItem key={code} value={code}>
627
+ {referenceTypeLabel(code)}
628
+ </SelectItem>
629
+ ))}
630
+ </SelectContent>
631
+ </Select>
632
+ </FormField>
633
+ </div>
634
+
635
+ <FormField
636
+ label={t('wms.backend.inventory.receive.form.serial', 'Serial number')}
637
+ required={trackingProfile?.trackSerial === true}
638
+ error={fieldErrors.serialNumber}
639
+ >
640
+ <Input
641
+ value={form.serialNumber}
642
+ onChange={(event) => patchForm({ serialNumber: event.target.value })}
643
+ placeholder={t(
644
+ trackingProfile?.trackSerial
645
+ ? 'wms.backend.inventory.receive.form.serialRequiredPlaceholder'
646
+ : 'wms.backend.inventory.receive.form.serialPlaceholder',
647
+ trackingProfile?.trackSerial
648
+ ? 'Enter serial number'
649
+ : 'Optional — for serial-tracked variants',
650
+ )}
651
+ disabled={submitting}
652
+ />
653
+ </FormField>
654
+
655
+ <FormField
656
+ label={t('wms.backend.inventory.receive.form.notes', 'Notes')}
657
+ error={fieldErrors.notes}
658
+ >
659
+ <Textarea
660
+ value={form.notes}
661
+ onChange={(event) => patchForm({ notes: event.target.value })}
662
+ placeholder={t(
663
+ 'wms.backend.inventory.receive.form.notesPlaceholder',
664
+ 'Optional notes or reference number',
665
+ )}
666
+ rows={2}
667
+ disabled={submitting}
668
+ />
669
+ </FormField>
670
+ </div>
671
+
672
+ <DialogFooter bordered={false} className="flex-row items-center justify-between border-t px-6 py-4">
673
+ <p className="hidden text-xs text-muted-foreground sm:inline-flex sm:items-center sm:gap-1.5">
674
+ <KbdShortcut keys={['⌘', 'Enter']} />
675
+ <span>/</span>
676
+ <KbdShortcut keys={['Ctrl', 'Enter']} />
677
+ <span>{t('wms.backend.inventory.receive.form.shortcut', 'to receive')}</span>
678
+ </p>
679
+ <div className="flex gap-2">
680
+ <Button type="button" variant="outline" onClick={closeDialog} disabled={submitting}>
681
+ {t('wms.backend.inventory.receive.form.cancel', 'Cancel')}
682
+ </Button>
683
+ <Button type="submit" disabled={submitting}>
684
+ <ArrowDown className="size-4" />
685
+ {submitting
686
+ ? t('wms.backend.inventory.receive.form.submitting', 'Receiving…')
687
+ : t('wms.backend.inventory.receive.form.submit', 'Receive')}
688
+ </Button>
689
+ </div>
690
+ </DialogFooter>
691
+ </form>
692
+ </DialogContent>
693
+ </Dialog>
694
+ )
695
+ }