Reference - Parms functions - money


App: ledger - Page: budgets
PHP
budgets.php
HTML
budgets.pad
Result
<?php

// What each category of spending may cost a month. A budget of 0 takes the category's
// budget away; the overview shows how far each month got.

if ( padPosted ( 'budgets' ) ) {

foreach ( (array)
padRequest ( 'budget', [] ) as $id => $amount ) {
if ( !
is_scalar ( $amount ) )
continue;
$amount = (float) str_replace ( ',', '.', (string) $amount );
if (
$amount > 0 )
db ( "INSERT OR REPLACE INTO budgets (category_id, monthly) SELECT id, {1} FROM categories WHERE id={0} AND kind = 'expense'", [ (int) $id, round ( $amount, 2 ) ] );
else
db ( "DELETE FROM budgets WHERE category_id={0}", [ (int) $id ] );
}

padFlash ( 'The budgets are saved.' );
padRedirect ( 'index', [ 'month' => $ledgerMonth ] );

}

$plan = array_values ( db ( "ARRAY c.id, c.name, c.color, coalesce(b.monthly, 0) AS monthly
FROM categories c LEFT JOIN budgets b ON b.category_id = c.id
WHERE c.kind = 'expense' ORDER BY c.name"
) ?: [] );

$planned = array_sum ( array_column ( $plan, 'monthly' ) );
$ledgerPage = 'Budgets';

?>
<div class="narrow">

<h1>Budgets</h1>
<p class="lead">What each kind of spending may cost a month - {$planned | money} together. 0 leaves a category without one.</p>

{form 'budgets', class='budget-form'}
{plan}
<label class="budget-row" for="budget-{$id}"><span class="dot" style="background: {$color}"></span>{$name}
<input id="budget-{$id}" name="budget[{$id}]" value="{$monthly}" inputmode="decimal" size="8"></label>
{/plan}
<div class="bar"><button class="button primary">Save</button><a class="button" href="{$padGo}index{?month}">Cancel</a></div>
{/form}

</div>


App: ledger - Page: index
PHP
index.php
HTML
index.pad
Result
<?php

// The month at a glance: what came in, what went out, what is left; six months of it as a
// chart, this month's spending by category, the budgets, the accounts, the latest entries
// - and a quick entry that ledger.js posts as JSON, answered by quick.php.

$totals = ledgerTotals ( $ledgerMonth );
$history = ledgerHistory ( $ledgerMonth );
$spending = ledgerSpending ( $ledgerMonth );
$budgets = ledgerBudgets ( $ledgerMonth );
$accounts = ledgerAccounts ();
$latest = array_slice ( array_values ( array_filter ( ledgerRows ( $ledgerMonth ), fn ( $r ) => $r ['kind'] != 'transfer' ) ), 0, 8 );
$spendable = array_values ( array_filter ( ledgerCategories (), fn ( $c ) => $c ['kind'] == 'expense' ) );
$monthName = ledgerMonthName ( $ledgerMonth );
$today = date ( 'Y-m-d' );

$ledgerPage = $monthName;

?>
<div class="head">
<h1>{$monthName}</h1>
<span class="dim">{$totals.entries} entries</span>
</div>

<section class="kpis" aria-label="This month">
<div class="kpi in"><span>Income</span><b data-kpi="income">{$totals.income | money}</b></div>
<div class="kpi out"><span>Spending</span><b data-kpi="spent">{$totals.spent | money}</b></div>
<div class="kpi"><span>Left</span><b data-kpi="left">{$totals.left | money}</b></div>
<div class="kpi"><span>Kept</span><b data-kpi="kept">{$totals.kept}%</b></div>
</section>

<div class="columns">

<div class="main">

<section class="card">
<h2>Six months</h2>
{chart 'bar', data='history', label='month', value='income, spending', title='Income and spending, six months'}
</section>

<section class="card">
<h2>Where it went</h2>
{if $totals.spent gt 0}
{chart 'donut', data='spending', label='category', value='spent', title='Spending by category'}
{else}
<p class="dim">Nothing spent this month.</p>
{/if}
</section>

<section class="card">
<h2>Budgets <a class="more" href="{$padGo}budgets{?month}">Change</a></h2>
<ul class="budgets">
{budgets}
<li class="{$state}">
<div class="line"><span class="dot" style="background: {$color}"></span><b>{$name}</b><span>{$spent | money} of {$monthly | money}</span></div>
{progress $share, max=100, label=$name, color=$tone}
</li>
@else@
<li class="dim">No budgets yet.</li>
{/budgets}
</ul>
</section>

