---
id: imobiliario/custo-obra-orcado-realizado
industry: Real estate
usage: common
effort: high
grain: Project x WBS item on the latest budget version; bill x WBS item for the detailed allocation view
---

# Construction cost budget vs. actuals

Budgeted, committed and actual cost for every construction stage, with the variance by sub-stage and physical progress alongside, matching the ERP report.

## Executive summary

**For:** Builders and developers that control construction cost in the ERP and want that report outside it, combined with schedule.

**What it solves**

- Cost by WBS level comes out of the ERP with the same numbers as the official report.
- Engineering sees where each project goes over budget, by sub-stage and item, in time to act.
- Cost and physical progress appear side by side, to tell whether the project is spending faster than it advances.

**Why it matters:** The construction budget is the developer's largest cash commitment, and the project margin depends on it. The ERP report shows the whole project, but it does not rank variances, does not combine with schedule, and only reaches the board exported to a spreadsheet. With the right rules, the same table serves the engineer, finance and the AI agent.

**Business questions it answers**

- How much of each project is already committed and how much has been paid against the budget?
- Which sub-stages and items have the largest cost overruns?
- Is the project spending faster than it advances?
- How much do we have in open advances and retentions with each supplier?
- How much of the budget for each input has already been requested?
- What is the material inventory worth at each site?

**What you need**

- Construction ERP connected (Sienge or UAU), with budget, accounts payable and bank movements
- The map of each project: project id, company (SPE) and cost center
- The planning tool connected (Agilean or Prevision), if you want physical progress

**What you get**

- A cost table by WBS level with budgeted, committed and actual
- A ranking of variances by sub-stage and item
- A detailed allocation view by bill and item, with payments
- The planned, rescheduled and actual physical progress curve next to cost

## Detailed

### The problem

The construction budget is stored in versions, in a tree of WBS (work breakdown structure) codes, and accounts payable bills arrive with nested arrays saying how much of each goes to each project and item. Summing every version, summing parent and child together, or ignoring the allocated percentage delivers a doubled budget and an actual cost that does not match the ERP report. Without this, variance by stage stays in a manual spreadsheet.

### Business rules

