diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/validation/hooks/EventDateValidationHook.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/validation/hooks/EventDateValidationHook.java index 5159be106e02..cbc0a4488d11 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/validation/hooks/EventDateValidationHook.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/validation/hooks/EventDateValidationHook.java @@ -74,11 +74,11 @@ public void validateEvent(ValidationErrorReporter reporter, TrackerBundle bundle return; } - validateExpiryDays(reporter, bundle, event, program); - validatePeriodType(reporter, event, program); + validateCompletionExpiryDays(reporter, bundle, event, program); + validateExpiryPeriodType(reporter, event, program); } - private void validateExpiryDays( + private void validateCompletionExpiryDays( ValidationErrorReporter reporter, TrackerBundle bundle, Event event, Program program) { User actingUser = bundle.getUser(); @@ -102,7 +102,8 @@ private void validateExpiryDays( } } - private void validatePeriodType(ValidationErrorReporter reporter, Event event, Program program) { + private void validateExpiryPeriodType( + ValidationErrorReporter reporter, Event event, Program program) { checkNotNull(event, TrackerImporterAssertErrors.EVENT_CANT_BE_NULL); checkNotNull(program, TrackerImporterAssertErrors.PROGRAM_CANT_BE_NULL); @@ -121,9 +122,16 @@ private void validatePeriodType(ValidationErrorReporter reporter, Event event, P return; } - Period period = periodType.createPeriod(new Date()); + Period eventPeriod = periodType.createPeriod(Date.from(referenceDate)); - if (referenceDate.isBefore(period.getStartDate().toInstant())) { + if (eventPeriod + .getEndDate() + .toInstant() // This will be 00:00 time of the period end date. + .plus( + ofDays( + program.getExpiryDays() + + 1L)) // Extra day added to account for final 24 hours of expiring day + .isBefore(Instant.now())) { reporter.addError(event, E1047, event); } } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/validation/hooks/EventDateValidationHookTest.java b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/validation/hooks/EventDateValidationHookTest.java index 7dd73084eb52..016a65dee09e 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/validation/hooks/EventDateValidationHookTest.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/validation/hooks/EventDateValidationHookTest.java @@ -94,7 +94,7 @@ public void setUp() { bundle = TrackerBundle.builder().user(user).preheat(preheat).build(); when(preheat.getProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID))) - .thenReturn(getProgramWithRegistration()); + .thenReturn(getProgramWithRegistration(5)); when(preheat.getProgram(MetadataIdentifier.ofUid(PROGRAM_WITHOUT_REGISTRATION_ID))) .thenReturn(getProgramWithoutRegistration()); @@ -104,7 +104,6 @@ public void setUp() { @Test void testEventIsValid() { - // given Event event = new Event(); event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITHOUT_REGISTRATION_ID)); event.setOccurredAt(now()); @@ -113,92 +112,74 @@ void testEventIsValid() { TrackerBundle bundle = TrackerBundle.builder().user(getEditExpiredUser()).preheat(preheat).build(); - // when this.hookToTest.validateEvent(reporter, bundle, event); - // then assertFalse(reporter.hasErrors()); } @Test void testEventIsNotValidWhenOccurredDateIsNotPresentAndProgramIsWithoutRegistration() { - // given Event event = new Event(); event.setEvent(CodeGenerator.generateUid()); event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITHOUT_REGISTRATION_ID)); - // when this.hookToTest.validateEvent(reporter, bundle, event); - // then hasTrackerError(reporter, E1031, EVENT, event.getUid()); } @Test void testEventIsNotValidWhenOccurredDateIsNotPresentAndEventIsActive() { - // given Event event = new Event(); event.setEvent(CodeGenerator.generateUid()); event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID)); event.setStatus(EventStatus.ACTIVE); - // when this.hookToTest.validateEvent(reporter, bundle, event); - // then hasTrackerError(reporter, E1031, EVENT, event.getUid()); } @Test void testEventIsNotValidWhenOccurredDateIsNotPresentAndEventIsCompleted() { - // given Event event = new Event(); event.setEvent(CodeGenerator.generateUid()); event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID)); event.setStatus(EventStatus.COMPLETED); - // when this.hookToTest.validateEvent(reporter, bundle, event); - // then hasTrackerError(reporter, E1031, EVENT, event.getUid()); } @Test void testEventIsNotValidWhenScheduledDateIsNotPresentAndEventIsSchedule() { - // given Event event = new Event(); event.setEvent(CodeGenerator.generateUid()); event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID)); event.setOccurredAt(Instant.now()); event.setStatus(EventStatus.SCHEDULE); - // when this.hookToTest.validateEvent(reporter, bundle, event); - // then hasTrackerError(reporter, E1050, EVENT, event.getUid()); } @Test void testEventIsNotValidWhenCompletedAtIsNotPresentAndEventIsCompleted() { - // given Event event = new Event(); event.setEvent(CodeGenerator.generateUid()); event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID)); event.setOccurredAt(now()); event.setStatus(EventStatus.COMPLETED); - // when this.hookToTest.validateEvent(reporter, bundle, event); - // then hasTrackerError(reporter, E1042, EVENT, event.getUid()); } @Test void testEventIsNotValidWhenCompletedAtIsTooSoonAndEventIsCompleted() { - // given Event event = new Event(); event.setEvent(CodeGenerator.generateUid()); event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID)); @@ -206,16 +187,13 @@ void testEventIsNotValidWhenCompletedAtIsTooSoonAndEventIsCompleted() { event.setCompletedAt(sevenDaysAgo()); event.setStatus(EventStatus.COMPLETED); - // when this.hookToTest.validateEvent(reporter, bundle, event); - // then hasTrackerError(reporter, E1043, EVENT, event.getUid()); } @Test void testEventIsNotValidWhenOccurredAtAndScheduledAtAreNotPresent() { - // given Event event = new Event(); event.setEvent(CodeGenerator.generateUid()); event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID)); @@ -223,35 +201,75 @@ void testEventIsNotValidWhenOccurredAtAndScheduledAtAreNotPresent() { event.setScheduledAt(null); event.setStatus(EventStatus.SKIPPED); - // when this.hookToTest.validateEvent(reporter, bundle, event); - // then hasTrackerError(reporter, E1046, EVENT, event.getUid()); } @Test - void testEventIsNotValidWhenDateBelongsToExpiredPeriod() { - // given + void shouldFailValidationForEventWhenDateBelongsToExpiredPeriod() { Event event = new Event(); event.setEvent(CodeGenerator.generateUid()); event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID)); event.setOccurredAt(sevenDaysAgo()); event.setStatus(EventStatus.ACTIVE); - // when this.hookToTest.validateEvent(reporter, bundle, event); - // then hasTrackerError(reporter, E1047, EVENT, event.getUid()); } - private Program getProgramWithRegistration() { + @Test + void shouldPassValidationForEventWhenDateBelongsToPastPeriodWithZeroExpiryDays() { + when(preheat.getProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID))) + .thenReturn(getProgramWithRegistration(0)); + Event event = new Event(); + event.setEvent(CodeGenerator.generateUid()); + event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID)); + event.setOccurredAt(sevenDaysAgo()); + event.setStatus(EventStatus.ACTIVE); + + this.hookToTest.validateEvent(reporter, bundle, event); + + assertFalse(reporter.hasErrors()); + } + + @Test + void shouldPassValidationForEventWhenDateBelongsPastEventPeriodButWithinExpiryDays() { + when(preheat.getProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID))) + .thenReturn(getProgramWithRegistration(7)); + Event event = new Event(); + event.setEvent(CodeGenerator.generateUid()); + event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID)); + event.setOccurredAt(sevenDaysAgo()); + event.setStatus(EventStatus.ACTIVE); + + this.hookToTest.validateEvent(reporter, bundle, event); + + assertFalse(reporter.hasErrors()); + } + + @Test + void shouldPassValidationForEventWhenScheduledDateBelongsToFuturePeriod() { + when(preheat.getProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID))) + .thenReturn(getProgramWithRegistration(5)); + Event event = new Event(); + event.setEvent(CodeGenerator.generateUid()); + event.setProgram(MetadataIdentifier.ofUid(PROGRAM_WITH_REGISTRATION_ID)); + event.setScheduledAt(sevenDaysLater()); + event.setStatus(EventStatus.SCHEDULE); + + this.hookToTest.validateEvent(reporter, bundle, event); + + assertFalse(reporter.hasErrors()); + } + + private Program getProgramWithRegistration(int expiryDays) { Program program = createProgram('A'); program.setUid(PROGRAM_WITH_REGISTRATION_ID); program.setProgramType(ProgramType.WITH_REGISTRATION); program.setCompleteEventsExpiryDays(5); - program.setExpiryDays(5); + program.setExpiryDays(expiryDays); program.setExpiryPeriodType(new DailyPeriodType()); return program; } @@ -280,4 +298,8 @@ private Instant now() { private Instant sevenDaysAgo() { return LocalDateTime.now().minus(7, ChronoUnit.DAYS).toInstant(ZoneOffset.UTC); } + + private Instant sevenDaysLater() { + return LocalDateTime.now().plusDays(7).toInstant(ZoneOffset.UTC); + } }