Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/main/java/uk/gov/hmcts/reform/pcs/ccd/PCSCaseView.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import uk.gov.hmcts.reform.pcs.ccd.view.DocumentsView;
import uk.gov.hmcts.reform.pcs.ccd.view.FeatureFlagView;
import uk.gov.hmcts.reform.pcs.ccd.view.GenAppsView;
import uk.gov.hmcts.reform.pcs.ccd.view.HearingView;
import uk.gov.hmcts.reform.pcs.ccd.view.NoticeOfPossessionView;
import uk.gov.hmcts.reform.pcs.ccd.view.PartiesView;
import uk.gov.hmcts.reform.pcs.ccd.view.RentArrearsView;
Expand Down Expand Up @@ -91,7 +90,6 @@ public class PCSCaseView implements CaseView<PCSCase, State> {
private final CaseFlagsView flagsView;
private final DefendantResponseView defendantResponseView;
private final FeatureFlagView featureFlagView;
private final HearingView hearingView;

/**
* Invoked by CCD to load PCS cases by reference.
Expand Down Expand Up @@ -173,7 +171,6 @@ private SubmittedCase getSubmittedCase(long caseReference) {
caseListView.setCaseFields(pcsCase);
defendantResponseView.setCaseFields(pcsCase, pcsCaseEntity);
featureFlagView.setCaseFields(pcsCase);
hearingView.setCaseFields(pcsCase, pcsCaseEntity);

return new SubmittedCase(pcsCase, pcsCaseEntity);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -748,9 +748,6 @@ public class PCSCase {
@CCD(searchable = false)
private Hearing hearing;

@CCD(searchable = false)
private List<ListValue<Hearing>> hearingList;

@CCD(searchable = false)
private VerticalYesNo showManageHearingPage;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public class Hearing {
public static final String NOTES_LABEL = "Hearing notes";
@CCD(ignore = true)
public static final String ADDITIONAL_INFORMATION_LABEL = "Enter any additional information";
@CCD(ignore = true)
public static final String CANCELLATION_REASON_LABEL = "Enter reason for cancellation";

private Long hearingId;

@CCD(label = "Which type of hearing is this?")
private HearingType type;
Expand Down Expand Up @@ -78,4 +82,13 @@ public class Hearing {
typeOverride = TextArea
)
private String additionalInformation;

@CCD(
label = CANCELLATION_REASON_LABEL,
hint = "This will be included in the notice sent to parties, if one is required",
typeOverride = TextArea
)
private String cancellationReason;

private String hearingSummaryMarkdown;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class HearingEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Long id;

@ManyToOne(fetch = LAZY)
@JoinColumn(name = "case_id")
Expand Down Expand Up @@ -75,6 +75,10 @@ public class HearingEntity {
@Builder.Default
private List<UUID> noticeParties = new ArrayList<>();

private Boolean cancelled;

private String cancellationReason;

public void addParty(UUID partyId) {
noticeParties.add(partyId);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package uk.gov.hmcts.reform.pcs.ccd.event.hearing;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase;
import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter;

@Component
@RequiredArgsConstructor
public class ConfirmationBodyRenderer {

private final AddressFormatter addressFormatter;

public String renderHearingAddedConfirmationBody(PCSCase caseData, long caseReference) {
String address = getFormattedAddress(caseData);
String caseName = caseData.getCaseNameHmctsInternal();

return """
---
<div class="govuk-panel govuk-panel--confirmation govuk-!-padding-top-3 govuk-!-padding-bottom-3">
<span class="govuk-panel__title govuk-!-font-size-36">Hearing added</span><br>
<span class="govuk-panel__body">Case number #%s</span><br>
<span class="govuk-panel__body">%s</span><br>
<span class="govuk-panel__body">%s</span><br>
</div>

<h3>What happens next</h3>

A hearing notice will be issued if you specified one is needed.
""".formatted(caseReference, address, caseName);
}

public String renderHearingCancelledConfirmationBody(PCSCase caseData, long caseReference) {
String address = getFormattedAddress(caseData);
String caseName = caseData.getCaseNameHmctsInternal();

return """
---
<div class="govuk-panel govuk-panel--confirmation govuk-!-padding-top-3 govuk-!-padding-bottom-3">
<span class="govuk-panel__title govuk-!-font-size-36">Hearing cancelled</span><br>
<span class="govuk-panel__body">Case number #%s</span><br>
<span class="govuk-panel__body">%s</span><br>
<span class="govuk-panel__body">%s</span><br>
</div>

<h3>What happens next</h3>

A cancellation notice will be sent to the parties.
""".formatted(caseReference, address, caseName);
}

private String getFormattedAddress(PCSCase caseData) {
return addressFormatter
.formatMediumAddress(caseData.getPropertyAddress(), AddressFormatter.COMMA_DELIMITER);
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package uk.gov.hmcts.reform.pcs.ccd.event;
package uk.gov.hmcts.reform.pcs.ccd.event.hearing;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import uk.gov.hmcts.ccd.sdk.api.CCDConfig;
Expand All @@ -10,6 +11,7 @@
import uk.gov.hmcts.ccd.sdk.api.EventPayload;
import uk.gov.hmcts.ccd.sdk.api.Permission;
import uk.gov.hmcts.ccd.sdk.api.callback.SubmitResponse;
import uk.gov.hmcts.ccd.sdk.type.CaseLocation;
import uk.gov.hmcts.ccd.sdk.type.DynamicListElement;
import uk.gov.hmcts.ccd.sdk.type.DynamicMultiSelectList;
import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole;
Expand All @@ -19,45 +21,70 @@
import uk.gov.hmcts.reform.pcs.ccd.domain.VerticalYesNo;
import uk.gov.hmcts.reform.pcs.ccd.domain.hearing.ManageHearingOption;
import uk.gov.hmcts.reform.pcs.ccd.entity.ClaimEntity;
import uk.gov.hmcts.reform.pcs.ccd.entity.HearingEntity;
import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity;
import uk.gov.hmcts.reform.pcs.ccd.entity.party.ClaimPartyEntity;
import uk.gov.hmcts.reform.pcs.ccd.entity.party.PartyEntity;
import uk.gov.hmcts.reform.pcs.ccd.entity.party.PartyRole;
import uk.gov.hmcts.reform.pcs.ccd.page.managehearing.ManageHearingConfigurer;
import uk.gov.hmcts.reform.pcs.ccd.service.HearingService;
import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService;
import uk.gov.hmcts.reform.pcs.ccd.service.hearing.HearingService;
import uk.gov.hmcts.reform.pcs.ccd.service.hearing.HearingSummaryRenderer;
import uk.gov.hmcts.reform.pcs.ccd.service.party.PartyService;
import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter;
import uk.gov.hmcts.reform.pcs.location.model.CourtVenue;
import uk.gov.hmcts.reform.pcs.location.service.LocationReferenceService;

import java.time.Clock;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.CaseworkerRoles.CASEWORKER_ROLES;
import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.JudicialHistoryRoles.JUDICIAL_HISTORY_ROLES;
import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.manageHearing;

@Component
@AllArgsConstructor
@Slf4j
public class ManageHearing implements CCDConfig<PCSCase, State, UserRole> {

private final ManageHearingConfigurer manageHearingConfigurer;
private final AddressFormatter addressFormatter;
private final HearingService hearingService;
private final LocationReferenceService locationReferenceService;
private final PcsCaseService pcsCaseService;
private final PartyService partyService;
private final HearingSummaryRenderer hearingSummaryRenderer;
private final ConfirmationBodyRenderer confirmationBodyRenderer;
private final Clock ukClock;

public ManageHearing(ManageHearingConfigurer manageHearingConfigurer,
HearingService hearingService,
LocationReferenceService locationReferenceService,
PcsCaseService pcsCaseService,
PartyService partyService,
HearingSummaryRenderer hearingSummaryRenderer,
ConfirmationBodyRenderer confirmationBodyRenderer,
@Qualifier("ukClock") Clock ukClock) {

this.manageHearingConfigurer = manageHearingConfigurer;
this.hearingService = hearingService;
this.locationReferenceService = locationReferenceService;
this.pcsCaseService = pcsCaseService;
this.partyService = partyService;
this.hearingSummaryRenderer = hearingSummaryRenderer;
this.confirmationBodyRenderer = confirmationBodyRenderer;
this.ukClock = ukClock;
}

@Override
public void configureDecentralised(DecentralisedConfigBuilder<PCSCase, State, UserRole> configBuilder) {
Event.EventBuilder<PCSCase, UserRole, State> eventBuilder =
configBuilder.decentralisedEvent(manageHearing.name(), this::submit, this::start)
.forStates(State.CASE_ISSUED)
.name("Manage hearing")
.grant(Permission.CRUD, UserRole.HEARING_CENTRE_ADMIN)
.grant(Permission.CRUD, CASEWORKER_ROLES)
.grantHistoryOnly(JUDICIAL_HISTORY_ROLES)
.showSummary()
.endButtonLabel("Submit");
Expand All @@ -73,7 +100,36 @@ private PCSCase start(EventPayload<PCSCase, State> eventPayload) {

pcsCase.setPartyMultiSelectionList(buildPartyList(pcsCaseEntity));

List<Integer> baseLocation = List.of(Integer.parseInt(pcsCase.getCaseManagementLocation().getBaseLocation()));
setHearingLocation(eventPayload, pcsCase);

List<HearingEntity> futureHearings = getFutureHearings(pcsCaseEntity);

if (futureHearings.isEmpty()) {
pcsCase.setShowManageHearingPage(VerticalYesNo.NO);
pcsCase.setManageHearingOption(ManageHearingOption.ADD);
} else {
HearingEntity nextHearingEntity = futureHearings.getFirst();
String hearingLocation = pcsCase.getHearingLocation();
pcsCase.getHearing().setHearingId(nextHearingEntity.getId());
pcsCase.getHearing().setHearingSummaryMarkdown(
hearingSummaryRenderer.renderMarkdown(nextHearingEntity, hearingLocation));

pcsCase.setShowManageHearingPage(VerticalYesNo.YES);
}

return pcsCase;
}

private void setHearingLocation(EventPayload<PCSCase, State> eventPayload, PCSCase pcsCase) {
CaseLocation caseManagementLocation = pcsCase.getCaseManagementLocation();

if (caseManagementLocation == null) {
log.warn("Unable to find hearing location for case {}:", eventPayload.caseReference());
pcsCase.setHearingLocation("Unable to find hearing location");
return;
}

List<Integer> baseLocation = List.of(Integer.parseInt(caseManagementLocation.getBaseLocation()));

try {
List<CourtVenue> courtVenues = locationReferenceService.getCourtVenues(baseLocation);
Expand All @@ -89,51 +145,41 @@ private PCSCase start(EventPayload<PCSCase, State> eventPayload) {
log.warn("Unable to fetch hearing location for case {}:", eventPayload.caseReference(), e);
pcsCase.setHearingLocation("Unable to find hearing location");
}

if (CollectionUtils.isEmpty(pcsCase.getHearingList())) {
pcsCase.setShowManageHearingPage(VerticalYesNo.NO);
pcsCase.setManageHearingOption(ManageHearingOption.ADD);
} else {
pcsCase.setShowManageHearingPage(VerticalYesNo.YES);
}

return pcsCase;
}

private SubmitResponse<State> submit(EventPayload<PCSCase, State> eventPayload) {
Long caseId = eventPayload.caseReference();
long caseReference = eventPayload.caseReference();
PCSCase caseData = eventPayload.caseData();
String address = addressFormatter
.formatMediumAddress(caseData.getPropertyAddress(), AddressFormatter.COMMA_DELIMITER);

if (
caseData.getManageHearingOption() == ManageHearingOption.ADD
|| caseData.getShowManageHearingPage() != VerticalYesNo.YES
) {
hearingService.addHearing(caseId, caseData);

// Default action is ADD if the choice screen wasn't shown
if (caseData.getShowManageHearingPage() != VerticalYesNo.YES) {
caseData.setManageHearingOption(ManageHearingOption.ADD);
}

String confirmationBody = "";
switch (caseData.getManageHearingOption()) {
case ADD: {
hearingService.addHearing(caseReference, caseData);
confirmationBody = confirmationBodyRenderer
.renderHearingAddedConfirmationBody(caseData, caseReference);
break;
}
case EDIT: {
break;
}
case CANCEL: {
hearingService.cancelHearing(caseData.getHearing());
confirmationBody = confirmationBodyRenderer
.renderHearingCancelledConfirmationBody(caseData, caseReference);
break;
}
}

return SubmitResponse.<State>builder()
.confirmationBody(getConfirmationBody(caseId, address, caseData.getCaseNameHmctsInternal()))
.confirmationBody(confirmationBody)
.build();
}

private String getConfirmationBody(Long caseId, String address, String caseName) {
return """
---
<div class="govuk-panel govuk-panel--confirmation govuk-!-padding-top-3 govuk-!-padding-bottom-3">
<span class="govuk-panel__title govuk-!-font-size-36">Hearing Added</span><br>
<span class="govuk-panel__body">Case number #%s</span><br>
<span class="govuk-panel__body">%s</span><br>
<span class="govuk-panel__body">%s</span><br>
</div>

<h3>What happens next</h3>

A hearing notice will be issued if you specified one is needed.
""".formatted(caseId, address, caseName);
}

private DynamicMultiSelectList buildPartyList(PcsCaseEntity pcsCaseEntity) {
ClaimEntity mainClaim = pcsCaseEntity.getMainClaim();
Map<PartyRole, List<ClaimPartyEntity>> partyRoleListMap = mainClaim.getClaimParties().stream()
Expand Down Expand Up @@ -162,4 +208,13 @@ private DynamicListElement mapToPartyListElement(ClaimEntity mainClaim, PartyEnt
.build();
}

private List<HearingEntity> getFutureHearings(PcsCaseEntity pcsCaseEntity) {
LocalDateTime now = LocalDateTime.now(ukClock);
return pcsCaseEntity.getHearings().stream()
.filter(hearingEntity -> hearingEntity.getHearingDate().isAfter(now))
.filter(hearingEntity -> BooleanUtils.isNotTrue(hearingEntity.getCancelled()))
.sorted(Comparator.comparing(HearingEntity::getHearingDate))
.toList();
}

}
Loading