diff --git a/CLAUDE.md b/CLAUDE.md index 03fea03..815b6f7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -34,17 +34,35 @@ password manager. **Strategic side note:** SSH access closes the `C:\Users\konra\.claude\plans\prancy-painting-brook.md` (off-platform backup of `media/` is now feasible via `rsync`). -**🔧 In progress — local only, NOT pushed (HARD STOP):** removal of -the "Log Today's Work" / **SiteReport** feature (Konrad wants to -rethink it from scratch separately — work mix is shifting). -**Implemented locally — Tasks 1-3 complete:** model/table/UI/routes -deleted, migration `0018_delete_sitereport` drops `core_sitereport`, -post-attendance flow now returns to the dashboard, suite **193 OK**. -Still un-pushed and under a HARD STOP — nothing reaches origin until -Konrad verifies locally (destructive migration on the daily-use -attendance path). Design knowledge preserved for a future rebuild in -the capture doc `docs/plans/2026-05-17-site-report-removed-capture.md`; -see also the parked rebuild entry in `docs/plans/parked-work.md`. +**SiteReport removal — pushed to origin (per git, 12 Jun 2026).** The +"Log Today's Work" / SiteReport removal (migration +`0018_delete_sitereport`, commit `7f5e4c9` + follow-ups through +`663b7d9`) is on `origin/ai-dev` — the old "local only, NOT pushed" +HARD STOP here is resolved. Production deploy status of those commits +should be confirmed with Konrad before assuming prod has them +(deploy needs: pull → `/run-migrate/` for `0018` → restart). Design +knowledge for a future rebuild lives in +`docs/plans/2026-05-17-site-report-removed-capture.md`; see also the +parked rebuild entry in `docs/plans/parked-work.md`. + +**🔧 In progress — local only, NOT pushed (HARD STOP): 12 Jun 2026 +audit-fix bundle.** A comprehensive technical audit (4 parallel +review agents + manual verification of every finding) produced 9 +local commits on `ai-dev` (`14ab8d0..921bdb6`): email-failure 500 +after committed payments fixed (the 28 May incident class), Batch Pay +modal no longer silently re-ticks unticked workers + surfaces server +errors, payments with deductions > earnings are REFUSED (Konrad's +decision — no negative PayrollRecords), attendance date range capped +at 31 days, worker-report views survive junk query params, **worker +batch report's lifetime "Total Paid" column was inflated by the +work-log join (real display bug — fixed + regression test)**, report +page N+1s killed, money paths standardised on Decimal. Suite **206 +OK** locally. **Nothing reaches origin until Konrad verifies +locally** — payment-path behaviour changes. Manual checks Konrad +should do: Batch Pay modal filter behaviour, attendance-form cost +estimator still computes, one preview-payslip open. Deploy (when +approved): pull → restart (NO new migrations; no `static/` changes so +no collectstatic; restart required — cached template loader). **🧊 Backburner — do NOT start in `ai-dev`:** Phase A.2 (manual JournalEntry UI) and Phase B (Letterly inbound webhook) are @@ -87,7 +105,7 @@ core/ — Single main app: ALL business logic, models, views, forms, forms.py — AttendanceLogForm, PayrollAdjustmentForm, ExpenseReceiptForm + formset models.py — All 10 database models utils.py — render_to_pdf() helper (lazy WeasyPrint import + Windows GTK3 DLL registration) - views.py — All view functions (~52 functions, ~3,800 lines) — dashboard, attendance, payroll, reports, worker/team/project CRUD + views.py — All view functions (~6,000 lines) — dashboard, attendance, payroll, reports, worker/team/project CRUD forms.py — All form classes + validators (WorkerForm, TeamForm, ProjectForm, AttendanceLogForm, PayrollAdjustmentForm, ExpenseReceiptForm, WorkerCertificate/WarningFormSet, 5MB file validator) admin.py — Django admin registrations for all core models + WorkerCertificate/Warning inlines on Worker templatetags/ — format_tags.py: `money` (ZAR), `money_abs` (signed callers), `type_slug` (type→CSS class), `url_replace` (swap one query-param), `dictlookup` @@ -357,6 +375,16 @@ section below) to find it. The test suite does NOT have `assertNumQueries` guards on these views — deliberate YAGNI for now, worth adding if regressions become a pattern. +**Jun 2026 audit note:** the history tab (`?status=history`), `/report/`, +`/workers/report/`, and the Batch Pay preview all had per-row query +loops removed (prefetches + batched GROUP BY dicts) — their query +counts should now be FLAT regardless of row count. The same audit also +fixed a real aggregation bug: mixing `Sum('payroll_records__...')` with +counts over OTHER relations in one `.annotate()` multiplies the Sum by +the join row count (see `WorkerReportLifetimeTotalsTests`) — keep +multi-valued aggregates on separate querysets / one relation per +annotate. + ## Commands ```bash # Local development (SQLite)