Add outstanding breakdown to payroll dashboard too

Same wages/additions/deductions breakdown as the home dashboard,
now also shown on the Payroll Dashboard stat card.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Konrad du Plessis 2026-03-05 17:09:18 +02:00
parent d33d5943f9
commit ec5c4198d6
2 changed files with 40 additions and 2 deletions

View File

@ -30,15 +30,39 @@
{# --- Left column: stat cards --- #}
<div class="col-xl-7">
<div class="row g-3 h-100">
{# Outstanding Total #}
{# Outstanding Total — with breakdown of wages vs adjustments #}
<div class="col-sm-6">
<div class="card stat-card h-100 py-2">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex align-items-start justify-content-between">
<div>
<div class="text-xs font-weight-bold text-uppercase mb-1" style="color: #ef4444;">
Outstanding Payments</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">R {{ outstanding_total|floatformat:2 }}</div>
{# === BREAKDOWN — only shown when there are pending adjustments === #}
{% if pending_adj_add_total or pending_adj_sub_total %}
<div class="mt-2 pt-2 border-top" style="font-size: 0.75rem; color: #64748b;">
<div class="d-flex justify-content-between">
<span>Unpaid wages</span>
<span>R {{ unpaid_wages_total|floatformat:2 }}</span>
</div>
{% if pending_adj_add_total %}
<div class="d-flex justify-content-between">
<span>+ Additions</span>
<span class="text-success">R {{ pending_adj_add_total|floatformat:2 }}</span>
</div>
{% endif %}
{% if pending_adj_sub_total %}
<div class="d-flex justify-content-between">
<span>- Deductions</span>
<span class="text-danger">-R {{ pending_adj_sub_total|floatformat:2 }}</span>
</div>
{% endif %}
</div>
{% endif %}
<div class="mt-1" style="font-size: 0.65rem; color: #94a3b8;">
<i class="fas fa-info-circle"></i> Loan repayments deducted at payment time
</div>
</div>
<i class="fas fa-exclamation-circle fa-2x text-danger opacity-25"></i>
</div>

View File

@ -781,6 +781,10 @@ def payroll_dashboard(request):
workers_data = []
outstanding_total = Decimal('0.00')
# === OUTSTANDING BREAKDOWN (same as home dashboard) ===
unpaid_wages_total = Decimal('0.00') # Pure daily rates for unpaid workers
pending_adj_add_total = Decimal('0.00') # Unpaid additive adjustments
pending_adj_sub_total = Decimal('0.00') # Unpaid deductive adjustments
all_ot_data = [] # For the Price Overtime modal
for worker in active_workers:
@ -817,11 +821,15 @@ def payroll_dashboard(request):
# Calculate net adjustment amount
pending_adjs = worker.pending_adjustments_list
adj_total = Decimal('0.00')
worker_adj_add = Decimal('0.00')
worker_adj_sub = Decimal('0.00')
for adj in pending_adjs:
if adj.type in ADDITIVE_TYPES:
adj_total += adj.amount
worker_adj_add += adj.amount
elif adj.type in DEDUCTIVE_TYPES:
adj_total -= adj.amount
worker_adj_sub += adj.amount
total_payable = log_amount + adj_total
@ -839,6 +847,9 @@ def payroll_dashboard(request):
'day_rate': float(worker.daily_rate),
})
outstanding_total += max(total_payable, Decimal('0.00'))
unpaid_wages_total += log_amount
pending_adj_add_total += worker_adj_add
pending_adj_sub_total += worker_adj_sub
# --- Payment history ---
paid_records = PayrollRecord.objects.select_related(
@ -1059,6 +1070,9 @@ def payroll_dashboard(request):
'workers_data': workers_data,
'paid_records': paid_records,
'outstanding_total': outstanding_total,
'unpaid_wages_total': unpaid_wages_total,
'pending_adj_add_total': pending_adj_add_total,
'pending_adj_sub_total': pending_adj_sub_total,
'recent_payments_total': recent_payments_total,
'outstanding_project_costs': outstanding_project_costs,
'active_tab': status_filter,