@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.
Files changed (63) hide show
  1. package/dist/entities/agreement/from-quote.d.ts +8 -8
  2. package/dist/entities/agreement/index.d.ts +2 -0
  3. package/dist/entities/agreement/invoice-head.d.ts +21 -0
  4. package/dist/entities/agreement/lifecycle.d.ts +10 -0
  5. package/dist/entities/agreement/period.d.ts +8 -0
  6. package/dist/entities/agreement/prices.d.ts +43 -0
  7. package/dist/entities/agreement/prices.test.d.ts +1 -0
  8. package/dist/entities/agreement/types.d.ts +54 -10
  9. package/dist/entities/bank/match.d.ts +16 -2
  10. package/dist/entities/bank/types.d.ts +12 -0
  11. package/dist/entities/bookkeeping/receipt.d.ts +45 -6
  12. package/dist/entities/bookkeeping/types.d.ts +1 -2
  13. package/dist/entities/business-entity/types.d.ts +11 -15
  14. package/dist/entities/catalog/pricing.d.ts +11 -11
  15. package/dist/entities/catalog/types.d.ts +15 -9
  16. package/dist/entities/company/role.d.ts +14 -0
  17. package/dist/entities/financing/schedule.d.ts +9 -3
  18. package/dist/entities/financing/types.d.ts +17 -6
  19. package/dist/entities/fulfilment/adopt.d.ts +149 -0
  20. package/dist/entities/fulfilment/customers.d.ts +63 -0
  21. package/dist/entities/fulfilment/execute.d.ts +67 -0
  22. package/dist/entities/fulfilment/fulfilment.test.d.ts +1 -0
  23. package/dist/entities/fulfilment/goods.d.ts +72 -0
  24. package/dist/entities/fulfilment/index.d.ts +8 -0
  25. package/dist/entities/fulfilment/path.d.ts +8 -0
  26. package/dist/entities/fulfilment/path.test.d.ts +1 -0
  27. package/dist/entities/fulfilment/rules.d.ts +124 -0
  28. package/dist/entities/fulfilment/target.d.ts +131 -0
  29. package/dist/entities/fulfilment/types.d.ts +321 -0
  30. package/dist/entities/ledger/entry.d.ts +47 -9
  31. package/dist/entities/ledger/types.d.ts +33 -35
  32. package/dist/entities/ledger/xaf.d.ts +3 -0
  33. package/dist/entities/money/tax.d.ts +6 -0
  34. package/dist/entities/money/totals.d.ts +5 -5
  35. package/dist/entities/purchase/choose.d.ts +57 -0
  36. package/dist/entities/purchase/choose.test.d.ts +1 -0
  37. package/dist/entities/purchase/contract.d.ts +44 -25
  38. package/dist/entities/purchase/demand.d.ts +22 -40
  39. package/dist/entities/purchase/feed.d.ts +53 -5
  40. package/dist/entities/purchase/index.d.ts +1 -0
  41. package/dist/entities/purchase/kinds.d.ts +2 -1
  42. package/dist/entities/purchase/logic.d.ts +32 -7
  43. package/dist/entities/purchase/match.d.ts +48 -6
  44. package/dist/entities/purchase/packing-slip.d.ts +23 -0
  45. package/dist/entities/purchase/types.d.ts +71 -38
  46. package/dist/entities/reports/vat.d.ts +20 -5
  47. package/dist/entities/transaction/booking.d.ts +4 -4
  48. package/dist/entities/transaction/convert.d.ts +10 -10
  49. package/dist/entities/transaction/document.d.ts +8 -3
  50. package/dist/entities/transaction/dunning.d.ts +12 -1
  51. package/dist/entities/transaction/facets.test.d.ts +1 -0
  52. package/dist/entities/transaction/keys.d.ts +3 -0
  53. package/dist/entities/transaction/kinds.d.ts +11 -10
  54. package/dist/entities/transaction/receivable.d.ts +5 -2
  55. package/dist/entities/transaction/settlement.d.ts +7 -7
  56. package/dist/entities/transaction/types.d.ts +123 -68
  57. package/dist/index.cjs +25 -25
  58. package/dist/index.d.ts +2 -1
  59. package/dist/index.js +5160 -4026
  60. package/dist/platform/bookkeeping.d.ts +8 -8
  61. package/dist/platform/provisioning.d.ts +210 -13
  62. package/package.json +1 -1
  63. /package/dist/entities/{purchase/demand.test.d.ts → agreement/invoice-head.test.d.ts} +0 -0
