@endora-commerce/mod-inventory 0.100.0
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/LICENSE +21 -0
- package/README.md +61 -0
- package/dist/admin/api/warehouses-client.d.ts +22 -0
- package/dist/admin/api/warehouses-client.d.ts.map +1 -0
- package/dist/admin/api/warehouses-client.js +32 -0
- package/dist/admin/api/warehouses-client.js.map +1 -0
- package/dist/admin/index.d.ts +43 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +190 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/AvailabilityNotificationsPage.d.ts +15 -0
- package/dist/admin/pages/AvailabilityNotificationsPage.d.ts.map +1 -0
- package/dist/admin/pages/AvailabilityNotificationsPage.js +111 -0
- package/dist/admin/pages/AvailabilityNotificationsPage.js.map +1 -0
- package/dist/admin/pages/InventoryPage.d.ts +17 -0
- package/dist/admin/pages/InventoryPage.d.ts.map +1 -0
- package/dist/admin/pages/InventoryPage.js +135 -0
- package/dist/admin/pages/InventoryPage.js.map +1 -0
- package/dist/admin/pages/LowStockPage.d.ts +16 -0
- package/dist/admin/pages/LowStockPage.d.ts.map +1 -0
- package/dist/admin/pages/LowStockPage.js +61 -0
- package/dist/admin/pages/LowStockPage.js.map +1 -0
- package/dist/admin/pages/StockImportWizard.d.ts +17 -0
- package/dist/admin/pages/StockImportWizard.d.ts.map +1 -0
- package/dist/admin/pages/StockImportWizard.js +111 -0
- package/dist/admin/pages/StockImportWizard.js.map +1 -0
- package/dist/admin/pages/WarehouseEditor.d.ts +12 -0
- package/dist/admin/pages/WarehouseEditor.d.ts.map +1 -0
- package/dist/admin/pages/WarehouseEditor.js +194 -0
- package/dist/admin/pages/WarehouseEditor.js.map +1 -0
- package/dist/admin/pages/WarehousesList.d.ts +12 -0
- package/dist/admin/pages/WarehousesList.d.ts.map +1 -0
- package/dist/admin/pages/WarehousesList.js +69 -0
- package/dist/admin/pages/WarehousesList.js.map +1 -0
- package/dist/admin/zones/ChannelWarehouses.d.ts +49 -0
- package/dist/admin/zones/ChannelWarehouses.d.ts.map +1 -0
- package/dist/admin/zones/ChannelWarehouses.js +109 -0
- package/dist/admin/zones/ChannelWarehouses.js.map +1 -0
- package/dist/backend/demo/reset.d.ts +18 -0
- package/dist/backend/demo/reset.d.ts.map +1 -0
- package/dist/backend/demo/reset.js +20 -0
- package/dist/backend/demo/reset.js.map +1 -0
- package/dist/backend/demo/rows.d.ts +38 -0
- package/dist/backend/demo/rows.d.ts.map +1 -0
- package/dist/backend/demo/rows.js +38 -0
- package/dist/backend/demo/rows.js.map +1 -0
- package/dist/backend/demo/seed.d.ts +26 -0
- package/dist/backend/demo/seed.d.ts.map +1 -0
- package/dist/backend/demo/seed.js +65 -0
- package/dist/backend/demo/seed.js.map +1 -0
- package/dist/backend/email-templates/transactional-defaults.d.ts +11 -0
- package/dist/backend/email-templates/transactional-defaults.d.ts.map +1 -0
- package/dist/backend/email-templates/transactional-defaults.js +49 -0
- package/dist/backend/email-templates/transactional-defaults.js.map +1 -0
- package/dist/backend/entities/availability-notification.entity.d.ts +49 -0
- package/dist/backend/entities/availability-notification.entity.d.ts.map +1 -0
- package/dist/backend/entities/availability-notification.entity.js +93 -0
- package/dist/backend/entities/availability-notification.entity.js.map +1 -0
- package/dist/backend/entities/inventory-threshold.entity.d.ts +24 -0
- package/dist/backend/entities/inventory-threshold.entity.d.ts.map +1 -0
- package/dist/backend/entities/inventory-threshold.entity.js +61 -0
- package/dist/backend/entities/inventory-threshold.entity.js.map +1 -0
- package/dist/backend/entities/product-warehouse-low-stock-threshold.entity.d.ts +15 -0
- package/dist/backend/entities/product-warehouse-low-stock-threshold.entity.d.ts.map +1 -0
- package/dist/backend/entities/product-warehouse-low-stock-threshold.entity.js +51 -0
- package/dist/backend/entities/product-warehouse-low-stock-threshold.entity.js.map +1 -0
- package/dist/backend/entities/stock-allocation.entity.d.ts +22 -0
- package/dist/backend/entities/stock-allocation.entity.d.ts.map +1 -0
- package/dist/backend/entities/stock-allocation.entity.js +69 -0
- package/dist/backend/entities/stock-allocation.entity.js.map +1 -0
- package/dist/backend/entities/stock-level.entity.d.ts +24 -0
- package/dist/backend/entities/stock-level.entity.d.ts.map +1 -0
- package/dist/backend/entities/stock-level.entity.js +74 -0
- package/dist/backend/entities/stock-level.entity.js.map +1 -0
- package/dist/backend/entities/warehouse-channel-assignment.entity.d.ts +17 -0
- package/dist/backend/entities/warehouse-channel-assignment.entity.d.ts.map +1 -0
- package/dist/backend/entities/warehouse-channel-assignment.entity.js +60 -0
- package/dist/backend/entities/warehouse-channel-assignment.entity.js.map +1 -0
- package/dist/backend/entities/warehouse.entity.d.ts +37 -0
- package/dist/backend/entities/warehouse.entity.d.ts.map +1 -0
- package/dist/backend/entities/warehouse.entity.js +90 -0
- package/dist/backend/entities/warehouse.entity.js.map +1 -0
- package/dist/backend/index.d.ts +139 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +351 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/plugin.d.ts +113 -0
- package/dist/backend/plugin.d.ts.map +1 -0
- package/dist/backend/plugin.js +75 -0
- package/dist/backend/plugin.js.map +1 -0
- package/dist/backend/prompt-tools.d.ts +23 -0
- package/dist/backend/prompt-tools.d.ts.map +1 -0
- package/dist/backend/prompt-tools.js +77 -0
- package/dist/backend/prompt-tools.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +62 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +383 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.d.ts +40 -0
- package/dist/backend/routes.d.ts.map +1 -0
- package/dist/backend/routes.js +263 -0
- package/dist/backend/routes.js.map +1 -0
- package/dist/backend/services/audit-references.d.ts +15 -0
- package/dist/backend/services/audit-references.d.ts.map +1 -0
- package/dist/backend/services/audit-references.js +27 -0
- package/dist/backend/services/audit-references.js.map +1 -0
- package/dist/backend/services/availability-notification-service.d.ts +155 -0
- package/dist/backend/services/availability-notification-service.d.ts.map +1 -0
- package/dist/backend/services/availability-notification-service.js +363 -0
- package/dist/backend/services/availability-notification-service.js.map +1 -0
- package/dist/backend/services/availability-worker.d.ts +57 -0
- package/dist/backend/services/availability-worker.d.ts.map +1 -0
- package/dist/backend/services/availability-worker.js +135 -0
- package/dist/backend/services/availability-worker.js.map +1 -0
- package/dist/backend/services/csv-stock-importer.d.ts +52 -0
- package/dist/backend/services/csv-stock-importer.d.ts.map +1 -0
- package/dist/backend/services/csv-stock-importer.js +154 -0
- package/dist/backend/services/csv-stock-importer.js.map +1 -0
- package/dist/backend/services/display-band-resolver.d.ts +19 -0
- package/dist/backend/services/display-band-resolver.d.ts.map +1 -0
- package/dist/backend/services/display-band-resolver.js +21 -0
- package/dist/backend/services/display-band-resolver.js.map +1 -0
- package/dist/backend/services/effective-fulfilment-strategy.d.ts +16 -0
- package/dist/backend/services/effective-fulfilment-strategy.d.ts.map +1 -0
- package/dist/backend/services/effective-fulfilment-strategy.js +16 -0
- package/dist/backend/services/effective-fulfilment-strategy.js.map +1 -0
- package/dist/backend/services/fulfilment-strategy-resolver.d.ts +13 -0
- package/dist/backend/services/fulfilment-strategy-resolver.d.ts.map +1 -0
- package/dist/backend/services/fulfilment-strategy-resolver.js +13 -0
- package/dist/backend/services/fulfilment-strategy-resolver.js.map +1 -0
- package/dist/backend/services/inventory-read-port.d.ts +65 -0
- package/dist/backend/services/inventory-read-port.d.ts.map +1 -0
- package/dist/backend/services/inventory-read-port.js +168 -0
- package/dist/backend/services/inventory-read-port.js.map +1 -0
- package/dist/backend/services/inventory-reservation-apply-port.d.ts +62 -0
- package/dist/backend/services/inventory-reservation-apply-port.d.ts.map +1 -0
- package/dist/backend/services/inventory-reservation-apply-port.js +134 -0
- package/dist/backend/services/inventory-reservation-apply-port.js.map +1 -0
- package/dist/backend/services/low-stock-alert-service.d.ts +87 -0
- package/dist/backend/services/low-stock-alert-service.d.ts.map +1 -0
- package/dist/backend/services/low-stock-alert-service.js +164 -0
- package/dist/backend/services/low-stock-alert-service.js.map +1 -0
- package/dist/backend/services/product-threshold-write.service.d.ts +38 -0
- package/dist/backend/services/product-threshold-write.service.d.ts.map +1 -0
- package/dist/backend/services/product-threshold-write.service.js +80 -0
- package/dist/backend/services/product-threshold-write.service.js.map +1 -0
- package/dist/backend/services/stock-import.service.d.ts +43 -0
- package/dist/backend/services/stock-import.service.d.ts.map +1 -0
- package/dist/backend/services/stock-import.service.js +124 -0
- package/dist/backend/services/stock-import.service.js.map +1 -0
- package/dist/backend/services/stock-level-service.d.ts +146 -0
- package/dist/backend/services/stock-level-service.d.ts.map +1 -0
- package/dist/backend/services/stock-level-service.js +489 -0
- package/dist/backend/services/stock-level-service.js.map +1 -0
- package/dist/backend/services/threshold-admin-service.d.ts +73 -0
- package/dist/backend/services/threshold-admin-service.d.ts.map +1 -0
- package/dist/backend/services/threshold-admin-service.js +167 -0
- package/dist/backend/services/threshold-admin-service.js.map +1 -0
- package/dist/backend/services/threshold-resolver.d.ts +23 -0
- package/dist/backend/services/threshold-resolver.d.ts.map +1 -0
- package/dist/backend/services/threshold-resolver.js +29 -0
- package/dist/backend/services/threshold-resolver.js.map +1 -0
- package/dist/backend/services/threshold-settings-mirror.d.ts +55 -0
- package/dist/backend/services/threshold-settings-mirror.d.ts.map +1 -0
- package/dist/backend/services/threshold-settings-mirror.js +84 -0
- package/dist/backend/services/threshold-settings-mirror.js.map +1 -0
- package/dist/backend/services/warehouse-channel-reconciler.d.ts +19 -0
- package/dist/backend/services/warehouse-channel-reconciler.d.ts.map +1 -0
- package/dist/backend/services/warehouse-channel-reconciler.js +65 -0
- package/dist/backend/services/warehouse-channel-reconciler.js.map +1 -0
- package/dist/backend/services/warehouse-channel-service.d.ts +57 -0
- package/dist/backend/services/warehouse-channel-service.d.ts.map +1 -0
- package/dist/backend/services/warehouse-channel-service.js +205 -0
- package/dist/backend/services/warehouse-channel-service.js.map +1 -0
- package/dist/backend/services/warehouse-country-reference.d.ts +14 -0
- package/dist/backend/services/warehouse-country-reference.d.ts.map +1 -0
- package/dist/backend/services/warehouse-country-reference.js +27 -0
- package/dist/backend/services/warehouse-country-reference.js.map +1 -0
- package/dist/backend/services/warehouse-service.d.ts +86 -0
- package/dist/backend/services/warehouse-service.d.ts.map +1 -0
- package/dist/backend/services/warehouse-service.js +267 -0
- package/dist/backend/services/warehouse-service.js.map +1 -0
- package/dist/manifest.d.ts +219 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +377 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260503T182812_inventory_workflow.d.ts +39 -0
- package/dist/migrations/20260503T182812_inventory_workflow.d.ts.map +1 -0
- package/dist/migrations/20260503T182812_inventory_workflow.js +205 -0
- package/dist/migrations/20260503T182812_inventory_workflow.js.map +1 -0
- package/dist/migrations/20260611T140347_inventory_warehouse_default_low_stock_threshold.d.ts +14 -0
- package/dist/migrations/20260611T140347_inventory_warehouse_default_low_stock_threshold.d.ts.map +1 -0
- package/dist/migrations/20260611T140347_inventory_warehouse_default_low_stock_threshold.js +18 -0
- package/dist/migrations/20260611T140347_inventory_warehouse_default_low_stock_threshold.js.map +1 -0
- package/dist/migrations/20260611T140348_inventory_per_warehouse_low_stock_thresholds.d.ts +28 -0
- package/dist/migrations/20260611T140348_inventory_per_warehouse_low_stock_thresholds.d.ts.map +1 -0
- package/dist/migrations/20260611T140348_inventory_per_warehouse_low_stock_thresholds.js +48 -0
- package/dist/migrations/20260611T140348_inventory_per_warehouse_low_stock_thresholds.js.map +1 -0
- package/dist/migrations/20260818T081243_inventory_stock_allocation_order_item_fk.d.ts +44 -0
- package/dist/migrations/20260818T081243_inventory_stock_allocation_order_item_fk.d.ts.map +1 -0
- package/dist/migrations/20260818T081243_inventory_stock_allocation_order_item_fk.js +81 -0
- package/dist/migrations/20260818T081243_inventory_stock_allocation_order_item_fk.js.map +1 -0
- package/dist/migrations/20260830T182139_inventory_organization_attribution.d.ts +109 -0
- package/dist/migrations/20260830T182139_inventory_organization_attribution.d.ts.map +1 -0
- package/dist/migrations/20260830T182139_inventory_organization_attribution.js +178 -0
- package/dist/migrations/20260830T182139_inventory_organization_attribution.js.map +1 -0
- package/dist/migrations/20260912T125716_inventory_organization_warehouses.d.ts +34 -0
- package/dist/migrations/20260912T125716_inventory_organization_warehouses.d.ts.map +1 -0
- package/dist/migrations/20260912T125716_inventory_organization_warehouses.js +50 -0
- package/dist/migrations/20260912T125716_inventory_organization_warehouses.js.map +1 -0
- package/dist/migrations/index.d.ts +32 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +39 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/ports/index.d.ts +183 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +2 -0
- package/dist/ports/index.js.map +1 -0
- package/docs/inventory.md +177 -0
- package/i18n/en.json +32 -0
- package/i18n/pl.json +32 -0
- package/package.json +105 -0
- package/tailwind.css +14 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { resolveAllocations, resolveEffectiveFulfilmentStrategy } from '@endora-commerce/contracts';
|
|
2
|
+
import { lazyPort } from '@endora-commerce/platform/kernel';
|
|
3
|
+
import { effectiveState } from '@endora-commerce/platform/kernel';
|
|
4
|
+
import { inventoryModule } from './plugin.js';
|
|
5
|
+
import { StockLevelService } from './services/stock-level-service.js';
|
|
6
|
+
import { InventoryStockReadService } from './services/inventory-read-port.js';
|
|
7
|
+
import { InventoryReservationApplyService } from './services/inventory-reservation-apply-port.js';
|
|
8
|
+
import { InventoryStockImportService } from './services/stock-import.service.js';
|
|
9
|
+
import { InventoryProductThresholdWriteService } from './services/product-threshold-write.service.js';
|
|
10
|
+
import { WarehouseChannelService } from './services/warehouse-channel-service.js';
|
|
11
|
+
import { WarehouseChannelReconciler } from './services/warehouse-channel-reconciler.js';
|
|
12
|
+
import { AVAILABILITY_BACK_IN_STOCK_DEFAULT, LOW_STOCK_ALERT_DEFAULT } from './email-templates/transactional-defaults.js';
|
|
13
|
+
import { inventoryPromptTools } from './prompt-tools.js';
|
|
14
|
+
import { registerWarehouseCountryReferences } from './services/warehouse-country-reference.js';
|
|
15
|
+
import { registerInventoryAuditReferences } from './services/audit-references.js';
|
|
16
|
+
import { AvailabilityNotification } from './entities/availability-notification.entity.js';
|
|
17
|
+
import { InventoryThreshold } from './entities/inventory-threshold.entity.js';
|
|
18
|
+
import { ProductWarehouseLowStockThreshold } from './entities/product-warehouse-low-stock-threshold.entity.js';
|
|
19
|
+
import { StockAllocation } from './entities/stock-allocation.entity.js';
|
|
20
|
+
import { StockLevel } from './entities/stock-level.entity.js';
|
|
21
|
+
import { WarehouseChannelAssignment } from './entities/warehouse-channel-assignment.entity.js';
|
|
22
|
+
import { Warehouse } from './entities/warehouse.entity.js';
|
|
23
|
+
export function registerModule(ctx) {
|
|
24
|
+
ctx.di.register({
|
|
25
|
+
inventory: ctx
|
|
26
|
+
.asFunction(({ emFactory, eventBus, auditLogService }) => inventoryModule({
|
|
27
|
+
emFactory,
|
|
28
|
+
eventBus,
|
|
29
|
+
auditLogService,
|
|
30
|
+
settingsService: lazyPort(ctx, 'settingsReadPort'),
|
|
31
|
+
channelResolver: lazyPort(ctx, 'salesChannelResolutionPort'),
|
|
32
|
+
dictionaryValidator: lazyPort(ctx, 'dictionaryValidator'),
|
|
33
|
+
// Feature 075, Phase C — the four reads and one write this module used
|
|
34
|
+
// to take by importing `catalog`'s, `customer_accounts`' and `email`'s
|
|
35
|
+
// files. Every one of them kept answering with its owner switched off.
|
|
36
|
+
catalogProducts: lazyPort(ctx, 'catalogProductReadPort'),
|
|
37
|
+
catalogCategories: lazyPort(ctx, 'catalogCategoryReadPort'),
|
|
38
|
+
catalogCategoryWrites: lazyPort(ctx, 'catalogCategoryWritePort'),
|
|
39
|
+
customerAccounts: lazyPort(ctx, 'customerAccountReadPort'),
|
|
40
|
+
// Issue #259 — the channel assortment gate on the notify-me seam. A
|
|
41
|
+
// kernel registration, not a module's, so there is no edge to declare
|
|
42
|
+
// in the manifest.
|
|
43
|
+
salesChannelMembership: lazyPort(ctx, 'salesChannelMembershipPort'),
|
|
44
|
+
mailer: lazyPort(ctx, 'emailMailer'),
|
|
45
|
+
requireAdmin: (permission) => async (req, reply) => ctx.cradle().requireAdmin(permission)(req, reply),
|
|
46
|
+
requireCustomer: (req, reply) => ctx.cradle().requireCustomer(req, reply),
|
|
47
|
+
resolveCustomerContext: (req) => ctx.cradle().customerContextResolver(req),
|
|
48
|
+
resolveSystemDefaultChannelId: () => ctx.cradle().settingsChannelResolver(),
|
|
49
|
+
resolveAdminAuditContext: (req) => ctx.cradle().inventoryAdminAuditContext(req),
|
|
50
|
+
templateEmail: {
|
|
51
|
+
trySend: (input) => ctx.cradle().templateEmailPort.trySend(input),
|
|
52
|
+
},
|
|
53
|
+
// Composed from the two halves, without a `catch` — the root closure
|
|
54
|
+
// this replaces had one, which would have read a disabled-module
|
|
55
|
+
// throw as "every warehouse is allowed" (T138).
|
|
56
|
+
resolveOrganizationWarehouseAllowList: async (req) => {
|
|
57
|
+
const cradle = ctx.cradle();
|
|
58
|
+
const organizationId = cradle.customerOrganizationIdResolver(req);
|
|
59
|
+
if (organizationId === null)
|
|
60
|
+
return null;
|
|
61
|
+
return cradle.organizationRestrictionPort.allowedIdsFor(organizationId, 'warehouseIds');
|
|
62
|
+
},
|
|
63
|
+
}))
|
|
64
|
+
.singleton(),
|
|
65
|
+
});
|
|
66
|
+
/**
|
|
67
|
+
* Feature 075, Phase P — the stock read model.
|
|
68
|
+
*
|
|
69
|
+
* `orders` assembles candidate warehouses for a line from three of this
|
|
70
|
+
* module's tables today, inside its own transaction, reaching them through a
|
|
71
|
+
* **dynamic** import. `candidatesFor` is that assembly, on this side of the
|
|
72
|
+
* boundary; the three list methods beside it are the transcriptions
|
|
73
|
+
* `import_export` and the dev seed need.
|
|
74
|
+
*/
|
|
75
|
+
ctx.di.providePort('inventoryStockReadPort', ctx
|
|
76
|
+
.asFunction(({ emFactory }) => new InventoryStockReadService(emFactory))
|
|
77
|
+
.singleton());
|
|
78
|
+
/**
|
|
79
|
+
* D-94.4 — the warehouse-picking policy, published.
|
|
80
|
+
*
|
|
81
|
+
* `orders` reached both functions through `await import(
|
|
82
|
+
* '../../inventory/services/…')` inside the placement method body. They are
|
|
83
|
+
* pure over their arguments, so nothing here reads a table and nothing takes
|
|
84
|
+
* an `EntityManager`; what the port buys is that the policy is asked of its
|
|
85
|
+
* owner rather than re-implemented by whoever edits the import next.
|
|
86
|
+
*
|
|
87
|
+
* A separate port from `inventoryStockReadPort` on purpose: a read port that
|
|
88
|
+
* also decides policy makes its own name a lie.
|
|
89
|
+
*
|
|
90
|
+
* The gate `providePort` wraps this in is real but never reached from
|
|
91
|
+
* placement: `orders` declares this name `degrades-without` and asks
|
|
92
|
+
* `effectiveState.isPresent('inventory')` before the reservation block, so
|
|
93
|
+
* with this module off there is no plan to compute rather than a 503 in the
|
|
94
|
+
* middle of one.
|
|
95
|
+
*/
|
|
96
|
+
ctx.di.providePort('inventoryFulfilmentPlanningPort', ctx
|
|
97
|
+
.asFunction(() => ({
|
|
98
|
+
resolveEffectiveStrategy: resolveEffectiveFulfilmentStrategy,
|
|
99
|
+
planAllocations: resolveAllocations,
|
|
100
|
+
}))
|
|
101
|
+
.singleton());
|
|
102
|
+
/**
|
|
103
|
+
* Feature 080, T048 / D-169 — the stock reservation, published.
|
|
104
|
+
*
|
|
105
|
+
* `orders` reached this module's `StockLevel` and `StockAllocation` classes
|
|
106
|
+
* for it, statically for the reservation and through an `await import()` for
|
|
107
|
+
* the release, and wrote both tables itself: the `FOR UPDATE` read, the
|
|
108
|
+
* `reserved` increment, the allocation insert and the release loop. D-168
|
|
109
|
+
* leaves a packaged `inventory` no entity class for a stranger to name, so
|
|
110
|
+
* the reach had to go before this module moves; the transaction it runs in
|
|
111
|
+
* did not change, and `stock_allocations_order_item_fk` is untouched.
|
|
112
|
+
*
|
|
113
|
+
* A third `inventory` name rather than a widening of either port above, and
|
|
114
|
+
* the three differ in exactly which transaction they run in:
|
|
115
|
+
* `inventoryStockReadPort` reads on this module's own `EntityManager`,
|
|
116
|
+
* `inventoryFulfilmentPlanningPort` opens none at all — it is pure over its
|
|
117
|
+
* arguments — and this one takes placement's, because the
|
|
118
|
+
* `PESSIMISTIC_WRITE` has to be held until the order commits and the
|
|
119
|
+
* allocation rows cannot exist before their order items do.
|
|
120
|
+
*
|
|
121
|
+
* The gate `providePort` wraps this in is real but never reached from
|
|
122
|
+
* placement, for the same reason `inventoryFulfilmentPlanningPort`'s is not:
|
|
123
|
+
* `orders` declares this name `degrades-without` and asks
|
|
124
|
+
* `effectiveState.isPresent('inventory')` before the reservation block and
|
|
125
|
+
* before the cancellation release, so with this module off nothing is
|
|
126
|
+
* reserved and nothing is released — rather than a 503 in the middle of a
|
|
127
|
+
* placement.
|
|
128
|
+
*/
|
|
129
|
+
ctx.di.providePort('inventoryReservationApplyPort', ctx.asFunction(() => new InventoryReservationApplyService()).singleton());
|
|
130
|
+
/**
|
|
131
|
+
* D-74 — the bulk stock import. `import_export` wrote `stock_levels` from its
|
|
132
|
+
* own transaction, with no Command, no audit row and the seeded warehouse id
|
|
133
|
+
* pasted in as a literal; all three come back here, where the rows live.
|
|
134
|
+
*
|
|
135
|
+
* `catalogProductReadPort` is resolved lazily and per call: a spreadsheet
|
|
136
|
+
* addresses a product by SKU, and this module already declares `catalog`.
|
|
137
|
+
*/
|
|
138
|
+
ctx.di.providePort('inventoryStockImportPort', ctx
|
|
139
|
+
.asFunction(({ commandBus }) => new InventoryStockImportService(commandBus, lazyPort(ctx, 'catalogProductReadPort')))
|
|
140
|
+
.singleton());
|
|
141
|
+
/**
|
|
142
|
+
* Issue #185 — the per-warehouse threshold copy, published.
|
|
143
|
+
*
|
|
144
|
+
* `catalog`'s product duplication wrote these rows itself, with an
|
|
145
|
+
* `insert … select` naming this module's table. It named no import specifier,
|
|
146
|
+
* so `check:module-boundary`'s specifier pass could not see it; it asked no
|
|
147
|
+
* gate, so it kept writing with this module switched off; and it left no
|
|
148
|
+
* audit row here, so the rows arrived with nothing on this side having decided
|
|
149
|
+
* they should. The port is the whole remedy: one Command, one audit row, and
|
|
150
|
+
* the gate `providePort` wraps it in.
|
|
151
|
+
*
|
|
152
|
+
* `catalog` declares this name `degrades-without` and decides presence in
|
|
153
|
+
* front of the gate, so the duplication itself never meets a 503 — see the
|
|
154
|
+
* contract's note on why the copy owns its own transaction.
|
|
155
|
+
*/
|
|
156
|
+
ctx.di.providePort('inventoryProductThresholdWritePort', ctx
|
|
157
|
+
.asFunction(({ commandBus }) => new InventoryProductThresholdWriteService(commandBus))
|
|
158
|
+
.singleton());
|
|
159
|
+
ctx.di.providePort('inventoryAvailabilityPort', ctx
|
|
160
|
+
.asFunction(({ emFactory, eventBus, auditLogService }) => {
|
|
161
|
+
const warehouseChannels = new WarehouseChannelService(emFactory, auditLogService);
|
|
162
|
+
const stockLevels = new StockLevelService(emFactory, lazyPort(ctx, 'catalogProductReadPort'), lazyPort(ctx, 'catalogCategoryReadPort'), eventBus, auditLogService);
|
|
163
|
+
return {
|
|
164
|
+
async resolveAvailabilityBands(productIds, salesChannelId) {
|
|
165
|
+
const candidateWarehouseIds = await warehouseChannels.resolveCandidateWarehouseIds(salesChannelId);
|
|
166
|
+
return stockLevels.resolveAvailabilityBands(productIds, candidateWarehouseIds.length > 0 ? candidateWarehouseIds : undefined);
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
})
|
|
170
|
+
.singleton());
|
|
171
|
+
/**
|
|
172
|
+
* The three reactors this module owns (issue #107).
|
|
173
|
+
*
|
|
174
|
+
* All three were bare `eventBus.on` calls inside the plugin body, so a
|
|
175
|
+
* switched-off `inventory` still sent back-in-stock mail, still sent low-stock
|
|
176
|
+
* alerts and still wrote the mirrored threshold row — three writes on a module
|
|
177
|
+
* an operator believed was absent. `ctx.subscribe` puts each behind
|
|
178
|
+
* `subscribeForModule`, which reads the effective state per event.
|
|
179
|
+
*
|
|
180
|
+
* The threshold mirror re-reads the changed setting, and reads the value that
|
|
181
|
+
* was just written: `SettingsAdminService` drops the settings cache at the
|
|
182
|
+
* write seam and awaits the drop before it emits (issue #45). This used to
|
|
183
|
+
* depend on the kernel's invalidator being registered ahead of this handler —
|
|
184
|
+
* true, but only by composition order, which nothing preserved.
|
|
185
|
+
*/
|
|
186
|
+
const handle = () => ctx.cradle().inventory.handle;
|
|
187
|
+
ctx.subscribe('inventory.adjusted.v1', async (payload) => {
|
|
188
|
+
await handle().availabilityWorker.handleAdjusted(payload);
|
|
189
|
+
});
|
|
190
|
+
ctx.subscribe('inventory.adjusted.v1', async (payload) => {
|
|
191
|
+
await handle().lowStockAlertService.handleAdjusted(payload);
|
|
192
|
+
});
|
|
193
|
+
ctx.subscribe('settings.value_changed', async (payload) => {
|
|
194
|
+
await handle().thresholdSettingsMirror?.onSettingChanged(payload);
|
|
195
|
+
});
|
|
196
|
+
ctx.routes(async (app) => {
|
|
197
|
+
await ctx.cradle().inventory.plugin(app);
|
|
198
|
+
});
|
|
199
|
+
/**
|
|
200
|
+
* Migration 030 seeds the Default warehouse and tries to bind it to every
|
|
201
|
+
* channel, but it runs *before* the default-channel reconciler creates the
|
|
202
|
+
* system channel at boot. This catches up at runtime so a channel is never
|
|
203
|
+
* seen without at least one warehouse assignment (feature 026 US3).
|
|
204
|
+
*
|
|
205
|
+
* It ran from `composition.ts` until T143a — which meant it ran with this
|
|
206
|
+
* module switched off, and did not run in the harness at all
|
|
207
|
+
* (`harness-parity` carried it as a production-only construct). As a boot
|
|
208
|
+
* hook it does neither.
|
|
209
|
+
*/
|
|
210
|
+
ctx.onBoot(async () => {
|
|
211
|
+
// Presence is decided here — first, and outside anything that could catch it
|
|
212
|
+
// (issue #146, D-68). The reconciler creates a
|
|
213
|
+
// `warehouse_channel_assignments` row per sales channel, so with the module
|
|
214
|
+
// switched off it wrote this module's tables at every boot. A boot hook has
|
|
215
|
+
// no caller to answer, so the question is asked rather than thrown:
|
|
216
|
+
// `runBootHooks` re-throws as `ModuleCompositionError`, which `index.ts`
|
|
217
|
+
// turns into `process.exit(1)`.
|
|
218
|
+
//
|
|
219
|
+
// The consequence of returning: a sales channel created while `inventory` is
|
|
220
|
+
// off gets its default warehouse assignment at the **next boot** rather than
|
|
221
|
+
// at reactivation. That is acceptable because the reconcile is idempotent
|
|
222
|
+
// and every read of those rows is gated anyway. If it stops being
|
|
223
|
+
// acceptable, the repair is to drive the reconcile from the activation
|
|
224
|
+
// event — not to un-probe this hook.
|
|
225
|
+
if (!effectiveState.isPresent('inventory'))
|
|
226
|
+
return;
|
|
227
|
+
await new WarehouseChannelReconciler(ctx.cradle().emFactory()).run();
|
|
228
|
+
});
|
|
229
|
+
/**
|
|
230
|
+
* The default subject and content for the 2 transactional emails this
|
|
231
|
+
* module declares in its manifest (T143a).
|
|
232
|
+
*
|
|
233
|
+
* These were fourteen `emailDefaultsRegistry.register(...)` calls in
|
|
234
|
+
* `composition.ts`, each importing a template constant out of the module that
|
|
235
|
+
* owns it — a root reaching into seven modules to hand their own content to
|
|
236
|
+
* an eighth. Each module registers its own now.
|
|
237
|
+
*
|
|
238
|
+
* `ctx.onBoot` rather than a registration: the registry is *read* once, by
|
|
239
|
+
* `transactional_emails`' boot reconciler inside its plugin body. Boot hooks
|
|
240
|
+
* run during composition and plugin bodies only when the Fastify app is
|
|
241
|
+
* built, so this always lands first — by construction, not by ordering luck.
|
|
242
|
+
*/
|
|
243
|
+
ctx.onBoot(async () => {
|
|
244
|
+
const defaults = lazyPort(ctx, 'emailDefaultsPort');
|
|
245
|
+
defaults.register('low_stock_alert', LOW_STOCK_ALERT_DEFAULT, 'inventory');
|
|
246
|
+
defaults.register('availability_back_in_stock', AVAILABILITY_BACK_IN_STOCK_DEFAULT, 'inventory');
|
|
247
|
+
});
|
|
248
|
+
/**
|
|
249
|
+
* The assistant tools this module contributes (D-44).
|
|
250
|
+
*
|
|
251
|
+
* Both roots built the warehouse resolver and the `set_stock_level` mutation
|
|
252
|
+
* from this module's own services and pushed them into `prompt_actions`'
|
|
253
|
+
* registry, because pushing from here would have made `prompt_actions` a
|
|
254
|
+
* declared dependency — and that declaration is what would have made an
|
|
255
|
+
* optional assistant undeactivatable while `inventory` is present.
|
|
256
|
+
* `nonBindingDependencies` declares the edge without that claim.
|
|
257
|
+
*
|
|
258
|
+
* A push, not a pull. The registry is a plain registration, so this resolves
|
|
259
|
+
* no gate, and the host drops every tool whose recorded owner is not
|
|
260
|
+
* effectively present.
|
|
261
|
+
*/
|
|
262
|
+
ctx.onBoot(() => {
|
|
263
|
+
const cradle = ctx.cradle();
|
|
264
|
+
const registry = cradle.promptActionToolRegistry;
|
|
265
|
+
for (const tool of inventoryPromptTools({
|
|
266
|
+
emFactory: cradle.emFactory,
|
|
267
|
+
catalogProducts: lazyPort(ctx, 'catalogProductReadPort'),
|
|
268
|
+
catalogCategories: lazyPort(ctx, 'catalogCategoryReadPort'),
|
|
269
|
+
eventBus: cradle.eventBus,
|
|
270
|
+
auditLogService: cradle.auditLogService,
|
|
271
|
+
})) {
|
|
272
|
+
registry.register(tool);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
/**
|
|
276
|
+
* This module's rows carry a country code, so it answers "who still points at
|
|
277
|
+
* this country?" about its own tables (feature 077, D-87), where the owner used
|
|
278
|
+
* to count them with SQL naming this module's tables.
|
|
279
|
+
*
|
|
280
|
+
* A **contribution** hook: it pushes an inert descriptor into `countryReferenceRegistry`,
|
|
281
|
+
* an ungated registry, and carries no presence probe (D-62/D-68). Probing
|
|
282
|
+
* would be wrong in the dangerous direction — a switched-off module still owns
|
|
283
|
+
* the rows, so its country must still refuse the delete, which is the
|
|
284
|
+
* enumeration policy the registry states.
|
|
285
|
+
*/
|
|
286
|
+
ctx.onBoot(() => {
|
|
287
|
+
registerWarehouseCountryReferences(lazyPort(ctx, 'countryReferenceRegistry'), ctx.cradle().emFactory);
|
|
288
|
+
});
|
|
289
|
+
/**
|
|
290
|
+
* What an audit row about a warehouse is called, and where the admin app shows it
|
|
291
|
+
* (feature 075, D-87 drain).
|
|
292
|
+
*
|
|
293
|
+
* `audit_logs` used to answer both by hand — one SQL statement naming this
|
|
294
|
+
* module's table, and this module's admin route spelled into its own switch.
|
|
295
|
+
* A read port would have been the wrong repair: `audit_logs` is a
|
|
296
|
+
* cross-cutting reader, and five ports into it would be five edges pointing
|
|
297
|
+
* from the record towards the things it records. One of the five contributors
|
|
298
|
+
* (`inventory`) is switchable, and `audit_logs` is `nonDeactivatable`, so that
|
|
299
|
+
* edge would also have taken the operator's switch away. A push costs nothing
|
|
300
|
+
* and reads the same for all five.
|
|
301
|
+
*
|
|
302
|
+
* A **contribution** hook: it pushes an inert resolver into
|
|
303
|
+
* `auditReferenceRegistry`, an ungated registry, and carries no presence probe
|
|
304
|
+
* (D-67/D-68). The registry's own enumeration policy is what drops this entry
|
|
305
|
+
* while the module is absent — probing here would make the drop survive a
|
|
306
|
+
* reactivation until the next restart.
|
|
307
|
+
*/
|
|
308
|
+
ctx.onBoot(() => {
|
|
309
|
+
registerInventoryAuditReferences(lazyPort(ctx, 'auditReferenceRegistry'), ctx.cradle().emFactory);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* The module's persisted entity classes, on the `./backend` subpath, as one
|
|
314
|
+
* array and **no named class export** (D-168).
|
|
315
|
+
*
|
|
316
|
+
* This is the shape the platform reads when the package is *installed*: the
|
|
317
|
+
* boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
|
|
318
|
+
* and the static declaration reader (`scripts/lib/package-declarations.ts`),
|
|
319
|
+
* which is the third source of `check:module-boundary`'s `table->owner` map and
|
|
320
|
+
* the package pass of `check-entity-tenant-classification`. A missing array is
|
|
321
|
+
* answered with `[]` — zero entities registered, no error anywhere.
|
|
322
|
+
*
|
|
323
|
+
* The order is the one `db/entities-registry.generated.ts` declared before this
|
|
324
|
+
* module became a package, so the registered set is the same list in the same
|
|
325
|
+
* sequence.
|
|
326
|
+
*/
|
|
327
|
+
export const entities = [
|
|
328
|
+
AvailabilityNotification,
|
|
329
|
+
InventoryThreshold,
|
|
330
|
+
ProductWarehouseLowStockThreshold,
|
|
331
|
+
StockAllocation,
|
|
332
|
+
StockLevel,
|
|
333
|
+
WarehouseChannelAssignment,
|
|
334
|
+
Warehouse,
|
|
335
|
+
];
|
|
336
|
+
/**
|
|
337
|
+
* The warehouse↔channel reconciler and this module's system warehouse id,
|
|
338
|
+
* published **by name** on `./backend`.
|
|
339
|
+
*
|
|
340
|
+
* The host's demo composition runs the reconciler, and a host program is
|
|
341
|
+
* composed against this package's `dist` while the ORM is registered from the
|
|
342
|
+
* same `entities` array above — so a filesystem path into this file's source
|
|
343
|
+
* would evaluate `warehouse.entity.ts` a second time and the reconciler would
|
|
344
|
+
* `em.create` a `WarehouseChannelAssignment` class the ORM has never heard of
|
|
345
|
+
* (D-160.6.1). D-168 bars an entity class from leaving by this door; a service
|
|
346
|
+
* and a constant are not entities, and `price_lists`' `DefaultPriceListMigrator`
|
|
347
|
+
* / `DEFAULT_PRICE_LIST_ID` pair is the precedent for exactly this shape.
|
|
348
|
+
*/
|
|
349
|
+
export { WarehouseChannelReconciler } from './services/warehouse-channel-reconciler.js';
|
|
350
|
+
export { DEFAULT_WAREHOUSE_ID } from './entities/warehouse.entity.js';
|
|
351
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { FastifyInstance, FastifyRequest } from 'fastify';
|
|
2
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
3
|
+
import type { EventBus } from '@endora-commerce/platform/events';
|
|
4
|
+
import { AvailabilityWorker } from './services/availability-worker.js';
|
|
5
|
+
import { ThresholdSettingsMirror } from './services/threshold-settings-mirror.js';
|
|
6
|
+
import { LowStockAlertService, type InventoryTemplateEmailPort } from './services/low-stock-alert-service.js';
|
|
7
|
+
import type { SalesChannelMembershipPort } from '@endora-commerce/platform/kernel';
|
|
8
|
+
import type { SalesChannelResolutionPort } from '@endora-commerce/platform/kernel';
|
|
9
|
+
import type { SettingsReadPort } from '@endora-commerce/platform/kernel';
|
|
10
|
+
import type { AuditPort } from '@endora-commerce/platform/kernel';
|
|
11
|
+
import type { CatalogCategoryReadPort, CatalogCategoryWritePort, CatalogProductReadPort, CustomerAccountReadPort, DictionaryValidator, EmailMailerPort } from '@endora-commerce/contracts';
|
|
12
|
+
import type { RequireAdminFactory } from '@endora-commerce/platform/kernel';
|
|
13
|
+
export interface InventoryAuditContext {
|
|
14
|
+
actorAdminUserId: string;
|
|
15
|
+
impersonatedCustomerAccountId?: string | null;
|
|
16
|
+
ipAddress?: string | null;
|
|
17
|
+
userAgent?: string | null;
|
|
18
|
+
requestId?: string | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Composition root for the inventory module — feature 010.
|
|
22
|
+
*
|
|
23
|
+
* Adds WarehouseService + StockLevelService alongside the existing
|
|
24
|
+
* AvailabilityNotificationService. Routes are registered via the
|
|
25
|
+
* plug-in factory so test harnesses get the same wiring.
|
|
26
|
+
*/
|
|
27
|
+
export interface InventoryModuleOptions {
|
|
28
|
+
emFactory: () => EntityManager;
|
|
29
|
+
/**
|
|
30
|
+
* The three reads and one write this module performs across a boundary
|
|
31
|
+
* (feature 075, Phase C). Required, not optional: `catalog` and
|
|
32
|
+
* `customer_accounts` are declared dependencies, and an optional port is a
|
|
33
|
+
* composition that silently answers without them — which is exactly what an
|
|
34
|
+
* entity import was.
|
|
35
|
+
*/
|
|
36
|
+
catalogProducts: CatalogProductReadPort;
|
|
37
|
+
catalogCategories: CatalogCategoryReadPort;
|
|
38
|
+
catalogCategoryWrites: CatalogCategoryWritePort;
|
|
39
|
+
customerAccounts: CustomerAccountReadPort;
|
|
40
|
+
/**
|
|
41
|
+
* `salesChannelMembershipPort` — the sanctioned bridge accessor
|
|
42
|
+
* (Constitution XII) the notify-when-available seam narrows against, through
|
|
43
|
+
* `outOfRequestChannel`. Required for the same reason the four ports above
|
|
44
|
+
* are: an optional channel gate is a composition that answers without one.
|
|
45
|
+
*/
|
|
46
|
+
salesChannelMembership: SalesChannelMembershipPort;
|
|
47
|
+
requireCustomer: (req: FastifyRequest, reply: unknown) => Promise<void>;
|
|
48
|
+
resolveCustomerContext: (req: FastifyRequest) => {
|
|
49
|
+
customerAccountId: string;
|
|
50
|
+
organizationId: string;
|
|
51
|
+
};
|
|
52
|
+
/** When supplied, the admin stock-level read + set routes are registered. */
|
|
53
|
+
requireAdmin?: RequireAdminFactory;
|
|
54
|
+
/** Optional event bus for `inventory.adjusted.v1` emission. */
|
|
55
|
+
eventBus?: EventBus;
|
|
56
|
+
/** Optional channel resolver — when supplied, storefront-public stock
|
|
57
|
+
* reads scope cumulative on-hand to the caller's channel binding. */
|
|
58
|
+
channelResolver?: SalesChannelResolutionPort;
|
|
59
|
+
/** Optional settings service used to read the inventory.display_mode key
|
|
60
|
+
* for the storefront-public display-mode endpoint. */
|
|
61
|
+
settingsService?: SettingsReadPort;
|
|
62
|
+
/**
|
|
63
|
+
* `emailMailer`, owned by `email`, as its published contract (feature 075).
|
|
64
|
+
* Required: the `ConsoleMailer` default this used to fall back to was a value
|
|
65
|
+
* import of another module's driver, and it has had no reachable caller since
|
|
66
|
+
* the container started resolving `emailMailer` for every composition.
|
|
67
|
+
*/
|
|
68
|
+
mailer: EmailMailerPort;
|
|
69
|
+
/** Feature 047 — optional admin-editable template path for inventory emails. */
|
|
70
|
+
templateEmail?: InventoryTemplateEmailPort;
|
|
71
|
+
/** Channel id used to read inventory.* settings for low-stock alerts. */
|
|
72
|
+
settingsChannelId?: string;
|
|
73
|
+
/** Lazy lookup for the system-default channel id; used by the
|
|
74
|
+
* threshold-settings mirror. Falls back to {@link channelResolver}
|
|
75
|
+
* when omitted. */
|
|
76
|
+
resolveSystemDefaultChannelId?: () => Promise<string | null>;
|
|
77
|
+
dictionaryValidator?: DictionaryValidator;
|
|
78
|
+
/** Feature 024 — optional cross-module hook so warehouse / stock /
|
|
79
|
+
* threshold / CSV-import mutations land in the audit log. Tests that
|
|
80
|
+
* don't care about audit can omit it. */
|
|
81
|
+
auditLogService?: AuditPort;
|
|
82
|
+
/** Feature 024 — resolves the admin actor identity for audit entries. */
|
|
83
|
+
resolveAdminAuditContext?: (request: FastifyRequest) => {
|
|
84
|
+
actorAdminUserId: string;
|
|
85
|
+
impersonatedCustomerAccountId?: string | null;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Feature 026 US4 — when provided, the storefront stock-figure endpoint
|
|
89
|
+
* intersects its candidate warehouse set with the Organization's assigned
|
|
90
|
+
* warehouses. Empty / null ⇒ platform defaults apply.
|
|
91
|
+
*/
|
|
92
|
+
resolveOrganizationWarehouseAllowList?: (req: FastifyRequest) => Promise<string[] | null>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The three event handlers this module owns, exposed so `backend.ts` can
|
|
96
|
+
* register them through `ctx.subscribe` (issue #107).
|
|
97
|
+
*
|
|
98
|
+
* They were attached here with a bare `eventBus.on`, which is why a switched-off
|
|
99
|
+
* `inventory` still mailed back-in-stock notices, still mailed low-stock alerts
|
|
100
|
+
* and still wrote the mirrored threshold row.
|
|
101
|
+
*/
|
|
102
|
+
export interface InventoryModuleHandle {
|
|
103
|
+
availabilityWorker: AvailabilityWorker;
|
|
104
|
+
lowStockAlertService: LowStockAlertService;
|
|
105
|
+
/** Absent when this composition wired no settings service. */
|
|
106
|
+
thresholdSettingsMirror: ThresholdSettingsMirror | undefined;
|
|
107
|
+
}
|
|
108
|
+
export interface InventoryModuleResult {
|
|
109
|
+
plugin: (app: FastifyInstance) => Promise<void>;
|
|
110
|
+
handle: InventoryModuleHandle;
|
|
111
|
+
}
|
|
112
|
+
export declare function inventoryModule(options: InventoryModuleOptions): InventoryModuleResult;
|
|
113
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/backend/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { AvailabilityNotificationService } from './services/availability-notification-service.js';
|
|
2
|
+
import { AvailabilityWorker } from './services/availability-worker.js';
|
|
3
|
+
import { CsvStockImporter } from './services/csv-stock-importer.js';
|
|
4
|
+
import { ThresholdSettingsMirror } from './services/threshold-settings-mirror.js';
|
|
5
|
+
import { WarehouseService } from './services/warehouse-service.js';
|
|
6
|
+
import { StockLevelService } from './services/stock-level-service.js';
|
|
7
|
+
import { WarehouseChannelService } from './services/warehouse-channel-service.js';
|
|
8
|
+
import { ThresholdAdminService } from './services/threshold-admin-service.js';
|
|
9
|
+
import { LowStockAlertService } from './services/low-stock-alert-service.js';
|
|
10
|
+
import { registerInventoryRoutes } from './routes.js';
|
|
11
|
+
import { registerInventoryAdminRoutes } from './routes.admin.js';
|
|
12
|
+
export function inventoryModule(options) {
|
|
13
|
+
const mailer = options.mailer;
|
|
14
|
+
const availabilityWorker = new AvailabilityWorker(options.emFactory, mailer, options.catalogProducts, options.customerAccounts);
|
|
15
|
+
const lowStockAlertService = new LowStockAlertService(options.emFactory, mailer, options.catalogProducts, options.settingsService, options.settingsChannelId, options.templateEmail);
|
|
16
|
+
let thresholdSettingsMirror;
|
|
17
|
+
if (options.settingsService) {
|
|
18
|
+
// D-48 — the last branch used to be `sysDefault?.id ?? null`, which
|
|
19
|
+
// mirrored the threshold settings platform-wide on a branch the platform
|
|
20
|
+
// guarantees against. `null` here now means only what it always should
|
|
21
|
+
// have: this composition wired no channel resolver at all.
|
|
22
|
+
const resolveChannelId = options.resolveSystemDefaultChannelId ??
|
|
23
|
+
(async () => {
|
|
24
|
+
if (options.settingsChannelId)
|
|
25
|
+
return options.settingsChannelId;
|
|
26
|
+
if (!options.channelResolver)
|
|
27
|
+
return null;
|
|
28
|
+
return (await options.channelResolver.getSystemDefault()).id;
|
|
29
|
+
});
|
|
30
|
+
thresholdSettingsMirror = new ThresholdSettingsMirror(options.emFactory, options.settingsService, resolveChannelId);
|
|
31
|
+
}
|
|
32
|
+
const plugin = async (app) => {
|
|
33
|
+
const availabilityService = new AvailabilityNotificationService(options.emFactory, options.catalogProducts, options.customerAccounts, options.salesChannelMembership, mailer, options.templateEmail);
|
|
34
|
+
const warehouseChannelService = new WarehouseChannelService(options.emFactory, options.auditLogService);
|
|
35
|
+
const stockLevelService = new StockLevelService(options.emFactory, options.catalogProducts, options.catalogCategories, options.eventBus, options.auditLogService);
|
|
36
|
+
const thresholdAdminService = new ThresholdAdminService(options.emFactory, options.catalogCategories, options.catalogCategoryWrites, options.catalogProducts, options.auditLogService);
|
|
37
|
+
await registerInventoryRoutes(app, {
|
|
38
|
+
emFactory: options.emFactory,
|
|
39
|
+
catalogProducts: options.catalogProducts,
|
|
40
|
+
catalogCategories: options.catalogCategories,
|
|
41
|
+
customerAccounts: options.customerAccounts,
|
|
42
|
+
availabilityService,
|
|
43
|
+
requireCustomer: options.requireCustomer,
|
|
44
|
+
resolveCustomerContext: options.resolveCustomerContext,
|
|
45
|
+
warehouseChannelService,
|
|
46
|
+
stockLevelService,
|
|
47
|
+
...(options.channelResolver ? { channelResolver: options.channelResolver } : {}),
|
|
48
|
+
...(options.settingsService ? { settingsService: options.settingsService } : {}),
|
|
49
|
+
...(options.resolveOrganizationWarehouseAllowList
|
|
50
|
+
? { resolveOrganizationWarehouseAllowList: options.resolveOrganizationWarehouseAllowList }
|
|
51
|
+
: {}),
|
|
52
|
+
});
|
|
53
|
+
if (options.requireAdmin) {
|
|
54
|
+
const warehouseService = new WarehouseService(options.emFactory, options.dictionaryValidator, options.auditLogService);
|
|
55
|
+
const csvStockImporter = new CsvStockImporter(options.emFactory, options.catalogProducts, options.eventBus, options.auditLogService);
|
|
56
|
+
await registerInventoryAdminRoutes(app, {
|
|
57
|
+
emFactory: options.emFactory,
|
|
58
|
+
catalogProducts: options.catalogProducts,
|
|
59
|
+
warehouseService,
|
|
60
|
+
stockLevelService,
|
|
61
|
+
warehouseChannelService,
|
|
62
|
+
thresholdAdminService,
|
|
63
|
+
lowStockAlertService,
|
|
64
|
+
availabilityNotificationService: availabilityService,
|
|
65
|
+
csvStockImporter,
|
|
66
|
+
requireAdmin: options.requireAdmin,
|
|
67
|
+
...(options.resolveAdminAuditContext
|
|
68
|
+
? { resolveAdminAuditContext: options.resolveAdminAuditContext }
|
|
69
|
+
: {}),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
return { plugin, handle: { availabilityWorker, lowStockAlertService, thresholdSettingsMirror } };
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/backend/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type CatalogCategoryReadPort, type CatalogProductReadPort, type PromptActionTool } from '@endora-commerce/contracts';
|
|
2
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
3
|
+
import type { EventBus } from '@endora-commerce/platform/events';
|
|
4
|
+
import type { AuditPort } from '@endora-commerce/platform/kernel';
|
|
5
|
+
/**
|
|
6
|
+
* Inventory's contribution to the prompt-assistant tool catalogue
|
|
7
|
+
* (feature 043, data-model §4): the warehouse resolver and the flagship
|
|
8
|
+
* `set_stock_level` mutation. The mutation's preview is server-computed
|
|
9
|
+
* from the same rows the execution will touch (FR-004), and execution
|
|
10
|
+
* rides `StockLevelService.setOnHand` — the exact path of the manual
|
|
11
|
+
* inventory screen, including its `stock_level.adjust` audit row.
|
|
12
|
+
*/
|
|
13
|
+
export interface InventoryPromptToolsDeps {
|
|
14
|
+
emFactory: () => EntityManager;
|
|
15
|
+
/** `catalogProductReadPort`, owned by `catalog` (feature 075, Phase C). */
|
|
16
|
+
catalogProducts: CatalogProductReadPort;
|
|
17
|
+
/** `catalogCategoryReadPort`, owned by `catalog` — read by the stock service. */
|
|
18
|
+
catalogCategories: CatalogCategoryReadPort;
|
|
19
|
+
eventBus?: EventBus;
|
|
20
|
+
auditLogService?: AuditPort;
|
|
21
|
+
}
|
|
22
|
+
export declare function inventoryPromptTools(deps: InventoryPromptToolsDeps): PromptActionTool[];
|
|
23
|
+
//# sourceMappingURL=prompt-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-tools.d.ts","sourceRoot":"","sources":["../../src/backend/prompt-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EAItB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAMlE;;;;;;;GAOG;AAEH,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,aAAa,CAAC;IAC/B,2EAA2E;IAC3E,eAAe,EAAE,sBAAsB,CAAC;IACxC,iFAAiF;IACjF,iBAAiB,EAAE,uBAAuB,CAAC;IAC3C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,eAAe,CAAC,EAAE,SAAS,CAAC;CAC7B;AAQD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,wBAAwB,GAAG,gBAAgB,EAAE,CAgFvF"}
|