@@ -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,