Skip to content

SPRDT-987: listing.command.move-hearing-to-past-date wrapper (MAGS via courtscheduler, CROWN listing-side)#22

Merged
ozturkmenb merged 12 commits into
team/pasthearingsfrom
dev/SPRDT-987-pasthearings
Jul 3, 2026
Merged

SPRDT-987: listing.command.move-hearing-to-past-date wrapper (MAGS via courtscheduler, CROWN listing-side)#22
ozturkmenb merged 12 commits into
team/pasthearingsfrom
dev/SPRDT-987-pasthearings

Conversation

@ozturkmenb

@ozturkmenb ozturkmenb commented Jul 2, 2026

Copy link
Copy Markdown

Jira link

See https://tools.hmcts.net/jira/browse/SPRDT-987

Change description

Re-lands the move-hearing-to-past-date wrapper cleanly for shipment ahead of Crown Phase 2. Ported from archived-repo PR #909 — only its three real commits (fbe4e705a, 168d669a0, bf047bd35); the rest of that branch was team/ccsph2n contamination.

  • New content-type action listing.command.move-hearing-to-past-date on the existing POST /hearings/{hearingId} resource. Request body: courtCentreId, startDate (single-day) — hearingId travels in the URL path only; the REST adapter injects it into the payload (same convention as update-hearing-for-listing).
  • Own permission "Change hearing to past date"/"Link" (createChangeHearingToPastDatePermission()) — the first hasPermission-based DRL rule in listing command-api.
  • Hearing-existence pre-check → 422 HEARING_ID_NOT_FOUND, no event sent (was in the original ACs but never implemented in PR #909).
  • MAGISTRATES: synchronous courtscheduler call (courtscheduler.move-hearing-to-past-date); on 2xx the enriched command re-issues the hearing day on the past date (changeStartDate + assignHearingDaysV2) carrying courtScheduleId/room/times — the court-schedule event alone cannot re-date a day (its projection matches days by date). On courtscheduler 422 the error is surfaced with its errorCode and no event is sent; a legacy courtscheduler 404 is normalised to 422 NO_SESSION_FOUND, so no-session is always a 422 to callers.
  • CROWN: listing-side-only date move — courtscheduler is never called (no CROWN courtschedule before Phase 2); past-only enforced in listing (422 FUTURE_DATE_NOT_ALLOWED). The hearing day re-dates too (follow-up f7c325ec/675ed2de): command-api rebuilds the day from the hearing's own current first day (same room, time-of-day and duration re-anchored onto the past date) and the handler applies changeStartDate + assignHearingDaysV2, mirroring the MAGS composition minus the courtschedule. endTime is always computed (startTime + duration) — the hearing-days-changed-for-hearing item schema requires it.
  • New plumbing this branch lacked: ListingCommandCommonProviders (@Specializes DefaultCommonProviders) + MoveHearingToPastDateExceptionMapper (422 rendering), purpose-built MoveHearingToPastDateResult DTO (replaces the ccsph2n-only CrownFallbackResult).

Error contract for callers (all 422, body {errorCode, message}): HEARING_ID_NOT_FOUND, FUTURE_DATE_NOT_ALLOWED, NO_SESSION_FOUND (no session on the requested date + court centre — includes normalised legacy courtscheduler 404s). Malformed request → 400 (RAML schema).

Stacked on #21 (dev/pasthearingssnapshot); retarget to team/pasthearings once #21 merges. Courtscheduler counterpart: hmcts/cpp-context-listing-courtscheduler#849.

Testing done

  • mvn clean install green (new: api 37, handler 83, adapter/mapper/permission/lookup suites; adapter suite now covers the 404→422 NO_SESSION_FOUND normalisation and asserts hearingId is absent from the courtscheduler request body).
  • ./runIntegrationTests.sh green: 231/231 (3 pre-existing skips) including new MoveHearingToPastDateIT 9/9 — MAGS happy path stores the moved day's courtScheduleId, re-move releases prior allocation, courtscheduler 422 propagated with no event, legacy courtscheduler 404 normalised to 422 NO_SESSION_FOUND, unknown hearingId 422, missing field 400, CROWN moved listing-side with the courtscheduler stub verifiably never called, CROWN future-date 422. IT bodies post without hearingId — proving the path-param injection end-to-end.
  • SonarQube quality gate: OK.

CVE Suppression: Are there any CVEs present in the codebase (either newly introduced or pre-existing) that are being intentionally suppressed or ignored by this commit?

  • Yes
  • No

@ozturkmenb ozturkmenb requested a review from a team as a code owner July 2, 2026 19:56
@cpp-github-management

Copy link
Copy Markdown

Passed

1 similar comment
@cpp-github-management

Copy link
Copy Markdown

Passed

@ozturkmenb

Copy link
Copy Markdown
Author
image

@cpp-github-management

Copy link
Copy Markdown

Passed

1 similar comment
@cpp-github-management

Copy link
Copy Markdown

Passed

…eduler, CROWN listing-side, past-only)

