@classytic/flow 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/LICENSE +21 -0
  3. package/README.md +258 -0
  4. package/dist/allocation-policy-my_HfzdV.d.mts +23 -0
  5. package/dist/base-MWBqRFM2.mjs +16 -0
  6. package/dist/catalog-bridge-K8bdkncJ.d.mts +29 -0
  7. package/dist/cost-layer.port-iH9pvZqB.d.mts +30 -0
  8. package/dist/cost-layer.service-BQ1bs-XN.mjs +86 -0
  9. package/dist/cost-layer.service-DWmo9dQz.d.mts +53 -0
  10. package/dist/count.port-BRqwGbi3.d.mts +57 -0
  11. package/dist/counting/index.d.mts +2 -0
  12. package/dist/counting/index.mjs +2 -0
  13. package/dist/counting.service-BiQXqorv.mjs +232 -0
  14. package/dist/counting.service-CpAxU2G0.d.mts +74 -0
  15. package/dist/domain/contracts/index.d.mts +3 -0
  16. package/dist/domain/contracts/index.mjs +1 -0
  17. package/dist/domain/enums/index.d.mts +2 -0
  18. package/dist/domain/enums/index.mjs +4 -0
  19. package/dist/domain/index.d.mts +24 -0
  20. package/dist/domain/index.mjs +10 -0
  21. package/dist/domain/policies/index.d.mts +4 -0
  22. package/dist/domain/policies/index.mjs +1 -0
  23. package/dist/domain-D5cpMpR0.mjs +96 -0
  24. package/dist/domain-errors-D7S9ydNF.mjs +133 -0
  25. package/dist/enums-C3_z6aHC.mjs +82 -0
  26. package/dist/event-bus-BNmyoJb4.mjs +37 -0
  27. package/dist/event-bus-Um_xrcMY.d.mts +21 -0
  28. package/dist/event-emitter.port-BFh2pasY.d.mts +183 -0
  29. package/dist/event-types-BSqQOvXv.mjs +29 -0
  30. package/dist/events/index.d.mts +3 -0
  31. package/dist/events/index.mjs +3 -0
  32. package/dist/idempotency.port-CTC70JON.d.mts +55 -0
  33. package/dist/index-Bia4m8d2.d.mts +67 -0
  34. package/dist/index-BmNm3oNU2.d.mts +107 -0
  35. package/dist/index-C5PciI9P.d.mts +203 -0
  36. package/dist/index-CMTUKEK_.d.mts +308 -0
  37. package/dist/index-C_aEnozN.d.mts +220 -0
  38. package/dist/index-CulWO137.d.mts +107 -0
  39. package/dist/index-DFF0GJ4J.d.mts +36 -0
  40. package/dist/index-DsE7lZdO.d.mts +11 -0
  41. package/dist/index-DwO9IdNa.d.mts +1 -0
  42. package/dist/index-dtWUZr2a2.d.mts +350 -0
  43. package/dist/index.d.mts +128 -0
  44. package/dist/index.mjs +102 -0
  45. package/dist/insufficient-stock.error-Dyr4BYaV.mjs +15 -0
  46. package/dist/location.port-CValXIpb.d.mts +52 -0
  47. package/dist/lot.port-ChsmvZqs.d.mts +32 -0
  48. package/dist/models/index.d.mts +2 -0
  49. package/dist/models/index.mjs +2 -0
  50. package/dist/models-CHTMbp-G.mjs +1020 -0
  51. package/dist/move-group.port-DHGoQA3d.d.mts +56 -0
  52. package/dist/move-status-DkaFp2GD.mjs +38 -0
  53. package/dist/move.port-Qg1CYp7h.d.mts +89 -0
  54. package/dist/package.service-4tcAwBbr.mjs +95 -0
  55. package/dist/package.service-C605NaBQ.d.mts +42 -0
  56. package/dist/packaging/index.d.mts +2 -0
  57. package/dist/packaging/index.mjs +2 -0
  58. package/dist/procurement/index.d.mts +2 -0
  59. package/dist/procurement/index.mjs +2 -0
  60. package/dist/quant.port-BBa66PBT.d.mts +42 -0
  61. package/dist/removal-policy-BItBB8FD.d.mts +29 -0
  62. package/dist/replenishment-rule.port-DnEYtbyD.d.mts +78 -0
  63. package/dist/replenishment.service-BT9P-HKM.mjs +284 -0
  64. package/dist/replenishment.service-HO0sDhB_.d.mts +89 -0
  65. package/dist/reporting/index.d.mts +2 -0
  66. package/dist/reporting/index.mjs +2 -0
  67. package/dist/reporting-CL5ffrKM.mjs +243 -0
  68. package/dist/repositories/index.d.mts +2 -0
  69. package/dist/repositories/index.mjs +2 -0
  70. package/dist/repositories-nZXJKvLW.mjs +842 -0
  71. package/dist/reservation-status-ZfuTaWG0.mjs +22 -0
  72. package/dist/reservation.port-l9NFQ0si.d.mts +85 -0
  73. package/dist/reservations/index.d.mts +2 -0
  74. package/dist/reservations/index.mjs +2 -0
  75. package/dist/reservations-Cg4wN0QB.mjs +112 -0
  76. package/dist/routing/index.d.mts +362 -0
  77. package/dist/routing/index.mjs +582 -0
  78. package/dist/runtime-config-C0ggPkiK.mjs +40 -0
  79. package/dist/runtime-config-CQLtPPqY.d.mts +38 -0
  80. package/dist/scan-token-CNM9QVLY.d.mts +26 -0
  81. package/dist/scanning/index.d.mts +45 -0
  82. package/dist/scanning/index.mjs +228 -0
  83. package/dist/services/index.d.mts +8 -0
  84. package/dist/services/index.mjs +8 -0
  85. package/dist/services-_lLO4Xbl.mjs +1009 -0
  86. package/dist/stock-move-group-C0DqUfPY.mjs +88 -0
  87. package/dist/stock-package-BIarxbDS.d.mts +19 -0
  88. package/dist/stock-quant-CZhgvTu7.d.mts +41 -0
  89. package/dist/tenant-guard-6Ne-BILP.mjs +12 -0
  90. package/dist/tenant-isolation.error-D3OcKUdx.mjs +11 -0
  91. package/dist/trace.service-B9vAh-l-.d.mts +55 -0
  92. package/dist/trace.service-DE6Eh8_8.mjs +71 -0
  93. package/dist/traceability/index.d.mts +2 -0
  94. package/dist/traceability/index.mjs +2 -0
  95. package/dist/types/index.d.mts +2 -0
  96. package/dist/types/index.mjs +1 -0
  97. package/dist/unit-of-work.port-CWEkrDKu.d.mts +17 -0
  98. package/dist/valuation/index.d.mts +78 -0
  99. package/dist/valuation/index.mjs +103 -0
  100. package/dist/valuation-policy-Dco8c9Vw.d.mts +14 -0
  101. package/dist/virtual-locations-B9zXqPdi.d.mts +38 -0
  102. package/package.json +155 -0
