@opencxh/domain 1.302.0 → 1.303.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 +54 -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 +11 -11
- package/dist/entities/catalog/types.d.ts +15 -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/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 +8 -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 +131 -0
- package/dist/entities/fulfilment/types.d.ts +321 -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 +57 -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 +22 -40
- package/dist/entities/purchase/feed.d.ts +53 -5
- package/dist/entities/purchase/index.d.ts +1 -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 +71 -38
- 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 +123 -68
- package/dist/index.cjs +25 -25
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5160 -4026
- package/dist/platform/bookkeeping.d.ts +8 -8
- package/dist/platform/provisioning.d.ts +210 -13
- package/package.json +1 -1
- /package/dist/entities/{purchase/demand.test.d.ts → agreement/invoice-head.test.d.ts} +0 -0
|
@@ -11,7 +11,7 @@ import { Transaction, TransactionLine } from '../transaction/types';
|
|
|
11
11
|
export interface SupplierOffer {
|
|
12
12
|
id: string;
|
|
13
13
|
organizationId: string;
|
|
14
|
-
businessEntityId
|
|
14
|
+
businessEntityId: string;
|
|
15
15
|
supplierCompanyId: string;
|
|
16
16
|
productId: string;
|
|
17
17
|
/** Their article number. */
|
|
@@ -39,19 +39,23 @@ export interface SupplierOffer {
|
|
|
39
39
|
validFrom?: number;
|
|
40
40
|
validTo?: number;
|
|
41
41
|
minQty?: number;
|
|
42
|
+
/** Ordered in multiples of this many purchase units (Exact `PurchaseLotSize`); `minQty` is no multiple. */
|
|
43
|
+
lotSize?: number;
|
|
44
|
+
/** Ships straight to a customer: never, only, or both (Exact `DropShipment`). Absent = both. */
|
|
45
|
+
dropship?: "no" | "yes" | "optional";
|
|
46
|
+
/**
|
|
47
|
+
* `quote`: no fixed price — the provider prices each order (a connection per address, B.6b);
|
|
48
|
+
* `costCents` is then 0 and never the product's cost. Absent = `list`.
|
|
49
|
+
*/
|
|
50
|
+
pricedBy?: "list" | "quote";
|
|
42
51
|
leadDays?: number;
|
|
43
52
|
/** Days from each term's start the supplier still takes a change (NCE: 7). */
|
|
44
53
|
changeWindowDays?: number;
|
|
45
|
-
/** Ordered through an app instead of by mail (fase 9). */
|
|
46
|
-
provider?: {
|
|
47
|
-
app: string;
|
|
48
|
-
offer: string;
|
|
49
|
-
};
|
|
50
54
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
55
|
+
* Ordered through an app instead of by mail (fase 9). Where it lands is not the offer's to say:
|
|
56
|
+
* the provider of that platform declares what it needs (047 v2 §2.3).
|
|
53
57
|
*/
|
|
54
|
-
|
|
58
|
+
provider?: {
|
|
55
59
|
app: string;
|
|
56
60
|
offer: string;
|
|
57
61
|
};
|
|
@@ -73,6 +77,8 @@ export interface OfferAvailability {
|
|
|
73
77
|
at: number;
|
|
74
78
|
source: "feed" | "api" | "manual";
|
|
75
79
|
leadDays?: number;
|
|
80
|
+
/** Until when the choice trusts it: a feed's rhythm × 2, a hand-set stand a day. */
|
|
81
|
+
freshUntil?: number;
|
|
76
82
|
}
|
|
77
83
|
/** Ours to keep, or sold on to a customer — decides where the cost books (fase 6). */
|
|
78
84
|
export type PurchaseUse = "own" | "resale";
|
|
@@ -83,35 +89,43 @@ export interface PurchaseLine extends TransactionLine {
|
|
|
83
89
|
/** Matched to supplier invoices (fase 7). */
|
|
84
90
|
billedQty: number;
|
|
85
91
|
use: PurchaseUse;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
action?: ProvisioningAction;
|
|
92
|
-
contractLine?: {
|
|
93
|
-
contractId: string;
|
|
94
|
-
lineId: string;
|
|
92
|
+
/** What the supplier confirmed (Ingram `quantity_confirmed`, `quantity_back_ordered`). */
|
|
93
|
+
confirmation?: {
|
|
94
|
+
quantity: number;
|
|
95
|
+
backorder?: number;
|
|
96
|
+
promisedAt?: number;
|
|
95
97
|
};
|
|
96
|
-
/**
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
98
|
+
/** The supplier's order for this line: one PO can become several (Ingram `order_split`). */
|
|
99
|
+
supplierRef?: string;
|
|
100
|
+
/**
|
|
101
|
+
* The fulfilment request this line pays for: fulfilment carries it out once the PO is sent. What
|
|
102
|
+
* the act is (a buy, a change, an end) is the request's; the line is what it costs.
|
|
103
|
+
*/
|
|
104
|
+
fulfilmentRequestId?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Server-set with the request: a change or an end on a running subscription. Absent = a buy. An
|
|
107
|
+
* act at no cost expects no invoice, so a PO of ends can be invoiced in full (review 6).
|
|
108
|
+
*/
|
|
109
|
+
act?: Exclude<ProvisioningAction, "purchase">;
|
|
110
|
+
/**
|
|
111
|
+
* Goods: which of fulfilment's allocations this line buys for, in base units (047 §4). Server-
|
|
112
|
+
* set; on a draft the line's quantity is their sum, so two needs share one line only by merging.
|
|
113
|
+
*/
|
|
114
|
+
allocations?: {
|
|
115
|
+
id: string;
|
|
116
|
+
quantity: number;
|
|
117
|
+
}[];
|
|
118
|
+
/**
|
|
119
|
+
* Never stored: on a read the server adds how the request this line pays for stands at
|
|
120
|
+
* fulfilment, so the order page can show it. The supplier's fields live on the request.
|
|
121
|
+
*/
|
|
122
|
+
request?: LineRequest;
|
|
109
123
|
}
|
|
110
124
|
/**
|
|
111
|
-
*
|
|
112
|
-
* a person does it and fills in the result.
|
|
125
|
+
* How a line's request stands, as the order page shows it. `waiting`: not out yet (its account,
|
|
126
|
+
* its day). `manual`: no API — a person does it and fills in the result.
|
|
113
127
|
*/
|
|
114
|
-
export interface
|
|
128
|
+
export interface LineRequest {
|
|
115
129
|
state: ProvisioningState | "waiting" | "manual";
|
|
116
130
|
requestId: string;
|
|
117
131
|
app?: string;
|
|
@@ -121,6 +135,8 @@ export interface LineProvisioning {
|
|
|
121
135
|
key: string;
|
|
122
136
|
reason: string;
|
|
123
137
|
}[];
|
|
138
|
+
/** The supplier's ordering fields as the request holds them. */
|
|
139
|
+
params?: Record<string, string>;
|
|
124
140
|
error?: string;
|
|
125
141
|
attempts?: number;
|
|
126
142
|
nextAttemptAt?: number;
|
|
@@ -134,18 +150,28 @@ export interface DeliverTo {
|
|
|
134
150
|
/** Frozen when the order is sent: what the supplier was told, whatever crm says later. */
|
|
135
151
|
address?: PostalAddress;
|
|
136
152
|
}
|
|
137
|
-
/**
|
|
138
|
-
export
|
|
139
|
-
|
|
153
|
+
/** What a purchase order goes through. Received is its own axis on the lines (`receivedQty`). */
|
|
154
|
+
export type PurchaseStatus = "draft" | "sent" | "confirmed" | "received" | "cancelled" | "superseded";
|
|
155
|
+
/** A purchase order: a {@link Transaction} of kind `purchase_order`; `companyId` is the supplier. */
|
|
156
|
+
export interface PurchaseOrder extends Transaction<PurchaseLine, PurchaseStatus> {
|
|
140
157
|
deliverTo: DeliverTo;
|
|
141
158
|
/** Bought for this customer (the M365 seats for Acme). */
|
|
142
159
|
customerCompanyId?: string;
|
|
160
|
+
/** `full` once every line that expects an invoice is billed: off the match and allocate scans. */
|
|
161
|
+
invoiceState?: InvoiceState;
|
|
143
162
|
}
|
|
163
|
+
export type InvoiceState = "open" | "full";
|
|
144
164
|
export interface GoodsReceiptLine {
|
|
145
165
|
poLineId: string;
|
|
146
166
|
/** Purchase units; positive, the movement says the direction. */
|
|
147
167
|
quantity: number;
|
|
148
168
|
serials: string[];
|
|
169
|
+
/** For a batch-tracked article (046 `tracking: "batch"`): what came in per batch. */
|
|
170
|
+
batches?: {
|
|
171
|
+
code: string;
|
|
172
|
+
quantity: number;
|
|
173
|
+
expiresAt?: number;
|
|
174
|
+
}[];
|
|
149
175
|
/** Still to come, as the packing slip says. */
|
|
150
176
|
backorderQty?: number;
|
|
151
177
|
}
|
|
@@ -153,7 +179,7 @@ export interface GoodsReceiptLine {
|
|
|
153
179
|
export interface GoodsReceipt {
|
|
154
180
|
id: string;
|
|
155
181
|
organizationId: string;
|
|
156
|
-
businessEntityId
|
|
182
|
+
businessEntityId: string;
|
|
157
183
|
movement: "in" | "return";
|
|
158
184
|
purchaseOrderId: string;
|
|
159
185
|
supplierCompanyId: string;
|
|
@@ -164,5 +190,12 @@ export interface GoodsReceipt {
|
|
|
164
190
|
supplierRef?: string;
|
|
165
191
|
status: "draft" | "booked";
|
|
166
192
|
lines: GoodsReceiptLine[];
|
|
193
|
+
/** Flat and indexed: `<productId>#<serial>` of every line, for the register across orders. */
|
|
194
|
+
serialKeys?: string[];
|
|
167
195
|
createdAt?: number;
|
|
168
196
|
}
|
|
197
|
+
/** Per administration: the storage folder packing slips are kept in. */
|
|
198
|
+
export interface PurchaseSettings {
|
|
199
|
+
businessEntityId: string;
|
|
200
|
+
slipFolderId?: string;
|
|
201
|
+
}
|
|
@@ -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 {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PurchaseStatus } from '../purchase/types';
|
|
2
|
+
import { SalesStatus } from './types';
|
|
2
3
|
/**
|
|
3
4
|
* A kind is a row of flags, not a subclass.
|
|
4
5
|
*
|
|
@@ -11,7 +12,7 @@ import { TransactionStatus } from './types';
|
|
|
11
12
|
* app, on the same type and its own table. A flag that is always `out` in one app and always `in`
|
|
12
13
|
* in the other is an app boundary, not a flag.
|
|
13
14
|
*/
|
|
14
|
-
export interface TransactionKind {
|
|
15
|
+
export interface TransactionKind<S extends string = string> {
|
|
15
16
|
key: string;
|
|
16
17
|
/** i18n key, not text. For a screen that has `t()`. */
|
|
17
18
|
label: string;
|
|
@@ -23,7 +24,7 @@ export interface TransactionKind {
|
|
|
23
24
|
numbered: boolean;
|
|
24
25
|
/** Invert amounts: a credit note is an invoice with a minus sign. */
|
|
25
26
|
signFlip: boolean;
|
|
26
|
-
statuses: readonly
|
|
27
|
+
statuses: readonly S[];
|
|
27
28
|
/**
|
|
28
29
|
* The route segment this kind lives under: `quotes`, `orders`, `invoices`.
|
|
29
30
|
*
|
|
@@ -38,13 +39,13 @@ export interface TransactionKind {
|
|
|
38
39
|
* handler writes `status: "sent"` for everything, and `sent` is not in the status list of an
|
|
39
40
|
* invoice or a credit note.
|
|
40
41
|
*/
|
|
41
|
-
issuedStatus:
|
|
42
|
+
issuedStatus: S;
|
|
42
43
|
/**
|
|
43
44
|
* The answers a person may give after issuing, per status. `draft -> issuedStatus` is not in
|
|
44
45
|
* here: that move is `issue`, with its gate and its number. Walking back one step is allowed —
|
|
45
46
|
* a mis-click on "accepted" must not need a new version.
|
|
46
47
|
*/
|
|
47
|
-
transitions: Partial<Record<
|
|
48
|
+
transitions: Partial<Record<S, readonly S[]>>;
|
|
48
49
|
/** What this kind may become through `convert`. A revision of the same kind is `version`. */
|
|
49
50
|
convertsTo: readonly string[];
|
|
50
51
|
/**
|
|
@@ -54,13 +55,13 @@ export interface TransactionKind {
|
|
|
54
55
|
credits?: string;
|
|
55
56
|
}
|
|
56
57
|
/** What `apps/sales` issues. Another app's kinds live in their own list, same shape. */
|
|
57
|
-
export declare const SALES_KINDS: readonly TransactionKind[];
|
|
58
|
+
export declare const SALES_KINDS: readonly TransactionKind<SalesStatus>[];
|
|
58
59
|
/**
|
|
59
60
|
* Every app's kinds, for looking one up by key. Keys are unique across apps (`invoice` is sales',
|
|
60
61
|
* `purchase_order` will be purchase's), so a key alone names its kind. Never enumerate this in an
|
|
61
62
|
* app: sales lists {@link SALES_KINDS}, or a purchase kind claims sales scopes and series.
|
|
62
63
|
*/
|
|
63
|
-
export declare const TRANSACTION_KINDS: readonly TransactionKind[];
|
|
64
|
+
export declare const TRANSACTION_KINDS: readonly (TransactionKind<SalesStatus> | TransactionKind<PurchaseStatus>)[];
|
|
64
65
|
/**
|
|
65
66
|
* Which kinds the app actually offers today.
|
|
66
67
|
*
|
|
@@ -84,7 +85,7 @@ export declare function listedTransactionKinds(): TransactionKind[];
|
|
|
84
85
|
*/
|
|
85
86
|
export declare function transactionKind(key: string): TransactionKind;
|
|
86
87
|
/** Dutch status names, for the same server-side readers as {@link TransactionKind.name}. */
|
|
87
|
-
export declare const STATUS_NAMES: Record<
|
|
88
|
+
export declare const STATUS_NAMES: Record<SalesStatus | PurchaseStatus, string>;
|
|
88
89
|
/** Where a person may move this document from its current status. Empty on a draft's issue. */
|
|
89
|
-
export declare function nextStatuses(kindKey: string, from:
|
|
90
|
-
export declare function canTransition(kindKey: string, from:
|
|
90
|
+
export declare function nextStatuses<S extends string>(kindKey: string, from: S): readonly S[];
|
|
91
|
+
export declare function canTransition(kindKey: string, from: string, to: string): boolean;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SettlementState } from '../../platform/bookkeeping';
|
|
2
2
|
import { Cents } from '../money/money';
|
|
3
|
-
import {
|
|
3
|
+
import { PaymentTermMethod } from './payment-term';
|
|
4
|
+
import { SalesTransaction } from './types';
|
|
4
5
|
/** One open invoice as "Openstaand" shows it. */
|
|
5
6
|
export interface ReceivableRow {
|
|
6
7
|
id: string;
|
|
@@ -18,11 +19,13 @@ export interface ReceivableRow {
|
|
|
18
19
|
/** The highest dunning step sent, 0 for none. */
|
|
19
20
|
dunningLevel: number;
|
|
20
21
|
lastDunningAt?: number;
|
|
22
|
+
/** How it is paid, from the copied payment condition: a direct debit is not chased. */
|
|
23
|
+
paymentMethod?: PaymentTermMethod;
|
|
21
24
|
}
|
|
22
25
|
export declare const AGING_BUCKETS: readonly ["current", "d1_30", "d31_60", "d61_90", "d90_plus"];
|
|
23
26
|
export type AgingBucket = (typeof AGING_BUCKETS)[number];
|
|
24
27
|
/** `null` for a row that is not open (a draft, cancelled, or paid). */
|
|
25
|
-
export declare function receivableRowOf(tx:
|
|
28
|
+
export declare function receivableRowOf(tx: SalesTransaction, today: string): ReceivableRow | null;
|
|
26
29
|
export declare function agingBucketOf(overdueDays: number): AgingBucket;
|
|
27
30
|
/** Open amount and count per bucket, every bucket present so the strip never jumps. */
|
|
28
31
|
export declare function agingOf(rows: readonly ReceivableRow[]): Record<AgingBucket, {
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { SettledNotice, SettlementState } from '../../platform/bookkeeping';
|
|
2
|
-
import {
|
|
2
|
+
import { SalesTransaction } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Payment and overdue as two axes beside the lifecycle (plan 039 datamodel §2.3): an invoice can
|
|
5
5
|
* be partly paid and overdue at once. Pure, so the list, the job and the notice agree.
|
|
6
6
|
*/
|
|
7
7
|
/** Unpaid until someone or something says otherwise. */
|
|
8
|
-
export declare function paymentStateOf(tx: Pick<
|
|
9
|
-
export declare function isSettled(tx: Pick<
|
|
8
|
+
export declare function paymentStateOf(tx: Pick<SalesTransaction, "settlement">): SettlementState;
|
|
9
|
+
export declare function isSettled(tx: Pick<SalesTransaction, "settlement">): boolean;
|
|
10
10
|
/** Open means: went out, is still live, and not paid. A draft or a cancelled document is not. */
|
|
11
|
-
export declare function isOutstanding(tx: Pick<
|
|
11
|
+
export declare function isOutstanding(tx: Pick<SalesTransaction, "status" | "issuedAt" | "settlement">): boolean;
|
|
12
12
|
/** Overdue on `today` (`"2026-09-26"`): outstanding and past its due day. */
|
|
13
|
-
export declare function isOverdueOn(tx: Pick<
|
|
13
|
+
export declare function isOverdueOn(tx: Pick<SalesTransaction, "status" | "issuedAt" | "settlement" | "dueAt">, today: string): boolean;
|
|
14
14
|
/**
|
|
15
15
|
* What a notice from the books changes on the document, or `null` when it changes nothing. A
|
|
16
16
|
* notice older than what we hold is ignored; posting facts only ever fill in, never overwrite.
|
|
17
17
|
*/
|
|
18
|
-
export declare function settlementPatch(tx: Pick<
|
|
18
|
+
export declare function settlementPatch(tx: Pick<SalesTransaction, "settlement" | "postedAt" | "externalIds" | "number">, notice: SettledNotice): Partial<SalesTransaction> | null;
|
|
19
19
|
/** A person ticking it off by hand, when no books are connected. */
|
|
20
|
-
export declare function manualSettlement(tx: Pick<
|
|
20
|
+
export declare function manualSettlement(tx: Pick<SalesTransaction, "totals">, state: "unpaid" | "paid", now: number): NonNullable<SalesTransaction["settlement"]>;
|