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.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_CONDOM_REFILL; import static org.ei.drishti.scheduler.DrishtiScheduleConstants.ECSchedulesConstants.EC_SCHEDULE_CONDOM_REFILL_MILESTONE; import static org.joda.time.LocalDate.parse; @Component public class CondomStrategy implements FPMethodStrategy { private static final int DUE_WINDOW_PERIOD_IN_WEEKS = 1; private static Logger logger = LoggerFactory.getLogger(CondomStrategy.class.toString()); private final ScheduleTrackingService scheduleTrackingService; private final ActionService actionService; private final ScheduleService scheduleService; private final Schedule condomRefillSchedule = new Schedule(EC_SCHEDULE_CONDOM_REFILL, asList(EC_SCHEDULE_CONDOM_REFILL_MILESTONE)); private LocalTime preferredTime; @Autowired public CondomStrategy(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) { enrollECToCondomRefillSchedule(fpInfo.entityId()); } @Override public void unEnrollFromPreviousScheduleAsFPMethodChanged(FPProductInformation fpInfo) { logger.info(format("Un-enrolling EC from Condom Refill schedule as FP method changed. entityId: {0}, new fp method: {1}", fpInfo.entityId(), fpInfo.currentFPMethod())); scheduleTrackingService.unenroll(fpInfo.entityId(), asList(condomRefillSchedule.name())); actionService.markAlertAsClosed(fpInfo.entityId(), fpInfo.anmId(), condomRefillSchedule.name(), fpInfo.fpMethodChangeDate()); } @Override public void enrollToNewScheduleForNewFPMethod(FPProductInformation fpInfo) { enrollECToCondomRefillSchedule(fpInfo.entityId()); } @Override public void renewFPProduct(FPProductInformation fpInfo) { if (tryParse(fpInfo.numberOfCondomsSupplied(), 0) <= 0) { return; } logger.info(format("Fulfilling Condom Refill schedule as FP product was renewed. entityId: {0}, condomRefillDate: {1}, numberOfCondomsSupplied: {2}", fpInfo.entityId(), fpInfo.submissionDate(), fpInfo.numberOfCondomsSupplied())); scheduleTrackingService.fulfillCurrentMilestone(fpInfo.entityId(), condomRefillSchedule.name(), parse(fpInfo.submissionDate())); actionService.markAlertAsClosed(fpInfo.entityId(), fpInfo.anmId(), condomRefillSchedule.name(), fpInfo.submissionDate()); enrollECToCondomRefillSchedule(fpInfo.entityId()); } @Override public void fpFollowup(FPProductInformation fpInfo) { } private void enrollECToCondomRefillSchedule(String entityId) { logger.info(format("Enrolling EC to Condom Refill schedule. entityId: {0}, Ref date: {1}", entityId, firstDayOfNextMonth())); scheduleService.enroll(entityId, condomRefillSchedule.name(), firstDayOfNextMonth().toString()); actionService.alertForBeneficiary(ec, entityId, condomRefillSchedule.name(), EC_SCHEDULE_CONDOM_REFILL_MILESTONE, upcoming, firstDayOfNextMonth().toDateTime(preferredTime), firstDayOfNextMonth().plusWeeks(DUE_WINDOW_PERIOD_IN_WEEKS).toDateTime(preferredTime)); } private LocalDate firstDayOfNextMonth() { return today().plusMonths(1).withDayOfMonth(1); } }