Skip to content
Merged
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
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ sonarqube {
property "sonar.projectKey", "civil-service"
property "sonar.coverage.jacoco.xmlReportPaths", "${jacocoTestReport.reports.xml.outputLocation}"
property "sonar.coverage.exclusions", "**/model/**, **/config/**/*Configuration.java, **/request/servlet/** , **/controllers/**, **/testingsupport/**, **/*ExternalTaskListener.java, **/*BaseExternalTaskHandler.java, **/stereotypes/**, **/*Exception.java, **/EventHistoryMapper*.java, **/model/hearingvalues/**, **/enums/hearing/**, **/fees/client/**, **/enums/sdo/**, **/service/PaymentsService.java, **/DashboardWithParamsCallbackHandler.java, **/PaymentRequestUpdateCallbackService.java, **/advice/**, **/dashboard/cache/**"
property "sonar.cpd.exclusions", "**/*DocumentManagementService.java, **/*Spec*.java, **/*CcdDashboardClaimantClaimMatcher.java, **/*CcdDashboardDefendantClaimMatcher.java, **/notification/handlers/respondtoquery/**/*EmailDTOGenerator.java, **/notification/handlers/respondtoquery/RespondToQueryHelper.java"
property "sonar.cpd.exclusions", "**/*DocumentManagementService.java, **/*Spec*.java, **/*CcdDashboardClaimantClaimMatcher.java, **/*CcdDashboardDefendantClaimMatcher.java, **/notification/handlers/respondtoquery/**/*EmailDTOGenerator.java, **/notification/handlers/respondtoquery/RespondToQueryHelper.java, **/handler/migration/FixDashboardParamsTextTask.java"
property "sonar.exclusions", "**/model/**, **/hmc/model/**, **/model/hearingvalues/**, **/handler/callback/camunda/dashboardnotifications/claimant/CCJRequestedDashboardNotificationHandler.java, **/handler/callback/camunda/dashboardnotifications/claimant/ClaimantCCJResponseNotificationHandler.java" +
", **/handler/callback/camunda/dashboardnotifications/claimant/ClaimantResponseNotificationHandler.java, **/utils/**, **/filters/**, **/handler/callback/camunda/dashboardnotifications/defendant/MoreTimeRequestedDashboardNotificationDefendantHandler.java, **/handler/callback/camunda/dashboardnotifications/claimant/ClaimantMediationSuccessfulDashboardNotificationHandler.java, **/handler/callback/camunda/dashboardnotifications/claimant/ClaimSettledDashboardNotificationHandler.java, **/handler/callback/camunda/dashboardnotifications/claimant/HearingScheduledClaimantNotificationHandler.java, **/handler/callback/camunda/dashboardnotifications/defendant/SettleClaimPaidInFullDefendantDashboardNotificationHandler.java, **/handler/callback/camunda/dashboardnotifications/defendant/DefendantNotifyDiscontinuanceDashboardNotificationHandler.java" +
",**/utils/CaseQueriesUtil.java, **/handler/callback/user/RaiseQueryCallbackHandler.java,**/handler/migration/MigrateCaseQueriesTask.java, **/handler/callback/user/RespondQueryCallbackHandler.java, **/service/servicebus/CcdCaseEventsExecutor.java, **/tasklisteners/MigrateCasesTaskListener.java, **/migration/MigrationTask.java, **/migration/CustomRequestScopeAttr.java"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package uk.gov.hmcts.reform.civil.handler.migration;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringSubstitutor;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.reform.civil.bulkupdate.csv.CaseReference;
import uk.gov.hmcts.reform.civil.model.CaseData;
import uk.gov.hmcts.reform.dashboard.entities.DashboardNotificationsEntity;
import uk.gov.hmcts.reform.dashboard.repositories.DashboardNotificationsRepository;

import java.time.OffsetDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class FixDashboardParamsTextTask extends MigrationTask<CaseReference> {

private static final String NOTIFICATION_NAME = "Notice.AAA6.ClaimantIntent.ClaimSettled.Defendant";
private static final String DEFENDANT = "DEFENDANT";

private static final Map<String, String> PARAM_KEY_MAPPING = Map.of(
"claimSettledDateEn", "applicant1ClaimSettledDateEn",
"claimSettledDateCy", "applicant1ClaimSettledDateCy"
);

private final DashboardNotificationsRepository dashboardNotificationsRepository;

public FixDashboardParamsTextTask(DashboardNotificationsRepository dashboardNotificationsRepository) {
super(CaseReference.class);
this.dashboardNotificationsRepository = dashboardNotificationsRepository;
}

@Override
protected String getTaskName() {
return "FixDashboardParamsTextTask";
}

@Override
protected String getEventSummary() {
return "Fix claim settled defendant notification with unresolved param placeholders";
}

@Override
protected String getEventDescription() {
return "Replaces ${claimSettledDateEn} with the correct applicant1ClaimSettledDateEn value from stored params";
}

@Override
protected CaseData migrateCaseData(CaseData caseData, CaseReference caseReference) {
String caseId = caseReference.getCaseReference();

List<DashboardNotificationsEntity> notifications =
dashboardNotificationsRepository.findByReferenceAndCitizenRoleAndName(caseId, DEFENDANT, NOTIFICATION_NAME);

if (notifications.isEmpty()) {
log.info("No {} notification found for case {}", NOTIFICATION_NAME, caseId);
return caseData;
}

for (DashboardNotificationsEntity notification : notifications) {
HashMap<String, Object> params = notification.getParams();
if (params == null || params.isEmpty()) {
log.warn("Notification {} for case {} has no stored params, skipping", NOTIFICATION_NAME, caseId);
continue;
}

HashMap<String, Object> mappedParams = buildMappedParams(params);
if (mappedParams.isEmpty()) {
log.warn("No matching param values found for case {}, skipping", caseId);
continue;
}

StringSubstitutor substitutor = new StringSubstitutor(mappedParams);
notification.setDescriptionEn(substitutor.replace(notification.getDescriptionEn()));
notification.setDescriptionCy(substitutor.replace(notification.getDescriptionCy()));
notification.setUpdatedOn(OffsetDateTime.now());
notification.setUpdatedBy("FixDashboardParamsTextTask");

dashboardNotificationsRepository.save(notification);
log.info("Fixed notification for case {} - descEn: [{}], descCy: [{}]",
caseId, notification.getDescriptionEn(), notification.getDescriptionCy());
}

return caseData;
}

private HashMap<String, Object> buildMappedParams(HashMap<String, Object> storedParams) {
HashMap<String, Object> mapped = new HashMap<>();
for (Map.Entry<String, String> entry : PARAM_KEY_MAPPING.entrySet()) {
String templateKey = entry.getKey();
String storedKey = entry.getValue();
Object value = storedParams.get(storedKey);
if (value != null) {
mapped.put(templateKey, value);
}
}
return mapped;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,28 @@
import uk.gov.hmcts.reform.civil.enums.YesOrNo;
import uk.gov.hmcts.reform.civil.handler.callback.camunda.dashboardnotifications.DashboardScenarios;
import uk.gov.hmcts.reform.civil.model.CaseData;
import uk.gov.hmcts.reform.civil.service.FeatureToggleService;
import uk.gov.hmcts.reform.civil.service.dashboardnotifications.DashboardNotificationsParamsMapper;
import uk.gov.hmcts.reform.civil.service.dashboardnotifications.DashboardScenarioService;
import uk.gov.hmcts.reform.dashboard.services.DashboardNotificationService;
import uk.gov.hmcts.reform.dashboard.services.DashboardScenariosService;
import uk.gov.hmcts.reform.dashboard.services.TaskListService;

@Service
public class ClaimSettledDefendantDashboardService extends DashboardScenarioService {

protected static final String DEFENDANT = "DEFENDANT";
protected final FeatureToggleService featureToggleService;
protected final DashboardNotificationService dashboardNotificationService;
private final TaskListService taskListService;

public ClaimSettledDefendantDashboardService(DashboardScenariosService dashboardScenariosService,
DashboardNotificationsParamsMapper mapper) {
DashboardNotificationsParamsMapper mapper, FeatureToggleService featureToggleService,
DashboardNotificationService dashboardNotificationService, TaskListService taskListService) {
super(dashboardScenariosService, mapper);
this.featureToggleService = featureToggleService;
this.dashboardNotificationService = dashboardNotificationService;
this.taskListService = taskListService;
}

public void notifyClaimSettled(CaseData caseData, String authToken) {
Expand All @@ -22,11 +34,34 @@ public void notifyClaimSettled(CaseData caseData, String authToken) {

@Override
protected String getScenario(CaseData caseData) {
return DashboardScenarios.SCENARIO_AAA6_CLAIMANT_INTENT_CLAIM_SETTLED_DEFENDANT.getScenario();
return DashboardScenarios.SCENARIO_AAA6_CLAIMANT_INTENT_CLAIM_SETTLE_EVENT_DEFENDANT.getScenario();
}

@Override
protected boolean shouldRecordScenario(CaseData caseData) {
return YesOrNo.NO.equals(caseData.getRespondent1Represented());
}

@Override
protected void beforeRecordScenario(CaseData caseData, String authToken) {
final String caseId = String.valueOf(caseData.getCcdCaseReference());

if (!featureToggleService.isLocationWhiteListed(caseData.getCaseManagementLocation().getBaseLocation())) {
inactiveGAItems(caseId);
}

}

private void inactiveGAItems(String caseId) {
dashboardNotificationService.deleteByReferenceAndCitizenRole(
caseId,
DEFENDANT
);

taskListService.makeProgressAbleTasksInactiveForCaseIdentifierAndRoleExcludingTemplate(
caseId,
DEFENDANT,
"Application.View"
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package uk.gov.hmcts.reform.civil.handler.migration;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import uk.gov.hmcts.reform.civil.bulkupdate.csv.CaseReference;
import uk.gov.hmcts.reform.civil.model.CaseData;
import uk.gov.hmcts.reform.dashboard.entities.DashboardNotificationsEntity;
import uk.gov.hmcts.reform.dashboard.repositories.DashboardNotificationsRepository;

import java.time.OffsetDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class FixDashboardParamsTextTaskTest {

private static final String CASE_ID = "1234567890";
private static final String NOTIFICATION_NAME = "Notice.AAA6.ClaimantIntent.ClaimSettled.Defendant";

@Mock
private DashboardNotificationsRepository dashboardNotificationsRepository;
@InjectMocks
private FixDashboardParamsTextTask task;

@Test
void shouldReplacePlaceholderWithCorrectParamValue() {
HashMap<String, Object> params = new HashMap<>();
params.put("applicant1ClaimSettledDateEn", "30 March 2026");
params.put("applicant1ClaimSettledDateCy", "30 Mawrth 2026");

DashboardNotificationsEntity notification = buildNotification(
"<p class=\"govuk-body\">The claimant has confirmed that this case was settled on ${claimSettledDateEn}.</p>"
+ "<p class=\"govuk-body\">If you do not agree that the case is settled, please outline your objections"
+ " in writing within 19 days of the settlement date, to the Civil National Business Centre"
+ " using the email address at {cmcCourtEmailId}</p>",
"<p class=\"govuk-body\">The claimant has confirmed that this case was settled on ${claimSettledDateEn}.</p>"
+ "<p class=\"govuk-body\">If you do not agree that the case is settled, please outline your objections"
+ " in writing within 19 days of the settlement date, to the Civil National Business Centre"
+ " using the email address at {cmcCourtEmailId}</p>",
params
);

when(dashboardNotificationsRepository.findByReferenceAndCitizenRoleAndName(CASE_ID, "DEFENDANT", NOTIFICATION_NAME))
.thenReturn(List.of(notification));

CaseReference caseRef = new CaseReference();
caseRef.setCaseReference(CASE_ID);
task.migrateCaseData(CaseData.builder().build(), caseRef);

ArgumentCaptor<DashboardNotificationsEntity> captor = ArgumentCaptor.forClass(DashboardNotificationsEntity.class);
verify(dashboardNotificationsRepository).save(captor.capture());

DashboardNotificationsEntity saved = captor.getValue();
assertThat(saved.getDescriptionEn()).contains("settled on 30 March 2026.");
assertThat(saved.getDescriptionEn()).doesNotContain("${claimSettledDateEn}");
assertThat(saved.getDescriptionEn()).contains("{cmcCourtEmailId}");
assertThat(saved.getDescriptionCy()).contains("settled on 30 March 2026.");
assertThat(saved.getUpdatedBy()).isEqualTo("FixDashboardParamsTextTask");
}

@Test
void shouldNotSaveWhenNoNotificationFound() {
when(dashboardNotificationsRepository.findByReferenceAndCitizenRoleAndName(CASE_ID, "DEFENDANT", NOTIFICATION_NAME))
.thenReturn(List.of());

CaseReference caseRef = new CaseReference();
caseRef.setCaseReference(CASE_ID);
task.migrateCaseData(CaseData.builder().build(), caseRef);

verify(dashboardNotificationsRepository, never()).save(any());
}

@Test
void shouldSkipWhenParamsAreNull() {
DashboardNotificationsEntity notification = buildNotification(
"text with ${claimSettledDateEn}",
"text with ${claimSettledDateEn}",
null
);

when(dashboardNotificationsRepository.findByReferenceAndCitizenRoleAndName(CASE_ID, "DEFENDANT", NOTIFICATION_NAME))
.thenReturn(List.of(notification));

CaseReference caseRef = new CaseReference();
caseRef.setCaseReference(CASE_ID);
task.migrateCaseData(CaseData.builder().build(), caseRef);

verify(dashboardNotificationsRepository, never()).save(any());
}

@Test
void shouldSkipWhenMappedParamValueNotInStoredParams() {
HashMap<String, Object> params = new HashMap<>();
params.put("someOtherParam", "value");

DashboardNotificationsEntity notification = buildNotification(
"text with ${claimSettledDateEn}",
"text with ${claimSettledDateEn}",
params
);

when(dashboardNotificationsRepository.findByReferenceAndCitizenRoleAndName(CASE_ID, "DEFENDANT", NOTIFICATION_NAME))
.thenReturn(List.of(notification));

CaseReference caseRef = new CaseReference();
caseRef.setCaseReference(CASE_ID);
task.migrateCaseData(CaseData.builder().build(), caseRef);

verify(dashboardNotificationsRepository, never()).save(any());
}

@Test
void shouldReturnCorrectTaskName() {
assertThat(task.getTaskName()).isEqualTo("FixDashboardParamsTextTask");
}

private DashboardNotificationsEntity buildNotification(String descEn, String descCy,
HashMap<String, Object> params) {
DashboardNotificationsEntity entity = new DashboardNotificationsEntity();
entity.setId(UUID.randomUUID());
entity.setReference(CASE_ID);
entity.setName(NOTIFICATION_NAME);
entity.setCitizenRole("DEFENDANT");
entity.setTitleEn("The claim is settled");
entity.setDescriptionEn(descEn);
entity.setTitleCy("Mae'r hawliad wedi'i setlo");
entity.setDescriptionCy(descCy);
entity.setParams(params);
entity.setCreatedAt(OffsetDateTime.now());
return entity;
}
}
Loading
Loading