Monthly Coach Payroll Process
What & Why
Turn the existing one-off coach timesheet flow into a disciplined
monthly payroll cycle with checks and balances, so nothing slips between an event happening and a coach getting paid. Today coaches submit hours per session (, PENDING → APPROVED → PROCESSED) and a ledger expense is recorded, but there is no payroll period, no setup/extra-time approval lane, no month-end close, no reconciliation against the event/staffing lists, and no structured hand-off to the bookkeeper. This adds all of that.
The end-to-end process we are building (most pieces 1–7 already exist; this task adds the bolded parts): 1. Coach applies → SuperAdmin approves assignment → coach accepts (exists). 2. Event happens; coach attends (exists). 3. Coach submits a timesheet for scheduled hours (exists), and can add setup/teardown/extra time as separate, approvable lines. 4. A per-event Head Coach OR a SuperAdmin/Coordinator approves the extra/setup time before it becomes payable. 5. Every timesheet belongs to a calendar-month payroll period with a submission cutoff (the 3rd of the next month). 6. A month-end reconciliation + SuperAdmin "close & approve" step verifies nothing is missing, then hands the batch to the bookkeeper. 7. The bookkeeper reviews the approved batch and marks it Paid (no external file/export needed), which finalizes the ledger expenses. 8. Automated reminder/reconciliation messages keep coaches, head coaches, SuperAdmins, and the bookkeeper on track so nothing is missed.
Product decisions (confirmed with the user)
- Extra/setup-time approval: a per-event Head Coach OR a SuperAdmin/Coordinator can approve their team's extra/setup time.
- Period & cutoff: period = calendar month (1st–last day). Coaches must submit by the 3rd of the following month; after that the SuperAdmin closes the period.
- Final payout: the bookkeeper marks the batch "Paid" inside the app — no CSV/bank export required.
Done looks like
- A coach, after an event, can submit their scheduled hours AND add separate "setup", "teardown", or "extra" time entries with a note. Those extra entries show as "Awaiting approval" until approved.
- The event's Head Coach (or a SuperAdmin/Coordinator) sees a list of pending extra-time requests for their event(s) and can approve or decline each with a reason. Declined/never-approved extra time is never paid.
- Every timesheet and approved extra-time entry is automatically grouped into the calendar month it belongs to. Coaches and admins can see "April 2026 payroll" as a unit.
- There is a clear monthly status a SuperAdmin can watch: Open → Submission Closed → Approved & Sent to Bookkeeper → Paid.
- A month-end reconciliation screen cross-checks the period: every completed event that needed staff, every accepted/completed coach assignment, whether each coach submitted a timesheet, whether any setup/extra time is still awaiting approval. Gaps are listed clearly ("Coach X worked Event Y on Apr 12 but has not submitted a timesheet"; "2 extra-time requests still pending").
- A SuperAdmin cannot mark the month "Approved & Sent to Bookkeeper" while unresolved gaps exist, unless they explicitly acknowledge/override each one (captured in an audit note).
- The bookkeeper sees the approved monthly batch with a per-coach total, can open the detail, and marks it Paid in one place. Marking Paid finalizes the existing ledger expense entries for that batch.
- Automated messages fire on a schedule: a post-event "submit your timesheet" nudge to coaches; reminders to head coaches with pending extra-time approvals; a reminder near the 3rd to coaches who still have outstanding timesheets; a month-end summary to SuperAdmins with the count of outstanding items; and a notification to the bookkeeper when a batch is sent.
- Every status change (submit, approve extra time, close, approve month, send to bookkeeper, mark paid) records who did it and when.
Out of scope
- External payroll-provider exports (CSV/NACHA/bank files) — confirmed not needed.
- Per-timesheet digital signatures beyond the existing submit action.
- Direct-deposit / actual money movement — "Paid" is a status the bookkeeper sets after paying out-of-band.
- Changing how athlete attendance or QR check-in works.
- Changing how hourly rates are set (reuse the existing rate resolution: assignment rate → coach custom rate → default).
Architectural constraints
- Reuse existing infrastructure; do not duplicate it. Timesheets already live in (PENDING/APPROVED/PROCESSED) with a unique 1:1 link to , and the ledger expense is already written via in on PROCESSED. The monthly "Paid" step should drive that finalization rather than introduce a parallel ledger path.
- Check what Task #80 ("Add Setup/Takedown Time Logging", merged) already added before building the setup/extra-time model — extend it with the approval lane instead of recreating columns/UI.
- New money/period tables must follow the project's Drizzle conventions in (insert schema via with , select/insert types exported). Apply schema with (this project does not use migration files); confirm new columns/tables exist after pushing.
- Payroll period for a timesheet is derived from the work date (event date), parsed as America/Regina local time (never UTC) per the project's timezone rule, so an event late on the last day of the month lands in the correct month.
- Any NEW in-memory email coalescer MUST use + from with a mirror table and boot-time recovery wired into (see the crash-safe coalescer rule in replit). Prefer the existing tick-based scheduler pattern (source rows in a table, swept on a schedule) for the new reminders, which avoids buffering in RAM.
- Any new scheduler job that runs less than daily (e.g. a month-end tick) MUST add a staleness override in () or it will false-positive the daily silent-failure alert.
- All authorization is server-side. Head-coach approval rights must be verified on the server from the actual (role = head coach for that event), never trusted from the client. Bookkeeper/SuperAdmin/Coordinator gates use the existing role checks.
Steps
1.
Payroll period + extra-time data model — Add a concept (calendar-month rows with start/end, submission deadline = 3rd of next month, and a status lifecycle Open → Submission Closed → Approved/Sent → Paid, plus who/when audit stamps). Link each row to its period (derived from the event work date in local time). Add an approvable extra/setup-time model (kind = setup/teardown/extra, minutes, note, status pending/approved/declined, approver + reason), building on whatever Task #80 already added. Push the schema and verify. 2.
Coach side: submit hours + add extra time — Extend the coach timesheet/session workbench so a coach can add setup/teardown/extra-time entries alongside their scheduled hours, each with a note, shown as "Awaiting approval" until resolved. Surface the coach's current-month payroll grouping and the submission deadline. 3.
Extra-time approval (Head Coach OR SuperAdmin/Coordinator) — Add a server-enforced approval surface where the event's head coach, or a SuperAdmin/Coordinator, sees pending extra-time requests for their events and approves/declines each with a reason. Approved extra time becomes payable and rolls into the month's totals; declined never pays. 4.
Month-end reconciliation + SuperAdmin close & approve — Build a reconciliation view for a selected month that cross-references completed events and their staffing needs against accepted/completed coach assignments, submitted timesheets, and unresolved extra-time. List every gap plainly. Let the SuperAdmin move the period Open → Submission Closed (on/after the 3rd) → Approved & Sent to Bookkeeper, blocking approval while gaps remain unless each is explicitly acknowledged (stored as an audit note). 5.
Bookkeeper batch review + mark Paid — In the Bookkeeper Portal, show the approved monthly batch with per-coach totals and drill-down, and a single "Mark Paid" action that finalizes the batch and its ledger expense entries. Record who/when. 6.
Reminders & checks (messages so nothing is missed) — Add scheduled, deduped notifications/emails: post-event "submit your timesheet" nudge to coaches; pending-extra-time reminders to head coaches; an escalating reminder before the 3rd to coaches with outstanding timesheets; a month-end outstanding-items summary to SuperAdmins; and a "batch sent" notification to the bookkeeper. Use the tick-based scheduler pattern (or the crash-safe coalescer helpers if buffering is unavoidable) and register staleness overrides for any sub-daily job. 7.
Docs — Update (Product + Architecture decisions + Gotchas) to describe the monthly payroll cycle, the period state machine, the extra-time approval rule, the reconciliation gate, and the new scheduler jobs.
Relevant files
- - - - - - - - - - - - - - - - -
No comments:
Post a Comment