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:
parent
d33d5943f9
commit
ec5c4198d6
@ -30,15 +30,39 @@
|
|||||||
{# --- Left column: stat cards --- #}
|
{# --- Left column: stat cards --- #}
|
||||||
<div class="col-xl-7">
|
<div class="col-xl-7">
|
||||||
<div class="row g-3 h-100">
|
<div class="row g-3 h-100">
|
||||||
{# Outstanding Total #}
|
{# Outstanding Total — with breakdown of wages vs adjustments #}
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="card stat-card h-100 py-2">
|
<div class="card stat-card h-100 py-2">
|
||||||
<div class="card-body">
|
<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>
|
||||||
<div class="text-xs font-weight-bold text-uppercase mb-1" style="color: #ef4444;">
|
<div class="text-xs font-weight-bold text-uppercase mb-1" style="color: #ef4444;">
|
||||||
Outstanding Payments</div>
|
Outstanding Payments</div>
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800">R {{ outstanding_total|floatformat:2 }}</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>
|
</div>
|
||||||
<i class="fas fa-exclamation-circle fa-2x text-danger opacity-25"></i>
|
<i class="fas fa-exclamation-circle fa-2x text-danger opacity-25"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -781,6 +781,10 @@ def payroll_dashboard(request):
|
|||||||
|
|
||||||
workers_data = []
|
workers_data = []
|
||||||
outstanding_total = Decimal('0.00')
|
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
|
all_ot_data = [] # For the Price Overtime modal
|
||||||
|
|
||||||
for worker in active_workers:
|
for worker in active_workers:
|
||||||
@ -817,11 +821,15 @@ def payroll_dashboard(request):
|
|||||||
# Calculate net adjustment amount
|
# Calculate net adjustment amount
|
||||||
pending_adjs = worker.pending_adjustments_list
|
pending_adjs = worker.pending_adjustments_list
|
||||||
adj_total = Decimal('0.00')
|
adj_total = Decimal('0.00')
|
||||||
|
worker_adj_add = Decimal('0.00')
|
||||||
|
worker_adj_sub = Decimal('0.00')
|
||||||
for adj in pending_adjs:
|
for adj in pending_adjs:
|
||||||
if adj.type in ADDITIVE_TYPES:
|
if adj.type in ADDITIVE_TYPES:
|
||||||
adj_total += adj.amount
|
adj_total += adj.amount
|
||||||
|
worker_adj_add += adj.amount
|
||||||
elif adj.type in DEDUCTIVE_TYPES:
|
elif adj.type in DEDUCTIVE_TYPES:
|
||||||
adj_total -= adj.amount
|
adj_total -= adj.amount
|
||||||
|
worker_adj_sub += adj.amount
|
||||||
|
|
||||||
total_payable = log_amount + adj_total
|
total_payable = log_amount + adj_total
|
||||||
|
|
||||||
@ -839,6 +847,9 @@ def payroll_dashboard(request):
|
|||||||
'day_rate': float(worker.daily_rate),
|
'day_rate': float(worker.daily_rate),
|
||||||
})
|
})
|
||||||
outstanding_total += max(total_payable, Decimal('0.00'))
|
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 ---
|
# --- Payment history ---
|
||||||
paid_records = PayrollRecord.objects.select_related(
|
paid_records = PayrollRecord.objects.select_related(
|
||||||
@ -1059,6 +1070,9 @@ def payroll_dashboard(request):
|
|||||||
'workers_data': workers_data,
|
'workers_data': workers_data,
|
||||||
'paid_records': paid_records,
|
'paid_records': paid_records,
|
||||||
'outstanding_total': outstanding_total,
|
'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,
|
'recent_payments_total': recent_payments_total,
|
||||||
'outstanding_project_costs': outstanding_project_costs,
|
'outstanding_project_costs': outstanding_project_costs,
|
||||||
'active_tab': status_filter,
|
'active_tab': status_filter,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user