@opencxh/domain 1.293.0 → 1.294.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.
@@ -86,10 +86,41 @@ export interface ReceiptLine {
86
86
  /** The account in the target books (`LedgerOption.key`). */
87
87
  accountKey?: string;
88
88
  aiSuggested?: boolean;
89
+ /** Absent = a cost. Own books only: the line becomes a fixed asset or is spread over months. */
90
+ treatment?: ReceiptLineTreatment;
89
91
  }
92
+ /**
93
+ * What a line becomes besides its booking (plan 041 §4): a fixed asset in a group (its account
94
+ * is then the group's cost account), or a prepaid cost released over months (its account is
95
+ * prepaid costs). Made once, when the receipt is handed to the books.
96
+ */
97
+ export type ReceiptLineTreatment = {
98
+ kind: "asset";
99
+ groupId: string;
100
+ name?: string;
101
+ identifier?: string;
102
+ assignedUserId?: string;
103
+ quantity?: number;
104
+ aiSuggested?: boolean;
105
+ } | {
106
+ kind: "spread";
107
+ months: number;
108
+ /** The first month released, as its first day. */
109
+ firstMonth: string;
110
+ resultAccountId: string;
111
+ };
112
+ /**
113
+ * Proposes "activate" for a line at or above the threshold whose account is a group's cost
114
+ * account: the reader picked a fixed-asset account, the amount says it is one. Never overrides
115
+ * what a person chose; without a threshold (no rule for the country) it proposes nothing.
116
+ */
117
+ export declare function suggestTreatments(lines: readonly ReceiptLine[], groups: readonly {
118
+ id: string;
119
+ costAccountId: string;
120
+ }[], thresholdCents: number | undefined): ReceiptLine[];
90
121
  /** Totals from the lines: the lines are the truth, the totals follow. */
91
122
  export declare function receiptTotals(lines: readonly ReceiptLine[]): Receipt["totals"];
92
- export type ReceiptProblem = "no_supplier" | "no_date" | "no_lines" | "no_account";
123
+ export type ReceiptProblem = "no_supplier" | "no_date" | "no_lines" | "no_account" | "asset_without_group" | "spread_without_months";
93
124
  export declare const RECEIPT_SCOPE_KIND = "receipt";
94
125
  /** The act a sign-off on a receipt is about. */
95
126
  export declare const RECEIPT_BOOK_ACT = "book";
@@ -52,10 +52,31 @@ type PlannedPosting = Omit<ScheduledPosting, "id" | "organizationId" | "business
52
52
  export declare function monthEnd(day: string): string;
53
53
  /** `totalCents` over `months` equal parts; the last takes the rounding, so the parts add up exactly. */
54
54
  export declare function spread(totalCents: Cents, months: number): Cents[];
55
- /** Straight-line depreciation: (cost − residual) over the life, from the month of acquisition. */
55
+ /**
56
+ * The monthly amounts, from the acquisition (or the restart after a revision) on. Linear spreads
57
+ * (start − residual) over the months left; declining takes the monthly share of a yearly
58
+ * percentage of the book value until the residual is reached, the last month exactly; none is
59
+ * nothing. The sum is always start − residual, never below the residual.
60
+ */
61
+ export declare function depreciationParts(t: FixedAssetTerms): Cents[];
62
+ /** Depreciation per month by the asset's method; a disposed asset plans nothing more. */
56
63
  export declare function depreciationPostings(item: Pick<FinancingItem, "id" | "name"> & {
57
64
  terms: FixedAssetTerms;
58
65
  }, through: string): PlannedPosting[];
66
+ /**
67
+ * The memorial entry that takes an asset off the books: its cost and accumulated depreciation
68
+ * off (both on the item, so it ends at nil), the proceeds on the clearing account the sales
69
+ * invoice books against, and the difference on the group's disposal account.
70
+ */
71
+ export declare function disposalLines(item: Pick<FinancingItem, "id" | "name" | "ledgerAccountId"> & {
72
+ terms: FixedAssetTerms;
73
+ }, input: {
74
+ /** The item's booked movements: its accumulated depreciation, negative. */
75
+ movementsCents: Cents;
76
+ proceedsCents: Cents;
77
+ clearingAccountId: string;
78
+ disposalAccountId: string;
79
+ }): PlannedPosting["lines"];
59
80
  /** A transitorium released month by month onto its result account. */
