From d33d5943f9881b933718626543dd01e7d8793505 Mon Sep 17 00:00:00 2001 From: Konrad du Plessis Date: Thu, 5 Mar 2026 15:56:40 +0200 Subject: [PATCH] Add outstanding payments breakdown on dashboard Split the single outstanding total into unpaid wages, additions, and deductions so the card shows where the number comes from. Rename the 'General' project bucket to 'No Project' so per-project totals now visibly sum to the overall total. Co-Authored-By: Claude Opus 4.6 --- core/templates/core/index.html | 27 ++++++++++++++++++++++++++- core/views.py | 23 +++++++++++++++++------ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/core/templates/core/index.html b/core/templates/core/index.html index 042e222..520acb2 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -24,6 +24,7 @@
+
@@ -32,8 +33,32 @@
Outstanding Payments
R {{ outstanding_payments|floatformat:2 }}
+ {# === BREAKDOWN — only shown when there are pending adjustments === #} + {% if pending_adjustments_add or pending_adjustments_sub %} +
+
+ Unpaid wages + R {{ unpaid_wages|floatformat:2 }} +
+ {% if pending_adjustments_add %} +
+ + Additions + R {{ pending_adjustments_add|floatformat:2 }} +
+ {% endif %} + {% if pending_adjustments_sub %} +
+ - Deductions + -R {{ pending_adjustments_sub|floatformat:2 }} +
+ {% endif %} +
+ {% endif %} +
+ Loan repayments deducted at payment time +
-
+
diff --git a/core/views.py b/core/views.py index 81fc200..f2596d4 100644 --- a/core/views.py +++ b/core/views.py @@ -79,7 +79,12 @@ def index(request): 'project' ).prefetch_related('workers', 'payroll_records') - outstanding_payments = Decimal('0.00') + # === OUTSTANDING BREAKDOWN === + # Track unpaid wages and adjustments separately so the dashboard + # can show a clear breakdown of what makes up the total. + unpaid_wages = Decimal('0.00') # Pure daily rates for unpaid workers + pending_adjustments_add = Decimal('0.00') # Unpaid additive adjustments (bonuses, overtime, etc.) + pending_adjustments_sub = Decimal('0.00') # Unpaid deductive adjustments (deductions, repayments) outstanding_by_project = {} for wl in all_worklogs: @@ -90,30 +95,33 @@ def index(request): for worker in wl.workers.all(): if worker.id not in paid_worker_ids: cost = worker.daily_rate - outstanding_payments += cost + unpaid_wages += cost if project_name not in outstanding_by_project: outstanding_by_project[project_name] = Decimal('0.00') outstanding_by_project[project_name] += cost # Also include unpaid payroll adjustments (bonuses, deductions, etc.) # Additive types (Bonus, Overtime, New Loan) increase outstanding. - # Deductive types (Deduction, Loan Repayment, Advance Payment) decrease it. + # Deductive types (Deduction, Loan Repayment, Advance Repayment) decrease it. unpaid_adjustments = PayrollAdjustment.objects.filter( payroll_record__isnull=True ).select_related('project') for adj in unpaid_adjustments: - project_name = adj.project.name if adj.project else 'General' + project_name = adj.project.name if adj.project else 'No Project' if project_name not in outstanding_by_project: outstanding_by_project[project_name] = Decimal('0.00') if adj.type in ADDITIVE_TYPES: - outstanding_payments += adj.amount + pending_adjustments_add += adj.amount outstanding_by_project[project_name] += adj.amount elif adj.type in DEDUCTIVE_TYPES: - outstanding_payments -= adj.amount + pending_adjustments_sub += adj.amount outstanding_by_project[project_name] -= adj.amount + # Net total = wages + additions - deductions (same result as before, just tracked separately) + outstanding_payments = unpaid_wages + pending_adjustments_add - pending_adjustments_sub + # Sum total paid out in the last 60 days sixty_days_ago = timezone.now().date() - timezone.timedelta(days=60) paid_this_month = PayrollRecord.objects.filter( @@ -148,6 +156,9 @@ def index(request): context = { 'is_admin': True, 'outstanding_payments': outstanding_payments, + 'unpaid_wages': unpaid_wages, + 'pending_adjustments_add': pending_adjustments_add, + 'pending_adjustments_sub': pending_adjustments_sub, 'paid_this_month': paid_this_month, 'active_loans_count': active_loans_count, 'active_loans_balance': active_loans_balance,