Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
<sonar.report.export.path>sonar-report.json</sonar.report.export.path>
<sonar.scm.provider>git</sonar.scm.provider>
<mvn.site.url>file://${project.build.directory}/site</mvn.site.url>
<coredomain.version>17.103.10</coredomain.version>
<referencedata.version>17.103.125</referencedata.version>
<coredomain.version>17.102.19-DLRM7-SNAPSHOT</coredomain.version>
<referencedata.version>17.103.128</referencedata.version>
<notification.notify.version>17.0.38</notification.notify.version>
<systemdocgenerator.version>17.103.104</systemdocgenerator.version>
<progression.version>17.0.210-DLRM7-SNAPSHOT</progression.version>
Expand All @@ -49,7 +49,7 @@
<netty.version>4.1.113.Final</netty.version>
<!-- Downgrade h2 until deltaspike tests have been updated to work with latest h2 version -->
<h2.version>1.4.196</h2.version>
<sjp.version>17.103.148</sjp.version>
<sjp.version>17.103.166</sjp.version>
<staging.dcs.version>17.103.8</staging.dcs.version>
<sonar.coverage.exclusions>
**/uk/gov/moj/cpp/results/command/api/accesscontrol/**/*,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import uk.gov.moj.cpp.results.domain.event.MigratedInactiveNcesEmailNotification;
import uk.gov.moj.cpp.results.domain.event.MigratedInactiveNcesEmailNotificationRequested;
import uk.gov.moj.cpp.results.domain.event.MigratedInactiveNcesEmailNotificationRequestedExists;
import uk.gov.moj.cpp.results.domain.event.MigratedInactiveNcesFinAcccountNumberAbsent;

import java.io.Serial;
import java.util.List;
Expand All @@ -29,9 +30,10 @@ public class MigratedInactiveHearingFinancialResultsAggregate implements Aggrega
private String sendToAddress;
private String subject;
private boolean isEventRaisedEarlier = false;
public static final String FINA_ACCOUNT_NOT_PRESENT = "FIN_ACCOUNT_NOT_PRESENT";

@Serial
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 101L;
private UUID caseId;


Expand Down Expand Up @@ -71,6 +73,15 @@ public Stream<Object> sendNcesEmailForMigratedApplication(
return apply(Stream.of(event));
}

if(FINA_ACCOUNT_NOT_PRESENT.equals(migratedCaseDetails.fineAccountNumber())){
final MigratedInactiveNcesFinAcccountNumberAbsent event = MigratedInactiveNcesFinAcccountNumberAbsent.migratedInactiveNcesFinAcccountNumberAbsent()
.withMasterDefendantId(fromString(migratedCaseDetails.masterDefendantId()))
.withDefendantId(fromString(migratedCaseDetails.masterDefendantId()))
.withCaseId(fromString(migratedCaseDetails.caseId()))
.build();
return apply(Stream.of(event));
}

final String subject = APPLICATION_TYPES.get(applicationType);
final MigratedInactiveNcesEmailNotificationRequested requested = migratedInactiveNcesEmailNotificationRequested()
.withNotificationId(randomUUID())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package uk.gov.moj.cpp.results.domain.aggregate;

import static java.util.Collections.singletonList;
import static java.util.UUID.fromString;
import static java.util.UUID.randomUUID;
import static java.util.stream.Collectors.toList;
import static org.hamcrest.CoreMatchers.is;
Expand All @@ -12,6 +13,7 @@
import uk.gov.moj.cpp.domains.results.MigratedMasterDefendantCaseDetails;
import uk.gov.moj.cpp.results.domain.event.MigratedInactiveNcesEmailNotificationRequested;
import uk.gov.moj.cpp.results.domain.event.MigratedInactiveNcesEmailNotificationRequestedExists;
import uk.gov.moj.cpp.results.domain.event.MigratedInactiveNcesFinAcccountNumberAbsent;

import java.util.List;
import java.util.UUID;
Expand Down Expand Up @@ -158,6 +160,42 @@ public void shouldReturnEmptyStreamWhenEventRaisedEarlier() {
is(EVENT_EARLIER_OR_MIGRATED_CASE_DETAILS_IS_NULL));
}

