@open-mercato/core 0.6.7-develop.6669.1.40b669666b → 0.6.7-develop.6671.1.4b925c5096

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,766 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { useQueryClient } from "@tanstack/react-query";
5
+ import { ArrowRight, Check, FileText } from "lucide-react";
6
+ import { flash } from "@open-mercato/ui/backend/FlashMessages";
7
+ import { flashMutationError } from "../../lib/flashMutationError.js";
8
+ import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuardedMutation";
9
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
10
+ import { raiseCrudError } from "@open-mercato/ui/backend/utils/serverErrors";
11
+ import { Button } from "@open-mercato/ui/primitives/button";
12
+ import {
13
+ Dialog,
14
+ DialogContent,
15
+ DialogDescription,
16
+ DialogFooter,
17
+ DialogHeader,
18
+ DialogTitle
19
+ } from "@open-mercato/ui/primitives/dialog";
20
+ import { Input } from "@open-mercato/ui/primitives/input";
21
+ import { KbdShortcut } from "@open-mercato/ui/primitives/kbd";
22
+ import {
23
+ Select,
24
+ SelectContent,
25
+ SelectItem,
26
+ SelectTrigger,
27
+ SelectValue
28
+ } from "@open-mercato/ui/primitives/select";
29
+ import { StatusBadge } from "@open-mercato/ui/primitives/status-badge";
30
+ import { Switch } from "@open-mercato/ui/primitives/switch";
31
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
32
+ import { createLogger } from "@open-mercato/shared/lib/logger";
33
+ import { cn } from "@open-mercato/shared/lib/utils";
34
+ import {
35
+ countMappedColumns,
36
+ detectColumnMappings,
37
+ mapCsvRowsWithMappings,
38
+ parseCsvText
39
+ } from "../../lib/inventoryImportCsv.js";
40
+ const logger = createLogger("wms");
41
+ const TARGET_FIELD_KEYS = [
42
+ "warehouseCode",
43
+ "locationCode",
44
+ "sku",
45
+ "quantity",
46
+ "lotNumber",
47
+ "serialNumber"
48
+ ];
49
+ function ImportStepIndicator({ step }) {
50
+ const steps = [1, 2, 3];
51
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 pt-1", "aria-label": `Step ${step} of 3`, children: steps.map((stepNumber, index) => {
52
+ const completed = stepNumber < step;
53
+ const current = stepNumber === step;
54
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
55
+ index > 0 ? /* @__PURE__ */ jsx(
56
+ "div",
57
+ {
58
+ className: cn(
59
+ "h-0.5 w-4 shrink-0",
60
+ stepNumber <= step ? "bg-foreground" : "bg-border"
61
+ ),
62
+ "aria-hidden": "true"
63
+ }
64
+ ) : null,
65
+ /* @__PURE__ */ jsx(
66
+ "div",
67
+ {
68
+ className: cn(
69
+ "flex size-5 shrink-0 items-center justify-center rounded-full text-xs font-semibold",
70
+ completed || current ? "bg-foreground text-primary-foreground" : "bg-muted text-muted-foreground"
71
+ ),
72
+ "aria-current": current ? "step" : void 0,
73
+ children: completed ? /* @__PURE__ */ jsx(Check, { className: "size-3", "aria-hidden": "true" }) : stepNumber
74
+ }
75
+ )
76
+ ] }, stepNumber);
77
+ }) });
78
+ }
79
+ function formatFileSize(bytes) {
80
+ if (bytes < 1024) return `${bytes} B`;
81
+ const kilobytes = bytes / 1024;
82
+ if (kilobytes < 1024) return `${Math.round(kilobytes)} KB`;
83
+ return `${(kilobytes / 1024).toFixed(1)} MB`;
84
+ }
85
+ function formatRowCount(value) {
86
+ return new Intl.NumberFormat().format(value);
87
+ }
88
+ function formatImportIssue(code, t) {
89
+ const duplicateMatch = /^duplicate_of_row_(\d+)$/.exec(code);
90
+ if (duplicateMatch) {
91
+ return t(
92
+ "wms.backend.inventory.import.validation.duplicate_of_row",
93
+ "Duplicate of row {row}",
94
+ { row: duplicateMatch[1] }
95
+ );
96
+ }
97
+ return t(`wms.backend.inventory.import.validation.${code}`, code);
98
+ }
99
+ function ImportInventoryDialog({ open, onOpenChange, access }) {
100
+ const t = useT();
101
+ const queryClient = useQueryClient();
102
+ const fileInputRef = React.useRef(null);
103
+ const [step, setStep] = React.useState(1);
104
+ const [selectedFile, setSelectedFile] = React.useState(null);
105
+ const [parsedFile, setParsedFile] = React.useState(null);
106
+ const [columnMappings, setColumnMappings] = React.useState([]);
107
+ const [validation, setValidation] = React.useState(null);
108
+ const [validating, setValidating] = React.useState(false);
109
+ const [applying, setApplying] = React.useState(false);
110
+ const [showIssueDetails, setShowIssueDetails] = React.useState(false);
111
+ const [skipDuplicates, setSkipDuplicates] = React.useState(true);
112
+ const [reconcileMode, setReconcileMode] = React.useState(false);
113
+ const [isDragging, setIsDragging] = React.useState(false);
114
+ const { runMutation, retryLastMutation } = useGuardedMutation({ contextId: "wms-inventory-import" });
115
+ const mutationContext = React.useMemo(
116
+ () => ({ retryLastMutation }),
117
+ [retryLastMutation]
118
+ );
119
+ const resetState = React.useCallback(() => {
120
+ setStep(1);
121
+ setSelectedFile(null);
122
+ setParsedFile(null);
123
+ setColumnMappings([]);
124
+ setValidation(null);
125
+ setValidating(false);
126
+ setApplying(false);
127
+ setShowIssueDetails(false);
128
+ setSkipDuplicates(true);
129
+ setReconcileMode(false);
130
+ setIsDragging(false);
131
+ }, []);
132
+ const closeDialog = React.useCallback(() => {
133
+ onOpenChange(false);
134
+ resetState();
135
+ }, [onOpenChange, resetState]);
136
+ React.useEffect(() => {
137
+ if (!open) resetState();
138
+ }, [open, resetState]);
139
+ const targetFieldLabel = React.useCallback(
140
+ (field) => {
141
+ const labels = {
142
+ warehouseCode: t("wms.backend.inventory.import.mapping.fields.warehouseCode", "warehouse_code"),
143
+ warehouseId: t("wms.backend.inventory.import.mapping.fields.warehouseId", "warehouse_id"),
144
+ locationCode: t("wms.backend.inventory.import.mapping.fields.locationCode", "location_code"),
145
+ locationId: t("wms.backend.inventory.import.mapping.fields.locationId", "location_id"),
146
+ sku: t("wms.backend.inventory.import.mapping.fields.sku", "sku"),
147
+ catalogVariantId: t(
148
+ "wms.backend.inventory.import.mapping.fields.catalogVariantId",
149
+ "catalog_variant_id"
150
+ ),
151
+ quantity: t("wms.backend.inventory.import.mapping.fields.quantity", "quantity"),
152
+ lotNumber: t("wms.backend.inventory.import.mapping.fields.lotNumber", "lot_number"),
153
+ lotId: t("wms.backend.inventory.import.mapping.fields.lotId", "lot_id"),
154
+ serialNumber: t("wms.backend.inventory.import.mapping.fields.serialNumber", "serial_number")
155
+ };
156
+ return labels[field];
157
+ },
158
+ [t]
159
+ );
160
+ const parseSelectedFile = React.useCallback(async (file) => {
161
+ const text = await file.text();
162
+ const parsed = parseCsvText(text);
163
+ const meta = {
164
+ headers: parsed.headers,
165
+ rowCount: parsed.rows.length,
166
+ fileSize: file.size
167
+ };
168
+ setParsedFile(meta);
169
+ setColumnMappings(detectColumnMappings(parsed.headers));
170
+ setValidation(null);
171
+ }, []);
172
+ const handleFileSelection = React.useCallback(
173
+ async (file) => {
174
+ setSelectedFile(file);
175
+ if (!file) {
176
+ setParsedFile(null);
177
+ setColumnMappings([]);
178
+ setValidation(null);
179
+ return;
180
+ }
181
+ await parseSelectedFile(file);
182
+ },
183
+ [parseSelectedFile]
184
+ );
185
+ const handleDownloadTemplate = React.useCallback(() => {
186
+ const anchor = document.createElement("a");
187
+ anchor.href = "/api/wms/inventory/import/template";
188
+ anchor.download = "wms-inventory-import-template.csv";
189
+ anchor.click();
190
+ }, []);
191
+ const handleAutoMap = React.useCallback(() => {
192
+ if (!parsedFile) return;
193
+ setColumnMappings(detectColumnMappings(parsedFile.headers));
194
+ }, [parsedFile]);
195
+ const handleReconcileModeChange = React.useCallback((checked) => {
196
+ setReconcileMode(checked);
197
+ setValidation(null);
198
+ }, []);
199
+ const handleMappingChange = React.useCallback(
200
+ (csvColumn, value) => {
201
+ setColumnMappings(
202
+ (current) => current.map((mapping) => {
203
+ if (mapping.csvColumn !== csvColumn) return mapping;
204
+ if (value === "skip") {
205
+ return { ...mapping, targetField: null, status: "skipped" };
206
+ }
207
+ return {
208
+ ...mapping,
209
+ targetField: value,
210
+ status: "mapped"
211
+ };
212
+ })
213
+ );
214
+ setValidation(null);
215
+ },
216
+ []
217
+ );
218
+ const handleDragOver = React.useCallback((event) => {
219
+ event.preventDefault();
220
+ event.stopPropagation();
221
+ setIsDragging(true);
222
+ }, []);
223
+ const handleDragLeave = React.useCallback((event) => {
224
+ event.preventDefault();
225
+ event.stopPropagation();
226
+ setIsDragging(false);
227
+ }, []);
228
+ const handleDrop = React.useCallback(
229
+ (event) => {
230
+ event.preventDefault();
231
+ event.stopPropagation();
232
+ setIsDragging(false);
233
+ const file = event.dataTransfer.files?.[0];
234
+ if (file) void handleFileSelection(file);
235
+ },
236
+ [handleFileSelection]
237
+ );
238
+ const handleValidate = React.useCallback(async () => {
239
+ if (!access.scopeReady || !access.organizationId || !access.tenantId) {
240
+ flash(t("wms.backend.inventory.import.errors.scope", "Select organization scope before importing."), "error");
241
+ return false;
242
+ }
243
+ if (!selectedFile) {
244
+ flash(t("wms.backend.inventory.import.errors.file", "Choose a CSV file first."), "error");
245
+ return false;
246
+ }
247
+ setValidating(true);
248
+ try {
249
+ const text = await selectedFile.text();
250
+ const parsed = parseCsvText(text);
251
+ const rows = mapCsvRowsWithMappings(parsed.headers, parsed.rows, columnMappings);
252
+ const call = await apiCall("/api/wms/inventory/import/validate", {
253
+ method: "POST",
254
+ headers: { "content-type": "application/json" },
255
+ body: JSON.stringify({
256
+ organizationId: access.organizationId,
257
+ tenantId: access.tenantId,
258
+ skipDuplicates,
259
+ mode: reconcileMode ? "reconcile" : "additive",
260
+ rows
261
+ })
262
+ });
263
+ if (!call.ok) {
264
+ await raiseCrudError(
265
+ call.response,
266
+ t("wms.backend.inventory.import.errors.validate", "Validation failed.")
267
+ );
268
+ }
269
+ setValidation(call.result ?? null);
270
+ if (call.result?.ok) {
271
+ flash(t("wms.backend.inventory.import.flash.validated", "CSV validated \u2014 review rows before applying."), "success");
272
+ } else {
273
+ flash(t("wms.backend.inventory.import.flash.validationErrors", "Fix validation errors before applying."), "error");
274
+ }
275
+ return Boolean(call.result);
276
+ } catch (error) {
277
+ logger.error("validate failed", { component: "ImportInventoryDialog", err: error });
278
+ flash(t("wms.backend.inventory.import.errors.validate", "Validation failed."), "error");
279
+ return false;
280
+ } finally {
281
+ setValidating(false);
282
+ }
283
+ }, [
284
+ access.organizationId,
285
+ access.scopeReady,
286
+ access.tenantId,
287
+ columnMappings,
288
+ reconcileMode,
289
+ selectedFile,
290
+ skipDuplicates,
291
+ t
292
+ ]);
293
+ const applyRows = React.useMemo(() => {
294
+ return (validation?.rows ?? []).filter((row) => row.resolved && (row.status === "valid" || row.status === "warning" || row.status === "skip")).map((row) => ({
295
+ rowNumber: row.rowNumber,
296
+ warehouseId: row.resolved.warehouseId,
297
+ locationId: row.resolved.locationId,
298
+ catalogVariantId: row.resolved.catalogVariantId,
299
+ quantity: row.resolved.quantity,
300
+ delta: row.resolved.delta,
301
+ lotId: row.resolved.lotId,
302
+ serialNumber: row.resolved.serialNumber
303
+ }));
304
+ }, [validation?.rows]);
305
+ const overwriteWarningRows = React.useMemo(() => {
306
+ return (validation?.rows ?? []).filter(
307
+ (row) => row.status === "warning" && row.warnings.includes("overwriting_existing_balance")
308
+ );
309
+ }, [validation?.rows]);
310
+ const importableRowCount = React.useMemo(() => {
311
+ return applyRows.filter((row) => Math.abs(row.delta) > 1e-6).length;
312
+ }, [applyRows]);
313
+ const canApply = Boolean(validation?.importBatchId) && importableRowCount > 0;
314
+ const issueRows = React.useMemo(() => {
315
+ return (validation?.rows ?? []).filter(
316
+ (row) => row.status === "error" || row.status === "skip" || row.errors.length > 0
317
+ );
318
+ }, [validation?.rows]);
319
+ const previewRows = React.useMemo(() => {
320
+ return (validation?.rows ?? []).filter((row) => row.resolved && (row.status === "valid" || row.status === "warning")).slice(0, 3);
321
+ }, [validation?.rows]);
322
+ const mappedColumnCount = countMappedColumns(columnMappings);
323
+ const handleApply = React.useCallback(async () => {
324
+ if (!access.scopeReady || !access.organizationId || !access.tenantId) return;
325
+ if (!validation?.importBatchId) return;
326
+ const mutationPayload = {
327
+ organizationId: access.organizationId,
328
+ tenantId: access.tenantId,
329
+ importBatchId: validation.importBatchId,
330
+ rows: applyRows
331
+ };
332
+ setApplying(true);
333
+ try {
334
+ const result = await runMutation({
335
+ operation: async () => {
336
+ const call = await apiCall(
337
+ "/api/wms/inventory/import/apply",
338
+ {
339
+ method: "POST",
340
+ headers: { "content-type": "application/json" },
341
+ body: JSON.stringify({
342
+ organizationId: access.organizationId,
343
+ tenantId: access.tenantId,
344
+ importBatchId: validation.importBatchId,
345
+ reason: reconcileMode ? t("wms.backend.inventory.import.defaultReasonReconcile", "CSV import opening balance") : t("wms.backend.inventory.import.defaultReason", "CSV import inventory receipt"),
346
+ continueOnError: true,
347
+ mode: reconcileMode ? "reconcile" : "additive",
348
+ rows: applyRows
349
+ })
350
+ }
351
+ );
352
+ if (!call.ok) {
353
+ await raiseCrudError(
354
+ call.response,
355
+ t("wms.backend.inventory.import.errors.apply", "Import failed.")
356
+ );
357
+ }
358
+ return call.result ?? {};
359
+ },
360
+ context: mutationContext,
361
+ mutationPayload
362
+ });
363
+ const applied = result?.summary?.applied ?? 0;
364
+ const skipped = result?.summary?.skipped ?? 0;
365
+ const failed = result?.summary?.failed ?? 0;
366
+ if (failed > 0) {
367
+ flash(
368
+ t(
369
+ "wms.backend.inventory.import.flash.appliedPartial",
370
+ "Import finished with errors ({applied} applied, {skipped} skipped, {failed} failed).",
371
+ { applied, skipped, failed }
372
+ ),
373
+ "warning"
374
+ );
375
+ } else {
376
+ flash(
377
+ t("wms.backend.inventory.import.flash.applied", "Import finished ({applied} applied, {skipped} skipped).", {
378
+ applied,
379
+ skipped
380
+ }),
381
+ "success"
382
+ );
383
+ }
384
+ await queryClient.invalidateQueries({ queryKey: ["wms-inventory-console"] });
385
+ await queryClient.invalidateQueries({ queryKey: ["wms-sku-detail"] });
386
+ closeDialog();
387
+ } catch (error) {
388
+ flashMutationError(error, t("wms.backend.inventory.import.errors.apply", "Import failed."), t);
389
+ } finally {
390
+ setApplying(false);
391
+ }
392
+ }, [
393
+ access.organizationId,
394
+ access.scopeReady,
395
+ access.tenantId,
396
+ applyRows,
397
+ closeDialog,
398
+ queryClient,
399
+ mutationContext,
400
+ reconcileMode,
401
+ runMutation,
402
+ t,
403
+ validation?.importBatchId
404
+ ]);
405
+ const handlePrimaryAction = React.useCallback(async () => {
406
+ if (step === 1) {
407
+ if (!selectedFile) {
408
+ flash(t("wms.backend.inventory.import.errors.file", "Choose a CSV file first."), "error");
409
+ return;
410
+ }
411
+ setStep(2);
412
+ return;
413
+ }
414
+ if (step === 2) {
415
+ const validated = await handleValidate();
416
+ if (validated) setStep(3);
417
+ return;
418
+ }
419
+ await handleApply();
420
+ }, [handleApply, handleValidate, selectedFile, step, t]);
421
+ const handleDialogKeyDown = React.useCallback(
422
+ (event) => {
423
+ if (event.key === "Escape") {
424
+ event.preventDefault();
425
+ closeDialog();
426
+ return;
427
+ }
428
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
429
+ event.preventDefault();
430
+ if (validating || applying) return;
431
+ if (step === 3 && !canApply) return;
432
+ void handlePrimaryAction();
433
+ }
434
+ },
435
+ [applying, canApply, closeDialog, handlePrimaryAction, step, validating]
436
+ );
437
+ const stepSubtitle = React.useMemo(() => {
438
+ if (step === 1) {
439
+ return t("wms.backend.inventory.import.steps.upload.subtitle", "Step 1 of 3 \xB7 Upload your file");
440
+ }
441
+ if (step === 2) {
442
+ return t(
443
+ "wms.backend.inventory.import.steps.mapping.subtitle",
444
+ "Step 2 of 3 \xB7 Map CSV columns to fields"
445
+ );
446
+ }
447
+ return t("wms.backend.inventory.import.steps.review.subtitle", "Step 3 of 3 \xB7 Review and import");
448
+ }, [step, t]);
449
+ const shortcutHint = React.useMemo(() => {
450
+ if (step === 3) {
451
+ return t("wms.backend.inventory.import.shortcut.import", "to import");
452
+ }
453
+ return t("wms.backend.inventory.import.shortcut.continue", "continue");
454
+ }, [step, t]);
455
+ const primaryDisabled = validating || applying || step === 1 && !selectedFile || step === 3 && !canApply;
456
+ const primaryLabel = React.useMemo(() => {
457
+ if (step === 1 || step === 2) {
458
+ return validating ? t("wms.backend.inventory.import.actions.validating", "Validating\u2026") : t("wms.backend.inventory.import.actions.next", "Next");
459
+ }
460
+ return applying ? t("wms.backend.inventory.import.actions.applying", "Importing\u2026") : t("wms.backend.inventory.import.actions.importRows", "Import {count} rows", {
461
+ count: formatRowCount(importableRowCount)
462
+ });
463
+ }, [applying, importableRowCount, step, t, validating]);
464
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (next) => next ? onOpenChange(true) : closeDialog(), children: /* @__PURE__ */ jsxs(
465
+ DialogContent,
466
+ {
467
+ className: "max-w-2xl gap-0 overflow-hidden p-0",
468
+ onKeyDown: handleDialogKeyDown,
469
+ children: [
470
+ /* @__PURE__ */ jsx("div", { className: "border-b px-6 py-4 pr-12", children: /* @__PURE__ */ jsxs(DialogHeader, { className: "space-y-1 text-left", children: [
471
+ /* @__PURE__ */ jsx(DialogTitle, { children: t("wms.backend.inventory.import.dialog.title", "Import CSV") }),
472
+ /* @__PURE__ */ jsx(DialogDescription, { children: stepSubtitle }),
473
+ /* @__PURE__ */ jsx(ImportStepIndicator, { step })
474
+ ] }) }),
475
+ /* @__PURE__ */ jsxs("div", { className: "flex max-h-[min(70vh,640px)] flex-col gap-5 overflow-y-auto px-6 py-6", children: [
476
+ step === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
477
+ /* @__PURE__ */ jsx(
478
+ "button",
479
+ {
480
+ type: "button",
481
+ className: cn(
482
+ "flex w-full flex-col items-center justify-center gap-2 rounded-lg border border-dashed px-5 py-8 text-center transition-colors",
483
+ isDragging ? "border-border bg-muted/60" : selectedFile ? "border-border bg-muted/40 hover:bg-muted/60" : "border-border bg-muted/20 hover:bg-muted/40"
484
+ ),
485
+ onClick: () => fileInputRef.current?.click(),
486
+ onDragOver: handleDragOver,
487
+ onDragLeave: handleDragLeave,
488
+ onDrop: handleDrop,
489
+ children: selectedFile ? /* @__PURE__ */ jsxs(Fragment, { children: [
490
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
491
+ /* @__PURE__ */ jsx(FileText, { className: "size-5 text-foreground", "aria-hidden": "true" }),
492
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: selectedFile.name })
493
+ ] }),
494
+ parsedFile ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t(
495
+ "wms.backend.inventory.import.upload.fileMeta",
496
+ "{rows} rows \xB7 {size} \xB7 detected",
497
+ {
498
+ rows: formatRowCount(parsedFile.rowCount),
499
+ size: formatFileSize(parsedFile.fileSize)
500
+ }
501
+ ) }) : null,
502
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-foreground", children: t("wms.backend.inventory.import.actions.chooseDifferent", "Choose different file") })
503
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
504
+ /* @__PURE__ */ jsx(FileText, { className: "size-5 text-muted-foreground", "aria-hidden": "true" }),
505
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: t("wms.backend.inventory.import.upload.dropzoneEmpty", "Choose CSV file or drop here") })
506
+ ] })
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsx(
510
+ Input,
511
+ {
512
+ ref: fileInputRef,
513
+ type: "file",
514
+ accept: ".csv,text/csv",
515
+ className: "hidden",
516
+ onChange: (event) => {
517
+ void handleFileSelection(event.target.files?.[0] ?? null);
518
+ }
519
+ }
520
+ ),
521
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [
522
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
523
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: t("wms.backend.inventory.import.upload.format", "Format") }),
524
+ /* @__PURE__ */ jsxs(Select, { value: "csv-comma", disabled: true, children: [
525
+ /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
526
+ /* @__PURE__ */ jsx(SelectContent, { children: /* @__PURE__ */ jsx(SelectItem, { value: "csv-comma", children: t(
527
+ "wms.backend.inventory.import.upload.formatValue",
528
+ "CSV \xB7 comma-separated"
529
+ ) }) })
530
+ ] })
531
+ ] }),
532
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
533
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: t("wms.backend.inventory.import.upload.encoding", "Encoding") }),
534
+ /* @__PURE__ */ jsxs(Select, { value: "utf8", disabled: true, children: [
535
+ /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
536
+ /* @__PURE__ */ jsx(SelectContent, { children: /* @__PURE__ */ jsx(SelectItem, { value: "utf8", children: t(
537
+ "wms.backend.inventory.import.upload.encodingValue",
538
+ "UTF-8 (auto-detected)"
539
+ ) }) })
540
+ ] })
541
+ ] })
542
+ ] }),
543
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
544
+ /* @__PURE__ */ jsx("div", { className: "flex justify-start", children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: () => void handleDownloadTemplate(), children: t("wms.backend.inventory.import.actions.template", "Download template") }) }),
545
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t(
546
+ "wms.backend.inventory.import.upload.skuHint",
547
+ "The sku column must match an existing catalog product variant in your organization. Warehouse and location codes must already exist in WMS."
548
+ ) }),
549
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t(
550
+ "wms.backend.inventory.import.upload.quantityHint",
551
+ "The quantity column is added to whatever stock already exists at that warehouse/location \u2014 it is not a target balance."
552
+ ) })
553
+ ] }),
554
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-status-warning-border bg-status-warning-bg px-3 py-3", children: [
555
+ /* @__PURE__ */ jsx(Switch, { checked: reconcileMode, onCheckedChange: handleReconcileModeChange }),
556
+ /* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
557
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-status-warning-text", children: t("wms.backend.inventory.import.upload.reconcileMode", "Reconcile to exact balance") }),
558
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-status-warning-text", children: t(
559
+ "wms.backend.inventory.import.upload.reconcileModeHint",
560
+ "Existing stock at each location is overwritten to match the file exactly \u2014 including reducing it. Use this for a full stocktake or opening-balance import. Leave off to add quantities to existing stock instead."
561
+ ) })
562
+ ] })
563
+ ] })
564
+ ] }) : null,
565
+ step === 2 ? /* @__PURE__ */ jsxs(Fragment, { children: [
566
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 rounded-lg bg-muted/50 px-3 py-2 text-xs font-medium text-foreground", children: [
567
+ /* @__PURE__ */ jsx("p", { children: t(
568
+ "wms.backend.inventory.import.mapping.summary",
569
+ "{mapped} of {total} columns mapped \xB7 {rows} rows detected",
570
+ {
571
+ mapped: mappedColumnCount,
572
+ total: columnMappings.length,
573
+ rows: formatRowCount(parsedFile?.rowCount ?? 0)
574
+ }
575
+ ) }),
576
+ /* @__PURE__ */ jsxs(
577
+ Button,
578
+ {
579
+ type: "button",
580
+ variant: "ghost",
581
+ size: "sm",
582
+ className: "h-auto px-1 py-0 text-xs font-medium",
583
+ onClick: handleAutoMap,
584
+ children: [
585
+ t("wms.backend.inventory.import.actions.autoMap", "Auto-map"),
586
+ /* @__PURE__ */ jsx(ArrowRight, { className: "size-3.5", "aria-hidden": "true" })
587
+ ]
588
+ }
589
+ )
590
+ ] }),
591
+ /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-muted/30 px-3 py-2", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)_auto] items-center gap-2 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: [
592
+ /* @__PURE__ */ jsx("span", { children: t("wms.backend.inventory.import.mapping.csvColumn", "CSV column") }),
593
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true" }),
594
+ /* @__PURE__ */ jsx("span", { children: t("wms.backend.inventory.import.mapping.targetField", "Target field") }),
595
+ /* @__PURE__ */ jsx("span", { className: "text-right", children: t("wms.backend.inventory.import.mapping.status", "Status") })
596
+ ] }) }),
597
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: columnMappings.map((mapping) => /* @__PURE__ */ jsxs(
598
+ "div",
599
+ {
600
+ className: "grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)_auto] items-center gap-2 rounded-lg border px-3 py-2.5",
601
+ children: [
602
+ /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold text-foreground", children: mapping.csvColumn }),
603
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", "aria-hidden": "true", children: "\u2192" }),
604
+ /* @__PURE__ */ jsxs(
605
+ Select,
606
+ {
607
+ value: mapping.targetField ?? "skip",
608
+ onValueChange: (value) => handleMappingChange(mapping.csvColumn, value),
609
+ children: [
610
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-9", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
611
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
612
+ TARGET_FIELD_KEYS.map((field) => /* @__PURE__ */ jsx(SelectItem, { value: field, children: targetFieldLabel(field) }, field)),
613
+ /* @__PURE__ */ jsx(SelectItem, { value: "skip", children: t("wms.backend.inventory.import.mapping.skipColumn", "\u2014 skip column") })
614
+ ] })
615
+ ]
616
+ }
617
+ ),
618
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(StatusBadge, { variant: mapping.status === "mapped" ? "success" : "neutral", children: mapping.status === "mapped" ? t("wms.backend.inventory.import.mapping.status.mapped", "Mapped") : t("wms.backend.inventory.import.mapping.status.skipped", "Skipped") }) })
619
+ ]
620
+ },
621
+ mapping.csvColumn
622
+ )) }),
623
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-lg border px-3 py-3", children: [
624
+ /* @__PURE__ */ jsx(Switch, { checked: skipDuplicates, onCheckedChange: setSkipDuplicates }),
625
+ /* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
626
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: t("wms.backend.inventory.import.review.skipDuplicates", "Skip duplicates") }),
627
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t(
628
+ "wms.backend.inventory.import.review.skipDuplicatesHint",
629
+ "Duplicate rows in the CSV file will be skipped instead of failing validation"
630
+ ) })
631
+ ] })
632
+ ] })
633
+ ] }) : null,
634
+ step === 3 && validation ? /* @__PURE__ */ jsxs(Fragment, { children: [
635
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-3 sm:grid-cols-3", children: [
636
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border px-3.5 py-3", children: [
637
+ /* @__PURE__ */ jsx("p", { className: "text-2xl font-bold tabular-nums text-foreground", children: formatRowCount(importableRowCount) }),
638
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("wms.backend.inventory.import.review.stats.rows", "Rows to import") })
639
+ ] }),
640
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border px-3.5 py-3", children: [
641
+ /* @__PURE__ */ jsx("p", { className: "text-2xl font-bold tabular-nums text-status-success-icon", children: mappedColumnCount }),
642
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("wms.backend.inventory.import.review.stats.columns", "Columns mapped") })
643
+ ] }),
644
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border px-3.5 py-3", children: [
645
+ /* @__PURE__ */ jsx("p", { className: "text-2xl font-bold tabular-nums text-status-warning-icon", children: issueRows.length }),
646
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("wms.backend.inventory.import.review.stats.issues", "Validation issues") })
647
+ ] })
648
+ ] }),
649
+ issueRows.length > 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-status-warning-border bg-status-warning-bg px-4 py-3.5", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
650
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
651
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-status-warning-text", children: t(
652
+ "wms.backend.inventory.import.review.banner.title",
653
+ "{count} rows will be skipped on import",
654
+ { count: issueRows.length }
655
+ ) }),
656
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5 text-xs text-muted-foreground", children: (showIssueDetails ? issueRows : issueRows.slice(0, 2)).map((row) => /* @__PURE__ */ jsx("p", { children: t(
657
+ "wms.backend.inventory.import.review.banner.rowIssue",
658
+ "Row {row}: {issue}",
659
+ {
660
+ row: row.rowNumber,
661
+ issue: [...row.errors, ...row.warnings].map((code) => formatImportIssue(code, t)).join(", ") || row.status
662
+ }
663
+ ) }, row.rowNumber)) })
664
+ ] }),
665
+ issueRows.length > 2 ? /* @__PURE__ */ jsx(
666
+ Button,
667
+ {
668
+ type: "button",
669
+ variant: "ghost",
670
+ size: "sm",
671
+ className: "h-auto shrink-0 px-1 py-0 text-xs font-medium text-status-warning-text hover:text-status-warning-text",
672
+ onClick: () => setShowIssueDetails((current) => !current),
673
+ children: showIssueDetails ? t("wms.backend.inventory.import.actions.hideDetails", "Hide details") : t("wms.backend.inventory.import.actions.viewDetails", "View details \u2192")
674
+ }
675
+ ) : null
676
+ ] }) }) : null,
677
+ overwriteWarningRows.length > 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-status-warning-border bg-status-warning-bg px-4 py-3.5", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
678
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-status-warning-text", children: t(
679
+ "wms.backend.inventory.import.review.overwriteBanner.title",
680
+ "{count} rows will change existing stock levels",
681
+ { count: overwriteWarningRows.length }
682
+ ) }),
683
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5 text-xs text-muted-foreground", children: overwriteWarningRows.map((row) => {
684
+ const current = row.resolved?.currentOnHand ?? 0;
685
+ const quantity = row.resolved?.quantity ?? 0;
686
+ const delta = row.resolved?.delta ?? 0;
687
+ const signedDelta = delta > 0 ? `+${delta}` : `${delta}`;
688
+ return /* @__PURE__ */ jsx("p", { children: t(
689
+ "wms.backend.inventory.import.review.overwriteBanner.rowDetail",
690
+ "Row {row}: {location} \u2014 {current} \u2192 {quantity} ({delta})",
691
+ {
692
+ row: row.rowNumber,
693
+ location: row.resolved?.locationCode ?? "\u2014",
694
+ current,
695
+ quantity,
696
+ delta: signedDelta
697
+ }
698
+ ) }, row.rowNumber);
699
+ }) })
700
+ ] }) }) : null,
701
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
702
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: t("wms.backend.inventory.import.review.preview.title", "Preview \xB7 first 3 rows") }),
703
+ /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-lg border", children: [
704
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1.2fr)_minmax(0,0.8fr)_minmax(0,1fr)_auto] gap-3 border-b bg-muted/40 px-3.5 py-2.5 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: [
705
+ /* @__PURE__ */ jsx("span", { children: t("wms.backend.inventory.import.columns.sku", "SKU") }),
706
+ /* @__PURE__ */ jsx("span", { children: t("wms.backend.inventory.import.columns.location", "Location") }),
707
+ /* @__PURE__ */ jsx("span", { children: t("wms.backend.inventory.import.review.preview.lot", "Lot") }),
708
+ /* @__PURE__ */ jsx("span", { className: "text-right", children: t("wms.backend.inventory.import.review.preview.qty", "Qty") })
709
+ ] }),
710
+ previewRows.length > 0 ? previewRows.map((row) => /* @__PURE__ */ jsxs(
711
+ "div",
712
+ {
713
+ className: "grid grid-cols-[minmax(0,1.2fr)_minmax(0,0.8fr)_minmax(0,1fr)_auto] gap-3 border-b px-3.5 py-2.5 text-xs last:border-b-0",
714
+ children: [
715
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium text-foreground", children: row.resolved?.sku ?? "\u2014" }),
716
+ /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: row.resolved?.locationCode ?? "\u2014" }),
717
+ /* @__PURE__ */ jsx("span", { className: "truncate text-muted-foreground", children: row.resolved?.serialNumber ?? row.resolved?.lotId ?? "\u2014" }),
718
+ /* @__PURE__ */ jsx("span", { className: "text-right font-semibold tabular-nums text-foreground", children: row.resolved?.quantity ?? "\u2014" })
719
+ ]
720
+ },
721
+ row.rowNumber
722
+ )) : /* @__PURE__ */ jsx("p", { className: "px-3.5 py-4 text-sm text-muted-foreground", children: t("wms.backend.inventory.import.review.preview.empty", "No preview rows available.") })
723
+ ] })
724
+ ] })
725
+ ] }) : null
726
+ ] }),
727
+ /* @__PURE__ */ jsxs(DialogFooter, { bordered: false, className: "border-t px-6 py-4 sm:justify-between", children: [
728
+ /* @__PURE__ */ jsxs("p", { className: "hidden text-xs text-muted-foreground sm:inline-flex sm:items-center sm:gap-1.5", children: [
729
+ /* @__PURE__ */ jsx(KbdShortcut, { keys: ["\u2318", "Enter"] }),
730
+ /* @__PURE__ */ jsx("span", { children: "/" }),
731
+ /* @__PURE__ */ jsx(KbdShortcut, { keys: ["Ctrl", "Enter"] }),
732
+ /* @__PURE__ */ jsx("span", { children: shortcutHint })
733
+ ] }),
734
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col-reverse gap-2 sm:w-auto sm:flex-row", children: [
735
+ step === 1 ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: closeDialog, disabled: validating || applying, children: t("wms.backend.inventory.import.actions.cancel", "Cancel") }) : /* @__PURE__ */ jsx(
736
+ Button,
737
+ {
738
+ type: "button",
739
+ variant: "outline",
740
+ onClick: () => setStep((current) => current === 3 ? 2 : 1),
741
+ disabled: validating || applying,
742
+ children: t("wms.backend.inventory.import.actions.back", "Back")
743
+ }
744
+ ),
745
+ /* @__PURE__ */ jsxs(
746
+ Button,
747
+ {
748
+ type: "button",
749
+ disabled: primaryDisabled,
750
+ onClick: () => void handlePrimaryAction(),
751
+ children: [
752
+ primaryLabel,
753
+ step !== 3 ? /* @__PURE__ */ jsx(ArrowRight, { className: "size-4", "aria-hidden": "true" }) : null
754
+ ]
755
+ }
756
+ )
757
+ ] })
758
+ ] })
759
+ ]
760
+ }
761
+ ) });
762
+ }
763
+ export {
764
+ ImportInventoryDialog
765
+ };
766
+ //# sourceMappingURL=ImportInventoryDialog.js.map