ContactService extends AbstractCoreAdoService<Contact> { public void updateFollowUpUntilAndStatus(Contact contact) { Disease disease = contact.getDisease(); boolean changeStatus = contact.getFollowUpStatus() != FollowUpStatus.CANCELED && contact.getFollowUpStatus() != FollowUpStatus.LOST; ContactProximity contactProximity = contact.getContactProximity(); if (!diseaseConfigurationFacade.hasFollowUp(disease) || (contactProximity != null && !contactProximity.hasFollowUp())) { contact.setFollowUpUntil(null); if (changeStatus) { contact.setFollowUpStatus(FollowUpStatus.NO_FOLLOW_UP); } } else { int followUpDuration = diseaseConfigurationFacade.getFollowUpDuration(disease); LocalDate beginDate = DateHelper8.toLocalDate(ContactLogic.getStartDate(contact.getLastContactDate(), contact.getReportDateTime())); LocalDate untilDate = contact.isOverwriteFollowUpUntil() || (contact.getFollowUpUntil() != null && DateHelper8.toLocalDate(contact.getFollowUpUntil()).isAfter(beginDate.plusDays(followUpDuration))) ? DateHelper8.toLocalDate(contact.getFollowUpUntil()) : beginDate.plusDays(followUpDuration); Visit lastVisit = null; boolean additionalVisitNeeded; do { additionalVisitNeeded = false; lastVisit = contact.getVisits().stream().max((v1, v2) -> v1.getVisitDateTime().compareTo(v2.getVisitDateTime())).orElse(null); if (lastVisit != null) { if (lastVisit.getVisitStatus() != VisitStatus.COOPERATIVE && DateHelper8.toLocalDate(lastVisit.getVisitDateTime()).isEqual(untilDate)) { additionalVisitNeeded = true; untilDate = untilDate.plusDays(1); } if (!contact.isOverwriteFollowUpUntil() && lastVisit.getVisitStatus() == VisitStatus.COOPERATIVE && DateHelper8.toLocalDate(lastVisit.getVisitDateTime()).isEqual(beginDate.plusDays(followUpDuration))) { additionalVisitNeeded = false; untilDate = beginDate.plusDays(followUpDuration); } } } while (additionalVisitNeeded); contact.setFollowUpUntil(DateHelper8.toDate(untilDate)); if (changeStatus) { if (lastVisit != null && DateHelper.isSameDay(lastVisit.getVisitDateTime(), DateHelper8.toDate(untilDate))) { contact.setFollowUpStatus(FollowUpStatus.COMPLETED); } else { contact.setFollowUpStatus(FollowUpStatus.FOLLOW_UP); } if (contact.getFollowUpStatus() != FollowUpStatus.COMPLETED && contact.getContactStatus() == ContactStatus.CONVERTED) { contact.setFollowUpStatus(FollowUpStatus.CANCELED); contact.setFollowUpComment(I18nProperties.getString(Strings.messageSystemFollowUpCanceled)); } } } ensurePersisted(contact); } ContactService(); List<Contact> findBy(ContactCriteria contactCriteria, User user); List<Contact> getAllActiveContactsAfter(Date date); @Override Predicate createChangeDateFilter(CriteriaBuilder cb, From<?, Contact> from, Date date); @Override Predicate createChangeDateFilter(CriteriaBuilder cb, From<?, Contact> from, Timestamp date); List<String> getAllActiveUuids(User user); int getContactCountByCase(Case caze); List<Contact> getAllByResultingCase(Case caze); List<Object[]> getSourceCaseClassifications(List<Long> caseIds); List<Contact> getFollowUpBetween(@NotNull Date fromDate, @NotNull Date toDate); List<Contact> getByPersonAndDisease(Person person, Disease disease); Set<Contact> getAllRelevantContacts(Person person, Disease disease, Date referenceDate); List<String> getDeletedUuidsSince(User user, Date since); List<MapContactDto> getContactsForMap(
		Region region,
		District district,
		Disease disease,
		Date fromDate,
		Date toDate,
		User user,
		List<String> caseUuids); List<DashboardContactDto> getContactsForDashboard(Region region, District district, Disease disease, Date from, Date to, User user); Predicate getRegionDistrictDiseasePredicate(
		Region region,
		District district,
		Disease disease,
		CriteriaBuilder cb,
		Root<Contact> contact,
		Join<Contact, Case> caze); List<DashboardQuarantineDataDto> getQuarantineDataForDashBoard(
		Region region,
		District district,
		Disease disease,
		Date from,
		Date to,
		User user); Map<ContactStatus, Long> getNewContactCountPerStatus(ContactCriteria contactCriteria, User user); Map<ContactClassification, Long> getNewContactCountPerClassification(ContactCriteria contactCriteria, User user); Map<FollowUpStatus, Long> getNewContactCountPerFollowUpStatus(ContactCriteria contactCriteria, User user); int getFollowUpUntilCount(ContactCriteria contactCriteria, User user); void udpateContactStatus(Contact contact); void updateFollowUpUntilAndStatus(Contact contact); List<Contact> getAllByVisit(Visit visit); @SuppressWarnings("rawtypes") @Override Predicate createUserFilter(CriteriaBuilder cb, CriteriaQuery cq, From<?, Contact> contactPath); @SuppressWarnings("rawtypes") Predicate createUserFilterForJoin(CriteriaBuilder cb, CriteriaQuery cq, From<?, Contact> contactPath); @SuppressWarnings("rawtypes") Predicate createUserFilterWithoutCase(CriteriaBuilder cb, CriteriaQuery cq, From<?, Contact> contactPath); Predicate buildCriteriaFilter(ContactCriteria contactCriteria, CriteriaBuilder cb, Root<Contact> from); @Override void delete(Contact contact); Predicate createActiveContactsFilter(CriteriaBuilder cb, Root<Contact> root); Predicate createDefaultFilter(CriteriaBuilder cb, Root<Contact> root); Predicate isInJurisdictionOrOwned(CriteriaBuilder cb, CriteriaQuery<Long> cq, ContactJoins joins);  }
