LostToFollowUpCalculation extends AbstractPatientCalculation implements PatientFlagCalculation { @Override public CalculationResultMap evaluate(Collection<Integer> cohort, Map<String, Object> arg1, PatientCalculationContext context) { Program hivProgram = MetadataUtils.existing(Program.class, HivMetadata._Program.HIV); Concept reasonForDiscontinuation = Dictionary.getConcept(Dictionary.REASON_FOR_PROGRAM_DISCONTINUATION); Concept transferout = Dictionary.getConcept(Dictionary.TRANSFERRED_OUT); Set<Integer> alive = Filters.alive(cohort, context); Set<Integer> inHivProgram = Filters.inProgram(hivProgram, alive, context); CalculationResultMap lastReturnDateObss = Calculations.lastObs(Dictionary.getConcept(Dictionary.RETURN_VISIT_DATE), inHivProgram, context); CalculationResultMap lastProgramDiscontinuation = Calculations.lastObs(reasonForDiscontinuation, cohort, context); CalculationResultMap ret = new CalculationResultMap(); for (Integer ptId : cohort) { boolean lost = false; if (alive.contains(ptId)) { Date lastScheduledReturnDate = EmrCalculationUtils.datetimeObsResultForPatient(lastReturnDateObss, ptId); Obs discontuation = EmrCalculationUtils.obsResultForPatient(lastProgramDiscontinuation, ptId); if (lastScheduledReturnDate != null) { if(daysSince(lastScheduledReturnDate, context) > HivConstants.LOST_TO_FOLLOW_UP_THRESHOLD_DAYS){ lost = true; } if(discontuation != null && discontuation.getValueCoded().equals(transferout)) { lost = false; } } } ret.put(ptId, new SimpleResult(lost, this, context)); } return ret; }  @Override String getFlagMessage(); @Override CalculationResultMap evaluate(Collection<Integer> cohort, Map<String, Object> arg1, PatientCalculationContext context);  }
@Test public void evaluate_shouldDetermineWhetherPatientsAreLostToFollowUp() throws Exception { Program hivProgram = MetadataUtils.existing(Program.class, HivMetadata._Program.HIV); Concept returnVisitDate = Dictionary.getConcept(Dictionary.RETURN_VISIT_DATE); Concept reasonForDiscontinuation = Dictionary.getConcept(Dictionary.REASON_FOR_PROGRAM_DISCONTINUATION); Concept dead = Dictionary.getConcept(Dictionary.DIED); Concept transferout = Dictionary.getConcept(Dictionary.TRANSFERRED_OUT) ; TestUtils.enrollInProgram(TestUtils.getPatient(6), hivProgram, TestUtils.date(2011, 1, 1)); TestUtils.enrollInProgram(TestUtils.getPatient(7), hivProgram, TestUtils.date(2011, 1, 1)); TestUtils.enrollInProgram(TestUtils.getPatient(8), hivProgram, TestUtils.date(2011, 1, 1)); Obs[] returnDate6 = {TestUtils.saveObs(TestUtils.getPatient(6), returnVisitDate, TestUtils.date(2011, 4, 1), TestUtils.date(2011, 1, 1))}; Obs[] returnDate7 = {TestUtils.saveObs(TestUtils.getPatient(7), returnVisitDate, TestUtils.date(2011, 4, 1), TestUtils.date(2011, 1, 1))}; Obs[] discontinuation6 = {TestUtils.saveObs(TestUtils.getPatient(6), reasonForDiscontinuation, dead, TestUtils.date(2011, 1, 1))}; Obs[] discontinuation7 = {TestUtils.saveObs(TestUtils.getPatient(7), reasonForDiscontinuation, dead, TestUtils.date(2011, 1, 1))}; Obs[] discontinuation8 = {TestUtils.saveObs(TestUtils.getPatient(8), reasonForDiscontinuation, transferout, TestUtils.date(2011, 1, 1))}; Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DATE, -200); EncounterType scheduledEncType = Context.getEncounterService().getEncounterType("Scheduled"); TestUtils.saveEncounter(TestUtils.getPatient(7), scheduledEncType, calendar.getTime(), returnDate7); calendar = Calendar.getInstance(); calendar.add(Calendar.DATE, -10); TestUtils.saveEncounter(TestUtils.getPatient(8), scheduledEncType, calendar.getTime()); List<Integer> ptIds = Arrays.asList(6, 7, 8, 999); CalculationResultMap resultMap = new LostToFollowUpCalculation().evaluate(ptIds, null, Context.getService(PatientCalculationService.class).createCalculationContext()); Assert.assertTrue((Boolean) resultMap.get(6).getValue()); Assert.assertTrue((Boolean) resultMap.get(7).getValue()); Assert.assertFalse((Boolean) resultMap.get(8).getValue()); Assert.assertFalse((Boolean) resultMap.get(999).getValue()); }