1. **Only the latest budget version.** building_cost_estimation_items stores every budget version. For each project and building unit, keep only the highest versionNumber. Summing every version multiplies the budget by the number of revisions. Store the version used in a column, so whoever compares with the ERP knows which one it is. (Avoid: Summing totalPrice across every row of the budget table.)
2. **Leaves to sum, rollup to display.** The wbsCode is hierarchical (for example, 01, 01.002, 01.002.003). For totals, sum only the leaves of the tree, because the parent is already the sum of its children. For the report by level, each code gets the sum of all its descendants (the code itself and those starting with it followed by a dot), not just the entries posted exactly on it. (Avoid: Summing parent and children, or matching entries only by the exact code.)
3. **Committed and actual are different columns.** Committed is everything posted to accounts payable for the item, paid or not. Actual is what has already been paid. Both come from the same bills allocated to the project, with each item's percentage. Budget minus committed is the amount left to contract; committed minus actual is what is left to pay. (Avoid: A single 'cost' column that is sometimes posted and sometimes paid.)
4. **Allocation by the item percentage.** Each bill has the buildingsCosts array with project, unit, WBS item (costEstimationSheetId) and rate. Amount allocated to the item = bill amount x rate / 100, rounded to cents per row. Allocated bank movements use the buldingCosts array (with the API's typo) and a sign by operation: outflow ('S') adds, inflow subtracts. (Avoid: Posting the whole bill to every item or project it mentions.)
5. **Variance only on 100% measured items.** Variance = committed - budgeted: positive is an overrun, negative is a saving. On an item still in progress, committed below budget is just a contract not yet signed, not a saving. Rank variances only for items with percentComplete = 100, by sub-stage (level 1) and by item within the sub-stage (level 2). The rest show as 'in progress', with the measured %. (Avoid: A savings ranking that includes items that just started.)
6. **Check allocation against the cost center.** The same bill carries the percentage by cost center and financial category (paymentsCategories) and the percentage by project (buildingsCosts). When the two disagree for the same project, the bill is misallocated. Generate a list of discrepancies by bill with both percentages, so finance can fix them in the ERP before closing. (Avoid: Trusting one of the arrays without checking the other.)
7. **Project linked by ids, with a map.** The project appears as buildingId in the budget and bills, as costCenterId in inventory and cost centers, and as companyId (the SPE) in finance. Keep a map with project, company and cost center. When only the name is available, the cost center usually ends with the project's abbreviation: match on the exact suffix, never on 'contains'. (Avoid: Finding the project by looking for the abbreviation anywhere in the name.)
8. **Advances and retentions by document type.** Supplier advances and retained deposits are accounts payable bills, identified by documentIdentificationName. Advance balance = balanceAmount of the construction advance bills, by creditor. The retention is allocated to the project through buildingsCosts like any other bill. The API does not link these bills to the supply contract: contract number and measurement date are not returned, and the agent should say so. (Avoid: Making up the retention's contract from the creditor.)
9. **Physical progress comes from the planning tool.** Planned, rescheduled and actual progress (monthly and cumulative), IDP (schedule performance index) and PPC (percent plan complete) come from Agilean or Prevision. Link to the ERP project through the id stored in the tool (in Prevision, siengeprojectid = the Sienge cost center id). Show only months up to the current month. Compare the % of budget committed with the cumulative actual progress %: cost far ahead of progress is an alert. (Avoid: Estimating progress from the percentage of cost paid.)
10. **An input is unique within its cost base.** The same input code can mean different things in different cost bases. The input key is cost base + code. The item key is project + unit + WBS code down to the level used. Budgeted vs. requested by input compares the quantity in the budget composition with the quantity allocated in fulfilled requests, by project and sub-stage. (Avoid: Summing the same input code across cost bases.)

### Where each project value comes from

Standard fields from the Sienge connector.

- **building_cost_estimation_items, highest versionNumber** → Budgeted (`totalPrice`)
- **building_cost_estimation_items** → Measured (`percentComplete, measuredQuantity`)
- **outcome x buildingsCosts, posted** → Committed (`value x rate / 100`)
- **outcome x buildingsCosts, paid** → Actual (`payments`)
- **bank_movement x buldingCosts** → Bank allocation (`sign by operationType 'S'`)
- **advance documentIdentificationName** → Supplier advance (`balanceAmount`)
- **retention documentIdentificationName** → Retained deposit (`no contract in the API`)
- **stock_inventories by costCenterId** → Site inventory (`quantity x averagePrice`)
- **Agilean or Prevision** → Physical progress and IDP (`cumulative actual vs planned`)
- **committed - budgeted on a 100% measured item** → Variance (`positive = cost overrun`)

### Definitions

| Metric | Definition |
|---|---|
| Budgeted | sum of totalPrice of the WBS leaves in the latest budget version, by project, unit and item |
| Committed | sum of the amount allocated to the item (amount x rate / 100) across all posted bills, paid or not, up to the cutoff date |
| Actual | sum of the paid amount allocated to the item, from payment and advance settlements, up to the cutoff date |
| Left to contract | budgeted - committed, by item and by WBS level |
| Variance | committed - budgeted on 100% measured items; variance % = variance / budgeted x 100 |
| % committed | committed / budgeted for the project, compared with cumulative actual physical progress in the same month |
| IDP | schedule performance index from the planning tool: cumulative actual progress / cumulative planned progress, by project and month |
| Advance balance | sum of balanceAmount of open construction advance bills, by creditor and project |
| Site inventory | quantity x averagePrice by project and input, on the load date |

### Pitfalls

- **Doubled budget.** Summing the whole budget table mixed old versions and parent items with their children, and the project budget came out several times larger. How to avoid: Latest version and only leaves in totals.
- **Empty level 1.** Matching on the exact code only found entries posted on that code, and sub-stages showed zero committed. How to avoid: Rollup by wbsCode prefix.
- **Savings that were missing contracts.** The ranking showed large savings on items that had just started. How to avoid: Rank only 100% measured items.
- **Project swapped by name.** A project's cost center was matched by 'contains' on the abbreviation and pulled in entries from another project with a similar abbreviation. How to avoid: Use the id map or the exact name suffix.
- **Inventory without a minimum.** The team asked for minimum stock and reserved quantity, which do not exist in stock_inventories and only come in an optional stream that was turned off. How to avoid: Enable building_resources or say the data does not exist.
- **Retention without a contract.** Finance asked for retentions by contract and measurement, and the accounts payable API does not carry that link. How to avoid: Deliver by creditor and project and record the gap in the context document.

### Acceptance test

- [ ] For one project, code, description, unit, quantity, unit price and total price of the budget match the ERP budget report for the current version.
- [ ] Budgeted, committed and actual for each sub-stage match the ERP cost-by-level report, within a cents tolerance.
- [ ] For each project, the sum of the leaf items equals the total of the top WBS level.
- [ ] The advance balance by creditor matches the ERP summary report.
- [ ] No item with less than 100% measured appears in the variance ranking.

### Context document

```text
Construction cost budget vs. actuals
- Budgeted = totalPrice of the latest version (highest versionNumber) per project and unit. Totals sum only the WBS leaves.
- Report by level: each code sums all its descendants (rollup by wbsCode prefix).
- Committed = posted bills, paid or not; actual = paid. Always side by side.
- Amount allocated to the item = bill amount x rate / 100 from buildingsCosts. In bank movements, buldingCosts, with outflows adding and inflows subtracting.
- Variance = committed - budgeted, only on 100% measured items. Positive = overrun.
- Project: buildingId (budget and bills) = costCenterId (inventory) = SPE companyId through the project map. Never match a project by 'contains'.
- Advances and retentions by documentIdentificationName. The API does not return the contract or measurement date for retentions: say so.
- Physical progress and IDP come from the planning tool, only up to the current month.
- Inventory = quantity x averagePrice. Minimum and reserved stock do not exist without building_resources.
Client-specific exceptions:
- <client>: project <abbreviation> = buildingId <id>, companyId <id>, cost center '<name>'.
- <client>: advance document type = '<name>'.
- <client>: budget version <n> of project <abbreviation> is the current one by engineering decision.
```

### Variations

- **UAU:** Same logic with UAU's total planning and input composition, refreshed once a week per company and project.
- **Procurement:** Time from request to purchase order and to delivery by input; a fulfilled request is one that became an issued order.
- **Financed project:** Monthly bank release against measurement: compare approved but unpaid committed cost with the disbursement schedule.
