@campfire-interactive/master-data-client 4.11.0 → 4.12.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/dist/client.d.ts +6 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +9 -0
- package/dist/client.js.map +1 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +5 -2
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/ownership.d.ts +21 -0
- package/dist/ownership.d.ts.map +1 -0
- package/dist/ownership.js +36 -0
- package/dist/ownership.js.map +1 -0
- package/dist/quoteAsks.d.ts +66 -0
- package/dist/quoteAsks.d.ts.map +1 -0
- package/dist/quoteAsks.js +103 -0
- package/dist/quoteAsks.js.map +1 -0
- package/dist/quoteLines.d.ts +91 -0
- package/dist/quoteLines.d.ts.map +1 -0
- package/dist/quoteLines.js +147 -0
- package/dist/quoteLines.js.map +1 -0
- package/dist/quotes.d.ts +10 -5
- package/dist/quotes.d.ts.map +1 -1
- package/dist/quotes.js +10 -5
- package/dist/quotes.js.map +1 -1
- package/dist/types.d.ts +312 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/partFamilies.d.ts +0 -12
- package/dist/partFamilies.d.ts.map +0 -1
- package/dist/partFamilies.js +0 -45
- package/dist/partFamilies.js.map +0 -1
- package/dist/rateLibraries.d.ts +0 -25
- package/dist/rateLibraries.d.ts.map +0 -1
- package/dist/rateLibraries.js +0 -132
- package/dist/rateLibraries.js.map +0 -1
- package/dist/suppliers.d.ts +0 -14
- package/dist/suppliers.d.ts.map +0 -1
- package/dist/suppliers.js +0 -84
- package/dist/suppliers.js.map +0 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QuoteLineResource = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Quote lines — the finished goods on a quote.
|
|
6
|
+
*
|
|
7
|
+
* A quote is MULTI-PART: it is the document the OEM receives and it carries one
|
|
8
|
+
* line per finished good, each with its own volume, cost and price. See the
|
|
9
|
+
* nextgen ADR `2026-08-05-multi-part-quotes.md`.
|
|
10
|
+
*
|
|
11
|
+
* Two things to know before using this:
|
|
12
|
+
*
|
|
13
|
+
* 1. **`Quote.partId` is now a derived mirror** of these lines and is
|
|
14
|
+
* deprecated. It reflects the FIRST line only, so it is lossy the moment a
|
|
15
|
+
* quote has more than one. Read `lines` here instead. It keeps working for
|
|
16
|
+
* the whole deprecation window — including writes, which transparently
|
|
17
|
+
* maintain the quote's single line — and is dropped in a later major.
|
|
18
|
+
*
|
|
19
|
+
* 2. **Never sum lines across competing quotes.** When an OEM asks for several
|
|
20
|
+
* competing groupings of the same parts, those are alternatives, not
|
|
21
|
+
* additions. `rollUp` covers ONE quote; anything aggregating across a round
|
|
22
|
+
* must dedupe by part.
|
|
23
|
+
*
|
|
24
|
+
* Cost is DERIVED, never authored: it reaches a line only through
|
|
25
|
+
* {@link setEffectiveCost}, published by whichever engine resolved it. There is
|
|
26
|
+
* no authored-cost field, deliberately — the earlier design had one whose only
|
|
27
|
+
* writer was a human, so it could store a per-grouping cost but never produce
|
|
28
|
+
* one, and went stale unnoticed on the next re-cost.
|
|
29
|
+
*/
|
|
30
|
+
class QuoteLineResource {
|
|
31
|
+
http;
|
|
32
|
+
constructor(http) {
|
|
33
|
+
this.http = http;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The quote's lines, each with resolved `terms` (volume / cost / price plus
|
|
37
|
+
* which tier each came from), and the quote-level `rollUp`.
|
|
38
|
+
*/
|
|
39
|
+
async list(quoteId) {
|
|
40
|
+
return this.http.request({
|
|
41
|
+
method: 'GET',
|
|
42
|
+
path: `/v1/quotes/${encodeURIComponent(quoteId)}/lines`,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The resolved line sets for MANY quotes, in one round trip.
|
|
47
|
+
*
|
|
48
|
+
* Use this instead of looping {@link list} whenever you read volume off a set
|
|
49
|
+
* of quotes — a per-quote fan-out is slow and, against a hub holding one warm
|
|
50
|
+
* instance, manufactures cold starts.
|
|
51
|
+
*
|
|
52
|
+
* Chunk to 200 ids per call (the server rejects more). Ids that don't exist, or
|
|
53
|
+
* belong to another tenant, are simply absent from the result — so index the
|
|
54
|
+
* response by `quoteId` rather than assuming it lines up positionally with the
|
|
55
|
+
* ids you passed. A quote that exists but has no finished goods comes back with
|
|
56
|
+
* an empty `lines` array.
|
|
57
|
+
*/
|
|
58
|
+
// Typed SingleResponse<T[]> rather than ListResponse<T>: this batch read is not
|
|
59
|
+
// paginated, so it carries no cursor/hasMore meta and claiming ListMeta would
|
|
60
|
+
// promise fields the server never sends.
|
|
61
|
+
async listForQuotes(quoteIds) {
|
|
62
|
+
return this.http.request({
|
|
63
|
+
method: 'GET',
|
|
64
|
+
path: '/v1/quote-lines',
|
|
65
|
+
query: { quoteIds: quoteIds.join(',') },
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Add a finished good to a quote. Returns the full line set, so a caller never
|
|
70
|
+
* has to re-fetch to get the new roll-up.
|
|
71
|
+
*
|
|
72
|
+
* Omit `partId` to have it resolved from `partNumber` against the parts
|
|
73
|
+
* catalog; it is left null when nothing matches, which is legal — soft
|
|
74
|
+
* enforcement, so a part number that hasn't been reconciled into the catalog
|
|
75
|
+
* can still be quoted. Pass `partId: null` to pin it null explicitly.
|
|
76
|
+
*/
|
|
77
|
+
async add(quoteId, input, idempotencyKey) {
|
|
78
|
+
return this.http.request({
|
|
79
|
+
method: 'POST',
|
|
80
|
+
path: `/v1/quotes/${encodeURIComponent(quoteId)}/lines`,
|
|
81
|
+
body: input,
|
|
82
|
+
idempotencyKey,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Update a line's AUTHORED terms. Derived cost/price are not settable here.
|
|
87
|
+
*
|
|
88
|
+
* A `note`-only patch is accepted while the quote is in review — flagging a bad
|
|
89
|
+
* part is something that happens DURING review. Anything touching the figures
|
|
90
|
+
* requires a pre-approval status (422 otherwise).
|
|
91
|
+
*/
|
|
92
|
+
async update(quoteId, lineId, input) {
|
|
93
|
+
return this.http.request({
|
|
94
|
+
method: 'PATCH',
|
|
95
|
+
path: `/v1/quotes/${encodeURIComponent(quoteId)}/lines/${encodeURIComponent(lineId)}`,
|
|
96
|
+
body: input,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/** Remove a finished good. The last line may be removed. */
|
|
100
|
+
async remove(quoteId, lineId) {
|
|
101
|
+
return this.http.request({
|
|
102
|
+
method: 'DELETE',
|
|
103
|
+
path: `/v1/quotes/${encodeURIComponent(quoteId)}/lines/${encodeURIComponent(lineId)}`,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Set the document order. `lineIds` must list every line on the quote exactly
|
|
108
|
+
* once (422 otherwise). Order also decides which line supplies the deprecated
|
|
109
|
+
* `quote.partId` mirror.
|
|
110
|
+
*/
|
|
111
|
+
async reorder(quoteId, lineIds) {
|
|
112
|
+
return this.http.request({
|
|
113
|
+
method: 'PUT',
|
|
114
|
+
path: `/v1/quotes/${encodeURIComponent(quoteId)}/lines/reorder`,
|
|
115
|
+
body: { lineIds },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Publish a DERIVED per-line cost — the line-scoped mirror of
|
|
120
|
+
* `quotes.setEffectiveCost`, and the only way a cost reaches a line.
|
|
121
|
+
*
|
|
122
|
+
* Deliberately NOT gated on quote status: a re-cost must always be able to
|
|
123
|
+
* land, or the published number silently diverges from the cost model that
|
|
124
|
+
* produced it. When the figure lands on a quote already in approval the
|
|
125
|
+
* response sets `invalidatesApproval` — the caller owns what to do about it
|
|
126
|
+
* (OMSF voids the collected approvals and re-routes).
|
|
127
|
+
*/
|
|
128
|
+
async setEffectiveCost(quoteId, lineId, input, idempotencyKey) {
|
|
129
|
+
return this.http.request({
|
|
130
|
+
method: 'PATCH',
|
|
131
|
+
path: `/v1/quotes/${encodeURIComponent(quoteId)}/lines/${encodeURIComponent(lineId)}/effective-cost`,
|
|
132
|
+
body: input,
|
|
133
|
+
idempotencyKey,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/** Price-side sibling of {@link setEffectiveCost}. */
|
|
137
|
+
async setEffectivePrice(quoteId, lineId, input, idempotencyKey) {
|
|
138
|
+
return this.http.request({
|
|
139
|
+
method: 'PATCH',
|
|
140
|
+
path: `/v1/quotes/${encodeURIComponent(quoteId)}/lines/${encodeURIComponent(lineId)}/effective-price`,
|
|
141
|
+
body: input,
|
|
142
|
+
idempotencyKey,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
exports.QuoteLineResource = QuoteLineResource;
|
|
147
|
+
//# sourceMappingURL=quoteLines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quoteLines.js","sourceRoot":"","sources":["../src/quoteLines.ts"],"names":[],"mappings":"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"}
|
package/dist/quotes.d.ts
CHANGED
|
@@ -19,13 +19,18 @@ export declare class QuoteResource {
|
|
|
19
19
|
get(id: string, options?: GetQuoteOptions): Promise<SingleResponse<Quote>>;
|
|
20
20
|
create(input: CreateQuoteInput, idempotencyKey?: string): Promise<CreateResponse<Quote>>;
|
|
21
21
|
/**
|
|
22
|
-
* Issue the next `
|
|
22
|
+
* Issue the next `Q-YYYY-NNN` for the caller's tenant — the authoritative
|
|
23
23
|
* quote-number mint (master-data owns the number and enforces `quoteNumber`
|
|
24
24
|
* uniqueness). Atomic per (tenant, year); the first call of a year seeds the
|
|
25
|
-
* counter above the existing numeric max
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* passed four digits.
|
|
25
|
+
* counter above the existing numeric max, across both prefixes. Returns
|
|
26
|
+
* `{ quoteNumber }`. Both CPQ and OMSF call this instead of scanning the quote
|
|
27
|
+
* list and incrementing — scans that wedged at 10000 once a tenant's yearly
|
|
28
|
+
* sequence passed four digits (CPQ) and raced on concurrent creates (OMSF).
|
|
29
|
+
*
|
|
30
|
+
* **The prefix changed from `RFQ-` to `Q-` on 2026-08-06**, because `RFQ-` now
|
|
31
|
+
* names the customer's request that several competing quotes answer. Quotes
|
|
32
|
+
* numbered before the change keep their `RFQ-` numbers — treat a quote number
|
|
33
|
+
* as an opaque string and never parse a prefix out of it.
|
|
29
34
|
*/
|
|
30
35
|
nextNumber(): Promise<SingleResponse<{
|
|
31
36
|
quoteNumber: string;
|
package/dist/quotes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quotes.d.ts","sourceRoot":"","sources":["../src/quotes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EACV,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,cAAc,EACd,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;GAWG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,aAAa;IAE1C,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAqB/D,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAY1E,MAAM,CACV,KAAK,EAAE,gBAAgB,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IASjC
|
|
1
|
+
{"version":3,"file":"quotes.d.ts","sourceRoot":"","sources":["../src/quotes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EACV,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,cAAc,EACd,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;GAWG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,aAAa;IAE1C,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAqB/D,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAY1E,MAAM,CACV,KAAK,EAAE,gBAAgB,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IASjC;;;;;;;;;;;;;OAaG;IACG,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAOpE;;;;OAIG;IACG,MAAM,CACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,gBAAgB,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IASjC;;;;;;;;;;;;;;;;;OAiBG;IACG,gBAAgB,CACpB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,0BAA0B,EACjC,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IASjC;;;;;;;;;;;;;OAaG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzD;;;;;;OAMG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAQvE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;IAOhE;;;;;;;;;;;;;;OAcG;IACG,gBAAgB,CACpB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,qBAAqB,EAC5B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IASjC;;;;;;;;;;;;;;OAcG;IACG,iBAAiB,CACrB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,sBAAsB,EAC7B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;CAQlC"}
|
package/dist/quotes.js
CHANGED
|
@@ -68,13 +68,18 @@ class QuoteResource {
|
|
|
68
68
|
});
|
|
69
69
|
}
|
|
70
70
|
/**
|
|
71
|
-
* Issue the next `
|
|
71
|
+
* Issue the next `Q-YYYY-NNN` for the caller's tenant — the authoritative
|
|
72
72
|
* quote-number mint (master-data owns the number and enforces `quoteNumber`
|
|
73
73
|
* uniqueness). Atomic per (tenant, year); the first call of a year seeds the
|
|
74
|
-
* counter above the existing numeric max
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* passed four digits.
|
|
74
|
+
* counter above the existing numeric max, across both prefixes. Returns
|
|
75
|
+
* `{ quoteNumber }`. Both CPQ and OMSF call this instead of scanning the quote
|
|
76
|
+
* list and incrementing — scans that wedged at 10000 once a tenant's yearly
|
|
77
|
+
* sequence passed four digits (CPQ) and raced on concurrent creates (OMSF).
|
|
78
|
+
*
|
|
79
|
+
* **The prefix changed from `RFQ-` to `Q-` on 2026-08-06**, because `RFQ-` now
|
|
80
|
+
* names the customer's request that several competing quotes answer. Quotes
|
|
81
|
+
* numbered before the change keep their `RFQ-` numbers — treat a quote number
|
|
82
|
+
* as an opaque string and never parse a prefix out of it.
|
|
78
83
|
*/
|
|
79
84
|
async nextNumber() {
|
|
80
85
|
return this.http.request({
|
package/dist/quotes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quotes.js","sourceRoot":"","sources":["../src/quotes.ts"],"names":[],"mappings":";;;AAiBA;;;;;;;;;;;GAWG;AACH,MAAa,aAAa;IACK;IAA7B,YAA6B,IAAmB;QAAnB,SAAI,GAAJ,IAAI,CAAe;IAAG,CAAC;IAEpD,KAAK,CAAC,IAAI,CAAC,OAA2B;QACpC,MAAM,KAAK,GAAuC,EAAE,CAAC;QACrD,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;gBAAE,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACrE,IAAI,OAAO,CAAC,MAAM;gBAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAClD,IAAI,OAAO,CAAC,IAAI;gBAAE,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAC5C,IAAI,OAAO,CAAC,CAAC;gBAAE,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;YACnC,IAAI,OAAO,CAAC,MAAM;gBAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAClD,IAAI,OAAO,CAAC,OAAO;gBAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YACrD,IAAI,OAAO,CAAC,iBAAiB;gBAAE,KAAK,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YACnF,IAAI,OAAO,CAAC,SAAS;gBAAE,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;YAC3D,IAAI,OAAO,CAAC,SAAS;gBAAE,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;YAC3D,IAAI,OAAO,CAAC,OAAO;gBAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAsB;YAC5C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,YAAY;YAClB,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAU,EAAE,OAAyB;QAC7C,MAAM,KAAK,GAAuC,EAAE,CAAC;QACrD,IAAI,OAAO,EAAE,OAAO,EAAE,CAAC;YACrB,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAwB;YAC9C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,cAAc,kBAAkB,CAAC,EAAE,CAAC,EAAE;YAC5C,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CACV,KAAuB,EACvB,cAAuB;QAEvB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAwB;YAC9C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,KAAK;YACX,cAAc;SACf,CAAC,CAAC;IACL,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"quotes.js","sourceRoot":"","sources":["../src/quotes.ts"],"names":[],"mappings":";;;AAiBA;;;;;;;;;;;GAWG;AACH,MAAa,aAAa;IACK;IAA7B,YAA6B,IAAmB;QAAnB,SAAI,GAAJ,IAAI,CAAe;IAAG,CAAC;IAEpD,KAAK,CAAC,IAAI,CAAC,OAA2B;QACpC,MAAM,KAAK,GAAuC,EAAE,CAAC;QACrD,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;gBAAE,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACrE,IAAI,OAAO,CAAC,MAAM;gBAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAClD,IAAI,OAAO,CAAC,IAAI;gBAAE,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAC5C,IAAI,OAAO,CAAC,CAAC;gBAAE,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;YACnC,IAAI,OAAO,CAAC,MAAM;gBAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAClD,IAAI,OAAO,CAAC,OAAO;gBAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YACrD,IAAI,OAAO,CAAC,iBAAiB;gBAAE,KAAK,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YACnF,IAAI,OAAO,CAAC,SAAS;gBAAE,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;YAC3D,IAAI,OAAO,CAAC,SAAS;gBAAE,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;YAC3D,IAAI,OAAO,CAAC,OAAO;gBAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAsB;YAC5C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,YAAY;YAClB,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAU,EAAE,OAAyB;QAC7C,MAAM,KAAK,GAAuC,EAAE,CAAC;QACrD,IAAI,OAAO,EAAE,OAAO,EAAE,CAAC;YACrB,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAwB;YAC9C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,cAAc,kBAAkB,CAAC,EAAE,CAAC,EAAE;YAC5C,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CACV,KAAuB,EACvB,cAAuB;QAEvB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAwB;YAC9C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,KAAK;YACX,cAAc;SACf,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAA0C;YAChE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,wBAAwB;SAC/B,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CACV,EAAU,EACV,KAAuB,EACvB,cAAuB;QAEvB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAwB;YAC9C,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,cAAc,kBAAkB,CAAC,EAAE,CAAC,EAAE;YAC5C,IAAI,EAAE,KAAK;YACX,cAAc;SACf,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,gBAAgB,CACpB,EAAU,EACV,KAAiC,EACjC,cAAuB;QAEvB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAwB;YAC9C,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,cAAc,kBAAkB,CAAC,EAAE,CAAC,SAAS;YACnD,IAAI,EAAE,KAAK;YACX,cAAc;SACf,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,OAAO,CAAC,EAAU,EAAE,MAAe;QACvC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAY;YACjC,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,cAAc,kBAAkB,CAAC,EAAE,CAAC,EAAE;YAC5C,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;SACtC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CAAC,GAAa;QAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAoC;YAC1D,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,0BAA0B;YAChC,IAAI,EAAE,EAAE,GAAG,EAAE;SACd,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAA8B;YACpD,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,cAAc,kBAAkB,CAAC,EAAE,CAAC,QAAQ;SACnD,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,gBAAgB,CACpB,EAAU,EACV,KAA4B,EAC5B,cAAuB;QAEvB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAwB;YAC9C,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,cAAc,kBAAkB,CAAC,EAAE,CAAC,iBAAiB;YAC3D,IAAI,EAAE,KAAK;YACX,cAAc;SACf,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,iBAAiB,CACrB,EAAU,EACV,KAA6B,EAC7B,cAAuB;QAEvB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAwB;YAC9C,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,cAAc,kBAAkB,CAAC,EAAE,CAAC,kBAAkB;YAC5D,IAAI,EAAE,KAAK;YACX,cAAc;SACf,CAAC,CAAC;IACL,CAAC;CACF;AAzND,sCAyNC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -106,7 +106,7 @@ export interface ListProgramsOptions {
|
|
|
106
106
|
export interface GetProgramOptions {
|
|
107
107
|
include?: ('customerCompany' | 'oemCompany')[];
|
|
108
108
|
}
|
|
109
|
-
export type QuoteStatus = 'draft' | 'costing_requested' | 'costing_in_progress' | 'costing_complete' | 'pricing' | 'routed_for_approval' | 'in_review' | 'approved' | 'submitted' | 'negotiating' | 'awarded' | 'lost';
|
|
109
|
+
export type QuoteStatus = 'draft' | 'costing_requested' | 'costing_in_progress' | 'costing_complete' | 'pricing' | 'routed_for_approval' | 'in_review' | 'approved' | 'submitted' | 'negotiating' | 'awarded' | 'lost' | 'not_taken';
|
|
110
110
|
/**
|
|
111
111
|
* Who is driving the transition. Required on every status update so the
|
|
112
112
|
* server can enforce role-gated transitions. `admin` is the escape hatch
|
|
@@ -137,6 +137,23 @@ export interface Quote {
|
|
|
137
137
|
name: string | null;
|
|
138
138
|
customerCompanyId: string;
|
|
139
139
|
programId: string | null;
|
|
140
|
+
/**
|
|
141
|
+
* The OEM request this quote is one competing answer to — see {@link QuoteAsk}.
|
|
142
|
+
* Null means it competes with nothing and is awardable on its own, which is a
|
|
143
|
+
* legitimate state, not missing data.
|
|
144
|
+
*/
|
|
145
|
+
askId: string | null;
|
|
146
|
+
/**
|
|
147
|
+
* @deprecated A DERIVED MIRROR of the quote's lines — read `quoteLines.list()`
|
|
148
|
+
* instead.
|
|
149
|
+
*
|
|
150
|
+
* Free text holding a part NUMBER (never a uuid), historically the quote's only
|
|
151
|
+
* part reference. A quote is multi-part now, and this reflects the FIRST line
|
|
152
|
+
* only, so it is lossy the moment a quote has more than one. Writes still work
|
|
153
|
+
* for the whole deprecation window (they transparently maintain the quote's
|
|
154
|
+
* single line), but new code should not read it as "the quote's part". Dropped
|
|
155
|
+
* in a later major. See the nextgen ADR `2026-08-05-multi-part-quotes.md`.
|
|
156
|
+
*/
|
|
140
157
|
partId: string | null;
|
|
141
158
|
/**
|
|
142
159
|
* The historical/parent quote this one was copied from. OMSF sets this when
|
|
@@ -215,6 +232,24 @@ export interface Quote {
|
|
|
215
232
|
* column stays the canonical yearly curve.
|
|
216
233
|
*/
|
|
217
234
|
effectiveVolumesByYear: EffectiveVolumeByYear[] | null;
|
|
235
|
+
/**
|
|
236
|
+
* The VEHICLE stream (added 2026-08-06) — how many vehicles the program
|
|
237
|
+
* builds, NOT how many parts we sell.
|
|
238
|
+
*
|
|
239
|
+
* This is what each {@link QuoteLine} bridges from: `vehicleAnnualVolume ×
|
|
240
|
+
* takeRate × partsPerVehicle` is that finished good's part volume. One quote
|
|
241
|
+
* covering four finished goods has ONE vehicle stream and four different part
|
|
242
|
+
* volumes, which is why the part columns above cannot serve as the input.
|
|
243
|
+
*
|
|
244
|
+
* **Null on every quote written before 2026-08-06**, and that is not a gap:
|
|
245
|
+
* those quotes' lines bridge from the part columns instead, at a 100/1 bridge
|
|
246
|
+
* that leaves the figure untouched. Read it as "does this quote calculate its
|
|
247
|
+
* line volumes, or carry them directly?" rather than as missing data.
|
|
248
|
+
*/
|
|
249
|
+
vehicleAnnualVolume: number | null;
|
|
250
|
+
/** Per-year vehicle curve, same shape as {@link effectiveVolumesByYear}.
|
|
251
|
+
* Bridged year by year onto each line. */
|
|
252
|
+
vehicleVolumesByYear: EffectiveVolumeByYear[] | null;
|
|
218
253
|
/**
|
|
219
254
|
* Customer-committed PART volume on ARBITRARY periods — the general form of
|
|
220
255
|
* {@link effectiveVolumesByYear}, for deals tracked at a granularity the year
|
|
@@ -306,6 +341,230 @@ export interface SetEffectivePriceInput {
|
|
|
306
341
|
/** Which app is writing — gated to 'omsf' | 'cpq' | 'admin' server-side. */
|
|
307
342
|
callerRole: 'omsf' | 'cpq' | 'admin';
|
|
308
343
|
}
|
|
344
|
+
export type QuoteAskStatus = 'open' | 'resolved' | 'cancelled';
|
|
345
|
+
export interface QuoteAsk {
|
|
346
|
+
id: string;
|
|
347
|
+
tenantId: string;
|
|
348
|
+
/** `ASK-YYYY-NNN`, minted server-side from an atomic per-(tenant, year) counter. */
|
|
349
|
+
askNumber: string;
|
|
350
|
+
name: string | null;
|
|
351
|
+
customerCompanyId: string;
|
|
352
|
+
/** Reporting only — NEVER used to decide competition. An opportunity spans
|
|
353
|
+
* rounds; an ask is one round. */
|
|
354
|
+
opportunityId: string | null;
|
|
355
|
+
dueDate: string | null;
|
|
356
|
+
status: QuoteAskStatus;
|
|
357
|
+
/** Which quote won. A recorded fact — closing the siblings is a later phase. */
|
|
358
|
+
resolvedByQuoteId: string | null;
|
|
359
|
+
resolvedAt: string | null;
|
|
360
|
+
createdBy: string;
|
|
361
|
+
updatedBy: string;
|
|
362
|
+
createdAt: string;
|
|
363
|
+
updatedAt: string;
|
|
364
|
+
}
|
|
365
|
+
export interface QuoteAskSummary extends QuoteAsk {
|
|
366
|
+
/** How many quotes compete in this ask. Deliberately not a value aggregate. */
|
|
367
|
+
quoteCount: number;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* A RANGE across the ask's quotes — deliberately not a total.
|
|
371
|
+
*
|
|
372
|
+
* The quotes are ALTERNATIVES: three of four lose on every multi-scenario RFQ by
|
|
373
|
+
* construction, so adding them multiply-counts the same business.
|
|
374
|
+
*/
|
|
375
|
+
export interface QuoteAskRange {
|
|
376
|
+
quoteCount: number;
|
|
377
|
+
minValue: number | null;
|
|
378
|
+
maxValue: number | null;
|
|
379
|
+
minBlendedMarginPct: number | null;
|
|
380
|
+
maxBlendedMarginPct: number | null;
|
|
381
|
+
}
|
|
382
|
+
export interface QuoteAskCompetingQuote {
|
|
383
|
+
id: string;
|
|
384
|
+
quoteNumber: string;
|
|
385
|
+
name: string | null;
|
|
386
|
+
status: QuoteStatus;
|
|
387
|
+
lines: QuoteLine[];
|
|
388
|
+
rollUp: QuoteLineRollUp;
|
|
389
|
+
}
|
|
390
|
+
export interface QuoteAskDetail extends QuoteAsk {
|
|
391
|
+
quotes: QuoteAskCompetingQuote[];
|
|
392
|
+
range: QuoteAskRange;
|
|
393
|
+
}
|
|
394
|
+
export interface CreateQuoteAskInput {
|
|
395
|
+
customerCompanyId: string;
|
|
396
|
+
name?: string | null;
|
|
397
|
+
opportunityId?: string | null;
|
|
398
|
+
dueDate?: string | null;
|
|
399
|
+
}
|
|
400
|
+
export interface UpdateQuoteAskInput {
|
|
401
|
+
name?: string | null;
|
|
402
|
+
dueDate?: string | null;
|
|
403
|
+
opportunityId?: string | null;
|
|
404
|
+
status?: QuoteAskStatus;
|
|
405
|
+
/** Required when resolving; must be one of this ask's own quotes. */
|
|
406
|
+
resolvedByQuoteId?: string | null;
|
|
407
|
+
}
|
|
408
|
+
export interface ListQuoteAsksOptions {
|
|
409
|
+
status?: QuoteAskStatus;
|
|
410
|
+
customerCompanyId?: string;
|
|
411
|
+
opportunityId?: string;
|
|
412
|
+
}
|
|
413
|
+
/** A per-year volume point. Same shape the quote header uses. */
|
|
414
|
+
export interface QuoteLineVolumeByYear {
|
|
415
|
+
year: number;
|
|
416
|
+
effectiveVolume: number;
|
|
417
|
+
}
|
|
418
|
+
export interface QuoteLine {
|
|
419
|
+
id: string;
|
|
420
|
+
tenantId: string;
|
|
421
|
+
quoteId: string;
|
|
422
|
+
/** Document order. Also picks the line that supplies the deprecated `Quote.partId`. */
|
|
423
|
+
sortOrder: number;
|
|
424
|
+
/**
|
|
425
|
+
* The canonical master-data {@link Part}. NULL is legal — soft enforcement, so a
|
|
426
|
+
* part number not yet reconciled into the catalog can still be quoted. Denotes
|
|
427
|
+
* the BASE part per the part-identity ADR.
|
|
428
|
+
*/
|
|
429
|
+
partId: string | null;
|
|
430
|
+
/** Required, denormalised. Carries the line on its own when `partId` is null. */
|
|
431
|
+
partNumber: string;
|
|
432
|
+
/** Engineering revision this line is quoted AT, when known. Never identity. */
|
|
433
|
+
revision: string | null;
|
|
434
|
+
/**
|
|
435
|
+
* Vehicle→part bridge, unique per line. At the defaults (100 / 1) the
|
|
436
|
+
* header→line volume projection is the IDENTITY.
|
|
437
|
+
*/
|
|
438
|
+
takeRate: number | null;
|
|
439
|
+
partsPerVehicle: number | null;
|
|
440
|
+
/** Authored. Null inherits the header through the bridge. */
|
|
441
|
+
annualVolume: number | null;
|
|
442
|
+
/** Authored per-year series. Authoritative over `annualVolume` when present. */
|
|
443
|
+
effectiveVolumesByYear: QuoteLineVolumeByYear[] | null;
|
|
444
|
+
/** Authored offered price for this line. */
|
|
445
|
+
unitPrice: string | null;
|
|
446
|
+
/** Free text against an unhealthy line. Writable during review. */
|
|
447
|
+
note: string | null;
|
|
448
|
+
/** DERIVED — published only via `quoteLines.setEffectiveCost`. */
|
|
449
|
+
effectiveUnitCost: string | null;
|
|
450
|
+
effectiveCostSource: string | null;
|
|
451
|
+
effectiveCostBasis: string | null;
|
|
452
|
+
effectiveCostedAt: string | null;
|
|
453
|
+
effectiveCostedBy: string | null;
|
|
454
|
+
effectiveCostBreakdown: unknown | null;
|
|
455
|
+
/** DERIVED — published only via `quoteLines.setEffectivePrice`. */
|
|
456
|
+
effectiveUnitPrice: string | null;
|
|
457
|
+
effectivePriceSource: string | null;
|
|
458
|
+
effectivePriceBasis: string | null;
|
|
459
|
+
effectivePricedAt: string | null;
|
|
460
|
+
effectivePricedBy: string | null;
|
|
461
|
+
effectivePriceBreakdown: unknown | null;
|
|
462
|
+
createdBy: string;
|
|
463
|
+
updatedBy: string;
|
|
464
|
+
createdAt: string;
|
|
465
|
+
updatedAt: string;
|
|
466
|
+
/** Present when the line resolves to a catalog part. */
|
|
467
|
+
part?: {
|
|
468
|
+
id: string;
|
|
469
|
+
partNumber: string;
|
|
470
|
+
name: string;
|
|
471
|
+
partTypeId: string | null;
|
|
472
|
+
} | null;
|
|
473
|
+
/** Resolved figures — see {@link ResolvedQuoteLineTerms}. */
|
|
474
|
+
terms: ResolvedQuoteLineTerms;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* A line's resolved terms. The `*Source` / `*FromLine` flags let a caller tell an
|
|
478
|
+
* authored figure from an inherited one without re-deriving the precedence.
|
|
479
|
+
*/
|
|
480
|
+
export interface ResolvedQuoteLineTerms {
|
|
481
|
+
annualVolume: number;
|
|
482
|
+
volumesByYear: QuoteLineVolumeByYear[] | null;
|
|
483
|
+
unitCost: number | null;
|
|
484
|
+
unitPrice: number | null;
|
|
485
|
+
value: number;
|
|
486
|
+
marginPct: number | null;
|
|
487
|
+
/**
|
|
488
|
+
* Which tier the volume came from: the line's own series, the line's own annual
|
|
489
|
+
* figure, or the quote header bridged through take rate × parts per vehicle.
|
|
490
|
+
*/
|
|
491
|
+
volumeSource: 'line_years' | 'line_annual' | 'header_bridged';
|
|
492
|
+
costFromLine: boolean;
|
|
493
|
+
priceFromLine: boolean;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Consolidated figures for ONE quote's lines, computed on read.
|
|
497
|
+
*
|
|
498
|
+
* `blendedMarginPct` is value-weighted over the lines whose margin is KNOWN, not
|
|
499
|
+
* over the whole quote value — a blend diluted by parts with no cost yet is a
|
|
500
|
+
* worse number that is equally false. `linesWithoutMargin` reports that gap.
|
|
501
|
+
*/
|
|
502
|
+
export interface QuoteLineRollUp {
|
|
503
|
+
lineCount: number;
|
|
504
|
+
totalAnnualVolume: number;
|
|
505
|
+
totalValue: number;
|
|
506
|
+
blendedMarginPct: number | null;
|
|
507
|
+
linesWithoutMargin: number;
|
|
508
|
+
/** Lines whose part number isn't reconciled into the catalog yet. */
|
|
509
|
+
linesWithoutCatalogPart: number;
|
|
510
|
+
}
|
|
511
|
+
export interface QuoteLinesResponse {
|
|
512
|
+
quoteId: string;
|
|
513
|
+
quoteNumber: string;
|
|
514
|
+
lines: QuoteLine[];
|
|
515
|
+
rollUp: QuoteLineRollUp;
|
|
516
|
+
}
|
|
517
|
+
export interface QuoteLinesWithApprovalFlag extends QuoteLinesResponse {
|
|
518
|
+
/**
|
|
519
|
+
* True when the published figure landed on a quote already in approval — the
|
|
520
|
+
* approver signed off on a different number. Surfaced rather than silently
|
|
521
|
+
* absorbed; the caller decides whether to void and re-route.
|
|
522
|
+
*/
|
|
523
|
+
invalidatesApproval: boolean;
|
|
524
|
+
}
|
|
525
|
+
export interface AddQuoteLineInput {
|
|
526
|
+
partNumber: string;
|
|
527
|
+
/** Omit to resolve from `partNumber`; pass `null` to pin it null. */
|
|
528
|
+
partId?: string | null;
|
|
529
|
+
revision?: string | null;
|
|
530
|
+
/** Defaults to the end of the list, so a new line can't take over the mirror. */
|
|
531
|
+
sortOrder?: number;
|
|
532
|
+
/** Percentage, 0–100. Defaults to 100. */
|
|
533
|
+
takeRate?: number;
|
|
534
|
+
/** Defaults to 1. */
|
|
535
|
+
partsPerVehicle?: number;
|
|
536
|
+
annualVolume?: number | null;
|
|
537
|
+
effectiveVolumesByYear?: QuoteLineVolumeByYear[] | null;
|
|
538
|
+
unitPrice?: number | null;
|
|
539
|
+
note?: string | null;
|
|
540
|
+
}
|
|
541
|
+
export interface UpdateQuoteLineInput {
|
|
542
|
+
partNumber?: string;
|
|
543
|
+
/** Omitted with a changed `partNumber` re-resolves the catalog link. */
|
|
544
|
+
partId?: string | null;
|
|
545
|
+
revision?: string | null;
|
|
546
|
+
sortOrder?: number;
|
|
547
|
+
takeRate?: number;
|
|
548
|
+
partsPerVehicle?: number;
|
|
549
|
+
annualVolume?: number | null;
|
|
550
|
+
effectiveVolumesByYear?: QuoteLineVolumeByYear[] | null;
|
|
551
|
+
unitPrice?: number | null;
|
|
552
|
+
note?: string | null;
|
|
553
|
+
}
|
|
554
|
+
export interface SetQuoteLineEffectiveCostInput {
|
|
555
|
+
unitCost: number;
|
|
556
|
+
/** Required — what the figure was costed against. */
|
|
557
|
+
costBasis: string;
|
|
558
|
+
/** Declared by the adapter. Defaults to 'cpq'. */
|
|
559
|
+
source?: string;
|
|
560
|
+
breakdown?: unknown;
|
|
561
|
+
}
|
|
562
|
+
export interface SetQuoteLineEffectivePriceInput {
|
|
563
|
+
unitPrice: number;
|
|
564
|
+
priceBasis: string;
|
|
565
|
+
source?: string;
|
|
566
|
+
breakdown?: unknown;
|
|
567
|
+
}
|
|
309
568
|
export interface CreateQuoteInput {
|
|
310
569
|
/**
|
|
311
570
|
* MIGRATION ESCAPE HATCH — do not set this from production code.
|
|
@@ -323,6 +582,10 @@ export interface CreateQuoteInput {
|
|
|
323
582
|
name?: string;
|
|
324
583
|
customerCompanyId: string;
|
|
325
584
|
programId?: string;
|
|
585
|
+
/** Join the quote to an OEM request ({@link QuoteAsk}). Optional — a quote with
|
|
586
|
+
* no ask competes with nothing and is awardable on its own. Validated to exist
|
|
587
|
+
* in-tenant AND to belong to the same customer as the quote. */
|
|
588
|
+
askId?: string | null;
|
|
326
589
|
partId?: string;
|
|
327
590
|
/** Historical/parent quote this one was copied from. Validated to exist
|
|
328
591
|
* in-tenant on write; no DB FK. */
|
|
@@ -342,6 +605,12 @@ export interface CreateQuoteInput {
|
|
|
342
605
|
eopPrecision?: SopEopPrecision;
|
|
343
606
|
effectiveAnnualVolume?: number;
|
|
344
607
|
effectiveVolumesByYear?: EffectiveVolumeByYear[];
|
|
608
|
+
/** The VEHICLE stream every line bridges from — vehicles the program builds,
|
|
609
|
+
* not parts sold. Each line turns it into its own part volume with its take
|
|
610
|
+
* rate and parts-per-vehicle. Omit it and the lines fall back to the part
|
|
611
|
+
* columns, which is what pre-2026-08-06 quotes do. (4.12.0) */
|
|
612
|
+
vehicleAnnualVolume?: number;
|
|
613
|
+
vehicleVolumesByYear?: EffectiveVolumeByYear[];
|
|
345
614
|
/** Arbitrary-period committed volume. Non-empty makes the two fields above
|
|
346
615
|
* derived — passing either alongside it is a 422. (4.8.0) */
|
|
347
616
|
effectiveVolumesByPeriod?: EffectiveVolumeByPeriod[];
|
|
@@ -372,6 +641,9 @@ export interface UpdateQuoteInput {
|
|
|
372
641
|
quoteNumber?: string;
|
|
373
642
|
name?: string | null;
|
|
374
643
|
programId?: string | null;
|
|
644
|
+
/** Join the quote to an OEM request ({@link QuoteAsk}), or `null` to detach it
|
|
645
|
+
* (it then competes with nothing). Validated to match the quote's customer. */
|
|
646
|
+
askId?: string | null;
|
|
375
647
|
partId?: string | null;
|
|
376
648
|
/** Set to a quote id to record provenance, or `null` to clear it. */
|
|
377
649
|
referenceQuoteId?: string | null;
|
|
@@ -389,6 +661,11 @@ export interface UpdateQuoteInput {
|
|
|
389
661
|
eopPrecision?: SopEopPrecision | null;
|
|
390
662
|
effectiveAnnualVolume?: number | null;
|
|
391
663
|
effectiveVolumesByYear?: EffectiveVolumeByYear[] | null;
|
|
664
|
+
/** The VEHICLE stream. Editing it moves EVERY line's calculated volume at
|
|
665
|
+
* once — one program build rate, many finished goods. `null` hands the lines
|
|
666
|
+
* back to the part columns. (4.12.0) */
|
|
667
|
+
vehicleAnnualVolume?: number | null;
|
|
668
|
+
vehicleVolumesByYear?: EffectiveVolumeByYear[] | null;
|
|
392
669
|
/** Full replace. Non-empty makes the yearly fields derived (writing them is a
|
|
393
670
|
* 422); `null` or `[]` clears the schedule and hands them back. The last
|
|
394
671
|
* derived values are left in place — clearing stops maintaining them, it
|
|
@@ -1790,7 +2067,7 @@ export type SourceApp = 'master-data' | 'erfq' | 'cpq' | 'bom' | 'forecast' | 'o
|
|
|
1790
2067
|
* "Empty" means SQL NULL only — a stored '', 0, false, or 0.0 counts as
|
|
1791
2068
|
* populated and will not be overwritten by fill_empty. */
|
|
1792
2069
|
export type MergePolicy = 'overwrite' | 'fill_empty';
|
|
1793
|
-
export type ImportTargetField = 'name' | 'legalName' | 'code' | 'taxId' | 'dunsNumber' | 'website' | 'logoUrl' | 'roles' | 'email' | 'phone' | 'role' | 'type' | 'description' | 'street' | 'city' | 'stateProvince' | 'postalCode' | 'country' | 'category' | 'parent_company_ref' | 'companyCode' | 'locationCode' | 'region' | 'headcount' | 'annualCapacityHours' | 'currentUtilization' | 'riskLevel' | 'numShifts' | 'hoursPerShift' | 'workingDaysPerYear' | 'indirectHeadcountPct' | 'currency' | 'effectiveDate' | 'effectiveTo' | 'libraryCode' | 'kind' | 'plantCode' | 'skillTier' | 'materialCode' | 'regionCode' | 'lane' | 'rate' | 'unit' | 'sourcingMode' | 'indexRef' | 'notes' | 'partNumber' | 'manufacturingPartNumber' | 'customerPartNumber' | 'partType' | 'manufacturer' | 'partCategoryCode' | 'quality' | 'revision' | 'uom' | 'weightPerUnit' | 'recycledPct' | 'pcfPerUnit' | 'releaseStatus' | 'leadTime' | 'customerCompanyCode' | 'customerCompanyName' | 'sopDate' | 'eopDate' | 'displayOrder' | 'label' | 'sortOrder' | 'processFamily' | 'capacityHoursPerYear' | 'cavities' | 'availabilityPct' | 'performancePct' | 'defaultHeadcount' | 'defaultAutomationPct' | 'defaultMachinesPerOperator' | 'defaultSetupCrew' | 'perUsd' | 'effectiveFrom' | 'quoteNumber' | 'programCode' | 'partId' | 'regionName' | 'annualVolume' | 'apw' | 'mpw' | 'targetPrice' | 'dueDate' | 'status' | 'key' | 'dataType' | 'options' | 'group' | 'required' | 'min' | 'max' | 'regex' | 'precision' | 'basis' | 'bindings' | 'perBaseFactor' | 'needsDensity' | 'binding' | 'allowedUoms' | 'defaultUom' | 'escalationDefault' | 'density' | 'densityUnit';
|
|
2070
|
+
export type ImportTargetField = 'name' | 'legalName' | 'code' | 'taxId' | 'dunsNumber' | 'website' | 'logoUrl' | 'roles' | 'email' | 'phone' | 'role' | 'type' | 'description' | 'street' | 'city' | 'stateProvince' | 'postalCode' | 'country' | 'category' | 'parent_company_ref' | 'companyCode' | 'companyName' | 'locationCode' | 'region' | 'headcount' | 'annualCapacityHours' | 'currentUtilization' | 'riskLevel' | 'numShifts' | 'hoursPerShift' | 'workingDaysPerYear' | 'indirectHeadcountPct' | 'currency' | 'effectiveDate' | 'effectiveTo' | 'libraryCode' | 'kind' | 'plantCode' | 'skillTier' | 'materialCode' | 'regionCode' | 'lane' | 'rate' | 'unit' | 'sourcingMode' | 'indexRef' | 'notes' | 'partNumber' | 'manufacturingPartNumber' | 'customerPartNumber' | 'partType' | 'manufacturer' | 'partCategoryCode' | 'quality' | 'revision' | 'uom' | 'weightPerUnit' | 'recycledPct' | 'pcfPerUnit' | 'releaseStatus' | 'leadTime' | 'customerCompanyCode' | 'customerCompanyName' | 'sopDate' | 'eopDate' | 'displayOrder' | 'label' | 'sortOrder' | 'processFamily' | 'capacityHoursPerYear' | 'cavities' | 'availabilityPct' | 'performancePct' | 'defaultHeadcount' | 'defaultAutomationPct' | 'defaultMachinesPerOperator' | 'defaultSetupCrew' | 'perUsd' | 'effectiveFrom' | 'quoteNumber' | 'programCode' | 'partId' | 'regionName' | 'annualVolume' | 'apw' | 'mpw' | 'targetPrice' | 'dueDate' | 'status' | 'key' | 'dataType' | 'options' | 'group' | 'required' | 'min' | 'max' | 'regex' | 'precision' | 'basis' | 'bindings' | 'perBaseFactor' | 'needsDensity' | 'binding' | 'allowedUoms' | 'defaultUom' | 'escalationDefault' | 'density' | 'densityUnit';
|
|
1794
2071
|
export interface ImportSession {
|
|
1795
2072
|
id: string;
|
|
1796
2073
|
tenantId: string;
|
|
@@ -2066,10 +2343,20 @@ export interface BulkArchiveResult {
|
|
|
2066
2343
|
errors: number;
|
|
2067
2344
|
};
|
|
2068
2345
|
}
|
|
2346
|
+
/** Ownership verdict carried on an *enforced* entity's read/list response
|
|
2347
|
+
* `meta` (Master Data Ownership Phase 4). Present only for enforced elements
|
|
2348
|
+
* (Plant today). `readOnly` ⇒ the element is externally owned and Campfire
|
|
2349
|
+
* edits are rejected server-side; the UI renders read-only + `editHint`. */
|
|
2350
|
+
export interface OwnershipMeta {
|
|
2351
|
+
readOnly: boolean;
|
|
2352
|
+
ownerSystem: string;
|
|
2353
|
+
editHint: string | null;
|
|
2354
|
+
}
|
|
2069
2355
|
export interface ApiMeta {
|
|
2070
2356
|
requestId: string;
|
|
2071
2357
|
timestamp: string;
|
|
2072
2358
|
resolvedFrom?: string;
|
|
2359
|
+
ownership?: OwnershipMeta;
|
|
2073
2360
|
}
|
|
2074
2361
|
export interface ListMeta extends ApiMeta {
|
|
2075
2362
|
nextCursor: string | null;
|
|
@@ -2083,6 +2370,29 @@ export interface DuplicateWarning {
|
|
|
2083
2370
|
matchName: string;
|
|
2084
2371
|
score: number;
|
|
2085
2372
|
}
|
|
2373
|
+
export type OwnerType = 'campfire' | 'external';
|
|
2374
|
+
/** One catalog element merged with its (optional) stored ownership row. The
|
|
2375
|
+
* GET response fills catalog defaults where a tenant has no row. */
|
|
2376
|
+
export interface MasterDataElementOwnership {
|
|
2377
|
+
element: string;
|
|
2378
|
+
label: string;
|
|
2379
|
+
category: string;
|
|
2380
|
+
ownerType: OwnerType;
|
|
2381
|
+
/** Owning system display name; 'Campfire' when Campfire-owned. */
|
|
2382
|
+
systemName: string;
|
|
2383
|
+
syncMethod: string | null;
|
|
2384
|
+
/** Opaque integrations Source id (external only) — traceability, not a FK. */
|
|
2385
|
+
sourceRef: string | null;
|
|
2386
|
+
updatedAt: string | null;
|
|
2387
|
+
updatedBy: string | null;
|
|
2388
|
+
}
|
|
2389
|
+
export interface SetOwnershipInput {
|
|
2390
|
+
ownerType: OwnerType;
|
|
2391
|
+
/** Required when ownerType is 'external'. */
|
|
2392
|
+
systemName?: string;
|
|
2393
|
+
syncMethod?: string;
|
|
2394
|
+
sourceRef?: string;
|
|
2395
|
+
}
|
|
2086
2396
|
export interface SingleResponse<T> {
|
|
2087
2397
|
data: T;
|
|
2088
2398
|
meta: ApiMeta;
|