</div>

<aside class="side">

<section class="card quick">
<h2>Quick entry</h2>
{form 'quick', action='?quick', class='quick-form'}
<input type="hidden" name="month" value="{$ledgerMonth}">
<label for="q-amount">Amount</label>
<input id="q-amount" name="amount" inputmode="decimal" placeholder="12.50" required pattern="[0-9]+([.,][0-9][0-9]?)?">
<label for="q-category">Category</label>
<select id="q-category" name="category">{spendable}<option value="{$id}">{$name}</option>{/spendable}</select>
<label for="q-note">Note</label>
<input id="q-note" name="note" placeholder="Coffee" maxlength="120">
<button class="button primary">Spend it</button>
<p class="said" role="status"></p>
{/form}
</section>

<section class="card">
<h2>Accounts</h2>
<ul class="accounts">
{accounts}<li><span>{$name}</span><b class="{if $balance lt 0}neg{/if}">{$balance | money}</b></li>{/accounts}
</ul>
</section>

<section class="card">
<h2>Latest <a class="more" href="{$padGo}transactions{?month}">All</a></h2>
<ul class="latest">
{latest}<li><span class="day">{$day | date('j M')}</span><span class="what">{$note}<small>{$category}</small></span><b class="{if $amount lt 0}neg{else}pos{/if}">{$amount | money}</b></li>
@else@<li class="dim">No entries this month.</li>{/latest}
</ul>
</section>

</aside>

</div>


App: ledger - Page: transactions
PHP
transactions.php
HTML
transactions.pad
Result
<?php

// A month's transactions as one table - sorted and paged on the server by {datatable} -
// narrowed to a category, an account or a word in the note. The same rows answer as CSV
// (?transactions&padFormat=csv) and JSON: $padExpose names them.

$only = (int) padRequest ( 'category', 0 );
$from = (int) padRequest ( 'account', 0 );
$word = trim ( ledgerText ( 'q' ) );

$rows = array_map ( fn ( $r ) => array_diff_key ( $r, [ 'id' => 1, 'kind' => 1 ] ), ledgerRows ( $ledgerMonth, $only, $from, $word ) );
$shown = count ( $rows );
$sum = round ( array_sum ( array_column ( $rows, 'amount' ) ), 2 );

$categoryList = array_map ( fn ( $c ) => $c + [ 'chosen' => $c ['id'] == $only ], ledgerCategories () );
$accountList = array_map ( fn ( $a ) => $a + [ 'chosen' => $a ['id'] == $from ], ledgerAccounts () );
$monthName = ledgerMonthName ( $ledgerMonth );
$csvName = "ledger-$ledgerMonth.csv";
$csvQuery = http_build_query ( [ 'month' => $ledgerMonth, 'category' => $only, 'account' => $from, 'q' => $word, 'padFormat' => 'csv' ] );

$padExpose = [ 'rows' ];
$ledgerPage = "Transactions, $monthName";

?>
<div class="head">
<h1>Transactions <span class="dim">{$monthName}</span></h1>
<a class="button" href="{$padGo}transactions&{$csvQuery}" download="{$csvName}">⬇ CSV</a>
</div>

<form class="filters" method="get">
<input type="hidden" name="transactions" value="">
<input type="hidden" name="month" value="{$ledgerMonth}">
<label>Category
<select name="category"><option value="0">All</option>{categoryList}<option value="{$id}"{if $chosen} selected{/if}>{$name}</option>{/categoryList}</select>
</label>
<label>Account
<select name="account"><option value="0">All</option>{accountList}<option value="{$id}"{if $chosen} selected{/if}>{$name}</option>{/accountList}</select>
</label>
<label>Note <input type="search" name="q" value="{$word}" placeholder="a word"></label>
<button class="button">Show</button>
</form>

<section class="card table">
{if $shown gt 0}
{datatable data='rows', columns='day, category, account, note, amount', format="amount:money, day:date('D j M')", totals='amount', sortable, rows=15, striped}
{else}
<p class="dim">No transactions here.</p>
{/if}
<p class="dim sum">{$shown} transactions, together {$sum | money}.</p>
</section>