@opencxh/domain 1.243.0 → 1.245.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.
@@ -0,0 +1 @@
1
+ export {};
@@ -9,8 +9,15 @@ export interface FillResult {
9
9
  /** Paths that resolved to nothing, in the order they appeared. Deduplicated. */
10
10
  unresolved: string[];
11
11
  }
12
- /** One string, filled in. */
13
- export declare function fillText(text: string, context: TemplateContext): FillResult;
12
+ /**
13
+ * One string, filled in.
14
+ *
15
+ * `missing` is what an unresolved token becomes. Left out, the token itself stays — the raw
16
+ * form, which a template editor needs to see. A reader does not: `{customer.address}` looks
17
+ * like a bug, where "[nog niet bekend]" says what it is. Either way the path is *reported*, so
18
+ * the issue gate judges the same document whichever form was asked for.
19
+ */
20
+ export declare function fillText(text: string, context: TemplateContext, missing?: string): FillResult;
14
21
  /** Does this block appear? A block with no condition always does. */
15
22
  export declare function conditionHolds(condition: TemplateCondition | undefined, context: TemplateContext): boolean;
16
23
  export interface FillDocumentResult {
@@ -36,4 +43,6 @@ export type DocumentSlots = Record<string, readonly DocumentBlock[]>;
36
43
  * value is the ordinary case for an invoice, and missing one would leave `{invoice.number}`
37
44
  * printed on a document that went out the door.
38
45
  */
39
- export declare function fillDocument(blocks: readonly DocumentBlock[], context: TemplateContext, conditions?: Record<string, TemplateCondition>, slots?: DocumentSlots): FillDocumentResult;
46
+ export declare function fillDocument(blocks: readonly DocumentBlock[], context: TemplateContext, conditions?: Record<string, TemplateCondition>, slots?: DocumentSlots,
47
+ /** What an unresolved token reads as. See {@link fillText}. */
48
+ missing?: string): FillDocumentResult;
@@ -1,4 +1,5 @@
1
1
  import { DocumentBlock } from '../../platform/document-blocks';
2
+ import { PostalAddress } from '../organization/types';
2
3
  /**
3
4
  * A document template: the blocks a generated document is built from.
4
5
  *
@@ -85,3 +86,44 @@ export interface OrganizationHouseStyle {
85
86
  */
86
87
  iban?: string;
87
88
  }
89
+ /**
90
+ * The sender, as a document shows it: the organisation's own details, already turned into lines.
91
+ *
92
+ * Drawn **around** a document rather than written into it — the reason `DocumentBlock` has no
93
+ * sender block. It is computed on the server so the print, the preview and whatever mails a PDF
94
+ * one day all show the same letterhead, and so the renderer needs to know nothing about
95
+ * `Organization`.
96
+ */
97
+ export interface DocumentSender {
98
+ name: string;
99
+ /** Street, postcode + city, country — only the lines that exist. */
100
+ addressLines: string[];
101
+ /** KvK, VAT, IBAN, plus the organisation's own footer sentence. Only what is filled in. */
102
+ footerLines: string[];
103
+ /** Inline data-URI; there is no publicly readable URL for an uploaded file. */
104
+ logo?: string;
105
+ }
106
+ /**
107
+ * An organisation's details as a letterhead.
108
+ *
109
+ * Every field is optional on `Organization`, so every line here is conditional: a half-filled
110
+ * organisation gets a short letterhead, never `undefined, undefined`. The billing name wins over
111
+ * the display name — what is on a quote is the legal entity.
112
+ */
113
+ export declare function organizationSender(organization: OrganizationLike | null | undefined): DocumentSender;
114
+ /**
115
+ * What {@link organizationSender} reads. Structural rather than `Organization` itself, so this
116
+ * file keeps pointing at the organisation entity instead of the other way round.
117
+ */
118
+ export interface OrganizationLike {
119
+ name?: string;
120
+ displayName?: string;
121
+ logo?: string;
122
+ address?: PostalAddress;
123
+ billing?: {
124
+ companyName?: string;
125
+ vatNumber?: string;
126
+ kvkNumber?: string;
127
+ };
128
+ houseStyle?: OrganizationHouseStyle;
129
+ }
@@ -30,5 +30,8 @@ export interface PricedTransaction {
30
30
  *
31
31
  * `overrideKey` is the "reverse charge / exempt" tick on the transaction: it replaces every line's
32
32
  * rate, because that is a property of the sale and not of the product.
33
+ *
34
+ * An **optional** line is priced like any other and then left out of every sum — see
35
+ * `TransactionLine.optional`.
33
36
  */
34
37
  export declare function transactionTotals(lines: readonly TransactionLine[], rates: readonly TaxRate[], overrideKey?: string): PricedTransaction;
@@ -49,6 +49,8 @@ export declare function transactionContext(transaction: Transaction, sources?: T
49
49
  export declare function transactionSlots(transaction: Transaction, rates?: readonly TaxRate[], labels?: SlotLabels): DocumentSlots;
50
50
  export interface SlotLabels {
51
51
  description: string;
52
+ /** Marks a line that is priced but not counted. */
53
+ optional: string;
52
54
  quantity: string;
53
55
  unitPrice: string;
54
56
  net: string;
@@ -110,6 +110,23 @@ export interface TransactionLine {
110
110
  costPriceCents?: Cents;
111
111
  /** The mapping axis onto a chart of accounts, copied from the product's category. */
112
112
  ledgerCategoryKey?: string;
113
+ /**
114
+ * The work item this line is for. Same referent as {@link Transaction.dealItemId}, one level
115
+ * down: a quote may cover one deal while its lines belong to different items under it.
116
+ *
117
+ * An id and never a copied title — whoever owns the item renames it, and a name stored here
118
+ * would be stale the same afternoon. Not printed on the document; it is what the work is
119
+ * booked against, not what the customer reads.
120
+ */
121
+ dealItemId?: string;
122
+ /**
123
+ * An option: priced and shown, but **not** in the total.
124
+ *
125
+ * The amount still stands on the line — the customer has to be able to read what the option
126
+ * costs — so this is a flag on the line and not a second list. Accepting an option is a new
127
+ * version of the quote with the flag off, the same way every other change to a sent quote is.
128
+ */
129
+ optional?: boolean;
113
130
  }
114
131
  export interface TransactionTotals {
115
132
  netCents: Cents;