Adds listing.command.move-hearing-to-past-date as a new content-type action on the
existing POST /hearings/{hearingId} resource. ListingCommandApi resolves the hearing
from the listing viewstore (new HearingLookupService, mirroring the existing
command.service.HearingService query-view lookup pattern) and rejects unknown
hearingIds with 422 HEARING_ID_NOT_FOUND before anything is sent.

MAGISTRATES hearings call courtscheduler synchronously via
CourtSchedulerServiceAdapter.moveHearingToPastDate (new HearingSlotsService POST to
/hearings/{hearingId}, application/vnd.courtscheduler.move-hearing-to-past-date+json);
a 2xx response enriches the command with a purpose-built MoveHearingToPastDateResult
and the enriched handler applies it via the existing
raiseHearingDayCourtSchedulesUpdated/HearingDayCourtScheduleUpdated event. A non-2xx
response raises MoveHearingToPastDateException, rendered as 422/404 by the new
MoveHearingToPastDateExceptionMapper (registered via the new
ListingCommandCommonProviders @specializes DefaultCommonProviders) - no event is sent.

CROWN hearings never call courtscheduler (Baris decision D1): the command-api
validates past-only (422 FUTURE_DATE_NOT_ALLOWED) and the enriched handler re-dates
the hearing purely listing-side by reusing the existing Hearing.changeStartDate
aggregate method (StartDateChangedForHearing event) - no new domain event needed.

Permission: PermissionConstants.createChangeHearingToPastDatePermission() (object
"Change hearing to past date", action "Link") plus a DRL rule using
userAndGroupProvider.hasPermission(...).

Adds MoveHearingToPastDateIT plus CourtSchedulerServiceStub/WireMockStubUtils
extensions and MAGS/CROWN test-data fixtures.
…(changeStartDate + assignHearingDaysV2) - the court-schedule event alone cannot re-date a day
…s (S3776), reuse adapter constants (S1192), transient responseBody (S1948)
…t from the hearing's own room/time on the past date
… requires it); carry existing endTime for CROWN
…04 normalised); hearingId dropped from command body (path param only)
@ozturkmenb ozturkmenb changed the base branch from dev/pasthearingssnapshot to team/pasthearings July 3, 2026 09:42
@ozturkmenb ozturkmenb force-pushed the dev/SPRDT-987-pasthearings branch from 9adddf8 to 1eb24a0 Compare July 3, 2026 09:42
@cpp-github-management

Copy link
Copy Markdown

Passed

@ozturkmenb

Copy link
Copy Markdown
Author

Rebased onto the rebuilt team/pasthearings (recreated from tag v17.103.176 — Framework D line, parent pom 17.103.8 — instead of main which carried unreleased Framework E work). Same 9 commits, zero conflicts; version now 17.103.177-PAST-SNAPSHOT (bump PR #23). Gates re-run on the new base: build + 1472 unit tests green, ITs 231/0/0 (3 skipped), MoveHearingToPastDateIT 9/9.

@cpp-github-management

Copy link
Copy Markdown

Passed

…s as update-hearing-for-listing - drops the unseeded 'Change hearing to past date'/Link permission (PermissionConstants removed, move IT uses the standard group stub)
@ozturkmenb

Copy link
Copy Markdown
Author

Permission model change: the move-hearing-to-past-date DRL rule now uses the same group set as update-hearing-for-listing (LISTING_OFFICERS, CROWN_COURT_ADMIN, COURT_ADMINISTRATORS, COURT_CLERKS, LEGAL_ADVISERS, COURT_ASSOCIATE) instead of hasPermission on 'Change hearing to past date'/'Link' — that permission existed nowhere in ref data, so this also removes the seeding dependency. PermissionConstants and the IT permission stub are deleted. Gates: build + 1471 unit tests green, ITs 231/0/0 (3 skipped), MoveHearingToPastDateIT 9/9.

@cpp-github-management

Copy link
Copy Markdown

Passed

@ozturkmenb ozturkmenb merged commit 007bc4f into team/pasthearings Jul 3, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant