Two payment-safety fixes in the Batch Pay modal JS:
1. Changing the team/loan filter force-checked every visible row,
silently re-selecting workers the admin had deliberately unticked
(untick a disputed worker -> change filter -> Confirm & Pay All pays
them anyway). Filters now only EXCLUDE (hidden rows untick); visible
rows keep the admin's manual choice, and Select All reflects the
real state instead of being forced on.
2. The batch-pay fetch() redirected to the dashboard on ANY HTTP
response — fetch only rejects on network failure, so a 500 (batch
died partway; each worker pays in its own transaction) looked like
success. Now checks resp.ok and tells the admin to verify the
History tab before retrying.
JS-only change; needs manual verification in the browser (no JS test
harness in this project).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
_send_payslip_email caught email errors, queued a warning toast, then
re-raised unconditionally — but only batch_pay catches that re-raise.
The Pay button (process_payment) and the three Pay-Immediately paths in
add_adjustment called it bare, so an SMTP failure AFTER the payment
committed replaced the warning with a 500 error page (the 28 May 2026
incident behaviour — admin can't tell the payment saved, may pay twice).
Re-raise is now conditional on suppress_messages=True (the batch path,
which counts failures in its summary); interactive callers get the
warning toast as intended. Regression tests cover both sides.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(3) PENDING: Konrad testing 17 May whether Spark Receipt handles the
is_salary payslip layout for variable-pay managers. (4) Deferred:
monthly_salary required field is misleading on manager report rows
(inert for pay; display-only tidy-up parked).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops core_sitereport via 0018_delete_sitereport. Knowledge preserved
in docs/plans/2026-05-17-site-report-removed-capture.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Also deletes AttendanceLogRedirectsToSiteReportTests (it asserted only
the removed redirect destination — a behavioural test, not a model
test). Suite 209 -> 208.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
Konrad confirmed the 36-commit bundle "all working well" on prod
(17 May 2026). Flip CLAUDE.md + parked-work.md production status from
"deploy pending" to "✅ fully caught up & verified at 80d96d7".
Also flags the in-progress (local-only) SiteReport removal.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Flip parked-work.md + CLAUDE.md from "paused, not pushed" to "pushed to
origin/ai-dev d7015b9..4c25011, Flatlogic VM deploy pending (migrate +
collectstatic + restart-last)". Prevents a fresh session reading stale
"not pushed" status.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Admin Quick Actions tile -> /payroll/?action=pay-salary; the payroll
page auto-clicks the existing paySalaryBtn then strips the param.
Reuses all existing Pay-Salary machinery; param inert server-side.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task 1: tile + deep-link hook + render test (TDD on the Django-render
part; auto-click is JS/manual-checklist). Task 2: docs. Suite 207->208.
Nothing pushed until Konrad's local verification.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Konrad-approved: a home-dashboard admin Quick Actions tile that
deep-links /payroll/?action=pay-salary and auto-clicks the existing
paySalaryBtn (then strips the param). Reuses all existing machinery;
no view/model/URL change. Rides the same paused-bundle HARD STOP.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When type=Salary: set pay-type filter to Managers-only, hide daily
rows, and untick any selected daily worker so a Salary can never
silently target a daily worker. Re-applied on the Pay-Salary open
path (the show.bs.modal reset clears it first). Pure JS; verified by
manual checklist; suite stays 207/207.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Konrad-approved: when Add-Adjustment type=Salary, auto-set the pay-type
filter to Managers-only, hide daily rows, and untick any selected daily
worker so a Salary can never silently target a daily worker. Pure JS,
hooks the toggleProjectField() chokepoint. Rides the same HARD STOP.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Prevents a pre-checked quick-adjust worker from opening hidden behind a
stale 'Managers only'/'Daily only' filter. Display-only; no data impact.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Konrad-approved design for a display-only ?pay_type= filter on /workers/
and a "Managers only" toggle on the Add-Adjustment modal picker. No
model/migration/URL changes; rides with the paused Manager/Salaried
feature's HARD STOP (nothing pushed until local verification).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final whole-feature review flagged the design doc's verification
checklist step 4 over-promised an auto-filled amount. Manual entry is
intentional; corrected so Konrad's local verification expectations match
actual behaviour. Docs-only, local-only — feature still NOT pushed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task-by-task TDD plan: Worker.pay_type + migration, Salary additive
type, attendance/absence picker exclusions, add_adjustment Salary
branch, per-project salaried-cost report line + byte-for-byte
daily-numbers regression guard, UI, docs. Ends with a HARD STOP
before any push for Konrad's local verification.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Models a manager as a Worker with a pay_type discriminator, reusing the
existing loan/adjustment/payslip/payroll pipeline. New 'Salary'
adjustment type, project-attributed; managers excluded from
attendance/absence pickers so daily-worker math is provably untouched.
HARD STOP after implementation for local verification before any push.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Konrad paused execution. parked-work.md now has a "⏸ Paused —
ready to execute" section pointing at the design (110545b) + plan
(29c36be) commits, with the resume instruction and the hard-stop
constraint. All 3 commits are local-only on ai-dev — nothing
pushed until Konrad verifies the flow locally.
4 small TDD tasks (~120 LOC): display rename, attendance 3-button
branch, Site Journal save+absences button, docs. Reuses Round C
next_action pattern. HARD STOP after Task 4 — local verification
by Konrad before any push (UX change to a daily-use path).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the forced post-attendance SiteReport redirect with 3
explicit buttons (Log Work → dashboard / + Site Journal / +
Absences) + a parallel "Save Site Journal + Add Absences" on the
journal page. Renames the user-facing "Site Report" → "Site
Journal" (display-only, Path-A; frees "Journal" for the parked
voice feature). Reuses the Round C next_action POST mechanism —
no model/migration/URL changes. NOT to be deployed until Konrad
verifies locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Konrad's decision (15 May 2026): Phase A.2 (manual JournalEntry
UI) + Phase B (Letterly inbound webhook) are too complex to
interleave with normal app work — they'll be built and tested
offline on a separate track, not in ai-dev.
Verified there is NOTHING to remove or bypass: zero JournalEntry
model/views/urls/templates, zero Letterly/webhook/@csrf_exempt
code anywhere on ai-dev, latest migration is 0015. The working
app was already 100% clean of journal/voice code — these features
never left the design-doc stage.
Doc changes:
- parked-work.md: "Blocked on Konrad's input" section replaced
with "🧊 Backburner — separate offline track", with an explicit
"do NOT start in ai-dev" warning and the nothing-to-remove
verification recorded.
- CLAUDE.md breadcrumb: reframed from "parked pending Q5/Q7
answers" (implies ready-to-go once answered) to "deliberately
deferred to offline track — do not pick up as normal feature
work".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>