Budget vs. actual
Compares the budget with the actual amounts per general ledger account, for periods 1–12 of a year.
Budgets come from the BudgetService, a Command & Query web service that can only read. budgets()->totals($code, $year) starts an immutable query; filters such as periods(1, 12) return a new query, and byProfitAndLoss() sends it.
The result is a BudgetTotals list of BudgetTotal lines, one per general ledger account and period, each with budget and actual amounts (debit, credit, total). Twinfield only returns lines with a budget or actual amount.
$twinfield = Example::twinfield();$budgets = $twinfield->budgets();
// Budget code and year from the command line; defaults: the first budget and the last year.$code = $argv[1] ?? iterator_to_array($budgets->search()->all(), false)[0]->code ?? null;$years = $twinfield->periods()->years();$year = (int) ($argv[2] ?? ($years === [] ? date('Y') : max($years)));
if ($code === null) { echo 'The company has no budgets.', PHP_EOL;
exit;}
$totals = $budgets->totals($code, $year)->periods(1, 12)->byProfitAndLoss();
echo 'Budget ', $code, ', ', $year, ', periods 1–12', PHP_EOL, PHP_EOL;echo sprintf('%-10s %14s %14s %14s', 'Account', 'Budget', 'Actual', 'Difference'), PHP_EOL;
// Amounts are exact decimal strings: add them up with bcmath, not with floats.foreach ($totals->generalLedgerAccounts() as $account) { $budget = '0'; $actual = '0';
foreach ($totals->forGeneralLedgerAccount($account) as $total) { $budget = bcadd($budget, $total->budget->total, 2); $actual = bcadd($actual, $total->actual->total, 2); }
echo sprintf('%-10s %14s %14s %14s', $account, $budget, $actual, bcsub($actual, $budget, 2)), PHP_EOL;}Amounts are exact decimal strings as Twinfield returns them, such as 2100.5000 or 0, never floats. This example uses bcmath to add them up; a money library works too. A total is debit minus credit: positive for costs, negative for revenue.
Other filters:
period(3)orperiods(1, 6): periods, both included. Default: 0 (opening balance) to 55.generalLedgerAccounts('8000', '8999')orgeneralLedgerAccount('8000').dimension2('KPL100', 'KPL199')anddimension3('P0001'): cost centers and projects, see By cost center and By project.finalOnly()orprovisionalOnly(): actual amounts of final or provisional transactions only. Default: both.
An unknown budget code throws a BudgetNotFoundException.
php examples/budgets/budget-vs-actual/example.phpphp examples/budgets/budget-vs-actual/example.php 001 2025Add TWINFIELD_DEBUG=1 to see the SOAP request and response.
Budget 001, 2025, periods 1–12
Account Budget Actual Difference4000 24000.00 25210.50 1210.504100 6000.00 5450.00 -550.008000 -180000.00 -172500.00 7500.00Source
Section titled “Source”View examples/budgets/budget-vs-actual/example.php on GitHub.
Twinfield and Wolters Kluwer are trademarks of Wolters Kluwer. Their names and logos are used only to refer to their products.