diff --git a/build.gradle.kts b/build.gradle.kts index 820ab40b..9788f47e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ plugins { } group = "uk.nhs.hee.trainee.details" -version = "1.3.0" +version = "1.3.1" configurations { compileOnly { diff --git a/src/main/java/uk/nhs/hee/trainee/details/service/NtnGenerator.java b/src/main/java/uk/nhs/hee/trainee/details/service/NtnGenerator.java index 8d2f411a..6318a99c 100644 --- a/src/main/java/uk/nhs/hee/trainee/details/service/NtnGenerator.java +++ b/src/main/java/uk/nhs/hee/trainee/details/service/NtnGenerator.java @@ -138,8 +138,7 @@ private String getSouthWestParentOrganization(ProgrammeMembership programmeMembe */ private String getSpecialtyConcat(ProgrammeMembership programmeMembership) { log.info("Calculating specialty concat."); - List curricula = programmeMembership.getCurricula(); - List sortedCurricula = filterAndSortCurricula(curricula); + List sortedCurricula = filterAndSortCurricula(programmeMembership); StringBuilder sb = new StringBuilder(); @@ -199,8 +198,7 @@ private String getSuffix(ProgrammeMembership programmeMembership) { case "CCT" -> "C"; case "CESR" -> "CP"; default -> { - List curricula = programmeMembership.getCurricula(); - List sortedCurricula = filterAndSortCurricula(curricula); + List sortedCurricula = filterAndSortCurricula(programmeMembership); String firstSpecialtyCode = sortedCurricula.get(0).getCurriculumSpecialtyCode(); log.info("Using specialty code '{}' to calculate suffix.", trainingPathway); @@ -213,19 +211,21 @@ private String getSuffix(ProgrammeMembership programmeMembership) { } /** - * Filter the given curricula to only those that are current and sort them alphanumerically. + * Filter a programme membership's curricula and sort them alphanumerically. * - * @param curricula The curricula to filter and sort. - * @return The current curricula, sorted alphanumerically by subtype and code. + * @param programmeMembership The programme membership to filter and sort the curricula of. + * @return The NTN valid curricula for this PM, sorted alphanumerically by subtype and code. */ - private List filterAndSortCurricula(List curricula) { + private List filterAndSortCurricula(ProgrammeMembership programmeMembership) { + LocalDate startDate = programmeMembership.getStartDate(); LocalDate now = LocalDate.now(); + LocalDate filterDate = startDate.isAfter(now) ? startDate : now; - return curricula.stream() + return programmeMembership.getCurricula().stream() .filter(c -> c.getCurriculumSpecialtyCode() != null && !c.getCurriculumSpecialtyCode().isBlank()) - .filter(c -> c.getCurriculumStartDate().isBefore(now)) - .filter(c -> c.getCurriculumEndDate().isAfter(now)) + .filter(c -> !c.getCurriculumStartDate().isAfter(filterDate)) + .filter(c -> !c.getCurriculumEndDate().isBefore(filterDate)) .sorted(Comparator .comparing(Curriculum::getCurriculumSubType) .reversed() @@ -287,7 +287,7 @@ private boolean isExcluded(ProgrammeMembership programmeMembership) { return true; } - List validCurricula = filterAndSortCurricula(programmeMembership.getCurricula()); + List validCurricula = filterAndSortCurricula(programmeMembership); if (validCurricula.isEmpty()) { log.info("Skipping NTN population as there are no valid curricula."); return true; diff --git a/src/test/java/uk/nhs/hee/trainee/details/service/NtnGeneratorTest.java b/src/test/java/uk/nhs/hee/trainee/details/service/NtnGeneratorTest.java index 910c4c66..d54ec705 100644 --- a/src/test/java/uk/nhs/hee/trainee/details/service/NtnGeneratorTest.java +++ b/src/test/java/uk/nhs/hee/trainee/details/service/NtnGeneratorTest.java @@ -58,8 +58,9 @@ class NtnGeneratorTest { private static final String PROGRAMME_NUMBER = "PROG123"; private static final String TRAINING_PATHWAY = "N/A"; - private static final LocalDate START_DATE = LocalDate.now().minusYears(1); - private static final LocalDate END_DATE = LocalDate.now().plusYears(1); + private static final LocalDate NOW = LocalDate.now(); + private static final LocalDate PAST = NOW.minusYears(1); + private static final LocalDate FUTURE = NOW.plusYears(1); private NtnGenerator service; @@ -79,12 +80,13 @@ void shouldNotPopulateNtnWhenNoPersonalDetails(CapturedOutput output) { pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -112,12 +114,13 @@ void shouldNotPopulateNtnWhenNoGmcOrGdcNumber(String referenceNumber, CapturedOu pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -144,12 +147,13 @@ void shouldNotPopulateNtnWhenNoProgrammeNumber(String programmeNumber, CapturedO pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(programmeNumber); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -176,12 +180,13 @@ void shouldNotPopulateNtnWhenNoProgrammeName(String programmeName, CapturedOutpu pm.setProgrammeName(programmeName); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -211,12 +216,13 @@ void shouldNotPopulateNtnWhenProgrammeIsFoundation(String programmeName, pm.setProgrammeName(programmeName); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -241,6 +247,7 @@ void shouldNotPopulateNtnWhenNoCurricula(CapturedOutput output) { pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); pm.setCurricula(List.of()); profile.setProgrammeMemberships(List.of(pm)); @@ -265,19 +272,18 @@ void shouldNotPopulateNtnWhenNoCurrentCurricula(CapturedOutput output) { pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); - LocalDate now = LocalDate.now(); - Curriculum past = new Curriculum(); past.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - past.setCurriculumStartDate(now.minusYears(1)); - past.setCurriculumEndDate(now.minusDays(1)); + past.setCurriculumStartDate(PAST); + past.setCurriculumEndDate(NOW.minusDays(1)); Curriculum future = new Curriculum(); future.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - future.setCurriculumStartDate(now.plusDays(1)); - future.setCurriculumEndDate(now.plusYears(1)); + future.setCurriculumStartDate(NOW.plusDays(1)); + future.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(past, future)); @@ -305,12 +311,13 @@ void shouldNotPopulateNtnWhenNoCurriculaSpecialtyCode(String specialtyCode, pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(specialtyCode); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -334,12 +341,13 @@ void shouldNotPopulateNtnWhenTrainingPathwayNull(CapturedOutput output) { pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(null); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -365,12 +373,13 @@ void shouldThrowExceptionPopulatingNtnWhenParentOrganizationNull(String ownerNam pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, @@ -381,7 +390,7 @@ void shouldThrowExceptionPopulatingNtnWhenParentOrganizationNull(String ownerNam } @Test - void shouldPopulateFullNtn() { + void shouldPopulateFullNtnWhenProgrammeIsCurrent() { TraineeProfile profile = new TraineeProfile(); PersonalDetails personalDetails = new PersonalDetails(); personalDetails.setGmcNumber(GMC_NUMBER); @@ -392,25 +401,72 @@ void shouldPopulateFullNtn() { pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum1 = new Curriculum(); curriculum1.setCurriculumSpecialtyCode("ABC"); curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); - curriculum1.setCurriculumStartDate(START_DATE); - curriculum1.setCurriculumEndDate(END_DATE); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(FUTURE); Curriculum curriculum2 = new Curriculum(); curriculum2.setCurriculumSpecialtyCode("123"); curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_SS); - curriculum2.setCurriculumStartDate(START_DATE); - curriculum2.setCurriculumEndDate(END_DATE); + curriculum2.setCurriculumStartDate(NOW); + curriculum2.setCurriculumEndDate(FUTURE); - pm.setCurricula(List.of(curriculum1, curriculum2)); + Curriculum curriculum3 = new Curriculum(); + curriculum3.setCurriculumSpecialtyCode("XYZ"); + curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_SS); + curriculum3.setCurriculumStartDate(PAST); + curriculum3.setCurriculumEndDate(NOW); + + pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3)); + + service.populateNtns(profile); + + assertThat("Unexpected NTN.", pm.getNtn(), is("LDN/ABC.XYZ.123/1234567/D")); + } + + @Test + void shouldPopulateFullNtnWhenProgrammeIsFuture() { + TraineeProfile profile = new TraineeProfile(); + PersonalDetails personalDetails = new PersonalDetails(); + personalDetails.setGmcNumber(GMC_NUMBER); + profile.setPersonalDetails(personalDetails); + + ProgrammeMembership pm = new ProgrammeMembership(); + pm.setManagingDeanery(OWNER_NAME); + pm.setProgrammeName(PROGRAMME_NAME); + pm.setProgrammeNumber(PROGRAMME_NUMBER); + pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(FUTURE); + profile.setProgrammeMemberships(List.of(pm)); + + Curriculum curriculum1 = new Curriculum(); + curriculum1.setCurriculumSpecialtyCode("ABC"); + curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum1.setCurriculumStartDate(NOW); + curriculum1.setCurriculumEndDate(FUTURE.plusDays(1)); + + Curriculum curriculum2 = new Curriculum(); + curriculum2.setCurriculumSpecialtyCode("123"); + curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_SS); + curriculum2.setCurriculumStartDate(FUTURE); + curriculum2.setCurriculumEndDate(FUTURE.plusDays(1)); + + Curriculum curriculum3 = new Curriculum(); + curriculum3.setCurriculumSpecialtyCode("XYZ"); + curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_SS); + curriculum3.setCurriculumStartDate(NOW); + curriculum3.setCurriculumEndDate(FUTURE); + + pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3)); service.populateNtns(profile); - assertThat("Unexpected NTN.", pm.getNtn(), is("LDN/ABC.123/1234567/D")); + assertThat("Unexpected NTN.", pm.getNtn(), is("LDN/ABC.XYZ.123/1234567/D")); } @ParameterizedTest @@ -445,12 +501,13 @@ void shouldPopulateNtnWithParentOrganizationWhenMappedByOwner(String ownerName, pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -479,12 +536,13 @@ void shouldPopulateNtnWithParentOrganizationWhenOwnerIsSouthWest(String ownerNam pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(programmeNumber); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -513,31 +571,32 @@ void shouldPopulateNtnWithOrderedSpecialtyConcatWhenMultipleSpecialty(String spe pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum1 = new Curriculum(); curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum1.setCurriculumSpecialtyCode(specialty1); - curriculum1.setCurriculumStartDate(START_DATE); - curriculum1.setCurriculumEndDate(END_DATE); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(FUTURE); Curriculum curriculum2 = new Curriculum(); curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum2.setCurriculumSpecialtyCode(specialty2); - curriculum2.setCurriculumStartDate(START_DATE); - curriculum2.setCurriculumEndDate(END_DATE); + curriculum2.setCurriculumStartDate(PAST); + curriculum2.setCurriculumEndDate(FUTURE); Curriculum curriculum3 = new Curriculum(); curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum3.setCurriculumSpecialtyCode(specialty3); - curriculum3.setCurriculumStartDate(START_DATE); - curriculum3.setCurriculumEndDate(END_DATE); + curriculum3.setCurriculumStartDate(PAST); + curriculum3.setCurriculumEndDate(FUTURE); Curriculum curriculum4 = new Curriculum(); curriculum4.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum4.setCurriculumSpecialtyCode(specialty4); - curriculum4.setCurriculumStartDate(START_DATE); - curriculum4.setCurriculumEndDate(END_DATE); + curriculum4.setCurriculumStartDate(PAST); + curriculum4.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3, curriculum4)); @@ -563,6 +622,7 @@ void shouldPopulateNtnWithDotNotatedSpecialtyConcatWhenHasSubSpecialties( pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); List curricula = new ArrayList<>(); @@ -572,16 +632,16 @@ void shouldPopulateNtnWithDotNotatedSpecialtyConcatWhenHasSubSpecialties( curriculum1.setCurriculumName("A sub spec 1"); curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_SS); curriculum1.setCurriculumSpecialtyCode("888"); - curriculum1.setCurriculumStartDate(START_DATE); - curriculum1.setCurriculumEndDate(END_DATE); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(FUTURE); curricula.add(curriculum1); Curriculum curriculum2 = new Curriculum(); curriculum2.setCurriculumName("A sub spec 2"); curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_SS); curriculum2.setCurriculumSpecialtyCode("999"); - curriculum2.setCurriculumStartDate(START_DATE); - curriculum2.setCurriculumEndDate(END_DATE); + curriculum2.setCurriculumStartDate(PAST); + curriculum2.setCurriculumEndDate(FUTURE); curricula.add(curriculum2); for (int i = 1; i <= additionalCurriculaCount; i++) { @@ -589,8 +649,8 @@ void shouldPopulateNtnWithDotNotatedSpecialtyConcatWhenHasSubSpecialties( additionalCurriculum.setCurriculumName("Not sub spec " + i); additionalCurriculum.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); additionalCurriculum.setCurriculumSpecialtyCode(String.format("%03d", i)); - additionalCurriculum.setCurriculumStartDate(START_DATE); - additionalCurriculum.setCurriculumEndDate(END_DATE); + additionalCurriculum.setCurriculumStartDate(PAST); + additionalCurriculum.setCurriculumEndDate(FUTURE); curricula.add(additionalCurriculum); } @@ -617,28 +677,29 @@ void shouldPopulateNtnWithFixedSpecialtyConcatWhenFirstSpecialtyIsAft() { pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum1 = new Curriculum(); curriculum1.setCurriculumName("AFT"); curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum1.setCurriculumSpecialtyCode("ACA"); - curriculum1.setCurriculumStartDate(START_DATE); - curriculum1.setCurriculumEndDate(END_DATE); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(FUTURE); Curriculum curriculum2 = new Curriculum(); curriculum2.setCurriculumName("Not AFT 2"); curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum2.setCurriculumSpecialtyCode("003"); - curriculum2.setCurriculumStartDate(START_DATE); - curriculum2.setCurriculumEndDate(END_DATE); + curriculum2.setCurriculumStartDate(PAST); + curriculum2.setCurriculumEndDate(FUTURE); Curriculum curriculum3 = new Curriculum(); curriculum3.setCurriculumName("Not AFT 1"); curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum3.setCurriculumSpecialtyCode("777"); - curriculum3.setCurriculumStartDate(START_DATE); - curriculum3.setCurriculumEndDate(END_DATE); + curriculum3.setCurriculumStartDate(PAST); + curriculum3.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3)); @@ -658,8 +719,8 @@ void shouldPopulateNtnWithFixedSpecialtyConcatWhenFirstSpecialtyIsAft() { 111 | AAA | ZZZ 111 | ZZZ | AAA """) - void shouldFilterCurriculaWhenPopulatingNtnWithOrderedSpecialtyConcat(String pastSpecialty, - String currentSpecialty, String futureSpecialty) { + void shouldFilterCurriculaWhenPopulatingNtnWithOrderedSpecialtyConcatAndCurriculaEnding( + String pastSpecialty, String endingSpecialty, String futureSpecialty) { TraineeProfile profile = new TraineeProfile(); PersonalDetails personalDetails = new PersonalDetails(); @@ -671,33 +732,92 @@ void shouldFilterCurriculaWhenPopulatingNtnWithOrderedSpecialtyConcat(String pas pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum1 = new Curriculum(); curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum1.setCurriculumSpecialtyCode(pastSpecialty); - curriculum1.setCurriculumStartDate(START_DATE); - curriculum1.setCurriculumEndDate(START_DATE); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(PAST); Curriculum curriculum2 = new Curriculum(); curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum2.setCurriculumSpecialtyCode(futureSpecialty); - curriculum2.setCurriculumStartDate(END_DATE); - curriculum2.setCurriculumEndDate(END_DATE); + curriculum2.setCurriculumStartDate(FUTURE); + curriculum2.setCurriculumEndDate(FUTURE); + + Curriculum curriculum3 = new Curriculum(); + curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum3.setCurriculumSpecialtyCode(endingSpecialty); + curriculum3.setCurriculumStartDate(PAST); + curriculum3.setCurriculumEndDate(NOW); + + Curriculum curriculum4 = new Curriculum(); + curriculum4.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum4.setCurriculumSpecialtyCode(null); + curriculum4.setCurriculumStartDate(PAST); + curriculum4.setCurriculumEndDate(FUTURE); + + pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3, curriculum4)); + + service.populateNtns(profile); + + String ntn = pm.getNtn(); + String[] ntnParts = ntn.split("/"); + assertThat("Unexpected parent organization.", ntnParts[1], is(endingSpecialty)); + } + + @ParameterizedTest + @CsvSource(delimiter = '|', textBlock = """ + AAA | ZZZ | 111 + AAA | 111 | ZZZ + ZZZ | AAA | 111 + ZZZ | 111 | AAA + 111 | AAA | ZZZ + 111 | ZZZ | AAA + """) + void shouldFilterCurriculaWhenPopulatingNtnWithOrderedSpecialtyConcatAndCurriculaCurrent( + String pastSpecialty, String currentSpecialty, String futureSpecialty) { + TraineeProfile profile = new TraineeProfile(); + + PersonalDetails personalDetails = new PersonalDetails(); + personalDetails.setGmcNumber(GMC_NUMBER); + profile.setPersonalDetails(personalDetails); + + ProgrammeMembership pm = new ProgrammeMembership(); + pm.setManagingDeanery(OWNER_NAME); + pm.setProgrammeName(PROGRAMME_NAME); + pm.setProgrammeNumber(PROGRAMME_NUMBER); + pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); + profile.setProgrammeMemberships(List.of(pm)); + + Curriculum curriculum1 = new Curriculum(); + curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum1.setCurriculumSpecialtyCode(pastSpecialty); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(PAST); + + Curriculum curriculum2 = new Curriculum(); + curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum2.setCurriculumSpecialtyCode(futureSpecialty); + curriculum2.setCurriculumStartDate(FUTURE); + curriculum2.setCurriculumEndDate(FUTURE); Curriculum curriculum3 = new Curriculum(); curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum3.setCurriculumSpecialtyCode(currentSpecialty); - curriculum3.setCurriculumStartDate(START_DATE); - curriculum3.setCurriculumEndDate(END_DATE); + curriculum3.setCurriculumStartDate(PAST); + curriculum3.setCurriculumEndDate(FUTURE); Curriculum curriculum4 = new Curriculum(); curriculum4.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); curriculum4.setCurriculumSpecialtyCode(null); - curriculum4.setCurriculumStartDate(START_DATE); - curriculum4.setCurriculumEndDate(END_DATE); + curriculum4.setCurriculumStartDate(PAST); + curriculum4.setCurriculumEndDate(FUTURE); - pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3)); + pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3, curriculum4)); service.populateNtns(profile); @@ -706,6 +826,122 @@ void shouldFilterCurriculaWhenPopulatingNtnWithOrderedSpecialtyConcat(String pas assertThat("Unexpected parent organization.", ntnParts[1], is(currentSpecialty)); } + @ParameterizedTest + @CsvSource(delimiter = '|', textBlock = """ + AAA | ZZZ | 111 + AAA | 111 | ZZZ + ZZZ | AAA | 111 + ZZZ | 111 | AAA + 111 | AAA | ZZZ + 111 | ZZZ | AAA + """) + void shouldFilterCurriculaWhenPopulatingNtnWithOrderedSpecialtyConcatAndCurriculaStarting( + String pastSpecialty, String startingSpecialty, String futureSpecialty) { + TraineeProfile profile = new TraineeProfile(); + + PersonalDetails personalDetails = new PersonalDetails(); + personalDetails.setGmcNumber(GMC_NUMBER); + profile.setPersonalDetails(personalDetails); + + ProgrammeMembership pm = new ProgrammeMembership(); + pm.setManagingDeanery(OWNER_NAME); + pm.setProgrammeName(PROGRAMME_NAME); + pm.setProgrammeNumber(PROGRAMME_NUMBER); + pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); + profile.setProgrammeMemberships(List.of(pm)); + + Curriculum curriculum1 = new Curriculum(); + curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum1.setCurriculumSpecialtyCode(pastSpecialty); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(PAST); + + Curriculum curriculum2 = new Curriculum(); + curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum2.setCurriculumSpecialtyCode(futureSpecialty); + curriculum2.setCurriculumStartDate(FUTURE); + curriculum2.setCurriculumEndDate(FUTURE); + + Curriculum curriculum3 = new Curriculum(); + curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum3.setCurriculumSpecialtyCode(startingSpecialty); + curriculum3.setCurriculumStartDate(NOW); + curriculum3.setCurriculumEndDate(FUTURE); + + Curriculum curriculum4 = new Curriculum(); + curriculum4.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum4.setCurriculumSpecialtyCode(null); + curriculum4.setCurriculumStartDate(PAST); + curriculum4.setCurriculumEndDate(FUTURE); + + pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3, curriculum4)); + + service.populateNtns(profile); + + String ntn = pm.getNtn(); + String[] ntnParts = ntn.split("/"); + assertThat("Unexpected parent organization.", ntnParts[1], is(startingSpecialty)); + } + + @ParameterizedTest + @CsvSource(delimiter = '|', textBlock = """ + AAA | ZZZ | 111 + AAA | 111 | ZZZ + ZZZ | AAA | 111 + ZZZ | 111 | AAA + 111 | AAA | ZZZ + 111 | ZZZ | AAA + """) + void shouldFilterCurriculaWhenPopulatingNtnWithOrderedSpecialtyConcatAndProgrammeFuture( + String currentSpecialty, String futureSpecialty, String farFutureSpecialty) { + TraineeProfile profile = new TraineeProfile(); + + PersonalDetails personalDetails = new PersonalDetails(); + personalDetails.setGmcNumber(GMC_NUMBER); + profile.setPersonalDetails(personalDetails); + + ProgrammeMembership pm = new ProgrammeMembership(); + pm.setManagingDeanery(OWNER_NAME); + pm.setProgrammeName(PROGRAMME_NAME); + pm.setProgrammeNumber(PROGRAMME_NUMBER); + pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(FUTURE); + profile.setProgrammeMemberships(List.of(pm)); + + Curriculum curriculum1 = new Curriculum(); + curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum1.setCurriculumSpecialtyCode(currentSpecialty); + curriculum1.setCurriculumStartDate(NOW); + curriculum1.setCurriculumEndDate(NOW); + + Curriculum curriculum2 = new Curriculum(); + curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum2.setCurriculumSpecialtyCode(futureSpecialty); + curriculum2.setCurriculumStartDate(FUTURE); + curriculum2.setCurriculumEndDate(FUTURE); + + Curriculum curriculum3 = new Curriculum(); + curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum3.setCurriculumSpecialtyCode(farFutureSpecialty); + curriculum3.setCurriculumStartDate(FUTURE.plusDays(1)); + curriculum3.setCurriculumEndDate(FUTURE.plusDays(1)); + + Curriculum curriculum4 = new Curriculum(); + curriculum4.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum4.setCurriculumSpecialtyCode(null); + curriculum4.setCurriculumStartDate(PAST); + curriculum4.setCurriculumEndDate(FUTURE); + + pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3, curriculum4)); + + service.populateNtns(profile); + + String ntn = pm.getNtn(); + String[] ntnParts = ntn.split("/"); + assertThat("Unexpected parent organization.", ntnParts[1], is(futureSpecialty)); + } + @Test void shouldPopulateNtnWithGmcNumberWhenValid() { TraineeProfile profile = new TraineeProfile(); @@ -719,12 +955,13 @@ void shouldPopulateNtnWithGmcNumberWhenValid() { pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -749,12 +986,13 @@ void shouldPopulateNtnWithGdcNumberWhenValidAndGmcInvalid(String gmcNumber) { pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -783,12 +1021,13 @@ void shouldPopulateNtnWithSuffixWhenMappedByTrainingPathway(String trainingPathw pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(trainingPathway); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum = new Curriculum(); curriculum.setCurriculumSpecialtyCode(CURRICULUM_SPECIALTY_CODE); - curriculum.setCurriculumStartDate(START_DATE); - curriculum.setCurriculumEndDate(END_DATE); + curriculum.setCurriculumStartDate(PAST); + curriculum.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum)); service.populateNtns(profile); @@ -811,19 +1050,20 @@ void shouldPopulateNtnWithSuffixWhenSpecialtyIsAcademic() { pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum1 = new Curriculum(); curriculum1.setCurriculumSpecialtyCode("123"); curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); - curriculum1.setCurriculumStartDate(START_DATE); - curriculum1.setCurriculumEndDate(END_DATE); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(FUTURE); Curriculum curriculum2 = new Curriculum(); curriculum2.setCurriculumSpecialtyCode("ACA"); curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); - curriculum2.setCurriculumStartDate(START_DATE); - curriculum2.setCurriculumEndDate(END_DATE); + curriculum2.setCurriculumStartDate(PAST); + curriculum2.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum1, curriculum2)); @@ -835,7 +1075,7 @@ void shouldPopulateNtnWithSuffixWhenSpecialtyIsAcademic() { } @Test - void shouldFilterCurriculaWhenPopulatingNtnWithSuffix() { + void shouldFilterCurriculaWhenPopulatingNtnWithSuffixAndCurriculaEnding() { TraineeProfile profile = new TraineeProfile(); PersonalDetails personalDetails = new PersonalDetails(); @@ -847,25 +1087,121 @@ void shouldFilterCurriculaWhenPopulatingNtnWithSuffix() { pm.setProgrammeName(PROGRAMME_NAME); pm.setProgrammeNumber(PROGRAMME_NUMBER); pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); profile.setProgrammeMemberships(List.of(pm)); Curriculum curriculum1 = new Curriculum(); - curriculum1.setCurriculumSpecialtyCode("123"); + curriculum1.setCurriculumName("Past"); + curriculum1.setCurriculumSpecialtyCode("ACA"); curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); - curriculum1.setCurriculumStartDate(START_DATE); - curriculum1.setCurriculumEndDate(END_DATE); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(PAST); Curriculum curriculum2 = new Curriculum(); - curriculum2.setCurriculumSpecialtyCode("ACA"); + curriculum2.setCurriculumName("Ending"); + curriculum2.setCurriculumSpecialtyCode("123"); + curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum2.setCurriculumStartDate(PAST); + curriculum2.setCurriculumEndDate(NOW); + + Curriculum curriculum3 = new Curriculum(); + curriculum3.setCurriculumName("Future"); + curriculum3.setCurriculumSpecialtyCode("ACA"); + curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum3.setCurriculumStartDate(FUTURE); + curriculum3.setCurriculumEndDate(FUTURE); + + pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3)); + + service.populateNtns(profile); + + String ntn = pm.getNtn(); + String[] ntnParts = ntn.split("/"); + assertThat("Unexpected parent organization.", ntnParts[3], is("D")); + } + + @Test + void shouldFilterCurriculaWhenPopulatingNtnWithSuffixAndCurriculaCurrent() { + TraineeProfile profile = new TraineeProfile(); + + PersonalDetails personalDetails = new PersonalDetails(); + personalDetails.setGmcNumber(GMC_NUMBER); + profile.setPersonalDetails(personalDetails); + + ProgrammeMembership pm = new ProgrammeMembership(); + pm.setManagingDeanery(OWNER_NAME); + pm.setProgrammeName(PROGRAMME_NAME); + pm.setProgrammeNumber(PROGRAMME_NUMBER); + pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); + profile.setProgrammeMemberships(List.of(pm)); + + Curriculum curriculum1 = new Curriculum(); + curriculum1.setCurriculumName("Past"); + curriculum1.setCurriculumSpecialtyCode("ACA"); + curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(PAST); + + Curriculum curriculum2 = new Curriculum(); + curriculum2.setCurriculumName("Current"); + curriculum2.setCurriculumSpecialtyCode("123"); + curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum2.setCurriculumStartDate(PAST); + curriculum2.setCurriculumEndDate(FUTURE); + + Curriculum curriculum3 = new Curriculum(); + curriculum3.setCurriculumName("Future"); + curriculum3.setCurriculumSpecialtyCode("ACA"); + curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum3.setCurriculumStartDate(FUTURE); + curriculum3.setCurriculumEndDate(FUTURE); + + pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3)); + + service.populateNtns(profile); + + String ntn = pm.getNtn(); + String[] ntnParts = ntn.split("/"); + assertThat("Unexpected parent organization.", ntnParts[3], is("D")); + } + + @Test + void shouldFilterCurriculaWhenPopulatingNtnWithSuffixAndCurriculaStarting() { + TraineeProfile profile = new TraineeProfile(); + + PersonalDetails personalDetails = new PersonalDetails(); + personalDetails.setGmcNumber(GMC_NUMBER); + profile.setPersonalDetails(personalDetails); + + ProgrammeMembership pm = new ProgrammeMembership(); + pm.setManagingDeanery(OWNER_NAME); + pm.setProgrammeName(PROGRAMME_NAME); + pm.setProgrammeNumber(PROGRAMME_NUMBER); + pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(NOW); + profile.setProgrammeMemberships(List.of(pm)); + + Curriculum curriculum1 = new Curriculum(); + curriculum1.setCurriculumName("Past"); + curriculum1.setCurriculumSpecialtyCode("ACA"); + curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(PAST); + + Curriculum curriculum2 = new Curriculum(); + curriculum2.setCurriculumName("Starting"); + curriculum2.setCurriculumSpecialtyCode("123"); curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); - curriculum2.setCurriculumStartDate(START_DATE); - curriculum2.setCurriculumEndDate(START_DATE); + curriculum2.setCurriculumStartDate(NOW); + curriculum2.setCurriculumEndDate(FUTURE); Curriculum curriculum3 = new Curriculum(); + curriculum3.setCurriculumName("Future"); curriculum3.setCurriculumSpecialtyCode("ACA"); curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); - curriculum3.setCurriculumStartDate(END_DATE); - curriculum3.setCurriculumEndDate(END_DATE); + curriculum3.setCurriculumStartDate(FUTURE); + curriculum3.setCurriculumEndDate(FUTURE); pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3)); @@ -875,4 +1211,57 @@ void shouldFilterCurriculaWhenPopulatingNtnWithSuffix() { String[] ntnParts = ntn.split("/"); assertThat("Unexpected parent organization.", ntnParts[3], is("D")); } + + @Test + void shouldFilterCurriculaWhenPopulatingNtnWithSuffixAndProgrammeFuture() { + TraineeProfile profile = new TraineeProfile(); + + PersonalDetails personalDetails = new PersonalDetails(); + personalDetails.setGmcNumber(GMC_NUMBER); + profile.setPersonalDetails(personalDetails); + + ProgrammeMembership pm = new ProgrammeMembership(); + pm.setManagingDeanery(OWNER_NAME); + pm.setProgrammeName(PROGRAMME_NAME); + pm.setProgrammeNumber(PROGRAMME_NUMBER); + pm.setTrainingPathway(TRAINING_PATHWAY); + pm.setStartDate(FUTURE); + profile.setProgrammeMemberships(List.of(pm)); + + Curriculum curriculum1 = new Curriculum(); + curriculum1.setCurriculumName("Past"); + curriculum1.setCurriculumSpecialtyCode("ACA"); + curriculum1.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum1.setCurriculumStartDate(PAST); + curriculum1.setCurriculumEndDate(PAST); + + Curriculum curriculum2 = new Curriculum(); + curriculum2.setCurriculumName("Past"); + curriculum2.setCurriculumSpecialtyCode("ACA"); + curriculum2.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum2.setCurriculumStartDate(NOW); + curriculum2.setCurriculumEndDate(NOW); + + Curriculum curriculum3 = new Curriculum(); + curriculum3.setCurriculumName("Future"); + curriculum3.setCurriculumSpecialtyCode("123"); + curriculum3.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum3.setCurriculumStartDate(FUTURE); + curriculum3.setCurriculumEndDate(FUTURE); + + Curriculum curriculum4 = new Curriculum(); + curriculum4.setCurriculumName("Future + 1"); + curriculum4.setCurriculumSpecialtyCode("ACA"); + curriculum4.setCurriculumSubType(CURRICULUM_SUB_TYPE_MC); + curriculum4.setCurriculumStartDate(FUTURE.plusDays(1)); + curriculum4.setCurriculumEndDate(FUTURE.plusDays(1)); + + pm.setCurricula(List.of(curriculum1, curriculum2, curriculum3, curriculum4)); + + service.populateNtns(profile); + + String ntn = pm.getNtn(); + String[] ntnParts = ntn.split("/"); + assertThat("Unexpected parent organization.", ntnParts[3], is("D")); + } }