Instructions for agents working on this brick
Scaffolded from the consolidation module spec by erp-compose scaffold: the shape is done, the rules are not.
Read erp-platform's BRICKS.md before changing anything — the rules (ownership, use cases, data, identity,
tests) and why each one exists.
Your work list
grep -rn "TODO(" src tests # every gap, by kind
pytest -q -rx # one xfail per story still to implement
| Kind | Open |
|---|---|
TODO(ai) | 1 |
TODO(permission) | 21 |
TODO(rule) | 103 |
TODO(scenario) | 6 |
TODO(test) | 26 |
TODO(visibility) | 9 |
TODO(rule): a gate, an effect or a story's Then. Write it indomain/, raisingRuleBrokenin the words a person reads; call thecheck_<story>stub from the transition it guards (or fold it in).TODO(test): rewrite the story's test from its Given/When/Then and remove the xfail mark.TODO(visibility): who sees which rows — the spec's row_visibility rule, in_visible_<root>().TODO(permission): a permission the spec's catalog does not name — add it to the spec, or pick one.TODO(scenario): the scenario's steps over the doors (tests/scenarios/catalogue.py).
The stories
- CON-01 (Group,
check_con_01): the structure in force on a period's last day decides scope and method (full | equity | none); ownership and voting are NUMERIC(9,6) above 0 and [...] - CON-02 (Group,
check_con_02): goodwill = consideration - 80% of net assets = 100,000.00 EUR (86,000.00 GBP at the acquisition rate), non-controlling interest = 20% of net [...] - CON-03 (Group,
check_con_03): consolidation calls gl's GET /group-reporting/balances per company and stores the rows (year-to-date and period, by group account, partner [...] - CON-04 (Group,
check_con_04): balance-sheet accounts at the closing rate, income and expense period by period at each month's average rate (summed year to date), equity at [...] - CON-05 (Group,
check_con_05): per pair and elimination rule (receivable vs payable, loans), an automatic entry removes both sides; the difference within tolerance posts to [...] - CON-06 (Group,
check_con_06): each rule pair (revenue vs cost of sales or expense, interest income vs expense) is removed per pair, the difference to ic_difference_pl; the [...] - CON-07 (Group,
check_con_07): unrealised profit = 12,000.00 x 25% = 3,000.00 EUR, translated at closing: Dr cost of sales (UK01) / Cr inventory (DE01), and deferred tax at [...] - CON-08 (Group,
check_con_08): the investment (G-1600 partner DE01) is eliminated against 80% of the equity at acquisition, goodwill and the NCI at acquisition are posted; the [...] - CON-09 (Group,
check_con_09): FR01's lines are not added line by line; one entry raises the investment by 15,000.00 EUR (30% of the result) to the share of profit of [...] - CON-10 (Group,
check_con_10): the entry is balanced in group currency, names company and partner per line and a movement type where the account tracks movements; it posts [...] - CON-11 (Group,
check_con_11): each line is the sum of translated data and consolidation entries through the version's assignment; each opens to the companies, to the entries [...] - CON-12 (Group,
check_con_12): the rows are validated (accounts exist in the group chart, amounts NUMERIC(18,2), the data nets to zero, partners are group companies) and [...] - CON-13 (Group,
check_con_13): readiness lists each gate as {gate, met, reason, fix}: every company in scope collected and current, each company's and the translated data nets [...] - CON-14 (Group,
check_con_14): the sign-off records who, when and the digest of the consolidated trial balance; the preparer cannot sign (email AND sub); signed figures are [...] - CON-16 (Group,
check_con_16): DE01's profit and loss is consolidated up to 2027-06 and its balance sheet no longer from that period's end; the gain = proceeds - (the group's [...] - CON-17 (Group,
check_con_17): without a change of control the difference between the price and the NCI given up goes to group equity (IFRS 10.23), not to profit, and the NCI [...] - CON-18 (Group,
check_con_18): every check is equal or explained where explaining is allowed; carried consolidated balances per group account and period must be equal; signing [...] - CON-19 (Group,
check_con_19): the accountant is refused (a control); the owner's row takes effect from tomorrow (business date in business_timezone), never today or earlier; [...] - CON-15 (Group,
check_con_15): cumulative entries' balance-sheet lines open FY2027 (per group account, company, partner, segment); their P&L effect opens on group retained [...] - CON-20 (Group,
check_con_20): DE01's new digest is stored, translation and eliminations become stale (the period moves back to collected), the next translate and eliminate [...] - CON-21 (Group,
check_con_21): the stored figures equal a fresh computation at the sign-off digest, and the second run changes nothing (keyed report, group, period, node) - CON-30 (Group,
check_con_30): the rows, the period status, the functional currency, the unmapped accounts and the digest come back; consolidation stores them as reported data [...] - CON-31 (Group,
check_con_31): the matched items and breaks come back; an accepted break is eliminated to ic_difference; an unaccepted one above tolerance blocks the pair; no [...] - CON-32 (Group,
check_con_32): the rates in force come back; a 404 names the currency, type and date and blocks translation with gl's fix - CON-33 (Group,
check_con_33): the lists come back; a structure row naming a company gl does not know is refused; a report on a version that is not published is refused - CON-34 (Group,
check_con_34): the structure per period, the account rules and the consolidation journals of closed periods written read-only, keyed on the Odoo record; a [...]
Where a change goes
| You are changing… | It goes in |
|---|---|
| a business rule | domain/ — and its test in tests/test_rules.py |
| who may do something, or which rows they see | application/ — the permission, or _visible_<root>() |
| a new action for people and agents | a new use case in application/use_cases.py — a route AND a tool |
| a column or table | infrastructure/tables.py AND schema.sql (append; never drop or rename) and a new migrations/NNNNN_<name>/ |
Never add an HTTP route or an MCP tool by hand. Never import SQLAlchemy, FastAPI or MCP in domain/. Don't
write to another brick's tables — call its seam. Don't write an upsert by hand — use the repository.
Before you commit
pytest -q --tb=short # rules + both doors + schema + composition, no bucket
ruff check src tests
State: slices A and B done (CON-01..14)
Built: structure + acquisition (application/structure.py), collect/translate/eliminate incl. investments, NCI and the equity method
(application/runs.py), uploads, readiness, sign-off and reopen (application/close.py), statements (application/reports.py), manual
entries (use cases + domain/cons_journal.py), pure arithmetic (domain/consolidation.py), gl port (infrastructure/seams.py, fake in
tests/fakes.py shaped only from gl's signed spec), bulk rows and number claims (infrastructure/data.py). Every group-level operation
saves the Group aggregate (0.9.6 snapshot save), so a run, a manual entry, a sign-off, a reopen and an upload acceptance of one group collide on
cons_group_versions; entry numbers are claimed on cons_number_series (plain INSERT, claim_tables). tests/test_statement_budget.py pins
every request path's statements (flat from 2 to 10 companies, count_statements). Later slices: C (CON-15..21), D (CON-30..34).