From b6dbe892c32b063667f8285bc8847651a4539278 Mon Sep 17 00:00:00 2001 From: vinay kumar Date: Tue, 28 Jul 2026 17:13:17 +0100 Subject: [PATCH 1/2] SNI-9205:Production Incident Fix - DT_missing co-defendants on PACFS. --- pom.xml | 2 +- progression-command/pom.xml | 2 +- .../progression-command-api/pom.xml | 2 +- .../progression-command-handler/pom.xml | 2 +- progression-domain/pom.xml | 2 +- .../progression-datatypes-common/pom.xml | 2 +- .../progression-domain-aggregate/pom.xml | 2 +- .../aggregate/HearingAggregate.java | 150 ++++++-- .../aggregate/HearingAggregateTest.java | 319 ++++++++++++++++++ .../progression-domain-common/pom.xml | 2 +- .../progression-domain-message/pom.xml | 2 +- progression-event-sources/pom.xml | 2 +- progression-event/pom.xml | 2 +- .../progression-event-indexer/pom.xml | 2 +- .../progression-event-listener/pom.xml | 2 +- .../progression-event-processor/pom.xml | 2 +- progression-eventprocessorstore/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- progression-healthchecks/pom.xml | 2 +- progression-integration-test/pom.xml | 2 +- progression-performance-test/pom.xml | 2 +- progression-query/pom.xml | 2 +- .../progression-query-api/pom.xml | 2 +- .../progression-query-view/pom.xml | 2 +- progression-refdata-service/pom.xml | 2 +- .../progression/service/RefDataService.java | 8 +- .../service/RefDataServiceTest.java | 12 + progression-service/pom.xml | 2 +- progression-test-utilities/pom.xml | 2 +- progression-viewstore/pom.xml | 2 +- .../progression-viewstore-liquibase/pom.xml | 2 +- .../progression-viewstore-persistence/pom.xml | 2 +- 33 files changed, 496 insertions(+), 51 deletions(-) diff --git a/pom.xml b/pom.xml index ff8378e52..4a37167ac 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT pom Progression services application diff --git a/progression-command/pom.xml b/progression-command/pom.xml index 1ee554379..f74cb6048 100644 --- a/progression-command/pom.xml +++ b/progression-command/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-command pom diff --git a/progression-command/progression-command-api/pom.xml b/progression-command/progression-command-api/pom.xml index 966d81948..c4bb922c7 100644 --- a/progression-command/progression-command-api/pom.xml +++ b/progression-command/progression-command-api/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-command - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-command-api war diff --git a/progression-command/progression-command-handler/pom.xml b/progression-command/progression-command-handler/pom.xml index 272d46106..1ee2912a1 100644 --- a/progression-command/progression-command-handler/pom.xml +++ b/progression-command/progression-command-handler/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-command - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-command-handler war diff --git a/progression-domain/pom.xml b/progression-domain/pom.xml index cb80fd99a..e7a7a63e5 100644 --- a/progression-domain/pom.xml +++ b/progression-domain/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-domain pom diff --git a/progression-domain/progression-datatypes-common/pom.xml b/progression-domain/progression-datatypes-common/pom.xml index 0839ebdb0..72b8f5afb 100644 --- a/progression-domain/progression-datatypes-common/pom.xml +++ b/progression-domain/progression-datatypes-common/pom.xml @@ -3,7 +3,7 @@ progression-domain uk.gov.moj.cpp.progression - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT 4.0.0 diff --git a/progression-domain/progression-domain-aggregate/pom.xml b/progression-domain/progression-domain-aggregate/pom.xml index 26317eab5..f2607d1be 100644 --- a/progression-domain/progression-domain-aggregate/pom.xml +++ b/progression-domain/progression-domain-aggregate/pom.xml @@ -3,7 +3,7 @@ progression-domain uk.gov.moj.cpp.progression - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT 4.0.0 progression-domain-aggregate diff --git a/progression-domain/progression-domain-aggregate/src/main/java/uk/gov/moj/cpp/progression/aggregate/HearingAggregate.java b/progression-domain/progression-domain-aggregate/src/main/java/uk/gov/moj/cpp/progression/aggregate/HearingAggregate.java index dcc4d0e40..b07f22850 100644 --- a/progression-domain/progression-domain-aggregate/src/main/java/uk/gov/moj/cpp/progression/aggregate/HearingAggregate.java +++ b/progression-domain/progression-domain-aggregate/src/main/java/uk/gov/moj/cpp/progression/aggregate/HearingAggregate.java @@ -125,7 +125,7 @@ @SuppressWarnings({"squid:S1948", "squid:S1172", "squid:S1188", "squid:S3655", "java:S6204"}) public class HearingAggregate implements Aggregate { private static final Logger LOGGER = LoggerFactory.getLogger(HearingAggregate.class); - private static final long serialVersionUID = 8888819367477517208L; + private static final long serialVersionUID = 8888819367477517209L; private final List listDefendantRequests = new ArrayList<>(); private final List applicationListingNeeds = new ArrayList<>(); private Hearing hearing; @@ -158,6 +158,7 @@ public class HearingAggregate implements Aggregate { // we need to know if offence was added hearing because the offence was added to case of the hearing. // The offence was not resulted from another hearing or not extended from another hearing. private final Set newOffences = new HashSet<>(); + private Set defendantsAddedToHearing = new HashSet<>(); private static final String GUILTY_VERDICT_STARTS_WITH = "GUILTY"; //changed GUILTY to address sonar issue : java:S1192 @@ -457,11 +458,13 @@ public Stream extendHearing(final HearingListingNeeds hearingListingNeed } public Stream enrichInitiateHearing(final Hearing hearing) { + final List mergedProsecutionCases = getMergedProsecutionCasesForEnrichInitiate(hearing); + if (!listDefendantRequests.isEmpty()) { final Hearing.Builder hearingBuilder = hearing(); - if (isNotEmpty(hearing.getProsecutionCases())) { - final List defendantIds = hearing.getProsecutionCases().stream() + if (isNotEmpty(mergedProsecutionCases)) { + final List defendantIds = mergedProsecutionCases.stream() .map(ProsecutionCase::getDefendants) .flatMap(Collection::stream) .map(Defendant::getId) @@ -495,7 +498,7 @@ public Stream enrichInitiateHearing(final Hearing hearing) { .withId(hearing.getId()) .withJudiciary(hearing.getJudiciary()) .withJurisdictionType(hearing.getJurisdictionType()) - .withProsecutionCases(hearing.getProsecutionCases()) + .withProsecutionCases(mergedProsecutionCases) .withCourtApplications(hearing.getCourtApplications()) .withProsecutionCounsels(hearing.getProsecutionCounsels()) .withReportingRestrictionReason(hearing.getReportingRestrictionReason()) @@ -514,12 +517,98 @@ public Stream enrichInitiateHearing(final Hearing hearing) { if (nonNull(this.hearing)) { enrichedHearingBuilder.withNumberOfGroupCases(this.hearing.getNumberOfGroupCases()); + enrichedHearingBuilder.withProsecutionCases(mergedProsecutionCases); } final Hearing enrichedHearing = enrichedHearingBuilder.build(); addNewOffencesToHearing(enrichedHearing); return apply(Stream.of(HearingInitiateEnriched.hearingInitiateEnriched().withHearing(enrichedHearing).build())); } + private List getMergedProsecutionCasesForEnrichInitiate(final Hearing enrichCommandHearing) { + if (isNull(this.hearing) || isEmpty(this.hearing.getProsecutionCases())) { + return enrichCommandHearing.getProsecutionCases(); + } + if (isEmpty(enrichCommandHearing.getProsecutionCases())) { + return this.hearing.getProsecutionCases(); + } + return mergeProsecutionCasesForEnrichInitiate(enrichCommandHearing.getProsecutionCases()); + } + + private List mergeProsecutionCasesForEnrichInitiate(final List payloadProsecutionCases) { + final List resultCases = new ArrayList<>(); + final Set processedCaseIds = new HashSet<>(); + + payloadProsecutionCases.forEach(payloadCase -> { + final Optional caseInHearingOptional = this.hearing.getProsecutionCases().stream() + .filter(hearingCase -> hearingCase.getId().equals(payloadCase.getId())) + .findFirst(); + if (caseInHearingOptional.isPresent()) { + resultCases.add(getMergedProsecutionForEnrichInitiate(caseInHearingOptional.get(), payloadCase)); + } else { + resultCases.add(ProsecutionCase.prosecutionCase().withValuesFrom(payloadCase).build()); + } + processedCaseIds.add(payloadCase.getId()); + }); + + this.hearing.getProsecutionCases().stream() + .filter(hearingCase -> !processedCaseIds.contains(hearingCase.getId())) + .forEach(hearingCase -> resultCases.add(ProsecutionCase.prosecutionCase().withValuesFrom(hearingCase).build())); + + return resultCases; + } + + private ProsecutionCase getMergedProsecutionForEnrichInitiate(final ProsecutionCase caseInHearing, final ProsecutionCase caseInPayload) { + final List defendantResult = new ArrayList<>(); + final Set processedDefendantIds = new HashSet<>(); + + caseInPayload.getDefendants().forEach(payloadDefendant -> { + final Optional defInHearingCaseOptional = caseInHearing.getDefendants().stream() + .filter(hearingDef -> hearingDef.getId().equals(payloadDefendant.getId())) + .findFirst(); + if (defInHearingCaseOptional.isPresent()) { + defendantResult.add(getMergedDefendantForEnrichInitiate(defInHearingCaseOptional.get(), payloadDefendant)); + } else { + defendantResult.add(Defendant.defendant().withValuesFrom(payloadDefendant).build()); + } + processedDefendantIds.add(payloadDefendant.getId()); + }); + + caseInHearing.getDefendants().stream() + .filter(hearingDef -> !processedDefendantIds.contains(hearingDef.getId())) + .filter(this::isDefendantAddedToHearingAfterListing) + .forEach(hearingDef -> defendantResult.add(Defendant.defendant().withValuesFrom(hearingDef).build())); + + return ProsecutionCase.prosecutionCase().withValuesFrom(caseInPayload).withDefendants(defendantResult).build(); + } + + private Defendant getMergedDefendantForEnrichInitiate(final Defendant defendantInHearingCase, final Defendant defendantInPayloadCase) { + final List offenceResult = new ArrayList<>(); + final Set processedOffenceIds = new HashSet<>(); + + ofNullable(defendantInPayloadCase.getOffences()).orElse(emptyList()).forEach(payloadOffence -> { + final Offence mergedOffence = ofNullable(defendantInHearingCase.getOffences()).orElse(emptyList()).stream() + .filter(hearingOffence -> hearingOffence.getId().equals(payloadOffence.getId())) + .findFirst() + .map(hearingOffence -> Offence.offence().withValuesFrom(hearingOffence).withValuesFrom(payloadOffence).build()) + .orElseGet(() -> Offence.offence().withValuesFrom(payloadOffence).build()); + offenceResult.add(mergedOffence); + processedOffenceIds.add(payloadOffence.getId()); + }); + + ofNullable(defendantInHearingCase.getOffences()).orElse(emptyList()).stream() + .filter(hearingOffence -> !processedOffenceIds.contains(hearingOffence.getId())) + .filter(this::isOffenceAddedToHearingAfterListing) + .forEach(hearingOffence -> offenceResult.add(Offence.offence().withValuesFrom(hearingOffence).build())); + + final Defendant.Builder builder = Defendant.defendant() + .withValuesFrom(defendantInPayloadCase) + .withOffences(offenceResult); + if (isNull(defendantInPayloadCase.getIsYouth()) && nonNull(defendantInHearingCase.getIsYouth())) { + builder.withIsYouth(defendantInHearingCase.getIsYouth()); + } + return builder.build(); + } + public Stream createHearingForApplication(final Hearing hearing, final HearingListingStatus hearingListingStatus, final List listHearingRequests) { final HearingForApplicationCreatedV2.Builder hearingForApplicationCreated = HearingForApplicationCreatedV2.hearingForApplicationCreatedV2(); LOGGER.info("Hearing with id {} and the status: {}", hearing.getId(), hearingListingStatus); @@ -2065,27 +2154,30 @@ public Stream updateRelatedHearingForAdhocHearing(final HearingListingNe */ private Set getProsecutionCasesAfterMergeAtDifferentLevel(HearingListingNeeds hearingListingNeeds, final Set resultCases) { if (nonNull(this.hearing.getProsecutionCases()) && nonNull(hearingListingNeeds.getProsecutionCases())) { + return mergeProsecutionCasesWithAggregateState(hearingListingNeeds.getProsecutionCases(), resultCases); + } + return resultCases; + } - // Collects combined set of case Ids - final Set combinedSetOfCaseIds = hearingListingNeeds.getProsecutionCases().stream().map(ProsecutionCase::getId).collect(Collectors.toSet()); - combinedSetOfCaseIds.addAll(this.hearing.getProsecutionCases().stream().map(ProsecutionCase::getId).collect(Collectors.toSet())); + private Set mergeProsecutionCasesWithAggregateState(final List payloadProsecutionCases, + final Set resultCases) { + final Set combinedSetOfCaseIds = payloadProsecutionCases.stream().map(ProsecutionCase::getId).collect(Collectors.toSet()); + combinedSetOfCaseIds.addAll(this.hearing.getProsecutionCases().stream().map(ProsecutionCase::getId).collect(Collectors.toSet())); - combinedSetOfCaseIds.stream().forEach(caseId -> { - final Optional caseInHearingOptional = this.hearing.getProsecutionCases().stream().filter(hearingCase -> hearingCase.getId().equals(caseId)).findFirst(); - final Optional caseInPayloadOptional = hearingListingNeeds.getProsecutionCases().stream().filter(payloadCase -> payloadCase.getId().equals(caseId)).findFirst(); + combinedSetOfCaseIds.forEach(caseId -> { + final Optional caseInHearingOptional = this.hearing.getProsecutionCases().stream().filter(hearingCase -> hearingCase.getId().equals(caseId)).findFirst(); + final Optional caseInPayloadOptional = payloadProsecutionCases.stream().filter(payloadCase -> payloadCase.getId().equals(caseId)).findFirst(); - if (caseInHearingOptional.isPresent()) { - if (caseInPayloadOptional.isPresent()) { - final ProsecutionCase mergedProsecutionCase = getMergedProsecutionFromPayloadAndHearing(caseInHearingOptional.get(), caseInPayloadOptional.get()); - resultCases.add(mergedProsecutionCase); - } else { - resultCases.add(ProsecutionCase.prosecutionCase().withValuesFrom(caseInHearingOptional.get()).build()); - } + if (caseInHearingOptional.isPresent()) { + if (caseInPayloadOptional.isPresent()) { + resultCases.add(getMergedProsecutionFromPayloadAndHearing(caseInHearingOptional.get(), caseInPayloadOptional.get())); } else { - resultCases.add(ProsecutionCase.prosecutionCase().withValuesFrom(caseInPayloadOptional.get()).build()); + resultCases.add(ProsecutionCase.prosecutionCase().withValuesFrom(caseInHearingOptional.get()).build()); } - }); - } + } else { + resultCases.add(ProsecutionCase.prosecutionCase().withValuesFrom(caseInPayloadOptional.get()).build()); + } + }); return resultCases; } @@ -3179,11 +3271,29 @@ private Offence getOffenceWithAdjourned(final Offence offence) { } public void addNewDefendant(final NewDefendantAddedToHearing newDefendantAddedToHearing) { + newDefendantAddedToHearing.getDefendants().forEach(defendant -> defendantsAddedToHearingSet().add(defendant.getId())); this.hearing.getProsecutionCases().stream().filter(prosecutionCase -> prosecutionCase.getId().equals(newDefendantAddedToHearing.getProsecutionCaseId())) .forEach(prosecutionCase -> prosecutionCase.getDefendants().addAll(newDefendantAddedToHearing.getDefendants())); } + private Set defendantsAddedToHearingSet() { + if (isNull(defendantsAddedToHearing)) { + defendantsAddedToHearing = new HashSet<>(); + } + return defendantsAddedToHearing; + } + + private boolean isDefendantAddedToHearingAfterListing(final Defendant defendant) { + return defendantsAddedToHearingSet().contains(defendant.getId()); + } + + private boolean isOffenceAddedToHearingAfterListing(final Offence offence) { + return newOffences.contains(offence.getId()) || addedOffencesMovedToHearings.stream() + .flatMap(addedOffencesMovedToHearing -> addedOffencesMovedToHearing.getNewOffences().stream()) + .anyMatch(newOffence -> newOffence.getId().equals(offence.getId())); + } + public HearingType getHearingType() { return hearing.getType(); } diff --git a/progression-domain/progression-domain-aggregate/src/test/java/uk/gov/moj/cpp/progression/aggregate/HearingAggregateTest.java b/progression-domain/progression-domain-aggregate/src/test/java/uk/gov/moj/cpp/progression/aggregate/HearingAggregateTest.java index a0d4f09a9..3b07bf9e6 100644 --- a/progression-domain/progression-domain-aggregate/src/test/java/uk/gov/moj/cpp/progression/aggregate/HearingAggregateTest.java +++ b/progression-domain/progression-domain-aggregate/src/test/java/uk/gov/moj/cpp/progression/aggregate/HearingAggregateTest.java @@ -4914,6 +4914,325 @@ public void shouldEnrichInitiateHearingWhenHearingDefendantRequestIsPresent() { assertThat(events.get(0), Matchers.instanceOf(HearingInitiateEnriched.class)); } + @Test + public void shouldNotLoseDefendantAddedToHearingWhenHearingInitiateEnrichedUsesStalePayload() { + final UUID hearingId = randomUUID(); + final UUID prosecutionCaseId = randomUUID(); + final UUID firstDefendantId = randomUUID(); + final UUID secondDefendantId = randomUUID(); + final UUID firstOffenceId = randomUUID(); + final UUID secondOffenceId = randomUUID(); + + hearingAggregate.createHearingDefendantRequest(singletonList(ListDefendantRequest.listDefendantRequest() + .withDefendantId(firstDefendantId) + .withProsecutionCaseId(prosecutionCaseId) + .build())).collect(toList()); + + final Hearing hearingWithFirstDefendantOnly = Hearing.hearing() + .withId(hearingId) + .withJurisdictionType(JurisdictionType.MAGISTRATES) + .withHearingLanguage(HearingLanguage.ENGLISH) + .withHasSharedResults(false) + .withHearingDays(singletonList(HearingDay.hearingDay().withSittingDay(ZonedDateTime.now()).build())) + .withType(HearingType.hearingType().withDescription("First hearing").build()) + .withCourtCentre(CourtCentre.courtCentre().withCode("B30PG00").build()) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(singletonList(Defendant.defendant() + .withId(firstDefendantId) + .withIsYouth(false) + .withOffences(new ArrayList<>(singletonList(Offence.offence() + .withId(firstOffenceId) + .withListingNumber(1) + .build()))) + .build()))) + .build()))) + .build(); + + hearingAggregate.apply(ProsecutionCaseDefendantListingStatusChangedV2.prosecutionCaseDefendantListingStatusChangedV2() + .withHearing(hearingWithFirstDefendantOnly) + .withHearingListingStatus(HearingListingStatus.SENT_FOR_LISTING) + .build()); + + hearingAggregate.createHearingDefendantRequest(singletonList(ListDefendantRequest.listDefendantRequest() + .withDefendantId(secondDefendantId) + .withProsecutionCaseId(prosecutionCaseId) + .build())).collect(toList()); + + final Defendant secondDefendant = Defendant.defendant() + .withId(secondDefendantId) + .withIsYouth(false) + .withOffences(new ArrayList<>(singletonList(Offence.offence() + .withId(secondOffenceId) + .withListingNumber(1) + .build()))) + .build(); + hearingAggregate.addDefendant(hearingId, prosecutionCaseId, singletonList(secondDefendant)).collect(toList()); + + assertThat(hearingAggregate.getHearing().getProsecutionCases().get(0).getDefendants().size(), is(2)); + + final Hearing staleEnrichedHearingFromCommand = Hearing.hearing() + .withValuesFrom(hearingWithFirstDefendantOnly) + .build(); + + final List enrichEvents = hearingAggregate.enrichInitiateHearing(staleEnrichedHearingFromCommand).collect(toList()); + assertThat(enrichEvents.get(0), instanceOf(HearingInitiateEnriched.class)); + + final HearingInitiateEnriched hearingInitiateEnriched = (HearingInitiateEnriched) enrichEvents.get(0); + + assertThat(hearingAggregate.getHearing().getProsecutionCases().get(0).getDefendants().size(), is(2)); + assertThat(hearingInitiateEnriched.getHearing().getProsecutionCases().get(0).getDefendants().size(), is(2)); + + final List probationEvents = hearingAggregate.populateHearingToProbationCaseWorker() + .map(HearingPopulatedToProbationCaseworker.class::cast) + .collect(toList()); + + assertThat(probationEvents.get(0).getHearing().getProsecutionCases().get(0).getDefendants().size(), is(2)); + } + + @Test + public void shouldPreserveOffenceOrderWhenEnrichInitiateHearingMergesAggregateOffencesWithStalePayload() { + final UUID hearingId = randomUUID(); + final UUID prosecutionCaseId = randomUUID(); + final UUID defendantId = randomUUID(); + final UUID firstOffenceId = UUID.fromString("3789ab16-0bb7-4ef1-87ef-c936bf0364f1"); + final UUID secondOffenceId = UUID.fromString("4789ab16-0bb7-4ef1-87ef-c936bf0364f1"); + + final Hearing hearingWithTwoOffences = Hearing.hearing() + .withId(hearingId) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(singletonList(Defendant.defendant() + .withId(defendantId) + .withOffences(new ArrayList<>(asList( + Offence.offence().withId(firstOffenceId).build(), + Offence.offence().withId(secondOffenceId).build()))) + .build()))) + .build()))) + .build(); + + hearingAggregate.apply(ProsecutionCaseDefendantListingStatusChangedV2.prosecutionCaseDefendantListingStatusChangedV2() + .withHearing(hearingWithTwoOffences) + .withHearingListingStatus(HearingListingStatus.SENT_FOR_LISTING) + .build()); + + hearingAggregate.getNewOffences().add(secondOffenceId); + + final Hearing staleEnrichedHearingFromCommand = Hearing.hearing() + .withId(hearingId) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(singletonList(Defendant.defendant() + .withId(defendantId) + .withOffences(new ArrayList<>(singletonList(Offence.offence().withId(firstOffenceId).build()))) + .build()))) + .build()))) + .build(); + + final List enrichEvents = hearingAggregate.enrichInitiateHearing(staleEnrichedHearingFromCommand).collect(toList()); + final HearingInitiateEnriched hearingInitiateEnriched = (HearingInitiateEnriched) enrichEvents.get(0); + final List offences = hearingInitiateEnriched.getHearing().getProsecutionCases().get(0).getDefendants().get(0).getOffences(); + + assertThat(offences.size(), is(2)); + assertThat(offences.get(0).getId(), is(firstOffenceId)); + assertThat(offences.get(1).getId(), is(secondOffenceId)); + } + + @Test + public void shouldNotReAddListedDefendantWhenEnrichInitiateHearingUsesPartialConfirmPayload() { + final UUID hearingId = randomUUID(); + final UUID prosecutionCaseId = randomUUID(); + final UUID confirmedDefendantId = randomUUID(); + final UUID unconfirmedDefendantId = randomUUID(); + + final Hearing hearingWithTwoDefendants = Hearing.hearing() + .withId(hearingId) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(asList( + Defendant.defendant().withId(confirmedDefendantId).withOffences(new ArrayList<>()).build(), + Defendant.defendant().withId(unconfirmedDefendantId).withOffences(new ArrayList<>()).build()))) + .build()))) + .build(); + + hearingAggregate.apply(ProsecutionCaseDefendantListingStatusChangedV2.prosecutionCaseDefendantListingStatusChangedV2() + .withHearing(hearingWithTwoDefendants) + .withHearingListingStatus(HearingListingStatus.SENT_FOR_LISTING) + .build()); + + final Hearing partialConfirmPayload = Hearing.hearing() + .withId(hearingId) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(singletonList(Defendant.defendant() + .withId(confirmedDefendantId) + .withOffences(new ArrayList<>()) + .build()))) + .build()))) + .build(); + + final List enrichEvents = hearingAggregate.enrichInitiateHearing(partialConfirmPayload).collect(toList()); + final HearingInitiateEnriched hearingInitiateEnriched = (HearingInitiateEnriched) enrichEvents.get(0); + final List defendants = hearingInitiateEnriched.getHearing().getProsecutionCases().get(0).getDefendants(); + + assertThat(defendants.size(), is(1)); + assertThat(defendants.get(0).getId(), is(confirmedDefendantId)); + } + + @Test + public void shouldNotReAddListedOffenceWhenEnrichInitiateHearingUsesPartialConfirmPayload() { + final UUID hearingId = randomUUID(); + final UUID prosecutionCaseId = randomUUID(); + final UUID defendantId = randomUUID(); + final UUID confirmedOffenceId = UUID.fromString("3789ab16-0bb7-4ef1-87ef-c936bf0364f1"); + final UUID unconfirmedOffenceId = UUID.fromString("4789ab16-0bb7-4ef1-87ef-c936bf0364f1"); + + final Hearing hearingWithTwoOffences = Hearing.hearing() + .withId(hearingId) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(singletonList(Defendant.defendant() + .withId(defendantId) + .withOffences(new ArrayList<>(asList( + Offence.offence().withId(confirmedOffenceId).withListingNumber(1).build(), + Offence.offence().withId(unconfirmedOffenceId).build()))) + .build()))) + .build()))) + .build(); + + hearingAggregate.apply(ProsecutionCaseDefendantListingStatusChangedV2.prosecutionCaseDefendantListingStatusChangedV2() + .withHearing(hearingWithTwoOffences) + .withHearingListingStatus(HearingListingStatus.SENT_FOR_LISTING) + .build()); + + final Hearing partialConfirmPayload = Hearing.hearing() + .withId(hearingId) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(singletonList(Defendant.defendant() + .withId(defendantId) + .withOffences(new ArrayList<>(singletonList(Offence.offence() + .withId(confirmedOffenceId) + .withListingNumber(1) + .build()))) + .build()))) + .build()))) + .build(); + + final List enrichEvents = hearingAggregate.enrichInitiateHearing(partialConfirmPayload).collect(toList()); + final HearingInitiateEnriched hearingInitiateEnriched = (HearingInitiateEnriched) enrichEvents.get(0); + final List offences = hearingInitiateEnriched.getHearing().getProsecutionCases().get(0).getDefendants().get(0).getOffences(); + + assertThat(offences.size(), is(1)); + assertThat(offences.get(0).getId(), is(confirmedOffenceId)); + assertThat(offences.get(0).getListingNumber(), is(1)); + } + + @Test + public void shouldPreferPayloadListingNumberWhenEnrichInitiateHearingMergesSharedOffence() { + final UUID hearingId = randomUUID(); + final UUID prosecutionCaseId = randomUUID(); + final UUID defendantId = randomUUID(); + final UUID confirmedOffenceId = UUID.fromString("3789ab16-0bb7-4ef1-87ef-c936bf0364f1"); + final UUID unconfirmedOffenceId = UUID.fromString("4789ab16-0bb7-4ef1-87ef-c936bf0364f1"); + + final Hearing hearingWithTwoOffences = Hearing.hearing() + .withId(hearingId) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(singletonList(Defendant.defendant() + .withId(defendantId) + .withOffences(new ArrayList<>(asList( + Offence.offence().withId(confirmedOffenceId).withListingNumber(2).build(), + Offence.offence().withId(unconfirmedOffenceId).build()))) + .build()))) + .build()))) + .build(); + + hearingAggregate.apply(ProsecutionCaseDefendantListingStatusChangedV2.prosecutionCaseDefendantListingStatusChangedV2() + .withHearing(hearingWithTwoOffences) + .withHearingListingStatus(HearingListingStatus.SENT_FOR_LISTING) + .build()); + + final Hearing partialConfirmPayload = Hearing.hearing() + .withId(hearingId) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(singletonList(Defendant.defendant() + .withId(defendantId) + .withOffences(new ArrayList<>(singletonList(Offence.offence() + .withId(confirmedOffenceId) + .withListingNumber(1) + .build()))) + .build()))) + .build()))) + .build(); + + final List enrichEvents = hearingAggregate.enrichInitiateHearing(partialConfirmPayload).collect(toList()); + final HearingInitiateEnriched hearingInitiateEnriched = (HearingInitiateEnriched) enrichEvents.get(0); + final List offences = hearingInitiateEnriched.getHearing().getProsecutionCases().get(0).getDefendants().get(0).getOffences(); + + assertThat(offences.size(), is(1)); + assertThat(offences.get(0).getId(), is(confirmedOffenceId)); + assertThat(offences.get(0).getListingNumber(), is(1)); + } + + @Test + public void shouldPreserveOffenceOrderWhenEnrichInitiateHearingUsesAddedOffencesMovedToHearingEvent() { + final UUID hearingId = randomUUID(); + final UUID prosecutionCaseId = randomUUID(); + final UUID defendantId = randomUUID(); + final UUID firstOffenceId = UUID.fromString("3789ab16-0bb7-4ef1-87ef-c936bf0364f1"); + final UUID secondOffenceId = UUID.fromString("4789ab16-0bb7-4ef1-87ef-c936bf0364f1"); + + final Hearing hearingWithTwoOffences = Hearing.hearing() + .withId(hearingId) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(singletonList(Defendant.defendant() + .withId(defendantId) + .withOffences(new ArrayList<>(asList( + Offence.offence().withId(firstOffenceId).build(), + Offence.offence().withId(secondOffenceId).build()))) + .build()))) + .build()))) + .build(); + + hearingAggregate.apply(ProsecutionCaseDefendantListingStatusChangedV2.prosecutionCaseDefendantListingStatusChangedV2() + .withHearing(hearingWithTwoOffences) + .withHearingListingStatus(HearingListingStatus.SENT_FOR_LISTING) + .build()); + + hearingAggregate.apply(AddedOffencesMovedToHearing.addedOffencesMovedToHearing() + .withHearingId(hearingId) + .withCaseId(prosecutionCaseId) + .withDefendantId(defendantId) + .withIsHearingInitiateEnriched(false) + .withNewOffences(singletonList(Offence.offence().withId(secondOffenceId).build())) + .build()); + + assertThat(hearingAggregate.getNewOffences().contains(secondOffenceId), is(true)); + + final Hearing staleEnrichedHearingFromCommand = Hearing.hearing() + .withId(hearingId) + .withProsecutionCases(new ArrayList<>(singletonList(ProsecutionCase.prosecutionCase() + .withId(prosecutionCaseId) + .withDefendants(new ArrayList<>(singletonList(Defendant.defendant() + .withId(defendantId) + .withOffences(new ArrayList<>(singletonList(Offence.offence().withId(firstOffenceId).build()))) + .build()))) + .build()))) + .build(); + + final List enrichEvents = hearingAggregate.enrichInitiateHearing(staleEnrichedHearingFromCommand).collect(toList()); + final HearingInitiateEnriched hearingInitiateEnriched = (HearingInitiateEnriched) enrichEvents.get(0); + final List offences = hearingInitiateEnriched.getHearing().getProsecutionCases().get(0).getDefendants().get(0).getOffences(); + + assertThat(offences.size(), is(2)); + assertThat(offences.get(0).getId(), is(firstOffenceId)); + assertThat(offences.get(1).getId(), is(secondOffenceId)); + } + @Test public void shouldUpdateDefendant(){ final Hearing hearing = CoreTestTemplates.hearing(defaultArguments() diff --git a/progression-domain/progression-domain-common/pom.xml b/progression-domain/progression-domain-common/pom.xml index 223459f0d..82ff546ce 100644 --- a/progression-domain/progression-domain-common/pom.xml +++ b/progression-domain/progression-domain-common/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-domain - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-domain-common diff --git a/progression-domain/progression-domain-message/pom.xml b/progression-domain/progression-domain-message/pom.xml index 35a80b77a..a5175f7fb 100644 --- a/progression-domain/progression-domain-message/pom.xml +++ b/progression-domain/progression-domain-message/pom.xml @@ -4,7 +4,7 @@ uk.gov.moj.cpp.progression progression-domain - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-domain-message diff --git a/progression-event-sources/pom.xml b/progression-event-sources/pom.xml index c582bcafb..834dc6cd4 100644 --- a/progression-event-sources/pom.xml +++ b/progression-event-sources/pom.xml @@ -3,7 +3,7 @@ progression-parent uk.gov.moj.cpp.progression - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT 4.0.0 diff --git a/progression-event/pom.xml b/progression-event/pom.xml index c9d8d6af4..ddcec9954 100644 --- a/progression-event/pom.xml +++ b/progression-event/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-event pom diff --git a/progression-event/progression-event-indexer/pom.xml b/progression-event/progression-event-indexer/pom.xml index 68a454f8e..29f9f2787 100644 --- a/progression-event/progression-event-indexer/pom.xml +++ b/progression-event/progression-event-indexer/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-event - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-event-indexer war diff --git a/progression-event/progression-event-listener/pom.xml b/progression-event/progression-event-listener/pom.xml index 56b55b620..879478be6 100644 --- a/progression-event/progression-event-listener/pom.xml +++ b/progression-event/progression-event-listener/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-event - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-event-listener war diff --git a/progression-event/progression-event-processor/pom.xml b/progression-event/progression-event-processor/pom.xml index 714a6f212..f3bc2ebbe 100644 --- a/progression-event/progression-event-processor/pom.xml +++ b/progression-event/progression-event-processor/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-event - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-event-processor war diff --git a/progression-eventprocessorstore/pom.xml b/progression-eventprocessorstore/pom.xml index 9c2ea8567..42ed8838a 100644 --- a/progression-eventprocessorstore/pom.xml +++ b/progression-eventprocessorstore/pom.xml @@ -3,7 +3,7 @@ progression-parent uk.gov.moj.cpp.progression - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT 4.0.0 progression-eventprocessorstore diff --git a/progression-eventprocessorstore/progression-eventprocessorstore-liquibase/pom.xml b/progression-eventprocessorstore/progression-eventprocessorstore-liquibase/pom.xml index ee7b4da6c..036b9b6bd 100644 --- a/progression-eventprocessorstore/progression-eventprocessorstore-liquibase/pom.xml +++ b/progression-eventprocessorstore/progression-eventprocessorstore-liquibase/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-eventprocessorstore - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT 4.0.0 progression-eventprocessorstore-liquibase diff --git a/progression-eventprocessorstore/progression-eventprocessorstore-persistence/pom.xml b/progression-eventprocessorstore/progression-eventprocessorstore-persistence/pom.xml index 293c6dd58..56875c4f5 100644 --- a/progression-eventprocessorstore/progression-eventprocessorstore-persistence/pom.xml +++ b/progression-eventprocessorstore/progression-eventprocessorstore-persistence/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-eventprocessorstore - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT 4.0.0 progression-eventprocessorstore-persistence diff --git a/progression-healthchecks/pom.xml b/progression-healthchecks/pom.xml index d00a57076..dd594dda6 100644 --- a/progression-healthchecks/pom.xml +++ b/progression-healthchecks/pom.xml @@ -3,7 +3,7 @@ progression-parent uk.gov.moj.cpp.progression - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT 4.0.0 diff --git a/progression-integration-test/pom.xml b/progression-integration-test/pom.xml index a7f52bf41..dba556e53 100644 --- a/progression-integration-test/pom.xml +++ b/progression-integration-test/pom.xml @@ -4,7 +4,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT false diff --git a/progression-performance-test/pom.xml b/progression-performance-test/pom.xml index b45706da0..26405d71e 100644 --- a/progression-performance-test/pom.xml +++ b/progression-performance-test/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT 4.0.0 diff --git a/progression-query/pom.xml b/progression-query/pom.xml index 01175cae6..b031eef8a 100644 --- a/progression-query/pom.xml +++ b/progression-query/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-query pom diff --git a/progression-query/progression-query-api/pom.xml b/progression-query/progression-query-api/pom.xml index 266666923..5851715c3 100644 --- a/progression-query/progression-query-api/pom.xml +++ b/progression-query/progression-query-api/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-query - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-query-api war diff --git a/progression-query/progression-query-view/pom.xml b/progression-query/progression-query-view/pom.xml index 0246d4fcd..43dfa139f 100644 --- a/progression-query/progression-query-view/pom.xml +++ b/progression-query/progression-query-view/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-query - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-query-view jar diff --git a/progression-refdata-service/pom.xml b/progression-refdata-service/pom.xml index 72dc77cd0..436922320 100644 --- a/progression-refdata-service/pom.xml +++ b/progression-refdata-service/pom.xml @@ -7,7 +7,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT diff --git a/progression-refdata-service/src/main/java/uk/gov/moj/cpp/progression/service/RefDataService.java b/progression-refdata-service/src/main/java/uk/gov/moj/cpp/progression/service/RefDataService.java index 755ed88ec..d75063f72 100644 --- a/progression-refdata-service/src/main/java/uk/gov/moj/cpp/progression/service/RefDataService.java +++ b/progression-refdata-service/src/main/java/uk/gov/moj/cpp/progression/service/RefDataService.java @@ -716,10 +716,14 @@ public Optional getProsecutorByProsecutionAuthority(final String pro .build(); final Envelope response = requester.requestAsAdmin(envelopeFrom(metadata, payload), JsonObject.class); - if (isNull(response.payload()) || response.payload().getJsonArray("prosecutors").isEmpty()) { + if (isNull(response) || isNull(response.payload())) { return Optional.empty(); } - return ofNullable(response.payload().getJsonArray("prosecutors").getJsonObject(0)); + final JsonArray prosecutors = response.payload().getJsonArray("prosecutors"); + if (isNull(prosecutors) || prosecutors.isEmpty()) { + return Optional.empty(); + } + return ofNullable(prosecutors.getJsonObject(0)); } public String getCountryByPostcode(final JsonEnvelope envelope, final String postCode, final Requester requester) { diff --git a/progression-refdata-service/src/test/java/uk/gov/moj/cpp/progression/service/RefDataServiceTest.java b/progression-refdata-service/src/test/java/uk/gov/moj/cpp/progression/service/RefDataServiceTest.java index 5d5913ec5..845eabf68 100644 --- a/progression-refdata-service/src/test/java/uk/gov/moj/cpp/progression/service/RefDataServiceTest.java +++ b/progression-refdata-service/src/test/java/uk/gov/moj/cpp/progression/service/RefDataServiceTest.java @@ -540,6 +540,18 @@ public void shouldGetEmptyPleaTypeByValue() throws Exception { assertThat(result.isPresent(), is(false)); } + @Test + public void shouldReturnEmptyWhenProsecutorsArrayIsMissingFromRefDataResponse() { + final Envelope envelope = envelopeFrom( + Envelope.metadataBuilder().withId(UUID.randomUUID()).withName("name").build(), + createObjectBuilder().build()); + + when(requester.requestAsAdmin(any(), eq(JsonObject.class))).thenReturn(envelope); + + assertThat(refDataService.getProsecutorByProsecutionAuthority("TFL", requester).isPresent(), is(false)); + assertThat(refDataService.getPoliceFlag(null, "TFL", requester), is(false)); + } + @Test public void shouldGetPetFormData() { diff --git a/progression-service/pom.xml b/progression-service/pom.xml index 42813ddbe..fd01c4a6b 100644 --- a/progression-service/pom.xml +++ b/progression-service/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT 4.0.0 diff --git a/progression-test-utilities/pom.xml b/progression-test-utilities/pom.xml index a720f5cad..4bd7ac13b 100644 --- a/progression-test-utilities/pom.xml +++ b/progression-test-utilities/pom.xml @@ -7,7 +7,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT diff --git a/progression-viewstore/pom.xml b/progression-viewstore/pom.xml index 2315ba386..642cc3f53 100644 --- a/progression-viewstore/pom.xml +++ b/progression-viewstore/pom.xml @@ -3,7 +3,7 @@ uk.gov.moj.cpp.progression progression-parent - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-viewstore pom diff --git a/progression-viewstore/progression-viewstore-liquibase/pom.xml b/progression-viewstore/progression-viewstore-liquibase/pom.xml index 00a305229..db4402034 100644 --- a/progression-viewstore/progression-viewstore-liquibase/pom.xml +++ b/progression-viewstore/progression-viewstore-liquibase/pom.xml @@ -4,7 +4,7 @@ uk.gov.moj.cpp.progression progression-viewstore - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-viewstore-liquibase diff --git a/progression-viewstore/progression-viewstore-persistence/pom.xml b/progression-viewstore/progression-viewstore-persistence/pom.xml index 2cada01f7..a719c807b 100644 --- a/progression-viewstore/progression-viewstore-persistence/pom.xml +++ b/progression-viewstore/progression-viewstore-persistence/pom.xml @@ -4,7 +4,7 @@ uk.gov.moj.cpp.progression progression-viewstore - 17.0.280-SNAPSHOT + 17.0.280-REL-3RDLINE-2620-SNAPSHOT progression-viewstore-persistence From 14adada4b06fbf032c8eacd89ab3e90bf5e323e2 Mon Sep 17 00:00:00 2001 From: vinay kumar Date: Tue, 28 Jul 2026 17:37:52 +0100 Subject: [PATCH 2/2] Chaning heairng and referencedata version --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4a37167ac..dd8239fb7 100644 --- a/pom.xml +++ b/pom.xml @@ -66,9 +66,9 @@ 17.0.75 1.0.6 6.4.1 - 17.104.136 + 17.104.137 17.104.3 - 17.104.176 + 17.104.182 17.104.50 17.104.102 17.104.48