package org.ei.drishti.service.scheduling.fpMethodStrategy; import org.ei.drishti.contract.Schedule; import org.ei.drishti.domain.FPProductInformation; import org.ei.drishti.service.ActionService; import org.ei.drishti.service.scheduling.ScheduleService; import org.joda.time.LocalDate; import org.joda.time.LocalTime; import org.motechproject.scheduletracking.api.service.ScheduleTrackingService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import static java.lang.Integer.parseInt; import static java.text.MessageFormat.format; import static java.util.Arrays.asList; import static org.ei.drishti.common.util.DateUtil.today; import static org.ei.drishti.common.util.IntegerUtil.tryParse; import static org.ei.drishti.dto.AlertStatus.upcoming; import static org.ei.drishti.dto.BeneficiaryType.ec; import static org.ei.drishti.scheduler.DrishtiScheduleConstants.ECSchedulesConstants.EC_SCHEDULE_OCP_REFILL; import static org.ei.drishti.scheduler.DrishtiScheduleConstants.ECSchedulesConstants.EC_SCHEDULE_OCP_REFILL_MILESTONE; import static org.joda.time.DateTimeConstants.DAYS_PER_WEEK; import static org.joda.time.LocalDate.parse; @Component public class OCPStrategy implements FPMethodStrategy { public static final int NUMBER_OF_PILLS_IN_ONE_OCP_STRIP = 28; public static final int DUE_WINDOW_PERIOD_IN_WEEKS = 1; private static Logger logger = LoggerFactory.getLogger(OCPStrategy.class.toString()); private final ScheduleTrackingService scheduleTrackingService; private final ActionService actionService; private final ScheduleService scheduleService; private final LocalTime preferredTime; private final Schedule ocpRefillSchedule = new Schedule(EC_SCHEDULE_OCP_REFILL, asList(EC_SCHEDULE_OCP_REFILL_MILESTONE)); @Autowired public OCPStrategy(ScheduleTrackingService scheduleTrackingService, ActionService actionService, ScheduleService scheduleService, @Value("#{drishti['preferred.time']}") int preferredTime) { this.scheduleTrackingService = scheduleTrackingService; this.actionService = actionService; this.scheduleService = scheduleService; this.preferredTime = new LocalTime(preferredTime, 0); } @Override public void registerEC(FPProductInformation fpInfo) { enrollECToOCPRefillSchedule(fpInfo.entityId(), fpInfo.numberOfOCPStripsSupplied(), fpInfo.ocpRefillDate()); } @Override public void unEnrollFromPreviousScheduleAsFPMethodChanged(FPProductInformation fpInfo) { logger.info(format("Un-enrolling EC from OCP Refill schedule. entityId: {0}, new fp method: {1}", fpInfo.entityId(), fpInfo.currentFPMethod())); scheduleTrackingService.unenroll(fpInfo.entityId(), asList(ocpRefillSchedule.name())); actionService.markAlertAsClosed(fpInfo.entityId(), fpInfo.anmId(), ocpRefillSchedule.name(), fpInfo.fpMethodChangeDate()); } @Override public void enrollToNewScheduleForNewFPMethod(FPProductInformation fpInfo) { enrollECToOCPRefillSchedule(fpInfo.entityId(), fpInfo.numberOfOCPStripsSupplied(), fpInfo.fpMethodChangeDate()); } @Override public void renewFPProduct(FPProductInformation fpInfo) { if (tryParse(fpInfo.numberOfOCPStripsSupplied(), 0) <= 0) { return; } logger.info(format("Fulfilling OCP Refill schedule as FP product was renewed. entityId: {0}, ocpRefillDate: {1}, numberOfOCPStripsSupplied: {2}", fpInfo.entityId(), fpInfo.ocpRefillDate(), fpInfo.numberOfOCPStripsSupplied())); scheduleTrackingService.fulfillCurrentMilestone(fpInfo.entityId(), ocpRefillSchedule.name(), parse(fpInfo.submissionDate())); actionService.markAlertAsClosed(fpInfo.entityId(), fpInfo.anmId(), ocpRefillSchedule.name(), fpInfo.ocpRefillDate()); enrollECToOCPRefillSchedule(fpInfo.entityId(), fpInfo.numberOfOCPStripsSupplied(), fpInfo.ocpRefillDate()); } @Override public void fpFollowup(FPProductInformation fpInfo) { } private void enrollECToOCPRefillSchedule(String entityId, String numberOfOCPStripsSupplied, String ocpRefillDate) { LocalDate scheduleStartDate = (tryParse(numberOfOCPStripsSupplied, 0) == 0) ? today() : twoWeeksBeforeOCPPillsRunOut(numberOfOCPStripsSupplied, ocpRefillDate); logger.info(format("Enrolling EC to OCP Refill schedule. entityId: {0}, Refill date: {1}, Ref date: {2}, Number of OCP Strips : {3}", entityId, ocpRefillDate, scheduleStartDate, numberOfOCPStripsSupplied)); scheduleService.enroll(entityId, ocpRefillSchedule.name(), scheduleStartDate.toString()); actionService.alertForBeneficiary(ec, entityId, EC_SCHEDULE_OCP_REFILL, EC_SCHEDULE_OCP_REFILL_MILESTONE, upcoming, scheduleStartDate.toDateTime(preferredTime), scheduleStartDate.plusWeeks(DUE_WINDOW_PERIOD_IN_WEEKS).toDateTime(preferredTime)); } private LocalDate twoWeeksBeforeOCPPillsRunOut(String numberOfOCPStripsSupplied, String ocpRefillDate) { return parse(ocpRefillDate) .plusDays(parseInt(numberOfOCPStripsSupplied) * NUMBER_OF_PILLS_IN_ONE_OCP_STRIP) .minusDays(2 * DAYS_PER_WEEK); } }