@happyvertical/smrt-inventory 0.57.17 → 0.57.19
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/AGENTS.md +19 -1
- package/README.md +32 -2
- package/dist/collections/LotCollection.d.ts +22 -0
- package/dist/collections/LotCollection.d.ts.map +1 -0
- package/dist/collections/LotCorrectionCollection.d.ts +12 -0
- package/dist/collections/LotCorrectionCollection.d.ts.map +1 -0
- package/dist/collections/LotDocumentCollection.d.ts +12 -0
- package/dist/collections/LotDocumentCollection.d.ts.map +1 -0
- package/dist/collections/LotStockLevelCollection.d.ts +21 -0
- package/dist/collections/LotStockLevelCollection.d.ts.map +1 -0
- package/dist/collections/LotUsageCollection.d.ts +18 -0
- package/dist/collections/LotUsageCollection.d.ts.map +1 -0
- package/dist/collections/index.d.ts +5 -0
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1168 -31
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +2921 -288
- package/dist/models/Lot.d.ts +96 -0
- package/dist/models/Lot.d.ts.map +1 -0
- package/dist/models/LotCorrection.d.ts +55 -0
- package/dist/models/LotCorrection.d.ts.map +1 -0
- package/dist/models/LotDocument.d.ts +45 -0
- package/dist/models/LotDocument.d.ts.map +1 -0
- package/dist/models/LotStockLevel.d.ts +43 -0
- package/dist/models/LotStockLevel.d.ts.map +1 -0
- package/dist/models/LotUsage.d.ts +64 -0
- package/dist/models/LotUsage.d.ts.map +1 -0
- package/dist/models/StockMovement.d.ts +7 -0
- package/dist/models/StockMovement.d.ts.map +1 -1
- package/dist/models/index.d.ts +5 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/services/LotService.d.ts +258 -0
- package/dist/services/LotService.d.ts.map +1 -0
- package/dist/services/StockService.d.ts +25 -2
- package/dist/services/StockService.d.ts.map +1 -1
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/lot-errors.d.ts +44 -0
- package/dist/services/lot-errors.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +1333 -76
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -8
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lot — a traceable batch of material, or a single serialized unit.
|
|
3
|
+
*
|
|
4
|
+
* A lot is the identity that stock carries when it must be traced back to
|
|
5
|
+
* where it came from (a supplier batch code, a serial number, any
|
|
6
|
+
* caller-defined identifier). Stock on hand per lot lives in
|
|
7
|
+
* {@link LotStockLevel}; who consumed the lot lives in {@link LotUsage};
|
|
8
|
+
* every after-the-fact change is a {@link LotCorrection}.
|
|
9
|
+
*
|
|
10
|
+
* **Write only through {@link LotService}.** The service keeps `searchKey`
|
|
11
|
+
* and `identityKey` in sync with `lotNumber`, records the correction trail,
|
|
12
|
+
* and enforces exclusivity for serials. Direct `save()` calls bypass all of
|
|
13
|
+
* that.
|
|
14
|
+
*
|
|
15
|
+
* `lotNumber` is not unique by default: one supplier lot can legitimately
|
|
16
|
+
* arrive on two receipts. `identityKey` is what the database enforces, and
|
|
17
|
+
* it derives from the number only for unique lots and serials (see
|
|
18
|
+
* {@link LotService.receiveLot}).
|
|
19
|
+
*
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
*/
|
|
22
|
+
import { SmrtObject, type SmrtObjectOptions } from '@happyvertical/smrt-core';
|
|
23
|
+
import type { LotKind } from '../types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Options accepted by the {@link Lot} constructor.
|
|
26
|
+
*/
|
|
27
|
+
export interface LotOptions extends SmrtObjectOptions {
|
|
28
|
+
tenantId?: string | null;
|
|
29
|
+
skuId?: string | null;
|
|
30
|
+
kind?: LotKind;
|
|
31
|
+
lotNumber?: string;
|
|
32
|
+
searchKey?: string;
|
|
33
|
+
identityKey?: string;
|
|
34
|
+
uniqueNumber?: boolean;
|
|
35
|
+
receivedQty?: number;
|
|
36
|
+
unit?: string;
|
|
37
|
+
sourceType?: string;
|
|
38
|
+
sourceId?: string;
|
|
39
|
+
attributes?: Record<string, unknown> | string;
|
|
40
|
+
status?: string;
|
|
41
|
+
receivedAt?: Date | string;
|
|
42
|
+
receivedByProfileId?: string | null;
|
|
43
|
+
lastUsedAt?: Date | string | null;
|
|
44
|
+
}
|
|
45
|
+
export declare class Lot extends SmrtObject {
|
|
46
|
+
/** Tenant scope. `null` means the lot is global. */
|
|
47
|
+
tenantId: string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Plain string reference to the catalog Sku. Null when the lot covers
|
|
50
|
+
* uncatalogued material.
|
|
51
|
+
*/
|
|
52
|
+
skuId: string | null;
|
|
53
|
+
/** `lot` for a quantity of material, `serial` for one unit. */
|
|
54
|
+
kind: LotKind;
|
|
55
|
+
/** The identifier as the caller wrote it: batch code, supplier lot, serial number. */
|
|
56
|
+
lotNumber: string;
|
|
57
|
+
/** `lotNumber` trimmed and upper-cased, for case-insensitive lookup. Service-maintained. */
|
|
58
|
+
searchKey: string;
|
|
59
|
+
/** What the database keeps unique. Service-maintained; never write it directly. */
|
|
60
|
+
identityKey: string;
|
|
61
|
+
/** Whether `identityKey` derives from the number (true for serials). */
|
|
62
|
+
uniqueNumber: boolean;
|
|
63
|
+
/** Quantity on the receipt that created the lot (1 for a serial). */
|
|
64
|
+
receivedQty: number;
|
|
65
|
+
/** Unit of measure for `receivedQty`, free text. */
|
|
66
|
+
unit: string;
|
|
67
|
+
/** Receipt attribution, same convention as {@link StockMovement.sourceType}. */
|
|
68
|
+
sourceType: string;
|
|
69
|
+
/** Id of the record that received this lot. */
|
|
70
|
+
sourceId: string;
|
|
71
|
+
/** Free-form properties as a JSON string; see {@link getAttributes}. */
|
|
72
|
+
attributes: string;
|
|
73
|
+
/**
|
|
74
|
+
* Open string. Documented values: `active`, `quarantined`, `consumed`,
|
|
75
|
+
* `void`.
|
|
76
|
+
*/
|
|
77
|
+
status: string;
|
|
78
|
+
/** When the lot arrived. */
|
|
79
|
+
receivedAt: Date;
|
|
80
|
+
/** Profile that received the lot. */
|
|
81
|
+
receivedByProfileId: string | null;
|
|
82
|
+
/**
|
|
83
|
+
* Touched by {@link LotService.recordUsage} and `unlinkUsage` so that
|
|
84
|
+
* concurrent changes to a lot's usage conflict on its revision.
|
|
85
|
+
*/
|
|
86
|
+
lastUsedAt: Date | null;
|
|
87
|
+
constructor(options?: LotOptions);
|
|
88
|
+
/**
|
|
89
|
+
* Parse {@link attributes}. Returns an empty object for invalid JSON so
|
|
90
|
+
* callers need no try/catch.
|
|
91
|
+
*/
|
|
92
|
+
getAttributes(): Record<string, unknown>;
|
|
93
|
+
/** Store attributes from an object or an already-serialized JSON string. */
|
|
94
|
+
setAttributes(value: Record<string, unknown> | string): void;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=Lot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Lot.d.ts","sourceRoot":"","sources":["../../src/models/Lot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAGL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,iBAAiB;IACnD,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,qBAiBa,GAAI,SAAQ,UAAU;IACjC,oDAAoD;IAEpD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;;OAGG;IAKH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE5B,+DAA+D;IAI/D,IAAI,EAAE,OAAO,CAAS;IAEtB,sFAAsF;IAMtF,SAAS,EAAE,MAAM,CAAM;IAEvB,4FAA4F;IAK5F,SAAS,EAAE,MAAM,CAAM;IAEvB,mFAAmF;IAMnF,WAAW,EAAE,MAAM,CAAM;IAEzB,wEAAwE;IAExE,YAAY,EAAE,OAAO,CAAS;IAE9B,qEAAqE;IAErE,WAAW,EAAE,MAAM,CAAO;IAE1B,oDAAoD;IAEpD,IAAI,EAAE,MAAM,CAAM;IAElB,gFAAgF;IAEhF,UAAU,EAAE,MAAM,CAAM;IAExB,+CAA+C;IAE/C,QAAQ,EAAE,MAAM,CAAM;IAEtB,wEAAwE;IAKxE,UAAU,EAAE,MAAM,CAAQ;IAE1B;;;OAGG;IAIH,MAAM,EAAE,MAAM,CAAY;IAE1B,4BAA4B;IAE5B,UAAU,EAAE,IAAI,CAAc;IAE9B,qCAAqC;IAErC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1C;;;OAGG;IAEH,UAAU,EAAE,IAAI,GAAG,IAAI,CAAQ;gBAEnB,OAAO,GAAE,UAAe;IAmCpC;;;OAGG;IACH,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYxC,4EAA4E;IAC5E,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI;CAI7D"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LotCorrection — append-only record of an after-the-fact change to a lot.
|
|
3
|
+
*
|
|
4
|
+
* Fixing a mistyped lot number, editing an attribute, changing status,
|
|
5
|
+
* unlinking a usage or detaching a document each write exactly one
|
|
6
|
+
* correction with the old value, the new value, who did it and why. The
|
|
7
|
+
* reason is mandatory. Like {@link StockMovement}, rows are never updated
|
|
8
|
+
* or deleted. Write only through {@link LotService}.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import { SmrtObject, type SmrtObjectOptions } from '@happyvertical/smrt-core';
|
|
13
|
+
import type { LotCorrectionKind } from '../types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Options accepted by the {@link LotCorrection} constructor.
|
|
16
|
+
*/
|
|
17
|
+
export interface LotCorrectionOptions extends SmrtObjectOptions {
|
|
18
|
+
tenantId?: string | null;
|
|
19
|
+
lotId?: string;
|
|
20
|
+
kind?: LotCorrectionKind;
|
|
21
|
+
field?: string;
|
|
22
|
+
oldValue?: string;
|
|
23
|
+
newValue?: string;
|
|
24
|
+
reason?: string;
|
|
25
|
+
usageId?: string | null;
|
|
26
|
+
documentId?: string | null;
|
|
27
|
+
actorProfileId?: string | null;
|
|
28
|
+
correctedAt?: Date | string;
|
|
29
|
+
}
|
|
30
|
+
export declare class LotCorrection extends SmrtObject {
|
|
31
|
+
/** Tenant scope. `null` means the correction is global. */
|
|
32
|
+
tenantId: string | null;
|
|
33
|
+
/** The lot that was corrected. */
|
|
34
|
+
lotId: string;
|
|
35
|
+
/** What was corrected. */
|
|
36
|
+
kind: LotCorrectionKind;
|
|
37
|
+
/** The attribute key for `attribute` corrections; empty otherwise. */
|
|
38
|
+
field: string;
|
|
39
|
+
/** The value before the correction. */
|
|
40
|
+
oldValue: string;
|
|
41
|
+
/** The value after the correction. */
|
|
42
|
+
newValue: string;
|
|
43
|
+
/** Why the correction was made. Required, at most 1000 characters. */
|
|
44
|
+
reason: string;
|
|
45
|
+
/** The {@link LotUsage} unlinked, for `unlink` corrections. */
|
|
46
|
+
usageId: string | null;
|
|
47
|
+
/** The {@link LotDocument} detached, for `document_detach` corrections. */
|
|
48
|
+
documentId: string | null;
|
|
49
|
+
/** Profile that made the correction. */
|
|
50
|
+
actorProfileId: string | null;
|
|
51
|
+
/** When the correction was made. */
|
|
52
|
+
correctedAt: Date;
|
|
53
|
+
constructor(options?: LotCorrectionOptions);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=LotCorrection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LotCorrection.d.ts","sourceRoot":"","sources":["../../src/models/LotCorrection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAIL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGrD;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CAC7B;AAED,qBAUa,aAAc,SAAQ,UAAU;IAC3C,2DAA2D;IAE3D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,kCAAkC;IAQlC,KAAK,EAAE,MAAM,CAAM;IAEnB,0BAA0B;IAE1B,IAAI,EAAE,iBAAiB,CAAe;IAEtC,sEAAsE;IAEtE,KAAK,EAAE,MAAM,CAAM;IAEnB,uCAAuC;IAEvC,QAAQ,EAAE,MAAM,CAAM;IAEtB,sCAAsC;IAEtC,QAAQ,EAAE,MAAM,CAAM;IAEtB,sEAAsE;IAOtE,MAAM,EAAE,MAAM,CAAM;IAEpB,+DAA+D;IAE/D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE9B,2EAA2E;IAE3E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEjC,wCAAwC;IAExC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IAErC,oCAAoC;IAEpC,WAAW,EAAE,IAAI,CAAc;gBAEnB,OAAO,GAAE,oBAAyB;CAoB/C"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LotDocument — a document attached to a lot (a certificate, a test
|
|
3
|
+
* report, a delivery note).
|
|
4
|
+
*
|
|
5
|
+
* The file itself is an Asset from `@happyvertical/smrt-assets`, referenced
|
|
6
|
+
* by id; this package takes no dependency on it. Detaching sets
|
|
7
|
+
* `detachedAt` and writes a {@link LotCorrection}; the row stays. Write
|
|
8
|
+
* only through {@link LotService}.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import { SmrtObject, type SmrtObjectOptions } from '@happyvertical/smrt-core';
|
|
13
|
+
/**
|
|
14
|
+
* Options accepted by the {@link LotDocument} constructor.
|
|
15
|
+
*/
|
|
16
|
+
export interface LotDocumentOptions extends SmrtObjectOptions {
|
|
17
|
+
tenantId?: string | null;
|
|
18
|
+
lotId?: string;
|
|
19
|
+
assetId?: string;
|
|
20
|
+
role?: string;
|
|
21
|
+
attachedAt?: Date | string;
|
|
22
|
+
attachedByProfileId?: string | null;
|
|
23
|
+
detachedAt?: Date | string | null;
|
|
24
|
+
detachedByProfileId?: string | null;
|
|
25
|
+
}
|
|
26
|
+
export declare class LotDocument extends SmrtObject {
|
|
27
|
+
/** Tenant scope. `null` means the document link is global. */
|
|
28
|
+
tenantId: string | null;
|
|
29
|
+
/** The lot the document belongs to. */
|
|
30
|
+
lotId: string;
|
|
31
|
+
/** The stored file. */
|
|
32
|
+
assetId: string;
|
|
33
|
+
/** What the document is for, free text, for example `certificate`. */
|
|
34
|
+
role: string;
|
|
35
|
+
/** When the document was attached. */
|
|
36
|
+
attachedAt: Date;
|
|
37
|
+
/** Profile that attached it. */
|
|
38
|
+
attachedByProfileId: string | null;
|
|
39
|
+
/** When it was detached, if it was. */
|
|
40
|
+
detachedAt: Date | null;
|
|
41
|
+
/** Profile that detached it. */
|
|
42
|
+
detachedByProfileId: string | null;
|
|
43
|
+
constructor(options?: LotDocumentOptions);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=LotDocument.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LotDocument.d.ts","sourceRoot":"","sources":["../../src/models/LotDocument.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAIL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAIlC;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IAClC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAKD,qBAQa,WAAY,SAAQ,UAAU;IACzC,8DAA8D;IAE9D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,uCAAuC;IAQvC,KAAK,EAAE,MAAM,CAAM;IAEnB,uBAAuB;IAEvB,OAAO,EAAE,MAAM,CAAM;IAErB,sEAAsE;IAEtE,IAAI,EAAE,MAAM,CAAiB;IAE7B,sCAAsC;IAEtC,UAAU,EAAE,IAAI,CAAc;IAE9B,gCAAgC;IAEhC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1C,uCAAuC;IAEvC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE/B,gCAAgC;IAEhC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAQ;gBAE9B,OAAO,GAAE,kBAAuB;CAgB7C"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LotStockLevel — materialized quantity at a `(lotId, locationId, state)`
|
|
3
|
+
* tuple.
|
|
4
|
+
*
|
|
5
|
+
* The per-lot companion to {@link StockLevel}: when a {@link StockService}
|
|
6
|
+
* mutation is given a `lotId`, it applies the same deltas here as it does
|
|
7
|
+
* to the SKU-level row. It is a separate table so `StockLevel`'s unique
|
|
8
|
+
* key never changes.
|
|
9
|
+
*
|
|
10
|
+
* **Do not call `create()` or `save()` on LotStockLevel directly.** Only
|
|
11
|
+
* {@link StockService} writes it, in the same transaction as the movement.
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
import { SmrtObject, type SmrtObjectOptions } from '@happyvertical/smrt-core';
|
|
16
|
+
import type { StockState } from '../types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Options accepted by the {@link LotStockLevel} constructor.
|
|
19
|
+
*/
|
|
20
|
+
export interface LotStockLevelOptions extends SmrtObjectOptions {
|
|
21
|
+
tenantId?: string | null;
|
|
22
|
+
lotId?: string;
|
|
23
|
+
skuId?: string;
|
|
24
|
+
locationId?: string;
|
|
25
|
+
state?: StockState;
|
|
26
|
+
qty?: number;
|
|
27
|
+
}
|
|
28
|
+
export declare class LotStockLevel extends SmrtObject {
|
|
29
|
+
/** Tenant scope. `null` means the level row is global. */
|
|
30
|
+
tenantId: string | null;
|
|
31
|
+
/** The {@link Lot} this row tracks. */
|
|
32
|
+
lotId: string;
|
|
33
|
+
/** Plain string reference to the Sku, copied from the movement. */
|
|
34
|
+
skuId: string;
|
|
35
|
+
/** Plain string reference to the {@link InventoryLocation}. */
|
|
36
|
+
locationId: string;
|
|
37
|
+
/** Logical state, same vocabulary as {@link StockLevel.state}. */
|
|
38
|
+
state: StockState;
|
|
39
|
+
/** Current quantity of the lot in this state at this location. */
|
|
40
|
+
qty: number;
|
|
41
|
+
constructor(options?: LotStockLevelOptions);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=LotStockLevel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LotStockLevel.d.ts","sourceRoot":"","sources":["../../src/models/LotStockLevel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAGL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBASa,aAAc,SAAQ,UAAU;IAC3C,0DAA0D;IAE1D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,uCAAuC;IAQvC,KAAK,EAAE,MAAM,CAAM;IAEnB,mEAAmE;IAEnE,KAAK,EAAE,MAAM,CAAM;IAEnB,+DAA+D;IAE/D,UAAU,EAAE,MAAM,CAAM;IAExB,kEAAkE;IAMlE,KAAK,EAAE,UAAU,CAAe;IAEhC,kEAAkE;IAElE,GAAG,EAAE,MAAM,CAAO;gBAEN,OAAO,GAAE,oBAAyB;CAS/C"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LotUsage — one edge of the trace graph: a lot used by a consumer.
|
|
3
|
+
*
|
|
4
|
+
* The consumer is cross-package attribution (`consumerType` +
|
|
5
|
+
* `consumerId`, for example `'ProductionOrder'` and its id). When the
|
|
6
|
+
* consumer is itself another lot (an assembly), use `consumerType: 'Lot'`
|
|
7
|
+
* so forward and backward traces can walk the lineage.
|
|
8
|
+
*
|
|
9
|
+
* Rows are never deleted. Correcting a mistaken link flips `status` to
|
|
10
|
+
* `unlinked` and writes a {@link LotCorrection}; the original edge stays
|
|
11
|
+
* on record. Write only through {@link LotService}.
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
import { SmrtObject, type SmrtObjectOptions } from '@happyvertical/smrt-core';
|
|
16
|
+
import type { LotUsageStatus } from '../types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Options accepted by the {@link LotUsage} constructor.
|
|
19
|
+
*/
|
|
20
|
+
export interface LotUsageOptions extends SmrtObjectOptions {
|
|
21
|
+
tenantId?: string | null;
|
|
22
|
+
lotId?: string;
|
|
23
|
+
consumerType?: string;
|
|
24
|
+
consumerId?: string;
|
|
25
|
+
qty?: number | null;
|
|
26
|
+
unit?: string;
|
|
27
|
+
status?: LotUsageStatus;
|
|
28
|
+
linkedAt?: Date | string;
|
|
29
|
+
linkedByProfileId?: string | null;
|
|
30
|
+
unlinkedAt?: Date | string | null;
|
|
31
|
+
unlinkedByProfileId?: string | null;
|
|
32
|
+
unlinkReason?: string;
|
|
33
|
+
movementId?: string | null;
|
|
34
|
+
}
|
|
35
|
+
export declare class LotUsage extends SmrtObject {
|
|
36
|
+
/** Tenant scope. `null` means the usage is global. */
|
|
37
|
+
tenantId: string | null;
|
|
38
|
+
/** The lot that was used. */
|
|
39
|
+
lotId: string;
|
|
40
|
+
/** Kind of consumer, for example `'ProductionOrder'`; `'Lot'` for an assembly. */
|
|
41
|
+
consumerType: string;
|
|
42
|
+
/** Id of the consumer. */
|
|
43
|
+
consumerId: string;
|
|
44
|
+
/** Quantity used; null means unspecified (the whole lot, or not tracked). */
|
|
45
|
+
qty: number | null;
|
|
46
|
+
/** Unit of measure for `qty`. */
|
|
47
|
+
unit: string;
|
|
48
|
+
/** `active`, or `unlinked` once a correction removed the link. */
|
|
49
|
+
status: LotUsageStatus;
|
|
50
|
+
/** When the usage was recorded. */
|
|
51
|
+
linkedAt: Date;
|
|
52
|
+
/** Profile that recorded the usage. */
|
|
53
|
+
linkedByProfileId: string | null;
|
|
54
|
+
/** When the link was removed, if it was. */
|
|
55
|
+
unlinkedAt: Date | null;
|
|
56
|
+
/** Profile that removed the link. */
|
|
57
|
+
unlinkedByProfileId: string | null;
|
|
58
|
+
/** Why the link was removed. */
|
|
59
|
+
unlinkReason: string;
|
|
60
|
+
/** Optional StockMovement that took this quantity out. */
|
|
61
|
+
movementId: string | null;
|
|
62
|
+
constructor(options?: LotUsageOptions);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=LotUsage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LotUsage.d.ts","sourceRoot":"","sources":["../../src/models/LotUsage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAIL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IAClC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAKD,qBAiBa,QAAS,SAAQ,UAAU;IACtC,sDAAsD;IAEtD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,6BAA6B;IAQ7B,KAAK,EAAE,MAAM,CAAM;IAEnB,kFAAkF;IAElF,YAAY,EAAE,MAAM,CAAM;IAE1B,0BAA0B;IAE1B,UAAU,EAAE,MAAM,CAAM;IAExB,6EAA6E;IAE7E,GAAG,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1B,iCAAiC;IAEjC,IAAI,EAAE,MAAM,CAAM;IAElB,kEAAkE;IAElE,MAAM,EAAE,cAAc,CAAY;IAElC,mCAAmC;IAEnC,QAAQ,EAAE,IAAI,CAAc;IAE5B,uCAAuC;IAEvC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAExC,4CAA4C;IAE5C,UAAU,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE/B,qCAAqC;IAErC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1C,gCAAgC;IAEhC,YAAY,EAAE,MAAM,CAAM;IAE1B,0DAA0D;IAK1D,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;gBAErB,OAAO,GAAE,eAAoB;CAuB1C"}
|
|
@@ -29,6 +29,7 @@ export interface StockMovementOptions extends SmrtObjectOptions {
|
|
|
29
29
|
tenantId?: string | null;
|
|
30
30
|
skuId?: string;
|
|
31
31
|
locationId?: string;
|
|
32
|
+
lotId?: string | null;
|
|
32
33
|
fromState?: StockState | null;
|
|
33
34
|
toState?: StockState | null;
|
|
34
35
|
qty?: number;
|
|
@@ -46,6 +47,12 @@ export declare class StockMovement extends SmrtObject {
|
|
|
46
47
|
skuId: string;
|
|
47
48
|
/** Plain string reference to the {@link InventoryLocation} being mutated. */
|
|
48
49
|
locationId: string;
|
|
50
|
+
/**
|
|
51
|
+
* Plain string reference to the {@link Lot} that moved; null when the
|
|
52
|
+
* movement is not tracked by lot. Nullable and additive: existing rows
|
|
53
|
+
* and SKU-level callers are unaffected.
|
|
54
|
+
*/
|
|
55
|
+
lotId: string | null;
|
|
49
56
|
/**
|
|
50
57
|
* Origin state for transitions (e.g. `available` → `allocated` for a
|
|
51
58
|
* reservation). `null` indicates "no origin" — used when stock enters
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StockMovement.d.ts","sourceRoot":"","sources":["../../src/models/StockMovement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAGL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CAC5B;AAED,
|
|
1
|
+
{"version":3,"file":"StockMovement.d.ts","sourceRoot":"","sources":["../../src/models/StockMovement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAGL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CAC5B;AAED,qBAoBa,aAAc,SAAQ,UAAU;IAC3C,yDAAyD;IAEzD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,6DAA6D;IAE7D,KAAK,EAAE,MAAM,CAAM;IAEnB,6EAA6E;IAE7E,UAAU,EAAE,MAAM,CAAM;IAExB;;;;OAIG;IAKH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE5B;;;;OAIG;IAIH,SAAS,EAAE,UAAU,GAAG,IAAI,CAAQ;IAEpC;;;OAGG;IAEH,OAAO,EAAE,UAAU,GAAG,IAAI,CAAQ;IAElC,4EAA4E;IAE5E,GAAG,EAAE,MAAM,CAAO;IAElB;;;;OAIG;IAKH,UAAU,EAAE,mBAAmB,CAAgB;IAE/C;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAM;IAExB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAM;IAEtB,+EAA+E;IAE/E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IAErC,kDAAkD;IAElD,IAAI,EAAE,MAAM,CAAM;IAElB;;;OAGG;IAEH,UAAU,EAAE,IAAI,CAAc;gBAElB,OAAO,GAAE,oBAAyB;CAsB/C"}
|
package/dist/models/index.d.ts
CHANGED
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import '../__smrt-register__.js';
|
|
12
12
|
export { InventoryLocation, type InventoryLocationOptions, } from './InventoryLocation.js';
|
|
13
|
+
export { Lot, type LotOptions } from './Lot.js';
|
|
14
|
+
export { LotCorrection, type LotCorrectionOptions } from './LotCorrection.js';
|
|
15
|
+
export { LotDocument, type LotDocumentOptions } from './LotDocument.js';
|
|
16
|
+
export { LotStockLevel, type LotStockLevelOptions } from './LotStockLevel.js';
|
|
17
|
+
export { LotUsage, type LotUsageOptions } from './LotUsage.js';
|
|
13
18
|
export { StockLevel, type StockLevelOptions } from './StockLevel.js';
|
|
14
19
|
export { StockMovement, type StockMovementOptions } from './StockMovement.js';
|
|
15
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,yBAAyB,CAAC;AAEjC,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,yBAAyB,CAAC;AAEjC,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LotService — the only sanctioned way to create and change lots.
|
|
3
|
+
*
|
|
4
|
+
* A lot is an identity for traceable stock: a batch code, a supplier lot, a
|
|
5
|
+
* serial number. This service records lots as they arrive, links them to
|
|
6
|
+
* what consumed them, keeps documents (certificates, reports) attached, and
|
|
7
|
+
* answers "where did this come from, and where did it go". Every
|
|
8
|
+
* after-the-fact change is a {@link LotCorrection} with a mandatory reason,
|
|
9
|
+
* so a wrong number or a wrong link is fixed on the record, not erased.
|
|
10
|
+
*
|
|
11
|
+
* **Stock is separate.** Receiving a lot creates the identity only; it moves
|
|
12
|
+
* no quantity. Compose the two in one transaction so the lot and its stock
|
|
13
|
+
* land together or not at all:
|
|
14
|
+
*
|
|
15
|
+
* ```typescript
|
|
16
|
+
* await stock.withTransaction(async (tx) => {
|
|
17
|
+
* const lots = await createLotService({ db: tx.db });
|
|
18
|
+
* const lot = await lots.receiveLot({ lotNumber: 'B-1042', skuId });
|
|
19
|
+
* await tx.receive(skuId, locationId, 40, { lotId: lot.id });
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* **Authorization is the caller's.** Nothing here checks who may receive,
|
|
24
|
+
* correct or unlink; pass `actorProfileId` so the trail says who did.
|
|
25
|
+
*
|
|
26
|
+
* **Concurrency.** Changes that matter to a lot (usage, unlink, number,
|
|
27
|
+
* attribute and status corrections) `save()` the lot row, so two concurrent
|
|
28
|
+
* changes to one lot conflict on its revision and the loser's transaction
|
|
29
|
+
* rolls back; retry it.
|
|
30
|
+
*
|
|
31
|
+
* @packageDocumentation
|
|
32
|
+
*/
|
|
33
|
+
import { type DatabaseConfig } from '@happyvertical/smrt-core';
|
|
34
|
+
import { LotCollection, LotCorrectionCollection, LotDocumentCollection, LotUsageCollection, StockMovementCollection } from '../collections/index.js';
|
|
35
|
+
import type { Lot } from '../models/Lot.js';
|
|
36
|
+
import type { LotCorrection } from '../models/LotCorrection.js';
|
|
37
|
+
import type { LotDocument } from '../models/LotDocument.js';
|
|
38
|
+
import type { LotUsage } from '../models/LotUsage.js';
|
|
39
|
+
import type { StockMovement } from '../models/StockMovement.js';
|
|
40
|
+
import type { LotKind } from '../types.js';
|
|
41
|
+
/** Options accepted by the {@link LotService} factory. */
|
|
42
|
+
export interface LotServiceOptions {
|
|
43
|
+
/** Same shapes as {@link StockServiceOptions.db}; pass `tx.db` to join a transaction. */
|
|
44
|
+
db: DatabaseConfig;
|
|
45
|
+
}
|
|
46
|
+
/** Input to {@link LotService.receiveLot}. */
|
|
47
|
+
export interface ReceiveLotInput {
|
|
48
|
+
/** Batch code, supplier lot or serial number as the caller has it. */
|
|
49
|
+
lotNumber: string;
|
|
50
|
+
/** Catalog Sku the lot is of; omit for uncatalogued material. */
|
|
51
|
+
skuId?: string | null;
|
|
52
|
+
/** `lot` (default) or `serial`. A serial is always unique with quantity 1. */
|
|
53
|
+
kind?: LotKind;
|
|
54
|
+
/**
|
|
55
|
+
* Make the number unique per SKU: a second receipt of the same number
|
|
56
|
+
* throws {@link DuplicateLotError}. Default false for lots, always true
|
|
57
|
+
* for serials. Without it one supplier lot may be received more than once.
|
|
58
|
+
*/
|
|
59
|
+
unique?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Makes the receipt retry-safe: repeating a call with the same key
|
|
62
|
+
* returns the lot the first call made instead of creating another.
|
|
63
|
+
* Ignored for unique lots and serials, whose number is the identity. A
|
|
64
|
+
* repeated key returns the first lot as it was, even when the other fields
|
|
65
|
+
* of the repeat differ.
|
|
66
|
+
*/
|
|
67
|
+
idempotencyKey?: string;
|
|
68
|
+
receivedQty?: number;
|
|
69
|
+
unit?: string;
|
|
70
|
+
sourceType?: string;
|
|
71
|
+
sourceId?: string;
|
|
72
|
+
attributes?: Record<string, unknown>;
|
|
73
|
+
/** Default `active`. */
|
|
74
|
+
status?: string;
|
|
75
|
+
receivedAt?: Date;
|
|
76
|
+
actorProfileId?: string | null;
|
|
77
|
+
}
|
|
78
|
+
/** Who made a correction, and why. `reason` is required. */
|
|
79
|
+
export interface LotChangeOptions {
|
|
80
|
+
reason: string;
|
|
81
|
+
actorProfileId?: string | null;
|
|
82
|
+
}
|
|
83
|
+
/** Input to {@link LotService.recordUsage}. */
|
|
84
|
+
export interface RecordUsageInput {
|
|
85
|
+
/** What used the lot, e.g. `'ProductionOrder'`; `'Lot'` for an assembly. */
|
|
86
|
+
consumerType: string;
|
|
87
|
+
consumerId: string;
|
|
88
|
+
/** Quantity used; omit when unspecified or the whole lot. */
|
|
89
|
+
qty?: number | null;
|
|
90
|
+
unit?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Refuse when a different consumer already has an active usage
|
|
93
|
+
* ({@link LotInUseError}). Default true for serials, false for lots.
|
|
94
|
+
*/
|
|
95
|
+
exclusive?: boolean;
|
|
96
|
+
/** Optional StockMovement that took the quantity out. */
|
|
97
|
+
movementId?: string | null;
|
|
98
|
+
actorProfileId?: string | null;
|
|
99
|
+
}
|
|
100
|
+
/** Input to {@link LotService.attachDocument}. */
|
|
101
|
+
export interface AttachDocumentInput {
|
|
102
|
+
/** Id of the stored file (an Asset from `@happyvertical/smrt-assets`). */
|
|
103
|
+
assetId: string;
|
|
104
|
+
/** Default `certificate`. */
|
|
105
|
+
role?: string;
|
|
106
|
+
actorProfileId?: string | null;
|
|
107
|
+
}
|
|
108
|
+
/** Options for {@link LotService.traceForward} and {@link LotService.traceBack}. */
|
|
109
|
+
export interface TraceOptions {
|
|
110
|
+
/** Include usages that were unlinked, and detached documents. Default false. */
|
|
111
|
+
includeUnlinked?: boolean;
|
|
112
|
+
/** How many levels of assembly to follow. Default 10. */
|
|
113
|
+
depth?: number;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* One lot in a trace.
|
|
117
|
+
*
|
|
118
|
+
* In {@link LotService.traceForward}, `usages` are every use of `lot` and
|
|
119
|
+
* `children` are the lots that consumed it (consumer type `Lot`). In
|
|
120
|
+
* {@link LotService.traceBack}, `usages` are the edges from the queried
|
|
121
|
+
* consumer to `lot` and `children` are the lots that went into `lot`.
|
|
122
|
+
*/
|
|
123
|
+
export interface TraceNode {
|
|
124
|
+
lot: Lot;
|
|
125
|
+
usages: LotUsage[];
|
|
126
|
+
/** Stock movements that carried this lot, oldest first. */
|
|
127
|
+
movements: StockMovement[];
|
|
128
|
+
documents: LotDocument[];
|
|
129
|
+
children: TraceNode[];
|
|
130
|
+
}
|
|
131
|
+
export declare class LotService {
|
|
132
|
+
/** The database this service is bound to; `tx.db` inside {@link withTransaction}. */
|
|
133
|
+
readonly db: DatabaseConfig;
|
|
134
|
+
readonly lots: LotCollection;
|
|
135
|
+
readonly usages: LotUsageCollection;
|
|
136
|
+
readonly corrections: LotCorrectionCollection;
|
|
137
|
+
readonly documents: LotDocumentCollection;
|
|
138
|
+
readonly movements: StockMovementCollection;
|
|
139
|
+
private readonly inTransaction;
|
|
140
|
+
private constructor();
|
|
141
|
+
/** Internal factory — prefer {@link createLotService}. */
|
|
142
|
+
static create(options: LotServiceOptions): Promise<LotService>;
|
|
143
|
+
/**
|
|
144
|
+
* Run `work` in one database transaction with a tx-bound service. Nested
|
|
145
|
+
* calls join the outer transaction. Same pattern as
|
|
146
|
+
* {@link StockService.withTransaction}.
|
|
147
|
+
*
|
|
148
|
+
* A service built on a transaction handle (`createLotService({ db: tx.db })`)
|
|
149
|
+
* opens a savepoint where the engine has them (PostgreSQL, SQLite). Where it
|
|
150
|
+
* does not (DuckDB) the handle refuses with `NestedTransactionError` before
|
|
151
|
+
* running anything, and `work` runs on the current handle instead, still
|
|
152
|
+
* inside the caller's transaction.
|
|
153
|
+
*/
|
|
154
|
+
withTransaction<T>(work: (tx: LotService) => Promise<T>): Promise<T>;
|
|
155
|
+
/**
|
|
156
|
+
* Open a transaction (or savepoint) on this service's handle and run `work`
|
|
157
|
+
* in it, even when already tx-bound. Falls back to the current handle when
|
|
158
|
+
* the engine cannot nest.
|
|
159
|
+
*/
|
|
160
|
+
private scoped;
|
|
161
|
+
/**
|
|
162
|
+
* Record a lot or serial. Creates the identity only; it moves no stock
|
|
163
|
+
* (see the module notes for composing with {@link StockService}).
|
|
164
|
+
*
|
|
165
|
+
* - Unique lots and all serials are keyed by SKU and number: receiving the
|
|
166
|
+
* same number again throws {@link DuplicateLotError}.
|
|
167
|
+
* - Otherwise a repeated `idempotencyKey` returns the lot already made.
|
|
168
|
+
* - With neither, every call makes a new lot, even for a number already
|
|
169
|
+
* seen: one supplier lot can arrive on two receipts.
|
|
170
|
+
*/
|
|
171
|
+
receiveLot(input: ReceiveLotInput): Promise<Lot>;
|
|
172
|
+
private resolveExisting;
|
|
173
|
+
private findByIdentity;
|
|
174
|
+
/**
|
|
175
|
+
* Fix a mistyped lot number. Recomputes the lookup key and, for unique
|
|
176
|
+
* lots and serials, the identity (a clash throws
|
|
177
|
+
* {@link DuplicateLotError}). Refuses a change to the same number.
|
|
178
|
+
*/
|
|
179
|
+
correctLotNumber(lotId: string, lotNumber: string, options: LotChangeOptions): Promise<{
|
|
180
|
+
lot: Lot;
|
|
181
|
+
correction: LotCorrection;
|
|
182
|
+
}>;
|
|
183
|
+
/**
|
|
184
|
+
* Change attributes. Each key in `patch` is set to its value, or removed
|
|
185
|
+
* when `null`. One correction is written per key that actually changes;
|
|
186
|
+
* refuses when none does. Values are stored as JSON.
|
|
187
|
+
*/
|
|
188
|
+
correctAttributes(lotId: string, patch: Record<string, unknown | null>, options: LotChangeOptions): Promise<{
|
|
189
|
+
lot: Lot;
|
|
190
|
+
corrections: LotCorrection[];
|
|
191
|
+
}>;
|
|
192
|
+
/** Change status (for example to `quarantined`). Refuses an unchanged status. */
|
|
193
|
+
setStatus(lotId: string, status: string, options: LotChangeOptions): Promise<{
|
|
194
|
+
lot: Lot;
|
|
195
|
+
correction: LotCorrection;
|
|
196
|
+
}>;
|
|
197
|
+
/**
|
|
198
|
+
* Record that a consumer used the lot. Repeating the call for the same
|
|
199
|
+
* consumer returns the active usage already on record, unchanged: a
|
|
200
|
+
* different `qty` or `movementId` on the repeat is ignored. For an exclusive
|
|
201
|
+
* lot (serials by default) a second consumer throws
|
|
202
|
+
* {@link LotInUseError}. The lot row is saved so two concurrent usages
|
|
203
|
+
* conflict on its revision instead of both landing.
|
|
204
|
+
*/
|
|
205
|
+
recordUsage(lotId: string, input: RecordUsageInput): Promise<LotUsage>;
|
|
206
|
+
/**
|
|
207
|
+
* Remove a mistaken usage. The row stays, marked `unlinked`, and a
|
|
208
|
+
* correction records who removed it and why. Refuses a usage that is
|
|
209
|
+
* already unlinked.
|
|
210
|
+
*/
|
|
211
|
+
unlinkUsage(usageId: string, options: LotChangeOptions): Promise<{
|
|
212
|
+
usage: LotUsage;
|
|
213
|
+
correction: LotCorrection;
|
|
214
|
+
}>;
|
|
215
|
+
/** Attach a stored file to the lot. Repeating the same asset and role returns the active link. */
|
|
216
|
+
attachDocument(lotId: string, input: AttachDocumentInput): Promise<LotDocument>;
|
|
217
|
+
/** Detach a document. The link stays on record with `detachedAt` set. */
|
|
218
|
+
detachDocument(documentId: string, options: LotChangeOptions): Promise<{
|
|
219
|
+
document: LotDocument;
|
|
220
|
+
correction: LotCorrection;
|
|
221
|
+
}>;
|
|
222
|
+
/** Every correction to the lot, oldest first. */
|
|
223
|
+
history(lotId: string): Promise<LotCorrection[]>;
|
|
224
|
+
/**
|
|
225
|
+
* Where a lot went: its usages, movements and documents, plus (as
|
|
226
|
+
* `children`) the lots that consumed it, followed up to `depth` levels.
|
|
227
|
+
*
|
|
228
|
+
* Cost: each distinct lot in the trace takes four queries (usages,
|
|
229
|
+
* movements, documents, and the lot itself). A lot reached by two paths
|
|
230
|
+
* (a diamond) is expanded once and the same node object appears under both
|
|
231
|
+
* parents. Bound large graphs with `depth`.
|
|
232
|
+
*/
|
|
233
|
+
traceForward(lotId: string, options?: TraceOptions): Promise<TraceNode>;
|
|
234
|
+
private forwardNode;
|
|
235
|
+
private expandForward;
|
|
236
|
+
/**
|
|
237
|
+
* Where a consumer's material came from: one node per lot it used, each
|
|
238
|
+
* with (as `children`) the lots that went into that lot when it was
|
|
239
|
+
* itself an assembly (consumer `('Lot', lotId)`), up to `depth` levels.
|
|
240
|
+
*
|
|
241
|
+
* Cost: one usage query per consumer visited plus, per lot, the lot,
|
|
242
|
+
* movements and documents queries. A lot reached by two paths is expanded
|
|
243
|
+
* once and shared. Bound large graphs with `depth`.
|
|
244
|
+
*/
|
|
245
|
+
traceBack(consumerType: string, consumerId: string, options?: TraceOptions): Promise<TraceNode[]>;
|
|
246
|
+
private backNodes;
|
|
247
|
+
private expandBack;
|
|
248
|
+
private nodeBase;
|
|
249
|
+
private atomically;
|
|
250
|
+
private requireLot;
|
|
251
|
+
private writeCorrection;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Convenience factory. Returns a {@link LotService} sharing the given
|
|
255
|
+
* database with its internal collections.
|
|
256
|
+
*/
|
|
257
|
+
export declare function createLotService(options: LotServiceOptions): Promise<LotService>;
|
|
258
|
+
//# sourceMappingURL=LotService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LotService.d.ts","sourceRoot":"","sources":["../../src/services/LotService.ts"],"names":[],"mappings":"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"}
|