Skip to content

Commit

Permalink
Merge branch 'master' into DFPL-2439
Browse files Browse the repository at this point in the history
  • Loading branch information
qasimnawaz-moj authored Aug 29, 2024
2 parents 851a966 + 3155bd8 commit 0f63594
Show file tree
Hide file tree
Showing 11 changed files with 459 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,24 @@
"CRUD": "R"
}
]
},
{
"LiveFrom": "01/01/2017",
"CaseTypeID": "CARE_SUPERVISION_EPO",
"CaseEventID": "populateCase-RETURNED",
"AccessControl": [
{
"UserRoles": ["caseworker-publiclaw-systemupdate"],
"CRUD": "CR"
},
{
"UserRoles": [
"caseworker-publiclaw-gatekeeper",
"caseworker-publiclaw-courtadmin",
"caseworker-publiclaw-solicitor"
],
"CRUD": "R"
}
]
}
]
9 changes: 9 additions & 0 deletions ccd-definition/CaseEvent/CareSupervision/StateChange.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,14 @@
"PreConditionState(s)": "*",
"PostConditionState": "PREPARE_FOR_HEARING",
"SecurityClassification": "Public"
},
{
"LiveFrom": "01/01/2017",
"CaseTypeID": "CARE_SUPERVISION_EPO",
"ID": "populateCase-RETURNED",
"Name": "Populate - Returned",
"PreConditionState(s)": "*",
"PostConditionState": "RETURNED",
"SecurityClassification": "Public"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import uk.gov.hmcts.reform.ccd.client.model.CallbackRequest;
import uk.gov.hmcts.reform.ccd.client.model.CaseDetails;
import uk.gov.hmcts.reform.fpl.controllers.CallbackController;
import uk.gov.hmcts.reform.fpl.model.CaseData;
import uk.gov.hmcts.reform.fpl.service.CaseConverter;
import uk.gov.hmcts.reform.fpl.service.MigrateCaseService;

Expand All @@ -28,7 +29,8 @@ public class MigrateCaseController extends CallbackController {

private final Map<String, Consumer<CaseDetails>> migrations = Map.of(
"DFPL-log", this::runLog,
"DFPL-2492", this::run2492
"DFPL-2492", this::run2492,
"DFPL-2491", this::run2491
);
private final CaseConverter caseConverter;

Expand Down Expand Up @@ -66,4 +68,10 @@ private void run2492(CaseDetails caseDetails) {
caseDetails.getData().putAll(migrateCaseService.removeCharactersFromThresholdDetails(getCaseData(caseDetails),
migrationId, thresholdDetailsStartIndex, thresholdDetailsEndIndex));
}

private void run2491(CaseDetails caseDetails) {
final String migrationId = "DFPL-2491";
final CaseData caseData = getCaseData(caseDetails);
caseDetails.getData().putAll(migrateCaseService.setCaseManagementLocation(caseData, migrationId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.reform.fpl.events.judicial.HandleHearingModificationRolesEvent;
import uk.gov.hmcts.reform.fpl.model.HearingBooking;
import uk.gov.hmcts.reform.fpl.service.JudicialService;

import java.util.Optional;

import static uk.gov.hmcts.reform.fpl.utils.ElementUtils.findElement;
import static uk.gov.hmcts.reform.fpl.utils.ElementUtils.nullSafeList;

Expand All @@ -23,14 +26,30 @@ public void handleCancelledHearingRoles(final HandleHearingModificationRolesEven
// Not an async function as it has to take place before we grant more roles, in case the times overlap
// when relisting. it has to be caught though to make sure nothing else afterward is impacted in case of
// failure
final Long caseId = event.getCaseData().getId();
final boolean isFirstHearing = event.getCaseData().getAllNonCancelledHearings().size() == 1;

try {
nullSafeList(event.getCaseData().getCancelledHearingDetails())
.forEach(hearing -> {
if (findElement(hearing.getId(), event.getCaseDataBefore().getCancelledHearingDetails())
.isEmpty()) {
// new cancelled hearing - need to attempt deletion
judicialService.deleteSpecificHearingRole(event.getCaseData().getId(), hearing.getValue());
judicialService.deleteSpecificHearingRole(caseId, hearing.getValue());

// find the latest active hearing before this one and fix its roles
Optional<HearingBooking> lastHearing = event.getCaseData()
.getLastHearingBefore(hearing.getValue().getStartDate());

if (lastHearing.isPresent()) {
judicialService.deleteSpecificHearingRole(caseId, lastHearing.get());

Optional<HearingBooking> possibleNextHearing = event.getCaseData()
.getNextHearingAfter(lastHearing.get().getStartDate());

judicialService
.assignHearingJudge(caseId, lastHearing.get(), possibleNextHearing, isFirstHearing);
}
}
});
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,11 @@
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.reform.fpl.enums.JudgeOrMagistrateTitle;
import uk.gov.hmcts.reform.fpl.events.judicial.NewHearingJudgeEvent;
import uk.gov.hmcts.reform.fpl.model.HearingBooking;
import uk.gov.hmcts.reform.fpl.model.common.Element;
import uk.gov.hmcts.reform.fpl.model.common.JudgeAndLegalAdvisor;
import uk.gov.hmcts.reform.fpl.service.JudicialService;
import uk.gov.hmcts.reform.rd.model.JudicialUserProfile;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Comparator;
import java.util.Optional;

Expand All @@ -40,45 +35,16 @@ public void handleNewHearingJudge(final NewHearingJudgeEvent event) {
return;
}

JudgeAndLegalAdvisor hearingJudge = event.getHearing().getJudgeAndLegalAdvisor();

Optional<HearingBooking> nextHearing = event.getCaseData().getAllNonCancelledHearings()
.stream()
.map(Element::getValue)
.filter(hearing -> hearing.getStartDate().isAfter(event.getHearing().getStartDate()))
.min(Comparator.comparing(HearingBooking::getStartDate));

ZonedDateTime possibleEnd = nextHearing.map(hearing -> hearing.getStartDate().atZone(ZoneId.systemDefault()))
.orElse(null);


if (!isEmpty(hearingJudge.getJudgeJudicialUser())
&& !isEmpty(hearingJudge.getJudgeJudicialUser().getIdamId())) {
final boolean isFirstHearing = event.getCaseData().getAllNonCancelledHearings().size() == 1;

// have an IDAM ID - use that to grant the role
judicialService.assignHearingJudge(event.getCaseData().getId(),
hearingJudge.getJudgeJudicialUser().getIdamId(),
event.getHearing().getStartDate().atZone(ZoneId.systemDefault()),
// if there's a hearing after the one added, we're going out of order, so set an end date
possibleEnd,
JudgeOrMagistrateTitle.LEGAL_ADVISOR.equals(hearingJudge.getJudgeTitle()));
} else if (!isEmpty(hearingJudge.getJudgeJudicialUser())
&& !isEmpty(hearingJudge.getJudgeJudicialUser().getPersonalCode())) {

// no IDAM ID, but has personal code, lookup in JRD first
Optional<JudicialUserProfile> judge = judicialService
.getJudge(hearingJudge.getJudgeJudicialUser().getPersonalCode());

judge.ifPresentOrElse(judicialUserProfile ->
judicialService.assignHearingJudge(event.getCaseData().getId(), judicialUserProfile.getSidamId(),
event.getHearing().getStartDate().atZone(ZoneId.systemDefault()),
possibleEnd,
JudgeOrMagistrateTitle.LEGAL_ADVISOR.equals(hearingJudge.getJudgeTitle())),
() -> log.info("Could not lookup in JRD, no auto allocation of hearing judge on case {}",
event.getCaseData().getId()));
} else {
log.info("No auto allocation of hearing judge on case {}", event.getCaseData().getId());
}
judicialService
.assignHearingJudge(event.getCaseData().getId(), event.getHearing(), nextHearing, isFirstHearing);
}

private void handleEditedHearing(final NewHearingJudgeEvent event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,13 @@ public Optional<HearingBooking> getNextHearingAfter(LocalDateTime time) {
.min(comparing(HearingBooking::getStartDate));
}

@JsonIgnore
public Optional<HearingBooking> getLastHearingBefore(LocalDateTime time) {
return unwrapElements(hearingDetails).stream()
.filter(hearingBooking -> hearingBooking.getStartDate().isBefore(time))
.max(comparing(HearingBooking::getStartDate));
}

@JsonIgnore
public HearingBooking getMostUrgentHearingBookingAfter(LocalDateTime time) {
return getNextHearingAfter(time).orElseThrow(NoHearingBookingException::new);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import uk.gov.hmcts.reform.ccd.client.model.CaseDetails;
import uk.gov.hmcts.reform.fpl.config.rd.JudicialUsersConfiguration;
import uk.gov.hmcts.reform.fpl.config.rd.LegalAdviserUsersConfiguration;
import uk.gov.hmcts.reform.fpl.enums.JudgeOrMagistrateTitle;
import uk.gov.hmcts.reform.fpl.enums.YesNo;
import uk.gov.hmcts.reform.fpl.model.CaseData;
import uk.gov.hmcts.reform.fpl.model.HearingBooking;
Expand Down Expand Up @@ -143,8 +144,8 @@ public void assignAllocatedJudge(Long caseId, String userId, boolean isLegalAdvi
* @param userId the user to assign hearing-judge to
* @param starting the time to start the new role at, and the old roles to END at (- HEARING_EXPIRY_OFFSET_MINS)
*/
public void assignHearingJudge(Long caseId, String userId, ZonedDateTime starting, ZonedDateTime ending,
boolean isLegalAdviser) {
private void assignHearingJudgeRole(Long caseId, String userId, ZonedDateTime starting, ZonedDateTime ending,
boolean isLegalAdviser) {
setExistingHearingJudgesAndLegalAdvisersToExpire(caseId, starting.minusMinutes(HEARING_EXPIRY_OFFSET_MINS));

if (isLegalAdviser) {
Expand All @@ -155,6 +156,40 @@ public void assignHearingJudge(Long caseId, String userId, ZonedDateTime startin
}
}

public void assignHearingJudge(Long caseId, HearingBooking hearing, Optional<HearingBooking> nextHearing,
boolean startNow) {
Optional<String> judgeId = getJudgeIdFromHearing(hearing);
ZonedDateTime possibleEndDate = nextHearing.map(HearingBooking::getStartDate)
.map(ld -> ld.atZone(ZoneId.systemDefault()))
.orElse(null);

judgeId.ifPresentOrElse(s -> assignHearingJudgeRole(caseId,
s,
startNow ? ZonedDateTime.now() : hearing.getStartDate().atZone(ZoneId.systemDefault()),
possibleEndDate,
JudgeOrMagistrateTitle.LEGAL_ADVISOR.equals(hearing.getJudgeAndLegalAdvisor().getJudgeTitle())),
() -> log.error("No judge details on hearing starting at {} on case {} to assign roles to",
hearing.getStartDate(), caseId));
}

public Optional<String> getJudgeIdFromHearing(HearingBooking booking) {
if (isEmpty(booking)
|| isEmpty(booking.getJudgeAndLegalAdvisor())
|| isEmpty(booking.getJudgeAndLegalAdvisor().getJudgeJudicialUser())) {
return Optional.empty();
}

if (!isEmpty(booking.getJudgeAndLegalAdvisor().getJudgeJudicialUser().getIdamId())) {
return Optional.of(booking.getJudgeAndLegalAdvisor().getJudgeJudicialUser().getIdamId());
}

if (!isEmpty(booking.getJudgeAndLegalAdvisor().getJudgeJudicialUser().getPersonalCode())) {
return this.getJudge(booking.getJudgeAndLegalAdvisor().getJudgeJudicialUser().getPersonalCode())
.map(JudicialUserProfile::getSidamId);
}
return Optional.empty();
}

/**
* Calls to Judicial Reference Data to check if a judge exists.
*
Expand Down Expand Up @@ -420,7 +455,7 @@ public List<String> validateHearingJudgeEmail(CaseDetails caseDetails, CaseData
.build();
} else {
return List.of("No Judge could be found, please retry your search or enter their"
+ " details manually.");
+ " details manually.");
}
} else {
// entered the judge manually - lookup in our mappings and add UUID manually
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import uk.gov.hmcts.reform.fpl.enums.JudgeOrMagistrateTitle;
import uk.gov.hmcts.reform.fpl.events.judicial.HandleHearingModificationRolesEvent;
import uk.gov.hmcts.reform.fpl.model.CaseData;
import uk.gov.hmcts.reform.fpl.model.HearingBooking;
Expand All @@ -15,11 +16,14 @@

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static uk.gov.hmcts.reform.fpl.utils.ElementUtils.element;
import static uk.gov.hmcts.reform.fpl.utils.ElementUtils.wrapElements;

@ExtendWith(MockitoExtension.class)
class HandleHearingModificationRolesEventHandlerTest {
Expand Down Expand Up @@ -55,6 +59,109 @@ void shouldHandleCancelledHearingRoles() {
verifyNoMoreInteractions(judicialService);
}

@Test
void shouldReconfigurePreviousHearingRoleWhenNoFurtherHearings() {
LocalDateTime now = LocalDateTime.now();
UUID cancelledBookingId = UUID.randomUUID();

HearingBooking prevBooking = HearingBooking.builder()
.startDate(now)
.judgeAndLegalAdvisor(JudgeAndLegalAdvisor.builder()
.judgeTitle(JudgeOrMagistrateTitle.HIS_HONOUR_JUDGE)
.judgeLastName("Test")
.judgeJudicialUser(JudicialUser.builder()
.idamId("1234")
.build())
.build())
.build();

HearingBooking cancelledBooking = HearingBooking.builder()
.startDate(now.plusDays(2))
.judgeAndLegalAdvisor(JudgeAndLegalAdvisor.builder()
.judgeTitle(JudgeOrMagistrateTitle.HIS_HONOUR_JUDGE)
.judgeLastName("Test")
.judgeJudicialUser(JudicialUser.builder()
.idamId("1234")
.build())
.build())
.build();


CaseData caseDataBefore = CaseData.builder()
.id(12345L)
.hearingDetails(List.of(element(prevBooking), element(cancelledBookingId, cancelledBooking)))
.build();

CaseData caseDataAfter = caseDataBefore.toBuilder()
.hearingDetails(List.of(element(prevBooking)))
.cancelledHearingDetails(List.of(element(cancelledBookingId, cancelledBooking)))
.build();

underTest.handleCancelledHearingRoles(new HandleHearingModificationRolesEvent(caseDataAfter, caseDataBefore));

verify(judicialService).deleteSpecificHearingRole(12345L, cancelledBooking);
verify(judicialService).deleteSpecificHearingRole(12345L, prevBooking);
verify(judicialService).assignHearingJudge(12345L, prevBooking, Optional.empty(), true);
}

@Test
void shouldReconfigurePreviousHearingRoleWhenFurtherHearings() {
LocalDateTime now = LocalDateTime.now();
UUID cancelledBookingId = UUID.randomUUID();

HearingBooking prevBooking = HearingBooking.builder()
.startDate(now)
.judgeAndLegalAdvisor(JudgeAndLegalAdvisor.builder()
.judgeTitle(JudgeOrMagistrateTitle.HIS_HONOUR_JUDGE)
.judgeLastName("Test")
.judgeJudicialUser(JudicialUser.builder()
.idamId("1234")
.build())
.build())
.build();

HearingBooking cancelledBooking = HearingBooking.builder()
.startDate(now.plusDays(2))
.judgeAndLegalAdvisor(JudgeAndLegalAdvisor.builder()
.judgeTitle(JudgeOrMagistrateTitle.HIS_HONOUR_JUDGE)
.judgeLastName("Test")
.judgeJudicialUser(JudicialUser.builder()
.idamId("1234")
.build())
.build())
.build();

HearingBooking futureHearing = HearingBooking.builder()
.startDate(now.plusDays(4))
.judgeAndLegalAdvisor(JudgeAndLegalAdvisor.builder()
.judgeTitle(JudgeOrMagistrateTitle.HIS_HONOUR_JUDGE)
.judgeLastName("Test")
.judgeJudicialUser(JudicialUser.builder()
.idamId("1234")
.build())
.build())
.build();

CaseData caseDataBefore = CaseData.builder()
.id(12345L)
.hearingDetails(List.of(
element(prevBooking),
element(cancelledBookingId, cancelledBooking),
element(futureHearing)))
.build();

CaseData caseDataAfter = caseDataBefore.toBuilder()
.hearingDetails(wrapElements(prevBooking, futureHearing))
.cancelledHearingDetails(List.of(element(cancelledBookingId, cancelledBooking)))
.build();

underTest.handleCancelledHearingRoles(new HandleHearingModificationRolesEvent(caseDataAfter, caseDataBefore));

verify(judicialService).deleteSpecificHearingRole(12345L, cancelledBooking);
verify(judicialService).deleteSpecificHearingRole(12345L, prevBooking);
verify(judicialService).assignHearingJudge(12345L, prevBooking, Optional.of(futureHearing), false);
}

@Test
void shouldNotThrowExceptionIfNullList() {
assertDoesNotThrow(() -> underTest.handleCancelledHearingRoles(new HandleHearingModificationRolesEvent(
Expand Down
Loading

0 comments on commit 0f63594

Please sign in to comment.