SPRDT-987: listing.command.move-hearing-to-past-date wrapper (MAGS via courtscheduler, CROWN listing-side)#22
Conversation
1 similar comment
1 similar comment
…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.
…ission DRL path in move IT
…m in MoveHearingToPastDateIT
…(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)
9adddf8 to
1eb24a0
Compare
|
Rebased onto the rebuilt |
…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)
|
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. |

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 wasteam/ccsph2ncontamination.listing.command.move-hearing-to-past-dateon the existingPOST /hearings/{hearingId}resource. Request body:courtCentreId,startDate(single-day) —hearingIdtravels in the URL path only; the REST adapter injects it into the payload (same convention asupdate-hearing-for-listing).createChangeHearingToPastDatePermission()) — the firsthasPermission-based DRL rule in listing command-api.HEARING_ID_NOT_FOUND, no event sent (was in the original ACs but never implemented in PR #909).courtscheduler.move-hearing-to-past-date); on 2xx the enriched command re-issues the hearing day on the past date (changeStartDate+assignHearingDaysV2) carryingcourtScheduleId/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 itserrorCodeand no event is sent; a legacy courtscheduler 404 is normalised to 422NO_SESSION_FOUND, so no-session is always a 422 to callers.FUTURE_DATE_NOT_ALLOWED). The hearing day re-dates too (follow-upf7c325ec/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 applieschangeStartDate+assignHearingDaysV2, mirroring the MAGS composition minus the courtschedule.endTimeis always computed (startTime + duration) — thehearing-days-changed-for-hearingitem schema requires it.ListingCommandCommonProviders(@Specializes DefaultCommonProviders) +MoveHearingToPastDateExceptionMapper(422 rendering), purpose-builtMoveHearingToPastDateResultDTO (replaces the ccsph2n-onlyCrownFallbackResult).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 toteam/pasthearingsonce #21 merges. Courtscheduler counterpart: hmcts/cpp-context-listing-courtscheduler#849.Testing done
mvn clean installgreen (new: api 37, handler 83, adapter/mapper/permission/lookup suites; adapter suite now covers the 404→422NO_SESSION_FOUNDnormalisation and assertshearingIdis absent from the courtscheduler request body)../runIntegrationTests.shgreen: 231/231 (3 pre-existing skips) including newMoveHearingToPastDateIT9/9 — MAGS happy path stores the moved day'scourtScheduleId, re-move releases prior allocation, courtscheduler 422 propagated with no event, legacy courtscheduler 404 normalised to 422NO_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 withouthearingId— proving the path-param injection end-to-end.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?