@@ -1,6 +1,7 @@
1
1
  import { SettlementState } from '../../platform/bookkeeping';
2
2
  import { DocumentBlock } from '../../platform/document-blocks';
3
3
  import { LineUsage } from '../agreement/types';
4
+ import { PartySnapshot } from '../company/role';
4
5
  import { DocumentSender } from '../document-template/types';
5
6
  import { Cents } from '../money/money';
6
7
  import { PricePer } from '../money/period-price';
@@ -9,43 +10,27 @@ import { PostalAddress } from '../organization/types';
9
10
  import { OwnerScope } from '../scope/types';
10
11
  import { TransactionPaymentTerm } from './payment-term';
11
12
  /**
12
- * The engine: a quote, an order, an invoice, a credit note.
13
+ * What every transaction shares, in either direction: the party, the money, the lines, the paper
14
+ * (plan 051). Sales adds its facet in {@link SalesTransaction}, purchase in `PurchaseOrder`.
13
15
  *
14
16
  * Deliberately **not** called a document. In this repo `Document*` means the sheet of paper —
15
17
  * blocks, templates, slots — and that layer renders a contract as readily as an invoice. A
16
18
  * transaction *has* a document; it is not one. See `plans/SALES-2026-09-14.md` §2.0.
17
19
  */
