@opencxh/domain 1.303.0 → 1.304.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/entities/agreement/types.d.ts +4 -3
- package/dist/entities/catalog/pricing.d.ts +3 -1
- package/dist/entities/catalog/types.d.ts +5 -0
- package/dist/entities/fulfilment/configuration.d.ts +99 -0
- package/dist/entities/fulfilment/configuration.test.d.ts +1 -0
- package/dist/entities/fulfilment/index.d.ts +1 -0
- package/dist/entities/fulfilment/target.d.ts +4 -2
- package/dist/entities/fulfilment/types.d.ts +5 -33
- package/dist/entities/purchase/choose.d.ts +5 -0
- package/dist/entities/purchase/demand.d.ts +2 -0
- package/dist/entities/purchase/index.d.ts +1 -0
- package/dist/entities/purchase/types.d.ts +20 -5
- package/dist/entities/purchase/upsell.d.ts +20 -0
- package/dist/entities/purchase/upsell.test.d.ts +1 -0
- package/dist/entities/transaction/types.d.ts +10 -5
- package/dist/index.cjs +23 -23
- package/dist/index.js +2619 -2486
- package/dist/platform/provisioning.d.ts +139 -61
- package/package.json +1 -1
|
@@ -145,9 +145,10 @@ export interface AgreementLine {
|
|
|
145
145
|
billingStart?: BillingStart;
|
|
146
146
|
/** Set by fulfilment, never by a person: the first day it ran. A resume does not move it. */
|
|
147
147
|
activatedAt?: number;
|
|
148
|
-
/** From the quote line (
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
/** From the quote line (plan 053): see {@link SalesLine.configurationId}. */
|
|
149
|
+
configurationId?: string;
|
|
150
|
+
/** A sub-line of that configuration: the answer it comes from (see `SalesLine.optionKey`). */
|
|
151
|
+
optionKey?: string;
|
|
151
152
|
}
|
|
152
153
|
export type LineBilling = "advance" | "arrears";
|
|
153
154
|
/** When a line starts billing: on its dates, or once what it sells runs (047 §10.2). */
|
|
@@ -3,7 +3,7 @@ import { PricePer } from '../money/period-price';
|
|
|
3
3
|
import { SalesLine } from '../transaction/types';
|
|
4
4
|
import { PriceRule, SellableProduct } from './types';
|
|
5
5
|
/** What the ladder reads of an article: its identity and sales' price row. */
|
|
6
|
-
export type PricedProduct = Pick<SellableProduct, "id" | "categoryKey" | "listPriceCents" | "currency" | "pricePer" | "rateCardId">;
|
|
6
|
+
export type PricedProduct = Pick<SellableProduct, "id" | "categoryKey" | "listPriceCents" | "currency" | "pricePer" | "rateCardId" | "markupPercent">;
|
|
7
7
|
/**
|
|
8
8
|
* The ladder: the most specific rule wins, whole. No sum, no stacking.
|
|
9
9
|
*
|
|
@@ -30,6 +30,8 @@ export interface PriceContext {
|
|
|
30
30
|
quantity: number;
|
|
31
31
|
/** Epoch ms; the validity window is judged against this, not against "now". */
|
|
32
32
|
at: number;
|
|
33
|
+
/** What one unit costs us, for a `markupPercent` article (from the line's configuration). */
|
|
34
|
+
costCents?: Cents;
|
|
33
35
|
}
|
|
34
36
|
/** Amount, currency and period travel together: € 222 means nothing without "per year". */
|
|
35
37
|
export interface ResolvedPrice {
|
|
@@ -147,6 +147,11 @@ export interface SalesProduct {
|
|
|
147
147
|
pricing?: ProductPricing;
|
|
148
148
|
/** The default card of a `rated` product. A price agreement may name another. */
|
|
149
149
|
rateCardId?: string;
|
|
150
|
+
/**
|
|
151
|
+
* Priced as cost plus this percentage instead of a list price (plan 053: an extra EVC costs us
|
|
152
|
+
* anything from € 4 to € 397). The line's cost comes from its configuration; no cost = no price.
|
|
153
|
+
*/
|
|
154
|
+
markupPercent?: number;
|
|
150
155
|
/** The unit a new line starts in (a box); absent = the base unit. */
|
|
151
156
|
unitKey?: string;
|
|
152
157
|
updatedAt?: number;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { AnswerSpec, OfferRef, Preparation, ProvisioningAnswers, Requirement, RequirementGate } from '../../platform/provisioning';
|
|
2
|
+
import { Commitment, LineRhythm } from '../agreement/types';
|
|
3
|
+
/**
|
|
4
|
+
* One article configured for one customer (plan 053): the answers, the offer chosen and what the
|
|
5
|
+
* provider last said. Sales carries only its id; fulfilment freezes the answers into the request.
|
|
6
|
+
*/
|
|
7
|
+
export interface Configuration {
|
|
8
|
+
id: string;
|
|
9
|
+
organizationId: string;
|
|
10
|
+
businessEntityId: string;
|
|
11
|
+
customerCompanyId: string;
|
|
12
|
+
productId: string;
|
|
13
|
+
/** The offer it is bought through; its `sku` follows the `main` answer. */
|
|
14
|
+
ref?: OfferRef;
|
|
15
|
+
supplierOfferId?: string;
|
|
16
|
+
answers: ProvisioningAnswers;
|
|
17
|
+
preparation?: Preparation;
|
|
18
|
+
preparedAt?: number;
|
|
19
|
+
createdBy: string;
|
|
20
|
+
updatedAt: number;
|
|
21
|
+
}
|
|
22
|
+
export type ConfigurationStatus = "open" | "ready" | "expired";
|
|
23
|
+
/** "Via leverancier" (plan 053): a provider whose flow asks something, and what it starts with. */
|
|
24
|
+
export interface SupplierFlow {
|
|
25
|
+
app: string;
|
|
26
|
+
label: string;
|
|
27
|
+
asks: AnswerSpec[];
|
|
28
|
+
productIds: string[];
|
|
29
|
+
}
|
|
30
|
+
/** Step 1, one article on the answers so far: can it be delivered, and from what cost. */
|
|
31
|
+
export interface ArticleCheck {
|
|
32
|
+
productId: string;
|
|
33
|
+
supplierOfferId: string;
|
|
34
|
+
available: boolean;
|
|
35
|
+
/** The first unmet condition's reason; absent when only questions are left. */
|
|
36
|
+
reason?: string;
|
|
37
|
+
/** The cheapest main option, per month where it recurs. Internal: colleagues only. */
|
|
38
|
+
fromCents?: number;
|
|
39
|
+
labels: string[];
|
|
40
|
+
}
|
|
41
|
+
/** One line a configuration sells, with the upsell article it becomes — or none yet. */
|
|
42
|
+
export interface ConfiguredSale {
|
|
43
|
+
/** The answer it comes from; absent for the main line. */
|
|
44
|
+
optionKey?: string;
|
|
45
|
+
label: string;
|
|
46
|
+
sku: string;
|
|
47
|
+
quantity: number;
|
|
48
|
+
costCents?: number;
|
|
49
|
+
recurring?: "month";
|
|
50
|
+
/** Our article: the configured one for the main line, the upsell rule's for a sub-line. */
|
|
51
|
+
productId?: string;
|
|
52
|
+
commitment?: Partial<Commitment>;
|
|
53
|
+
}
|
|
54
|
+
export interface ConfigurationView {
|
|
55
|
+
configuration: Configuration;
|
|
56
|
+
status: ConfigurationStatus;
|
|
57
|
+
sales: ConfiguredSale[];
|
|
58
|
+
}
|
|
59
|
+
/** What still stands in the way of `gate`: at `order`, the quote's requirements count too. */
|
|
60
|
+
export declare function blockersOf(preparation: Preparation, gate: RequirementGate): Requirement[];
|
|
61
|
+
/** Ready for `gate` when prepared, not expired and nothing blocks it. */
|
|
62
|
+
export declare function configurationStatus(config: Pick<Configuration, "preparation">, gate: RequirementGate, now: number): ConfigurationStatus;
|
|
63
|
+
/** A chosen product: the main line's or one add-on's. Cost is per unit, internal. */
|
|
64
|
+
export interface ConfiguredLine {
|
|
65
|
+
/** The answer it comes from (`evc_2`, `sla`). */
|
|
66
|
+
key: string;
|
|
67
|
+
/** As the provider names it: what an upsell article's match reads. */
|
|
68
|
+
label: string;
|
|
69
|
+
sku: string;
|
|
70
|
+
quantity: number;
|
|
71
|
+
costCents?: number;
|
|
72
|
+
recurring?: "month";
|
|
73
|
+
commitment?: Partial<Commitment>;
|
|
74
|
+
billedEvery?: LineRhythm;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* What the answers buy: the supplier's product for the main line, and one sub-line per add-on
|
|
78
|
+
* taken (decided 05-10: an add-on is its own sales line). A `no` or a `0` is no line.
|
|
79
|
+
*/
|
|
80
|
+
export declare function linesOf(preparation: Preparation, answers: ProvisioningAnswers): {
|
|
81
|
+
main?: ConfiguredLine;
|
|
82
|
+
addons: ConfiguredLine[];
|
|
83
|
+
};
|
|
84
|
+
/** The offer as bought: the chosen main product becomes its sku, its option's commitment ours. */
|
|
85
|
+
export declare function chosenOf(ref: OfferRef, preparation: Preparation, answers: ProvisioningAnswers): {
|
|
86
|
+
ref: OfferRef;
|
|
87
|
+
commitment?: Partial<Commitment>;
|
|
88
|
+
billedEvery?: LineRhythm;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* The answers that go out, frozen on the request: only keys the provider asked for, its own
|
|
92
|
+
* proposal where nobody typed one. A stray key never reaches the supplier.
|
|
93
|
+
*/
|
|
94
|
+
export declare function orderAnswers(preparation: Preparation, answers: ProvisioningAnswers): ProvisioningAnswers;
|
|
95
|
+
/**
|
|
96
|
+
* An exclusive item configured per unit (plan 053 G2: ten SIMs, ten numbers to port): one set of
|
|
97
|
+
* answers per unit, the shared ones copied, the `perUnit` ones from `perUnitValues` in order.
|
|
98
|
+
*/
|
|
99
|
+
export declare function splitUnits(preparation: Preparation, answers: ProvisioningAnswers, quantity: number, perUnitValues?: Record<string, string[]>): ProvisioningAnswers[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -78,7 +78,8 @@ export declare function draftRequest(input: {
|
|
|
78
78
|
/** What was asked on the sale (047 step 8): the item's own purchase carries it. */
|
|
79
79
|
answers?: {
|
|
80
80
|
params: Record<string, string>;
|
|
81
|
-
|
|
81
|
+
configurationId?: string;
|
|
82
|
+
termMonths?: number;
|
|
82
83
|
};
|
|
83
84
|
revision: string;
|
|
84
85
|
requestedBy: string;
|
|
@@ -118,7 +119,8 @@ export declare function planFor(input: {
|
|
|
118
119
|
/** The sale's answers, for the item's own request only: what it needs is made without them. */
|
|
119
120
|
answers?: {
|
|
120
121
|
params: Record<string, string>;
|
|
121
|
-
|
|
122
|
+
configurationId?: string;
|
|
123
|
+
termMonths?: number;
|
|
122
124
|
};
|
|
123
125
|
revision: string;
|
|
124
126
|
requestedBy: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ProvidedResource,
|
|
1
|
+
import { ProvidedResource, ProvisioningAction, ProvisioningCommand, ProvisioningResult } from '../../platform/provisioning';
|
|
2
2
|
import { DeliverTo } from '../purchase/types';
|
|
3
3
|
/**
|
|
4
4
|
* What runs at or for a customer (plan 047 v2): a subscription, an account, a bought number, one
|
|
@@ -36,6 +36,8 @@ export interface ProvisionedItem {
|
|
|
36
36
|
at?: {
|
|
37
37
|
app: string;
|
|
38
38
|
offer?: string;
|
|
39
|
+
/** The supplier offer it is bought on (`SupplierOffer.id`): what "Te bestellen" orders. */
|
|
40
|
+
offerId?: string;
|
|
39
41
|
externalRef?: string;
|
|
40
42
|
fulfillment?: Record<string, string>;
|
|
41
43
|
};
|
|
@@ -136,8 +138,8 @@ export interface ProvisioningRequest {
|
|
|
136
138
|
app: string;
|
|
137
139
|
offer: string;
|
|
138
140
|
params: Record<string, string>;
|
|
139
|
-
/** The
|
|
140
|
-
|
|
141
|
+
/** The configuration the sale was made on (plan 053); its answers are in `params`. */
|
|
142
|
+
configurationId?: string;
|
|
141
143
|
/** Bound by role from what the item requires, then checked by kind (§10.1). */
|
|
142
144
|
inputs?: {
|
|
143
145
|
role: string;
|
|
@@ -289,33 +291,3 @@ export interface Delivery {
|
|
|
289
291
|
carrier?: string;
|
|
290
292
|
trackingNumber?: string;
|
|
291
293
|
}
|
|
292
|
-
/**
|
|
293
|
-
* Deliverable here, before the promise (047 step 8, TMF679): the answers asked for one article,
|
|
294
|
-
* what each provider said (`perOffer`, with cost: internal) and that answer in our own assortment
|
|
295
|
-
* (`products`: the only part a customer may see). No address field: `site` is a crm address id.
|
|
296
|
-
*/
|
|
297
|
-
export interface Qualification {
|
|
298
|
-
id: string;
|
|
299
|
-
organizationId: string;
|
|
300
|
-
businessEntityId: string;
|
|
301
|
-
productId: string;
|
|
302
|
-
params: Record<string, string>;
|
|
303
|
-
perOffer: OfferQualification[];
|
|
304
|
-
products: QualifiedProduct[];
|
|
305
|
-
expiresAt: number;
|
|
306
|
-
createdBy: string;
|
|
307
|
-
at: number;
|
|
308
|
-
}
|
|
309
|
-
export type OfferQualification = ProviderQualification & {
|
|
310
|
-
app: string;
|
|
311
|
-
offer: string;
|
|
312
|
-
};
|
|
313
|
-
export interface QualifiedProduct {
|
|
314
|
-
productId: string;
|
|
315
|
-
available: boolean;
|
|
316
|
-
/** A code, never the supplier's words: `unavailable` or `no_answer`. */
|
|
317
|
-
reason?: "unavailable" | "no_answer";
|
|
318
|
-
}
|
|
319
|
-
/** What leaves fulfilment for a person or a portal: never the suppliers, networks or costs. */
|
|
320
|
-
export type QualificationView = Omit<Qualification, "perOffer">;
|
|
321
|
-
export declare const qualificationView: ({ perOffer: _, ...view }: Qualification) => QualificationView;
|
|
@@ -10,9 +10,14 @@ export interface OfferNeed {
|
|
|
10
10
|
/** `own` through our warehouse, anything else straight to the customer. */
|
|
11
11
|
deliverTo?: DeliverTo["kind"];
|
|
12
12
|
/** The delivery check the sale was made on: only what it found available qualifies (6c). */
|
|
13
|
+
/**
|
|
14
|
+
* The offers a delivery check found deliverable. `vendorSku` tells products apart that share
|
|
15
|
+
* one provider offer (every Nextpertise connection is `connection`, 045 D N-4).
|
|
16
|
+
*/
|
|
13
17
|
qualified?: readonly {
|
|
14
18
|
app: string;
|
|
15
19
|
offer: string;
|
|
20
|
+
vendorSku?: string;
|
|
16
21
|
}[];
|
|
17
22
|
/** The administration's currency; prices in another one need `rates`. */
|
|
18
23
|
currency: string;
|
|
@@ -39,6 +39,8 @@ export interface DemandItem {
|
|
|
39
39
|
warnings?: string[];
|
|
40
40
|
};
|
|
41
41
|
costUnknown?: boolean;
|
|
42
|
+
/** The term it is ordered for: the offer's, else the sale's (045 D N-3). The price is asked on it. */
|
|
43
|
+
termMonths?: number;
|
|
42
44
|
/** The request's answers (the site as a crm address id): what a per-order price is asked on. */
|
|
43
45
|
params?: Record<string, string>;
|
|
44
46
|
/** The request this waits for: the customer's account before its numbers. */
|
|
@@ -1,9 +1,27 @@
|
|
|
1
|
-
import { ProvisioningAction, ProvisioningState } from '../../platform/provisioning';
|
|
1
|
+
import { ProvisioningAction, ProvisioningAnswers, ProvisioningState } from '../../platform/provisioning';
|
|
2
2
|
import { LineRhythm } from '../agreement/types';
|
|
3
3
|
import { Cents } from '../money/money';
|
|
4
4
|
import { PricePer } from '../money/period-price';
|
|
5
5
|
import { PostalAddress } from '../organization/types';
|
|
6
6
|
import { Transaction, TransactionLine } from '../transaction/types';
|
|
7
|
+
/** How an offer is ordered through an app, and what of that app's assortment it stands for. */
|
|
8
|
+
export interface OfferProvider {
|
|
9
|
+
app: string;
|
|
10
|
+
offer: string;
|
|
11
|
+
/**
|
|
12
|
+
* The article as a filter (plan 053): fixed answers in this provider's own words
|
|
13
|
+
* (`technology: fiber`, `min_download: 1000`). They go to `prepare` with every other answer.
|
|
14
|
+
*/
|
|
15
|
+
answers?: ProvisioningAnswers;
|
|
16
|
+
/**
|
|
17
|
+
* An upsell article: which of the provider's options it sells — by answer key (`evc_*` is every
|
|
18
|
+
* circuit) and option key or label (`24x7`); no `match` = every option of that answer.
|
|
19
|
+
*/
|
|
20
|
+
option?: {
|
|
21
|
+
answer: string;
|
|
22
|
+
match?: string;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
7
25
|
/**
|
|
8
26
|
* What a supplier asks for a product: one row per supplier and product (and validity window).
|
|
9
27
|
* The default offer is the product's cost price; the rest are the alternatives a buyer compares.
|
|
@@ -55,10 +73,7 @@ export interface SupplierOffer {
|
|
|
55
73
|
* Ordered through an app instead of by mail (fase 9). Where it lands is not the offer's to say:
|
|
56
74
|
* the provider of that platform declares what it needs (047 v2 §2.3).
|
|
57
75
|
*/
|
|
58
|
-
provider?:
|
|
59
|
-
app: string;
|
|
60
|
-
offer: string;
|
|
61
|
-
};
|
|
76
|
+
provider?: OfferProvider;
|
|
62
77
|
/** The supplier's advised price (the Microsoft ERP price), from a feed (plan 045 G). */
|
|
63
78
|
listCents?: Cents;
|
|
64
79
|
/** The last known stock; only the latest, no history (plan 045 B.1). */
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OfferProvider, SupplierOffer } from './types';
|
|
2
|
+
/** One option a configuration took, as its provider named it. */
|
|
3
|
+
export interface TakenOption {
|
|
4
|
+
/** The answer it comes from: `evc_2`, `sla`, `cpe`. */
|
|
5
|
+
answer: string;
|
|
6
|
+
/** The provider's own option key (`608`) and label (`24x7`). */
|
|
7
|
+
key: string;
|
|
8
|
+
label: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Whether an upsell article's rule covers an option (plan 053): the answer by name, or every
|
|
12
|
+
* numbered one with a trailing `*` (`evc_*`); then the option by key or label, or any.
|
|
13
|
+
*/
|
|
14
|
+
export declare function sellsOption(rule: OfferProvider["option"], option: TakenOption): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* The upsell article that sells this option at this provider, or none: then a colleague is told
|
|
17
|
+
* "no sales article linked" and nothing is sold without a price. The exact match wins over a
|
|
18
|
+
* catch-all (`SLA 24x7` over a rule for every SLA).
|
|
19
|
+
*/
|
|
20
|
+
export declare function upsellOfferFor(offers: readonly SupplierOffer[], app: string, option: TakenOption): SupplierOffer | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -298,12 +298,17 @@ export interface SalesLine extends TransactionLine {
|
|
|
298
298
|
lineId: string;
|
|
299
299
|
};
|
|
300
300
|
/**
|
|
301
|
-
*
|
|
302
|
-
*
|
|
301
|
+
* Ordered through a supplier (plan 053): fulfilment's `Configuration` holds the answers, the
|
|
302
|
+
* offer chosen and what the supplier said. Sales carries only the id; it travels to the
|
|
303
|
+
* agreement and the request. Never on the paper.
|
|
303
304
|
*/
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
|
|
305
|
+
configurationId?: string;
|
|
306
|
+
/**
|
|
307
|
+
* A sub-line of that configuration (an extra EVC, a paid SLA): the answer it comes from
|
|
308
|
+
* (`evc_2`). The main line has the same `configurationId` and no `optionKey`. Billed as its
|
|
309
|
+
* own line, ordered as part of the main one.
|
|
310
|
+
*/
|
|
311
|
+
optionKey?: string;
|
|
307
312
|
}
|
|
308
313
|
export interface TransactionTotals {
|
|
309
314
|
netCents: Cents;
|