FinanceBuddy: per-column net total in the header (v0.4)

This commit is contained in:
2026-07-07 17:05:03 -03:00
parent 6c23c4aeb2
commit 6328f3632f
4 changed files with 76 additions and 4 deletions

View File

@@ -1,9 +1,30 @@
/*
* FinanceBuddy styles.
*
* The per-column total (.fb-column-total) styling is added in a later version.
*/
/* Per-column net total in the column header (its own line, subtle pill). */
.fb-column-total {
display: inline-block;
margin-top: 3px;
padding: 0 5px;
font-weight: bold;
font-size: 0.95em;
background: rgba(0, 0, 0, 0.05);
border-radius: 3px;
}
.fb-total-debit {
color: #b94a48;
}
.fb-total-credit {
color: #468847;
}
.fb-total-zero {
color: #777;
}
/* Line-3 money badge on board cards. Its own background guarantees contrast on any card color. */
.fb-line {
margin: 2px 0 4px;

View File

@@ -62,6 +62,54 @@ class FinanceHelper extends Base
);
}
/**
* Net money for a board column: credits positive, debits negative, summed over the cards in
* the column. One grouped query over the column's task ids (the task rows carry no metadata).
*
* @param array $column A board column as passed to template:board:column:header ('tasks').
* @return float
*/
public function columnNet(array $column)
{
if (empty($column['tasks'])) {
return 0.0;
}
$task_ids = array();
foreach ($column['tasks'] as $task) {
$task_ids[] = (int) $task['id'];
}
$rows = $this->db->table('task_has_metadata')
->columns('task_id', 'name', 'value')
->in('task_id', $task_ids)
->in('name', array(self::AMOUNT_KEY, self::DIRECTION_KEY))
->findAll();
$amounts = array();
$directions = array();
foreach ($rows as $row) {
if ($row['name'] === self::AMOUNT_KEY) {
$amounts[$row['task_id']] = (float) $row['value'];
} else {
$directions[$row['task_id']] = $row['value'];
}
}
$net = 0.0;
foreach ($amounts as $task_id => $amount) {
if ($amount <= 0) {
continue;
}
$is_credit = isset($directions[$task_id]) && $directions[$task_id] === 'credit';
$net += $is_credit ? $amount : -$amount;
}
return $net;
}
/**
* Values to prefill the task-form fields: a re-post (after a validation error) wins, then the
* stored metadata for an existing task, otherwise blanks for a new task.

View File

@@ -33,6 +33,9 @@ class Plugin extends Base
// "private" is the normal board, "public" is the read-only board shared by token.
$this->template->hook->attach('template:board:private:task:after-title', 'financeBuddy:board/task_money');
$this->template->hook->attach('template:board:public:task:after-title', 'financeBuddy:board/task_money');
// Per-column net total (credits - debits) in the column header.
$this->template->hook->attach('template:board:column:header', 'financeBuddy:board/column_total');
}
public function getHelpers()
@@ -59,7 +62,7 @@ class Plugin extends Base
public function getPluginVersion()
{
return '0.3.1';
return '0.4.0';
}
public function getPluginHomepage()

View File

@@ -1 +1 @@
FinanceBuddy v0.3.1
FinanceBuddy v0.4