60
81
  export declare function accrualPostings(item: Pick<FinancingItem, "id" | "name" | "ledgerAccountId"> & {
61
82
  terms: AccrualTerms;
@@ -70,4 +91,22 @@ export declare function startingCents(terms: FixedAssetTerms | AccrualTerms): Ce
70
91
  * show it as a short-term liability (aflossingsverplichting), the rest as long-term.
71
92
  */
72
93
  export declare function shortTermPrincipal(terms: Pick<LoanTerms, "principalCents" | "ratePercent" | "method" | "termMonths" | "firstDueOn">, yearEnd: string): Cents;
94
+ /**
95
+ * Part of a batch leaving: its share (quantity / the batch) of cost and accumulated depreciation
96
+ * comes off. The accumulated share leaves the item's sub-account; the cost share leaves the cost
97
+ * account without it, because the item's cost is its terms — they shrink by the same share.
98
+ */
99
+ export declare function partialDisposalLines(item: Pick<FinancingItem, "id" | "name" | "ledgerAccountId"> & {
100
+ terms: FixedAssetTerms;
101
+ }, input: {
102
+ quantity: number;
103
+ movementsCents: Cents;
104
+ proceedsCents: Cents;
105
+ clearingAccountId: string;
106
+ disposalAccountId: string;
107
+ }): {
108
+ lines: PlannedPosting["lines"];
109
+ costCents: Cents;
110
+ residualCents: Cents;
111
+ };
73
112
  export {};
@@ -50,10 +50,12 @@ export interface DepositTerms {
50
50
  kind: "deposit_paid";
51
51
  refundableOn?: string;
52
52
  }
53
+ /** Straight-line over the life, a yearly percentage of the book value, or none (land). */
54
+ export type DepreciationMethod = "linear" | "declining" | "none";
53
55
  /**
54
- * A fixed asset, depreciated straight-line per month from the month it was acquired. The item
55
- * sits under the cost account; depreciation lands on the accumulated-depreciation account, so the
56
- * annual accounts show cost and accumulated apart. Acquisition itself is booked by its invoice.
56
+ * A fixed asset, depreciated per month from the month it was acquired. The item sits under the
57
+ * cost account; depreciation lands on the accumulated-depreciation account, so the annual accounts
58
+ * show cost and accumulated apart. Acquisition itself is booked by its invoice.
57
59
  */
58
60
  export interface FixedAssetTerms {
59
61
  kind: "fixed_asset";
@@ -61,11 +63,95 @@ export interface FixedAssetTerms {
61
63
  costCents: Cents;
62
64
  residualCents: Cents;
63
65
  lifeMonths: number;
66
+ /** Absent on assets made before methods existed: linear. */
67
+ method?: DepreciationMethod;
68
+ /** `declining`: the yearly percentage of the book value, as a decimal string (`"25"`). */
69
+ ratePercent?: string;
64
70
  /** Expense: `Afschrijving inventaris`. */
65
71
  depreciationAccountId: string;
66
72
  /** Contra-asset: `Afschrijving inventaris` under the fixed assets. */
67
73
  accumulatedAccountId: string;
74
+ /** Register: the group it came from, what identifies it, where it is and who uses it. */
75
+ groupId?: string;
76
+ /** A licence plate, a serial number, an address. */
77
+ identifier?: string;
78
+ location?: string;
79
+ assignedUserId?: string;
80
+ /** A batch (12 laptops) is one asset with a quantity. */
81
+ quantity?: number;
82
+ /**
83
+ * A revision (new life, residual or method) from a month on: the schedule starts over from the
84
+ * book value then, numbered on from `fromSequence`, so the terms already posted stay as they are.
85
+ */
86
+ restart?: {
87
+ fromMonth: string;
88
+ bookValueCents: Cents;
89
+ fromSequence: number;
90
+ };
91
+ /**
92
+ * Part of a batch that left (3 of 12 laptops): each took its share of cost, residual and
93
+ * accumulated depreciation off; `costCents`, `residualCents` and `quantity` are what is left.
94
+ */
95
+ partialDisposals?: {
96
+ on: string;
97
+ quantity: number;
98
+ reason: "sold" | "scrapped" | "lost";
99
+ costCents: Cents;
100
+ proceedsCents: Cents;
101
+ buyerCompanyId?: string;
102
+ entryId?: string;
103
+ }[];
104
+ /** Sold, scrapped or lost: booked once, and the schedule stops. */
105
+ disposal?: {
106
+ on: string;
107
+ reason: "sold" | "scrapped" | "lost";
108
+ proceedsCents: Cents;
109
+ buyerCompanyId?: string;
110
+ entryId?: string;
111
+ };
112
+ }
113
+ /**
114
+ * A kind of fixed asset (plan 041 §2): a flat list per administration, no tree. A new asset takes
115
+ * its accounts, method and life from the group; an asset may differ from it.
116
+ */
117
+ export interface AssetGroup {
118
+ id: string;
119
+ organizationId: string;
120
+ businessEntityId: string;
121
+ name: string;
122
+ costAccountId: string;
123
+ /** Absent for a group that is not depreciated (land). */
124
+ accumulatedAccountId?: string;
125
+ depreciationAccountId?: string;
126
+ /** Where a disposal's gain or loss lands: `Boekresultaat vervoermiddelen`. */
127
+ disposalAccountId: string;
128
+ method: DepreciationMethod;
129
+ lifeMonths?: number;
130
+ ratePercent?: string;
131
+ residualPercent?: string;
132
+ archived?: boolean;
133
+ createdAt?: number;
134
+ updatedAt?: number;
68
135
  }
136
+ /**
137
+ * Below this a purchase is a cost, at or above it a fixed asset: per country, an administration
138
+ * may set its own. Only the Netherlands is filled in (€ 450, the fiscal rule); a country comes
139
+ * with its country pack. Known, not built: DE € 800 (GWG), FR € 500 HT, US $ 2,500 (de minimis).
140
+ * BE and UK have no statutory threshold: their own valuation rules decide.
141
+ */
142
+ export declare const CAPITALIZATION_THRESHOLD_CENTS: Readonly<Record<string, Cents>>;
143
+ export declare const capitalizationThreshold: (country?: string, own?: Cents) => Cents | undefined;
144
+ /** The groups a new administration starts with, by template account code. */
145
+ export declare const ASSET_GROUP_SEEDS: readonly {
146
+ name: string;
147
+ cost: string;
148
+ accumulated?: string;
149
+ depreciation?: string;
150
+ disposal: string;
151
+ method: DepreciationMethod;
152
+ lifeMonths?: number;
153
+ residualPercent?: string;
154
+ }[];
69
155
  /**
70
156
  * An amount spread over months (transitoria): prepaid insurance released to costs, revenue
71
157
  * invoiced ahead released to revenue, costs accrued before their invoice. `expense` debits the
@@ -101,6 +187,8 @@ export interface FinancingItem {
101
187
  openedOn?: string;
102
188
  closedOn?: string;
103
189
  archived?: boolean;
190
+ /** Made from a document line (`receipt:<id>:<line>`): once per line. */
191
+ sourceKey?: string;
104
192
  createdAt?: number;
105
193
  updatedAt?: number;
106
194
  }
@@ -33,3 +33,8 @@ export interface LedgerTemplate {
33
33
  */
34
34
  export declare const NL_BV_TEMPLATE: LedgerTemplate;
35
35
  export declare const LEDGER_TEMPLATES: readonly LedgerTemplate[];
36
+ /**
37
+ * The categories a payroll journal books on (HRM, or a package like Nmbrs or Loket), and the
38
+ * template account each lands on unless a posting rule says otherwise.
39
+ */
40
+ export declare const PAYROLL_CATEGORIES: Readonly<Record<string, string>>;
@@ -19,6 +19,11 @@ export interface LedgerAccount {
19
19
  };
20
20
  /** Accounts with detail (bank, loan, current account) require a `subAccountId` on every line. */
21
21
  requiresSubAccount?: boolean;
22
+ /**
23
+ * The VAT code a line on this account usually carries (`TaxCode.key`, e.g. `high`): proposed
24
+ * when a bank line is booked straight onto it. Empty is none.
25
+ */
26
+ defaultTaxCode?: string;
22
27
  /** Where it sits in the reports: `"revenue.net"`, `"costs.office"`. The reports are not hard-coded. */
23
28
  reportGroup?: string;
24
29
  order?: number;
@@ -155,7 +160,7 @@ export interface PostingRule {
155
160
  organizationId: string;
156
161
  businessEntityId: string;
157
162
  appliesTo: {
158
- direction: "sale" | "purchase";
163
+ direction: BookingDocument["direction"];
159
164
  kind?: BookingDocument["kind"];
160
165
  };
161
166
  match: {
@@ -29,6 +29,15 @@ export interface BooksReport {
29
29
  /** Where the figures come from: our books, or a connected package by name. */
30
30
  source: string;
31
31
  }
32
+ /** A report row with its amount in this period and in the one it is compared to. */
33
+ export interface ComparedRow extends BooksReportRow {
34
+ priorCents: Cents;
35
+ }
36
+ /**
37
+ * Two reports of the same kind side by side. A row only one of them has (an account that moved
38
+ * last year and not this year) keeps its place under its own parent, with 0 on the other side.
39
+ */
40
+ export declare function compareReports(current: BooksReport, prior: BooksReport | null): ComparedRow[];
32
41
  /** A posted line as the reports need it: account, day, signed amount (debit +). */
33
42
  export interface ReportLine {
34
43
  accountId: string;
@@ -3,6 +3,6 @@ export * from './attention';
3
3
  export * from './item-types';
4
4
  export * from './keys';
5
5
  export * from './ladder';
6
+ export * from './recurrence';
6
7
  export * from './types';
7
8
  export * from './view';
8
- export * from './recurrence';
@@ -1,6 +1,6 @@
1
- import { WorkRecurrence } from './recurrence';
2
1
  import { Relation } from '../../platform/resource-source';
3
2
  import { OwnerScope } from '../scope/types';
3
+ import { WorkRecurrence } from './recurrence';
4
4
  /**
5
5
  * Work management — one entity for everything that is *work*.
6
6
  *