38686-vm/docs/plans/parked-work.md
Konrad du Plessis 7d4d7b1f8b docs: park the production deploy step + rotate parked-work queue
Worker Absences feature shipped (bf6f0a5..27fe05e), so it's no
longer the active queue item. Promoted the pending production
deploy (run /run-migrate/, collectstatic, restart service) to the
top of parked-work.md — production /history/ is 500ing until those
migrations run. CLAUDE.md breadcrumb updated to flag this as the
next operator action when a fresh session starts.

Also captured the small polish follow-ups from the absences code
reviews (AbsenceQuickForm dead code, N+1 in team_workers_map,
duplicated CSV filter block, etc.) so they don't get lost in a
future janitorial pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 23:43:32 +02:00

8.7 KiB

Parked / deferred work

Updated 14 May 2026 (late evening). A small index of features that are designed, half-built, blocked on input, or pending an operator step. When a fresh session opens, glance here first to see what's already on the workbench.


⚠ Needs operator action (production)

Production deploy of SiteReport + Absences (pending Konrad)

Status: All code committed and pushed to origin/ai-dev (HEAD 27fe05e as of 14 May 2026 late evening). Production at https://foxlog.flatlogic.app/ has pulled the new code but is crashing on /history/ with:

ProgrammingError: (1146, "Table 'app_38686.core_sitereport' doesn't exist")

Why: Flatlogic auto-pulled the new code but didn't run migrations. The new template logic references log.site_report, which queries a table that doesn't exist yet on the production MySQL.

The fix (~2 minutes total):

  1. Backup first (safety net) — visit https://foxlog.flatlogic.app/backup-data/ while logged in as admin. Download the .json file to a safe location.
  2. Run pending migrations — visit https://foxlog.flatlogic.app/run-migrate/. Applies three migrations:
    • 0013_add_site_report — creates core_sitereport table (fixes the immediate /history/ error)
    • 0014_add_absence — creates core_absence table
    • 0015_absence_project — adds project FK to absence
  3. Refresh static files + restart service — ask Gemini in Flatlogic to run:
    python3 manage.py collectstatic --noinput
    sudo systemctl restart django-dev.service
    
    Needed because static/css/custom.css has new .badge-absence-* rules — without collectstatic, the reason badges on the new pages will render with no color.
  4. Smoke test (incognito) — visit foxlog.flatlogic.app/history/ (should load), /absences/ (should load), Resources → Absences (admin dropdown should now have it). Log one test absence end-to-end.

Rollback if anything breaks: visit https://foxlog.flatlogic.app/restore-data/, upload the backup from step 1, ask Gemini to restart the service.

Why this is parked, not urgent: The /history/ error only fires when someone actively uses the History page. The dashboard, attendance log, and payroll pages all work fine. Konrad chose to defer the deploy step — that's the right call when you don't have time to babysit a deploy properly.

Reference: the deployment hazard is documented in CLAUDE.md under "Migrations" in the Flatlogic/AppWizzy Deployment section.


Blocked on Konrad's input

Phase A.2 — Manual JournalEntry web UI

Status: Designed in the Site Work Logging brainstorm. Model class drafted in the design doc (not yet in core/models.py). Not yet built.

Blocked on: Q7 from the original brainstorm — "Who is Vi?" The answer drives whether JournalEntry needs a recipient or audience field (i.e. is this a public log, or does it have specific addressees like a client). Default if unanswered: no recipient field — entries are all-admin-readable.

Scope when unblocked: ~1 hour of work. Manual entry form at /journal/new/, list at /journal/, edit at /journal/<id>/edit/. Admin-only views. Lives on ai-dev (no webhook involvement).

Phase B — Letterly inbound webhook (integrations branch)

Status: Designed in the Site Work Logging brainstorm. Belongs on the integrations branch, not ai-dev.

Blocked on: Q5 from the original brainstorm — Konrad needs to share a sample Letterly webhook payload. Need to know:

  • Does it include the recording user (so we can map to a Django User)?
  • Does it include project / location metadata, or just the transcript?
  • Does it include an audio URL for link-back?
  • Does Letterly support custom fields (so a deep-link from /site-report/<id>/edit/ could embed a work_log_id that the webhook reads back)?

Scope when unblocked: ~3-4 hours including tests + one-off Letterly account setup. Adds a @csrf_exempt view at /webhooks/letterly/, JournalEntry row creation, HMAC body verification, shared-secret URL token.


