From da805d9bb30372bed8874ab14e1d57e51f6c5027 Mon Sep 17 00:00:00 2001 From: Konrad du Plessis Date: Thu, 19 Feb 2026 22:29:10 +0200 Subject: [PATCH] Ver 14.07 Edit & delete unpaid payroll adjustments Add ability for admins to edit or delete unpaid payroll adjustments directly from the payroll dashboard. Clickable adjustment badges open edit/delete modals with type-specific handling (LOAN cascades, OVERTIME un-pricing). No model changes or migrations needed. Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 68 ++++++++++ core/templates/core/payroll_dashboard.html | 139 ++++++++++++++++++++- core/urls.py | 4 + core/views.py | 87 +++++++++++++ 4 files changed, 296 insertions(+), 2 deletions(-) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..574f647 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,68 @@ +# Fox Fitt LabourPay + +## Project Overview +Django payroll management system for Fox Fitt Construction, a civil works contractor specializing in solar farm foundation installations. Manages field worker attendance, payroll processing, employee loans, and business expenses for solar farm projects. + +## Tech Stack +- Django 5.x, Python 3.11, MariaDB +- Bootstrap 5 with Material Design-inspired styling, vanilla JavaScript +- PDF generation for payslips and receipts +- SMTP email integration for automated document delivery +- Apache reverse proxy with systemd service management + +## Project Structure +- `config/` — Django project settings, URLs, WSGI/ASGI entrypoints +- `core/` — Single main app containing ALL business logic, models, views, forms, templates, and migrations +- `ai/` — Local AI API integration module +- `media/workers/ids/` — Worker ID photo uploads +- `static/` — Source static files (custom CSS) +- `staticfiles/` — Collected static assets (Bootstrap, Popper.js, admin) + +## Key Business Rules +- All business logic lives in the `core/` app — do not create additional apps +- Workers have a `day_rate` calculated automatically from monthly salary / 20 working days +- PIN authentication (4-digit) exists alongside password auth for quick field access +- Supervisors can only see their assigned projects and teams +- Admins have full access to payroll, adjustments, and resource management +- WorkLog is the central attendance record — links workers to projects on specific dates +- Attendance logging includes conflict detection to prevent double-logging +- Loans have automated repayment deductions during payroll processing +- Cascading deletes use SET_NULL for supervisors to preserve historical data + +## Key Models +- **UserProfile** — extends User with PIN and is_admin flag +- **Project** — work sites/contracts with supervisor assignments +- **Worker** — profiles with salary, day_rate, employment details +- **Team** — groups of workers under a supervisor +- **WorkLog** — daily attendance records (worker + project + date) +- **PayrollRecord** — completed payments linked to WorkLog entries +- **PayrollAdjustment** — bonuses, deductions, overtime, loan repayments +- **Loan** — worker advances with balance tracking +- **ExpenseReceipt / ExpenseLineItem** — business expense records + +## Commands +- `python manage.py runserver 0.0.0.0:8000` — run dev server +- `python manage.py migrate` — apply database migrations +- `python manage.py collectstatic` — collect static files for production +- `python manage.py setup_groups` — configure permission groups +- `python manage.py update_permission_names` — update permission display names +- `python manage.py check` — system check (ignore staticfiles warnings about missing `assets/` and `node_modules/` dirs — pre-existing, harmless) + +## Development Workflow +- Active development branch: `ai-dev` (PR target: `master`) +- Admin check in views: `is_admin(request.user)` helper (imported at top of views.py) +- "Unpaid" adjustment = `payroll_record__isnull=True` (no linked PayrollRecord) +- POST-only mutation views pattern: check `request.method != 'POST'` → redirect, then process +- Template UI pattern: Bootstrap 5 modals with dynamic JS wiring, data-* attributes on clickable elements + +## PayrollAdjustment Type Handling +- **BONUS / DEDUCTION** — standalone, no linked objects +- **LOAN** — links to `Loan` model via `adj.loan` FK; editing syncs loan amount/balance/reason; deleting cascades to Loan + unpaid repayments (blocked if paid repayments exist) +- **OVERTIME** — links to `WorkLog` via `adj.work_log` FK; deleting removes worker from `work_log.overtime_paid_to` M2M (un-prices the OT) +- **LOAN_REPAYMENT** — links to `Loan` via `adj.loan` FK; loan balance only changes during payment processing + +## Important Context +- Read APP_DOCUMENTATION.md for detailed workflows (attendance, payroll, expenses) +- Environment variables loaded from `../.env` +- The owner (Konrad) is not a developer — explain changes clearly and avoid unnecessary complexity +- This system handles real payroll for 14 field workers — accuracy is critical diff --git a/core/templates/core/payroll_dashboard.html b/core/templates/core/payroll_dashboard.html index 961a44c..94bfb25 100644 --- a/core/templates/core/payroll_dashboard.html +++ b/core/templates/core/payroll_dashboard.html @@ -163,8 +163,16 @@ {% if item.adjustments %}
{% for adj in item.adjustments %} - - {{ adj.get_type_display }}: R {{ adj.amount }} + + {{ adj.get_type_display }}: R {{ adj.amount }} ✎ {% endfor %}
@@ -475,6 +483,74 @@ + + + + + +