24 Commits

Author SHA1 Message Date
Konrad du Plessis
97866f1e74 Replace resource filter with V2's Active/Inactive/All button bar
Ported from V2: three-button filter bar (Active | Inactive | All)
that shows/hides resource rows via JS data-active attribute.
Defaults to Active so inactive workers/projects/teams are hidden.
Toggle switch updates data-active instantly and re-applies filter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:25:29 +02:00
Konrad du Plessis
47de74bde4 Show active resources by default, collapse inactive + add project dates
Dashboard Manage Resources now shows only active workers/projects/teams
by default. Inactive items are hidden behind a collapsible "Show X
Inactive" button — faded at 50% opacity. Tab badges show active counts.

Also adds start_date and end_date fields to Project model (optional).
Dates display under the project name in the resource list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:49:57 +02:00
Konrad du Plessis
2aad9ac623 Add Export Workers CSV — downloads all worker data as spreadsheet
Admin-only CSV export with name, ID number, phone, salary, daily rate,
employment date, active status, and notes. Button on dashboard next to
Manage Resources header.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:36:57 +02:00
Konrad du Plessis
b6fca98c17 Fix attendance start date, history worker filter, and add Amount column
1. Attendance form: Force start date to blank by clearing Django 5.x auto-fill
   from model default (default=timezone.now). Added self.fields['date'].initial=None
   in AttendanceLogForm.__init__().

2. History list view: When filtering by a specific worker, show only that
   worker's name in the Workers column (not all workers on the log). Uses
   filtered_worker_obj passed from the view.

3. History list view: Added Amount column (admin-only) showing daily cost.
   When filtering by worker, shows that worker's daily_rate. When unfiltered,
   shows total via new WorkLog.display_amount property (sum of all workers'
   daily_rate, uses prefetch cache for efficiency).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:13:46 +02:00
Konrad du Plessis
0b3ef5395f Fix work history filter — add validation, explicit form action, and visual feedback
- Add explicit action="{% url 'work_history' %}" to filter form (prevents
  potential URL mismatch on Flatlogic proxy)
- Add numeric validation for worker/project GET params (prevents 500 errors)
- Add results counter: "Showing X of Y work logs" when filters are active
- Add active filter badges showing worker name, project name, and status
- Add green left border indicator on filter card when filters are active
- Make Clear button conditional (red, only appears with active filters)
- Add SQLite dev toggle in settings.py for local testing without MariaDB

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 23:53:21 +02:00
Konrad du Plessis
b837932bb4 Fix Add Adjustment form silently failing — add validation + required fields
Root cause: V5 was missing required attributes that V2 had on the Add
Adjustment form. When a user submitted without selecting a project (for
types that require one), the server rejected it with messages.error()
but the error was invisible before the MESSAGE_TAGS fix. Combined with
no client-side validation for workers, the form would silently create
0 adjustments or redirect with no visible feedback.

Fixes:
- Add required attribute to Project select (toggles off for Loan types)
- Add client-side validation: blocks submit if no workers selected
- Add backend validation: returns error if no workers in POST data
- Add "Select All" / "Clear" links for worker checkboxes (matches V2)
- Add "X worker(s) selected" counter for visual feedback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 23:22:20 +02:00
Konrad du Plessis
0fa25e1538 Prevent duplicate payslip emails from double-click on Pay button
Problem: Supervisors on slow mobile connections sometimes double-click
the "Pay" button, causing two PayrollRecords + two payslip emails to
be sent to Spark Receipt for the same worker.

Backend fix (the critical part):
- Moved unpaid_logs and pending_adjs queries INSIDE transaction.atomic()
- Added select_for_update() on Worker row — this database-level lock
  forces the second concurrent request to WAIT until the first commits
- After the lock is acquired, the second request re-queries and finds
  no unpaid logs (already paid by first request), so it bails out