@Test
public void shouldEmitMigratedInactiveNcesFinAccountNumberAbsentWhenFineAccountNotPresent() {
final MigratedMasterDefendantCaseDetails migratedCaseDetails = MigratedMasterDefendantCaseDetails.builder()
.withMasterDefendantId(MASTER_DEFENDANT_ID)
.withCaseId(CASE_ID)
.withFineAccountNumber(MigratedInactiveHearingFinancialResultsAggregate.FINA_ACCOUNT_NOT_PRESENT)
.withCourtEmail(COURT_EMAIL)
.withDivision(DIVISION)
.withDefendantId(DEFENDANT_ID)
.withDefendantName(DEFENDANT_NAME)
.withDefendantAddress(DEFENDANT_ADDRESS)
.withOriginalDateOfConviction(ORIGINAL_DATE_OF_CONVICTION)
.withDefendantEmail(DEFENDANT_EMAIL)
.withDefendantDateOfBirth(DEFENDANT_DATE_OF_BIRTH)
.withDefendantContactNumber(DEFENDANT_CONTACT_NUMBER)
.withMigrationSourceSystemCaseIdentifier("CASE123")
.withCaseURN("caseUrn1")
.build();

final Stream<Object> result = aggregate.sendNcesEmailForMigratedApplication(
STAT_DEC,
LISTING_DATE,
singletonList("caseUrn"),
HEARING_COURT_CENTRE_NAME,
migratedCaseDetails);

final List<Object> events = result.collect(toList());
assertThat(events.size(), is(1));
assertThat(events.get(0).getClass(), is(MigratedInactiveNcesFinAcccountNumberAbsent.class));

final MigratedInactiveNcesFinAcccountNumberAbsent event = (MigratedInactiveNcesFinAcccountNumberAbsent) events.get(0);
assertThat(event.getMasterDefendantId(), is(fromString(MASTER_DEFENDANT_ID)));
assertThat(event.getDefendantId(), is(fromString(MASTER_DEFENDANT_ID)));
assertThat(event.getCaseId(), is(fromString(CASE_ID)));
}

