Multi-entity & FX
Consolidation and currency are where finance UIs produce wrong numbers without anyone noticing. Both ask you to add up figures that look like they add up and don't: two entities that trade with each other, or euros and dollars in one column.
1. The consolidation model#
type Entity = {
id: string; name: string; legalName: string;
functionalCurrency: string; // the currency it primarily operates in
parentId?: string;
ownershipPct: number; // of the immediate parent's interest
consolidationMethod: "full" | "equity" | "proportional" | "none";
fiscalCalendar: FiscalCalendar; // subsidiaries can differ from the parent
};
| Ownership | Method | Treatment |
|---|---|---|
| Control (presumed > 50% of votes; a VIE or IFRS 10 power-and-returns test can override) | Full consolidation | Line-by-line, with non-controlling interest for the minority share |
| Significant influence (presumed 20–50%) | Equity method (ASC 323) | One line: investment in an equity-method investee (IFRS: an associate), moving with the investor's share of profit |
| No significant influence (typically < 20%) | ASC 321 | Equity securities at fair value through net income — or, where fair value is not readily determinable, the measurement alternative (cost less impairment, adjusted for observable price changes) |
| Joint control | Equity method for a joint venture | IFRS 11 joint operations recognize their share of assets and liabilities; US GAAP allows proportionate consolidation only in narrow industries |
UI rules:
- The consolidation scope is always stated in the statement header. "Northwind Holdings Ltd. and subsidiaries" and "Northwind Holdings Ltd. (standalone)" are different statements.
- Entity selection is explicit, never inferred from a user's default. Someone who thinks they're reading the group while looking at one subsidiary will make decisions on the wrong numbers.
- Non-controlling interest appears on both statements: as a component of equity on the balance sheet, and as an allocation of net income on the P&L. Leave it out and the parent's share is overstated.
- Subsidiaries with different fiscal year-ends need aligned reporting or a stated adjustment. The UI flags the mismatch instead of adding them up anyway.
2. Intercompany#
Transactions between group entities eliminate on consolidation. Each entity booked them, and the group never did them.
Entity A sells $100k of services to Entity B
─────────────────────────────────────────────
A: Dr IC receivable 100k / Cr Revenue 100k
B: Dr Expense 100k / Cr IC payable 100k
Group elimination: Dr Revenue 100k / Cr Expense 100k
Dr IC payable 100k / Cr IC receivable 100k
Group effect: zero
UI rules:
- The intercompany matrix must net to zero.
IntercompanyMatrixrenders an entity × entity grid of balances; every cell has an equal and opposite counterpart. Non-zero cells are the exception queue. They're the most common reason a consolidation doesn't tie. - Name the break. Timing differences (one side booked in a later period), FX differences (each side translated at a different rate) and one-sided entries (the other entity never booked it) have different fixes, so the matrix labels the break type instead of showing a bare difference.
- Unrealized profit in inventory (goods sold intercompany and still on hand) is eliminated too. The UI flags it and doesn't compute it, because that takes knowing what's still in stock.
- Elimination entries are
source: "elimination"and exist only at the consolidated level. They never show up in an entity's standalone statements, and the UI makes that boundary visible.
3. Functional vs. presentation currency#
This distinction decides whether an FX difference hits the P&L or equity, and it's an easy one to get backwards.
| Definition | |
|---|---|
| Transaction currency | What the invoice was denominated in |
| Functional currency | The currency of the entity's primary economic environment |
| Presentation currency | What the statements are shown in — IAS 21's term; ASC 830 calls it the reporting currency |
Three different processes, two different destinations:
| Transaction gains and losses | Remeasurement | Translation | |
|---|---|---|---|
| Converts | A foreign-currency-denominated monetary item → functional | Books kept in another currency → functional | Functional → reporting (presentation) |
| FX difference goes to | P&L (ASC 830-20-35-1) | P&L (ASC 830-10-45-17) | Equity (CTA, in OCI — ASC 830-30-45-12) |
| Applies to | One receivable, payable, loan or cash balance | An entity whose ledger is not in its functional currency | An entire foreign operation's statements |
A EUR receivable held by a USD-functional entity produces a P&L gain or loss when rates move. Translate that same entity's statements into a GBP-presentation group and you get a CTA in OCI, which stays out of the P&L until the foreign operation is sold or substantially liquidated and is then reclassified to earnings. Mix the two up and earnings are misstated.
4. Translation rates#
| Item | Rate |
|---|---|
| Assets and liabilities | Closing rate at the balance sheet date |
| Income and expenses | Rate at the date each item is recognized — a weighted-average rate for the period is the usual practical approximation permitted by ASC 830-30-45, and is not appropriate when rates swing within the period |
| Equity | Historical rate at the date of each contribution |
| Retained earnings | Rolled forward, not re-translated |
Mixing rates means the translated balance sheet does not balance. The plug is the cumulative translation adjustment, recorded in other comprehensive income.
UI rules:
- CTA gets its own equity line, never buried. It falls straight out of the method, and hiding it leaves a balance sheet nobody can explain.
- Every translated statement shows the rates used: closing, average and the source. Without the rate, nobody can check the translated number.
- The average-rate method is stated (simple average of daily, monthly weighted, transaction-date). The methods give different results, and you can't compare two periods without knowing which one each used.
- Hyperinflationary economies differ by framework. IFRS (IAS 29) restates for inflation, then translates. US GAAP (ASC 830) remeasures as if the reporting currency were functional, with differences in the P&L. The UI flags the jurisdiction and the framework and doesn't attempt the calculation.
5. FX gain and loss#
Three events, three rates, on a single foreign-currency invoice (the rates are illustrative):
1. Invoice issued Sep 1 €10,000 @ 1.0850 = $10,850 → AR recorded
2. Period end Sep 30 €10,000 @ 1.0920 = $10,920 → unrealized gain $70
3. Payment received Oct 12 €10,000 @ 1.0790 = $10,790 → Sep unrealized gain reverses (−$70)
realized loss $60 vs. invoice rate
(October P&L −$130; cumulative −$60)
UI rules:
- Realized and unrealized are separate lines, never combined. Unrealized reverses and realized doesn't. Show one number and the reader can't tell what happened to the cash.
- The period-end revaluation is a system entry with the rate and source shown, reversing at the start of the next period.
- Only monetary items are revalued. Cash, receivables, payables and debt are. Inventory, fixed assets and prepaids stay at the historical rate. Revaluing a non-monetary item is a common and material error, so the UI derives this from the account classification instead of trusting a flag.
- Every conversion records the rate source and timestamp. An auditor can't test a rate nobody can trace.
6. Rate management#
type ExchangeRate = {
from: string; to: string;
rate: number;
asOf: Date;
type: "spot" | "closing" | "average" | "historical" | "budget";
source: string; // "ECB" | "OANDA" | "manual"
enteredBy?: string; // manual rates need an actor
};
- Rate type is required. The same pair on the same date has a different closing rate and average rate, and the wrong one misstates the figure with nothing on screen to show it.
- Manual rate overrides need a reason and an approver, and look different from sourced rates everywhere they're used.
- A missing rate is a blocking error, never a default of 1.0. Parity is the worst fallback there is: EUR 10,000 becomes $10,000 and the totals still look plausible.
- Inverse rates are computed, never stored separately. Store both and they drift apart.
- Rounding: rates carry 5–6 significant figures; converted amounts round once, at the end, per the currency's minor unit.
7. Multi-entity UI rules#
- Entity is a required dimension on every transaction.
- Every number states its entity scope and its currency.
- Never sum across currencies without a stated conversion, with the rate, the type, and the as-of date reachable.
- A converted value is marked with
≈and its basis in a tooltip. - Entity switching is a full context change, so nothing animates and every cached figure is invalidated. Showing the previous entity's figure for even one frame is a serious error.
- Consolidated and standalone views look different, beyond their labels. The consolidated view carries a persistent scope chip in the header.
- A user with access to some of the entities sees totals for those entities only, and the UI says so. A partial total never passes as the group total.
8. Component set#
| Component | Purpose |
|---|---|
EntitySelector |
Explicit scope, with standalone/consolidated distinction |
ConsolidationView |
Entity columns + eliminations + group total |
IntercompanyMatrix |
Entity × entity, with break types named |
EliminationEntry |
Consolidation-level only, clearly scoped |
NciPanel |
Non-controlling interest on both statements |
TranslationSummary |
Rates used, by type, with sources |
CtaRollForward |
Opening CTA → movement → closing |
FxRevaluation |
Period-end revaluation preview and posting |
FxGainLossPanel |
Realized and unrealized, separated |
RateTable |
By pair, date, and type, with source and overrides flagged |