Small polish follow-ups from the Absences feature

These were flagged during code review of the absences feature but deemed non-blocking. They can roll into a future janitorial pass.

  • AbsenceQuickForm is defined but never wired upcore/forms.py:797-827. Originally planned for a per-worker ✗ modal on the attendance form, but Round C replaced that paradigm with the "Submit + Log Absences" button. Either wire the form up somewhere or delete the class. ~30 LOC.
  • N+1 in team_workers_map build — affects both attendance_log and absence_log. Pre-existing in attendance_log; Round A inherited the pattern. Fix is to use Prefetch('workers', queryset=Worker.objects.filter(active=True), to_attr='active_workers_cached') like the payroll dashboard does. Recommend extracting _build_team_workers_map(user) as a shared helper.
  • absence_list permission check duplicates _user_can_log_absencescore/views.py:5535 inlines is_admin(user) or user.supervised_teams.exists() instead of calling the helper. Trivial DRY cleanup.
  • --badge-neutral-bg referenced but never definedstatic/css/custom.css near line 2197. The CSS uses var(--badge-neutral-bg, #6c757d) for .badge-absence-unpaid and .badge-absence-other; the fallback always wins because the variable isn't declared in :root. Either define it in both themes or drop the var() wrapper.
  • conflicting_worklogs() runs N queries per (worker, date) paircore/forms.py:785-786. Fine at FoxFitt's scale. Worth profiling if/when batch sizes grow.
  • CSV export filter block is duplicatedcore/views.py absence_export_csv copies the filter logic from absence_list. TODO comment in code says "factor into _apply_absence_filters when a third filter joins."
  • Paid-checkmark icon in site_report_detail.html uses color: var(--badge-bonus-bg) (a BACKGROUND color) as foreground — fails WCAG contrast on white. Same fix as we applied to absence templates (use text-success). Trivial one-line change.

Defaulted (not blocking — flag if you disagree)

From Q9, Q4 of the Site Work Logging brainstorm:

  • Q9 — photos on site reports. Deferred to v2 of SiteReport. Construction supervisors often want to attach a phone photo of "plinths cast today" but it adds ~50 LOC + storage handling + thumbnail rendering. v1 ships without.
  • Q4 — per-project metric templates. Same metric set for all projects in v1. If/when a non-solar-farm project lands and the metrics diverge wildly, we add a MetricTemplate model. YAGNI for now — core/site_report_schema.py is one Python file edit.

Recently shipped (for context, so a fresh session knows what just landed)

  • Worker Absences feature (commits bf6f0a527fe05e, 14 May 2026): Complete absence-tracking system. 8 reason choices, optional project FK (auto-attributes paid-absence Bonus adjustments to the project), date-range logging with weekend toggles, supervisor scoping (admin sees all; supervisors see their teams). Standalone /absences/log/ form + "Submit + Log Absences" shortcut on attendance form. List/edit/delete + CSV export. Worker-detail "Absences" tab with YTD totals. Dashboard alert card "X absent in last 7 days". Bidirectional cascade with PayrollAdjustment via _sync_absence_payroll_adjustment helper (single-chokepoint design, transaction.atomic-wrapped). All 12 commits pushed to origin/ai-dev. Test count: 85 → 149 (+64 tests). All ai-dev tests green.
  • Phase A.1 — SiteReport (commit 864ae72, 14 May 2026): Model, migration 0013_add_site_report.py, form, two-step flow from attendance log, 16 new tests. CLAUDE.md updated with model summary + site_report_schema.py pattern section.
  • Pastel soft-fill payroll action buttons (commit 6c6ade9, 24 Apr 2026): unified Worker Lookup / Batch Pay / Add Adjustment / Price Overtime treatment.
  • Path A display-only rename (UX Polish Pass, Apr 2026): "New Loan" / "Advance Payment" / "Advance Repayment" display as "Loan" / "Advance" / "Advance Repaid" — but DB values are unchanged. See "UI-vs-DB naming drift" section in CLAUDE.md before writing any filter/comparison on PayrollAdjustment.type.

Original Site Work Logging brainstorm

The full Q1-Q13 question list and design rationale lives in ~/.claude/plans/prancy-painting-brook.md (local — deliberately not committed to the repo, since the parts that matter have been absorbed into CLAUDE.md and this file). If Konrad answers Q5 or Q7 later, refer back to that file for the original framing.