@Test
public void shouldSaveMigratedInactiveNcesEmailNotificationDetails() {
final UUID masterDefendantId = randomUUID();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://moj.gov.uk/cpp/results/domain/event/results.event.migrated-inactive-nces-fin-acccount-number-absent.json",
"type": "object",
"properties": {
"masterDefendantId": {
"$ref": "http://justice.gov.uk/domain/core/common/definitions.json#/definitions/uuid"
},
"defendantId": {
"$ref": "http://justice.gov.uk/domain/core/common/definitions.json#/definitions/uuid"
},
"caseId": {
"$ref": "http://justice.gov.uk/domain/core/common/definitions.json#/definitions/uuid"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.stream.Stream;

import javax.inject.Inject;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonString;
Expand All @@ -61,6 +62,7 @@ public class StagingEnforcementAcknowledgmentEventProcessor {
private static final String HEARING_FINANCIAL_RESULT_REQUEST = "hearingFinancialResultRequest";
private static final DateTimeFormatter ISO_FORMATTER = ofPattern("yyyy-MM-dd");
private static final DateTimeFormatter OUTPUT_FORMATTER = ofPattern("dd/MM/yyyy");
public static final String FINA_ACCOUNT_NOT_PRESENT = "FIN_ACCOUNT_NOT_PRESENT";

private record NcesNotificationDetails(String email, String division) {
}
Expand Down Expand Up @@ -149,7 +151,7 @@ public void processSendNcesMailForNewApplication(final JsonEnvelope event) { //A
ncesNotificationDetails = extractNcesNotificationEmail(event, payload);
}

if (isNotEmpty(enrichedDetails) && nonNull(ncesNotificationDetails) && nonNull(ncesNotificationDetails.email())) {
if (nonNull(ncesNotificationDetails) && nonNull(ncesNotificationDetails.email())) {
for (EnrichedFineDetail item : enrichedDetails) {

final JsonObjectBuilder builder = createObjectBuilder()
Expand Down Expand Up @@ -225,32 +227,46 @@ private List<EnrichedFineDetail> extractAllEnrichedData(JsonObject json, String
.map(JsonValue::asJsonObject)
.filter(obj -> obj.containsKey(InactiveMigratedCase.INACTIVE_CASE_SUMMARY))
.map(obj -> obj.getJsonObject(InactiveMigratedCase.INACTIVE_CASE_SUMMARY))
.flatMap(caseSummary -> {
String caseId = caseSummary.getString(InactiveMigratedCase.ID);
String caseURN = caseSummary.getString(Case.URN);

JsonObject sourceSystem = caseSummary.getJsonObject(InactiveMigratedCase.MIGRATION_SOURCE_SYSTEM);
String caseIdentifier = sourceSystem.getString(InactiveMigratedCase.MIGRATION_SOURCE_SYSTEM_CASE_IDENTIFIER);

return caseSummary.getJsonArray(Defendant.DEFENDANTS).stream()
.map(JsonValue::asJsonObject)
.filter(def -> masterId.equals(def.getString(MASTER_DEFENDANT_ID)))
.flatMap(def -> {
String currentDefId = def.getString(Defendant.ID);
DefendantDetails details = mapToDefendantDetails(def);

return sourceSystem.getJsonArray(InactiveMigratedCase.DEFENDANT_FINE_ACCOUNT_NUMBERS).stream()
.map(JsonValue::asJsonObject)
.filter(fa -> currentDefId.equals(fa.getString(Defendant.ID)))
.map(fa -> new EnrichedFineDetail(
new FineAccount(caseId, fa.getString(MigrationConstants.FineAccount.FINE_ACCOUNT_NUMBER), caseIdentifier, caseURN),
details)
);
});
})
.flatMap(caseSummary -> processCaseSummary(caseSummary, masterId))
.toList();
}

private Stream<EnrichedFineDetail> processCaseSummary(JsonObject caseSummary, String masterId) {
String caseId = caseSummary.getString(InactiveMigratedCase.ID);
String caseURN = caseSummary.getString(Case.URN);

JsonObject sourceSystem = caseSummary.getJsonObject(InactiveMigratedCase.MIGRATION_SOURCE_SYSTEM);
String caseIdentifier = sourceSystem.getString(InactiveMigratedCase.MIGRATION_SOURCE_SYSTEM_CASE_IDENTIFIER);

return caseSummary.getJsonArray(Defendant.DEFENDANTS).stream()
.map(JsonValue::asJsonObject)
.filter(def -> masterId.equals(def.getString(MASTER_DEFENDANT_ID)))
.flatMap(def -> enrichFineDetails(def, sourceSystem, caseId, caseURN, caseIdentifier));
}

private Stream<EnrichedFineDetail> enrichFineDetails(JsonObject def, JsonObject sourceSystem,
String caseId, String caseURN, String caseIdentifier) {
String currentDefId = def.getString(Defendant.ID);
DefendantDetails details = mapToDefendantDetails(def);

List<JsonObject> fineAccountList = Optional.ofNullable(sourceSystem.getJsonArray(InactiveMigratedCase.DEFENDANT_FINE_ACCOUNT_NUMBERS))
.stream()
.flatMap(JsonArray::stream)
.map(JsonValue::asJsonObject)
.toList();

String accountNumber = fineAccountList.stream()
.filter(fa -> currentDefId.equals(fa.getString(Defendant.ID)))
.map(fa -> fa.getString(MigrationConstants.FineAccount.FINE_ACCOUNT_NUMBER))
.findFirst()
.orElse(FINA_ACCOUNT_NOT_PRESENT);

return Stream.of(new EnrichedFineDetail(
new FineAccount(caseId, accountNumber, caseIdentifier, caseURN),
details)
);
}

private DefendantDetails mapToDefendantDetails(JsonObject defendantJson) {
if (defendantJson == null) {
return new DefendantDetails("", "", "", "", "", "", "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
Expand All @@ -18,6 +19,7 @@
import static uk.gov.justice.services.test.utils.core.matchers.JsonEnvelopeMetadataMatcher.metadata;
import static uk.gov.justice.services.test.utils.core.matchers.JsonEnvelopePayloadMatcher.payloadIsJson;
import static uk.gov.justice.services.test.utils.core.messaging.MetadataBuilderFactory.metadataWithRandomUUID;
import static uk.gov.moj.cpp.results.event.processor.StagingEnforcementAcknowledgmentEventProcessor.FINA_ACCOUNT_NOT_PRESENT;

import uk.gov.justice.services.core.sender.Sender;
import uk.gov.justice.services.messaging.Envelope;
Expand Down Expand Up @@ -186,6 +188,7 @@ public void shouldCallUpdatecorrelationId() {

}


@Test
void shouldProcessSendNcesMailForNewApplication() {
// GIVEN
Expand Down Expand Up @@ -218,10 +221,12 @@ void shouldProcessSendNcesMailForNewApplication() {
// THEN
verify(progressionService).getInactiveMigratedCasesByCaseIds(List.of(caseId1, caseId2, caseId3));

verify(sender, times(4)).sendAsAdmin(envelopeArgumentCaptor.capture());
// Updated to 5: (3 from Case1 + 1 from Case2 + 1 Final Notification)
verify(sender, times(5)).sendAsAdmin(envelopeArgumentCaptor.capture());

List<Envelope<JsonObject>> allEnvelopes = envelopeArgumentCaptor.getAllValues();

// 0: Case 1 - Garfield (12345)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this comment

assertThat(JsonEnvelope.envelopeFrom(allEnvelopes.get(0).metadata(), allEnvelopes.get(0).payload()),
jsonEnvelope(
metadata().withName("result.command.send-migrated-inactive-nces-email-for-application"),
Expand All @@ -236,6 +241,7 @@ void shouldProcessSendNcesMailForNewApplication() {
withJsonPath("$.migratedMasterDefendantCourtEmailAndFineAccount.originalDateOfConviction", is("09/11/2025, 10/11/2025"))
))));

// 1: Case 1 - Junior (54321)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this comment

assertThat(JsonEnvelope.envelopeFrom(allEnvelopes.get(1).metadata(), allEnvelopes.get(1).payload()),
jsonEnvelope(
metadata().withName("result.command.send-migrated-inactive-nces-email-for-application"),
Expand All @@ -247,7 +253,19 @@ void shouldProcessSendNcesMailForNewApplication() {
withJsonPath("$.migratedMasterDefendantCourtEmailAndFineAccount.defendantEmail", is("junior@gmail.com"))
))));

// 2: Case 1 - Jane (NOT PRESENT)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this

assertThat(JsonEnvelope.envelopeFrom(allEnvelopes.get(2).metadata(), allEnvelopes.get(2).payload()),
jsonEnvelope(
metadata().withName("result.command.send-migrated-inactive-nces-email-for-application"),
payloadIsJson(allOf(
withJsonPath("$.migratedMasterDefendantCourtEmailAndFineAccount.caseId", is(caseId1)),
withJsonPath("$.migratedMasterDefendantCourtEmailAndFineAccount.fineAccountNumber", is(FINA_ACCOUNT_NOT_PRESENT)),
withJsonPath("$.migratedMasterDefendantCourtEmailAndFineAccount.defendantName", is("Jane Dare")),
withJsonPath("$.migratedMasterDefendantCourtEmailAndFineAccount.defendantEmail", is("jane.dare@gmail.com"))
))));

// 3: Case 2 - Garfield (67890)
assertThat(JsonEnvelope.envelopeFrom(allEnvelopes.get(3).metadata(), allEnvelopes.get(3).payload()),
jsonEnvelope(
metadata().withName("result.command.send-migrated-inactive-nces-email-for-application"),
payloadIsJson(allOf(
Expand All @@ -256,6 +274,65 @@ void shouldProcessSendNcesMailForNewApplication() {
withJsonPath("$.migratedMasterDefendantCourtEmailAndFineAccount.defendantName", is("Garfield Dare"))
))));

// 4: Final notification
assertThat(allEnvelopes.get(4).metadata().name(), is("result.command.send-nces-email-for-application"));
}

@Test
void shouldProcessSendNcesMailForNewApplicationWhenDefendantFineAccountNumbersMissing() {
// GIVEN
final String masterDefendantId = "1a9176f4-3adc-4ea1-a808-26c4632f38ab";
final String caseId1 = "b00acc1c-eb69-4b3c-960e-76be9153125a";
final String caseId2 = "7776f4-3adc-4ea1-a808-26c4632f38ab";
final String caseId3 = "b10acc1c-eb69-4b3c-960e-76be9153125a";
final String hearingCourtCentreId = "faa91bb2-19cb-384b-bcc1-06d31d12cc67";

final JsonObject notificationPayload = createObjectBuilder()
.add("masterDefendantId", masterDefendantId)
.add("caseIds", createCaseIds(caseId1, caseId2, caseId3))
.add("hearingCourtCentreId", hearingCourtCentreId)
.build();

final JsonObject progressionResponse = getPayload("inactive-migrated-cases-without-defendant-fine-account-numbers.json");

when(progressionService.getInactiveMigratedCasesByCaseIds(List.of(caseId1, caseId2, caseId3)))
.thenReturn(Optional.of(progressionResponse));

final JsonObject payload = getPayload("organisation-units.json");
when(referenceDataService.getOrganisationUnit(eq(hearingCourtCentreId), any())).thenReturn(payload);

final JsonEnvelope event = JsonEnvelope.envelopeFrom(
metadataWithRandomUUID("public.hearing.nces-email-notification-for-application"), notificationPayload);

// WHEN
stagingEnforcementAcknowledgmentEventProcessor.processSendNcesMailForNewApplication(event);

// THEN
verify(progressionService).getInactiveMigratedCasesByCaseIds(List.of(caseId1, caseId2, caseId3));

// UPDATED: 2 from Case 1 (NOT PRESENT) + 1 from Case 2 + 1 Final = 4 total
verify(sender, times(4)).sendAsAdmin(envelopeArgumentCaptor.capture());

List<Envelope<JsonObject>> allEnvelopes = envelopeArgumentCaptor.getAllValues();

// 0: Case 1 - Garfield (NOT PRESENT)
assertThat(allEnvelopes.get(0).payload().getJsonObject("migratedMasterDefendantCourtEmailAndFineAccount").getString("fineAccountNumber"), is(FINA_ACCOUNT_NOT_PRESENT));
assertThat(allEnvelopes.get(0).payload().getJsonObject("migratedMasterDefendantCourtEmailAndFineAccount").getString("caseId"), is(caseId1));

// 1: Case 1 - Junior (NOT PRESENT)
assertThat(allEnvelopes.get(1).payload().getJsonObject("migratedMasterDefendantCourtEmailAndFineAccount").getString("fineAccountNumber"), is(FINA_ACCOUNT_NOT_PRESENT));
assertThat(allEnvelopes.get(1).payload().getJsonObject("migratedMasterDefendantCourtEmailAndFineAccount").getString("defendantName"), containsString("Junior"));

// 2: Case 2 - Garfield (67890)
assertThat(JsonEnvelope.envelopeFrom(allEnvelopes.get(2).metadata(), allEnvelopes.get(2).payload()),
jsonEnvelope(
metadata().withName("result.command.send-migrated-inactive-nces-email-for-application"),
payloadIsJson(allOf(
withJsonPath("$.migratedMasterDefendantCourtEmailAndFineAccount.caseId", is(caseId2)),
withJsonPath("$.migratedMasterDefendantCourtEmailAndFineAccount.fineAccountNumber", is("67890"))
))));

// 3: Final command
assertThat(allEnvelopes.get(3).metadata().name(), is("result.command.send-nces-email-for-application"));
}

Expand Down
Loading
Loading