18
- export interface Transaction {
20
+ export interface Transaction<L extends TransactionLine = TransactionLine, S extends string = string> {
19
21
  id: string;
20
22
  organizationId: string;
21
23
  /** Which kind. See {@link TRANSACTION_KINDS}. In v1 only `quote` is switched on. */
22
24
  kindKey: string;
23
- /**
24
- * The transaction this one came out of: quote -> order -> invoice.
25
- *
26
- * This one field *is* the conversion. `copyFrom()` carries over the lines, the customer, the
27
- * currency and the price sources; there is no second code path per direction, and "which
28
- * invoice belongs to this quote" is an indexed query instead of a hunt.
29
- */
30
- sourceTransactionId?: string;
31
- /** The agreement that produced it, when it came from one. */
32
- agreementId?: string;
33
- /** Version within the same quote. A sent quote is revised, never edited. */
34
- version: number;
35
- previousVersionId?: string;
36
25
  /**
37
26
  * Which sending entity issues this — whose letterhead, whose books, whose number series.
38
27
  *
39
- * Empty means the organisation's default. Frozen at issue: it is not in
28
+ * Always a real id (review 5a-4). Frozen at issue: it is not in
40
29
  * {@link FROZEN_WRITABLE_FIELDS}, so changing it on a sent document is already refused.
41
30
  */
42
- businessEntityId?: string;
31
+ businessEntityId: string;
43
32
  companyId: string;
44
33
  contactId?: string;
45
- /** The work item (the deal) this belongs to. Optional: not every quote has a deal. */
46
- dealItemId?: string;
47
- ownerScope: OwnerScope;
48
- ownerUserId: string;
49
34
  title?: string;
50
35
  reference?: string;
51
36
  currency: string;
@@ -54,7 +39,7 @@ export interface Transaction {
54
39
  * its books in (the ECB rate of that day). Absent in the books' own currency.
55
40
  */
56
41
  fxRate?: string;
57
- status: TransactionStatus;
42
+ status: S;
58
43
  /**
59
44
  * The lines, as a column and not a table.
60
45
  *
@@ -62,11 +47,9 @@ export interface Transaction {
62
47
  * indivisible, which two tables without a transaction cannot do. The price is that "revenue per
63
48
  * product" is not a query; that question is answered from the facts written at issue time.
64
49
  */
65
- lines: TransactionLine[];
50
+ lines: L[];
66
51
  /** Recomputed on every save, stored so a list can sort and add up. */
67
52
  totals: TransactionTotals;
68
- /** Reverse charge or exemption: ticked, never derived. Replaces every line's rate. */
69
- taxOverrideKey?: string;
70
53
  /**
71
54
  * The remark above the lines, and the conditions under them.
72
55
  *
@@ -84,11 +67,63 @@ export interface Transaction {
84
67
  * ride along because the due date is computed at issue, and by then the row may be gone.
85
68
  */
86
69
  paymentTerm?: TransactionPaymentTerm;
70
+ /** Epoch ms. `issuedAt` set = frozen. */
71
+ issuedAt?: number;
72
+ /** Only on a numbered kind, and only at the moment of issuing. */
73
+ number?: string;
74
+ /**
75
+ * The paper as it went out: blocks and letterhead, filled at issue. A frozen document shows
76
+ * this and never re-renders — the customer's address, the sender's IBAN, a VAT rate and the
77
+ * template may all change afterwards, and an invoice must keep saying what it said.
78
+ */
79
+ issuedPaper?: IssuedPaper;
80
+ /** The rendered PDF in `apps/storage`. A reference, never the content. */
81
+ fileRef?: {
82
+ mountId: string;
83
+ fileId: string;
84
+ };
85
+ /**
86
+ * This transaction in external systems (`moneybird:412`). The dedupe axis the ingest pipeline
87
+ * upserts on — without it the second run of an order import creates every order again.
88
+ */
89
+ externalIds?: string[];
90
+ createdBy: string;
91
+ createdAt?: number;
92
+ updatedAt?: number;
93
+ }
94
+ /** Who is invoiced and chased: the invoice recipient, else the customer. Revenue stays the customer's. */
95
+ export declare const debtorOf: (tx: Pick<SalesTransaction, "companyId" | "invoiceTo">) => string;
96
+ /** The sales facet: a quote, an order, an invoice, a credit note. */
97
+ export interface SalesTransaction extends Transaction<SalesLine, SalesStatus> {
98
+ /**
99
+ * The transaction this one came out of: quote -> order -> invoice.
100
+ *
101
+ * This one field *is* the conversion. `copyFrom()` carries over the lines, the customer, the
102
+ * currency and the price sources; there is no second code path per direction, and "which
103
+ * invoice belongs to this quote" is an indexed query instead of a hunt.
104
+ */
105
+ sourceTransactionId?: string;
106
+ /** The agreement that produced it, when it came from one. */
107
+ agreementId?: string;
108
+ /** Version within the same quote. A sent quote is revised, never edited. */
109
+ version: number;
110
+ previousVersionId?: string;
111
+ /** The work item (the deal) this belongs to. Optional: not every quote has a deal. */
112
+ dealItemId?: string;
113
+ ownerScope: OwnerScope;
114
+ ownerUserId: string;
115
+ /** Reverse charge or exemption: ticked, never derived. Replaces every line's rate. */
116
+ taxOverrideKey?: string;
87
117
  /**
88
118
  * The customer's crm address this document goes to (plan 050); absent = its primary billing
89
119
  * address. Read while it is a draft, frozen as `issuedPaper.billingAddress` when it goes out.
90
120
  */
91
121
  billingAddressId?: string;
122
+ /**
123
+ * Where the goods go (Exact `DeliveryAddress`): a crm address of the customer; absent = its
124
+ * primary delivery address. Fulfilment delivers there.
125
+ */
126
+ deliveryAddressId?: string;
92
127
  /**
93
128
  * When it falls due. Computed at issue from the condition, and only for a numbered kind: a quote
94
129
  * does not fall due, it expires — that is `expiresAt`.
@@ -107,24 +142,9 @@ export interface Transaction {
107
142
  */
108
143
  periodFrom?: number;
109
144
  periodTo?: number;
110
- /** Epoch ms. `issuedAt` set = frozen. */
111
- issuedAt?: number;
112
145
  expiresAt?: number;
113
- /** Only on a numbered kind, and only at the moment of issuing. */
114
- number?: string;
115
- /**
116
- * The paper as it went out: blocks and letterhead, filled at issue. A frozen document shows
117
- * this and never re-renders — the customer's address, the sender's IBAN, a VAT rate and the
118
- * template may all change afterwards, and an invoice must keep saying what it said.
119
- */
120
- issuedPaper?: IssuedPaper;
121
146
  /** Posted — to whichever set of books. Set by the push, never by a person. */
122
147
  postedAt?: number;
123
- /** The rendered PDF in `apps/storage`. A reference, never the content. */
124
- fileRef?: {
125
- mountId: string;
126
- fileId: string;
127
- };
128
148
  /** Which dunning step went out when. There is no dunning table. */
129
149
  dunning?: {
130
150
  level: number;
@@ -136,6 +156,11 @@ export interface Transaction {
136
156
  * reconciliation in the books. A separate axis from `status`, and from `overdueSince`: an
137
157
  * invoice can be partly paid and overdue at once (plan 039 datamodel §2.3).
138
158
  */
159
+ /**
160
+ * `isSettled(settlement)` as a flat, indexed column: "what is still open" is a query on it, not
161
+ * a scan of every open invoice. Written with `settlement`, `false` from issue on.
162
+ */
163
+ settled?: boolean;
139
164
  settlement?: {
140
165
  state: SettlementState;
141
166
  paidCents: Cents;
@@ -147,18 +172,18 @@ export interface Transaction {
147
172
  };
148
173
  /** The day it fell overdue, set by a daily job; cleared once paid. Days, not instants. */
149
174
  overdueSince?: string;
150
- /**
151
- * This transaction in external systems (`moneybird:412`). The dedupe axis the ingest pipeline
152
- * upserts on — without it the second run of an order import creates every order again.
153
- */
154
- externalIds?: string[];
155
175
  /** Which credential a change has to be written back with. Two connections, two answers. */
156
176
  source?: {
157
177
  connectionId?: string;
158
178
  };
159
- createdBy: string;
160
- createdAt?: number;
161
- updatedAt?: number;
179
+ /**
180
+ * Who gets the invoice when that is not the customer: the holding that pays for its daughter
181
+ * (KETEN-STAND B2; Exact `InvoiceTo`). Its address is `billingAddressId`. Frozen at issue.
182
+ */
183
+ invoiceTo?: {
184
+ companyId: string;
185
+ contactId?: string;
186
+ };
162
187
  }
163
188
  /**
164
189
  * The statuses, all kinds together. Which kind offers which is {@link TransactionKind.statuses}.
@@ -166,9 +191,7 @@ export interface Transaction {
166
191
  * A union and not a free string: kinds and their statuses are **ours**, not the organisation's.
167
192
  * Labels follow from the key as `status_<key>`.
168
193
  */
169
- export type TransactionStatus = "draft" | "sent" | "accepted" | "rejected" | "expired" | "confirmed" | "delivered"
170
- /** A purchase order whose every line came in. */
171
- | "received" | "open" | "cancelled"
194
+ export type SalesStatus = "draft" | "sent" | "accepted" | "rejected" | "expired" | "confirmed" | "open" | "cancelled"
172
195
  /** A newer version of this document went out. Set by the server, never by a person. */
173
196
  | "superseded";
174
197
  export interface IssuedPaper {
@@ -178,6 +201,8 @@ export interface IssuedPaper {
178
201
  customerName?: string;
179
202
  /** The billing address as it went out (plan 050); the books take this one, not crm's today. */
180
203
  billingAddress?: PostalAddress;
204
+ /** The debtor as it went out: the invoice recipient when there is one, else the customer. */
205
+ counterparty?: PartySnapshot;
181
206
  }
182
207
  export interface TransactionLine {
183
208
  /** Stable within the transaction, so a version diff can follow a line. */
@@ -201,28 +226,46 @@ export interface TransactionLine {
201
226
  pricePer?: PricePer;
202
227
  discountPercent?: number;
203
228
  taxRateKey: string;
204
- /** Which rung of the price ladder produced this amount. Purely to account for it. */
205
- priceSourceKey?: string;
206
229
  /** Step 1 of the rounding order, stored so the client need not recompute. */
207
230
  netCents: Cents;
208
231
  /** This line's share of its rate group's VAT. Shielded, like the cost price. */
209
232
  taxCents: Cents;
233
+ /** The mapping axis onto a chart of accounts, copied from the product's category. */
234
+ ledgerCategoryKey?: string;
235
+ /** The days the line is for: a month of rental, a year of a licence bought (Exact: both sides). */
236
+ servicePeriod?: {
237
+ from: number;
238
+ to: number;
239
+ };
240
+ /**
241
+ * What the line is booked against (049 J, KETEN-STAND B1): the same shape on every line that
242
+ * reaches the books. Ids, never names. `costUnitId` is derived from `projectId` at booking.
243
+ */
244
+ dimensions?: LineDimensions;
245
+ }
246
+ /** Only the known dimensions, as non-empty strings; `undefined` when none is left. */
247
+ export declare function cleanDimensions(raw: unknown): LineDimensions | undefined;
248
+ /** KETEN-STAND B1: the four dimensions a booked line carries, defined once. */
249
+ export declare const DIMENSION_KEYS: readonly ["costCenterId", "costUnitId", "projectId", "customerCompanyId"];
250
+ export interface LineDimensions {
251
+ /** organization (plan 040): a department or branch. */
252
+ costCenterId?: string;
253
+ /** finance (plan 040): a cost unit — a project's, or a car, a building, a grant. */
254
+ costUnitId?: string;
255
+ /** work: a work item of type project. */
256
+ projectId?: string;
257
+ /** crm: for whom, when it is passed on or carries a margin per customer. */
258
+ customerCompanyId?: string;
259
+ }
260
+ /** A sales line: priced on the ladder, billed from hours, usage or an agreement. */
261
+ export interface SalesLine extends TransactionLine {
262
+ /** Which rung of the price ladder produced this amount. Purely to account for it. */
263
+ priceSourceKey?: string;
210
264
  /**
211
265
  * The cost price as it stood when the line was added, per `unitKey`, **in the document's
212
266
  * currency** (converted on that day, plan 046 #16). Shielded by `catalog.product.cost`.
213
267
  */
214
268
  costPriceCents?: Cents;
215
- /** The mapping axis onto a chart of accounts, copied from the product's category. */
216
- ledgerCategoryKey?: string;
217
- /**
218
- * The work item this line is for. Same referent as {@link Transaction.dealItemId}, one level
219
- * down: a quote may cover one deal while its lines belong to different items under it.
220
- *
221
- * An id and never a copied title — whoever owns the item renames it, and a name stored here
222
- * would be stale the same afternoon. Not printed on the document; it is what the work is
223
- * booked against, not what the customer reads.
224
- */
225
- dealItemId?: string;
226
269
  /**
227
270
  * The time entries this line bills. Sales stamps exactly this set onto them on every save, so
228
271
  * the line — not the entry — is the source of truth. Never copied to a new document.
@@ -235,10 +278,6 @@ export interface TransactionLine {
235
278
  * the whole "what was billed" state of an agreement — see `dueCharges`.
236
279
  */
237
280
  agreementLineId?: string;
238
- servicePeriod?: {
239
- from: number;
240
- to: number;
241
- };
242
281
  /** Settles days of a window billed earlier, at the price it was billed at. */
243
282
  correction?: boolean;
244
283
  /**
@@ -249,6 +288,22 @@ export interface TransactionLine {
249
288
  * version of the quote with the flag off, the same way every other change to a sent quote is.
250
289
  */
251
290
  optional?: boolean;
291
+ /**
292
+ * The line it came from when converted: an invoice line points at its order line (KETEN-STAND
293
+ * B3; Exact `SalesInvoiceLine.SalesOrderLine`). "How much of this order line is invoiced" is the
294
+ * sum of the lines pointing at it — derived, never a counter on the order.
295
+ */
296
+ sourceLine?: {
297
+ transactionId: string;
298
+ lineId: string;
299
+ };
300
+ /**
301
+ * The answers to what a provider asks before the promise (047 step 8), by param key; an address
302
+ * is a crm address id (`site: "<addressId>"`). Travel to the agreement and the request.
303
+ */
304
+ answers?: Record<string, string>;
305
+ /** The delivery check made with those answers (fulfilment's `Qualification`). */
306
+ qualificationId?: string;
252
307
  }
253
308
  export interface TransactionTotals {
254
309
  netCents: Cents;