feat(iac-daily-list): add IAC Daily List and Additional Cases list types (#791) - #879
Conversation
Add two manually-published list types for the Immigration and Asylum Chamber, rendered as read-only bilingual GOV.UK style-guide pages: - IAC_DAILY_LIST (/iac-daily-list) - IAC_DAILY_LIST_ADDITIONAL_CASES (/iac-daily-list-additional-cases) New lib @hmcts/iac-daily-list with schema, validator, renderer, PDF generator and en/cy locales. Registered in the seed catalogue, PDF generator registry and web app. Daily List is always ordered before Additional Cases under the same venue via a stable-name tie-break in summary-of-publications, regardless of publish order. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Port pip-frontend's party-role manipulation so the Appellant/Applicant, representative and Prosecuting authority columns populate from CLAIMANT_PETITIONER, CLAIMANT_PETITIONER_REPRESENTATIVE and PROSECUTING_AUTHORITY (with raw role codes converted via partyRoleMappings). Wrap the case sequence indicator in square brackets and format sitting start times as h:mma (e.g. "2:00pm") to match pip exactly. These fixes flow through to the PDF, which reuses the same renderer. Add the IAC daily list email summary builder and register it in the notification EMAIL_BUILDER_REGISTRY for both IAC_DAILY_LIST and IAC_DAILY_LIST_ADDITIONAL_CASES. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…link Match pip-frontend staging: the list title becomes a caption, the "First-tier Tribunal: Immigration and Asylum Chamber" heading becomes the h1, and the venue name + "Daily List" the h2. Add the missing "Find contact details and other information about courts and tribunals in England and Wales, and some non-devolved tribunals in Scotland." link. Applied to both HTML templates and the PDF template. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the caption and separate h2; the h1 now reads "First-tier Tribunal: Immigration and Asylum Chamber" with the venue name and "Daily List" on a second line. Applied to both HTML templates and the PDF. The #top back-to-top anchor moves onto the h1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the "Search by case reference, appellant, or other details" label text. The search input keeps an accessible name via a visually-hidden label reusing the "Search Cases" heading, so it stays WCAG-compliant. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
IAC_DAILY_LIST_ADDITIONAL_CASES shares the IAC_DAILY_LIST JSON schema, so alias the iac-daily-list-additional-cases package to iac-daily-list in the validator dispatch. JSON uploads for the additional-cases list type now validate via validateIacDailyList instead of failing with "no schema". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tional Cases"
The additional-cases h1 now reads "First-tier Tribunal: Immigration and
Asylum Chamber / {venue} Daily List - Additional Cases". Adds a
dailyListAdditionalCases locale key (en + cy) and an isAdditionalCases flag
on the rendered header so the shared PDF template picks the right suffix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (8)
🚧 Files skipped from review as they are similar to previous changes (8)
📝 WalkthroughWalkthroughSummaryThe change adds IAC Daily List and Additional Cases support. It introduces schemas, rendering, Welsh and English pages, PDF generation, email summaries, catalogue entries, publication ordering, application wiring, and implementation documentation. ChangesIAC Daily List
Sequence Diagram(s)sequenceDiagram
participant Browser
participant IACRoute
participant Validator
participant IACRenderer
participant Nunjucks
Browser->>IACRoute: Request IAC list artefact
IACRoute->>Validator: Validate publication JSON
Validator-->>IACRoute: Return validation result
IACRoute->>IACRenderer: Render data with locale
IACRenderer-->>IACRoute: Return rendered hearings
IACRoute->>Nunjucks: Render IAC template
Nunjucks-->>Browser: Return HTML page
Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🎭 Playwright E2E Test Results82 tests 52 ✅ 5m 54s ⏱️ Results for commit a05cf9f. ♻️ This comment has been updated with latest results. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
The IAC Daily List and Additional Cases templates were byte-identical except for the h1 suffix. Collapse them into a single iac-daily-list.njk that branches on header.isAdditionalCases, and point both list types at it. Remove the duplicate template and its test, the stray ticket schema copy, and the obsolete list-type-data test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (4)
libs/publication/package.json (1)
42-42: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winPin the new workspace dependency version.
workspace:*is not an exact dependency version and does not meet the package-version policy.
libs/publication/package.json#L42-L42: use the exact IAC package version through the workspace protocol.libs/notifications/package.json#L39-L39: use the same exact IAC package version.As per coding guidelines, packages must “use pinned dependency versions except for peer dependencies.”
Source: Coding guidelines
libs/list-types/iac-daily-list/src/pdf/pdf-generator.ts (1)
17-28: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueFollow the required module declaration conventions.
Rename
__filenameand__dirnameto SCREAMING_SNAKE_CASE, and movePdfGenerationOptionsto the type section at the bottom of the module.As per coding guidelines, “Constants declared outside functions must use SCREAMING_SNAKE_CASE” and interfaces/types must be “at the bottom.”
Source: Coding guidelines
apps/web/src/pages/(public)/summary-of-publications/index.test.ts (1)
707-801: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winGood cross-type ordering coverage; consider adding a same-type case.
These tests confirm
IAC_DAILY_LISTsorts beforeIAC_DAILY_LIST_ADDITIONAL_CASESregardless of publish order/locale. Consider adding a case with twoIAC_DAILY_LISTartefacts on different content dates to guard against the date-ordering regression described onindex.tslines 107-112.libs/list-types/iac-daily-list/src/index.ts (1)
2-2: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMove the type-only export to the end of the module.
Place
export type { ValidationResult } ...after the value exports.As per coding guidelines, interfaces and types must be ordered at the bottom of TypeScript modules.
Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 2521e0a9-d4b4-47d9-b2bf-bcc5a2567137
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (42)
apps/web/package.jsonapps/web/src/app.tsapps/web/src/pages/(list-types)/iac-daily-list/iac-daily-list-additional-cases.njkapps/web/src/pages/(list-types)/iac-daily-list/iac-daily-list-additional-cases.njk.test.tsapps/web/src/pages/(list-types)/iac-daily-list/iac-daily-list.njkapps/web/src/pages/(list-types)/iac-daily-list/iac-daily-list.njk.test.tsapps/web/src/pages/(list-types)/iac-daily-list/index.test.tsapps/web/src/pages/(list-types)/iac-daily-list/index.tsapps/web/src/pages/(public)/summary-of-publications/index.test.tsapps/web/src/pages/(public)/summary-of-publications/index.tsdocs/tickets/791/iac_daily_list.schema.jsondocs/tickets/791/pip-reference.mddocs/tickets/791/plan.mddocs/tickets/791/review.mddocs/tickets/791/tasks.mddocs/tickets/791/ticket.mdlibs/list-types/common/src/list-type-data.test.tslibs/list-types/common/src/list-type-data.tslibs/list-types/common/src/validation/list-type-validator.test.tslibs/list-types/common/src/validation/list-type-validator.tslibs/list-types/iac-daily-list/package.jsonlibs/list-types/iac-daily-list/src/config.tslibs/list-types/iac-daily-list/src/email-summary/summary-builder.test.tslibs/list-types/iac-daily-list/src/email-summary/summary-builder.tslibs/list-types/iac-daily-list/src/index.tslibs/list-types/iac-daily-list/src/locales/cy.tslibs/list-types/iac-daily-list/src/locales/en.tslibs/list-types/iac-daily-list/src/models/types.tslibs/list-types/iac-daily-list/src/pdf/pdf-generator.test.tslibs/list-types/iac-daily-list/src/pdf/pdf-generator.tslibs/list-types/iac-daily-list/src/pdf/pdf-template.njklibs/list-types/iac-daily-list/src/rendering/renderer.test.tslibs/list-types/iac-daily-list/src/rendering/renderer.tslibs/list-types/iac-daily-list/src/schemas/iac-daily-list.jsonlibs/list-types/iac-daily-list/src/validation/json-validator.test.tslibs/list-types/iac-daily-list/src/validation/json-validator.tslibs/list-types/iac-daily-list/tsconfig.jsonlibs/notifications/package.jsonlibs/notifications/src/notification/notification-service.tslibs/publication/package.jsonlibs/publication/src/processing/service.tstsconfig.json
| // IAC Daily List must always appear before its Additional Cases list, regardless | ||
| // of publish order or locale. Keyed on the stable list-type name, so no other | ||
| // list type's ordering is affected. | ||
| if (a.name in IAC_ORDER && b.name in IAC_ORDER) { | ||
| return IAC_ORDER[a.name] - IAC_ORDER[b.name]; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Same-type IAC comparisons short-circuit before the date tie-breaker.
a.name in IAC_ORDER && b.name in IAC_ORDER is also true when a.name === b.name (e.g. two IAC_DAILY_LIST entries with different content dates). In that case IAC_ORDER[a.name] - IAC_ORDER[b.name] is always 0, so the comparator returns "equal" and never falls through to the date-descending/language tie-breakers applied to every other list type. Multiple publications of the same IAC list type can end up out of date order. None of the new "IAC Daily List ordering" tests cover this (they only compare the two different IAC types against each other).
🐛 Proposed fix
- if (a.name in IAC_ORDER && b.name in IAC_ORDER) {
+ if (a.name in IAC_ORDER && b.name in IAC_ORDER && a.name !== b.name) {
return IAC_ORDER[a.name] - IAC_ORDER[b.name];
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // IAC Daily List must always appear before its Additional Cases list, regardless | |
| // of publish order or locale. Keyed on the stable list-type name, so no other | |
| // list type's ordering is affected. | |
| if (a.name in IAC_ORDER && b.name in IAC_ORDER) { | |
| return IAC_ORDER[a.name] - IAC_ORDER[b.name]; | |
| } | |
| // IAC Daily List must always appear before its Additional Cases list, regardless | |
| // of publish order or locale. Keyed on the stable list-type name, so no other | |
| // list type's ordering is affected. | |
| if (a.name in IAC_ORDER && b.name in IAC_ORDER && a.name !== b.name) { | |
| return IAC_ORDER[a.name] - IAC_ORDER[b.name]; | |
| } |
| > This plan is grounded in the actual repo. The embedded ticket spec (by | ||
| > `hmctsclaudecode`) is broadly correct about the helper names and registration | ||
| > points — those were verified to exist. Several concrete claims were **wrong or | ||
| > imprecise** and are corrected inline (see the "SPEC CORRECTION" callouts and | ||
| > §5). The single biggest unknown is that the pip source files (schema, template, | ||
| > locales, manipulation service) **cannot be fetched from this environment** — the | ||
| > exact field names, columns and grouping must be ported by a human before the | ||
| > renderer/schema/template can be finalised. Everything downstream of those field | ||
| > names is blocked on that port. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Remove the stale “blocked” source-porting statement.
This contradicts docs/tickets/791/pip-reference.md, which now records the fetched schema, required fields, and locale strings. Update the plan to identify that reference as the implementation source of truth.
🧰 Tools
🪛 LanguageTool
[style] ~15-~15: Would you like to use the Oxford spelling “finalized”? The spelling ‘finalised’ is also correct.
Context: ...e the > renderer/schema/template can be finalised. Everything downstream of those field >...
(OXFORD_SPELLING_Z_NOT_S)
| HIGH-priority items should be addressed before merge: a client-side search-filtering | ||
| wiring gap on the IAC templates, and unverified party-role string constants in the | ||
| renderer. A third HIGH item is the incomplete AC2 permutation coverage. | ||
|
|
||
| Overall verdict: **NEEDS CHANGES** (both ACs met and coverage strong, but the | ||
| search-box functional defect and the unverified party-role mapping warrant a fix | ||
| before merge). |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Make the AC2 test-gap prioritisation consistent throughout the review.
The record lists three HIGH items but repeatedly summarises only two, while also describing the missing Welsh permutation as low impact and not an AC2 failure. Downgrade it to a recommended coverage improvement, or include and justify it consistently as a HIGH item.
docs/tickets/791/review.md#L17-L23: correct the “two HIGH-priority items” summary.docs/tickets/791/review.md#L81-L90: align the item’s severity with its stated low impact.docs/tickets/791/review.md#L175-L182: keep the AC2 status and test-gap priority consistent.docs/tickets/791/review.md#L211-L217: update the final verdict to match the chosen classification.
📍 Affects 1 file
docs/tickets/791/review.md#L17-L23(this comment)docs/tickets/791/review.md#L81-L90docs/tickets/791/review.md#L175-L182docs/tickets/791/review.md#L211-L217
| const __filename = fileURLToPath(import.meta.url); | ||
| const __dirname = path.dirname(__filename); | ||
|
|
||
| export const moduleRoot = __dirname; | ||
| export const assets = path.join(__dirname, "assets/"); | ||
| export const schemaPath = path.join(__dirname, "schemas/iac-daily-list.json"); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Use SCREAMING_SNAKE_CASE for module-level constants.
Rename these to FILENAME, DIRNAME, MODULE_ROOT, ASSETS, and SCHEMA_PATH, then update consumers such as the validator import.
As per coding guidelines, constants declared outside functions must use SCREAMING_SNAKE_CASE.
Source: Coding guidelines
| summaries.push([ | ||
| { label: "Appellant/Applicant", value: parties.appellant }, | ||
| { label: "Prosecuting authority", value: parties.prosecutingAuthority }, | ||
| { label: "Case reference", value: caseItem.caseNumber ?? "" } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Localise the remaining IAC presentation strings. Welsh output still contains hard-coded English email labels, PDF metadata title, and document language.
libs/list-types/iac-daily-list/src/email-summary/summary-builder.ts#L19-L22: source labels from the English/Welsh locale resources and propagate locale through the email-summary contract.libs/list-types/iac-daily-list/src/pdf/pdf-generator.ts#L25-L28: derive the PDF title from locale resources rather thanLIST_TITLE_MAP.libs/list-types/iac-daily-list/src/pdf/pdf-template.njk#L2-L2: pass the selected locale into the template and bind it tohtml[lang].
As per coding guidelines, “List-type-specific display strings must come from both English and Welsh locale files, not hardcoded controller strings.”
📍 Affects 3 files
libs/list-types/iac-daily-list/src/email-summary/summary-builder.ts#L19-L22(this comment)libs/list-types/iac-daily-list/src/pdf/pdf-generator.ts#L25-L28libs/list-types/iac-daily-list/src/pdf/pdf-template.njk#L2-L2
Source: Coding guidelines
| savePdfToStorage | ||
| } from "@hmcts/list-types-common"; | ||
| import { generatePdfFromHtml } from "@hmcts/pdf-generation"; | ||
| import { PROVENANCE_LABELS } from "@hmcts/publication"; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
Remove the publication ↔ IAC package dependency cycle.
@hmcts/publication imports this package in libs/publication/src/processing/service.ts, while this file imports PROVENANCE_LABELS from @hmcts/publication. Move the shared provenance labels to a lower-level package already depended on by both packages.
Source: Coding guidelines
| const PARTY_ROLE_MAPPINGS: Record<string, string[]> = { | ||
| APPLICANT_PETITIONER: ["APL", "APP", "CLP20", "CRED", "OTH", "PET"], | ||
| APPLICANT_PETITIONER_REPRESENTATIVE: ["CREP", "CREP20"], | ||
| RESPONDENT: ["DEBT", "DEF", "DEF20", "RES"], | ||
| RESPONDENT_REPRESENTATIVE: ["DREP", "DREP20", "RREP"] | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Map raw roles to identifiers handled by extractCaseParties. convertPartyRole("PET") returns APPLICANT_PETITIONER, but the switch only handles CLAIMANT_PETITIONER; raw-role parties are therefore omitted from rendered lists and notification summaries.
libs/list-types/iac-daily-list/src/rendering/renderer.ts#L32-L37: map raw codes to the role constants handled by the switch, or align the switch with the mapping outputs.libs/list-types/iac-daily-list/src/email-summary/summary-builder.test.ts#L62-L71: assert"Jane Roe"rather than an empty appellant so the test validates the intended mapping.
📍 Affects 2 files
libs/list-types/iac-daily-list/src/rendering/renderer.ts#L32-L37(this comment)libs/list-types/iac-daily-list/src/email-summary/summary-builder.test.ts#L62-L71
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
…list # Conflicts: # libs/publication/src/processing/service.ts
|
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |



Summary
Adds the First-tier Tribunal: Immigration and Asylum Chamber (IAC) Daily List and its Additional Cases variant, matching the authoritative pip-frontend staging output for HTML, PDF, and email summary.
Closes #791.
Changes
renderer.ts): splits parties into Appellant/Applicant, representative and Prosecuting authority (mirroring pip-frontend'sfindAndManipulatePartyInformation), presiding judge first in the judiciary string,h:mmasitting times, bracketed case-sequence indicators on the case reference, sitting-channel-over-session-channel fallback.h1readingFirst-tier Tribunal: Immigration and Asylum Chamber/{venue} Daily List, with the Additional Cases variant showing{venue} Daily List - Additional Cases. Added the "Find contact details and other information about courts and tribunals…" find-court link. Removed the visible search hint; the search input keeps agovuk-visually-hiddenlabel for screen readers.IAC_DAILY_LIST_ADDITIONAL_CASESvalidates against theIAC_DAILY_LISTschema via aPACKAGE_ALIASESentry — no duplicate schema.summary-builder.ts): case summary extraction/formatting wired into notifications.listTypeName;list-type-data.tsentries added for both list types.Testing
.njktemplates covered.tsc --noEmitclean across changed workspaces.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation