From 777c7c6dcccbb80113c06a16f78ef1cdf09facfa Mon Sep 17 00:00:00 2001 From: Konrad du Plessis Date: Sun, 17 May 2026 01:23:09 +0200 Subject: [PATCH] docs: SiteReport removal design + future-rebuild capture doc Konrad-approved design to fully remove the SiteReport / "Log Today's Work" feature (drop core_sitereport, no backup, revert post-attendance to redirect-home). Capture doc preserves the schema-as-Python pattern, the flow, recovery pointers, and rebuild guidance. Local-only; the removal itself is HARD-STOPPED before push. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../2026-05-17-site-report-removal-design.md | 167 ++++++++++++++++++ .../2026-05-17-site-report-removed-capture.md | 112 ++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 docs/plans/2026-05-17-site-report-removal-design.md create mode 100644 docs/plans/2026-05-17-site-report-removed-capture.md diff --git a/docs/plans/2026-05-17-site-report-removal-design.md b/docs/plans/2026-05-17-site-report-removal-design.md new file mode 100644 index 0000000..eb168e0 --- /dev/null +++ b/docs/plans/2026-05-17-site-report-removal-design.md @@ -0,0 +1,167 @@ +# Remove "Log Today's Work" / SiteReport — Design + +**Date:** 17 May 2026 +**Status:** Approved by Konrad on 17 May 2026; ready for implementation plan. +**Branch:** `ai-dev` (origin HEAD `aaca0b3` at design time — production +caught up & verified). **HARD STOP before push** — destructive +migration on the daily-use attendance path; Konrad verifies locally +first. + +## Goal (one sentence) + +Completely remove the optional post-attendance SiteReport ("Log Today's +Work") feature — model, table, code, UI, routes, tests, docs — with no +remnants and nothing broken, reverting the post-attendance flow to its +pre-SiteReport behaviour, and preserve the design thinking in a capture +doc for a future from-scratch rebuild. + +## Why + +Konrad wants to rethink site-progress logging from scratch separately. +The work mix is shifting ("we might start piling and not cast so many +plinths anymore") so the metric set and the whole scope are genuinely +uncertain — half-fitting code is worse than a clean slate. The feature +was lightly used; **Konrad explicitly accepted irreversible loss of any +existing SiteReport data (no backup)** when choosing the removal path. + +## Decision (from the brainstorm) + +Konrad chose **"Drop the table — no backup"**: a real migration +(`0018_delete_sitereport`) drops `core_sitereport` on deploy; no +production backup is taken. Full removal, no orphaned model/table. + +## §1 — Behavioural change (the only user-visible effect) + +`core/views.py::attendance_log` POST, currently ~lines 750-785: after a +successful submit it `return redirect('site_report_edit', +work_log_id=created_log_ids[-1])`. After removal: just +`return redirect('home')` — the existing green "Successfully created N +work log(s)." toast still fires. This reverts to the original +pre-SiteReport behaviour. + +- The **`next_action == 'log_absences'`** branch (the "Submit + Log + Absences" shortcut) is **untouched** — unrelated to SiteReport. +- The now-dead `created_log_ids` list (`= []` + `.append()`) and the + Round-C comment's "log_only → Site Report flow" wording are cleaned + up so no dead plumbing remains. `dates_to_log[-1]` (used by the + absences branch) is unaffected. + +## §2 — Code / model / template removal (no remnants) + +**Delete entire files:** +- `core/site_report_schema.py` +- `core/templates/core/site_report_edit.html` +- `core/templates/core/site_report_detail.html` + +**Edit:** +- `core/models.py` — delete the `SiteReport` class + its doc-header block. +- `core/forms.py` — delete `SiteReportForm` and the + `from .site_report_schema import …` line (and the form's surrounding + doc-header comment). +- `core/views.py` — delete `_can_access_site_report`, + `site_report_edit`, `site_report_detail`; remove the `SiteReport`, + `SiteReportForm`, `site_report_schema` imports; drop + `select_related('site_report')` in `work_history` (use plain + `WorkLog.objects` / keep other select_related args intact); remove + the SiteReport redirect block + dead `created_log_ids` plumbing in + `attendance_log` (per §1). +- `core/urls.py` — delete the two `path('site-report/…')` routes. +- `core/admin.py` — delete the `@admin.register(SiteReport)` block and + the `SiteReport` import. +- `core/templates/core/work_history.html` — delete the report + indicator / link block (`{% if log.site_report %}` … the + `site_report_detail` / `site_report_edit` anchors, ~lines 462-471). + +**Migration:** after the model is gone, run `python manage.py +makemigrations core` → it generates **`0018_delete_sitereport`** +(`DeleteModel`, depends on `0017_alter_payrolladjustment_type`). Do not +hand-write it — let the autodetector emit the correct +RemoveField/DeleteModel ordering. `makemigrations --check` must be +clean afterwards. + +## §3 — Tests + +Delete the 5 SiteReport-only classes in `core/tests.py`: +`SiteReportModelTests`, `SiteReportFormTests`, `SiteReportEditViewTests`, +`SiteReportDetailViewTests`, `AttendanceLogRedirectsToSiteReportTests`, +plus the `from core.models import SiteReport` / +`from core.forms import SiteReportForm` lines (~1629-1630) and the +section header comment block (~1624-1631). + +The one cross-reference — `test_log_only_explicit_value_still_goes_to_site_report` +(~line 2873, inside the absences-shortcut test class) — asserts the OLD +contract. **Rewrite** it (rename to e.g. +`test_plain_submit_redirects_home`) to assert the NEW contract: a plain +attendance POST (no `next_action` / `next_action='log_only'`) → HTTP +302 to `/`. This keeps regression coverage of the reverted flow rather +than deleting coverage outright. + +Full suite must stay green at the new count (209 minus the deleted +SiteReport tests, ± the rewritten one). The exact expected number is +computed and pinned in the plan. + +## §4 — Docs + +- **CLAUDE.md:** delete the entire "SiteReport metric schema + (Apr 2026)" section; the Key Models `SiteReport` bullet; the + `/site-report//edit/` and `/site-report//` URL-routes table + rows; and any two-step-flow / "auto-redirected here after + /attendance/log/ POST" mentions. Add a one-line pointer under the + relevant area: SiteReport removed 17 May 2026 — see capture doc. + (The production breadcrumb was already flipped to ✅ in commit + `aaca0b3`.) +- **docs/plans/parked-work.md:** the **"Post-Attendance Flow v2"** + entry (under "⏸ Paused — ready to execute") is now obsolete — it + reworked the very flow being deleted. Replace it with a short + "SiteReport removed; future rebuild parked" pointer to the capture + doc. Keep the `2026-05-15-post-attendance-flow-v2-*` design/plan + files on disk (prior thinking worth mining) — the capture doc marks + them superseded. +- **New capture doc** `docs/plans/2026-05-17-site-report-removed-capture.md` + (written now, in this design step) — preserves the institutional + knowledge for the future rebuild (see that file). + +## §5 — Process / scope + +- **Done already (separate, pushed):** the production-caught-up + breadcrumb flip (commit `aaca0b3`). +- **This removal:** writing-plans → subagent-driven execution → **HARD + STOP before any push**. Konrad runs the local verification, then + pushes. +- **Deploy (when Konrad later approves):** pull → `python3 manage.py + migrate` (applies `0018`, drops `core_sitereport`) → restart. **No + `collectstatic`** (no `static/` change — pure code/template/model + deletion). Restart still required (DEBUG=False template cache). +- **No backup** of SiteReport data (Konrad's explicit choice — accepted + irreversible loss). + +## Local verification (Konrad — HARD STOP gate) + +1. Submit `/attendance/log/` → lands straight on the dashboard `/` with + the green "Successfully created N work log(s)." toast — **no** + "Log Today's Work" page. +2. "Submit + Log Absences" button still jumps to `/absences/log/` + prefilled (unchanged). +3. `GET /site-report/1/edit/` and `GET /site-report/1/` → **404** + (routes gone). +4. Django admin (`/admin/`) shows **no** SiteReport model. +5. `python manage.py makemigrations --check` → clean (no pending); + `python manage.py migrate` applies `0018_delete_sitereport` with no + errors; `core_sitereport` table is gone. +6. Full test suite green. +7. `grep -ri "sitereport\|site_report\|site-report" core/` → only + inert historical migration files `0013`/`0014` match (expected — + immutable history, not a code remnant); zero matches in + models/views/forms/urls/admin/templates/tests. + +Then — and only then — Konrad pushes; deploy as in §5. + +## Out of scope (deliberately) + +- No replacement site-progress feature now (that's the future separate + rethink — captured, not built). +- Absences shortcut, Manager/Salaried, pay-type filter, Salary + auto-scope, Pay Salary quick action — all untouched. +- The historical migrations `0013`/`0014` are NOT edited (immutable + Django history; "no remnants" means no live code/model/UI, not + rewriting migration history). diff --git a/docs/plans/2026-05-17-site-report-removed-capture.md b/docs/plans/2026-05-17-site-report-removed-capture.md new file mode 100644 index 0000000..40cafd8 --- /dev/null +++ b/docs/plans/2026-05-17-site-report-removed-capture.md @@ -0,0 +1,112 @@ +# SiteReport / "Log Today's Work" — Removed; Future-Rebuild Capture + +**Date removed:** 17 May 2026 +**Why this doc exists:** Konrad removed the SiteReport feature to +rethink site-progress logging **from scratch, separately**. This file +preserves everything worth knowing so a future session can rebuild it +without re-deriving the design — and without resurrecting code that no +longer fits. + +> **Status: NOT a plan. Do NOT implement from this file.** It is a +> knowledge capsule. A future rebuild starts with a fresh +> brainstorming pass (see "When you rebuild" at the bottom). + +## Why it was removed (the important part) + +The on-site work mix is changing. The original feature was modelled +around a solar-farm foundation workflow (plinths cast, plinth holes +dug, boxes placed, steel placed, …). Konrad's words: *"we might start +piling and not cast so many plinths anymore so the scope might get +bigger or smaller."* The metric set — and whether a fixed metric set is +even the right model — is genuinely unknown. Half-fitting code on a +daily-use path is worse than a clean slate. So: full removal now, +deliberate redesign later when the new workflow is clearer. + +Konrad explicitly accepted **irreversible loss of existing SiteReport +rows** (no backup taken) — the data was lightly used and not worth +carrying into a redesign. + +## What it did (so you don't have to reverse-engineer it) + +A `SiteReport` model, **optional 1:1 with `WorkLog`** (a WorkLog with +no report was a normal historical row). Fields: + +- `weather` (choices: sunny/cloudy/rain/storm/hot/cold/windy), + `temperature_min` / `temperature_max` (°C, IntegerField), + free-form `notes`, `created_by`, `created_at`, `updated_at`. +- `metrics` — a `JSONField` of shape + `{'counts': {key: int}, 'checks': {key: bool}}`. + +### The one genuinely good idea worth keeping: schema-as-Python, no migration + +The metric **keys were NOT model columns**. They lived in a single +Python file `core/site_report_schema.py` (`COUNT_METRICS`, +`CHECK_METRICS`, `label_for()`). Adding/removing/renaming a metric was a +one-line edit + redeploy — **no DB migration**, old rows degrade +gracefully (missing key → 0/unchecked; retired key still shows via +`label_for` fallback). `SiteReportForm` iterated the schema at +`__init__` to build dynamic `IntegerField`/`BooleanField`s and +serialised back into the JSON blob on `save()`. + +**This pattern is the single most reusable lesson.** Given Konrad's +"scope may get bigger or smaller" concern, a flexible-by-default schema +(JSON blob + a Python/DB-driven field list) is almost certainly the +right foundation again — possibly upgraded to an admin-managed +`MetricTemplate` model if per-project metric sets diverge. + +### The flow it was wired into + +Two-step: `attendance_log` POST (success) → redirect to +`/site-report//edit/` (mobile-first form, "Skip" link to +home). Read-only view at `/site-report//`. Permission: +admin, or supervisor of the WorkLog's team/project. On removal the flow +reverted to the original **redirect → home + success toast**. + +## Prior thinking already on disk (mine these, then move past them) + +- `docs/plans/2026-05-15-post-attendance-flow-v2-design.md` + + `-plan.md` — a *fully designed, Konrad-approved-but-never-built* + rework of this flow: replace the forced redirect with 3 explicit + buttons (Log Work → dashboard / + Site Journal / + Absences), plus a + "Save + Add Absences" button; and a Path-A display-only rename + "Site Report" → **"Site Journal"** (to free the word "Journal" for + the parked voice-notes feature). **Superseded by the removal** — the + flow it modified no longer exists. Kept on disk because the + button-hierarchy and naming-collision analysis are good raw material. +- `docs/plans/2026-05-17-site-report-removal-design.md` — the removal + design that this capture accompanies. + +## How to recover the deleted implementation if you want a reference + +The full original implementation is in git history. The recovery point +is **the commit immediately before `0018_delete_sitereport` landed** on +`ai-dev`. To find and read any deleted file: + +``` +git log --oneline -- core/site_report_schema.py # last commit is the recovery point +git show :core/site_report_schema.py +git show :core/models.py # SiteReport class +git show :core/forms.py # SiteReportForm +git show :core/views.py # site_report_edit / _detail / _can_access_site_report +git show :core/templates/core/site_report_edit.html +``` + +Nothing is lost from *code* history — only the production *table* and +its rows were dropped. + +## When you rebuild (guidance, not a plan) + +1. **Brainstorm first** — the new workflow (piling vs casting, etc.) + must drive the metric model. Do not start from the old metric list. +2. **Keep the JSON-blob + Python/admin-driven schema** idea — it is the + right answer to "scope may change." Decide early: fixed global + schema vs per-project `MetricTemplate`. +3. **Decide the flow deliberately** — the v2 design's "3 explicit + buttons, no forced redirect" instinct was sound; revisit it with + fresh eyes against the new workflow. +4. **Re-evaluate the model name** — "SiteReport" / "Site Journal" / + something else; mind the parked voice-notes "Journal" collision + noted in the Backburner section of `parked-work.md`. +5. New design doc + plan under `docs/plans/`, normal + brainstorm → writing-plans → subagent execution, HARD STOP before + push (it touches the daily attendance path).