# Recipes axmo-format-version: ed0892bbbdf4 Each recipe is a complete model in [`../recipes/`](../recipes/), with its data, that **imports with no error and computes the values stated beside it** (`.expected.json`). Its YAML is beside it as text (`.model.yaml`). The build checks every recipe on every change. **Start from the closest recipe** and adapt it; the patterns below are the ones you will need most. | Pattern | Recipe | |---|---| | Combining inputs of different shapes; dropping a dimension through its total; a ratio over totals; a price per country | [kitchenware-production](#a-complete-operational-model) | | A balance carried forward from an opening value | [cash-balance](#a-balance-carried-forward) | | A value that depends on the future | [loan-outstanding](#a-balance-from-the-future) | | A rate that belongs to a higher level than the data | [fx-conversion](#a-rate-held-at-a-higher-level) | | Ratios, weighted averages and shares | [pricing-and-margins](#totals-that-are-not-sums) | | One series from two tables of different shapes; versions; variance | [actual-vs-budget](#actual-versus-budget-from-two-table-shapes) | | A figure entered at a total and split down | [budget-split](#a-top-down-split) | | A dimension built from a table | [generated-dimension](#a-dimension-built-from-data) | | A generated tree with versions, a wide budget with a Total column, a ratio over an averaged headcount | [cost-centre-report](#cost-centre-reporting-from-a-master-list) | | Comparisons, `IF`, powers, `ROUND`, `ISEMPTY`, element ranges, running and year-to-date totals | [formula-forms](#formula-forms) | | A P&L from ledger postings; a budget by line; the last closed month found from the data; a forecast | [pl-from-ledger](#a-pl-from-a-general-ledger) | | A headcount and salary roll-forward; a year-on-year change | `walkthrough-demo` (the axmo.it guide's model) | | A small P&L by country and year; shares; a rank | `intro` | ## A complete operational model **`kitchenware-production.axmo`** — a manufacturer with 20 products, 10 production stages, 4 resources, 4 plants in 3 countries, and 12 months. The Check sheet's bottom-right cell, **25,533.53**, was confirmed in Excel. ```yaml Stage load, h: Production Volume * Production Time / 60 Resource cost: Production Volume * Resource Usage * Resource Price Utilisation: '[Stage load, h][All_Product_Catalog] / Stage Capacity' # FORMULA on every dimension ``` - **Three inputs of different shapes meet in one formula**: volume by product, plant and month; usage by product, stage, resource and plant; price by resource, country and month. - **Utilisation has no product dimension**, so it reads stage load's all-products total. - **Prices are loaded per country**, copied to plants (`COPY`). ## A balance carried forward **`cash-balance.axmo`** ```yaml formula: Nz(Closing Balance[Month[-1]], Opening Balance) + Receipts - Payments dimensions: [{Accounts: {rollUp: SUM}}, {Time: {rollUp: LAST}}] ``` - **In the first month there is no previous month**, so `Nz` falls back to the opening balance, an input over accounts only. - **Across time a balance takes its `LAST` value**: a quarter's balance is its last month's. - **Receipts and payments come from one table by one bulk loader** (`targets`). ## A balance from the future **`loan-outstanding.axmo`** ```yaml formula: Nz(Outstanding[Month[+1]], 0) + Nz(Repayment[Month[+1]], 0) ``` The amount still owed at a month's end is everything repaid after it, so the formula refers to its own **next** value. The last month has no next one, so it is 0. ## A rate held at a higher level **`fx-conversion.axmo`** — the entity tree has a `Currency` layer above `Entity`, so the tree itself maps each entity to its currency. - **Rates are loaded once per currency** and copied down (`splitDown: COPY`). - **`Sales EUR = Sales LC * FX Rate`** is converted month by month, then summed. - **Local-currency sales are not added across entities** (`NONE`). - **A quarter's rate is the average of its months**, but a quarter's euro sales are the **sum of monthly conversions**, not the quarter's sales times the average rate. ## Totals that are not sums **`pricing-and-margins.axmo`** - **Margin %, average price and revenue share use `FORMULA`**, so at every total they are recalculated from that total's margin, revenue and volume. - **`Revenue Share = Revenue / Revenue[All_Products]`** divides by the total element. - **Unit cost is an input with `WEIGHTED_AVG` by volume** on both its dimensions. Its value at a total equals total cost over total volume. ## Actual versus budget from two table shapes **`actual-vs-budget.axmo`** — one series, **Cost**, over Departments × Versions × Time: - **Actuals** arrive as a long table, with one loader and `fixedCoordinates: { Versions: Actual }`; - **the budget** arrives as a wide table, months across the columns, read by **one** loader through the source's `columnLayout: dimension`, with `fixedCoordinates: { Versions: Budget }`; - **Versions are never added** (`NONE`); `Variance = Cost[Actual] - Cost[Budget]`, and `Variance %` uses `FORMULA`. ## A top-down split **`budget-split.axmo`** — each region's quarter target is loaded at `All_Products` and `2027-Q1`: - **To products** in proportion to last year's sales (`PROPORTIONAL`, `driverSeries: Prior Year Sales`). The driver spans products and regions, so both dimensions name it. - **To months equally** (`EQUAL`). ## A dimension built from data **`generated-dimension.axmo`** — the Customers dimension declares only its layers and `All_Customers: null`. Two generators fill it: - **`Segments`** places the segments under the root (`parentElement`); - **`Customers`** places each customer under the segment named in its row (`parentColumn`). They place as one batch, so their names do not matter ([02](02-model-file.md#a-dimension-built-from-data)). ## Cost-centre reporting from a master list **`cost-centre-report.axmo`** — actual cost, budget, variance, variance % and cost per head, by cost centre, department and company, by month and quarter: - **The cost-centre tree is generated** from the master list: departments under the root, and cost centres under their department (`parentColumn`). - **The budget table ends in a `Total` column**, which the band leaves out: `bandEndMode: before`, `bandEndColumn: Total`. - **Headcount sums across cost centres and averages across time** (`AVG`), so `Cost per head = Cost[Actual] / Headcount` with `FORMULA` totals gives a quarter's cost over its average headcount. ## Formula forms **`formula-forms.axmo`** — one calculated series per form in [03](03-formulas-and-totals.md#more-forms). Each totals with `NONE`, so read it month by month. ## A P&L from a general ledger **`pl-from-ledger.axmo`** — the *P&L Budget vs Actuals from the general ledger* demo: ledger postings by account and cost centre, against a budget by P&L line. - **The P&L tree is generated** from an Element/Parent table and the chart of accounts (each account under its line). - **The ledger loads as exported** (`duplicateHandling: SUM`) from an Excel Table (`namedStructures`), so new rows load on the next Update. **Signs belong to lines**, copied to their accounts (`COPY`). - **The budget is entered by line, above the accounts**, so it is split down (`EQUAL`). Without the split, `Budget = Budget Input * Sign`, computed at the accounts, reads nothing there, and the load warns. - **The last closed month comes from the data**, as the last month with postings (`WHERE`, in *Month Actual Index*). `IF(Month@ <= Month Actual Index, …)` leaves later months empty, and the forecast takes the budget there.