@Test public void testUpdateFollowUpUntilAndStatus() { RDCFEntities rdcf = creator.createRDCFEntities("Region", "District", "Community", "Facility"); UserDto user = creator .createUser(rdcf.region.getUuid(), rdcf.district.getUuid(), rdcf.facility.getUuid(), "Surv", "Sup", UserRole.SURVEILLANCE_SUPERVISOR); PersonDto cazePerson = creator.createPerson("Case", "Person"); CaseDataDto caze = creator.createCase( user.toReference(), cazePerson.toReference(), Disease.EVD, CaseClassification.PROBABLE, InvestigationStatus.PENDING, new Date(), rdcf); PersonDto contactPerson = creator.createPerson("Contact", "Person"); ContactDto contact = creator.createContact(user.toReference(), user.toReference(), contactPerson.toReference(), caze, new Date(), new Date(), null); assertEquals(FollowUpStatus.FOLLOW_UP, contact.getFollowUpStatus()); assertEquals(LocalDate.now().plusDays(21), DateHelper8.toLocalDate(contact.getFollowUpUntil())); VisitDto visit = creator.createVisit(caze.getDisease(), contactPerson.toReference(), DateUtils.addDays(new Date(), 21), VisitStatus.UNAVAILABLE); contact = getContactFacade().getContactByUuid(contact.getUuid()); assertEquals(FollowUpStatus.FOLLOW_UP, contact.getFollowUpStatus()); assertEquals(LocalDate.now().plusDays(21 + 1), DateHelper8.toLocalDate(contact.getFollowUpUntil())); visit.setVisitStatus(VisitStatus.COOPERATIVE); visit = getVisitFacade().saveVisit(visit); contact = getContactFacade().getContactByUuid(contact.getUuid()); assertEquals(FollowUpStatus.COMPLETED, contact.getFollowUpStatus()); assertEquals(LocalDate.now().plusDays(21), DateHelper8.toLocalDate(contact.getFollowUpUntil())); PersonDto person2 = creator.createPerson(); ContactDto contact2 = creator.createContact(user.toReference(), person2.toReference()); contact2.setContactStatus(ContactStatus.CONVERTED); contact2 = getContactFacade().saveContact(contact2); assertThat(contact2.getFollowUpStatus(), is(FollowUpStatus.CANCELED)); assertNotNull(contact2.getFollowUpComment()); }