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
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,14 @@ public Stream<Object> sendNcesEmailForMigratedApplication(
return apply(Stream.of(event));
}

if(FINA_ACCOUNT_NOT_PRESENT.equals(migratedCaseDetails.fineAccountNumber())){
MigratedInactiveNcesFinAcccountNumberAbsent.migratedInactiveNcesFinAcccountNumberAbsent()
.withMasterDefendantId(UUID.fromString(migratedCaseDetails.masterDefendantId()))
.withDefendantId(UUID.fromString(migratedCaseDetails.masterDefendantId()))
.withCaseId(UUID.fromString(migratedCaseDetails.caseId()))
.build();
}

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
@@ -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)
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)
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)
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"inactiveMigratedCaseSummaries": [
{
"inactiveCaseSummary": {
"id": "b00acc1c-eb69-4b3c-960e-76be9153125a",
"caseURN": "SCRDID98443",
"defendants": [
{
"defendantId": "1a9176f4-3adc-4ea1-a808-26c4632f38ab",
"masterDefendantId": "1a9176f4-3adc-4ea1-a808-26c4632f38ab",
"personDefendant": {
"personDetails": {
"firstName": "Garfield",
"lastName": "Dare",
"dateOfBirth": "1998-08-23",
"address": {
"address1": "59 Meadow Lane",
"postcode": "B1 1AA"
},
"contact": {
"work": "07431234511",
"primaryEmail": "test@gmail.com"
}
}
},
"offences": [
{ "convictionDate": "2025-11-09" },
{ "convictionDate": "2025-11-10" }
]
},
{
"defendantId": "NEW-DEF-ID-55555",
"masterDefendantId": "1a9176f4-3adc-4ea1-a808-26c4632f38ab",
"personDefendant": {
"personDetails": {
"firstName": "Garfield (Junior)",
"lastName": "Dare",
"dateOfBirth": "2020-01-01",
"address": {
"address1": "59 Meadow Lane",
"postcode": "B1 1AA"
},
"contact": {
"work": "0000000000",
"primaryEmail": "junior@gmail.com"
}
}
},
"offences": [
{ "convictionDate": "2026-01-01" }
]
}
],
"migrationSourceSystem": {
"migrationCaseStatus": "INACTIVE",
"migrationSourceSystemName": "XHIBIT",
"migrationSourceSystemCaseIdentifier": "T20250001"
}
}
},
{
"inactiveCaseSummary": {
"id": "7776f4-3adc-4ea1-a808-26c4632f38ab",
"caseURN": "SCRDID98447",
"defendants": [
{
"defendantId": "999176f4-3adc-4ea1-a808-26c4632f38ab",
"masterDefendantId": "1a9176f4-3adc-4ea1-a808-26c4632f38ab",
"personDefendant": {
"personDetails": {
"firstName": "Garfield",
"lastName": "Dare",
"dateOfBirth": "1998-08-23",
"address": { "address1": "59 Meadow Lane", "postcode": "B1 1AA" },
"contact": { "primaryEmail": "test@gmail.com" }
}
},
"offences": [
{ "convictionDate": "2025-11-09" }
]
}
],
"migrationSourceSystem": {
"migrationCaseStatus": "INACTIVE",
"migrationSourceSystemName": "XHIBIT",
"defendantFineAccountNumbers": [
{
"defendantId": "999176f4-3adc-4ea1-a808-26c4632f38ab",
"fineAccountNumber": "67890"
}
],
"migrationSourceSystemCaseIdentifier": "T20259999"
}
}
}
]
}
Loading
Loading