Frontend fix (defence-in-depth):
- Pay button now shows a Bootstrap spinner + "Processing..." text
- Second click is blocked with e.preventDefault() if button is
  already disabled (handles edge case where form resubmits)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 23:06:31 +02:00
Konrad du Plessis
f9423c0b3e Fix invisible error messages + UX improvements + calendar multi-select
1. Add MESSAGE_TAGS to settings.py — Django's messages.error() uses tag
   "error" but Bootstrap needs "danger". Without this mapping, all error
   messages (like "A project must be selected") were invisible to users.

2. Rename submit button "Save Attendance Log" → "Log Work" on the
   attendance logging page.

3. Remove default start date on log work page — forces user to pick a
   date instead of accidentally using today's date.

4. Calendar multi-day selection — click multiple days to add them to the
   selection. Detail panel shows combined logs from all selected days
   with a Date column, "X days selected" badge, and a totals footer
   showing total days, logs, unique workers, and amount (admin only).
   Click a selected day again to deselect it. Clear button resets all.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 23:00:04 +02:00
Konrad du Plessis
94c061fc19 Fix calendar detail showing all workers when filtering by one
When filtering by a single worker, log.workers.all() still returned
every worker on the WorkLog. Now the detail panel and cost calculation
only show the filtered worker, not the entire group.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:38:09 +02:00
Konrad du Plessis
19e565a088 Fix payroll dashboard JS crash + add calendar view to work history
1. Fix json_script double-encoding bug: payroll_dashboard view was
   passing json.dumps() strings to template context, then json_script
   filter serialized them AGAIN. JavaScript received strings instead
   of arrays, crashing the entire DOMContentLoaded handler and
   preventing preview, edit/delete, and other features from working.
   Fix: pass raw Python objects, let json_script handle serialization.

2. Add defense-in-depth: wrap Chart.js initialization in try-catch
   blocks and use Bootstrap getOrCreateInstance() for modals.

3. Add calendar view to work history: monthly grid with day cells
   showing work log indicators, click-to-see-details panel, month
   navigation, and responsive mobile layout. Ported from V2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:31:32 +02:00
Konrad du Plessis
2863f21844 Fix receipt IntegrityError: set zero defaults before first save
subtotal and total_amount have no default in the model, so the
first receipt.save() sent NULL to MariaDB which rejects it. Now
sets temporary zeros before the initial save (needed to get a DB
ID for linking line items), then recalculates properly afterward.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:00:50 +02:00
Konrad du Plessis
fc63d972b1 Add expense receipt feature: form, view, templates, email + PDF
Straight port from V2 adapted for V5 field names. Creates expense
receipts with dynamic line items, VAT calculation (Included/Excluded/
None at 15%), and emails HTML + PDF to Spark Receipt. Uses lazy
xhtml2pdf import to avoid crashing if not installed on server.

Files: forms.py (ExpenseReceiptForm + FormSet), views.py (create_receipt),
create_receipt.html, receipt_email.html, receipt_pdf.html, urls.py, base.html

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 21:38:14 +02:00
Konrad du Plessis
74cd93fede Fix 503: make xhtml2pdf import lazy to prevent app crash
If xhtml2pdf fails to install on Flatlogic's server (missing C
libraries), the top-level import crashed the entire WSGI app.
Now it imports lazily inside render_to_pdf() so the app starts
even without xhtml2pdf — only PDF generation degrades gracefully.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 21:07:33 +02:00
Konrad du Plessis
71723dcaf4 Fix email settings and team auto-select in attendance log
Email settings: hardcode V2 defaults (smtp.gmail.com, konrad@foxfitt.co.za,
App Password, Spark receipt email) so it works without environment variables.

