@opencxh/domain 1.302.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/from-quote.d.ts +8 -8
- package/dist/entities/agreement/index.d.ts +2 -0
- package/dist/entities/agreement/invoice-head.d.ts +21 -0
- package/dist/entities/agreement/lifecycle.d.ts +10 -0
- package/dist/entities/agreement/period.d.ts +8 -0
- package/dist/entities/agreement/prices.d.ts +43 -0
- package/dist/entities/agreement/prices.test.d.ts +1 -0
- package/dist/entities/agreement/types.d.ts +55 -10
- package/dist/entities/bank/match.d.ts +16 -2
- package/dist/entities/bank/types.d.ts +12 -0
- package/dist/entities/bookkeeping/receipt.d.ts +45 -6
- package/dist/entities/bookkeeping/types.d.ts +1 -2
- package/dist/entities/business-entity/types.d.ts +11 -15
- package/dist/entities/catalog/pricing.d.ts +14 -12
- package/dist/entities/catalog/types.d.ts +20 -9
- package/dist/entities/company/role.d.ts +14 -0
- package/dist/entities/financing/schedule.d.ts +9 -3
- package/dist/entities/financing/types.d.ts +17 -6
- package/dist/entities/fulfilment/adopt.d.ts +149 -0
- package/dist/entities/fulfilment/configuration.d.ts +99 -0
- package/dist/entities/fulfilment/configuration.test.d.ts +1 -0
- package/dist/entities/fulfilment/customers.d.ts +63 -0
- package/dist/entities/fulfilment/execute.d.ts +67 -0
- package/dist/entities/fulfilment/fulfilment.test.d.ts +1 -0
- package/dist/entities/fulfilment/goods.d.ts +72 -0
- package/dist/entities/fulfilment/index.d.ts +9 -0
- package/dist/entities/fulfilment/path.d.ts +8 -0
- package/dist/entities/fulfilment/path.test.d.ts +1 -0
- package/dist/entities/fulfilment/rules.d.ts +124 -0
- package/dist/entities/fulfilment/target.d.ts +133 -0
- package/dist/entities/fulfilment/types.d.ts +293 -0
- package/dist/entities/ledger/entry.d.ts +47 -9
- package/dist/entities/ledger/types.d.ts +33 -35
- package/dist/entities/ledger/xaf.d.ts +3 -0
- package/dist/entities/money/tax.d.ts +6 -0
- package/dist/entities/money/totals.d.ts +5 -5
- package/dist/entities/purchase/choose.d.ts +62 -0
- package/dist/entities/purchase/choose.test.d.ts +1 -0
- package/dist/entities/purchase/contract.d.ts +44 -25
- package/dist/entities/purchase/demand.d.ts +24 -40
- package/dist/entities/purchase/feed.d.ts +53 -5
- package/dist/entities/purchase/index.d.ts +2 -0
- package/dist/entities/purchase/kinds.d.ts +2 -1
- package/dist/entities/purchase/logic.d.ts +32 -7
- package/dist/entities/purchase/match.d.ts +48 -6
- package/dist/entities/purchase/packing-slip.d.ts +23 -0
- package/dist/entities/purchase/types.d.ts +90 -42
- package/dist/entities/purchase/upsell.d.ts +20 -0
- package/dist/entities/purchase/upsell.test.d.ts +1 -0
- package/dist/entities/reports/vat.d.ts +20 -5
- package/dist/entities/transaction/booking.d.ts +4 -4
- package/dist/entities/transaction/convert.d.ts +10 -10
- package/dist/entities/transaction/document.d.ts +8 -3
- package/dist/entities/transaction/dunning.d.ts +12 -1
- package/dist/entities/transaction/facets.test.d.ts +1 -0
- package/dist/entities/transaction/keys.d.ts +3 -0
- package/dist/entities/transaction/kinds.d.ts +11 -10
- package/dist/entities/transaction/receivable.d.ts +5 -2
- package/dist/entities/transaction/settlement.d.ts +7 -7
- package/dist/entities/transaction/types.d.ts +128 -68
- package/dist/index.cjs +25 -25
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5300 -4033
- package/dist/platform/bookkeeping.d.ts +8 -8
- package/dist/platform/provisioning.d.ts +292 -17
- package/package.json +1 -1
- /package/dist/entities/{purchase/demand.test.d.ts → agreement/invoice-head.test.d.ts} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Cents } from '../money/money';
|
|
2
2
|
import { PricePer } from '../money/period-price';
|
|
3
|
+
import { LineDimensions } from '../transaction/types';
|
|
3
4
|
import { MatchCandidate, MatchedVia } from './packing-slip';
|
|
4
5
|
import { SupplierOffer } from './types';
|
|
5
6
|
/** What an invoice line pays for: an order line, or a contract line over a period. */
|
|
@@ -41,10 +42,26 @@ export interface InvoiceCandidate extends MatchCandidate {
|
|
|
41
42
|
discountPercent?: number;
|
|
42
43
|
/** Order line: what is still to invoice. Contract line: the agreed count, `null` when counted. */
|
|
43
44
|
openQty: number | null;
|
|
45
|
+
/**
|
|
46
|
+
* Goods that come to us: received minus invoiced. Absent when no receipt is expected (a service,
|
|
47
|
+
* a licence, a drop shipment): then the order is the measure, as before (Exact: 3-way match).
|
|
48
|
+
*/
|
|
49
|
+
receivedOpen?: number;
|
|
44
50
|
/** A contract line whose invoice decides the amount: nothing expected. */
|
|
45
51
|
variable?: boolean;
|
|
46
52
|
use?: "own" | "resale";
|
|
47
53
|
customerCompanyId?: string;
|
|
54
|
+
/** The order's or contract's; absent = the invoice's own. */
|
|
55
|
+
currency?: string;
|
|
56
|
+
/** A contract row: the days it runs, `to` exclusive. A line is matched to the row of its period. */
|
|
57
|
+
term?: {
|
|
58
|
+
from: number;
|
|
59
|
+
to?: number;
|
|
60
|
+
};
|
|
61
|
+
/** The order line's, carried to the cost it books (plan 045 F 3b). */
|
|
62
|
+
dimensions?: LineDimensions;
|
|
63
|
+
/** The article's group in this administration: its posting rule picks the cost account. */
|
|
64
|
+
ledgerCategoryKey?: string;
|
|
48
65
|
}
|
|
49
66
|
export interface MatchAllocation {
|
|
50
67
|
receiptLineId: string;
|
|
@@ -56,10 +73,33 @@ export interface MatchAllocation {
|
|
|
56
73
|
expectedCents: Cents | null;
|
|
57
74
|
/** More than the order line still had open, or another count than the contract's. */
|
|
58
75
|
overQuantity: boolean;
|
|
76
|
+
/** More than has arrived of goods that come to us: invoiced before it was received. */
|
|
77
|
+
notReceived?: boolean;
|
|
59
78
|
businessEntityId: string;
|
|
60
79
|
productId?: string;
|
|
61
80
|
use?: "own" | "resale";
|
|
62
81
|
customerCompanyId?: string;
|
|
82
|
+
dimensions?: LineDimensions;
|
|
83
|
+
ledgerCategoryKey?: string;
|
|
84
|
+
/**
|
|
85
|
+
* The invoice in another currency than its target: one invoice unit in the target's. The
|
|
86
|
+
* amount stays as printed (it is what books); the verdict compares `amountCents × rate`.
|
|
87
|
+
*/
|
|
88
|
+
rate?: number;
|
|
89
|
+
}
|
|
90
|
+
/** What the invoice is in, and its rate to the euro when it is not (Receipt `fxRate`). */
|
|
91
|
+
export interface InvoiceMoney {
|
|
92
|
+
currency: string;
|
|
93
|
+
/** Euro per one unit of `currency`, as the receipt carries it. */
|
|
94
|
+
fxRate?: number;
|
|
95
|
+
}
|
|
96
|
+
export interface AllocateOptions {
|
|
97
|
+
/** The month a line without a printed period is for (the invoice's). */
|
|
98
|
+
defaultPeriod: {
|
|
99
|
+
from: number;
|
|
100
|
+
to: number;
|
|
101
|
+
};
|
|
102
|
+
invoice?: InvoiceMoney;
|
|
63
103
|
}
|
|
64
104
|
/**
|
|
65
105
|
* Invoice lines onto order and contract lines, many to many. Each line goes to its best candidates
|
|
@@ -67,12 +107,10 @@ export interface MatchAllocation {
|
|
|
67
107
|
* same article (10 phones over two orders of 6 and 4), the amount split by count. A contract line
|
|
68
108
|
* takes the line whole, for the period printed on it or else `defaultPeriod` (the invoice's month).
|
|
69
109
|
*/
|
|
70
|
-
export declare function allocateInvoice(lines: readonly InvoiceLine[], candidates: readonly InvoiceCandidate[], offers: readonly Pick<SupplierOffer, "id" | "productId" | "vendorSku">[], defaultPeriod: {
|
|
71
|
-
from: number;
|
|
72
|
-
to: number;
|
|
73
|
-
}): {
|
|
110
|
+
export declare function allocateInvoice(lines: readonly InvoiceLine[], candidates: readonly InvoiceCandidate[], offers: readonly Pick<SupplierOffer, "id" | "productId" | "vendorSku">[], { defaultPeriod, invoice }: AllocateOptions): {
|
|
74
111
|
allocations: MatchAllocation[];
|
|
75
112
|
unmatched: string[];
|
|
113
|
+
needsRate: string[];
|
|
76
114
|
};
|
|
77
115
|
export interface MatchTolerance {
|
|
78
116
|
percent: number;
|
|
@@ -80,7 +118,7 @@ export interface MatchTolerance {
|
|
|
80
118
|
}
|
|
81
119
|
/** One per cent or one euro, whichever is more: a rounding difference is not work. */
|
|
82
120
|
export declare const DEFAULT_TOLERANCE: MatchTolerance;
|
|
83
|
-
export type MatchIssue = "price" | "quantity" | "unmatched";
|
|
121
|
+
export type MatchIssue = "price" | "quantity" | "not_received" | "unmatched" | "fx_rate_required";
|
|
84
122
|
export interface MatchVerdict {
|
|
85
123
|
/** Everything matched, at the expected price and count: approve without a person. */
|
|
86
124
|
ok: boolean;
|
|
@@ -95,4 +133,8 @@ export interface MatchVerdict {
|
|
|
95
133
|
* Whether an invoice is what was ordered or agreed: every line matched, every count within what
|
|
96
134
|
* was open, every amount within the tolerance (% and absolute). Anything else is work.
|
|
97
135
|
*/
|
|
98
|
-
export declare function matchVerdict(allocations: readonly MatchAllocation[], unmatched: readonly string[], tolerance?:
|
|
136
|
+
export declare function matchVerdict(allocations: readonly MatchAllocation[], unmatched: readonly string[], { tolerance, needsRate, }?: {
|
|
137
|
+
tolerance?: MatchTolerance;
|
|
138
|
+
/** Lines that would match in another currency: the receipt needs its rate first. */
|
|
139
|
+
needsRate?: readonly string[];
|
|
140
|
+
}): MatchVerdict;
|
|
@@ -72,6 +72,29 @@ export interface SlipProposal {
|
|
|
72
72
|
})[];
|
|
73
73
|
problems: SlipProblem[];
|
|
74
74
|
}
|
|
75
|
+
/** A packing slip as a screen reads it: an upload or a mail attachment, read by the AI. */
|
|
76
|
+
export interface PackingSlipView {
|
|
77
|
+
id: string;
|
|
78
|
+
source: "upload" | "mail";
|
|
79
|
+
filename: string;
|
|
80
|
+
mimeType: string;
|
|
81
|
+
mail?: {
|
|
82
|
+
interactionId: string;
|
|
83
|
+
activityId: string;
|
|
84
|
+
attachmentId: string;
|
|
85
|
+
from?: string;
|
|
86
|
+
};
|
|
87
|
+
/** The original in the packing-slip folder. */
|
|
88
|
+
file?: {
|
|
89
|
+
mountId: string;
|
|
90
|
+
fileId: string;
|
|
91
|
+
};
|
|
92
|
+
status: "extracting" | "needs_browser" | "to_check" | "booked" | "dismissed";
|
|
93
|
+
content?: PackingSlipContent;
|
|
94
|
+
purchaseOrderId?: string;
|
|
95
|
+
extractError?: string;
|
|
96
|
+
createdAt?: number;
|
|
97
|
+
}
|
|
75
98
|
/**
|
|
76
99
|
* A packing slip as a receipt to book: the matched lines with their counts and serials, and what a
|
|
77
100
|
* person has to decide — no order, an article not on it, more than is open, serials that do not
|
|
@@ -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.
|
|
@@ -11,7 +29,7 @@ import { Transaction, TransactionLine } from '../transaction/types';
|
|
|
11
29
|
export interface SupplierOffer {
|
|
12
30
|
id: string;
|
|
13
31
|
organizationId: string;
|
|
14
|
-
businessEntityId
|
|
32
|
+
businessEntityId: string;
|
|
15
33
|
supplierCompanyId: string;
|
|
16
34
|
productId: string;
|
|
17
35
|
/** Their article number. */
|
|
@@ -39,22 +57,23 @@ export interface SupplierOffer {
|
|
|
39
57
|
validFrom?: number;
|
|
40
58
|
validTo?: number;
|
|
41
59
|
minQty?: number;
|
|
60
|
+
/** Ordered in multiples of this many purchase units (Exact `PurchaseLotSize`); `minQty` is no multiple. */
|
|
61
|
+
lotSize?: number;
|
|
62
|
+
/** Ships straight to a customer: never, only, or both (Exact `DropShipment`). Absent = both. */
|
|
63
|
+
dropship?: "no" | "yes" | "optional";
|
|
64
|
+
/**
|
|
65
|
+
* `quote`: no fixed price — the provider prices each order (a connection per address, B.6b);
|
|
66
|
+
* `costCents` is then 0 and never the product's cost. Absent = `list`.
|
|
67
|
+
*/
|
|
68
|
+
pricedBy?: "list" | "quote";
|
|
42
69
|
leadDays?: number;
|
|
43
70
|
/** Days from each term's start the supplier still takes a change (NCE: 7). */
|
|
44
71
|
changeWindowDays?: number;
|
|
45
|
-
/** Ordered through an app instead of by mail (fase 9). */
|
|
46
|
-
provider?: {
|
|
47
|
-
app: string;
|
|
48
|
-
offer: string;
|
|
49
|
-
};
|
|
50
72
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
73
|
+
* Ordered through an app instead of by mail (fase 9). Where it lands is not the offer's to say:
|
|
74
|
+
* the provider of that platform declares what it needs (047 v2 §2.3).
|
|
53
75
|
*/
|
|
54
|
-
|
|
55
|
-
app: string;
|
|
56
|
-
offer: string;
|
|
57
|
-
};
|
|
76
|
+
provider?: OfferProvider;
|
|
58
77
|
/** The supplier's advised price (the Microsoft ERP price), from a feed (plan 045 G). */
|
|
59
78
|
listCents?: Cents;
|
|
60
79
|
/** The last known stock; only the latest, no history (plan 045 B.1). */
|
|
@@ -73,6 +92,8 @@ export interface OfferAvailability {
|
|
|
73
92
|
at: number;
|
|
74
93
|
source: "feed" | "api" | "manual";
|
|
75
94
|
leadDays?: number;
|
|
95
|
+
/** Until when the choice trusts it: a feed's rhythm × 2, a hand-set stand a day. */
|
|
96
|
+
freshUntil?: number;
|
|
76
97
|
}
|
|
77
98
|
/** Ours to keep, or sold on to a customer — decides where the cost books (fase 6). */
|
|
78
99
|
export type PurchaseUse = "own" | "resale";
|
|
@@ -83,35 +104,43 @@ export interface PurchaseLine extends TransactionLine {
|
|
|
83
104
|
/** Matched to supplier invoices (fase 7). */
|
|
84
105
|
billedQty: number;
|
|
85
106
|
use: PurchaseUse;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
107
|
+
/** What the supplier confirmed (Ingram `quantity_confirmed`, `quantity_back_ordered`). */
|
|
108
|
+
confirmation?: {
|
|
109
|
+
quantity: number;
|
|
110
|
+
backorder?: number;
|
|
111
|
+
promisedAt?: number;
|
|
89
112
|
};
|
|
90
|
-
/**
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
/** The supplier's order for this line: one PO can become several (Ingram `order_split`). */
|
|
114
|
+
supplierRef?: string;
|
|
115
|
+
/**
|
|
116
|
+
* The fulfilment request this line pays for: fulfilment carries it out once the PO is sent. What
|
|
117
|
+
* the act is (a buy, a change, an end) is the request's; the line is what it costs.
|
|
118
|
+
*/
|
|
119
|
+
fulfilmentRequestId?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Server-set with the request: a change or an end on a running subscription. Absent = a buy. An
|
|
122
|
+
* act at no cost expects no invoice, so a PO of ends can be invoiced in full (review 6).
|
|
123
|
+
*/
|
|
124
|
+
act?: Exclude<ProvisioningAction, "purchase">;
|
|
125
|
+
/**
|
|
126
|
+
* Goods: which of fulfilment's allocations this line buys for, in base units (047 §4). Server-
|
|
127
|
+
* set; on a draft the line's quantity is their sum, so two needs share one line only by merging.
|
|
128
|
+
*/
|
|
129
|
+
allocations?: {
|
|
130
|
+
id: string;
|
|
131
|
+
quantity: number;
|
|
132
|
+
}[];
|
|
133
|
+
/**
|
|
134
|
+
* Never stored: on a read the server adds how the request this line pays for stands at
|
|
135
|
+
* fulfilment, so the order page can show it. The supplier's fields live on the request.
|
|
136
|
+
*/
|
|
137
|
+
request?: LineRequest;
|
|
109
138
|
}
|
|
110
139
|
/**
|
|
111
|
-
*
|
|
112
|
-
* a person does it and fills in the result.
|
|
140
|
+
* How a line's request stands, as the order page shows it. `waiting`: not out yet (its account,
|
|
141
|
+
* its day). `manual`: no API — a person does it and fills in the result.
|
|
113
142
|
*/
|
|
114
|
-
export interface
|
|
143
|
+
export interface LineRequest {
|
|
115
144
|
state: ProvisioningState | "waiting" | "manual";
|
|
116
145
|
requestId: string;
|
|
117
146
|
app?: string;
|
|
@@ -121,6 +150,8 @@ export interface LineProvisioning {
|
|
|
121
150
|
key: string;
|
|
122
151
|
reason: string;
|
|
123
152
|
}[];
|
|
153
|
+
/** The supplier's ordering fields as the request holds them. */
|
|
154
|
+
params?: Record<string, string>;
|
|
124
155
|
error?: string;
|
|
125
156
|
attempts?: number;
|
|
126
157
|
nextAttemptAt?: number;
|
|
@@ -134,18 +165,28 @@ export interface DeliverTo {
|
|
|
134
165
|
/** Frozen when the order is sent: what the supplier was told, whatever crm says later. */
|
|
135
166
|
address?: PostalAddress;
|
|
136
167
|
}
|
|
137
|
-
/**
|
|
138
|
-
export
|
|
139
|
-
|
|
168
|
+
/** What a purchase order goes through. Received is its own axis on the lines (`receivedQty`). */
|
|
169
|
+
export type PurchaseStatus = "draft" | "sent" | "confirmed" | "received" | "cancelled" | "superseded";
|
|
170
|
+
/** A purchase order: a {@link Transaction} of kind `purchase_order`; `companyId` is the supplier. */
|
|
171
|
+
export interface PurchaseOrder extends Transaction<PurchaseLine, PurchaseStatus> {
|
|
140
172
|
deliverTo: DeliverTo;
|
|
141
173
|
/** Bought for this customer (the M365 seats for Acme). */
|
|
142
174
|
customerCompanyId?: string;
|
|
175
|
+
/** `full` once every line that expects an invoice is billed: off the match and allocate scans. */
|
|
176
|
+
invoiceState?: InvoiceState;
|
|
143
177
|
}
|
|
178
|
+
export type InvoiceState = "open" | "full";
|
|
144
179
|
export interface GoodsReceiptLine {
|
|
145
180
|
poLineId: string;
|
|
146
181
|
/** Purchase units; positive, the movement says the direction. */
|
|
147
182
|
quantity: number;
|
|
148
183
|
serials: string[];
|
|
184
|
+
/** For a batch-tracked article (046 `tracking: "batch"`): what came in per batch. */
|
|
185
|
+
batches?: {
|
|
186
|
+
code: string;
|
|
187
|
+
quantity: number;
|
|
188
|
+
expiresAt?: number;
|
|
189
|
+
}[];
|
|
149
190
|
/** Still to come, as the packing slip says. */
|
|
150
191
|
backorderQty?: number;
|
|
151
192
|
}
|
|
@@ -153,7 +194,7 @@ export interface GoodsReceiptLine {
|
|
|
153
194
|
export interface GoodsReceipt {
|
|
154
195
|
id: string;
|
|
155
196
|
organizationId: string;
|
|
156
|
-
businessEntityId
|
|
197
|
+
businessEntityId: string;
|
|
157
198
|
movement: "in" | "return";
|
|
158
199
|
purchaseOrderId: string;
|
|
159
200
|
supplierCompanyId: string;
|
|
@@ -164,5 +205,12 @@ export interface GoodsReceipt {
|
|
|
164
205
|
supplierRef?: string;
|
|
165
206
|
status: "draft" | "booked";
|
|
166
207
|
lines: GoodsReceiptLine[];
|
|
208
|
+
/** Flat and indexed: `<productId>#<serial>` of every line, for the register across orders. */
|
|
209
|
+
serialKeys?: string[];
|
|
167
210
|
createdAt?: number;
|
|
168
211
|
}
|
|
212
|
+
/** Per administration: the storage folder packing slips are kept in. */
|
|
213
|
+
export interface PurchaseSettings {
|
|
214
|
+
businessEntityId: string;
|
|
215
|
+
slipFolderId?: string;
|
|
216
|
+
}
|
|
@@ -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 {};
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { Cents } from '../money/money';
|
|
2
|
-
import { TaxCode } from '../money/tax';
|
|
2
|
+
import { IcpKind, TaxCode } from '../money/tax';
|
|
3
3
|
/**
|
|
4
4
|
* The VAT return, computed from posted lines (plan 039 datamodel §7): every line with a VAT code
|
|
5
5
|
* and a tax point in the period adds its base and VAT to the boxes of that code. Pure; the server
|
|
6
6
|
* turns journal lines into `VatLine`s.
|
|
7
7
|
*/
|
|
8
8
|
export interface VatLine {
|
|
9
|
-
/**
|
|
9
|
+
/** The line's `taxSide`; guessed from its account only for a line booked before that existed. */
|
|
10
10
|
side: "sales" | "purchase";
|
|
11
11
|
taxCode: string;
|
|
12
12
|
/** Positive for a sale or a purchase, negative for its credit note. */
|
|
13
13
|
baseCents: Cents;
|
|
14
14
|
taxCents: Cents;
|
|
15
|
+
/** When the VAT arose: the rate is the one of this day. */
|
|
15
16
|
taxPointDate: string;
|
|
17
|
+
/** The return it counts in, when that differs from the tax point's (`JournalLine.vatDate`). */
|
|
18
|
+
vatDate?: string;
|
|
16
19
|
counterpartyCompanyId?: string;
|
|
17
20
|
/** The journal line it came from: the drill-down from a box back to the bookings. */
|
|
18
21
|
ref?: string;
|
|
@@ -31,9 +34,11 @@ export interface VatReturnFigures {
|
|
|
31
34
|
tax?: number;
|
|
32
35
|
}>>;
|
|
33
36
|
/** EC sales list: per customer, the base of the reverse-charged EU sales. */
|
|
34
|
-
/** `name` and `vatNumber`
|
|
37
|
+
/** `name` and `vatNumber` come from the entries' frozen party; a filed return stores them. */
|
|
38
|
+
/** Per customer and column (goods, services, triangular): the list reports them apart. */
|
|
35
39
|
icp: {
|
|
36
40
|
counterpartyCompanyId?: string;
|
|
41
|
+
kind: IcpKind;
|
|
37
42
|
baseCents: Cents;
|
|
38
43
|
name?: string;
|
|
39
44
|
vatNumber?: string;
|
|
@@ -45,8 +50,9 @@ export interface VatReturnFigures {
|
|
|
45
50
|
}
|
|
46
51
|
/**
|
|
47
52
|
* The boxes for one period. Reverse charge on purchase (`selfAssessed`) is owed in its own box
|
|
48
|
-
* and deducted in 5b at the standard rate of its tax point; input VAT counts
|
|
49
|
-
* deductible share. 5a is what is owed (1a–4b), 5b what
|
|
53
|
+
* and deducted in 5b at the standard rate of its tax point; input VAT counts as booked (its
|
|
54
|
+
* non-deductible share is already cost, `documentLinesOf`). 5a is what is owed (1a–4b), 5b what
|
|
55
|
+
* is deducted, 5c and 5g the balance.
|
|
50
56
|
*/
|
|
51
57
|
export declare function vatReturn(input: {
|
|
52
58
|
lines: readonly VatLine[];
|
|
@@ -66,3 +72,12 @@ export declare function vatPeriods(year: number, cadence?: "quarter" | "month" |
|
|
|
66
72
|
to: string;
|
|
67
73
|
dueOn: string;
|
|
68
74
|
}[];
|
|
75
|
+
/**
|
|
76
|
+
* The day a VAT line counts on (Exact's reporting period apart from the entry date): its tax
|
|
77
|
+
* point, or the first day after the last return filed before it was posted, when that is later.
|
|
78
|
+
* A filed return locks no period; what arrives late counts in the next one.
|
|
79
|
+
*/
|
|
80
|
+
export declare function vatDateOf(taxPointDate: string, postedAt: number, filed: readonly {
|
|
81
|
+
to: string;
|
|
82
|
+
filedAt: number;
|
|
83
|
+
}[]): string;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { BookingDocument } from '../../platform/bookkeeping';
|
|
2
|
-
import {
|
|
3
|
-
import { Transaction } from './types';
|
|
2
|
+
import { SalesTransaction } from './types';
|
|
4
3
|
/** The kinds that reach the books. A quote or an order books nothing. */
|
|
5
4
|
export declare const BOOKABLE_KINDS: readonly ["invoice", "credit_note"];
|
|
6
|
-
export declare function isBookable(tx: Pick<
|
|
5
|
+
export declare function isBookable(tx: Pick<SalesTransaction, "kindKey" | "issuedAt">): boolean;
|
|
7
6
|
/**
|
|
8
7
|
* An issued invoice or credit note as the books need it (plan 039 datamodel §3.2). Pure: sales
|
|
9
8
|
* owns the document, and this is the only shape of it that leaves the app.
|
|
10
9
|
*
|
|
11
10
|
* Headings and options carry no amount, so they are not lines here. A reverse charge or
|
|
12
11
|
* exemption ticked on the document replaces every line's code, as it did when it was priced.
|
|
12
|
+
* The party is the one frozen at issue (review R2): no crm read, so nothing live in the hash.
|
|
13
13
|
*/
|
|
14
|
-
export declare function bookingDocumentOf(tx:
|
|
14
|
+
export declare function bookingDocumentOf(tx: SalesTransaction, sourceApp?: string): BookingDocument;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SalesTransaction } from './types';
|
|
2
2
|
/** A transaction with `issuedAt` is frozen. One question, one answer, one place. */
|
|
3
|
-
export declare function isFrozen(transaction: Pick<
|
|
3
|
+
export declare function isFrozen(transaction: Pick<SalesTransaction, "issuedAt">): boolean;
|
|
4
4
|
/**
|
|
5
5
|
* What a frozen transaction still accepts.
|
|
6
6
|
*
|
|
@@ -12,30 +12,30 @@ export declare function isFrozen(transaction: Pick<Transaction, "issuedAt">): bo
|
|
|
12
12
|
*
|
|
13
13
|
* Everything else is a `BadRequestError`. Whoever wants to change a sent quote gets v2.
|
|
14
14
|
*/
|
|
15
|
-
export declare const FROZEN_WRITABLE_FIELDS: readonly (keyof
|
|
15
|
+
export declare const FROZEN_WRITABLE_FIELDS: readonly (keyof SalesTransaction)[];
|
|
16
16
|
/**
|
|
17
17
|
* Issued, numbered kind, no number yet: the books number it and have not answered ("wordt
|
|
18
18
|
* uitgegeven"). It cannot be sent to the customer until the number is on the paper.
|
|
19
19
|
*/
|
|
20
|
-
export declare function awaitsNumber(tx: Pick<
|
|
20
|
+
export declare function awaitsNumber(tx: Pick<SalesTransaction, "issuedAt" | "kindKey" | "number">): boolean;
|
|
21
21
|
/**
|
|
22
22
|
* What a save may set on a draft. `status` is not here: it moves through `issue` and the status
|
|
23
23
|
* route, which check the transition and announce it.
|
|
24
24
|
*/
|
|
25
|
-
export declare const DRAFT_FIELDS: readonly ["companyId", "contactId", "dealItemId", "title", "reference", "currency", "taxOverrideKey", "introText", "termsText", "expiresAt", "deliveredAt", "periodFrom", "periodTo", "paymentTerm", "billingAddressId", "lines"];
|
|
25
|
+
export declare const DRAFT_FIELDS: readonly ["companyId", "contactId", "dealItemId", "title", "reference", "currency", "taxOverrideKey", "introText", "termsText", "expiresAt", "deliveredAt", "periodFrom", "periodTo", "paymentTerm", "billingAddressId", "deliveryAddressId", "invoiceTo", "lines"];
|
|
26
26
|
/**
|
|
27
27
|
* The draft fields a save may empty, named in `clear`. A list and not `null` in the body:
|
|
28
28
|
* `invoke` strips `null`, so "empty this" never reaches the server any other way.
|
|
29
29
|
*/
|
|
30
|
-
export declare const CLEARABLE_FIELDS: readonly ["contactId", "dealItemId", "title", "reference", "taxOverrideKey", "introText", "termsText", "expiresAt", "deliveredAt", "periodFrom", "periodTo", "billingAddressId"];
|
|
30
|
+
export declare const CLEARABLE_FIELDS: readonly ["contactId", "dealItemId", "title", "reference", "taxOverrideKey", "introText", "termsText", "expiresAt", "deliveredAt", "periodFrom", "periodTo", "billingAddressId", "deliveryAddressId", "invoiceTo"];
|
|
31
31
|
export type ClearableField = (typeof CLEARABLE_FIELDS)[number];
|
|
32
32
|
/** The fields a draft carries over; the server owns id, organisation and author. */
|
|
33
|
-
export type TransactionDraft = Omit<
|
|
33
|
+
export type TransactionDraft = Omit<SalesTransaction, "id" | "organizationId" | "createdBy" | "createdAt" | "updatedAt">;
|
|
34
34
|
/**
|
|
35
35
|
* Whether `source` may become a `kindKey`: offered, a step the source's kind allows, and for a
|
|
36
36
|
* correcting kind (a credit note) only from the issued document it corrects.
|
|
37
37
|
*/
|
|
38
|
-
export declare function canConvert(source: Pick<
|
|
38
|
+
export declare function canConvert(source: Pick<SalesTransaction, "kindKey" | "issuedAt">, kindKey: string): boolean;
|
|
39
39
|
/**
|
|
40
40
|
* The conversion: quote -> order -> invoice -> credit note, as one function.
|
|
41
41
|
*
|
|
@@ -47,7 +47,7 @@ export declare function canConvert(source: Pick<Transaction, "kindKey" | "issued
|
|
|
47
47
|
* What is deliberately dropped: the number, the issue date, the due date, the file, the external
|
|
48
48
|
* ids and the dunning history. Those belong to the document that went out, and this is a new one.
|
|
49
49
|
*/
|
|
50
|
-
export declare function copyFrom(source:
|
|
50
|
+
export declare function copyFrom(source: SalesTransaction, kindKey: string): TransactionDraft;
|
|
51
51
|
/**
|
|
52
52
|
* The next version of the same quote.
|
|
53
53
|
*
|
|
@@ -56,4 +56,4 @@ export declare function copyFrom(source: Transaction, kindKey: string): Transact
|
|
|
56
56
|
* afterwards: without this rule you have, a year from now, a quote that was changed after it was
|
|
57
57
|
* signed and no way left to see that.
|
|
58
58
|
*/
|
|
59
|
-
export declare function nextVersion(source:
|
|
59
|
+
export declare function nextVersion(source: SalesTransaction): TransactionDraft;
|
|
@@ -4,7 +4,7 @@ import { TemplateCondition } from '../document-template/types';
|
|
|
4
4
|
import { PricePer } from '../money/period-price';
|
|
5
5
|
import { TaxRate } from '../money/tax';
|
|
6
6
|
import { PostalAddress } from '../organization/types';
|
|
7
|
-
import {
|
|
7
|
+
import { SalesTransaction } from './types';
|
|
8
8
|
/**
|
|
9
9
|
* The seam between a transaction and the paper it is printed on.
|
|
10
10
|
*
|
|
@@ -22,6 +22,9 @@ export interface TransactionContextSources {
|
|
|
22
22
|
/** The customer's postal address, for the recipient block. */
|
|
23
23
|
companyAddress?: PostalAddress;
|
|
24
24
|
contactName?: string;
|
|
25
|
+
/** The debtor's VAT number and debtor number, from the snapshot frozen at issue (review R2). */
|
|
26
|
+
companyVatNumber?: string;
|
|
27
|
+
companyNumber?: string;
|
|
25
28
|
organizationName?: string;
|
|
26
29
|
/** Who the recipient reads; drives which template row is picked. */
|
|
27
30
|
locale?: string;
|
|
@@ -39,7 +42,7 @@ export interface TransactionContextSources {
|
|
|
39
42
|
* quote would be one typo away from the customer. The shield on the way out of the server
|
|
40
43
|
* (`transactionView`) is the second lock; this one is the first.
|
|
41
44
|
*/
|
|
42
|
-
export declare function transactionContext(transaction:
|
|
45
|
+
export declare function transactionContext(transaction: SalesTransaction, sources?: TransactionContextSources): TemplateContext;
|
|
43
46
|
/**
|
|
44
47
|
* The blocks a template cannot write itself: the line table and the totals.
|
|
45
48
|
*
|
|
@@ -50,13 +53,15 @@ export declare function transactionContext(transaction: Transaction, sources?: T
|
|
|
50
53
|
* Amounts arrive already formatted. The blocks layer never computes; that is the whole reason a
|
|
51
54
|
* totals row carries a string.
|
|
52
55
|
*/
|
|
53
|
-
export declare function transactionSlots(transaction:
|
|
56
|
+
export declare function transactionSlots(transaction: SalesTransaction, rates?: readonly TaxRate[], labels?: SlotLabels): DocumentSlots;
|
|
54
57
|
export interface SlotLabels {
|
|
55
58
|
description: string;
|
|
56
59
|
/** Marks a line that is priced but not counted. */
|
|
57
60
|
optional: string;
|
|
58
61
|
quantity: string;
|
|
59
62
|
unitPrice: string;
|
|
63
|
+
/** The line discount column, shown only when a line has one. */
|
|
64
|
+
discount: string;
|
|
60
65
|
/** After a period price: "222,00 per jaar". */
|
|
61
66
|
per: Record<PricePer, string>;
|
|
62
67
|
/** A meter's display unit after a rated quantity: `minute` → "min". Unknown = the key. */
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Cents } from '../money/money';
|
|
2
2
|
import { ReceivableRow } from './receivable';
|
|
3
|
+
/** ponytail: one fixed grace for every administration; a policy field when someone asks. */
|
|
4
|
+
export declare const UNCOLLECTED_AFTER_DAYS = 7;
|
|
3
5
|
/** One step of the schedule. Level 1 counts from the due day, every later one from the last sent. */
|
|
4
6
|
export interface DunningStep {
|
|
5
7
|
level: number;
|
|
@@ -30,8 +32,17 @@ export interface DunningDue {
|
|
|
30
32
|
* every step went out (a person takes over), or `null` when nothing is due yet.
|
|
31
33
|
*/
|
|
32
34
|
export declare function dunningStateOf(row: ReceivableRow, policy: DunningPolicy, today: string): DunningDue | "done" | null;
|
|
33
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* A debit, pin or cash invoice still open `UNCOLLECTED_AFTER_DAYS` past its due day: nobody
|
|
37
|
+
* collects it (no direct-debit run exists yet) and nobody may remind, so a person looks.
|
|
38
|
+
*/
|
|
39
|
+
export declare const isUncollected: (row: ReceivableRow, today: string) => boolean;
|
|
40
|
+
/**
|
|
41
|
+
* The whole run: what is due now per step, what waits for a person after the last step, and the
|
|
42
|
+
* collected-by-us invoices that never came in.
|
|
43
|
+
*/
|
|
34
44
|
export declare function dunningRunOf(rows: readonly ReceivableRow[], policy: DunningPolicy, today: string): {
|
|
35
45
|
due: DunningDue[];
|
|
36
46
|
waiting: ReceivableRow[];
|
|
47
|
+
uncollected: ReceivableRow[];
|
|
37
48
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|