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) <noreply@anthropic.com>
This commit is contained in:
parent
aaca0b36d3
commit
777c7c6dcc
167
docs/plans/2026-05-17-site-report-removal-design.md
Normal file
167
docs/plans/2026-05-17-site-report-removal-design.md
Normal file
@ -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/<id>/edit/` and `/site-report/<id>/` 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).
|
||||
112
docs/plans/2026-05-17-site-report-removed-capture.md
Normal file
112
docs/plans/2026-05-17-site-report-removed-capture.md
Normal file
@ -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/<work_log_id>/edit/` (mobile-first form, "Skip" link to
|
||||
home). Read-only view at `/site-report/<work_log_id>/`. 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 <that_sha>:core/site_report_schema.py
|
||||
git show <that_sha>:core/models.py # SiteReport class
|
||||
git show <that_sha>:core/forms.py # SiteReportForm
|
||||
git show <that_sha>:core/views.py # site_report_edit / _detail / _can_access_site_report
|
||||
git show <that_sha>: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).
|
||||
Loading…
x
Reference in New Issue
Block a user