@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.
- package/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/inventory_balance/index.js +21 -0
- package/dist/generated/entities/inventory_balance/index.js.map +7 -0
- package/dist/generated/entities/inventory_lot/index.js +19 -0
- package/dist/generated/entities/inventory_lot/index.js.map +7 -0
- package/dist/generated/entities/inventory_movement/index.js +35 -0
- package/dist/generated/entities/inventory_movement/index.js.map +7 -0
- package/dist/generated/entities/inventory_reservation/index.js +23 -0
- package/dist/generated/entities/inventory_reservation/index.js.map +7 -0
- package/dist/generated/entities/product_inventory_profile/index.js +21 -0
- package/dist/generated/entities/product_inventory_profile/index.js.map +7 -0
- package/dist/generated/entities/sales_order_warehouse_assignment/index.js +11 -0
- package/dist/generated/entities/sales_order_warehouse_assignment/index.js.map +7 -0
- package/dist/generated/entities/warehouse/index.js +25 -0
- package/dist/generated/entities/warehouse/index.js.map +7 -0
- package/dist/generated/entities/warehouse_location/index.js +21 -0
- package/dist/generated/entities/warehouse_location/index.js.map +7 -0
- package/dist/generated/entities/warehouse_zone/index.js +11 -0
- package/dist/generated/entities/warehouse_zone/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +12 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +98 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +12 -4
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/lib/backendChrome.js +1 -0
- package/dist/modules/auth/lib/backendChrome.js.map +2 -2
- package/dist/modules/auth/services/rbacService.js +16 -17
- package/dist/modules/auth/services/rbacService.js.map +2 -2
- package/dist/modules/catalog/api/products/route.js +3 -0
- package/dist/modules/catalog/api/products/route.js.map +2 -2
- package/dist/modules/catalog/api/variants/route.js +3 -0
- package/dist/modules/catalog/api/variants/route.js.map +2 -2
- package/dist/modules/customer_accounts/migrations/Migration20260724120000_customer_accounts.js +56 -0
- package/dist/modules/customer_accounts/migrations/Migration20260724120000_customer_accounts.js.map +7 -0
- package/dist/modules/directory/api/organizations/route.js +1 -1
- package/dist/modules/directory/api/organizations/route.js.map +1 -1
- package/dist/modules/entities/api/definitions.js +2 -0
- package/dist/modules/entities/api/definitions.js.map +2 -2
- package/dist/modules/entities/lib/helpers.js +1 -0
- package/dist/modules/entities/lib/helpers.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +6 -6
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +1 -0
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/dist/modules/sales/api/quotes/accept/route.js +7 -2
- package/dist/modules/sales/api/quotes/accept/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/public/[token]/route.js +2 -1
- package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +53 -0
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +51 -2
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/events.js +2 -0
- package/dist/modules/sales/events.js.map +2 -2
- package/dist/modules/sales/lib/publicQuoteTenantScope.js +24 -0
- package/dist/modules/sales/lib/publicQuoteTenantScope.js.map +7 -0
- package/dist/modules/sales/widgets/injection/order-items-context.js +11 -0
- package/dist/modules/sales/widgets/injection/order-items-context.js.map +7 -0
- package/dist/modules/wms/acl.js +18 -0
- package/dist/modules/wms/acl.js.map +7 -0
- package/dist/modules/wms/analytics.js +11 -0
- package/dist/modules/wms/analytics.js.map +7 -0
- package/dist/modules/wms/api/dashboard/operational/route.js +80 -0
- package/dist/modules/wms/api/dashboard/operational/route.js.map +7 -0
- package/dist/modules/wms/api/interceptors.js +90 -0
- package/dist/modules/wms/api/interceptors.js.map +7 -0
- package/dist/modules/wms/api/inventory/adjust/route.js +51 -0
- package/dist/modules/wms/api/inventory/adjust/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/allocate/route.js +51 -0
- package/dist/modules/wms/api/inventory/allocate/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/balances/route.js +172 -0
- package/dist/modules/wms/api/inventory/balances/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/cycle-count/route.js +52 -0
- package/dist/modules/wms/api/inventory/cycle-count/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/helpers.js +113 -0
- package/dist/modules/wms/api/inventory/helpers.js.map +7 -0
- package/dist/modules/wms/api/inventory/import/apply/route.js +46 -0
- package/dist/modules/wms/api/inventory/import/apply/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/import/helpers.js +195 -0
- package/dist/modules/wms/api/inventory/import/helpers.js.map +7 -0
- package/dist/modules/wms/api/inventory/import/template/route.js +32 -0
- package/dist/modules/wms/api/inventory/import/template/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/import/validate/route.js +54 -0
- package/dist/modules/wms/api/inventory/import/validate/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/move/route.js +51 -0
- package/dist/modules/wms/api/inventory/move/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/movements/route.js +164 -0
- package/dist/modules/wms/api/inventory/movements/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/receive/route.js +50 -0
- package/dist/modules/wms/api/inventory/receive/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/release/route.js +44 -0
- package/dist/modules/wms/api/inventory/release/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/reservations/route.js +128 -0
- package/dist/modules/wms/api/inventory/reservations/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/reserve/route.js +59 -0
- package/dist/modules/wms/api/inventory/reserve/route.js.map +7 -0
- package/dist/modules/wms/api/inventory-profiles/route.js +178 -0
- package/dist/modules/wms/api/inventory-profiles/route.js.map +7 -0
- package/dist/modules/wms/api/listEnrichers.js +181 -0
- package/dist/modules/wms/api/listEnrichers.js.map +7 -0
- package/dist/modules/wms/api/listSearch.js +77 -0
- package/dist/modules/wms/api/listSearch.js.map +7 -0
- package/dist/modules/wms/api/locations/route.js +172 -0
- package/dist/modules/wms/api/locations/route.js.map +7 -0
- package/dist/modules/wms/api/lots/route.js +204 -0
- package/dist/modules/wms/api/lots/route.js.map +7 -0
- package/dist/modules/wms/api/openapi.js +27 -0
- package/dist/modules/wms/api/openapi.js.map +7 -0
- package/dist/modules/wms/api/sales-orders/[salesOrderId]/re-run-reservation/route.js +54 -0
- package/dist/modules/wms/api/sales-orders/[salesOrderId]/re-run-reservation/route.js.map +7 -0
- package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js +279 -0
- package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js.map +7 -0
- package/dist/modules/wms/api/sales-orders/assign-warehouse/route.js +56 -0
- package/dist/modules/wms/api/sales-orders/assign-warehouse/route.js.map +7 -0
- package/dist/modules/wms/api/sales-orders/unassign-warehouse/route.js +43 -0
- package/dist/modules/wms/api/sales-orders/unassign-warehouse/route.js.map +7 -0
- package/dist/modules/wms/api/warehouses/route.js +181 -0
- package/dist/modules/wms/api/warehouses/route.js.map +7 -0
- package/dist/modules/wms/api/zones/route.js +159 -0
- package/dist/modules/wms/api/zones/route.js.map +7 -0
- package/dist/modules/wms/backend/config/wms/page.js +9 -0
- package/dist/modules/wms/backend/config/wms/page.js.map +7 -0
- package/dist/modules/wms/backend/config/wms/page.meta.js +18 -0
- package/dist/modules/wms/backend/config/wms/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/page.js +9 -0
- package/dist/modules/wms/backend/page.js.map +7 -0
- package/dist/modules/wms/backend/page.meta.js +16 -0
- package/dist/modules/wms/backend/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/inventory/page.js +9 -0
- package/dist/modules/wms/backend/wms/inventory/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/inventory/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/inventory/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/location/[id]/page.js +9 -0
- package/dist/modules/wms/backend/wms/location/[id]/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/location/[id]/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/location/[id]/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/locations/page.js +10 -0
- package/dist/modules/wms/backend/wms/locations/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/locations/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/locations/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/lot/[id]/page.js +9 -0
- package/dist/modules/wms/backend/wms/lot/[id]/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/lot/[id]/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/lot/[id]/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/lots/page.js +9 -0
- package/dist/modules/wms/backend/wms/lots/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/lots/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/lots/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/movements/page.js +22 -0
- package/dist/modules/wms/backend/wms/movements/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/movements/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/movements/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/reservations/page.js +23 -0
- package/dist/modules/wms/backend/wms/reservations/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/reservations/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/reservations/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/sku/[id]/page.js +9 -0
- package/dist/modules/wms/backend/wms/sku/[id]/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/sku/[id]/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/sku/[id]/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/warehouses/page.js +10 -0
- package/dist/modules/wms/backend/wms/warehouses/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/warehouses/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/warehouses/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/zones/page.js +10 -0
- package/dist/modules/wms/backend/wms/zones/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/zones/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/zones/page.meta.js.map +7 -0
- package/dist/modules/wms/ce.js +80 -0
- package/dist/modules/wms/ce.js.map +7 -0
- package/dist/modules/wms/cli.js +83 -0
- package/dist/modules/wms/cli.js.map +7 -0
- package/dist/modules/wms/commands/configuration.js +1519 -0
- package/dist/modules/wms/commands/configuration.js.map +7 -0
- package/dist/modules/wms/commands/index.js +4 -0
- package/dist/modules/wms/commands/index.js.map +7 -0
- package/dist/modules/wms/commands/inventory-actions.js +1539 -0
- package/dist/modules/wms/commands/inventory-actions.js.map +7 -0
- package/dist/modules/wms/commands/sales-order-assignment.js +277 -0
- package/dist/modules/wms/commands/sales-order-assignment.js.map +7 -0
- package/dist/modules/wms/commands/shared.js +82 -0
- package/dist/modules/wms/commands/shared.js.map +7 -0
- package/dist/modules/wms/components/backend/AdjustInventoryDialog.js +755 -0
- package/dist/modules/wms/components/backend/AdjustInventoryDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/ChangeLotStatusDialog.js +269 -0
- package/dist/modules/wms/components/backend/ChangeLotStatusDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/CycleCountWizardDialog.js +1783 -0
- package/dist/modules/wms/components/backend/CycleCountWizardDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/ImportInventoryDialog.js +766 -0
- package/dist/modules/wms/components/backend/ImportInventoryDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/InventoryOperationsSection.js +119 -0
- package/dist/modules/wms/components/backend/InventoryOperationsSection.js.map +7 -0
- package/dist/modules/wms/components/backend/LocationEditDialog.js +140 -0
- package/dist/modules/wms/components/backend/LocationEditDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/MoveInventoryDialog.js +791 -0
- package/dist/modules/wms/components/backend/MoveInventoryDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/ReceiveInventoryDialog.js +656 -0
- package/dist/modules/wms/components/backend/ReceiveInventoryDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/ReleaseReservationDialog.js +344 -0
- package/dist/modules/wms/components/backend/ReleaseReservationDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/ReserveInventoryDialog.js +475 -0
- package/dist/modules/wms/components/backend/ReserveInventoryDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js +1112 -0
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +908 -0
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +1015 -0
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js +1049 -0
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsLotsListPage.js +297 -0
- package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsOperationalDashboardPage.js +757 -0
- package/dist/modules/wms/components/backend/WmsOperationalDashboardPage.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +975 -0
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +7 -0
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +710 -0
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +7 -0
- package/dist/modules/wms/components/backend/useWmsInventoryMutationAccess.js +79 -0
- package/dist/modules/wms/components/backend/useWmsInventoryMutationAccess.js.map +7 -0
- package/dist/modules/wms/components/backend/useWmsInventoryScopeFromSearchParams.js +24 -0
- package/dist/modules/wms/components/backend/useWmsInventoryScopeFromSearchParams.js.map +7 -0
- package/dist/modules/wms/components/backend/wmsLookupLoaders.js +55 -0
- package/dist/modules/wms/components/backend/wmsLookupLoaders.js.map +7 -0
- package/dist/modules/wms/data/enrichers.js +501 -0
- package/dist/modules/wms/data/enrichers.js.map +7 -0
- package/dist/modules/wms/data/entities.js +467 -0
- package/dist/modules/wms/data/entities.js.map +7 -0
- package/dist/modules/wms/data/validators.js +399 -0
- package/dist/modules/wms/data/validators.js.map +7 -0
- package/dist/modules/wms/di.js +27 -0
- package/dist/modules/wms/di.js.map +7 -0
- package/dist/modules/wms/events.js +42 -0
- package/dist/modules/wms/events.js.map +7 -0
- package/dist/modules/wms/index.js +17 -0
- package/dist/modules/wms/index.js.map +7 -0
- package/dist/modules/wms/lib/catalogInventoryProfileIntent.js +54 -0
- package/dist/modules/wms/lib/catalogInventoryProfileIntent.js.map +7 -0
- package/dist/modules/wms/lib/catalogInventoryProfileSync.js +144 -0
- package/dist/modules/wms/lib/catalogInventoryProfileSync.js.map +7 -0
- package/dist/modules/wms/lib/expiry.js +29 -0
- package/dist/modules/wms/lib/expiry.js.map +7 -0
- package/dist/modules/wms/lib/flashMutationError.js +51 -0
- package/dist/modules/wms/lib/flashMutationError.js.map +7 -0
- package/dist/modules/wms/lib/inventoryDisplayUi.js +188 -0
- package/dist/modules/wms/lib/inventoryDisplayUi.js.map +7 -0
- package/dist/modules/wms/lib/inventoryIdempotency.js +37 -0
- package/dist/modules/wms/lib/inventoryIdempotency.js.map +7 -0
- package/dist/modules/wms/lib/inventoryImportCsv.js +173 -0
- package/dist/modules/wms/lib/inventoryImportCsv.js.map +7 -0
- package/dist/modules/wms/lib/inventoryImportService.js +468 -0
- package/dist/modules/wms/lib/inventoryImportService.js.map +7 -0
- package/dist/modules/wms/lib/inventoryMutationUi.js +25 -0
- package/dist/modules/wms/lib/inventoryMutationUi.js.map +7 -0
- package/dist/modules/wms/lib/inventoryPolicy.js +61 -0
- package/dist/modules/wms/lib/inventoryPolicy.js.map +7 -0
- package/dist/modules/wms/lib/inventoryReconciliation.js +193 -0
- package/dist/modules/wms/lib/inventoryReconciliation.js.map +7 -0
- package/dist/modules/wms/lib/inventoryTrackingValidation.js +13 -0
- package/dist/modules/wms/lib/inventoryTrackingValidation.js.map +7 -0
- package/dist/modules/wms/lib/loadOperationalDashboard.js +580 -0
- package/dist/modules/wms/lib/loadOperationalDashboard.js.map +7 -0
- package/dist/modules/wms/lib/lowStockBalanceFilter.js +49 -0
- package/dist/modules/wms/lib/lowStockBalanceFilter.js.map +7 -0
- package/dist/modules/wms/lib/primaryWarehousePolicy.js +32 -0
- package/dist/modules/wms/lib/primaryWarehousePolicy.js.map +7 -0
- package/dist/modules/wms/lib/roleFeatures.js +30 -0
- package/dist/modules/wms/lib/roleFeatures.js.map +7 -0
- package/dist/modules/wms/lib/salesOrderInventoryAutomation.js +291 -0
- package/dist/modules/wms/lib/salesOrderInventoryAutomation.js.map +7 -0
- package/dist/modules/wms/lib/salesOrderWarehouseAssignment.js +54 -0
- package/dist/modules/wms/lib/salesOrderWarehouseAssignment.js.map +7 -0
- package/dist/modules/wms/lib/wmsIntegrationToggles.js +71 -0
- package/dist/modules/wms/lib/wmsIntegrationToggles.js.map +7 -0
- package/dist/modules/wms/migrations/Migration20260428110546.js +78 -0
- package/dist/modules/wms/migrations/Migration20260428110546.js.map +7 -0
- package/dist/modules/wms/migrations/Migration20260527120000.js +15 -0
- package/dist/modules/wms/migrations/Migration20260527120000.js.map +7 -0
- package/dist/modules/wms/migrations/Migration20260527140000.js +37 -0
- package/dist/modules/wms/migrations/Migration20260527140000.js.map +7 -0
- package/dist/modules/wms/migrations/Migration20260613120000.js +23 -0
- package/dist/modules/wms/migrations/Migration20260613120000.js.map +7 -0
- package/dist/modules/wms/migrations/Migration20260616090000.js +13 -0
- package/dist/modules/wms/migrations/Migration20260616090000.js.map +7 -0
- package/dist/modules/wms/migrations/Migration20260707180000.js +15 -0
- package/dist/modules/wms/migrations/Migration20260707180000.js.map +7 -0
- package/dist/modules/wms/notifications.client.js +18 -0
- package/dist/modules/wms/notifications.client.js.map +7 -0
- package/dist/modules/wms/notifications.js +53 -0
- package/dist/modules/wms/notifications.js.map +7 -0
- package/dist/modules/wms/search.js +196 -0
- package/dist/modules/wms/search.js.map +7 -0
- package/dist/modules/wms/setup.js +30 -0
- package/dist/modules/wms/setup.js.map +7 -0
- package/dist/modules/wms/subscribers/low-stock-notification.js +40 -0
- package/dist/modules/wms/subscribers/low-stock-notification.js.map +7 -0
- package/dist/modules/wms/subscribers/reservation-shortfall-notification.js +69 -0
- package/dist/modules/wms/subscribers/reservation-shortfall-notification.js.map +7 -0
- package/dist/modules/wms/subscribers/sales-order-cancelled-release.js +14 -0
- package/dist/modules/wms/subscribers/sales-order-cancelled-release.js.map +7 -0
- package/dist/modules/wms/subscribers/sales-order-confirmed-reserve.js +14 -0
- package/dist/modules/wms/subscribers/sales-order-confirmed-reserve.js.map +7 -0
- package/dist/modules/wms/translations.js +10 -0
- package/dist/modules/wms/translations.js.map +7 -0
- package/dist/modules/wms/vector.js +9 -0
- package/dist/modules/wms/vector.js.map +7 -0
- package/dist/modules/wms/widgets/injection/catalog-inventory-profile/widget.js +200 -0
- package/dist/modules/wms/widgets/injection/catalog-inventory-profile/widget.js.map +7 -0
- package/dist/modules/wms/widgets/injection/order-items-stock-column/widget.js +104 -0
- package/dist/modules/wms/widgets/injection/order-items-stock-column/widget.js.map +7 -0
- package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.client.js +389 -0
- package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.client.js.map +7 -0
- package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.js +16 -0
- package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.js.map +7 -0
- package/dist/modules/wms/widgets/injection-table.js +36 -0
- package/dist/modules/wms/widgets/injection-table.js.map +7 -0
- package/dist/modules/wms/widgets/notifications/WmsLowStockRenderer.js +150 -0
- package/dist/modules/wms/widgets/notifications/WmsLowStockRenderer.js.map +7 -0
- package/dist/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.js +186 -0
- package/dist/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.js.map +7 -0
- package/dist/modules/wms/widgets/notifications/index.js +7 -0
- package/dist/modules/wms/widgets/notifications/index.js.map +7 -0
- package/generated/entities/inventory_balance/index.ts +9 -0
- package/generated/entities/inventory_lot/index.ts +8 -0
- package/generated/entities/inventory_movement/index.ts +16 -0
- package/generated/entities/inventory_reservation/index.ts +10 -0
- package/generated/entities/product_inventory_profile/index.ts +9 -0
- package/generated/entities/sales_order_warehouse_assignment/index.ts +4 -0
- package/generated/entities/warehouse/index.ts +11 -0
- package/generated/entities/warehouse_location/index.ts +9 -0
- package/generated/entities/warehouse_zone/index.ts +4 -0
- package/generated/entities.ids.generated.ts +12 -0
- package/generated/entity-fields-registry.ts +98 -0
- package/package.json +7 -7
- package/src/modules/auth/backend/roles/page.tsx +13 -4
- package/src/modules/auth/i18n/de.json +2 -0
- package/src/modules/auth/i18n/en.json +2 -0
- package/src/modules/auth/i18n/es.json +2 -0
- package/src/modules/auth/i18n/pl.json +2 -0
- package/src/modules/auth/lib/backendChrome.tsx +1 -0
- package/src/modules/auth/services/rbacService.ts +25 -21
- package/src/modules/catalog/api/products/route.ts +3 -0
- package/src/modules/catalog/api/variants/route.ts +3 -0
- package/src/modules/customer_accounts/migrations/Migration20260724120000_customer_accounts.ts +96 -0
- package/src/modules/directory/api/organizations/route.ts +1 -1
- package/src/modules/entities/api/definitions.ts +2 -0
- package/src/modules/entities/lib/helpers.ts +1 -0
- package/src/modules/query_index/lib/engine.ts +18 -6
- package/src/modules/sales/api/documents/factory.ts +1 -0
- package/src/modules/sales/api/quotes/accept/route.ts +9 -2
- package/src/modules/sales/api/quotes/public/[token]/route.ts +2 -1
- package/src/modules/sales/commands/documents.ts +71 -0
- package/src/modules/sales/components/documents/ItemsSection.tsx +58 -0
- package/src/modules/sales/events.ts +2 -0
- package/src/modules/sales/lib/publicQuoteTenantScope.ts +49 -0
- package/src/modules/sales/widgets/injection/order-items-context.ts +15 -0
- package/src/modules/wms/acl.ts +14 -0
- package/src/modules/wms/analytics.ts +9 -0
- package/src/modules/wms/api/dashboard/operational/route.ts +83 -0
- package/src/modules/wms/api/interceptors.ts +108 -0
- package/src/modules/wms/api/inventory/adjust/route.ts +50 -0
- package/src/modules/wms/api/inventory/allocate/route.ts +50 -0
- package/src/modules/wms/api/inventory/balances/route.ts +178 -0
- package/src/modules/wms/api/inventory/cycle-count/route.ts +51 -0
- package/src/modules/wms/api/inventory/helpers.ts +128 -0
- package/src/modules/wms/api/inventory/import/apply/route.ts +47 -0
- package/src/modules/wms/api/inventory/import/helpers.ts +223 -0
- package/src/modules/wms/api/inventory/import/template/route.ts +31 -0
- package/src/modules/wms/api/inventory/import/validate/route.ts +56 -0
- package/src/modules/wms/api/inventory/move/route.ts +50 -0
- package/src/modules/wms/api/inventory/movements/route.ts +164 -0
- package/src/modules/wms/api/inventory/receive/route.ts +49 -0
- package/src/modules/wms/api/inventory/release/route.ts +43 -0
- package/src/modules/wms/api/inventory/reservations/route.ts +128 -0
- package/src/modules/wms/api/inventory/reserve/route.ts +59 -0
- package/src/modules/wms/api/inventory-profiles/route.ts +177 -0
- package/src/modules/wms/api/listEnrichers.ts +312 -0
- package/src/modules/wms/api/listSearch.ts +121 -0
- package/src/modules/wms/api/locations/route.ts +171 -0
- package/src/modules/wms/api/lots/route.ts +205 -0
- package/src/modules/wms/api/openapi.ts +28 -0
- package/src/modules/wms/api/sales-orders/[salesOrderId]/re-run-reservation/route.ts +58 -0
- package/src/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.ts +306 -0
- package/src/modules/wms/api/sales-orders/assign-warehouse/route.ts +57 -0
- package/src/modules/wms/api/sales-orders/unassign-warehouse/route.ts +43 -0
- package/src/modules/wms/api/warehouses/route.ts +181 -0
- package/src/modules/wms/api/zones/route.ts +158 -0
- package/src/modules/wms/backend/config/wms/page.meta.ts +14 -0
- package/src/modules/wms/backend/config/wms/page.tsx +5 -0
- package/src/modules/wms/backend/page.meta.ts +12 -0
- package/src/modules/wms/backend/page.tsx +5 -0
- package/src/modules/wms/backend/wms/inventory/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/inventory/page.tsx +5 -0
- package/src/modules/wms/backend/wms/location/[id]/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/location/[id]/page.tsx +5 -0
- package/src/modules/wms/backend/wms/locations/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/locations/page.tsx +12 -0
- package/src/modules/wms/backend/wms/lot/[id]/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/lot/[id]/page.tsx +5 -0
- package/src/modules/wms/backend/wms/lots/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/lots/page.tsx +5 -0
- package/src/modules/wms/backend/wms/movements/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/movements/page.tsx +23 -0
- package/src/modules/wms/backend/wms/reservations/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/reservations/page.tsx +24 -0
- package/src/modules/wms/backend/wms/sku/[id]/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/sku/[id]/page.tsx +5 -0
- package/src/modules/wms/backend/wms/warehouses/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/warehouses/page.tsx +12 -0
- package/src/modules/wms/backend/wms/zones/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/zones/page.tsx +12 -0
- package/src/modules/wms/ce.ts +76 -0
- package/src/modules/wms/cli.ts +96 -0
- package/src/modules/wms/commands/configuration.ts +1844 -0
- package/src/modules/wms/commands/index.ts +3 -0
- package/src/modules/wms/commands/inventory-actions.ts +1866 -0
- package/src/modules/wms/commands/sales-order-assignment.ts +346 -0
- package/src/modules/wms/commands/shared.ts +90 -0
- package/src/modules/wms/components/backend/AdjustInventoryDialog.tsx +820 -0
- package/src/modules/wms/components/backend/ChangeLotStatusDialog.tsx +312 -0
- package/src/modules/wms/components/backend/CycleCountWizardDialog.tsx +2007 -0
- package/src/modules/wms/components/backend/ImportInventoryDialog.tsx +1018 -0
- package/src/modules/wms/components/backend/InventoryOperationsSection.tsx +159 -0
- package/src/modules/wms/components/backend/LocationEditDialog.tsx +185 -0
- package/src/modules/wms/components/backend/MoveInventoryDialog.tsx +907 -0
- package/src/modules/wms/components/backend/ReceiveInventoryDialog.tsx +695 -0
- package/src/modules/wms/components/backend/ReleaseReservationDialog.tsx +424 -0
- package/src/modules/wms/components/backend/ReserveInventoryDialog.tsx +511 -0
- package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +1340 -0
- package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +1132 -0
- package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +1310 -0
- package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +1355 -0
- package/src/modules/wms/components/backend/WmsLotsListPage.tsx +359 -0
- package/src/modules/wms/components/backend/WmsOperationalDashboardPage.tsx +958 -0
- package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +1245 -0
- package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +960 -0
- package/src/modules/wms/components/backend/useWmsInventoryMutationAccess.ts +89 -0
- package/src/modules/wms/components/backend/useWmsInventoryScopeFromSearchParams.ts +32 -0
- package/src/modules/wms/components/backend/wmsLookupLoaders.ts +78 -0
- package/src/modules/wms/data/enrichers.ts +718 -0
- package/src/modules/wms/data/entities.ts +436 -0
- package/src/modules/wms/data/validators.ts +463 -0
- package/src/modules/wms/di.ts +25 -0
- package/src/modules/wms/events.ts +41 -0
- package/src/modules/wms/i18n/de.json +1051 -0
- package/src/modules/wms/i18n/en.json +1051 -0
- package/src/modules/wms/i18n/es.json +1051 -0
- package/src/modules/wms/i18n/pl.json +1051 -0
- package/src/modules/wms/index.ts +15 -0
- package/src/modules/wms/lib/catalogInventoryProfileIntent.ts +65 -0
- package/src/modules/wms/lib/catalogInventoryProfileSync.ts +199 -0
- package/src/modules/wms/lib/expiry.ts +30 -0
- package/src/modules/wms/lib/flashMutationError.ts +74 -0
- package/src/modules/wms/lib/inventoryDisplayUi.ts +249 -0
- package/src/modules/wms/lib/inventoryIdempotency.ts +54 -0
- package/src/modules/wms/lib/inventoryImportCsv.ts +212 -0
- package/src/modules/wms/lib/inventoryImportService.ts +629 -0
- package/src/modules/wms/lib/inventoryMutationUi.ts +21 -0
- package/src/modules/wms/lib/inventoryPolicy.ts +111 -0
- package/src/modules/wms/lib/inventoryReconciliation.ts +263 -0
- package/src/modules/wms/lib/inventoryTrackingValidation.ts +23 -0
- package/src/modules/wms/lib/loadOperationalDashboard.ts +776 -0
- package/src/modules/wms/lib/lowStockBalanceFilter.ts +74 -0
- package/src/modules/wms/lib/primaryWarehousePolicy.ts +46 -0
- package/src/modules/wms/lib/roleFeatures.ts +32 -0
- package/src/modules/wms/lib/salesOrderInventoryAutomation.ts +390 -0
- package/src/modules/wms/lib/salesOrderWarehouseAssignment.ts +78 -0
- package/src/modules/wms/lib/wmsIntegrationToggles.ts +81 -0
- package/src/modules/wms/migrations/.snapshot-open-mercato.json +2880 -0
- package/src/modules/wms/migrations/Migration20260428110546.ts +91 -0
- package/src/modules/wms/migrations/Migration20260527120000.ts +15 -0
- package/src/modules/wms/migrations/Migration20260527140000.ts +35 -0
- package/src/modules/wms/migrations/Migration20260613120000.ts +21 -0
- package/src/modules/wms/migrations/Migration20260616090000.ts +11 -0
- package/src/modules/wms/migrations/Migration20260707180000.ts +13 -0
- package/src/modules/wms/notifications.client.ts +18 -0
- package/src/modules/wms/notifications.ts +51 -0
- package/src/modules/wms/search.ts +230 -0
- package/src/modules/wms/setup.ts +29 -0
- package/src/modules/wms/subscribers/low-stock-notification.ts +54 -0
- package/src/modules/wms/subscribers/reservation-shortfall-notification.ts +98 -0
- package/src/modules/wms/subscribers/sales-order-cancelled-release.ts +21 -0
- package/src/modules/wms/subscribers/sales-order-confirmed-reserve.ts +21 -0
- package/src/modules/wms/translations.ts +6 -0
- package/src/modules/wms/vector.ts +7 -0
- package/src/modules/wms/widgets/injection/catalog-inventory-profile/widget.ts +238 -0
- package/src/modules/wms/widgets/injection/order-items-stock-column/widget.tsx +153 -0
- package/src/modules/wms/widgets/injection/sales-order-stock-context/widget.client.tsx +476 -0
- package/src/modules/wms/widgets/injection/sales-order-stock-context/widget.ts +15 -0
- package/src/modules/wms/widgets/injection-table.ts +34 -0
- package/src/modules/wms/widgets/notifications/WmsLowStockRenderer.tsx +153 -0
- package/src/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.tsx +194 -0
- package/src/modules/wms/widgets/notifications/index.ts +2 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
async function resolveLowStockVariantIds(em, scope, mode) {
|
|
2
|
+
const params = [scope.organizationId, scope.tenantId];
|
|
3
|
+
let warehouseJoin = "";
|
|
4
|
+
if (scope.warehouseId) {
|
|
5
|
+
warehouseJoin = " and b.warehouse_id = ?";
|
|
6
|
+
params.push(scope.warehouseId);
|
|
7
|
+
}
|
|
8
|
+
const thresholdExpr = mode === "belowSafety" ? "coalesce(p.safety_stock, 0)" : "coalesce(p.reorder_point, 0)";
|
|
9
|
+
const thresholdGuard = mode === "belowSafety" ? "coalesce(p.safety_stock, 0) > 0" : "(coalesce(p.reorder_point, 0) > 0 or coalesce(p.safety_stock, 0) > 0)";
|
|
10
|
+
params.push(scope.organizationId, scope.tenantId);
|
|
11
|
+
const sql = `
|
|
12
|
+
select distinct p.catalog_variant_id as catalog_variant_id
|
|
13
|
+
from wms_product_inventory_profiles p
|
|
14
|
+
join (
|
|
15
|
+
select
|
|
16
|
+
b.catalog_variant_id,
|
|
17
|
+
b.warehouse_id,
|
|
18
|
+
sum(
|
|
19
|
+
coalesce(b.quantity_on_hand, 0)
|
|
20
|
+
- coalesce(b.quantity_reserved, 0)
|
|
21
|
+
- coalesce(b.quantity_allocated, 0)
|
|
22
|
+
) as available
|
|
23
|
+
from wms_inventory_balances b
|
|
24
|
+
where b.organization_id = ?
|
|
25
|
+
and b.tenant_id = ?
|
|
26
|
+
and b.deleted_at is null
|
|
27
|
+
${warehouseJoin}
|
|
28
|
+
group by b.catalog_variant_id, b.warehouse_id
|
|
29
|
+
) availability
|
|
30
|
+
on availability.catalog_variant_id = p.catalog_variant_id
|
|
31
|
+
where p.organization_id = ?
|
|
32
|
+
and p.tenant_id = ?
|
|
33
|
+
and p.deleted_at is null
|
|
34
|
+
and p.catalog_variant_id is not null
|
|
35
|
+
and ${thresholdGuard}
|
|
36
|
+
and availability.available <= ${thresholdExpr}
|
|
37
|
+
`;
|
|
38
|
+
const rows = await em.getConnection().execute(sql, params);
|
|
39
|
+
return rows.map((row) => row.catalog_variant_id?.trim()).filter((value) => Boolean(value));
|
|
40
|
+
}
|
|
41
|
+
const NO_MATCH_UUID = "00000000-0000-4000-8000-000000000000";
|
|
42
|
+
function formatLowStockVariantIdsForFilter(variantIds) {
|
|
43
|
+
return variantIds.length > 0 ? variantIds : [NO_MATCH_UUID];
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
formatLowStockVariantIdsForFilter,
|
|
47
|
+
resolveLowStockVariantIds
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=lowStockBalanceFilter.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/wms/lib/lowStockBalanceFilter.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\n\nexport type LowStockBalanceFilterMode = 'belowReorder' | 'belowSafety'\n\ntype LowStockScope = {\n organizationId: string\n tenantId: string\n warehouseId?: string | null\n}\n\nexport async function resolveLowStockVariantIds(\n em: EntityManager,\n scope: LowStockScope,\n mode: LowStockBalanceFilterMode,\n): Promise<string[]> {\n const params: unknown[] = [scope.organizationId, scope.tenantId]\n let warehouseJoin = ''\n if (scope.warehouseId) {\n warehouseJoin = ' and b.warehouse_id = ?'\n params.push(scope.warehouseId)\n }\n\n const thresholdExpr =\n mode === 'belowSafety'\n ? 'coalesce(p.safety_stock, 0)'\n : 'coalesce(p.reorder_point, 0)'\n\n const thresholdGuard =\n mode === 'belowSafety'\n ? 'coalesce(p.safety_stock, 0) > 0'\n : '(coalesce(p.reorder_point, 0) > 0 or coalesce(p.safety_stock, 0) > 0)'\n\n params.push(scope.organizationId, scope.tenantId)\n\n const sql = `\n select distinct p.catalog_variant_id as catalog_variant_id\n from wms_product_inventory_profiles p\n join (\n select\n b.catalog_variant_id,\n b.warehouse_id,\n sum(\n coalesce(b.quantity_on_hand, 0)\n - coalesce(b.quantity_reserved, 0)\n - coalesce(b.quantity_allocated, 0)\n ) as available\n from wms_inventory_balances b\n where b.organization_id = ?\n and b.tenant_id = ?\n and b.deleted_at is null\n ${warehouseJoin}\n group by b.catalog_variant_id, b.warehouse_id\n ) availability\n on availability.catalog_variant_id = p.catalog_variant_id\n where p.organization_id = ?\n and p.tenant_id = ?\n and p.deleted_at is null\n and p.catalog_variant_id is not null\n and ${thresholdGuard}\n and availability.available <= ${thresholdExpr}\n `\n\n const rows = await em.getConnection().execute<Array<{ catalog_variant_id: string }>>(sql, params)\n return rows\n .map((row) => row.catalog_variant_id?.trim())\n .filter((value): value is string => Boolean(value))\n}\n\n/** Sentinel UUID that never matches a real entity \u2014 forces zero results when a low-stock filter returns an empty variant set. */\nconst NO_MATCH_UUID = '00000000-0000-4000-8000-000000000000'\n\nexport function formatLowStockVariantIdsForFilter(variantIds: string[]): string[] {\n return variantIds.length > 0 ? variantIds : [NO_MATCH_UUID]\n}\n"],
|
|
5
|
+
"mappings": "AAUA,eAAsB,0BACpB,IACA,OACA,MACmB;AACnB,QAAM,SAAoB,CAAC,MAAM,gBAAgB,MAAM,QAAQ;AAC/D,MAAI,gBAAgB;AACpB,MAAI,MAAM,aAAa;AACrB,oBAAgB;AAChB,WAAO,KAAK,MAAM,WAAW;AAAA,EAC/B;AAEA,QAAM,gBACJ,SAAS,gBACL,gCACA;AAEN,QAAM,iBACJ,SAAS,gBACL,oCACA;AAEN,SAAO,KAAK,MAAM,gBAAgB,MAAM,QAAQ;AAEhD,QAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAgBJ,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAQX,cAAc;AAAA,sCACY,aAAa;AAAA;AAGjD,QAAM,OAAO,MAAM,GAAG,cAAc,EAAE,QAA+C,KAAK,MAAM;AAChG,SAAO,KACJ,IAAI,CAAC,QAAQ,IAAI,oBAAoB,KAAK,CAAC,EAC3C,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC;AACtD;AAGA,MAAM,gBAAgB;AAEf,SAAS,kCAAkC,YAAgC;AAChF,SAAO,WAAW,SAAS,IAAI,aAAa,CAAC,aAAa;AAC5D;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
2
|
+
import { Warehouse } from "../data/entities.js";
|
|
3
|
+
async function resolvePrimaryWarehouseId(em, scope) {
|
|
4
|
+
const warehouse = await findOneWithDecryption(
|
|
5
|
+
em,
|
|
6
|
+
Warehouse,
|
|
7
|
+
{
|
|
8
|
+
organizationId: scope.organizationId,
|
|
9
|
+
isPrimary: true,
|
|
10
|
+
isActive: true,
|
|
11
|
+
deletedAt: null
|
|
12
|
+
},
|
|
13
|
+
void 0,
|
|
14
|
+
scope
|
|
15
|
+
);
|
|
16
|
+
return warehouse?.id ?? null;
|
|
17
|
+
}
|
|
18
|
+
function sortWarehouseAvailabilityForReservation(warehouses, primaryWarehouseId) {
|
|
19
|
+
return [...warehouses].sort((left, right) => {
|
|
20
|
+
if (primaryWarehouseId) {
|
|
21
|
+
const leftPrimary = left.warehouseId === primaryWarehouseId ? 1 : 0;
|
|
22
|
+
const rightPrimary = right.warehouseId === primaryWarehouseId ? 1 : 0;
|
|
23
|
+
if (leftPrimary !== rightPrimary) return rightPrimary - leftPrimary;
|
|
24
|
+
}
|
|
25
|
+
return right.available - left.available;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
resolvePrimaryWarehouseId,
|
|
30
|
+
sortWarehouseAvailabilityForReservation
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=primaryWarehousePolicy.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/wms/lib/primaryWarehousePolicy.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { Warehouse } from '../data/entities'\n\ntype Scope = {\n tenantId: string\n organizationId: string\n}\n\nexport type WarehouseAvailability = {\n warehouseId: string\n available: number\n}\n\nexport async function resolvePrimaryWarehouseId(\n em: EntityManager,\n scope: Scope,\n): Promise<string | null> {\n const warehouse = await findOneWithDecryption(\n em,\n Warehouse,\n {\n organizationId: scope.organizationId,\n isPrimary: true,\n isActive: true,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n return warehouse?.id ?? null\n}\n\nexport function sortWarehouseAvailabilityForReservation(\n warehouses: WarehouseAvailability[],\n primaryWarehouseId: string | null,\n): WarehouseAvailability[] {\n return [...warehouses].sort((left, right) => {\n if (primaryWarehouseId) {\n const leftPrimary = left.warehouseId === primaryWarehouseId ? 1 : 0\n const rightPrimary = right.warehouseId === primaryWarehouseId ? 1 : 0\n if (leftPrimary !== rightPrimary) return rightPrimary - leftPrimary\n }\n return right.available - left.available\n })\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,6BAA6B;AACtC,SAAS,iBAAiB;AAY1B,eAAsB,0BACpB,IACA,OACwB;AACxB,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,MACE,gBAAgB,MAAM;AAAA,MACtB,WAAW;AAAA,MACX,UAAU;AAAA,MACV,WAAW;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,WAAW,MAAM;AAC1B;AAEO,SAAS,wCACd,YACA,oBACyB;AACzB,SAAO,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,MAAM,UAAU;AAC3C,QAAI,oBAAoB;AACtB,YAAM,cAAc,KAAK,gBAAgB,qBAAqB,IAAI;AAClE,YAAM,eAAe,MAAM,gBAAgB,qBAAqB,IAAI;AACpE,UAAI,gBAAgB,aAAc,QAAO,eAAe;AAAA,IAC1D;AACA,WAAO,MAAM,YAAY,KAAK;AAAA,EAChC,CAAC;AACH;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const WMS_OPERATOR_ROLE = "operator";
|
|
2
|
+
const WMS_SUPERVISOR_ROLE = "supervisor";
|
|
3
|
+
const WMS_CUSTOM_ROLE_NAMES = [WMS_OPERATOR_ROLE, WMS_SUPERVISOR_ROLE];
|
|
4
|
+
const WMS_OPERATOR_FEATURES = [
|
|
5
|
+
"wms.view",
|
|
6
|
+
"wms.adjust_inventory",
|
|
7
|
+
"wms.receive_inventory",
|
|
8
|
+
"wms.cycle_count"
|
|
9
|
+
];
|
|
10
|
+
const WMS_MANAGE_FEATURES = [
|
|
11
|
+
"wms.manage_warehouses",
|
|
12
|
+
"wms.manage_zones",
|
|
13
|
+
"wms.manage_locations",
|
|
14
|
+
"wms.manage_inventory",
|
|
15
|
+
"wms.manage_reservations"
|
|
16
|
+
];
|
|
17
|
+
const WMS_SUPERVISOR_FEATURES = [
|
|
18
|
+
...WMS_OPERATOR_FEATURES,
|
|
19
|
+
"wms.import",
|
|
20
|
+
...WMS_MANAGE_FEATURES
|
|
21
|
+
];
|
|
22
|
+
export {
|
|
23
|
+
WMS_CUSTOM_ROLE_NAMES,
|
|
24
|
+
WMS_MANAGE_FEATURES,
|
|
25
|
+
WMS_OPERATOR_FEATURES,
|
|
26
|
+
WMS_OPERATOR_ROLE,
|
|
27
|
+
WMS_SUPERVISOR_FEATURES,
|
|
28
|
+
WMS_SUPERVISOR_ROLE
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=roleFeatures.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/wms/lib/roleFeatures.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Reserved tenant role names seeded by WMS `setup.ts` via `ensureRoles`.\n * Other modules MUST NOT reuse `operator` or `supervisor` without coordinating ACL grants and i18n labels.\n */\nexport const WMS_OPERATOR_ROLE = 'operator' as const\nexport const WMS_SUPERVISOR_ROLE = 'supervisor' as const\n\nexport const WMS_CUSTOM_ROLE_NAMES = [WMS_OPERATOR_ROLE, WMS_SUPERVISOR_ROLE] as const\n\nexport const WMS_OPERATOR_FEATURES = [\n 'wms.view',\n 'wms.adjust_inventory',\n 'wms.receive_inventory',\n 'wms.cycle_count',\n] as const\n\nexport const WMS_MANAGE_FEATURES = [\n 'wms.manage_warehouses',\n 'wms.manage_zones',\n 'wms.manage_locations',\n 'wms.manage_inventory',\n 'wms.manage_reservations',\n] as const\n\nexport const WMS_SUPERVISOR_FEATURES = [\n ...WMS_OPERATOR_FEATURES,\n 'wms.import',\n ...WMS_MANAGE_FEATURES,\n] as const\n\nexport type WmsOperatorFeature = (typeof WMS_OPERATOR_FEATURES)[number]\nexport type WmsSupervisorFeature = (typeof WMS_SUPERVISOR_FEATURES)[number]\n"],
|
|
5
|
+
"mappings": "AAIO,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB;AAE5B,MAAM,wBAAwB,CAAC,mBAAmB,mBAAmB;AAErE,MAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,sBAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,0BAA0B;AAAA,EACrC,GAAG;AAAA,EACH;AAAA,EACA,GAAG;AACL;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
2
|
+
import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
3
|
+
import { E } from "../../../generated/entities.ids.generated.js";
|
|
4
|
+
import { InventoryBalance, InventoryReservation } from "../data/entities.js";
|
|
5
|
+
import { emitWmsEvent } from "../events.js";
|
|
6
|
+
import { loadExplicitWarehouseIdForOrder } from "./salesOrderWarehouseAssignment.js";
|
|
7
|
+
import {
|
|
8
|
+
resolvePrimaryWarehouseId,
|
|
9
|
+
sortWarehouseAvailabilityForReservation
|
|
10
|
+
} from "./primaryWarehousePolicy.js";
|
|
11
|
+
import { resolveWmsIntegrationToggleEnabled } from "./wmsIntegrationToggles.js";
|
|
12
|
+
function isInsufficientStockError(error) {
|
|
13
|
+
return error instanceof CrudHttpError && error.status === 409 && error.body?.error === "insufficient_stock";
|
|
14
|
+
}
|
|
15
|
+
function isBalanceIntegrityViolationError(error) {
|
|
16
|
+
return error instanceof CrudHttpError && error.status === 409 && error.body?.error === "balance_integrity_violation";
|
|
17
|
+
}
|
|
18
|
+
function toNumber(value) {
|
|
19
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
20
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
21
|
+
const parsed = Number(value);
|
|
22
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
23
|
+
}
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
function getWarehouseId(balance) {
|
|
27
|
+
const relation = balance.warehouse;
|
|
28
|
+
if (typeof relation === "string") return relation;
|
|
29
|
+
return typeof relation?.id === "string" ? relation.id : null;
|
|
30
|
+
}
|
|
31
|
+
function buildCommandContext(ctx, scope) {
|
|
32
|
+
return {
|
|
33
|
+
container: {
|
|
34
|
+
resolve: ctx.resolve
|
|
35
|
+
},
|
|
36
|
+
auth: null,
|
|
37
|
+
organizationScope: null,
|
|
38
|
+
selectedOrganizationId: scope.organizationId,
|
|
39
|
+
organizationIds: [scope.organizationId]
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async function isInventoryAutomationEnabled(ctx, tenantId) {
|
|
43
|
+
try {
|
|
44
|
+
const featureTogglesService = ctx.resolve("featureTogglesService");
|
|
45
|
+
const em = ctx.resolve("em");
|
|
46
|
+
return resolveWmsIntegrationToggleEnabled(
|
|
47
|
+
featureTogglesService,
|
|
48
|
+
em,
|
|
49
|
+
"wms_integration_sales_order_inventory",
|
|
50
|
+
tenantId
|
|
51
|
+
);
|
|
52
|
+
} catch {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function loadOrderViaQueryEngine(ctx, orderId, scope) {
|
|
57
|
+
const queryEngine = ctx.resolve("queryEngine");
|
|
58
|
+
const result = await queryEngine.query(E.sales.sales_order, {
|
|
59
|
+
tenantId: scope.tenantId,
|
|
60
|
+
organizationId: scope.organizationId,
|
|
61
|
+
filters: { id: { $eq: orderId } },
|
|
62
|
+
fields: ["id", "order_number", "tenant_id", "organization_id"],
|
|
63
|
+
page: { page: 1, pageSize: 1 }
|
|
64
|
+
});
|
|
65
|
+
return result.items[0] ?? null;
|
|
66
|
+
}
|
|
67
|
+
async function loadOrderLinesViaQueryEngine(ctx, orderId, scope) {
|
|
68
|
+
const queryEngine = ctx.resolve("queryEngine");
|
|
69
|
+
const result = await queryEngine.query(E.sales.sales_order_line, {
|
|
70
|
+
tenantId: scope.tenantId,
|
|
71
|
+
organizationId: scope.organizationId,
|
|
72
|
+
filters: { order_id: { $eq: orderId } },
|
|
73
|
+
fields: ["id", "kind", "product_variant_id", "quantity", "line_number"],
|
|
74
|
+
sort: [{ field: "line_number", dir: "asc" }],
|
|
75
|
+
page: { page: 1, pageSize: 1e3 }
|
|
76
|
+
});
|
|
77
|
+
return result.items;
|
|
78
|
+
}
|
|
79
|
+
async function loadActiveReservations(em, orderId, scope) {
|
|
80
|
+
return findWithDecryption(
|
|
81
|
+
em,
|
|
82
|
+
InventoryReservation,
|
|
83
|
+
{
|
|
84
|
+
sourceType: "order",
|
|
85
|
+
sourceId: orderId,
|
|
86
|
+
status: "active",
|
|
87
|
+
tenantId: scope.tenantId,
|
|
88
|
+
organizationId: scope.organizationId,
|
|
89
|
+
deletedAt: null
|
|
90
|
+
},
|
|
91
|
+
{ orderBy: { createdAt: "asc" } },
|
|
92
|
+
scope
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
async function loadBalances(em, variantIds, scope) {
|
|
96
|
+
if (variantIds.length === 0) return [];
|
|
97
|
+
return findWithDecryption(
|
|
98
|
+
em,
|
|
99
|
+
InventoryBalance,
|
|
100
|
+
{
|
|
101
|
+
catalogVariantId: { $in: variantIds },
|
|
102
|
+
tenantId: scope.tenantId,
|
|
103
|
+
organizationId: scope.organizationId,
|
|
104
|
+
deletedAt: null
|
|
105
|
+
},
|
|
106
|
+
void 0,
|
|
107
|
+
scope
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
function buildRequiredQuantityByVariant(lines) {
|
|
111
|
+
const quantities = /* @__PURE__ */ new Map();
|
|
112
|
+
for (const line of lines) {
|
|
113
|
+
if (line.kind !== "product" || !line.product_variant_id) continue;
|
|
114
|
+
const quantity = toNumber(line.quantity);
|
|
115
|
+
if (quantity <= 0) continue;
|
|
116
|
+
quantities.set(
|
|
117
|
+
line.product_variant_id,
|
|
118
|
+
(quantities.get(line.product_variant_id) ?? 0) + quantity
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
return quantities;
|
|
122
|
+
}
|
|
123
|
+
function buildReservedQuantityByVariant(reservations) {
|
|
124
|
+
const quantities = /* @__PURE__ */ new Map();
|
|
125
|
+
for (const reservation of reservations) {
|
|
126
|
+
quantities.set(
|
|
127
|
+
reservation.catalogVariantId,
|
|
128
|
+
(quantities.get(reservation.catalogVariantId) ?? 0) + toNumber(reservation.quantity)
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
return quantities;
|
|
132
|
+
}
|
|
133
|
+
function buildWarehouseAvailability(balances) {
|
|
134
|
+
const byVariant = /* @__PURE__ */ new Map();
|
|
135
|
+
for (const balance of balances) {
|
|
136
|
+
const warehouseId = getWarehouseId(balance);
|
|
137
|
+
if (!warehouseId) continue;
|
|
138
|
+
const available = toNumber(balance.quantityOnHand) - toNumber(balance.quantityReserved) - toNumber(balance.quantityAllocated);
|
|
139
|
+
if (available <= 0) continue;
|
|
140
|
+
const warehouseMap = byVariant.get(balance.catalogVariantId) ?? /* @__PURE__ */ new Map();
|
|
141
|
+
warehouseMap.set(warehouseId, (warehouseMap.get(warehouseId) ?? 0) + available);
|
|
142
|
+
byVariant.set(balance.catalogVariantId, warehouseMap);
|
|
143
|
+
}
|
|
144
|
+
const result = /* @__PURE__ */ new Map();
|
|
145
|
+
for (const [variantId, warehouseMap] of byVariant.entries()) {
|
|
146
|
+
result.set(
|
|
147
|
+
variantId,
|
|
148
|
+
Array.from(warehouseMap.entries()).map(([warehouseId, available]) => ({ warehouseId, available }))
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
async function reserveInventoryForConfirmedOrder(payload, ctx) {
|
|
154
|
+
if (!payload.orderId || !payload.tenantId || !payload.organizationId) return;
|
|
155
|
+
if (!await isInventoryAutomationEnabled(ctx, payload.tenantId)) return;
|
|
156
|
+
const scope = {
|
|
157
|
+
tenantId: payload.tenantId,
|
|
158
|
+
organizationId: payload.organizationId
|
|
159
|
+
};
|
|
160
|
+
const em = ctx.resolve("em").fork();
|
|
161
|
+
const commandBus = ctx.resolve("commandBus");
|
|
162
|
+
const commandCtx = buildCommandContext(ctx, scope);
|
|
163
|
+
const order = await loadOrderViaQueryEngine(ctx, payload.orderId, scope);
|
|
164
|
+
if (!order || typeof order.id !== "string") return;
|
|
165
|
+
const orderId = order.id;
|
|
166
|
+
const orderNumber = typeof order.order_number === "string" ? order.order_number : null;
|
|
167
|
+
const [lines, activeReservations] = await Promise.all([
|
|
168
|
+
loadOrderLinesViaQueryEngine(ctx, orderId, scope),
|
|
169
|
+
loadActiveReservations(em, orderId, scope)
|
|
170
|
+
]);
|
|
171
|
+
const requiredByVariant = buildRequiredQuantityByVariant(lines);
|
|
172
|
+
if (requiredByVariant.size === 0) return;
|
|
173
|
+
const reservedByVariant = buildReservedQuantityByVariant(activeReservations);
|
|
174
|
+
const balances = await loadBalances(em, Array.from(requiredByVariant.keys()), scope);
|
|
175
|
+
const availabilityByVariant = buildWarehouseAvailability(balances);
|
|
176
|
+
const [primaryWarehouseId, assignedWarehouseId] = await Promise.all([
|
|
177
|
+
resolvePrimaryWarehouseId(em, scope),
|
|
178
|
+
loadExplicitWarehouseIdForOrder(em, orderId, scope)
|
|
179
|
+
]);
|
|
180
|
+
const preferredWarehouseId = assignedWarehouseId ?? primaryWarehouseId;
|
|
181
|
+
const shortfalls = [];
|
|
182
|
+
for (const [variantId, requiredQuantity] of requiredByVariant.entries()) {
|
|
183
|
+
let remainingQuantity = requiredQuantity - (reservedByVariant.get(variantId) ?? 0);
|
|
184
|
+
if (remainingQuantity <= 0) continue;
|
|
185
|
+
let variantBuckets = availabilityByVariant.get(variantId) ?? [];
|
|
186
|
+
if (assignedWarehouseId) {
|
|
187
|
+
variantBuckets = variantBuckets.filter(
|
|
188
|
+
(bucket) => bucket.warehouseId === assignedWarehouseId
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
const warehouseAvailability = sortWarehouseAvailabilityForReservation(
|
|
192
|
+
variantBuckets,
|
|
193
|
+
preferredWarehouseId
|
|
194
|
+
);
|
|
195
|
+
let reservedForVariant = 0;
|
|
196
|
+
try {
|
|
197
|
+
for (const bucket of warehouseAvailability) {
|
|
198
|
+
if (remainingQuantity <= 0) break;
|
|
199
|
+
const reserveQuantity = Math.min(remainingQuantity, bucket.available);
|
|
200
|
+
if (reserveQuantity <= 0) continue;
|
|
201
|
+
await commandBus.execute("wms.inventory.reserve", {
|
|
202
|
+
input: {
|
|
203
|
+
tenantId: scope.tenantId,
|
|
204
|
+
organizationId: scope.organizationId,
|
|
205
|
+
warehouseId: bucket.warehouseId,
|
|
206
|
+
catalogVariantId: variantId,
|
|
207
|
+
quantity: reserveQuantity,
|
|
208
|
+
sourceType: "order",
|
|
209
|
+
sourceId: orderId,
|
|
210
|
+
metadata: {
|
|
211
|
+
automation: "sales.order.confirmed",
|
|
212
|
+
orderId,
|
|
213
|
+
orderNumber,
|
|
214
|
+
catalogVariantId: variantId
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
ctx: commandCtx
|
|
218
|
+
});
|
|
219
|
+
remainingQuantity -= reserveQuantity;
|
|
220
|
+
reservedForVariant += reserveQuantity;
|
|
221
|
+
bucket.available -= reserveQuantity;
|
|
222
|
+
}
|
|
223
|
+
} catch (error) {
|
|
224
|
+
if (!isInsufficientStockError(error)) throw error;
|
|
225
|
+
}
|
|
226
|
+
if (remainingQuantity > 1e-6) {
|
|
227
|
+
shortfalls.push({
|
|
228
|
+
catalogVariantId: variantId,
|
|
229
|
+
requiredQuantity,
|
|
230
|
+
reservedQuantity: reservedForVariant + (reservedByVariant.get(variantId) ?? 0),
|
|
231
|
+
shortfallQuantity: remainingQuantity
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (shortfalls.length > 0) {
|
|
236
|
+
await emitWmsEvent("wms.inventory.reservation_shortfall", {
|
|
237
|
+
id: orderId,
|
|
238
|
+
orderId,
|
|
239
|
+
orderNumber,
|
|
240
|
+
shortfalls,
|
|
241
|
+
tenantId: scope.tenantId,
|
|
242
|
+
organizationId: scope.organizationId
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
async function releaseInventoryForCancelledOrder(payload, ctx) {
|
|
247
|
+
if (!payload.orderId || !payload.tenantId || !payload.organizationId) return;
|
|
248
|
+
if (!await isInventoryAutomationEnabled(ctx, payload.tenantId)) return;
|
|
249
|
+
const scope = {
|
|
250
|
+
tenantId: payload.tenantId,
|
|
251
|
+
organizationId: payload.organizationId
|
|
252
|
+
};
|
|
253
|
+
const em = ctx.resolve("em").fork();
|
|
254
|
+
const commandBus = ctx.resolve("commandBus");
|
|
255
|
+
const commandCtx = buildCommandContext(ctx, scope);
|
|
256
|
+
const activeReservations = await loadActiveReservations(em, payload.orderId, scope);
|
|
257
|
+
for (const reservation of activeReservations) {
|
|
258
|
+
try {
|
|
259
|
+
await commandBus.execute("wms.inventory.release", {
|
|
260
|
+
input: {
|
|
261
|
+
tenantId: scope.tenantId,
|
|
262
|
+
organizationId: scope.organizationId,
|
|
263
|
+
reservationId: reservation.id,
|
|
264
|
+
reason: "sales.order.cancelled",
|
|
265
|
+
metadata: {
|
|
266
|
+
automation: "sales.order.cancelled",
|
|
267
|
+
orderId: payload.orderId
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
ctx: commandCtx
|
|
271
|
+
});
|
|
272
|
+
} catch (error) {
|
|
273
|
+
if (!isBalanceIntegrityViolationError(error)) throw error;
|
|
274
|
+
void emitWmsEvent("wms.inventory.balance_drift", {
|
|
275
|
+
id: reservation.id,
|
|
276
|
+
balanceId: reservation.id,
|
|
277
|
+
reservationId: reservation.id,
|
|
278
|
+
field: "quantityReserved",
|
|
279
|
+
attemptedValue: null,
|
|
280
|
+
clampedValue: null,
|
|
281
|
+
tenantId: scope.tenantId,
|
|
282
|
+
organizationId: scope.organizationId
|
|
283
|
+
}).catch(() => void 0);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
export {
|
|
288
|
+
releaseInventoryForCancelledOrder,
|
|
289
|
+
reserveInventoryForConfirmedOrder
|
|
290
|
+
};
|
|
291
|
+
//# sourceMappingURL=salesOrderInventoryAutomation.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/wms/lib/salesOrderInventoryAutomation.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { FeatureTogglesService } from '@open-mercato/core/modules/feature_toggles/lib/feature-flag-check'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { InventoryBalance, InventoryReservation } from '../data/entities'\nimport { emitWmsEvent } from '../events'\nimport { loadExplicitWarehouseIdForOrder } from './salesOrderWarehouseAssignment'\nimport {\n resolvePrimaryWarehouseId,\n sortWarehouseAvailabilityForReservation,\n type WarehouseAvailability,\n} from './primaryWarehousePolicy'\nimport { resolveWmsIntegrationToggleEnabled } from './wmsIntegrationToggles'\n\ntype EventContext = {\n resolve: <T = unknown>(name: string) => T\n}\n\ntype SalesOrderLifecyclePayload = {\n orderId?: string | null\n tenantId?: string | null\n organizationId?: string | null\n}\n\ntype Scope = {\n tenantId: string\n organizationId: string\n}\n\ntype ReservationShortfallLine = {\n catalogVariantId: string\n requiredQuantity: number\n reservedQuantity: number\n shortfallQuantity: number\n}\n\nfunction isInsufficientStockError(error: unknown): boolean {\n return error instanceof CrudHttpError && error.status === 409 && error.body?.error === 'insufficient_stock'\n}\n\nfunction isBalanceIntegrityViolationError(error: unknown): boolean {\n return error instanceof CrudHttpError && error.status === 409 && error.body?.error === 'balance_integrity_violation'\n}\n\ntype SalesOrderRow = {\n id?: string\n order_number?: string | null\n tenant_id?: string | null\n organization_id?: string | null\n}\n\ntype SalesOrderLineRow = {\n id?: string\n kind?: string | null\n product_variant_id?: string | null\n quantity?: string | number | null\n line_number?: number | null\n}\n\nfunction toNumber(value: unknown): number {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string' && value.trim().length > 0) {\n const parsed = Number(value)\n if (Number.isFinite(parsed)) return parsed\n }\n return 0\n}\n\nfunction getWarehouseId(balance: InventoryBalance): string | null {\n const relation = balance.warehouse as { id?: string } | string | undefined\n if (typeof relation === 'string') return relation\n return typeof relation?.id === 'string' ? relation.id : null\n}\n\nfunction buildCommandContext(ctx: EventContext, scope: Scope): CommandRuntimeContext {\n return {\n container: {\n resolve: ctx.resolve,\n } as CommandRuntimeContext['container'],\n auth: null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: [scope.organizationId],\n }\n}\n\nasync function isInventoryAutomationEnabled(ctx: EventContext, tenantId: string): Promise<boolean> {\n try {\n const featureTogglesService = ctx.resolve<FeatureTogglesService>('featureTogglesService')\n const em = ctx.resolve<EntityManager>('em')\n return resolveWmsIntegrationToggleEnabled(\n featureTogglesService,\n em,\n 'wms_integration_sales_order_inventory',\n tenantId,\n )\n } catch {\n return true\n }\n}\n\nasync function loadOrderViaQueryEngine(\n ctx: EventContext,\n orderId: string,\n scope: Scope,\n): Promise<SalesOrderRow | null> {\n // Read sales orders/lines via QueryEngine instead of importing the sales ORM\n // entity classes \u2014 keeps the WMS module decoupled from sales internals.\n // Sales mutations also flush their CRUD side effects synchronously through\n // the command bus before this subscriber fires, so the query_index/base\n // table is consistent at this point.\n const queryEngine = ctx.resolve<QueryEngine>('queryEngine')\n const result = await queryEngine.query<SalesOrderRow>(E.sales.sales_order, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n filters: { id: { $eq: orderId } },\n fields: ['id', 'order_number', 'tenant_id', 'organization_id'],\n page: { page: 1, pageSize: 1 },\n })\n return result.items[0] ?? null\n}\n\nasync function loadOrderLinesViaQueryEngine(\n ctx: EventContext,\n orderId: string,\n scope: Scope,\n): Promise<SalesOrderLineRow[]> {\n const queryEngine = ctx.resolve<QueryEngine>('queryEngine')\n const result = await queryEngine.query<SalesOrderLineRow>(E.sales.sales_order_line, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n filters: { order_id: { $eq: orderId } },\n fields: ['id', 'kind', 'product_variant_id', 'quantity', 'line_number'],\n sort: [{ field: 'line_number', dir: 'asc' as never }],\n page: { page: 1, pageSize: 1000 },\n })\n return result.items\n}\n\nasync function loadActiveReservations(\n em: EntityManager,\n orderId: string,\n scope: Scope,\n): Promise<InventoryReservation[]> {\n return findWithDecryption(\n em,\n InventoryReservation,\n {\n sourceType: 'order',\n sourceId: orderId,\n status: 'active',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n { orderBy: { createdAt: 'asc' } },\n scope,\n )\n}\n\nasync function loadBalances(\n em: EntityManager,\n variantIds: string[],\n scope: Scope,\n): Promise<InventoryBalance[]> {\n if (variantIds.length === 0) return []\n return findWithDecryption(\n em,\n InventoryBalance,\n {\n catalogVariantId: { $in: variantIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n}\n\nfunction buildRequiredQuantityByVariant(lines: SalesOrderLineRow[]): Map<string, number> {\n const quantities = new Map<string, number>()\n for (const line of lines) {\n if (line.kind !== 'product' || !line.product_variant_id) continue\n const quantity = toNumber(line.quantity)\n if (quantity <= 0) continue\n quantities.set(\n line.product_variant_id,\n (quantities.get(line.product_variant_id) ?? 0) + quantity,\n )\n }\n return quantities\n}\n\nfunction buildReservedQuantityByVariant(reservations: InventoryReservation[]): Map<string, number> {\n const quantities = new Map<string, number>()\n for (const reservation of reservations) {\n quantities.set(\n reservation.catalogVariantId,\n (quantities.get(reservation.catalogVariantId) ?? 0) + toNumber(reservation.quantity),\n )\n }\n return quantities\n}\n\nfunction buildWarehouseAvailability(\n balances: InventoryBalance[],\n): Map<string, WarehouseAvailability[]> {\n const byVariant = new Map<string, Map<string, number>>()\n for (const balance of balances) {\n const warehouseId = getWarehouseId(balance)\n if (!warehouseId) continue\n const available =\n toNumber(balance.quantityOnHand) -\n toNumber(balance.quantityReserved) -\n toNumber(balance.quantityAllocated)\n if (available <= 0) continue\n\n const warehouseMap = byVariant.get(balance.catalogVariantId) ?? new Map<string, number>()\n warehouseMap.set(warehouseId, (warehouseMap.get(warehouseId) ?? 0) + available)\n byVariant.set(balance.catalogVariantId, warehouseMap)\n }\n\n const result = new Map<string, WarehouseAvailability[]>()\n for (const [variantId, warehouseMap] of byVariant.entries()) {\n result.set(\n variantId,\n Array.from(warehouseMap.entries()).map(([warehouseId, available]) => ({ warehouseId, available })),\n )\n }\n return result\n}\n\nexport async function reserveInventoryForConfirmedOrder(\n payload: SalesOrderLifecyclePayload,\n ctx: EventContext,\n): Promise<void> {\n if (!payload.orderId || !payload.tenantId || !payload.organizationId) return\n if (!(await isInventoryAutomationEnabled(ctx, payload.tenantId))) return\n\n const scope: Scope = {\n tenantId: payload.tenantId,\n organizationId: payload.organizationId,\n }\n const em = ctx.resolve<EntityManager>('em').fork()\n const commandBus = ctx.resolve<CommandBus>('commandBus')\n const commandCtx = buildCommandContext(ctx, scope)\n const order = await loadOrderViaQueryEngine(ctx, payload.orderId, scope)\n if (!order || typeof order.id !== 'string') return\n\n const orderId = order.id\n const orderNumber = typeof order.order_number === 'string' ? order.order_number : null\n\n const [lines, activeReservations] = await Promise.all([\n loadOrderLinesViaQueryEngine(ctx, orderId, scope),\n loadActiveReservations(em, orderId, scope),\n ])\n const requiredByVariant = buildRequiredQuantityByVariant(lines)\n if (requiredByVariant.size === 0) return\n\n const reservedByVariant = buildReservedQuantityByVariant(activeReservations)\n const balances = await loadBalances(em, Array.from(requiredByVariant.keys()), scope)\n const availabilityByVariant = buildWarehouseAvailability(balances)\n const [primaryWarehouseId, assignedWarehouseId] = await Promise.all([\n resolvePrimaryWarehouseId(em, scope),\n loadExplicitWarehouseIdForOrder(em, orderId, scope),\n ])\n const preferredWarehouseId = assignedWarehouseId ?? primaryWarehouseId\n const shortfalls: ReservationShortfallLine[] = []\n\n for (const [variantId, requiredQuantity] of requiredByVariant.entries()) {\n let remainingQuantity = requiredQuantity - (reservedByVariant.get(variantId) ?? 0)\n if (remainingQuantity <= 0) continue\n\n let variantBuckets = availabilityByVariant.get(variantId) ?? []\n if (assignedWarehouseId) {\n variantBuckets = variantBuckets.filter(\n (bucket) => bucket.warehouseId === assignedWarehouseId,\n )\n }\n\n const warehouseAvailability = sortWarehouseAvailabilityForReservation(\n variantBuckets,\n preferredWarehouseId,\n )\n let reservedForVariant = 0\n try {\n for (const bucket of warehouseAvailability) {\n if (remainingQuantity <= 0) break\n const reserveQuantity = Math.min(remainingQuantity, bucket.available)\n if (reserveQuantity <= 0) continue\n\n await commandBus.execute('wms.inventory.reserve', {\n input: {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n warehouseId: bucket.warehouseId,\n catalogVariantId: variantId,\n quantity: reserveQuantity,\n sourceType: 'order',\n sourceId: orderId,\n metadata: {\n automation: 'sales.order.confirmed',\n orderId,\n orderNumber,\n catalogVariantId: variantId,\n },\n },\n ctx: commandCtx,\n })\n\n remainingQuantity -= reserveQuantity\n reservedForVariant += reserveQuantity\n bucket.available -= reserveQuantity\n }\n } catch (error) {\n if (!isInsufficientStockError(error)) throw error\n }\n\n if (remainingQuantity > 0.000001) {\n shortfalls.push({\n catalogVariantId: variantId,\n requiredQuantity,\n reservedQuantity: reservedForVariant + (reservedByVariant.get(variantId) ?? 0),\n shortfallQuantity: remainingQuantity,\n })\n }\n }\n\n if (shortfalls.length > 0) {\n await emitWmsEvent('wms.inventory.reservation_shortfall', {\n id: orderId,\n orderId,\n orderNumber,\n shortfalls,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n }\n}\n\nexport async function releaseInventoryForCancelledOrder(\n payload: SalesOrderLifecyclePayload,\n ctx: EventContext,\n): Promise<void> {\n if (!payload.orderId || !payload.tenantId || !payload.organizationId) return\n if (!(await isInventoryAutomationEnabled(ctx, payload.tenantId))) return\n\n const scope: Scope = {\n tenantId: payload.tenantId,\n organizationId: payload.organizationId,\n }\n const em = ctx.resolve<EntityManager>('em').fork()\n const commandBus = ctx.resolve<CommandBus>('commandBus')\n const commandCtx = buildCommandContext(ctx, scope)\n const activeReservations = await loadActiveReservations(em, payload.orderId, scope)\n\n for (const reservation of activeReservations) {\n try {\n await commandBus.execute('wms.inventory.release', {\n input: {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n reservationId: reservation.id,\n reason: 'sales.order.cancelled',\n metadata: {\n automation: 'sales.order.cancelled',\n orderId: payload.orderId,\n },\n },\n ctx: commandCtx,\n })\n } catch (error) {\n if (!isBalanceIntegrityViolationError(error)) throw error\n void emitWmsEvent('wms.inventory.balance_drift', {\n id: reservation.id,\n balanceId: reservation.id,\n reservationId: reservation.id,\n field: 'quantityReserved',\n attemptedValue: null,\n clampedValue: null,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n }).catch(() => undefined)\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,qBAAqB;AAC9B,SAAS,0BAAiD;AAG1D,SAAS,SAAS;AAClB,SAAS,kBAAkB,4BAA4B;AACvD,SAAS,oBAAoB;AAC7B,SAAS,uCAAuC;AAChD;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,0CAA0C;AAwBnD,SAAS,yBAAyB,OAAyB;AACzD,SAAO,iBAAiB,iBAAiB,MAAM,WAAW,OAAO,MAAM,MAAM,UAAU;AACzF;AAEA,SAAS,iCAAiC,OAAyB;AACjE,SAAO,iBAAiB,iBAAiB,MAAM,WAAW,OAAO,MAAM,MAAM,UAAU;AACzF;AAiBA,SAAS,SAAS,OAAwB;AACxC,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO;AAChE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,GAAG;AACxD,UAAM,SAAS,OAAO,KAAK;AAC3B,QAAI,OAAO,SAAS,MAAM,EAAG,QAAO;AAAA,EACtC;AACA,SAAO;AACT;AAEA,SAAS,eAAe,SAA0C;AAChE,QAAM,WAAW,QAAQ;AACzB,MAAI,OAAO,aAAa,SAAU,QAAO;AACzC,SAAO,OAAO,UAAU,OAAO,WAAW,SAAS,KAAK;AAC1D;AAEA,SAAS,oBAAoB,KAAmB,OAAqC;AACnF,SAAO;AAAA,IACL,WAAW;AAAA,MACT,SAAS,IAAI;AAAA,IACf;AAAA,IACA,MAAM;AAAA,IACN,mBAAmB;AAAA,IACnB,wBAAwB,MAAM;AAAA,IAC9B,iBAAiB,CAAC,MAAM,cAAc;AAAA,EACxC;AACF;AAEA,eAAe,6BAA6B,KAAmB,UAAoC;AACjG,MAAI;AACF,UAAM,wBAAwB,IAAI,QAA+B,uBAAuB;AACxF,UAAM,KAAK,IAAI,QAAuB,IAAI;AAC1C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,wBACb,KACA,SACA,OAC+B;AAM/B,QAAM,cAAc,IAAI,QAAqB,aAAa;AAC1D,QAAM,SAAS,MAAM,YAAY,MAAqB,EAAE,MAAM,aAAa;AAAA,IACzE,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,IACtB,SAAS,EAAE,IAAI,EAAE,KAAK,QAAQ,EAAE;AAAA,IAChC,QAAQ,CAAC,MAAM,gBAAgB,aAAa,iBAAiB;AAAA,IAC7D,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE;AAAA,EAC/B,CAAC;AACD,SAAO,OAAO,MAAM,CAAC,KAAK;AAC5B;AAEA,eAAe,6BACb,KACA,SACA,OAC8B;AAC9B,QAAM,cAAc,IAAI,QAAqB,aAAa;AAC1D,QAAM,SAAS,MAAM,YAAY,MAAyB,EAAE,MAAM,kBAAkB;AAAA,IAClF,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,IACtB,SAAS,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE;AAAA,IACtC,QAAQ,CAAC,MAAM,QAAQ,sBAAsB,YAAY,aAAa;AAAA,IACtE,MAAM,CAAC,EAAE,OAAO,eAAe,KAAK,MAAe,CAAC;AAAA,IACpD,MAAM,EAAE,MAAM,GAAG,UAAU,IAAK;AAAA,EAClC,CAAC;AACD,SAAO,OAAO;AAChB;AAEA,eAAe,uBACb,IACA,SACA,OACiC;AACjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,WAAW;AAAA,IACb;AAAA,IACA,EAAE,SAAS,EAAE,WAAW,MAAM,EAAE;AAAA,IAChC;AAAA,EACF;AACF;AAEA,eAAe,aACb,IACA,YACA,OAC6B;AAC7B,MAAI,WAAW,WAAW,EAAG,QAAO,CAAC;AACrC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,kBAAkB,EAAE,KAAK,WAAW;AAAA,MACpC,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,WAAW;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,+BAA+B,OAAiD;AACvF,QAAM,aAAa,oBAAI,IAAoB;AAC3C,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,aAAa,CAAC,KAAK,mBAAoB;AACzD,UAAM,WAAW,SAAS,KAAK,QAAQ;AACvC,QAAI,YAAY,EAAG;AACnB,eAAW;AAAA,MACT,KAAK;AAAA,OACJ,WAAW,IAAI,KAAK,kBAAkB,KAAK,KAAK;AAAA,IACnD;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,+BAA+B,cAA2D;AACjG,QAAM,aAAa,oBAAI,IAAoB;AAC3C,aAAW,eAAe,cAAc;AACtC,eAAW;AAAA,MACT,YAAY;AAAA,OACX,WAAW,IAAI,YAAY,gBAAgB,KAAK,KAAK,SAAS,YAAY,QAAQ;AAAA,IACrF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,2BACP,UACsC;AACtC,QAAM,YAAY,oBAAI,IAAiC;AACvD,aAAW,WAAW,UAAU;AAC9B,UAAM,cAAc,eAAe,OAAO;AAC1C,QAAI,CAAC,YAAa;AAClB,UAAM,YACJ,SAAS,QAAQ,cAAc,IAC/B,SAAS,QAAQ,gBAAgB,IACjC,SAAS,QAAQ,iBAAiB;AACpC,QAAI,aAAa,EAAG;AAEpB,UAAM,eAAe,UAAU,IAAI,QAAQ,gBAAgB,KAAK,oBAAI,IAAoB;AACxF,iBAAa,IAAI,cAAc,aAAa,IAAI,WAAW,KAAK,KAAK,SAAS;AAC9E,cAAU,IAAI,QAAQ,kBAAkB,YAAY;AAAA,EACtD;AAEA,QAAM,SAAS,oBAAI,IAAqC;AACxD,aAAW,CAAC,WAAW,YAAY,KAAK,UAAU,QAAQ,GAAG;AAC3D,WAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,aAAa,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,aAAa,SAAS,OAAO,EAAE,aAAa,UAAU,EAAE;AAAA,IACnG;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,kCACpB,SACA,KACe;AACf,MAAI,CAAC,QAAQ,WAAW,CAAC,QAAQ,YAAY,CAAC,QAAQ,eAAgB;AACtE,MAAI,CAAE,MAAM,6BAA6B,KAAK,QAAQ,QAAQ,EAAI;AAElE,QAAM,QAAe;AAAA,IACnB,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ;AAAA,EAC1B;AACA,QAAM,KAAK,IAAI,QAAuB,IAAI,EAAE,KAAK;AACjD,QAAM,aAAa,IAAI,QAAoB,YAAY;AACvD,QAAM,aAAa,oBAAoB,KAAK,KAAK;AACjD,QAAM,QAAQ,MAAM,wBAAwB,KAAK,QAAQ,SAAS,KAAK;AACvE,MAAI,CAAC,SAAS,OAAO,MAAM,OAAO,SAAU;AAE5C,QAAM,UAAU,MAAM;AACtB,QAAM,cAAc,OAAO,MAAM,iBAAiB,WAAW,MAAM,eAAe;AAElF,QAAM,CAAC,OAAO,kBAAkB,IAAI,MAAM,QAAQ,IAAI;AAAA,IACpD,6BAA6B,KAAK,SAAS,KAAK;AAAA,IAChD,uBAAuB,IAAI,SAAS,KAAK;AAAA,EAC3C,CAAC;AACD,QAAM,oBAAoB,+BAA+B,KAAK;AAC9D,MAAI,kBAAkB,SAAS,EAAG;AAElC,QAAM,oBAAoB,+BAA+B,kBAAkB;AAC3E,QAAM,WAAW,MAAM,aAAa,IAAI,MAAM,KAAK,kBAAkB,KAAK,CAAC,GAAG,KAAK;AACnF,QAAM,wBAAwB,2BAA2B,QAAQ;AACjE,QAAM,CAAC,oBAAoB,mBAAmB,IAAI,MAAM,QAAQ,IAAI;AAAA,IAClE,0BAA0B,IAAI,KAAK;AAAA,IACnC,gCAAgC,IAAI,SAAS,KAAK;AAAA,EACpD,CAAC;AACD,QAAM,uBAAuB,uBAAuB;AACpD,QAAM,aAAyC,CAAC;AAEhD,aAAW,CAAC,WAAW,gBAAgB,KAAK,kBAAkB,QAAQ,GAAG;AACvE,QAAI,oBAAoB,oBAAoB,kBAAkB,IAAI,SAAS,KAAK;AAChF,QAAI,qBAAqB,EAAG;AAE5B,QAAI,iBAAiB,sBAAsB,IAAI,SAAS,KAAK,CAAC;AAC9D,QAAI,qBAAqB;AACvB,uBAAiB,eAAe;AAAA,QAC9B,CAAC,WAAW,OAAO,gBAAgB;AAAA,MACrC;AAAA,IACF;AAEA,UAAM,wBAAwB;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AACA,QAAI,qBAAqB;AACzB,QAAI;AACF,iBAAW,UAAU,uBAAuB;AAC1C,YAAI,qBAAqB,EAAG;AAC5B,cAAM,kBAAkB,KAAK,IAAI,mBAAmB,OAAO,SAAS;AACpE,YAAI,mBAAmB,EAAG;AAE1B,cAAM,WAAW,QAAQ,yBAAyB;AAAA,UAChD,OAAO;AAAA,YACL,UAAU,MAAM;AAAA,YAChB,gBAAgB,MAAM;AAAA,YACtB,aAAa,OAAO;AAAA,YACpB,kBAAkB;AAAA,YAClB,UAAU;AAAA,YACV,YAAY;AAAA,YACZ,UAAU;AAAA,YACV,UAAU;AAAA,cACR,YAAY;AAAA,cACZ;AAAA,cACA;AAAA,cACA,kBAAkB;AAAA,YACpB;AAAA,UACF;AAAA,UACA,KAAK;AAAA,QACP,CAAC;AAED,6BAAqB;AACrB,8BAAsB;AACtB,eAAO,aAAa;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,UAAI,CAAC,yBAAyB,KAAK,EAAG,OAAM;AAAA,IAC9C;AAEA,QAAI,oBAAoB,MAAU;AAChC,iBAAW,KAAK;AAAA,QACd,kBAAkB;AAAA,QAClB;AAAA,QACA,kBAAkB,sBAAsB,kBAAkB,IAAI,SAAS,KAAK;AAAA,QAC5E,mBAAmB;AAAA,MACrB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,aAAa,uCAAuC;AAAA,MACxD,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,IACxB,CAAC;AAAA,EACH;AACF;AAEA,eAAsB,kCACpB,SACA,KACe;AACf,MAAI,CAAC,QAAQ,WAAW,CAAC,QAAQ,YAAY,CAAC,QAAQ,eAAgB;AACtE,MAAI,CAAE,MAAM,6BAA6B,KAAK,QAAQ,QAAQ,EAAI;AAElE,QAAM,QAAe;AAAA,IACnB,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ;AAAA,EAC1B;AACA,QAAM,KAAK,IAAI,QAAuB,IAAI,EAAE,KAAK;AACjD,QAAM,aAAa,IAAI,QAAoB,YAAY;AACvD,QAAM,aAAa,oBAAoB,KAAK,KAAK;AACjD,QAAM,qBAAqB,MAAM,uBAAuB,IAAI,QAAQ,SAAS,KAAK;AAElF,aAAW,eAAe,oBAAoB;AAC5C,QAAI;AACF,YAAM,WAAW,QAAQ,yBAAyB;AAAA,QAChD,OAAO;AAAA,UACL,UAAU,MAAM;AAAA,UAChB,gBAAgB,MAAM;AAAA,UACtB,eAAe,YAAY;AAAA,UAC3B,QAAQ;AAAA,UACR,UAAU;AAAA,YACR,YAAY;AAAA,YACZ,SAAS,QAAQ;AAAA,UACnB;AAAA,QACF;AAAA,QACA,KAAK;AAAA,MACP,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UAAI,CAAC,iCAAiC,KAAK,EAAG,OAAM;AACpD,WAAK,aAAa,+BAA+B;AAAA,QAC/C,IAAI,YAAY;AAAA,QAChB,WAAW,YAAY;AAAA,QACvB,eAAe,YAAY;AAAA,QAC3B,OAAO;AAAA,QACP,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd,UAAU,MAAM;AAAA,QAChB,gBAAgB,MAAM;AAAA,MACxB,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,IAC1B;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
2
|
+
import { SalesOrderWarehouseAssignment } from "../data/entities.js";
|
|
3
|
+
function resolveWarehouseId(assignment) {
|
|
4
|
+
const warehouseRel = assignment.warehouse;
|
|
5
|
+
return typeof warehouseRel?.id === "string" ? warehouseRel.id : null;
|
|
6
|
+
}
|
|
7
|
+
async function loadExplicitWarehouseIdForOrder(em, salesOrderId, scope) {
|
|
8
|
+
const assignment = await findOneWithDecryption(
|
|
9
|
+
em,
|
|
10
|
+
SalesOrderWarehouseAssignment,
|
|
11
|
+
{
|
|
12
|
+
salesOrderId,
|
|
13
|
+
organizationId: scope.organizationId,
|
|
14
|
+
tenantId: scope.tenantId,
|
|
15
|
+
deletedAt: null
|
|
16
|
+
},
|
|
17
|
+
{ populate: ["warehouse"] },
|
|
18
|
+
scope
|
|
19
|
+
);
|
|
20
|
+
if (!assignment) return null;
|
|
21
|
+
return resolveWarehouseId(assignment);
|
|
22
|
+
}
|
|
23
|
+
async function loadSalesOrderWarehouseAssignmentView(em, salesOrderId, scope) {
|
|
24
|
+
const assignment = await findOneWithDecryption(
|
|
25
|
+
em,
|
|
26
|
+
SalesOrderWarehouseAssignment,
|
|
27
|
+
{
|
|
28
|
+
salesOrderId,
|
|
29
|
+
organizationId: scope.organizationId,
|
|
30
|
+
tenantId: scope.tenantId,
|
|
31
|
+
deletedAt: null
|
|
32
|
+
},
|
|
33
|
+
{ populate: ["warehouse"] },
|
|
34
|
+
scope
|
|
35
|
+
);
|
|
36
|
+
if (!assignment) return null;
|
|
37
|
+
const warehouseId = resolveWarehouseId(assignment);
|
|
38
|
+
if (!warehouseId) return null;
|
|
39
|
+
const warehouse = assignment.warehouse;
|
|
40
|
+
return {
|
|
41
|
+
id: assignment.id,
|
|
42
|
+
salesOrderId: assignment.salesOrderId,
|
|
43
|
+
warehouseId,
|
|
44
|
+
warehouseName: warehouse?.name ?? null,
|
|
45
|
+
warehouseCode: warehouse?.code ?? null,
|
|
46
|
+
notes: assignment.notes ?? null,
|
|
47
|
+
assignedBy: assignment.assignedBy ?? null
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
loadExplicitWarehouseIdForOrder,
|
|
52
|
+
loadSalesOrderWarehouseAssignmentView
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=salesOrderWarehouseAssignment.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/wms/lib/salesOrderWarehouseAssignment.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { SalesOrderWarehouseAssignment, Warehouse } from '../data/entities'\n\ntype Scope = {\n tenantId: string\n organizationId: string\n}\n\nexport type SalesOrderWarehouseAssignmentView = {\n id: string\n salesOrderId: string\n warehouseId: string\n warehouseName: string | null\n warehouseCode: string | null\n notes: string | null\n assignedBy: string | null\n}\n\nfunction resolveWarehouseId(assignment: SalesOrderWarehouseAssignment): string | null {\n const warehouseRel = assignment.warehouse as { id?: string } | undefined\n return typeof warehouseRel?.id === 'string' ? warehouseRel.id : null\n}\n\nexport async function loadExplicitWarehouseIdForOrder(\n em: EntityManager,\n salesOrderId: string,\n scope: Scope,\n): Promise<string | null> {\n const assignment = await findOneWithDecryption(\n em,\n SalesOrderWarehouseAssignment,\n {\n salesOrderId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n { populate: ['warehouse'] },\n scope,\n )\n if (!assignment) return null\n return resolveWarehouseId(assignment)\n}\n\nexport async function loadSalesOrderWarehouseAssignmentView(\n em: EntityManager,\n salesOrderId: string,\n scope: Scope,\n): Promise<SalesOrderWarehouseAssignmentView | null> {\n const assignment = await findOneWithDecryption(\n em,\n SalesOrderWarehouseAssignment,\n {\n salesOrderId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n { populate: ['warehouse'] },\n scope,\n )\n if (!assignment) return null\n\n const warehouseId = resolveWarehouseId(assignment)\n if (!warehouseId) return null\n\n const warehouse = assignment.warehouse as Warehouse | undefined\n return {\n id: assignment.id,\n salesOrderId: assignment.salesOrderId,\n warehouseId,\n warehouseName: warehouse?.name ?? null,\n warehouseCode: warehouse?.code ?? null,\n notes: assignment.notes ?? null,\n assignedBy: assignment.assignedBy ?? null,\n }\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,6BAA6B;AACtC,SAAS,qCAAgD;AAiBzD,SAAS,mBAAmB,YAA0D;AACpF,QAAM,eAAe,WAAW;AAChC,SAAO,OAAO,cAAc,OAAO,WAAW,aAAa,KAAK;AAClE;AAEA,eAAsB,gCACpB,IACA,cACA,OACwB;AACxB,QAAM,aAAa,MAAM;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,MACE;AAAA,MACA,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,WAAW;AAAA,IACb;AAAA,IACA,EAAE,UAAU,CAAC,WAAW,EAAE;AAAA,IAC1B;AAAA,EACF;AACA,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,mBAAmB,UAAU;AACtC;AAEA,eAAsB,sCACpB,IACA,cACA,OACmD;AACnD,QAAM,aAAa,MAAM;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,MACE;AAAA,MACA,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,WAAW;AAAA,IACb;AAAA,IACA,EAAE,UAAU,CAAC,WAAW,EAAE;AAAA,IAC1B;AAAA,EACF;AACA,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,cAAc,mBAAmB,UAAU;AACjD,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,YAAY,WAAW;AAC7B,SAAO;AAAA,IACL,IAAI,WAAW;AAAA,IACf,cAAc,WAAW;AAAA,IACzB;AAAA,IACA,eAAe,WAAW,QAAQ;AAAA,IAClC,eAAe,WAAW,QAAQ;AAAA,IAClC,OAAO,WAAW,SAAS;AAAA,IAC3B,YAAY,WAAW,cAAc;AAAA,EACvC;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
2
|
+
import { FeatureToggle } from "@open-mercato/core/modules/feature_toggles/data/entities";
|
|
3
|
+
const WMS_INTEGRATION_TOGGLES = [
|
|
4
|
+
{
|
|
5
|
+
identifier: "wms_integration_sales_order_inventory",
|
|
6
|
+
name: "Sales Order Inventory Reservation",
|
|
7
|
+
description: "Allows WMS to reserve and release inventory from sales order lifecycle events.",
|
|
8
|
+
category: "wms",
|
|
9
|
+
type: "boolean",
|
|
10
|
+
defaultValue: true
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
identifier: "wms_integration_shipping_shipments",
|
|
14
|
+
name: "Shipping Shipment Coordination",
|
|
15
|
+
description: "Allows WMS to react to shipping shipment lifecycle events when shipment orchestration is enabled.",
|
|
16
|
+
category: "wms",
|
|
17
|
+
type: "boolean",
|
|
18
|
+
defaultValue: true
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
identifier: "wms_integration_procurement_goods_receipt",
|
|
22
|
+
name: "Procurement Goods Receipt Bridge",
|
|
23
|
+
description: "Reserved toggle for future procurement-driven receiving integration.",
|
|
24
|
+
category: "wms",
|
|
25
|
+
type: "boolean",
|
|
26
|
+
defaultValue: false
|
|
27
|
+
}
|
|
28
|
+
];
|
|
29
|
+
function findWmsIntegrationToggleDefinition(identifier) {
|
|
30
|
+
return WMS_INTEGRATION_TOGGLES.find((toggle) => toggle.identifier === identifier) ?? null;
|
|
31
|
+
}
|
|
32
|
+
async function seedWmsIntegrationToggles(em) {
|
|
33
|
+
for (const toggle of WMS_INTEGRATION_TOGGLES) {
|
|
34
|
+
const existing = await findOneWithDecryption(em, FeatureToggle, {
|
|
35
|
+
identifier: toggle.identifier,
|
|
36
|
+
deletedAt: null
|
|
37
|
+
});
|
|
38
|
+
if (existing) continue;
|
|
39
|
+
em.persist(
|
|
40
|
+
em.create(FeatureToggle, {
|
|
41
|
+
identifier: toggle.identifier,
|
|
42
|
+
name: toggle.name,
|
|
43
|
+
description: toggle.description,
|
|
44
|
+
category: toggle.category,
|
|
45
|
+
type: toggle.type,
|
|
46
|
+
defaultValue: toggle.defaultValue
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
await em.flush();
|
|
51
|
+
}
|
|
52
|
+
async function resolveWmsIntegrationToggleEnabled(featureTogglesService, em, identifier, tenantId) {
|
|
53
|
+
const definition = findWmsIntegrationToggleDefinition(identifier);
|
|
54
|
+
const fallback = definition?.defaultValue ?? true;
|
|
55
|
+
const result = await featureTogglesService.getBoolConfig(identifier, tenantId);
|
|
56
|
+
if (result.ok) return result.value;
|
|
57
|
+
if (result.error?.code !== "MISSING_TOGGLE" || !definition) {
|
|
58
|
+
return fallback;
|
|
59
|
+
}
|
|
60
|
+
await seedWmsIntegrationToggles(em);
|
|
61
|
+
await featureTogglesService.invalidateIsEnabledCacheByKey(identifier, tenantId);
|
|
62
|
+
const retried = await featureTogglesService.getBoolConfig(identifier, tenantId);
|
|
63
|
+
return retried.ok ? retried.value : fallback;
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
WMS_INTEGRATION_TOGGLES,
|
|
67
|
+
findWmsIntegrationToggleDefinition,
|
|
68
|
+
resolveWmsIntegrationToggleEnabled,
|
|
69
|
+
seedWmsIntegrationToggles
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=wmsIntegrationToggles.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/wms/lib/wmsIntegrationToggles.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { FeatureToggle } from '@open-mercato/core/modules/feature_toggles/data/entities'\nimport type { FeatureTogglesService } from '@open-mercato/core/modules/feature_toggles/lib/feature-flag-check'\n\nexport const WMS_INTEGRATION_TOGGLES = [\n {\n identifier: 'wms_integration_sales_order_inventory',\n name: 'Sales Order Inventory Reservation',\n description: 'Allows WMS to reserve and release inventory from sales order lifecycle events.',\n category: 'wms',\n type: 'boolean' as const,\n defaultValue: true,\n },\n {\n identifier: 'wms_integration_shipping_shipments',\n name: 'Shipping Shipment Coordination',\n description: 'Allows WMS to react to shipping shipment lifecycle events when shipment orchestration is enabled.',\n category: 'wms',\n type: 'boolean' as const,\n defaultValue: true,\n },\n {\n identifier: 'wms_integration_procurement_goods_receipt',\n name: 'Procurement Goods Receipt Bridge',\n description: 'Reserved toggle for future procurement-driven receiving integration.',\n category: 'wms',\n type: 'boolean' as const,\n defaultValue: false,\n },\n] as const\n\nexport type WmsIntegrationToggleIdentifier = (typeof WMS_INTEGRATION_TOGGLES)[number]['identifier']\n\nexport function findWmsIntegrationToggleDefinition(identifier: string) {\n return WMS_INTEGRATION_TOGGLES.find((toggle) => toggle.identifier === identifier) ?? null\n}\n\nexport async function seedWmsIntegrationToggles(em: EntityManager): Promise<void> {\n for (const toggle of WMS_INTEGRATION_TOGGLES) {\n const existing = await findOneWithDecryption(em, FeatureToggle, {\n identifier: toggle.identifier,\n deletedAt: null,\n })\n if (existing) continue\n em.persist(\n em.create(FeatureToggle, {\n identifier: toggle.identifier,\n name: toggle.name,\n description: toggle.description,\n category: toggle.category,\n type: toggle.type,\n defaultValue: toggle.defaultValue,\n }),\n )\n }\n await em.flush()\n}\n\nexport async function resolveWmsIntegrationToggleEnabled(\n featureTogglesService: FeatureTogglesService,\n em: EntityManager,\n identifier: WmsIntegrationToggleIdentifier,\n tenantId: string,\n): Promise<boolean> {\n const definition = findWmsIntegrationToggleDefinition(identifier)\n const fallback = definition?.defaultValue ?? true\n\n const result = await featureTogglesService.getBoolConfig(identifier, tenantId)\n if (result.ok) return result.value\n\n if (result.error?.code !== 'MISSING_TOGGLE' || !definition) {\n return fallback\n }\n\n await seedWmsIntegrationToggles(em)\n await featureTogglesService.invalidateIsEnabledCacheByKey(identifier, tenantId)\n\n const retried = await featureTogglesService.getBoolConfig(identifier, tenantId)\n return retried.ok ? retried.value : fallback\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,6BAA6B;AACtC,SAAS,qBAAqB;AAGvB,MAAM,0BAA0B;AAAA,EACrC;AAAA,IACE,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AACF;AAIO,SAAS,mCAAmC,YAAoB;AACrE,SAAO,wBAAwB,KAAK,CAAC,WAAW,OAAO,eAAe,UAAU,KAAK;AACvF;AAEA,eAAsB,0BAA0B,IAAkC;AAChF,aAAW,UAAU,yBAAyB;AAC5C,UAAM,WAAW,MAAM,sBAAsB,IAAI,eAAe;AAAA,MAC9D,YAAY,OAAO;AAAA,MACnB,WAAW;AAAA,IACb,CAAC;AACD,QAAI,SAAU;AACd,OAAG;AAAA,MACD,GAAG,OAAO,eAAe;AAAA,QACvB,YAAY,OAAO;AAAA,QACnB,MAAM,OAAO;AAAA,QACb,aAAa,OAAO;AAAA,QACpB,UAAU,OAAO;AAAA,QACjB,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACA,QAAM,GAAG,MAAM;AACjB;AAEA,eAAsB,mCACpB,uBACA,IACA,YACA,UACkB;AAClB,QAAM,aAAa,mCAAmC,UAAU;AAChE,QAAM,WAAW,YAAY,gBAAgB;AAE7C,QAAM,SAAS,MAAM,sBAAsB,cAAc,YAAY,QAAQ;AAC7E,MAAI,OAAO,GAAI,QAAO,OAAO;AAE7B,MAAI,OAAO,OAAO,SAAS,oBAAoB,CAAC,YAAY;AAC1D,WAAO;AAAA,EACT;AAEA,QAAM,0BAA0B,EAAE;AAClC,QAAM,sBAAsB,8BAA8B,YAAY,QAAQ;AAE9E,QAAM,UAAU,MAAM,sBAAsB,cAAc,YAAY,QAAQ;AAC9E,SAAO,QAAQ,KAAK,QAAQ,QAAQ;AACtC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|