# Parked / deferred work > Updated 12 Jun 2026. 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. --- ## πŸ”§ Audit leftovers (12 Jun 2026) β€” small, deliberate deferrals The 12 Jun 2026 technical-audit bundle (deployed; see CLAUDE.md breadcrumb) deliberately left these on the bench: 1. **Team/project batch-report per-row queries.** `_build_team_report_context` and `_build_project_report_context` (`core/views.py`) still run a per-team/per-project query loop (~2 queries Γ— ~6 rows on `/teams/report/` and `/projects/report/`). Same disease as the fixed worker report; skipped because the pages are rarely used and the fix pattern is already proven (copy the batched-GROUP-BY-dict restructure from `_build_worker_report_context`). Do it next time those pages feel slow or get touched anyway. 2. **JS vs server decimal-separator inconsistency (cosmetic).** Browser-side money helpers use `toLocaleString('en-ZA')` β†’ comma decimals (`R 2 400,00`); server-side `money` filter renders dot decimals (`R 2 400.00`). Pre-dates the audit; harmonising means choosing ONE convention and touching both sides. Pure cosmetics β€” decide when something user-facing forces the question. 3. **Stale VM safety branches.** Five `pre-*` branches on the VM (four from Apr 2026 + `pre-audit-deploy-20260612`). After a few days of confirmed stability post-12-Jun, tell the Flatlogic agent to delete them all (the 20260612 one anchors autosave `98f66e9`, whose only real content is now properly committed as `abfae69`). 4. **gitea mirror auth broken** β€” operator step: Konrad asks Erik (Flatlogic support) to restore the VM's gitea credentials; then re-sync with `git push gitea ai-dev` (may need `--force`). Until then deploys are GitHubβ†’VM one-way. Details in CLAUDE.md "Git remotes on the VM". --- ## ⏸ Paused β€” ready to execute (not started, not pushed) ### Site-progress logging β€” rebuild from scratch (parked) The SiteReport / "Log Today's Work" feature was **removed 17 May 2026** (Konrad's call β€” work mix shifting, scope uncertain). The post-attendance flow now simply returns to the dashboard. A future rebuild starts fresh β€” see `docs/plans/2026-05-17-site-report-removed-capture.md` (preserves the schema-as-Python pattern, recovery pointers, and the now-superseded `2026-05-15-post-attendance-flow-v2-*` prior thinking, which stays on disk). **Removal status: SHIPPED.** Pushed to origin and confirmed deployed on production (migration `0018_delete_sitereport` shows `[X]` applied β€” verified 12 Jun 2026 during the audit-bundle deploy). Nothing pending; only the future rebuild remains parked. --- ## βœ… Shipped & live β€” Manager / Salaried bundle (17 May 2026) ### Manager / Salaried Pay (+ pay-type filter + Salary auto-scope + Pay Salary quick action) **Status:** Brainstormed + designed + planned + **fully implemented**, every task two-stage code-reviewed, **PUSHED and DEPLOYED**. The 36-commit bundle `d7015b9..4c25011` is live on production (`https://foxlog.flatlogic.app/`) and **Konrad verified it "all working well" on 17 May 2026**. `origin/ai-dev` HEAD `80d96d7` == prod (only delta over `4c25011` is doc breadcrumbs). Migrations `0016`/`0017` applied; `static/css/custom.css` collected. **209/209 tests green.** Design/plan docs: `2026-05-15-manager-salaried-pay-*`, `2026-05-16-managers-paytype-filter-*`, `2026-05-16-salary-autoscope-picker-*`, `2026-05-16-pay-salary-quick-action-*` (all under `docs/plans/`). Nothing pending on this bundle β€” fully done. **What it does:** Lets a manager / salaried worker be paid a fixed monthly amount without ever logging attendance. A new `Worker.pay_type` (`'daily'` default | `'fixed'`) marks managers; they're excluded from attendance + absence pickers ONLY (NOT payroll modals / TeamForm β€” they must stay payable), and paid via a new `Salary` `PayrollAdjustment` type (project-required; "Pay Immediately" β†’ isolated PayrollRecord like New Loan; unpaid nets via `_process_single_payment`). The report shows a separate per-project "Management / Salaried Cost" line β€” never merged into WorkLog-derived daily labour cost, so all existing money math is provably unchanged. "Manager / Salaried" is a Path-A display-only label (model stays `Worker`). Migrations `0016_worker_pay_type`, `0017_alter_payrolladjustment_type`. **To resume:** the push is done; the remaining step is the **Flatlogic VM deploy** (ordered steps in the Status block above β€” migrate + collectstatic + restart-last). After Gemini/Konrad deploys, verify on `https://foxlog.flatlogic.app/` using the manual checklists in the four design docs, then update this file's "Production status" + the CLAUDE.md "What's mid-flight" breadcrumb to "fully caught up at `4c25011`". No code changes pending β€” implementation is complete and reviewed. Now also includes a display-only pay-type filter (design `docs/plans/2026-05-16-managers-paytype-filter-design.md`, plan `docs/plans/2026-05-16-managers-paytype-filter-plan.md`): a `/workers/?pay_type=fixed` filter + dropdown and a "Managers only" client-side toggle on the Add-Adjustment modal picker. Shipped in the 36-commit push `d7015b9..4c25011`. Also now: setting the Add-Adjustment **type = Salary** auto-scopes the picker β€” pay-type filter β†’ "Managers only", daily rows hidden, and any selected daily worker auto-unticked (UI guard so a `Salary` can never silently target a daily worker). Design `docs/plans/2026-05-16-salary-autoscope-picker-design.md`, plan `docs/plans/2026-05-16-salary-autoscope-picker-plan.md`. Shipped in the 36-commit push `d7015b9..4c25011`. Also now: a home-dashboard admin Quick Actions tile **"Pay Salary"** deep-links `/payroll/?action=pay-salary` and auto-opens the existing Pay Salary modal (param stripped after; no re-pop on refresh). Design `docs/plans/2026-05-16-pay-salary-quick-action-design.md`, plan `docs/plans/2026-05-16-pay-salary-quick-action-plan.md`. Shipped in the 36-commit push `d7015b9..4c25011`. #### Follow-ups from code review (parked, out of scope for this feature) 1. **Atomicity hardening (cross-cutting, pre-existing).** `add_adjustment`'s three immediate-payment branches β€” `New Loan`, `Advance Payment`, and now `Salary` β€” create a `PayrollAdjustment` + `PayrollRecord` and call `_send_payslip_email` WITHOUT a wrapping `transaction.atomic()`, and `_send_payslip_email` re-raises on email failure. A mid-sequence failure can therefore orphan a payment row / 500 after commit. This is **PRE-EXISTING** (Salary just consistently matches the New Loan / Advance pattern, it did not introduce the gap) β€” flagged by Task 5 code review as a separate hardening ticket, **NOT a Manager/Salaried defect**. Recommended future cross-cutting fix: wrap each immediate-branch body in `transaction.atomic()` and swallow/log email failures the way `process_payment` already does. Out of scope for this feature. 2. **Pre-existing flaky test.** `AbsenceListViewTests` (in `core/tests.py`) has an `assertContains`/`assertNotContains` against the `/absences/` list HTML that intermittently failed ~1-in-3 in one run during this feature's execution, then passed on rerun; 3+ subsequent full-suite runs were clean. A reviewer's isolation analysis concluded it's pre-existing environmental nondeterminism (proper Django `TestCase` transactional isolation; the Manager/Salaried tests cannot perturb it). Low priority: investigate a possible date/locale or response-rendering nondeterminism in that test. **NOT introduced by this feature.** 3. **⏳ PENDING OPERATOR VERIFICATION β€” Spark Receipt payslip handling for Salary payments (Konrad testing 17 May 2026).** Manager/Salaried `Salary` payments email a payslip PDF to Spark Receipt (`_send_payslip_email`, `SPARK_RECEIPT_EMAIL`) using the `is_salary` clean single-line layout (no work-log/days table β€” mirrors `is_advance`/`is_loan`). Konrad's managers (Konrad, Christiaan, Fitz) have **variable** monthly pay β€” there is no fixed salary; the amount is entered manually per Salary adjustment. UNKNOWN: whether Spark Receipt's downstream system parses/accepts this Salary payslip format the same as a normal daily-worker payslip. Konrad is testing a real Salary payment **later today (17 May 2026)**. Until confirmed, this is an OPEN external- integration verification, NOT an in-app defect. If Spark Receipt mishandles it β†’ follow-up to adjust the `is_salary` payslip template / email body (`pdf/payslip_pdf.html`, `email/payslip_email.html`, `core/payslip.html`). 4. **Deferred display tidy-up β€” `monthly_salary` is misleading for fixed-pay managers.** `Worker.monthly_salary` is a required field (no null/blank) but means nothing for variable-pay managers. It is **inert for their pay/cost** (managers never reach a `WorkLog`, so `daily_rate` / all WorkLog-derived math never includes them) yet still **displays** as "monthly salary" + a computed "daily rate" on the worker detail page, worker batch report, and CSV/PDF exports β€” authoritative-looking but meaningless numbers on manager rows. Pragmatic interim: enter a representative figure (or 0) for managers. Optional future tidy-up (small, display-only, no pay/cost impact): hide/relabel the monthly-salary field for `pay_type='fixed'` in `WorkerForm` + `workers/edit.html`, and suppress/relabel the monthly/daily columns for managers in `workers/detail.html`, `workers/batch_report.html`, the workers CSV export, and `pdf/workers_report_pdf.html`. Low priority β€” flagged by Konrad 17 May 2026. > Note: the **Site-progress logging β€” rebuild from scratch** parked > entry above is unaffected by this Manager/Salaried entry (it was > superseded separately by the 17 May 2026 SiteReport removal). --- ## Production status β€” βœ… fully caught up (15 May 2026) Production (`https://foxlog.flatlogic.app/`) is deployed at `origin/ai-dev` HEAD **`1d224bc`**. Everything is live: the original SiteReport + Absences feature, all UX polish, the team filters, the dashboard/report number audit (18 findings), and the template-comment + subline-clarity fixes. (The 17 May Manager/ Salaried bundle has since shipped too β€” see the "Shipped & live" section above.) **In-progress local-only work (HARD STOP β€” not pushed):** the SiteReport / "Log Today's Work" removal β€” Tasks 1-3 done, suite **193 OK**, migration `0018_delete_sitereport` drops the table. Un-pushed pending Konrad's local verify; see the "Site-progress logging β€” rebuild from scratch (parked)" entry above + the capture doc `docs/plans/2026-05-17-site-report-removed-capture.md`. **Deploy-ordering lesson learned (now in CLAUDE.md):** production runs `DEBUG=False` β†’ Django's cached template loader holds compiled templates in memory until the process restarts. The 14 commits of template fixes were briefly "invisible" because the service was restarted *before* the code reached the target commit. The fix was simply to restart AGAIN once `git log` confirmed the right commit. Correct order is always: `git reset --hard github/ai-dev` β†’ migrate (if needed) β†’ collectstatic (if `static/` changed) β†’ restart **last**. See the "DEPLOY ORDERING" bullet in CLAUDE.md's Flatlogic Deployment section. --- ## 🧊 Backburner β€” journal/voice features (separate offline track) > **Decision (15 May 2026):** Konrad parked the entire journal / > voice-transcript line of work. It's more complex than the rest of > the app and will be built + tested **offline, on a separate > track**, NOT mixed into `ai-dev`. **Do NOT start either of these > in `ai-dev` or in any normal feature session.** They are not > "blocked waiting on an answer" β€” they are deliberately deferred > until Konrad chooses to spin up a dedicated offline effort. **Important β€” nothing is in the working app.** Verified 15 May 2026: zero `JournalEntry` model / views / URLs / templates anywhere in `core/`, zero Letterly / webhook / `@csrf_exempt` code on `ai-dev`, latest migration is `0015_absence_project`. There is no dead code, no feature flag, no migration to reverse. "Removing" these was a no-op β€” they were never built into the running app. The working app (`ai-dev` + production) is completely clean of journal/voice code. ### Phase A.2 β€” Manual JournalEntry web UI (deferred) Designed in the Site Work Logging brainstorm (`~/.claude/plans/ prancy-painting-brook.md`, local). A `JournalEntry` model + manual entry form/list/edit, admin-only. Open question if/when resumed: **Q7 "Who is Vi?"** β€” drives whether `JournalEntry` needs a `recipient`/`audience` field. Default if never answered: no recipient field, all-admin-readable. ~1 hour scope. When resumed, build on the offline track first, not directly in `ai-dev`. ### Phase B β€” Letterly inbound webhook (deferred) Designed in the same brainstorm. A `@csrf_exempt` view at `/webhooks/letterly/` that creates `JournalEntry` rows from voice transcripts, with HMAC body verification + shared-secret URL token. Open question if/when resumed: **Q5 β€” a sample Letterly webhook payload** (does it include the recording user / project metadata / audio URL / custom fields?). ~3-4 hours scope + one-off Letterly account setup. This was always meant to live on the `integrations` branch, never `ai-dev` β€” and now it's offline-track until Konrad revisits. --- ## Small polish follow-ups from the Absences feature > All 7 cleared on 15 May 2026 (commit `d1d3e15`). Kept the section > header in place because more polish items will accumulate from > future code reviews β€” when they do, append here. The shipped items > are summarized under "Recently shipped" below. --- ## Defaulted (not blocking β€” flag if you disagree) The Q9 (photos on site reports) and Q4 (per-project metric templates) defaults from the Site Work Logging brainstorm are now **obsolete** β€” the SiteReport feature was removed 17 May 2026. Both were open design considerations for that feature; they are captured (along with the rest of the design rationale) in `docs/plans/2026-05-17-site-report-removed-capture.md` for whoever rebuilds site-progress logging from scratch. --- ## Recently shipped (for context, so a fresh session knows what just landed) - **Dashboard + report numbers audit** (commits `18c75b2` β†’ `c02edce`, 15 May 2026): Konrad spotted that the home dashboard's "Paid This Month" actually showed the last 60 days. A thorough audit found 17 more issues across the home dashboard, payroll dashboard, and report. All 18 fixed in 7 commits: calendar-month math, outstanding totals aligned between dashboards, `Project.name` dedupe (was silently merging same-named projects), `timezone.localdate()` replacing `timezone.now().date()` (SAST drift fix), off-by-one on "last 7 / 60 days" windows, dead `year_projects`/`year_teams` context removed, `_company_cost_velocity` rewritten as single SQL aggregate, signed/coloured adjustment amounts on report tables (Bonus vs Deduction now visually distinct), "Outstanding Now" hero card subline now shows scope when filters active, dual daily_rate code paths documented in CLAUDE.md. 160 β†’ 173 tests (+13 regression). - **Absence-feature polish pass** (commit `d1d3e15`, 15 May 2026): Seven small cleanups in one focused commit. (1) Deleted unused `AbsenceQuickForm` (Round C made it obsolete). (2) Extracted `_build_team_workers_map(user)` helper using `Prefetch(..., to_attr=...)`, fixing N+1 on both `attendance_log` and `absence_log` (one query instead of one-per-team). (3) `absence_list` now calls the existing `_user_can_log_absences` helper. (4) Removed undefined `var(--badge-neutral-bg)` CSS wrapper β€” fallback hex was always winning anyway. (5) `conflicting_worklogs()` rewritten as a single query with Python-side pair-set filtering β€” 25-query β†’ 2-query for a 5Γ—5 form. (6) Extracted `_apply_absence_filters(qs, request)` shared by `absence_list` + `absence_export_csv` so adding a filter param now touches one place, not two. (7) `site_report_detail.html` paid-check icon uses `text-success` instead of background-color variable as foreground (WCAG contrast fix). 157/157 tests still green. - **Day name in Work Log Payroll modal header** (commit `70fa085`, 15 May 2026): The modal opened from /history/ now shows "Friday, 15 May 2026" instead of "2026-05-15". Pure server-side `strftime` on the already-loaded `log.date` β€” zero overhead. - **Team filters on `/workers/` and `/history/`** (commits `4b57cff`, `398a5b2`, 15 May 2026): Both pages now have a Team dropdown in their filter row. `/workers/?team=` filters by Team.workers M2M membership (who's CURRENTLY on the team); `/history/?team=` filters by WorkLog.team FK (logs TAGGED with the team when created β€” different semantics, intentional). Both accept `team=none` for the "no team assigned" / "ad-hoc work log" case. CSV export at `/history/export/` honours the same param. +8 regression tests. - **Absences UX polish** (commits `4368e53`, `02c6d4d`, 15 May 2026): Two production-found bugs fixed. (1) Absence-form team filter was hiding ALL workers when a team was selected β€” switched the JS to read `[value]` directly instead of going through `data-worker-id` (proven attendance-form pattern). (2) Reasons multi-checkbox dropdown on `/absences/` was rendering behind the table β€” lifted the filter card with `position: relative; z-index: 10` so the whole card sits above its sibling table card in the stacking order. See the Coding Style section in CLAUDE.md for both gotchas. - **Worker Absences feature** (commits `bf6f0a5` β†’ `27fe05e`, 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). 12 commits pushed to `origin/ai-dev`. Test count: 85 β†’ 149 (+64 tests). Migrations `0013_add_site_report`, `0014_add_absence`, `0015_absence_project` are LIVE on production as of late 14 May 2026. - **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.