Construction ERP: budget, bills, banks and inputs
Latest version, WBS rollup and allocation by percentage
Budgeted, committed, actual and variance by item
Construction committee, variance alert and AI agent
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.
Business questions it answers
Ask your agent these questions once the case is live.
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
Where to activate
Cost by WBS level, variance ranking and physical progress curve for each project on a single page.
Notifies engineering when a measured item closes with an overrun above the limit or when committed cost runs well ahead of actual progress.
Answers about amounts left to contract, advances and variances with the version and rollup rules already applied.
The ERP arrays have to be unnested carefully and every number validated against the project report. Start with one project and only open it up to the others once that one matches. The detailed view has the business rules, the pitfalls and the acceptance test. Or send everything straight to your agent with the Nekt MCP.
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.
How it is usually done, and the rule
Each row is a mistake that already happened in practice.
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.
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.
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.
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.
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 %.
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.
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'.
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.
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.
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.
Where each project value comes from
Standard fields from the Sienge connector.
Definitions
Pitfalls that already happened
Summing the whole budget table mixed old versions and parent items with their children, and the project budget came out several times larger.
Latest version and only leaves in totals.
Matching on the exact code only found entries posted on that code, and sub-stages showed zero committed.
Rollup by wbsCode prefix.
The ranking showed large savings on items that had just started.
Rank only 100% measured items.
A project's cost center was matched by 'contains' on the abbreviation and pulled in entries from another project with a similar abbreviation.
Use the id map or the exact name suffix.
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.
Enable building_resources or say the data does not exist.
Finance asked for retentions by contract and measurement, and the accounts payable API does not carry that link.
Deliver by creditor and project and record the gap in the context document.
Acceptance test
The case is done when every item passes.
- 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.
Agent package
Paste into Claude, ChatGPT or any client with the Nekt MCP connected.
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.
Build the "Construction cost budget vs. actuals" case in my Nekt workspace following the rules at https://academy.nekt.com/en/industrias/imobiliario/custo-obra-orcado-realizado.md. 1) Find the source tables and confirm the columns the rules use. 2) Create a transformation at the stated grain applying every rule. 3) Run the acceptance test and show me the result of each item. 4) Create the case's context document in the workspace, leaving my clients' exceptions open for me to fill in.
Variations
Same logic with UAU's total planning and input composition, refreshed once a week per company and project.
Time from request to purchase order and to delivery by input; a fulfilled request is one that became an issued order.
Monthly bank release against measurement: compare approved but unpaid committed cost with the disbursement schedule.