Skip to content

T-134 β€” Records page + Employer's Returns (IR56M) tab overhaul

Why this exists

Owner-requested batch of UX/structure changes to the Records page and the IR56M ("Employer's Returns") tab, dumped across several messages on 2026-06-29 while reviewing the freshly-deployed app. Captured here so the interdependent pieces build in a sensible order instead of piecemeal.

Workstreams

A β€” Distribution settings modal (components/ir56m/IR56MDistributionEditModal.tsx + kebab)

  1. Remove the redundant "Distribution" text (the modal/section already says it).
  2. Stop showing the read-only notice ("The completed email has already been sent β€” these settings can no longer be changed."). Instead hide the settings AND the "Distribution settings" kebab item entirely once the IR56M is awaiting-signature / sealed / archived. β†’ This rolls back the "editable after signing on both tabs" behavior from T-047 #5d: distribution becomes set-only-at-sign-time. (Owner's explicit wording; flagged as a deliberate reversal.)

B β€” Tab title row (components/records/RecordsApp.tsx)

  1. Rename the Receipts parent tab β†’ "Receipts & Service Invoices" (inactive label).
  2. When selected, hide the grouped name and show "Receipts (x) | Service Invoices (x)" (the active-expand-to-subcounts pattern already exists for this tab β€” extend the label).
  3. Add an expand/collapse animation to that label transition.
  4. Merge Project Invoices + Coaching Invoices into one parent "Project & Coaching Invoices" with sub-tabs, applying #2 + #3 (inactive = grouped name; active = "Project Invoices (x) | Coaching Invoices (x)" + animation). RBAC: Project = ERL, Coaching = MEL β€” parent visible if the user can see either; each sub-tab gates to its own subsidiary.
  5. Reorder top-level tabs β†’ Project & Coaching Invoices | Receipts & Service Invoices | WOPCs | Bank Statements | Employer's Returns.
  6. Rename the IR56M tab β†’ "Employer's Returns" (owner wrote "Employment's Returns" β€” interpreting as the standard term; IR56M is an employer's return).

C β€” IR56M 7-state lifecycle (extends T-047 / I-018)

Replace the vestigial draft|confirmed|signed|filed enum + mirror the full lifecycle onto the filing doc (the I-018 mirror already shipped for draft↔signed). Locked labels:

key display colour set when
draft Drafted grey filing exists, configured FY not fully closed
awaiting_director Assign Signing Director red configured FY fully closed, no director
ready_to_send Signature Required gold director assigned, not sent
awaiting_signature Awaiting signature blue sent to director
rejected Rejected volcano director declined
sealed Sealed green signed & sealed
archived Archived purple completed copy distributed / fully settled & turned in
  • Window = the user-configured fiscal year (not the fixed 1 Apr–31 Mar YA). Re-key the draft β†’ awaiting_director gate to "configured FY fully closed."
  • Re-open + figure changed β†’ jump back to ready_to_send (keep director, void old copy).
  • Manual "fully close FY" gate + any further confirmation status β†’ deferred to T-133.
  • Collapse the Records tab's two status columns ("Status" + "Signing") into this one.

D β€” Employer's Returns tab: row selection + batch download

Mirror the Project Invoices tab selection behaviour (select + download + right-click menu) on the IR56M tab: - The collapsed FY (group) row is clickable + selectable; selecting an FY row = "all IR56Ms under that FY." - Support mixed selection: a whole FY row + individual recipient IR56M(s) inside expanded FYs, selected together. - Download = all signed IR56M PDFs across the selected FYs + individual rows (batch ZIP, reusing the records batch-download popup).

Build order (by dependency + risk)

  1. C (lifecycle) β€” foundational: A's hide-condition + the tab status column key off it.
  2. A (distribution modal) β€” uses C's statuses.
  3. D (selection + batch download) β€” self-contained to the IR56M tab.
  4. B (tab row) β€” self-contained top-level restructure (riskiest merge; do last so the IR56M-internal work isn't churned by it).

Decision log

2026-06-29 β€” βœ… Read AGENTS.md before opening this task. Source: Records (Infrastructure) Β· https://claude.ai/code/session_018RDB37kCqfouHdygVXTAtD

Owner dumped the spec across several 2026-06-29 messages (distribution modal β†’ tab row β†’ IR56M selection/download), plus the earlier locked 7-state lifecycle. Two interpretations pending owner confirm: (1) "Employment's Returns" β†’ "Employer's Returns"; (2) A#2 is a deliberate rollback of T-047 #5d's after-signing editing. Awaiting a single "go" before the multi-part build (touches shared RecordsApp.tsx + audit-critical IR56M code).

2026-06-29 β€” owner refinements (round 2)

Source: Records (Infrastructure) Β· https://claude.ai/code/session_018RDB37kCqfouHdygVXTAtD

  • "Employer's Returns" CONFIRMED (B#6).
  • WOPC batch-download filename β€” DONE this round (commit 2ef5733b): a sealed ref ERL-WOPC/2024-001 produced a ZIP entry with a /, nesting the file under an ERL-WOPC/ folder and dropping the <sub>-WOPC prefix. Flattened /β†’_ centrally in recordsBatchPopup (+ the WOPC filename builder). Not a workstream item β€” standalone bug.
  • D additions: (a) double-click a YA (FY) group row β†’ expand it; (b) IR56M download filename = <subsidiaryId>_IRD_IR56M_<FY>_<lastName>_<firstName>_<YYYYMMDD> (e.g. ERL_IRD_IR56M_FY24-25_Chan_Jeffero_20260629; date = download day).
  • C lifecycle revisions:
  • Blink every status tag EXCEPT Signed and Archived (CSS pulse).
  • Archived = the FY is manually closed β†’ render the tag and the entire YA row greyed out. ⚠️ Trigger = the manual FY-close gate, which is T-133 (currently deferred) β€” so Archived isn't reachable until T-133 ships (see open question below).
  • New state "Cooling Off" for a sealed IR56M inside the regret/cooling-off (grace) period. OPEN QUESTION (blocking C): the owner's confirm-list of 7 states does NOT include "Cooling Off", so its placement + colour are unresolved. Working hypothesis: Awaiting signature β†’ Cooling Off (signed, regret window open; distribution editable; blinks) β†’ Signed (regret elapsed/sent; no blink; distribution locked) β†’ Archived. Needs owner confirmation before building C.
  • A#2 hide-rule REVISED: hide the "Distribution settings" kebab item ONLY when the status is Signed or Archived (not the earlier "awaiting-signature/sealed/archived"). So distribution settings stay editable through Cooling Off β€” consistent with the regret window β€” and lock once Signed/Archived.
  • Cooling Off placement CONFIRMED (owner, 2026-06-29): conditional on the signing director's choice β€” regret window chosen β†’ Awaiting signature β†’ Cooling Off β†’ Signed; send-immediately β†’ Awaiting signature β†’ Signed (Cooling Off skipped). Maps to the distribution graceMode (grace vs immediate).

2026-06-29 β€” first batch SHIPPED + deployed (merge/C-finish remain)

Source: Records (Infrastructure) Β· https://claude.ai/code/session_018RDB37kCqfouHdygVXTAtD

Merged to main (merge commit 2f895c9b, PR #820). ⚠️ The 2f895c9b production build FAILED (next build TS7006 β€” implicit any on the IR56M tab's AntD Table callbacks; the sandbox's npx tsc missed it without the pinned TS + antd types). Prod stayed on the prior good build (no breakage). Fixed by annotating the callback params (ba730cbb, after npm ci + a faithful pinned-tsc check) β†’ the redeploy of ba730cbb is READY/live. Landed: - WOPC batch-download filename /-flatten (2ef5733b). - C inc 1 β€” derived 8-state IR56M status column (blink + Cooling Off split via the distribution grace window) (1243d747). - A β€” distribution modal: dropped the redundant "Distribution" text; the kebab "Distribution settings" item shows only during Cooling Off (59b413b8). - D β€” double-click a YA row to expand (4db54a8a); whole-FY + individual-recipient selection + batch ZIP of signed IR56Ms, filename <SUB>_IRD_IR56M_FY<yy-yy>_<Last>_<First>_<YYYYMMDD>.pdf (401c8533). - B part 1 β€” IR56M tab β†’ "Employer's Returns"; Receipts tab β†’ "Receipts & Service Invoices" with active sub-counts + expand animation (bd854760).

REMAINING (follow-up PR): - B#4 — merge Project + Coaching into one "Project & Coaching Invoices" parent (the high-risk multi-touch refactor: the tab IDs project-invoices/coaching-invoices are referenced in ~6 places — deep-link remap, active-tab toolbar logic, csvExportableTabs, keyboard shortcuts, the two selection stores, the activeTab effects — all must change in lockstep) + reorder to Project & Coaching | Receipts & Service Invoices | WOPCs | Bank Statements | Employer's Returns. - C-finish — re-key the Drafted→Assign-Director gate to the configured FY; Archived row-greying (needs T-133 manual FY-close); readjust→Signature-Required jump. - Small: right-click menu on the Employer's Returns tab (Project-Invoices parity); the Accounting→Filings distribution-gear cooling-off gate.

Blast radius (shipped): Records β†’ Employer's Returns tab (status column, selection, double-click), Receipts tab label, the IR56M distribution modal, and recordsBatchPopup (new ir56m BatchKind + the central /-flatten β€” affects every batch download).

2026-06-29 β€” batch 2 (merge + WOPC sorting + C item) on PR #821

Source: Records (Infrastructure) Β· https://claude.ai/code/session_018RDB37kCqfouHdygVXTAtD

Built on a fresh branch off the live main; on draft PR #821, pinned-tsc clean AND a local next build βœ“ Compiled successfully (the build phase that broke batch 1; the non-zero exit was a sandbox-only Firebase-env false negative on the unrelated /v/[id]). - B#4/B#5 β€” merged Project + Coaching β†’ "Project & Coaching Invoices" (animated sub-counts, in-place panes, RBAC-aware) + tab reorder; done via boundary edits (no 150-line block relocation) + a TAB_ORDER sort; all 8 tab-ID reference sites updated. - WOPC tab (owner follow-up) β€” sortable Reference column (numeric-aware) + the WOPC XLSX export ordered by ref number instead of issue date. - C item 3 β€” readjust (figure changed on YA re-close) β†’ a signed IR56M shows Signature Required (signature stale, needs void + re-file).

Deferred to T-133 (need the manual FY-close infra): C item 1 (re-key the Drafted→Assign-Director gate to the configured FY — the current fixed-YA gate is the legally-correct salaries-tax window, so this is a refinement, not a bug) and C item 2 (Archived row-greying — Archived is unreachable until the manual FY-close sets it).

2026-07-01 β€” reconciliation β†’ DONE (EOP Local Assistance board sweep)

Source: Records (Infrastructure) Β· https://claude.ai/code/session_018RDB37kCqfouHdygVXTAtD

Answering the fork's status question + adding the missing updated:: - PR #821 is MERGED and live in production. Its commits are in origin/main (8e108cf7 merge Project + Coaching + reorder; f8f988b5 readjust β†’ Signature Required; c8d362e6 the batch-2 docs entry) and it deployed 2026-06-30 alongside I-020. - Workstreams A / B / C / D β€” all shipped + deployed (PR #820 batch 1, live build ba730cbb, + PR #821 batch 2). The owner reviewed the deployed result across the 2026-06-29β†’30 iterations. - Only substantive remainder is carved into T-133 (todo): C item 1 (configured-FY gate re-key) + C item 2 (Archived row-greying). Both need the manual FY-close infra, so they are correctly NOT part of T-134. - Two minor batch-1 "Small" follow-ups were NOT built β€” descoped (owner never re-requested; reopen or spin a ticket if wanted): 1. A row right-click context menu on the Employer's Returns tab for Project/WOPC-tab parity. The tab has selection + batch download + a click-kebab, but not the trigger:['contextMenu'] row menu the Project/WOPC tabs use (RecordsApp.tsx 2571/2757 vs zero onContextMenu in IR56MFilingsTab.tsx). 2. The Accounting β†’ Filings distribution-gear cooling-off gate. The gear exists (IR56MFilingTab.tsx) and the Records-side distribution modal is already Cooling-Off-gated; matching that visibility gate on the Accounting Filings gear was never separately done.

Closing T-134 done β€” the owner-requested overhaul is delivered + live; the deferred work is tracked in T-133 and the two residuals are minor, un-requested polish.