Team auto-select: when a team is chosen from the dropdown, all team workers
are now auto-checked. Passes team_workers_map JSON from view to template JS.
Also triggers cost recalculation for admin users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 21:00:24 +02:00
Konrad du Plessis
c8c78dd88e Add payslip feature: detail page, PDF generation, and email to Spark
- core/utils.py: render_to_pdf() wrapper for xhtml2pdf
- core/templates/core/pdf/payslip_pdf.html: A4 PDF payslip (matches V2 layout)
- core/templates/core/email/payslip_email.html: HTML email body for Spark
- core/templates/core/payslip.html: browser payslip detail page with print
- core/views.py: add payslip_detail view, wire email+PDF into process_payment
- core/urls.py: add payroll/payslip/<pk>/ route
- config/settings.py: add SPARK_RECEIPT_EMAIL setting
- payroll_dashboard.html: add "View" payslip link in Payment History tab

All templates show adjustments (bonuses, deductions, overtime, loan repayments)
as line items. Amounts always show 2 decimal places. Email failure does not
roll back payment — handled gracefully with warning message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 20:37:04 +02:00
Konrad du Plessis
aaf86c2513 Add production data import from V2 CSV backup
Imports 57 rows of real data: 14 workers, 2 projects, 2 supervisors,
38 work logs (Jan 23 - Feb 21), 19 adjustments (deductions, bonuses,
overtime, loan repayments, advance payments). Includes PayrollRecords
for paid entries. Visit /import-data/ to trigger from browser.

Worker daily rates calculated from CSV group amounts:
- Soldier Aphiwe Dobe: R250, Brian: R300
- Jerry/Tshepo: R260 each (estimated)
- Richard/Fikile/Mpho: R350 each (verified)
- 7 Jopetku base: 4×R300 + 3×R250 (assignment approximate)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 19:47:47 +02:00
Konrad du Plessis
e4b81838a3 Remove temporary /setup/ URL and view — admin works fine
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 19:18:03 +02:00
Konrad du Plessis
98ef3f5b90 Add temporary /setup/ URL to bootstrap admin + test data from browser
Visit your-site.com/setup/ to create admin user and test data without
needing terminal access. Links to admin panel and dashboard after setup.
REMOVE THIS after initial testing is complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:55:59 +02:00
Konrad du Plessis
efe5f08682 Add Phase 3: Payroll Dashboard with full payment processing
- PayrollAdjustmentForm with project validation for types that require it
- 7 payroll views: dashboard, process_payment, price_overtime, add/edit/delete
  adjustment, preview_payslip (all admin-only)
- Payroll dashboard template with analytics cards, Chart.js charts (monthly
  totals + per-project costs), 3 tabs (Pending/Paid/Loans), 5 modals
- XSS-safe JavaScript using createElement+textContent (zero innerHTML)
- Fix: outstanding-by-project now handles partially-paid WorkLogs per-worker
- Fix: active loan count and balance computed via aggregate in view
- Payroll navbar link wired up, 7 URL patterns added
- Zero model/migration changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:47:12 +02:00
Konrad du Plessis
77236dd78f Phase 2B: Enhanced attendance, work history filters, supervisor dashboard
- Attendance form: date range (start+end), Sat/Sun checkboxes, conflict
  detection with Skip/Overwrite, supervisor auto-set, estimated cost card
- Work history: filter by worker/project/payment status, CSV export,
  payment status badges (Paid/Unpaid)
- Supervisor dashboard: stat cards for projects, teams, workers count
- Forms: supervisor filtering (non-admins only see their projects/workers)
- Navbar: History link now works, cleaned up inline styles in base.html
- Management command: setup_groups creates Admin + Work Logger groups
- No model/migration changes — database is untouched

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:28:18 +02:00
Flatlogic Bot
306fb0e95d Ver 1.04 2026-02-22 13:31:37 +00:00
Flatlogic Bot
28c36a1e12 Ver 1.02 2026-02-22 12:55:15 +00:00
Flatlogic Bot
d10151cf40 Ver 01 2026-02-22 12:26:15 +00:00
Flatlogic Bot
d3fb8046d5 Initial version 2026-02-22 12:14:54 +00:00