New AJAX endpoint (worker_lookup_ajax) returns a comprehensive financial report card for any active worker. Modal shows: amount payable, outstanding loans, paid this month/year, loans this year, recent activity, active loans table, current project + days, PPE sizing, drivers license, and notes. Worker names across all dashboard tabs are now clickable links that open the modal. Header button with searchable dropdown for quick access. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
146 lines
6.1 KiB
Markdown
146 lines
6.1 KiB
Markdown
# Worker Lookup Modal — Implementation Plan
|
|
|
|
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
|
|
**Goal:** Add a "Worker Lookup" modal to the payroll dashboard that shows a comprehensive financial report card for any active worker — payable amount, loans, recent payments, sizing, and notes.
|
|
|
|
**Architecture:** New AJAX endpoint (`worker_lookup_ajax`) returns JSON with all worker data. Modal HTML + JS in the dashboard template dynamically renders the data using safe DOM methods (textContent, createElement). Worker names across all dashboard tabs become clickable links that open the modal. A "Worker Lookup" button in the header lets you search any active worker.
|
|
|
|
**Tech Stack:** Django views (JSON), Bootstrap 5 modal, vanilla JavaScript (matching existing patterns)
|
|
|
|
---
|
|
|
|
### Task 1: Add the AJAX backend endpoint
|
|
|
|
**Files:**
|
|
- Modify: `core/views.py` (add new view after `preview_payslip` at ~line 2155)
|
|
- Modify: `core/urls.py` (add new URL pattern at ~line 54)
|
|
|
|
**Step 1: Add URL pattern in `core/urls.py`**
|
|
|
|
Add after the `preview_payslip` URL (line 51):
|
|
|
|
```python
|
|
# Worker lookup — AJAX report card for a single worker (returns JSON)
|
|
path('payroll/worker-lookup/<int:worker_id>/', views.worker_lookup_ajax, name='worker_lookup_ajax'),
|
|
```
|
|
|
|
**Step 2: Add `worker_lookup_ajax` view in `core/views.py`**
|
|
|
|
Add after `preview_payslip` function (after line 2155). The view:
|
|
|
|
1. Checks admin access (`is_admin`)
|
|
2. Fetches the Worker object with all model fields (sizing, license, notes)
|
|
3. Calculates Amount Payable:
|
|
- Unpaid WorkLogs x daily_rate (same logic as `preview_payslip` lines 2069-2083)
|
|
- Net pending adjustments (additive minus deductive)
|
|
4. Outstanding Loans: `Loan.filter(worker=worker, active=True).aggregate(Sum('remaining_balance'))`
|
|
5. Paid This Month: `PayrollRecord.filter(worker=worker, date__year=now.year, date__month=now.month).aggregate(Sum('amount_paid'))`
|
|
6. Loans This Year: `Loan.filter(worker=worker, date__year=now.year).aggregate(Sum('principal_amount'))`
|
|
7. Paid This Year: `PayrollRecord.filter(worker=worker, date__year=now.year).aggregate(Sum('amount_paid'))`
|
|
8. Last Payslip: `PayrollRecord.filter(worker=worker).order_by('-date').first()` -> date + amount
|
|
9. Last Loan Given: `Loan.filter(worker=worker).order_by('-date').first()` -> date + amount + reason
|
|
10. Last Loan Repayment: `PayrollAdjustment.filter(worker=worker, type='Loan Repayment', payroll_record__isnull=False).order_by('-date').first()` -> date + amount
|
|
11. Last Advance: `PayrollAdjustment.filter(worker=worker, type='Advance Payment', payroll_record__isnull=False).order_by('-date').first()` -> date + amount
|
|
12. Active Loans list: `Loan.filter(worker=worker, active=True).order_by('-date')` -> type, principal, balance, date, reason
|
|
13. Current Project: most recent WorkLog -> project name + count of logs on that project
|
|
14. Team: `get_worker_active_team(worker)` -> team name
|
|
|
|
**Step 3: Verify imports**
|
|
|
|
Ensure `Sum` is imported from `django.db.models` at the top of `views.py`. Check for existing `from django.db.models import ...` line and add `Sum` if missing.
|
|
|
|
---
|
|
|
|
### Task 2: Add the modal HTML to the dashboard template
|
|
|
|
**Files:**
|
|
- Modify: `core/templates/core/payroll_dashboard.html`
|
|
|
|
**Step 1: Add "Worker Lookup" button in the page header (line 15)**
|
|
|
|
Add a new button in the header button group, before Batch Pay.
|
|
|
|
**Step 2: Add the Worker Lookup modal HTML**
|
|
|
|
Add after the `previewPayslipModal` (after line ~783). The modal contains:
|
|
- Worker dropdown in header
|
|
- A body div (`#workerLookupBody`) that gets populated by JS
|
|
- Placeholder text as default content
|
|
|
|
**Step 3: Pass `active_workers_list` from the view**
|
|
|
|
In `core/views.py`, in the `payroll_dashboard` view, add to the context dict:
|
|
|
|
```python
|
|
'active_workers_list': Worker.objects.filter(active=True).order_by('name'),
|
|
```
|
|
|
|
---
|
|
|
|
### Task 3: Make worker names clickable across all tabs
|
|
|
|
**Files:**
|
|
- Modify: `core/templates/core/payroll_dashboard.html`
|
|
|
|
Replace `<strong>worker.name</strong>` with clickable links using class `worker-lookup-link` and `data-worker-id` at:
|
|
|
|
- **Pending Payments tab** (line 268)
|
|
- **Payment History tab** (line 365)
|
|
- **Loans & Advances tab** (line 432)
|
|
|
|
---
|
|
|
|
### Task 4: Add JavaScript to fetch data and render the modal
|
|
|
|
**Files:**
|
|
- Modify: `core/templates/core/payroll_dashboard.html` (JS section at bottom)
|
|
|
|
**Step 1: Add the `loadWorkerLookup(workerId)` function**
|
|
|
|
This function:
|
|
1. Shows a loading spinner in `#workerLookupBody`
|
|
2. Fetches `/payroll/worker-lookup/<workerId>/` via fetch API
|
|
3. Builds the report card using safe DOM methods (createElement, textContent — no innerHTML with user data)
|
|
4. Renders sections: Identity, Quick Stats (4 cards), Recent Activity, Active Loans table, Paid This Year, Sizing & Info
|
|
|
|
Format currency as `R X,XXX.XX` using `toLocaleString('en-ZA', {minimumFractionDigits: 2})`.
|
|
|
|
**Step 2: Add event listeners**
|
|
|
|
- Worker Lookup button click -> open modal with empty dropdown
|
|
- Dropdown change -> call `loadWorkerLookup(selectedId)`
|
|
- `.worker-lookup-link` click -> set dropdown value, load data, open modal
|
|
|
|
---
|
|
|
|
### Task 5: Update CLAUDE.md
|
|
|
|
**Files:**
|
|
- Modify: `CLAUDE.md`
|
|
|
|
- Add Worker Lookup documentation to Development Workflow section
|
|
- Add URL route to the URL Routes table
|
|
- Update view count from "27 functions" to "28 functions"
|
|
|
|
---
|
|
|
|
### Task 6: Test locally
|
|
|
|
1. Start dev server: `run_dev.bat`
|
|
2. Go to `/payroll/` -> verify "Worker Lookup" button appears in header
|
|
3. Click "Worker Lookup" -> modal opens with dropdown -> select a worker -> report card loads
|
|
4. Click a worker name in Pending Payments -> modal opens with that worker's data
|
|
5. Click a worker name in Payment History -> same
|
|
6. Click a worker name in Loans & Advances -> same
|
|
7. Switch workers via dropdown while modal is open -> data refreshes
|
|
8. Verify all sections render correctly:
|
|
- Quick stats show correct amounts
|
|
- Recent activity shows dates and amounts (or "None")
|
|
- Active loans table shows if worker has loans
|
|
- Sizing and notes display at bottom
|
|
9. Verify existing functionality is unbroken:
|
|
- Preview payslip modal still works
|
|
- Quick adjust button still works
|
|
- Pay/Batch pay still works
|