@ekwo-ai/xbrl-cbso 0.4.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 (56) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/LICENSE +21 -0
  3. package/README.md +202 -0
  4. package/dist/enterprise-number.d.ts +9 -0
  5. package/dist/enterprise-number.d.ts.map +1 -0
  6. package/dist/enterprise-number.js +18 -0
  7. package/dist/enterprise-number.js.map +1 -0
  8. package/dist/equations.d.ts +35 -0
  9. package/dist/equations.d.ts.map +1 -0
  10. package/dist/equations.js +77 -0
  11. package/dist/equations.js.map +1 -0
  12. package/dist/errors.d.ts +9 -0
  13. package/dist/errors.d.ts.map +1 -0
  14. package/dist/errors.js +12 -0
  15. package/dist/errors.js.map +1 -0
  16. package/dist/fact-keys.d.ts +68 -0
  17. package/dist/fact-keys.d.ts.map +1 -0
  18. package/dist/fact-keys.js +121 -0
  19. package/dist/fact-keys.js.map +1 -0
  20. package/dist/generator.d.ts +73 -0
  21. package/dist/generator.d.ts.map +1 -0
  22. package/dist/generator.js +394 -0
  23. package/dist/generator.js.map +1 -0
  24. package/dist/index.d.ts +11 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +8 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/pcmn/index.d.ts +68 -0
  29. package/dist/pcmn/index.d.ts.map +1 -0
  30. package/dist/pcmn/index.js +266 -0
  31. package/dist/pcmn/index.js.map +1 -0
  32. package/dist/rounding.d.ts +25 -0
  33. package/dist/rounding.d.ts.map +1 -0
  34. package/dist/rounding.js +35 -0
  35. package/dist/rounding.js.map +1 -0
  36. package/dist/taxonomy/cbso-26-m01-f.d.ts +17 -0
  37. package/dist/taxonomy/cbso-26-m01-f.d.ts.map +1 -0
  38. package/dist/taxonomy/cbso-26-m01-f.js +433 -0
  39. package/dist/taxonomy/cbso-26-m01-f.js.map +1 -0
  40. package/dist/taxonomy/identification.d.ts +13 -0
  41. package/dist/taxonomy/identification.d.ts.map +1 -0
  42. package/dist/taxonomy/identification.js +16 -0
  43. package/dist/taxonomy/identification.js.map +1 -0
  44. package/dist/taxonomy/index.d.ts +27 -0
  45. package/dist/taxonomy/index.d.ts.map +1 -0
  46. package/dist/taxonomy/index.js +83 -0
  47. package/dist/taxonomy/index.js.map +1 -0
  48. package/dist/types.d.ts +149 -0
  49. package/dist/types.d.ts.map +1 -0
  50. package/dist/types.js +2 -0
  51. package/dist/types.js.map +1 -0
  52. package/dist/validate.d.ts +4 -0
  53. package/dist/validate.d.ts.map +1 -0
  54. package/dist/validate.js +84 -0
  55. package/dist/validate.js.map +1 -0
  56. package/package.json +65 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,66 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to
