/*
* Electronic Logistics Management Information System (eLMIS) is a supply chain management system for health commodities in a developing country setting.
*
* Copyright (C) 2015 John Snow, Inc (JSI). This program was produced for the U.S. Agency for International Development (USAID). It was prepared under the USAID | DELIVER PROJECT, Task Order 4.
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openlmis.vaccine.service.reports;
import lombok.NoArgsConstructor;
import org.joda.time.DateTime;
import org.joda.time.Months;
import org.joda.time.format.DateTimeFormat;
import org.openlmis.core.domain.GeographicZone;
import org.openlmis.core.repository.ProcessingPeriodRepository;
import org.openlmis.core.service.*;
import org.openlmis.ivdform.domain.reports.*;
import org.openlmis.report.mapper.PerformanceCoverageReportMapper;
import org.openlmis.vaccine.domain.reports.VaccineCoverageReport;
import org.openlmis.report.mapper.PerformanceByDropoutRateByDistrictMapper;
import org.openlmis.vaccine.repository.reports.VaccineReportRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
@NoArgsConstructor
public class VaccineReportService {
private static final Logger LOGGER = LoggerFactory.getLogger(VaccineReportService.class);
public static final String VACCINE_REPORT_VACCINE_CATEGORY_CODE = "VACCINE_REPORT_VACCINE_CATEGORY_CODE";
public static final String VACCINE_REPORT_VITAMINS_CATEGORY_CODE = "VACCINE_REPORT_VITAMINS_CATEGORY_CODE";
public static final String VACCINE_REPORT_SYRINGES_CATEGORY_CODE = "VACCINE_REPORT_SYRINGES_CATEGORY_CODE";
@Autowired
private PerformanceByDropoutRateByDistrictMapper dropoutRateByDistrictMapper;
@Autowired
VaccineReportRepository repository;
@Autowired
ProgramProductService programProductService;
@Autowired
ProcessingPeriodRepository periodService;
@Autowired
ProgramService programService;
@Autowired
MessageService messageService;
@Autowired
ConfigurationSettingService configurationSettingService;
@Autowired
GeographicZoneService geographicZoneService;
@Autowired
private PerformanceCoverageReportMapper reportMapper;
private static final String DATE_FORMAT = "yyyy-MM-dd";
public Long getReportIdForFacilityAndPeriod(Long facilityId, Long periodId) {
return repository.getReportIdForFacilityAndPeriod(facilityId, periodId);
}
private List<DiseaseLineItem> getDiseaseSurveillance(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getDiseaseSurveillance(reportId,userId);
}
return repository.getDiseaseSurveillanceAggregateReport(periodId, zoneId, userId);
}
private Map<String, DiseaseLineItem> getCumulativeDiseaseSurveillance(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getCumFacilityDiseaseSurveillance(reportId, facilityId, userId);
}
return repository.getCumDiseaseSurveillanceAggregateReport(periodId, zoneId, userId);
}
private List<ColdChainLineItem> getColdChain(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getColdChain(reportId, userId);
}
return repository.getColdChainAggregateReport(periodId, zoneId, userId);
}
private List<AdverseEffectLineItem> getAdverseEffectReport(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getAdverseEffectReport(reportId, userId);
}
return repository.getAdverseEffectAggregateReport(periodId, zoneId, userId);
}
private List<HashMap<String, Object>> getVaccineCoverageReport(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getVaccineCoverageReport(reportId, userId);
}
return repository.getVaccineCoverageAggregateReport(periodId, zoneId, userId);
}
private Map<String, VaccineCoverageReport> calculateVaccineCoverageReport(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.calculateVaccineCoverageReportForFacility(reportId, facilityId, userId);
}
return repository.calculateVaccineCoverageReport(periodId, zoneId, userId);
}
private List<VaccineReport> getImmunizationSession(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getImmunizationSession(reportId);
}
return repository.getImmunizationSessionAggregate(periodId, zoneId, userId);
}
private List<HashMap<String, Object>> getVaccineReport(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getVaccinationReport(VACCINE_REPORT_VACCINE_CATEGORY_CODE, reportId,userId);
} else {
return repository.getVaccinationAggregateByGeoZoneReport(VACCINE_REPORT_VACCINE_CATEGORY_CODE, periodId, zoneId, userId);
}
}
private List<HashMap<String, Object>> getSyringeAndSafetyBoxReport(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getVaccinationReport(VACCINE_REPORT_SYRINGES_CATEGORY_CODE, reportId, userId);
}
return repository.getVaccinationAggregateByGeoZoneReport(VACCINE_REPORT_SYRINGES_CATEGORY_CODE, periodId, zoneId,userId);
}
private List<HashMap<String, Object>> getVitaminsReport(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getVaccinationReport(VACCINE_REPORT_VITAMINS_CATEGORY_CODE, reportId,userId);
}
return repository.getVaccinationAggregateByGeoZoneReport(VACCINE_REPORT_VITAMINS_CATEGORY_CODE, periodId, zoneId,userId);
}
private List<HashMap<String, Object>> getTargetPopulation(Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getTargetPopulation(facilityId, periodId);
}
return repository.getTargetPopulationAggregateByGeoZone(periodId, zoneId, userId);
}
private List<VitaminSupplementationLineItem> getVitaminSupplementationReport(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getVitaminSupplementationReport(reportId);
}
return repository.getVitaminSupplementationAggregateReport(periodId, zoneId, userId);
}
private List<HashMap<String, Object>> getDropOuts(Long reportId, Long facilityId, Long periodId, Long zoneId,Long userId) {
if (facilityId != null && facilityId != 0) {
return repository.getDropOuts(reportId, userId);
}
return repository.getAggregateDropOuts(periodId, zoneId, userId);
}
public List<HashMap<String, Object>> vaccineUsageTrend(String facilityCode, String productCode, Long periodId, Long zoneId, Long userId) {
List<HashMap<String, Object>> vaccineUsageTrend = null;
Long districtId;
try {
if (zoneId == -1 || zoneId == 0) {
districtId = getNationalZoneId();
} else {
districtId = zoneId;
}
if ((facilityCode == null || facilityCode.isEmpty()) && periodId != 0) {
vaccineUsageTrend = repository.vaccineUsageTrendByGeographicZone(periodId, districtId, productCode,userId);
} else {
vaccineUsageTrend = repository.vaccineUsageTrend(facilityCode, productCode,userId);
}
} catch (Exception ex) {
LOGGER.warn("Error Message: ", ex);
}
return vaccineUsageTrend;
}
public Map<String, Object> getMonthlyVaccineReport(Long facilityId, Long periodId, Long zoneId,Long userId) {
Map<String, Object> data = new HashMap();
Long reportId = null;
Long districtId;
if (facilityId != null && facilityId != 0) {
reportId = getReportIdForFacilityAndPeriod(facilityId, periodId);
}
if (zoneId == -1 || zoneId == 0) {
districtId = getNationalZoneId();
} else {
districtId = zoneId;
}
try {
data.put("vaccination", getVaccineReport(reportId, facilityId, periodId, districtId,userId));
data.put("diseaseSurveillance", getDiseaseSurveillance(reportId, facilityId, periodId, districtId,userId));
data.put("cumDiseaseSurveillance", this.getCumulativeDiseaseSurveillance(reportId, facilityId, periodId, districtId,userId));
data.put("vaccineCoverage", getVaccineCoverageReport(reportId, facilityId, periodId, districtId,userId));
data.put("vaccineCoverageCalculation", calculateVaccineCoverageReport(reportId, facilityId, periodId, districtId,userId));
data.put("immunizationSession", getImmunizationSession(reportId, facilityId, periodId, districtId,userId));
data.put("vitaminSupplementation", getVitaminSupplementationReport(reportId, facilityId, periodId, districtId,userId));
data.put("adverseEffect", getAdverseEffectReport(reportId, facilityId, periodId, districtId,userId));
data.put("coldChain", getColdChain(reportId, facilityId, periodId, districtId,userId));
data.put("targetPopulation", getTargetPopulation(facilityId, periodId, districtId,userId));
data.put("syringes", getSyringeAndSafetyBoxReport(reportId, facilityId, periodId, districtId,userId));
data.put("vitamins", getVitaminsReport(reportId, facilityId, periodId, districtId,userId));
data.put("dropOuts", getDropOuts(reportId, facilityId, periodId, districtId,userId));
} catch (Exception ex) {
LOGGER.warn("error while loading Reporting summary:... ", ex);
}
return data;
}
private Long getNationalZoneId() {
return repository.getNationalZone().getId();
}
public Map<String, List<Map<String, Object>>> getPerformanceCoverageReportData(String periodStart, String periodEnd,
Long districtId, Long productId, Long doseId, Long userId) {
Date startDate, endDate;
startDate = DateTimeFormat.forPattern(DATE_FORMAT).parseDateTime(periodStart).toDate();
endDate = DateTimeFormat.forPattern(DATE_FORMAT).parseDateTime(periodEnd).toDate();
Map<String, List<Map<String, Object>>> result = new HashMap<>();
GeographicZone zone = geographicZoneService.getById(districtId);
if (districtId == 0) {
result.put("mainreportRegionAggregate", repository.getPerformanceCoverageMainReportDataByRegionAggregate(startDate, endDate, districtId, productId, doseId, userId));
result.put("summaryRegionAggregate", repository.getPerformanceCoverageSummaryReportDataByRegionAggregate(startDate, endDate, districtId, productId, doseId, userId));
result.put("regionPopulation", repository.getClassficationVaccinePopulationForRegion(startDate,endDate,districtId,productId,doseId));
}
if (zone != null && zone.getLevel().getCode().equals("dist")) {
result.put("mainreport", repository.getPerformanceCoverageMainReportDataByDistrict(startDate, endDate, districtId, productId, doseId, userId));
result.put("summary", repository.getPerformanceCoverageSummaryReportDataByDistrict(startDate, endDate, districtId, productId, doseId, userId));
result.put("population", repository.getClassficationVaccinePopulationForFacility(startDate, endDate, districtId, productId,doseId));
} else {
result.put("mainreport", repository.getPerformanceCoverageMainReportDataByRegion(startDate, endDate, districtId, productId, doseId, userId));
result.put("summary", repository.getPerformanceCoverageSummaryReportDataByRegion(startDate, endDate, districtId, productId, doseId, userId));
result.put("population", repository.getClassficationVaccinePopulationForDistrict(startDate,endDate,districtId,productId,doseId));
}
result.put("summaryPeriodLists", getSummaryPeriodList(startDate, endDate));
return result;
}
public Map<String, List<Map<String, Object>>> getCompletenessAndTimelinessReportData(String periodStart, String periodEnd,
Long districtId) {
Date startDate, endDate;
startDate = DateTimeFormat.forPattern(DATE_FORMAT).parseDateTime(periodStart).toDate();
endDate = DateTimeFormat.forPattern(DATE_FORMAT).parseDateTime(periodEnd).toDate();
Map<String, List<Map<String, Object>>> result = new HashMap<>();
result.put("mainreport", repository.getCompletenessAndTimelinessMainReportDataByDistrict(startDate, endDate, districtId));
result.put("summary", repository.getCompletenessAndTimelinessSummaryReportDataByDistrict(startDate, endDate, districtId));
result.put("summaryPeriodLists", getSummaryPeriodList(startDate, endDate));
return result;
}
public Map<String, List<Map<String, Object>>> getAdequacyLevelOfSupply(String periodStart, String periodEnd, Long districtId,
Long productId) {
Date startDate, endDate;
startDate = DateTimeFormat.forPattern(DATE_FORMAT).parseDateTime(periodStart).toDate();
endDate = DateTimeFormat.forPattern(DATE_FORMAT).parseDateTime(periodEnd).toDate();
Map<String, List<Map<String, Object>>> result = new HashMap<>();
result.put("bydistrict", repository.getAdequacyLevelOfSupplyByDistrict(startDate, endDate, districtId, productId));
result.put("byregion", repository.getAdequacyLevelOfSupplyByRegion(startDate, endDate, districtId, productId));
result.put("summaryPeriodLists", getSummaryPeriodList(startDate, endDate));
return result;
}
private static List<Map<String, Object>> getSummaryPeriodList(Date startDate, Date endDate) {
DateTime periodStart = new DateTime(startDate);
DateTime periodEnd = new DateTime(endDate);
int monthDiff = Months.monthsBetween(periodStart.withDayOfMonth(1), periodEnd.withDayOfMonth(1)).getMonths();
DateTime temp = periodStart.withDayOfMonth(1);
List<Map<String, Object>> list = new ArrayList<>();
while (monthDiff >= 0) {
Map<String, Object> period = new HashMap<>();
period.put("year", temp.getYear());
period.put("month", temp.getMonthOfYear());
period.put("monthString", temp.toString("MMM"));
monthDiff--;
list.add(period);
temp = temp.plusMonths(1);
}
return list;
}
public List<Map<String, Object>> getVaccineProductsList() {
return this.repository.getVaccineProductsList();
}
public Map<String, List<Map<String, Object>>> getClassificationVaccineUtilizationPerformance(String periodStart, String periodEnd, Long zoneId, Long productId) {
Map<String, List<Map<String, Object>>> result = new HashMap<>();
boolean regionReport;
boolean facilityReport;
regionReport = zoneId == 0 ? true : false;
facilityReport = dropoutRateByDistrictMapper.isDistrictLevel(zoneId) > 0 ? true : false;
try {
Date startDate;
Date endDate;
Date yearStartDate;
startDate = DateTimeFormat.forPattern(DATE_FORMAT).parseDateTime(periodStart).toDate();
endDate = DateTimeFormat.forPattern(DATE_FORMAT).parseDateTime(periodEnd).toDate();
yearStartDate = getStartOfTheYearDate(startDate);
if (regionReport) {
result.put("regionReport", repository.getClassificationVaccineUtilizationPerformanceRegion(yearStartDate, endDate, zoneId, productId));
result.put("regionPopulation", repository.getClassficationVaccinePopulationForRegion(yearStartDate, endDate, zoneId, productId));
}
if (facilityReport) {
result.put("facilityReport", repository.getClassificationVaccineUtilizationPerformanceFacility(yearStartDate, endDate, zoneId, productId));
result.put("population", repository.getClassficationVaccinePopulationForFacility(yearStartDate, endDate, zoneId, productId));
} else {
result.put("zoneReport", repository.getClassificationVaccineUtilizationPerformanceByZone(yearStartDate, endDate, zoneId, productId));
result.put("population", repository.getClassficationVaccinePopulationForDistrict(yearStartDate, endDate, zoneId, productId));
}
result.put("summaryPeriodLists", getPaddingSummaryPeriodList(startDate, endDate));
} catch (Exception ex) {
LOGGER.warn("Error Message: ", ex);
}
return result;
}
public Map<String, List<Map<String, Object>>> getCategorizationVaccineUtilizationPerformance(String periodStart, String periodEnd, Long zoneId, Long productId) {
Map<String, List<Map<String, Object>>> result = new HashMap<>();
boolean regionReport;
boolean facilityReport;
regionReport = zoneId == 0 ? true : false;
facilityReport = dropoutRateByDistrictMapper.isDistrictLevel(zoneId) > 0 ? true : false;
try {
Date startDate;
Date endDate;
Date yearStartDate;
startDate = DateTimeFormat.forPattern(DATE_FORMAT).parseDateTime(periodStart).toDate();
endDate = DateTimeFormat.forPattern(DATE_FORMAT).parseDateTime(periodEnd).toDate();
yearStartDate = getStartOfTheYearDate(startDate);
if (regionReport) {
result.put("regionReport", repository.getCategorizationVaccineUtilizationPerformanceRegion(yearStartDate, endDate, zoneId, productId));
result.put("regionPopulation", repository.getClassficationVaccinePopulationForRegion(yearStartDate, endDate, zoneId, productId));
}
if (facilityReport) {
result.put("facilityReport", repository.getCategorizationVaccineUtilizationPerformanceFacility(yearStartDate, endDate, zoneId, productId));
result.put("population", repository.getClassficationVaccinePopulationForFacility(yearStartDate, endDate, zoneId, productId));
} else {
result.put("zoneReport", repository.getCategorizationVaccineUtilizationPerformanceByZone(yearStartDate, endDate, zoneId, productId));
result.put("population", repository.getClassficationVaccinePopulationForDistrict(yearStartDate, endDate, zoneId, productId));
}
result.put("summaryPeriodLists", getPaddingSummaryPeriodList(startDate, endDate));
} catch (Exception ex) {
LOGGER.warn("Error Message: ", ex);
}
return result;
}
private static Date getStartOfTheYearDate(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.MONTH, Calendar.JANUARY);
calendar.set(Calendar.DATE, 1);
return calendar.getTime();
}
private static List<Map<String, Object>> getPaddingSummaryPeriodList(Date startDate, Date endDate) {
Date yearStartDate = getStartOfTheYearDate(startDate);
List<Map<String, Object>> paddingDateList = getSummaryPeriodList(yearStartDate, new DateTime(startDate).minusMonths(1).toDate());
for (Map paddingMapDate : paddingDateList) {
paddingMapDate.put("hide", "true");
}
List<Map<String, Object>> summaryateList = getSummaryPeriodList(startDate, endDate);
paddingDateList.addAll(summaryateList);
return paddingDateList;
}
public List<Map<String,Object>> loadYearList(){
return repository.loadYearList();
}
public Map<String,String> getCoverageAndDropoutCoeffients( Long productId){
return repository.getCoverageAndDropoutCoeffients(productId);
}
}