@@ -0,0 +1,82 @@
1
+ //#region src/domain/enums/location-type.ts
2
+ const LocationType = {
3
+ view: "view",
4
+ internal: "internal",
5
+ receiving: "receiving",
6
+ storage: "storage",
7
+ picking: "picking",
8
+ packing: "packing",
9
+ shipping: "shipping",
10
+ transit: "transit",
11
+ vendor: "vendor",
12
+ customer: "customer",
13
+ returns: "returns",
14
+ quality_hold: "quality_hold",
15
+ damaged: "damaged",
16
+ scrap: "scrap",
17
+ inventory_loss: "inventory_loss",
18
+ production: "production"
19
+ };
20
+ /** Location types that hold physical stock (non-virtual). */
21
+ const STOCKABLE_LOCATION_TYPES = [
22
+ LocationType.internal,
23
+ LocationType.receiving,
24
+ LocationType.storage,
25
+ LocationType.picking,
26
+ LocationType.packing,
27
+ LocationType.shipping,
28
+ LocationType.transit,
29
+ LocationType.returns,
30
+ LocationType.quality_hold,
31
+ LocationType.damaged,
32
+ LocationType.production
33
+ ];
34
+ /** Virtual location types — no physical stock, used for accounting/routing. */
35
+ const VIRTUAL_LOCATION_TYPES = [
36
+ LocationType.view,
37
+ LocationType.vendor,
38
+ LocationType.customer,
39
+ LocationType.scrap,
40
+ LocationType.inventory_loss
41
+ ];
42
+ //#endregion
43
+ //#region src/domain/enums/operation-type.ts
44
+ const OperationType = {
45
+ receipt: "receipt",
46
+ transfer: "transfer",
47
+ shipment: "shipment",
48
+ return: "return",
49
+ adjustment: "adjustment",
50
+ count: "count"
51
+ };
52
+ //#endregion
53
+ //#region src/domain/enums/stock-status.ts
54
+ const StockStatus = {
55
+ sellable: "sellable",
56
+ damaged: "damaged",
57
+ quarantine: "quarantine",
58
+ hold: "hold",
59
+ returns: "returns",
60
+ expired: "expired",
61
+ in_transit: "in_transit"
62
+ };
63
+ /** Only sellable stock is counted as available for sale. */
64
+ const SELLABLE_STATUSES = [StockStatus.sellable];
65
+ //#endregion
66
+ //#region src/domain/enums/tracking-mode.ts
67
+ const TrackingMode = {
68
+ none: "none",
69
+ lot: "lot",
70
+ serial: "serial"
71
+ };
72
+ //#endregion
73
+ //#region src/domain/enums/valuation-method.ts
74
+ const ValuationMethod = {
75
+ wac: "wac",
76
+ fifo: "fifo",
77
+ fefo: "fefo",
78
+ specific: "specific",
79
+ standard: "standard"
80
+ };
81
+ //#endregion
82
+ export { OperationType as a, VIRTUAL_LOCATION_TYPES as c, StockStatus as i, TrackingMode as n, LocationType as o, SELLABLE_STATUSES as r, STOCKABLE_LOCATION_TYPES as s, ValuationMethod as t };
@@ -0,0 +1,37 @@
1
+ //#region src/events/event-bus.ts
2
+ /**
3
+ * In-process event bus.
4
+ *
5
+ * Serves as the default {@link EventEmitterPort} implementation.
6
+ * Handlers are invoked fire-and-forget; failures are logged but never
7
+ * propagate to the emitter. Replace with a Redis/Kafka adapter for
8
+ * distributed workloads.
9
+ */
10
+ var InProcessEventBus = class {
11
+ handlers = /* @__PURE__ */ new Map();
12
+ async emit(event, data, _session) {
13
+ const subscribers = this.handlers.get(event);
14
+ if (!subscribers || subscribers.size === 0) return;
15
+ const tasks = [...subscribers].map((handler) => handler(data).catch((err) => {
16
+ console.error(`[FlowEventBus] Handler error on "${event}":`, err);
17
+ }));
18
+ await Promise.all(tasks);
19
+ }
20
+ on(event, handler) {
21
+ let set = this.handlers.get(event);
22
+ if (!set) {
23
+ set = /* @__PURE__ */ new Set();
24
+ this.handlers.set(event, set);
25
+ }
26
+ set.add(handler);
27
+ }
28
+ off(event, handler) {
29
+ const set = this.handlers.get(event);
30
+ if (set) {
31
+ set.delete(handler);
32
+ if (set.size === 0) this.handlers.delete(event);
33
+ }
34
+ }
35
+ };
36
+ //#endregion
37
+ export { InProcessEventBus as t };
@@ -0,0 +1,21 @@
1
+ import { t as TransactionSession } from "./unit-of-work.port-CWEkrDKu.mjs";
2
+ import { t as EventEmitterPort } from "./event-emitter.port-BFh2pasY.mjs";
3
+
4
+ //#region src/events/event-bus.d.ts
5
+ type EventHandler = (data: Record<string, unknown>) => Promise<void>;
6
+ /**
7
+ * In-process event bus.
8
+ *
9
+ * Serves as the default {@link EventEmitterPort} implementation.
10
+ * Handlers are invoked fire-and-forget; failures are logged but never
11
+ * propagate to the emitter. Replace with a Redis/Kafka adapter for
12
+ * distributed workloads.
13
+ */
14
+ declare class InProcessEventBus implements EventEmitterPort {
15
+ private handlers;
16
+ emit(event: string, data: Record<string, unknown>, _session?: TransactionSession): Promise<void>;
17
+ on(event: string, handler: EventHandler): void;
18
+ off(event: string, handler: EventHandler): void;
19
+ }
20
+ //#endregion
21
+ export { InProcessEventBus as t };
@@ -0,0 +1,183 @@
1
+ import { t as TransactionSession } from "./unit-of-work.port-CWEkrDKu.mjs";
2
+
3
+ //#region src/events/event-types.d.ts
4
+ /**
5
+ * Typed event catalog for the @classytic/flow inventory package.
6
+ *
7
+ * All domain event names are defined here as a single `as const` object so
8
+ * consumers get full autocompletion and compile-time safety.
9
+ */
10
+ declare const FlowEvents: {
11
+ readonly MOVE_GROUP_CREATED: "inventory.move_group.created";
12
+ readonly MOVE_GROUP_CONFIRMED: "inventory.move_group.confirmed";
13
+ readonly MOVE_GROUP_CANCELLED: "inventory.move_group.cancelled";
14
+ readonly MOVE_PLANNED: "inventory.move.planned";
15
+ readonly MOVE_RESERVED: "inventory.move.reserved";
16
+ readonly MOVE_DONE: "inventory.move.done";
17
+ readonly RESERVATION_CREATED: "inventory.reservation.created";
18
+ readonly RESERVATION_RELEASED: "inventory.reservation.released";
19
+ readonly RESERVATION_CONSUMED: "inventory.reservation.consumed";
20
+ readonly TRANSFER_DISPATCHED: "inventory.transfer.dispatched";
21
+ readonly TRANSFER_RECEIVED: "inventory.transfer.received";
22
+ readonly PROCUREMENT_RECEIVED: "inventory.procurement.received";
23
+ readonly COUNT_STARTED: "inventory.count.started";
24
+ readonly COUNT_RECONCILED: "inventory.count.reconciled";
25
+ readonly REPLENISHMENT_TRIGGERED: "inventory.replenishment.triggered";
26
+ readonly STOCK_LOW: "inventory.stock.low";
27
+ readonly ADJUSTMENT_POSTED: "inventory.adjustment.posted";
28
+ readonly LANDED_COST_APPLIED: "inventory.landed_cost.applied";
29
+ };
30
+ /** Union of all flow event names. */
31
+ type FlowEventName = (typeof FlowEvents)[keyof typeof FlowEvents];
32
+ /** Base payload — every event carries organizationId for tenant routing. */
33
+ interface BasePayload {
34
+ organizationId: string;
35
+ }
36
+ interface MoveGroupCreatedPayload extends BasePayload {
37
+ groupId: string;
38
+ groupType: string;
39
+ documentNumber: string;
40
+ procurementOrderId?: string;
41
+ }
42
+ interface MoveGroupConfirmedPayload extends BasePayload {
43
+ groupId: string;
44
+ documentNumber: string;
45
+ }
46
+ interface MoveGroupCancelledPayload extends BasePayload {
47
+ groupId: string;
48
+ documentNumber: string;
49
+ }
50
+ interface MovePlannedPayload extends BasePayload {
51
+ moveId: string;
52
+ moveGroupId: string;
53
+ skuRef: string;
54
+ operationType: string;
55
+ }
56
+ interface MoveDonePayload extends BasePayload {
57
+ moveId: string;
58
+ moveGroupId: string;
59
+ skuRef: string;
60
+ operationType: string;
61
+ quantityDone: number;
62
+ sourceLocationId: string;
63
+ destinationLocationId: string;
64
+ }
65
+ interface ReservationCreatedPayload extends BasePayload {
66
+ reservationId: string;
67
+ skuRef: string;
68
+ locationId: string;
69
+ quantity: number;
70
+ ownerType: string;
71
+ ownerId: string;
72
+ }
73
+ interface ReservationReleasedPayload extends BasePayload {
74
+ reservationId: string;
75
+ skuRef: string;
76
+ locationId: string;
77
+ quantity: number;
78
+ }
79
+ interface ReservationConsumedPayload extends BasePayload {
80
+ reservationId: string;
81
+ skuRef: string;
82
+ locationId: string;
83
+ quantityConsumed: number;
84
+ totalConsumed: number;
85
+ isFullyConsumed: boolean;
86
+ }
87
+ interface TransferDispatchedPayload extends BasePayload {
88
+ groupId: string;
89
+ documentNumber: string;
90
+ }
91
+ interface TransferReceivedPayload extends BasePayload {
92
+ groupId: string;
93
+ documentNumber: string;
94
+ partial?: boolean;
95
+ failedMoves?: Array<{
96
+ moveId: string;
97
+ error: string;
98
+ }>;
99
+ }
100
+ interface ProcurementReceivedPayload extends BasePayload {
101
+ orderId: string;
102
+ orderNumber: string;
103
+ vendorRef: string;
104
+ destinationNodeId: string;
105
+ itemCount: number;
106
+ }
107
+ interface CountStartedPayload extends BasePayload {
108
+ countId: string;
109
+ countNumber: string;
110
+ countType: string;
111
+ lineCount: number;
112
+ }
113
+ interface CountReconciledPayload extends BasePayload {
114
+ countId: string;
115
+ totalLines: number;
116
+ varianceLines: number;
117
+ autoApproved: boolean;
118
+ needsManualReview: boolean;
119
+ moveGroupId: string;
120
+ documentNumber: string;
121
+ }
122
+ interface ReplenishmentTriggeredPayload extends BasePayload {
123
+ ruleId: string;
124
+ skuRef: string;
125
+ currentLevel: number;
126
+ reorderPoint: number;
127
+ }
128
+ interface StockLowPayload extends BasePayload {
129
+ skuRef: string;
130
+ locationId: string;
131
+ currentLevel: number;
132
+ threshold: number;
133
+ }
134
+ interface AdjustmentPostedPayload extends BasePayload {
135
+ countId: string;
136
+ countNumber: string;
137
+ movesPosted: number;
138
+ }
139
+ interface LandedCostAppliedPayload extends BasePayload {
140
+ skuRef: string;
141
+ additionalCost: number;
142
+ }
143
+ /**
144
+ * Maps event names to their typed payloads.
145
+ * Use with `emit<E extends keyof FlowEventMap>(event: E, data: FlowEventMap[E])`.
146
+ */
147
+ interface FlowEventMap {
148
+ [FlowEvents.MOVE_GROUP_CREATED]: MoveGroupCreatedPayload;
149
+ [FlowEvents.MOVE_GROUP_CONFIRMED]: MoveGroupConfirmedPayload;
150
+ [FlowEvents.MOVE_GROUP_CANCELLED]: MoveGroupCancelledPayload;
151
+ [FlowEvents.MOVE_PLANNED]: MovePlannedPayload;
152
+ [FlowEvents.MOVE_DONE]: MoveDonePayload;
153
+ [FlowEvents.RESERVATION_CREATED]: ReservationCreatedPayload;
154
+ [FlowEvents.RESERVATION_RELEASED]: ReservationReleasedPayload;
155
+ [FlowEvents.RESERVATION_CONSUMED]: ReservationConsumedPayload;
156
+ [FlowEvents.TRANSFER_DISPATCHED]: TransferDispatchedPayload;
157
+ [FlowEvents.TRANSFER_RECEIVED]: TransferReceivedPayload;
158
+ [FlowEvents.PROCUREMENT_RECEIVED]: ProcurementReceivedPayload;
159
+ [FlowEvents.COUNT_STARTED]: CountStartedPayload;
160
+ [FlowEvents.COUNT_RECONCILED]: CountReconciledPayload;
161
+ [FlowEvents.REPLENISHMENT_TRIGGERED]: ReplenishmentTriggeredPayload;
162
+ [FlowEvents.STOCK_LOW]: StockLowPayload;
163
+ [FlowEvents.ADJUSTMENT_POSTED]: AdjustmentPostedPayload;
164
+ [FlowEvents.LANDED_COST_APPLIED]: LandedCostAppliedPayload;
165
+ }
166
+ //#endregion
167
+ //#region src/domain/ports/event-emitter.port.d.ts
168
+ /**
169
+ * Domain event emitter port.
170
+ * In-process default; consumer provides adapters for Redis, Kafka, webhooks, etc.
171
+ *
172
+ * Typed overload ensures compile-time safety for known Flow events.
173
+ * The string fallback keeps the port extensible for consumer-defined events.
174
+ */
175
+ interface EventEmitterPort {
176
+ emit<E extends keyof FlowEventMap>(event: E, data: FlowEventMap[E], session?: TransactionSession): Promise<void>;
177
+ emit(event: string, data: Record<string, unknown>, session?: TransactionSession): Promise<void>;
178
+ on<E extends keyof FlowEventMap>(event: E, handler: (data: FlowEventMap[E]) => Promise<void>): void;
179
+ on(event: string, handler: (data: Record<string, unknown>) => Promise<void>): void;
180
+ off(event: string, handler: (data: Record<string, unknown>) => Promise<void>): void;
181
+ }
182
+ //#endregion
183
+ export { FlowEvents as i, FlowEventMap as n, FlowEventName as r, EventEmitterPort as t };
@@ -0,0 +1,29 @@
1
+ //#region src/events/event-types.ts
2
+ /**
3
+ * Typed event catalog for the @classytic/flow inventory package.
4
+ *
5
+ * All domain event names are defined here as a single `as const` object so
6
+ * consumers get full autocompletion and compile-time safety.
7
+ */
8
+ const FlowEvents = {
9
+ MOVE_GROUP_CREATED: "inventory.move_group.created",
10
+ MOVE_GROUP_CONFIRMED: "inventory.move_group.confirmed",
11
+ MOVE_GROUP_CANCELLED: "inventory.move_group.cancelled",
12
+ MOVE_PLANNED: "inventory.move.planned",
13
+ MOVE_RESERVED: "inventory.move.reserved",
14
+ MOVE_DONE: "inventory.move.done",
15
+ RESERVATION_CREATED: "inventory.reservation.created",
16
+ RESERVATION_RELEASED: "inventory.reservation.released",
17
+ RESERVATION_CONSUMED: "inventory.reservation.consumed",
18
+ TRANSFER_DISPATCHED: "inventory.transfer.dispatched",
19
+ TRANSFER_RECEIVED: "inventory.transfer.received",
20
+ PROCUREMENT_RECEIVED: "inventory.procurement.received",
21
+ COUNT_STARTED: "inventory.count.started",
22
+ COUNT_RECONCILED: "inventory.count.reconciled",
23
+ REPLENISHMENT_TRIGGERED: "inventory.replenishment.triggered",
24
+ STOCK_LOW: "inventory.stock.low",
25
+ ADJUSTMENT_POSTED: "inventory.adjustment.posted",
26
+ LANDED_COST_APPLIED: "inventory.landed_cost.applied"
27
+ };
28
+ //#endregion
29
+ export { FlowEvents as t };
@@ -0,0 +1,3 @@
1
+ import { i as FlowEvents, r as FlowEventName } from "../event-emitter.port-BFh2pasY.mjs";
2
+ import { t as InProcessEventBus } from "../event-bus-Um_xrcMY.mjs";
3
+ export { type FlowEventName, FlowEvents, InProcessEventBus };
@@ -0,0 +1,3 @@
1
+ import { t as InProcessEventBus } from "../event-bus-BNmyoJb4.mjs";
2
+ import { t as FlowEvents } from "../event-types-BSqQOvXv.mjs";
3
+ export { FlowEvents, InProcessEventBus };
@@ -0,0 +1,55 @@
1
+ //#region src/domain/ports/idempotency.port.d.ts
2
+ /**
3
+ * Idempotency port — safe-retry protocol for Flow operations.
4
+ *
5
+ * Two tiers:
6
+ *
7
+ * 1. **Legacy (required)**: `check()` + `save()` — simple check-then-save.
8
+ * Every adapter MUST implement these.
9
+ *
10
+ * 2. **Atomic (optional)**: `claim()` + `complete()` + `release()` — prevents
11
+ * the TOCTOU race under concurrent retries. Adapters SHOULD implement these
12
+ * when the backing store supports atomic locks (Redis SET NX, Mongo upsert).
13
+ *
14
+ * Services prefer the atomic path when available, and fall back to legacy.
15
+ */
16
+ interface IdempotencyPort {
17
+ /** Check if a result exists for the given key. */
18
+ check<T>(key: string): Promise<{
19
+ hit: true;
20
+ result: T;
21
+ } | {
22
+ hit: false;
23
+ }>;
24
+ /** Save a result for the given key. */
25
+ save<T>(key: string, result: T, ttlMs?: number): Promise<void>;
26
+ /**
27
+ * Atomically claim a key. If the key already has a completed result,
28
+ * return it. If it's unclaimed, acquire the lock.
29
+ *
30
+ * @returns
31
+ * - `{ status: 'hit', result }` — a previous execution completed with this result
32
+ * - `{ status: 'acquired' }` — lock acquired, caller should execute then call complete()
33
+ * - `{ status: 'busy' }` — another caller holds the lock; retry later
34
+ */
35
+ claim?<T>(key: string, ttlMs?: number): Promise<{
36
+ status: 'hit';
37
+ result: T;
38
+ } | {
39
+ status: 'acquired';
40
+ } | {
41
+ status: 'busy';
42
+ }>;
43
+ /**
44
+ * Store the result for a previously claimed key.
45
+ * Only the caller that received `{ status: 'acquired' }` should call this.
46
+ */
47
+ complete?<T>(key: string, result: T): Promise<void>;
48
+ /**
49
+ * Release a claim without storing a result (e.g., on error).
50
+ * Allows a future retry to re-acquire the key.
51
+ */
52
+ release?(key: string): Promise<void>;
53
+ }
54
+ //#endregion
55
+ export { IdempotencyPort as t };
@@ -0,0 +1,67 @@
1
+ import { n as StockQuant } from "./stock-quant-CZhgvTu7.mjs";
2
+ import { n as AllocationResult, t as AllocationPolicy } from "./allocation-policy-my_HfzdV.mjs";
3
+
4
+ //#region src/reservations/exact-lot.strategy.d.ts
5
+ /**
6
+ * Exact-lot allocation — only allocate from a specific lot.
7
+ * Used when a customer or regulation requires a specific batch.
8
+ */
9
+ declare class ExactLotStrategy implements AllocationPolicy {
10
+ private targetLotId;
11
+ readonly name = "exact_lot";
12
+ constructor(targetLotId: string);
13
+ resolve(_skuRef: string, quantity: number, candidates: StockQuant[]): AllocationResult;
14
+ }
15
+ //#endregion
16
+ //#region src/reservations/fefo.strategy.d.ts
17
+ /**
18
+ * FEFO allocation — consume nearest-expiry stock first.
19
+ * Requires quants to carry lot expiry info. Quants without expiry sort last.
20
+ *
21
+ * Used for perishable goods: food, pharma, cosmetics.
22
+ */
23
+ declare class FefoStrategy implements AllocationPolicy {
24
+ private minShelfLifeDays?;
25
+ readonly name = "fefo";
26
+ constructor(minShelfLifeDays?: number | undefined);
27
+ resolve(_skuRef: string, quantity: number, candidates: StockQuant[]): AllocationResult;
28
+ }
29
+ //#endregion
30
+ //#region src/reservations/fifo.strategy.d.ts
31
+ /**
32
+ * FIFO allocation — consume oldest stock first (by inDate).
33
+ * Default strategy for most operations.
34
+ */
35
+ declare class FifoStrategy implements AllocationPolicy {
36
+ readonly name = "fifo";
37
+ resolve(_skuRef: string, quantity: number, candidates: StockQuant[]): AllocationResult;
38
+ }
39
+ /**
40
+ * Shared allocation logic — iterates sorted candidates and picks until quantity is met.
41
+ * Used by all strategies after sorting.
42
+ */
43
+ declare function allocateFromSorted(sorted: StockQuant[], quantity: number): AllocationResult;
44
+ //#endregion
45
+ //#region src/reservations/lifo.strategy.d.ts
46
+ /**
47
+ * LIFO allocation — consume newest stock first (by inDate DESC).
48
+ * Useful when freshness matters less and you want to keep oldest stock for auditing.
49
+ */
50
+ declare class LifoStrategy implements AllocationPolicy {
51
+ readonly name = "lifo";
52
+ resolve(_skuRef: string, quantity: number, candidates: StockQuant[]): AllocationResult;
53
+ }
54
+ //#endregion
55
+ //#region src/reservations/nearest.strategy.d.ts
56
+ /**
57
+ * Nearest allocation — consume stock closest to pick face (by location sortOrder ASC).
58
+ * Minimizes warehouse travel distance.
59
+ *
60
+ * Requires quants to carry locationSortOrder (set by repository join or denormalized).
61
+ */
62
+ declare class NearestStrategy implements AllocationPolicy {
63
+ readonly name = "nearest";
64
+ resolve(_skuRef: string, quantity: number, candidates: StockQuant[]): AllocationResult;
65
+ }
66
+ //#endregion
67
+ export { FefoStrategy as a, allocateFromSorted as i, LifoStrategy as n, ExactLotStrategy as o, FifoStrategy as r, NearestStrategy as t };
@@ -0,0 +1,107 @@
1
+ import { n as MovePort } from "./move.port-Qg1CYp7h.mjs";
2
+ import { t as FlowContext } from "./index-DFF0GJ4J.mjs";
3
+ import { t as LocationPort } from "./location.port-CValXIpb.mjs";
4
+ import { r as QuantPort } from "./quant.port-BBa66PBT.mjs";
5
+
6
+ //#region src/reporting/availability.d.ts
7
+ interface AvailabilityMatrixQuery {
8
+ skuRefs: string[];
9
+ nodeIds?: string[];
10
+ }
11
+ interface AvailabilityMatrixResult {
12
+ matrix: Array<{
13
+ skuRef: string;
14
+ nodes: Array<{
15
+ nodeId: string;
16
+ onHand: number;
17
+ reserved: number;
18
+ available: number;
19
+ incoming: number;
20
+ outgoing: number;
21
+ }>;
22
+ totalOnHand: number;
23
+ totalAvailable: number;
24
+ }>;
25
+ }
26
+ declare class AvailabilityReport {
27
+ private quantPort;
28
+ private locationPort?;
29
+ constructor(quantPort: QuantPort, locationPort?: LocationPort | undefined);
30
+ getMatrix(query: AvailabilityMatrixQuery, ctx: FlowContext): Promise<AvailabilityMatrixResult>;
31
+ }
32
+ //#endregion
33
+ //#region src/reporting/health-metrics.d.ts
34
+ interface StockHealthMetrics {
35
+ turnoverRate: number;
36
+ daysOfInventory: number;
37
+ stockoutRate: number;
38
+ fillRate: number;
39
+ deadStockPercentage: number;
40
+ expiryRiskValue: number;
41
+ totalSkus: number;
42
+ totalOnHand: number;
43
+ totalValue: number;
44
+ }
45
+ declare class HealthMetricsReport {
46
+ private quantPort;
47
+ constructor(quantPort: QuantPort, _movePort: MovePort);
48
+ generate(ctx: FlowContext): Promise<StockHealthMetrics>;
49
+ }
50
+ //#endregion
51
+ //#region src/reporting/stock-aging.d.ts
52
+ interface AgingBucket {
53
+ label: string;
54
+ minDays: number;
55
+ maxDays: number;
56
+ quantity: number;
57
+ value: number;
58
+ skuCount: number;
59
+ }
60
+ interface StockAgingResult {
61
+ asOfDate: Date;
62
+ buckets: AgingBucket[];
63
+ slowMoving: Array<{
64
+ skuRef: string;
65
+ locationId: string;
66
+ quantity: number;
67
+ ageDays: number;
68
+ }>;
69
+ deadStock: Array<{
70
+ skuRef: string;
71
+ locationId: string;
72
+ quantity: number;
73
+ ageDays: number;
74
+ }>;
75
+ }
76
+ declare class StockAgingReport {
77
+ private quantPort;
78
+ constructor(quantPort: QuantPort);
79
+ generate(ctx: FlowContext, nodeId?: string): Promise<StockAgingResult>;
80
+ }
81
+ //#endregion
82
+ //#region src/reporting/turnover.d.ts
83
+ interface TurnoverResult {
84
+ period: {
85
+ start: Date;
86
+ end: Date;
87
+ };
88
+ totalCOGS: number;
89
+ averageInventoryValue: number;
90
+ turnoverRate: number;
91
+ daysOfInventory: number;
92
+ skuBreakdown: Array<{
93
+ skuRef: string;
94
+ unitsSold: number;
95
+ cogs: number;
96
+ avgInventory: number;
97
+ turnover: number;
98
+ }>;
99
+ }
100
+ declare class TurnoverReport {
101
+ private quantPort;
102
+ private movePort;
103
+ constructor(quantPort: QuantPort, movePort: MovePort);
104
+ generate(periodDays: number, ctx: FlowContext): Promise<TurnoverResult>;
105
+ }
106
+ //#endregion
107
+ export { StockAgingResult as a, AvailabilityMatrixQuery as c, StockAgingReport as i, AvailabilityMatrixResult as l, TurnoverResult as n, HealthMetricsReport as o, AgingBucket as r, StockHealthMetrics as s, TurnoverReport as t, AvailabilityReport as u };