5
+ [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.2.0] — 2026-09-14
10
+
11
+ Released with Ekwo OS `v0.2.0`, the first tagged release of the repository this
12
+ package lives in.
13
+
14
+ ### Fixed
15
+ - **A negative half was rounded the wrong way.** The equations and the PCMN
16
+ mapping used `Math.round(v * 100) / 100`, which goes towards positive
17
+ infinity and turns `-0.005` into `-0.00`, and which reads `2.675` as `2.67`
18
+ because `2.675 * 100` is really `267.49999999999994`. The new `roundCurrency`
19
+ rounds half up on the absolute value, and is the same file in the three
20
+ packages that hold a copy.
21
+ - **53 reporting codes were filed under the wrong fact**, among them nine pairs that were
22
+ swapped with each other: `22/27` (Immobilisations corporelles) with `24` (Mobilier et
23
+ matériel roulant), `20/58` (TOTAL DE L'ACTIF) with `10/49` (TOTAL DU PASSIF), `10`
24
+ (Capital) with `10/11` (Apport), `65` with `65/66B` (Charges financières), `14`
25
+ (Bénéfice à reporter) with `9906` (Bénéfice à affecter), `8179` with `8309` in the
26
+ fixed-assets annex, and nine rows of the social balance sheet. `29` (Créances à plus d'un
27
+ an), `44` (Dettes commerciales), `62` (Rémunérations) and `66A` were filed under `902`,
28
+ `440/4`, `1023` and `29`. Every correction is sourced in
29
+ [`docs/sources.md`](docs/sources.md) and pinned by `test/rubrics.test.ts`.
30
+
31
+ ### Changed
32
+ - **Target framework is now CBSO 26.0**, in use by the Central Balance Sheet Office since
33
+ 2 January 2026: `link:schemaRef` points at `fws/26.0/mod/m01/m01-f.xsd` and the
34
+ enumeration namespaces move to `26.0`. The abridged model itself did not change between
35
+ 25.0 and 26.0 — the generator produces the same 430 facts against either framework — but
36
+ the postal-code enumeration follows the municipality mergers of 1 January 2025.
37
+ - The reporting-code table is **generated** from the NBB taxonomy package by
38
+ `scripts/build-taxonomy.mjs`, no longer transcribed by hand, and covers the whole model:
39
+ 297 codes and 430 cells, against 106 codes before. `--check` verifies the committed table
40
+ against a package.
41
+ - The previous-year boxes the NBB suffixes with `P` in the annexes (`8059P`, `1003P`) stay
42
+ the `p` column of their base code; `14P`, which is a line of its own, keeps its own code.
43
+ - `CBSO_25_M01F` is renamed `CBSO_26_M01F`; `FRAMEWORK` is exported.
44
+ - `CbsoInput.values` becomes optional, and `unknownCodes` returns a sorted array.
45
+
46
+ ### Added
47
+ - `CbsoInput.lines`: statement lines keyed by their fact signature
48
+ (`met:am1|bas:m9|rst:m2`) instead of by a reporting code, so the mapping can live in the
49
+ system that produced the statement rather than being copied here. `CbsoInput.values`
50
+ remains supported as the legacy path, and the two can be combined.
51
+ - `resolveFactKey`, `valuesFromFactKeys`, `parseFactKey`, `factKeyOf`, `mergeValues` and
52
+ `CbsoFactKeyError`, which names the candidate codes when a key fits more than one line.
53
+ - `unfiledValues(input)`: figures that would be dropped, because the code is unknown or
54
+ because the model has no such column.
55
+ - `docs/sources.md`: where every assertion comes from, and what still needs a filing to
56
+ confirm it.
57
+
58
+ ## [0.1.0] — 2026-09-11
59
+
60
+ ### Added
61
+ - `generateCbsoXbrl` / `XbrlCbso`: XBRL instance generator for the CBSO taxonomy,
62
+ abridged model for companies with capital (m01-f), with board members (natural persons,
63
+ legal entities, permanent representatives, foreign addresses).
64
+ - `checkBnbEquations`: arithmetic identities of the abridged model.
65
+ - `validateInput`, `CbsoInputError`, enterprise-number helpers.
66
+ - `@ekwo-ai/xbrl-cbso/pcmn`: Belgian minimum chart of accounts → reporting codes.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ekwo AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,202 @@
1
+ # @ekwo-ai/xbrl-cbso
2
+
3
+ Generate the XBRL file of Belgian annual accounts for the National Bank of Belgium
4
+ (Central Balance Sheet Office, *CBSO* / *Centrale des bilans* / *Balanscentrale*),
5
+ taxonomy **26.0**, abridged model for companies with capital (**m01-f**).
6
+
7
+ - **Pure TypeScript, zero runtime dependencies.** Works in Node ≥ 18, Deno, Bun and browsers.
8
+ - **Generated from the official taxonomy.** The 297 reporting codes of the model (430 cells,
9
+ current and previous year), with their metric and dimension members, are read straight out of
10
+ the NBB taxonomy package by
11
+ [`scripts/build-taxonomy.mjs`](scripts/build-taxonomy.mjs) — not transcribed by hand. Sources
12
+ and method: [`docs/sources.md`](docs/sources.md).
13
+ - **Two ways in.** Reporting codes (`20/58`, `9904`), or the fact keys a book-keeping system
14
+ already stores next to each statement line (`met:am1|bas:m9|rst:m2`).
15
+ - **Partial forms welcome.** Only the codes you provide are emitted; Filing fills the rest.
16
+ `unknownCodes()` tells you which of your codes the model would skip.
17
+ - **Built-in checks.** Enterprise-number check digits, ISO dates, Belgian postal codes, and the
18
+ arithmetic identities of the form (`20/58 = 10/49`, `9904 = 9903 + 780 − 680 − 67/77`, …).
19
+ - **Optional PCMN layer.** Turn a trial balance (Belgian minimum chart of accounts) into the
20
+ reporting codes.
21
+
22
+ ## Install
23
+
24
+ ```sh
25
+ npm install @ekwo-ai/xbrl-cbso
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ```ts
31
+ import { generateCbsoXbrl, checkBnbEquations, LegalForm, EnterpriseCourt } from '@ekwo-ai/xbrl-cbso';
32
+
33
+ const input = {
34
+ entityNumber: '0123.456.749',
35
+ denomination: 'Exemple Conseil',
36
+ legalForm: LegalForm.SA_NV, // 'lgf:m014'
37
+ court: EnterpriseCourt.BRUSSELS_FR, // 'cct:m31'
38
+ address: { street: "Rue de l'Exemple", number: '1', postalCode: '1000', city: 'Bruxelles' },
39
+ periodStart: '2025-01-01',
40
+ periodEnd: '2025-12-31',
41
+ prevPeriodStart: '2024-01-01',
42
+ prevPeriodEnd: '2024-12-31',
43
+ gaDate: '2026-05-15', // general meeting approving the accounts
44
+ deedDate: '2019-03-04', // deed of incorporation / latest amendment of the articles
45
+ values: {
46
+ '20/58': { n: 201500, p: 171000 }, // total assets, current and previous year
47
+ '10/49': { n: 201500, p: 171000 },
48
+ '9904': { n: 57500, p: 43600 },
49
+ '9087': { n: 3.5, p: 3 }, // full-time equivalents
50
+ // … any other code of the abridged model
51
+ },
52
+ administrators: [
53
+ { kind: 'person', lastName: 'Dupont', firstName: 'Marie',
54
+ street: 'Avenue des Tilleuls', number: '12', postalCode: '1180', city: 'Uccle' },
55
+ { kind: 'company', name: 'Gestion Exemple', enterpriseNumber: '0400.000.086',
56
+ street: 'Kerkstraat', number: '7', postalCode: '9000', city: 'Gent',
57
+ representative: { lastName: 'Janssens', firstName: 'Pieter' } },
58
+ ],
59
+ };
60
+
61
+ const violations = checkBnbEquations(input.values); // [] when the form adds up
62
+ const xml = generateCbsoXbrl(input); // string, UTF-8, ready to upload
63
+ ```
64
+
65
+ See [`examples/basic.ts`](examples/basic.ts) for a runnable version (`npm run example`).
66
+
67
+ ### From statement lines that already carry their taxonomy key
68
+
69
+ A book-keeping system that stores the CBSO fact key next to each line of its
70
+ financial statements does not need to know the reporting codes at all. Hand the
71
+ lines over as they are:
72
+
73
+ ```ts
74
+ import { generateCbsoXbrl } from '@ekwo-ai/xbrl-cbso';
75
+
76
+ const xml = generateCbsoXbrl({
77
+ ...identification,
78
+ lines: [
79
+ { xbrl_element: 'met:am1|bas:m2|ntr:m2', amount: 12000, previous_amount: 15000 }, // 22/27
80
+ { xbrl_element: 'met:am1|bas:m5|ntr:m2', amount: 8000, previous_amount: 10000 }, // 24
81
+ { xbrl_element: 'met:am1|bas:m9|rst:m2', amount: 60000, previous_amount: 47500 }, // 40/41
82
+ ],
83
+ });
84
+ ```
85
+
86
+ A key is the metric followed by the domain members that matter; the members that
87
+ only place a fact in a column (`dim:part`, `dim:prd`) may be left out. It
88
+ resolves to the line that adds the fewest members of its own, so
89
+ `met:am1|bas:m2` is the heading *ACTIFS IMMOBILISÉS* (21/28) and not one of the
90
+ three lines under it. A key that fits two lines equally well is refused rather
91
+ than guessed:
92
+
93
+ ```ts
94
+ resolveFactKey('met:am1|bas:m25', CBSO_26_M01F);
95
+ // CbsoFactKeyError: signature shared by 10/49, 20/58 — add the member that
96
+ // separates them (usually a "part:" member)
97
+ ```
98
+
99
+ `met:am1|bas:m25|part:m1` is the total of the assets, `|part:m3` the total of
100
+ the liabilities. `resolveFactKey`, `valuesFromFactKeys` and `factKeyOf` are
101
+ exported for callers that want to do the mapping themselves; `mergeValues`
102
+ shows what a filing would carry when both `values` and `lines` are given, and
103
+ refuses a code that the two disagree on.
104
+
105
+ ### From a trial balance
106
+
107
+ ```ts
108
+ import { valuesFromTrialBalance } from '@ekwo-ai/xbrl-cbso/pcmn';
109
+
110
+ // balance = debit − credit, for the current and the previous year
111
+ const values = valuesFromTrialBalance([
112
+ { account: '400000', balance: 52000, priorBalance: 41000 },
113
+ { account: '440000', balance: -31000, priorBalance: -28000 },
114
+ { account: '700000', balance: -320000, priorBalance: -270000 },
115
+ // …
116
+ ]);
117
+ ```
118
+
119
+ `valuesFromTrialBalance` computes the four sections (assets, equity and liabilities, income
120
+ statement, appropriation) with the sign conventions of the standardised form, and returns them in
121
+ the shape the generator expects. Lower-level functions (`computeBalanceSheet`,
122
+ `computeIncomeStatement`, `computeAppropriation`, the `ASSETS` / `LIABILITIES` /
123
+ `INCOME_STATEMENT` / `APPROPRIATION` tables) are exported for custom pipelines.
124
+
125
+ Annex figures that do not derive from the trial balance (fixed-assets movements `8029`–`8395`,
126
+ staff `9087`, …) are plain codes: add them to `values` yourself.
127
+
128
+ ## API
129
+
130
+ | Export | Description |
131
+ |---|---|
132
+ | `generateCbsoXbrl(input, options?)` | One call: `CbsoInput` → XBRL string. Validates the input unless `options.validate === false`. `options.lang` sets `xml:lang` (default `fr`). |
133
+ | `checkBnbEquations(values, options?)` | Returns the identities that do not add up (`code`, `column`, `expected`, `actual`, `rule`). Missing operands count as zero, as in Filing. |
134
+ | `unknownCodes(values)` | Codes the abridged model does not carry (they would be silently skipped), sorted. |
135
+ | `unfiledValues(input)` | Figures that would be dropped: an unknown code, or a code whose column the model does not have. |
136
+ | `resolveFactKey(key, template)` | `"met:am1\|bas:m9\|rst:m2"` → `"40/41"`. Throws a `CbsoFactKeyError` naming the candidates when the key fits more than one line. |
137
+ | `valuesFromFactKeys(lines, template)`, `factKeyOf(fact)`, `parseFactKey(key)` | The pieces of that path, for callers doing the mapping themselves. |
138
+ | `mergeValues(input, template?)` | `values` plus the resolved `lines`; throws when the two disagree on a code. |
139
+ | `validateInput(input)` | Throws a `CbsoInputError` (`path`, `message`) on the first problem. |
140
+ | `normalizeEnterpriseNumber`, `isValidEnterpriseNumber` | `"BE 0123.456.749"` → `"0123456749"`; mod-97 check digits. |
141
+ | `LegalForm`, `EnterpriseCourt` | Taxonomy members verified against accepted filings. Any other `lgf:*` / `cct:*` member can be passed as a string. |
142
+ | `XbrlCbso`, `CBSO_26_M01F`, `FRAMEWORK`, `NAMESPACES` | Class API and bundled template, for a custom or updated taxonomy. |
143
+
144
+ Types: `CbsoInput`, `FactKeyLine`, `PostalAddress`, `Administrator`, `YearValues`,
145
+ `Declarations`, `TemplateFact`, `CbsoTemplate`.
146
+
147
+ `CbsoInput.values` is the legacy path: it makes the caller hold its own mapping
148
+ from its accounts to the reporting codes of the model. `CbsoInput.lines` exists
149
+ so that mapping can live in one place — the system that produced the statement —
150
+ instead of being copied here. Both stay supported, and they can be combined.
151
+
152
+ ## How it works
153
+
154
+ The CBSO taxonomy carries the reporting code (*rubrique* / *rubriek*) in the **dimensions** of the
155
+ context (`dim:bas → bas:mXX`, `dim:part`, `dim:prd` for current vs previous year…), never in the
156
+ element name: amounts are all `met:am1` / `met:am2`, figures `met:int*` / `met:dec1`. A template
157
+ lists, for each of the 430 cells of the abridged model, that exact signature. The generator:
158
+
159
+ 1. keeps the template facts that have a value (identification fields, reporting codes);
160
+ 2. adds the enumerated identification facts (legal form, court, postal code, country) and the
161
+ board members (typed dimensions keyed by name);
162
+ 3. builds the deduplicated contexts, declares only the namespaces actually used, and formats
163
+ numbers according to the element facets (two decimals for amounts, one for FTEs, integers).
164
+
165
+ The previous financial year is **not** a second period: both columns are reported in a context
166
+ whose period is the closing date of the current year, and `dim:prd` (`prd:m1` / `prd:m2`) says
167
+ which column. The boxes the NBB itself suffixes with `P` in the annexes (`8059P`, `1003P`) measure
168
+ the same thing as their base code one year earlier, so they are its `p` figure. `14P` is not in
169
+ that case — "profit carried forward from the previous year" is a line of its own — and keeps its
170
+ own code.
171
+
172
+ To rebuild the table against a newer taxonomy package:
173
+
174
+ ```sh
175
+ node scripts/build-taxonomy.mjs --package ~/nbb-cbso-26.0.15 # rewrite
176
+ node scripts/build-taxonomy.mjs --package ~/nbb-cbso-26.0.15 --check # verify only
177
+ ```
178
+
179
+ ## Scope and limitations
180
+
181
+ - Model **m01-f** only (abridged, companies with capital). Full and micro models, and the
182
+ non-profit taxonomy, are not covered yet — though the build script takes `--model` and
183
+ `--framework`, so the table for another one is a command away.
184
+ - The **identification** facts (section 1) are not generated: they carry no reporting code, and
185
+ are kept from a filing the NBB accepted. Everything else comes from the taxonomy.
186
+ - Only the legal form and court identifiers verified in accepted filings are named constants;
187
+ other members must be looked up in the taxonomy's `lgf` / `cct` domains.
188
+ - The generator does not validate against the XSD. The NBB *Filing* application remains the
189
+ authority: import the file in a draft and check its validation report before submitting.
190
+
191
+ ## Development
192
+
193
+ ```sh
194
+ npm install
195
+ npm run typecheck
196
+ npm test
197
+ npm run build
198
+ ```
199
+
200
+ ## License
201
+
202
+ [MIT](LICENSE) © Ekwo AI
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Belgian enterprise number (numéro d'entreprise / ondernemingsnummer):
3
+ * ten digits, the last two being `97 - (first eight mod 97)`.
4
+ */
5
+ /** Strip dots, spaces and an optional `BE` prefix: `"BE 0123.456.749"` → `"0123456749"`. */
6
+ export declare function normalizeEnterpriseNumber(raw: string): string;
7
+ /** `true` when the ten-digit number carries valid check digits. */
8
+ export declare function isValidEnterpriseNumber(raw: string): boolean;
9
+ //# sourceMappingURL=enterprise-number.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enterprise-number.d.ts","sourceRoot":"","sources":["../src/enterprise-number.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,4FAA4F;AAC5F,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,mEAAmE;AACnE,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAM5D"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Belgian enterprise number (numéro d'entreprise / ondernemingsnummer):
3
+ * ten digits, the last two being `97 - (first eight mod 97)`.
4
+ */
5
+ /** Strip dots, spaces and an optional `BE` prefix: `"BE 0123.456.749"` → `"0123456749"`. */
6
+ export function normalizeEnterpriseNumber(raw) {
7
+ return raw.replace(/^\s*BE/i, '').replace(/\D/g, '');
8
+ }
9
+ /** `true` when the ten-digit number carries valid check digits. */
10
+ export function isValidEnterpriseNumber(raw) {
11
+ const digits = normalizeEnterpriseNumber(raw);
12
+ if (!/^\d{10}$/.test(digits))
13
+ return false;
14
+ const base = Number(digits.slice(0, 8));
15
+ const check = Number(digits.slice(8));
16
+ return 97 - (base % 97) === check;
17
+ }
18
+ //# sourceMappingURL=enterprise-number.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enterprise-number.js","sourceRoot":"","sources":["../src/enterprise-number.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,4FAA4F;AAC5F,MAAM,UAAU,yBAAyB,CAAC,GAAW;IACnD,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,MAAM,MAAM,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,OAAO,EAAE,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC;AACpC,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Arithmetic identities of the abridged model, as checked by the Filing
3
+ * application. Run them before generating to catch inconsistent inputs early.
4
+ */
5
+ import type { BnbCode, YearValues } from './types.js';
6
+ export interface EquationViolation {
7
+ /** Code of the total that does not add up. */
8
+ code: BnbCode;
9
+ column: 'n' | 'p';
10
+ expected: number;
11
+ actual: number;
12
+ /** Human-readable identity, e.g. `"20/58 = 20 + 21/28 + 29/58"`. */
13
+ rule: string;
14
+ }
15
+ interface Identity {
16
+ total: BnbCode;
17
+ /** Operands with their sign. */
18
+ terms: Array<{
19
+ code: BnbCode;
20
+ sign: 1 | -1;
21
+ }>;
22
+ }
23
+ /** Identities of the abridged model for companies with capital. */
24
+ export declare const ABRIDGED_IDENTITIES: readonly Identity[];
25
+ /**
26
+ * Checks every identity whose total and at least one operand are present in
27
+ * `values`. Missing operands count as zero, as in Filing. Returns the
28
+ * violations (empty = consistent).
29
+ */
30
+ export declare function checkBnbEquations(values: Record<BnbCode, YearValues>, options?: {
31
+ tolerance?: number;
32
+ identities?: readonly Identity[];
33
+ }): EquationViolation[];
34
+ export {};
35
+ //# sourceMappingURL=equations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"equations.d.ts","sourceRoot":"","sources":["../src/equations.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGtD,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,QAAQ;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,gCAAgC;IAChC,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;KAAE,CAAC,CAAC;CAC/C;AAKD,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,EAAE,SAAS,QAAQ,EAiClD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,EACnC,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAA;CAAO,GACrE,iBAAiB,EAAE,CA8BrB"}
@@ -0,0 +1,77 @@
1
+ import { roundCurrency } from './rounding.js';
2
+ const plus = (code) => ({ code, sign: 1 });
3
+ const minus = (code) => ({ code, sign: -1 });
4
+ /** Identities of the abridged model for companies with capital. */
5
+ export const ABRIDGED_IDENTITIES = [
6
+ // Balance sheet
7
+ { total: '20/58', terms: [plus('20'), plus('21/28'), plus('29/58')] },
8
+ { total: '21/28', terms: [plus('21'), plus('22/27'), plus('28')] },
9
+ { total: '22/27', terms: [plus('22'), plus('23'), plus('24'), plus('25'), plus('26'), plus('27')] },
10
+ { total: '29/58', terms: [plus('29'), plus('3'), plus('40/41'), plus('50/53'), plus('54/58'), plus('490/1')] },
11
+ { total: '40/41', terms: [plus('40'), plus('41')] },
12
+ { total: '10/49', terms: [plus('10/15'), plus('16'), plus('17/49')] },
13
+ { total: '10/15', terms: [plus('10/11'), plus('12'), plus('13'), plus('14'), plus('15'), plus('19')] },
14
+ { total: '10/11', terms: [plus('10'), plus('11')] },
15
+ { total: '10', terms: [plus('100'), plus('101')] },
16
+ { total: '13', terms: [plus('130/1'), plus('132'), plus('133')] },
17
+ { total: '17/49', terms: [plus('17'), plus('42/48'), plus('492/3')] },
18
+ { total: '42/48', terms: [plus('42'), plus('43'), plus('44'), plus('46'), plus('45'), plus('47/48')] },
19
+ { total: '45', terms: [plus('450/3'), plus('454/9')] },
20
+ // Balance sheet total = total of liabilities and equity
21
+ { total: '20/58', terms: [plus('10/49')] },
22
+ // Income statement
23
+ { total: '75/76B', terms: [plus('75'), plus('76B')] },
24
+ { total: '65/66B', terms: [plus('65'), plus('66B')] },
25
+ {
26
+ total: '9901',
27
+ terms: [plus('9900'), minus('62'), minus('630'), minus('631/4'), minus('635/8'), minus('640/8'), plus('649'), minus('66A')],
28
+ },
29
+ { total: '9903', terms: [plus('9901'), plus('75/76B'), minus('65/66B')] },
30
+ { total: '9904', terms: [plus('9903'), plus('780'), minus('680'), minus('67/77')] },
31
+ { total: '9905', terms: [plus('9904'), plus('789'), minus('689')] },
32
+ // Appropriation
33
+ { total: '9906', terms: [plus('9905'), plus('14P')] },
34
+ // Fixed assets: net book value = acquisition value − depreciation
35
+ { total: '21', terms: [plus('8059'), minus('8129')] },
36
+ { total: '22/27', terms: [plus('8199'), minus('8329')] },
37
+ { total: '28', terms: [plus('8395')] },
38
+ ];
39
+ /**
40
+ * Checks every identity whose total and at least one operand are present in
41
+ * `values`. Missing operands count as zero, as in Filing. Returns the
42
+ * violations (empty = consistent).
43
+ */
44
+ export function checkBnbEquations(values, options = {}) {
45
+ const tolerance = options.tolerance ?? 0.005;
46
+ const identities = options.identities ?? ABRIDGED_IDENTITIES;
47
+ const violations = [];
48
+ for (const identity of identities) {
49
+ for (const column of ['n', 'p']) {
50
+ const actual = values[identity.total]?.[column];
51
+ if (actual == null)
52
+ continue;
53
+ // An identity whose operands are all absent is not part of the form
54
+ // being filed (e.g. the fixed-assets annex was not provided).
55
+ if (!identity.terms.some((t) => values[t.code]?.[column] != null))
56
+ continue;
57
+ const expected = identity.terms.reduce((sum, t) => sum + t.sign * (values[t.code]?.[column] ?? 0), 0);
58
+ if (Math.abs(expected - actual) > tolerance) {
59
+ violations.push({
60
+ code: identity.total,
61
+ column,
62
+ expected: round2(expected),
63
+ actual: round2(actual),
64
+ rule: `${identity.total} = ${identity.terms
65
+ .map((t, k) => `${t.sign < 0 ? '- ' : k === 0 ? '' : '+ '}${t.code}`)
66
+ .join(' ')}`,
67
+ });
68
+ }
69
+ }
70
+ }
71
+ return violations;
72
+ }
73
+ /** The one rounding rule, at two decimals. See `rounding.ts`. */
74
+ function round2(v) {
75
+ return roundCurrency(v, 2);
76
+ }
77
+ //# sourceMappingURL=equations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"equations.js","sourceRoot":"","sources":["../src/equations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /** Thrown by {@link generateCbsoXbrl} when the input cannot produce a valid filing. */
2
+ export declare class CbsoInputError extends Error {
3
+ /** Dotted path of the offending field, e.g. `"address.postalCode"`. */
4
+ readonly path: string;
5
+ constructor(message: string,
6
+ /** Dotted path of the offending field, e.g. `"address.postalCode"`. */
7
+ path: string);
8
+ }
9
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,qBAAa,cAAe,SAAQ,KAAK;IAGrC,uEAAuE;aACvD,IAAI,EAAE,MAAM;gBAF5B,OAAO,EAAE,MAAM;IACf,uEAAuE;IACvD,IAAI,EAAE,MAAM;CAK/B"}
package/dist/errors.js ADDED
@@ -0,0 +1,12 @@
1
+ /** Thrown by {@link generateCbsoXbrl} when the input cannot produce a valid filing. */
2
+ export class CbsoInputError extends Error {
3
+ path;
4
+ constructor(message,
5
+ /** Dotted path of the offending field, e.g. `"address.postalCode"`. */
6
+ path) {
7
+ super(`${path}: ${message}`);
8
+ this.path = path;
9
+ this.name = 'CbsoInputError';
10
+ }
11
+ }
12
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,OAAO,cAAe,SAAQ,KAAK;IAIrB;IAHlB,YACE,OAAe;IACf,uEAAuE;IACvD,IAAY;QAE5B,KAAK,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QAFb,SAAI,GAAJ,IAAI,CAAQ;QAG5B,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Fact keys — the dimensional way to name a line of the annual accounts.
3
+ *
4
+ * The CBSO taxonomy has no element per reporting code: a code is a generic
5
+ * metric plus a set of explicit dimension members. A fact key writes that
6
+ * signature down, metric first:
7
+ *
8
+ * met:am1|bas:m9|rst:m2 → "Créances à un an au plus" (40/41)
9
+ * met:am2|bas:m44|ntr:m4 → "Bénéfice (Perte) reporté(e)" (14)
10
+ *
11
+ * A key names the members that matter and leaves the rest implicit, so it can
12
+ * be stored next to a statement line without repeating the whole context. It
13
+ * resolves against the template to exactly one reporting code, or throws.
14
+ */
15
+ import { CbsoInputError } from './errors.js';
16
+ import type { BnbCode, CbsoTemplate, TemplateFact, YearValues } from './types.js';
17
+ /**
18
+ * One line of a financial statement, keyed by its fact signature rather than
19
+ * by a reporting code. Shaped after the rows a book-keeping system produces:
20
+ * `xbrl_element` holds the key, `amount` the figure of the financial year.
21
+ */
22
+ export interface FactKeyLine {
23
+ /** Fact key, e.g. `"met:am1|bas:m9|rst:m2"`. */
24
+ xbrl_element: string;
25
+ /** Amount of the current financial year. */
26
+ amount?: number | null;
27
+ /** Amount of the previous financial year, when the line carries one. */
28
+ previous_amount?: number | null;
29
+ }
30
+ /** Thrown when a fact key names no line of the model, or more than one. */
31
+ export declare class CbsoFactKeyError extends CbsoInputError {
32
+ /** The key that could not be resolved. */
33
+ readonly key: string;
34
+ /** Reporting codes the key could stand for, when it is ambiguous. */
35
+ readonly candidates: readonly BnbCode[];
36
+ constructor(message: string,
37
+ /** The key that could not be resolved. */
38
+ key: string,
39
+ /** Reporting codes the key could stand for, when it is ambiguous. */
40
+ candidates?: readonly BnbCode[]);
41
+ }
42
+ interface ParsedKey {
43
+ metric: string;
44
+ members: Record<string, string>;
45
+ }
46
+ /** `"met:am1|bas:m9|rst:m2"` → metric plus `{ "dim:bas": "bas:m9", … }`. */
47
+ export declare function parseFactKey(key: string): ParsedKey;
48
+ /**
49
+ * Reporting code a fact key stands for.
50
+ *
51
+ * Candidates are the facts of the template that carry the key's metric and
52
+ * every one of its members; the winner is the one that adds the fewest members
53
+ * of its own — `met:am1|bas:m2` is "ACTIFS IMMOBILISÉS" (21/28) and not one of
54
+ * the three lines under it. A tie means the key does not say enough: the error
55
+ * lists the codes it could stand for.
56
+ */
57
+ export declare function resolveFactKey(key: string, template: CbsoTemplate): BnbCode;
58
+ /**
59
+ * Turns statement lines keyed by fact signature into the `values` map of
60
+ * {@link CbsoInput}. Lines whose two amounts are both absent are skipped; a
61
+ * code reached twice with conflicting figures is an error, not a silent
62
+ * overwrite.
63
+ */
64
+ export declare function valuesFromFactKeys(lines: readonly FactKeyLine[], template: CbsoTemplate): Record<BnbCode, YearValues>;
65
+ /** Fact key of one template fact, in the same syntax {@link parseFactKey} reads. */
66
+ export declare function factKeyOf(fact: TemplateFact): string;
67
+ export {};
68
+ //# sourceMappingURL=fact-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fact-keys.d.ts","sourceRoot":"","sources":["../src/fact-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAElF;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,gDAAgD;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,2EAA2E;AAC3E,qBAAa,gBAAiB,SAAQ,cAAc;IAGhD,0CAA0C;aAC1B,GAAG,EAAE,MAAM;IAC3B,qEAAqE;aACrD,UAAU,EAAE,SAAS,OAAO,EAAE;gBAJ9C,OAAO,EAAE,MAAM;IACf,0CAA0C;IAC1B,GAAG,EAAE,MAAM;IAC3B,qEAAqE;IACrD,UAAU,GAAE,SAAS,OAAO,EAAO;CAKtD;AAKD,UAAU,SAAS;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAkBnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAiC3E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,QAAQ,EAAE,YAAY,GACrB,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAiB7B;AAED,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAMpD"}