Skip to content
Draft
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
8 changes: 7 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,13 @@ sonarqube {
"**/uk/gov/hmcts/reform/pcs/ccd/domain/**/*.java," +
"**/uk/gov/hmcts/reform/pcs/ccd/page/**/*.java," +
"**/uk/gov/hmcts/reform/pcs/ccd/entity/**/*.java," +
"**/entities/**," + "**/model/**," + "**/uk/gov/hmcts/reform/pcs/testingsupport/**/*.java"
"**/entities/**," +
"**/model/**," +
"**/uk/gov/hmcts/reform/pcs/testingsupport/**/*.java," +
"**/uk/gov/hmcts/reform/pcs/ccd/event/DashboardView.java," +
"**/uk/gov/hmcts/reform/pcs/ccd/service/dashboard/DashboardJourneyService.java," +
"**/uk/gov/hmcts/reform/pcs/ccd/event/dashboard/StartDashboardViewHandler.java," +
"**/uk/gov/hmcts/reform/pcs/ccd/event/dashboard/SubmitDashboardViewHandler.java"
property "sonar.cpd.exclusions", "**/uk/gov/hmcts/reform/pcs/ccd/domain/enforcetheorder/warrant/StatementOfTruthDetails.java"
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package uk.gov.hmcts.reform.pcs.ccd.event;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.ccd.sdk.api.CCDConfig;
import uk.gov.hmcts.ccd.sdk.api.DecentralisedConfigBuilder;
import uk.gov.hmcts.ccd.sdk.api.Permission;
import uk.gov.hmcts.reform.pcs.ccd.ShowConditions;
import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole;
import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase;
import uk.gov.hmcts.reform.pcs.ccd.domain.State;
import uk.gov.hmcts.reform.pcs.ccd.event.dashboard.StartDashboardViewHandler;
import uk.gov.hmcts.reform.pcs.ccd.event.dashboard.SubmitDashboardViewHandler;

import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.dashboardView;

@Component
@Slf4j
@RequiredArgsConstructor
public class DashboardView implements CCDConfig<PCSCase, State, UserRole> {

private final StartDashboardViewHandler startDashboardViewHandler;
private final SubmitDashboardViewHandler submitDashboardViewHandler;

@Override
public void configureDecentralised(final DecentralisedConfigBuilder<PCSCase, State, UserRole> configBuilder) {
configBuilder
.decentralisedEvent(dashboardView.name(), submitDashboardViewHandler, startDashboardViewHandler)
// TODO: HDPI-5421 - Revist this once we have clarification on the states we need
.forAllStates()
.showCondition(ShowConditions.NEVER_SHOW)
.name("Dashboard view")
.description("Compute dashboard notifications for case journey")
.grant(Permission.CRU, UserRole.DEFENDANT);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ public enum EventId {
enforceTheOrder,
respondPossessionClaim,
submitDefendantResponse,
createTestCase
createTestCase,
dashboardView
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package uk.gov.hmcts.reform.pcs.ccd.event.dashboard;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.ccd.sdk.api.EventPayload;
import uk.gov.hmcts.ccd.sdk.api.callback.Start;
import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase;
import uk.gov.hmcts.reform.pcs.ccd.domain.State;
import uk.gov.hmcts.reform.pcs.ccd.event.EventId;
import uk.gov.hmcts.reform.pcs.ccd.service.DraftCaseDataService;
import uk.gov.hmcts.reform.pcs.ccd.service.dashboard.DashboardJourneyService;
import uk.gov.hmcts.reform.pcs.dashboard.model.DashboardNotification;

import java.util.List;
import java.util.Optional;

import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.respondPossessionClaim;

@Component
@Slf4j
@RequiredArgsConstructor
public class StartDashboardViewHandler implements Start<PCSCase, State> {

private final DraftCaseDataService draftCaseDataService;
private final DashboardJourneyService dashboardJourneyService;
private final ObjectMapper objectMapper;

@Override
public PCSCase start(EventPayload<PCSCase, State> eventPayload) {
long caseReference = eventPayload.caseReference();
State state = State.CASE_ISSUED;

log.info("DashboardView START invoked for caseReference={}, assumedState={}", caseReference, state);

PCSCase submittedCaseData = eventPayload.caseData();

Optional<PCSCase> draftForRespondPossession = getDraft(caseReference, respondPossessionClaim);

boolean hasDraft = draftForRespondPossession.isPresent();
log.info("DashboardView START loaded data for caseReference={}, hasRespondPossessionDraft={}",
caseReference, hasDraft);

List<DashboardNotification> notifications = dashboardJourneyService.computeNotifications(
caseReference,
state,
submittedCaseData,
draftForRespondPossession
);

log.info("DashboardView START computed {} dashboard notification(s) for caseReference={}",
notifications.size(), caseReference);

String payloadJson = toPayloadJson(caseReference, notifications);

log.info("DashboardView START serialised dashboard payload for caseReference={} (length={} chars)",
caseReference, payloadJson.length());

submittedCaseData.setCaseTitleMarkdown(payloadJson);
return submittedCaseData;
}

private Optional<PCSCase> getDraft(long caseReference, EventId eventId) {
try {
log.info("DashboardView START attempting to load draft for caseReference={}, eventId={}",
caseReference, eventId);
return draftCaseDataService.getUnsubmittedCaseData(caseReference, eventId);
} catch (Exception e) {
log.warn("Failed to load draft case data for caseReference={} eventId={}", caseReference, eventId, e);
return Optional.empty();
}
}

private String toPayloadJson(long caseReference, List<DashboardNotification> notifications) {
DashboardPayload payload = new DashboardPayload(notifications);
try {
return objectMapper.writeValueAsString(payload);
} catch (JsonProcessingException e) {
log.error("Failed to serialise dashboard payload for caseReference={}", caseReference, e);
return "{\"notifications\":[]}";
}
}

private record DashboardPayload(List<DashboardNotification> notifications) {
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package uk.gov.hmcts.reform.pcs.ccd.event.dashboard;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.ccd.sdk.api.EventPayload;
import uk.gov.hmcts.ccd.sdk.api.callback.Submit;
import uk.gov.hmcts.ccd.sdk.api.callback.SubmitResponse;
import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase;
import uk.gov.hmcts.reform.pcs.ccd.domain.State;

@Component
@Slf4j
@RequiredArgsConstructor
public class SubmitDashboardViewHandler implements Submit<PCSCase, State> {

@Override
public SubmitResponse<State> submit(EventPayload<PCSCase, State> eventPayload) {
long caseReference = eventPayload.caseReference();
log.info("DashboardView SUBMIT invoked for caseReference={} (no-op submit, read-only event)", caseReference);
// READ-ONLY: the dashboard view event should not persist changes.
return SubmitResponse.defaultResponse();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package uk.gov.hmcts.reform.pcs.ccd.service.dashboard;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase;
import uk.gov.hmcts.reform.pcs.ccd.domain.State;
import uk.gov.hmcts.reform.pcs.dashboard.model.DashboardNotification;

import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
* Computes dashboard notifications (template IDs + values) from submitted and draft case data.
*
* <p>READ-ONLY: callers are responsible for loading any data needed and passing it in.</p>
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class DashboardJourneyService {

public List<DashboardNotification> computeNotifications(long caseReference,
State state,
PCSCase submittedCaseData,
Optional<PCSCase> draftCaseData) {

boolean hasDraft = draftCaseData.isPresent();

log.info("DashboardJourneyService.computeNotifications called for caseReference={}, state={}, hasDraft={}",
caseReference, state, hasDraft);

if (state == State.CASE_ISSUED) {
DashboardNotification journeyNotification = DashboardNotification.builder()
.templateId("Notice.PCS.Dashboard.CaseIssued")
.templateValues(Map.of(
"caseReference", caseReference,
"hasDraft", hasDraft
))
.build();

log.info("DashboardJourneyService selected templateId={} for caseReference={}, state={}",
journeyNotification.getTemplateId(), caseReference, state);
return List.of(journeyNotification);
}

if (state == State.AWAITING_SUBMISSION_TO_HMCTS && hasDraft) {
DashboardNotification resumeNotification = DashboardNotification.builder()
.templateId("Notice.PCS.Dashboard.DraftInProgress")
.templateValues(Map.of(
"caseReference", caseReference
))
.build();
log.info("DashboardJourneyService selected templateId={} for caseReference={}, state={}",
resumeNotification.getTemplateId(), caseReference, state);
return List.of(resumeNotification);
}

log.info(
"DashboardJourneyService no matching dashboard notification rules for caseReference={}, state={}",
caseReference, state);
return List.of();
}
}

Loading