package org.openlmis.rnr.service; import org.openlmis.core.domain.*; import org.openlmis.core.exception.DataException; import org.openlmis.core.message.OpenLmisMessage; import org.openlmis.core.service.*; import org.openlmis.db.repository.mapper.DbMapper; import org.openlmis.equipment.domain.EquipmentInventory; import org.openlmis.equipment.service.EquipmentInventoryService; import org.openlmis.rnr.domain.*; import org.openlmis.rnr.dto.RnrDTO; import org.openlmis.rnr.repository.RequisitionRepository; import org.openlmis.rnr.search.criteria.RequisitionSearchCriteria; import org.openlmis.rnr.search.factory.RequisitionSearchStrategyFactory; import org.openlmis.rnr.search.strategy.RequisitionSearchStrategy; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.*; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static org.openlmis.core.domain.RightName.*; import static org.openlmis.rnr.domain.RnrStatus.*; import static org.springframework.util.CollectionUtils.isEmpty; /** * Exposes the services for handling Rnr entity. */ @Service public class RequisitionService { public static final String RNR_AUTHORIZATION_ERROR = "error.rnr.authorization"; public static final String RNR_SUBMISSION_ERROR = "error.rnr.submission"; public static final String RNR_OPERATION_UNAUTHORIZED = "error.rnr.operation.unauthorized"; public static final String RNR_AUTHORIZED_SUCCESSFULLY = "msg.rnr.authorized.success"; public static final String RNR_SUBMITTED_SUCCESSFULLY = "msg.rnr.submitted.success"; public static final String RNR_AUTHORIZED_SUCCESSFULLY_WITHOUT_SUPERVISOR = "msg.rnr.authorized.without.supervisor"; public static final String RNR_APPROVED_SUCCESSFULLY_WITHOUT_SUPERVISOR = "msg.rnr.approved.without.supervisor"; public static final String NO_SUPERVISORY_NODE_CONTACT_ADMIN = "msg.rnr.submitted.without.supervisor"; public static final String RNR_APPROVED_SUCCESSFULLY = "msg.rnr.approved.success"; public static final String APPROVAL_NOT_ALLOWED = "rnr.approval.not.allowed"; public static final String SEARCH_ALL = "all"; public static final String SEARCH_PROGRAM_NAME = "programName"; public static final String SEARCH_FACILITY_CODE = "facilityCode"; public static final String SEARCH_FACILITY_NAME = "facilityName"; public static final String SEARCH_SUPPLYING_DEPOT_NAME = "supplyingDepot"; public static final String CONVERT_TO_ORDER_PAGE_SIZE = "order.page.size"; public static final String NUMBER_OF_PAGES = "number_of_pages"; @Autowired private RequisitionRepository requisitionRepository; @Autowired private RnrTemplateService rnrTemplateService; @Autowired private FacilityApprovedProductService facilityApprovedProductService; @Autowired private SupervisoryNodeService supervisoryNodeService; @Autowired private RoleAssignmentService roleAssignmentService; @Autowired private ProgramService programService; @Autowired private ProcessingScheduleService processingScheduleService; @Autowired private FacilityService facilityService; @Autowired private SupplyLineService supplyLineService; @Autowired private RequisitionPermissionService requisitionPermissionService; @Autowired private UserService userService; @Autowired private RequisitionEventService requisitionEventService; @Autowired private RegimenService regimenService; @Autowired private RegimenColumnService regimenColumnService; @Autowired private ProgramProductService programProductService; @Autowired private StaticReferenceDataService staticReferenceDataService; @Autowired private CalculationService calculationService; @Autowired private DbMapper dbMapper; @Autowired private BudgetLineItemService budgetLineItemService; @Autowired private StatusChangeEventService statusChangeEventService; @Autowired private EquipmentInventoryService equipmentInventoryService; @Autowired private ConfigurationSettingService configurationSettingsService; private RequisitionSearchStrategyFactory requisitionSearchStrategyFactory; @Autowired private ProductPriceScheduleService priceScheduleService; @Autowired public void setRequisitionSearchStrategyFactory(RequisitionSearchStrategyFactory requisitionSearchStrategyFactory) { this.requisitionSearchStrategyFactory = requisitionSearchStrategyFactory; } @Transactional public Rnr initiate(Facility facility, Program program, Long modifiedBy, Boolean emergency, ProcessingPeriod proposedPeriod, String sourceApplication) { if (!requisitionPermissionService.hasPermission(modifiedBy, facility, program, CREATE_REQUISITION)) { throw new DataException(RNR_OPERATION_UNAUTHORIZED); } ProgramRnrTemplate rnrTemplate = rnrTemplateService.fetchProgramTemplateForRequisition(program.getId()); if (rnrTemplate.getColumns().size() == 0) { throw new DataException("error.rnr.template.not.defined"); } program = programService.getById(program.getId()); ProcessingPeriod period = findPeriod(facility, program, emergency); if (proposedPeriod != null) { if (proposedPeriod.getId() != period.getId()) { // take caution in this case. // todo: log a warning here. period = proposedPeriod; } } List<FacilityTypeApprovedProduct> facilityTypeApprovedProducts = facilityApprovedProductService.getFullSupplyFacilityApprovedProductByFacilityAndProgram( facility.getId(), program.getId()); //N:B If usePriceSchedule is selected for the selected program, use the product price from price_schedule table if (program.getUsePriceSchedule()) populateProductsPriceBasedOnPriceSchedule(facility.getId(), program.getId(), facilityTypeApprovedProducts); //non intrusive on the legacy setup List<Regimen> regimens = regimenService.getByProgram(program.getId()); RegimenTemplate regimenTemplate = regimenColumnService.getRegimenTemplateByProgramId(program.getId()); Rnr requisition = new Rnr(facility, program, period, emergency, facilityTypeApprovedProducts, regimens, modifiedBy); requisition.setCreatedDate(dbMapper.getCurrentTimeStamp()); populateAllocatedBudget(requisition); calculationService.fillFieldsForInitiatedRequisition(requisition, rnrTemplate, regimenTemplate); calculationService.fillReportingDays(requisition); if (!emergency && configurationSettingsService.getBoolValue(ConfigurationSettingKey.RNR_COPY_SKIPPED_FROM_PREVIOUS_RNR)) { calculationService.copySkippedFieldFromPreviousPeriod(requisition); } if (emergency && program.getHideSkippedProducts()) { calculationService.skipAllLineItems(requisition); } // if program supports equipments, initialize it here. if (program.getIsEquipmentConfigured()) { populateEquipments(requisition); } requisition.setSourceApplication(sourceApplication); insert(requisition); requisition = requisitionRepository.getById(requisition.getId()); return fillSupportingInfo(requisition); } public void populateProductsPriceBasedOnPriceSchedule(Long facilityId, Long programId, List<FacilityTypeApprovedProduct> facilityTypeApprovedProducts) { List<ProductPriceSchedule> productPriceSchedules = priceScheduleService.getPriceScheduleFullSupplyFacilityApprovedProduct(programId, facilityId); for (ProductPriceSchedule productPriceSchedule : productPriceSchedules) { Optional<FacilityTypeApprovedProduct> facilityTypeApprovedProduct = facilityTypeApprovedProducts .parallelStream() .filter(f -> f.getProgramProduct().getProduct().getId().equals(productPriceSchedule.getProduct().getId())) .findFirst(); facilityTypeApprovedProduct .ifPresent( facilityTypeApprovedProduct1 -> facilityTypeApprovedProduct1 .getProgramProduct() .setCurrentPrice(new Money(BigDecimal.valueOf(productPriceSchedule.getPrice()))) ); } } private void populateEquipments(Rnr requisition) { List<EquipmentInventory> inventories = equipmentInventoryService.getInventoryForFacility(requisition.getFacility().getId(), requisition.getProgram().getId()); requisition.setEquipmentLineItems(new ArrayList<EquipmentLineItem>()); for (EquipmentInventory inv : inventories) { EquipmentLineItem lineItem = new EquipmentLineItem(); lineItem.setRnrId(requisition.getId()); lineItem.setEquipmentSerial(inv.getSerialNumber()); lineItem.setEquipmentInventoryId(inv.getId()); lineItem.setCode(inv.getEquipment().getEquipmentType().getCode()); lineItem.setEquipmentCategory(inv.getEquipment().getEquipmentType().getName()); lineItem.setOperationalStatusId(inv.getOperationalStatusId()); lineItem.setEquipmentName(inv.getEquipment().getName()); lineItem.setDaysOutOfUse(0L); requisition.getEquipmentLineItems().add(lineItem); } } private void populateAllocatedBudget(Rnr requisition) { if (requisition.isBudgetingApplicable()) { BudgetLineItem budgetLineItem = budgetLineItemService.get(requisition.getFacility().getId(), requisition.getProgram().getId(), requisition.getPeriod().getId()); BigDecimal allocatedBudget = (budgetLineItem == null) ? null : budgetLineItem.getAllocatedBudget(); requisition.setAllocatedBudget(allocatedBudget); } } @Transactional public Rnr save(Rnr rnr) { Rnr savedRnr = getFullRequisitionById(rnr.getId()); if (!requisitionPermissionService.hasPermissionToSave(rnr.getModifiedBy(), savedRnr)) { throw new DataException(RNR_OPERATION_UNAUTHORIZED); } ProgramRnrTemplate rnrTemplate = rnrTemplateService.fetchProgramTemplate(savedRnr.getProgram().getId()); RegimenTemplate regimenTemplate = regimenColumnService.getRegimenTemplateByProgramId(savedRnr.getProgram().getId()); if (savedRnr.getStatus() == AUTHORIZED || savedRnr.getStatus() == IN_APPROVAL) { savedRnr.copyApproverEditableFields(rnr, rnrTemplate); } else { List<ProgramProduct> programProducts = programProductService.getNonFullSupplyProductsForProgram(savedRnr.getProgram()); savedRnr.copyCreatorEditableFields(rnr, rnrTemplate, regimenTemplate, programProducts); //TODO: copy only the editable fields. savedRnr.setEquipmentLineItems(rnr.getEquipmentLineItems()); } requisitionRepository.update(savedRnr); return savedRnr; } @Transactional public Rnr submit(Rnr rnr) { Rnr savedRnr = getFullRequisitionById(rnr.getId()); if (savedRnr.getStatus() != INITIATED) throw new DataException(new OpenLmisMessage(RNR_SUBMISSION_ERROR)); savedRnr.validateRegimenLineItems(regimenColumnService.getRegimenTemplateByProgramId(savedRnr.getProgram().getId())); if (!requisitionPermissionService.hasPermission(rnr.getModifiedBy(), savedRnr, CREATE_REQUISITION)) throw new DataException(RNR_OPERATION_UNAUTHORIZED); savedRnr.setAuditFieldsForRequisition(rnr.getModifiedBy(), SUBMITTED); ProgramRnrTemplate template = rnrTemplateService.fetchProgramTemplate(savedRnr.getProgram().getId()); calculationService.perform(savedRnr, template); return update(savedRnr); } @Transactional public Rnr authorize(Rnr rnr) { Rnr savedRnr = getFullRequisitionById(rnr.getId()); if (savedRnr.getStatus() != SUBMITTED) throw new DataException(new OpenLmisMessage(RNR_AUTHORIZATION_ERROR)); savedRnr.validateRegimenLineItems(regimenColumnService.getRegimenTemplateByProgramId(savedRnr.getProgram().getId())); if (!requisitionPermissionService.hasPermission(rnr.getModifiedBy(), savedRnr, AUTHORIZE_REQUISITION)) throw new DataException(RNR_OPERATION_UNAUTHORIZED); savedRnr.setAuditFieldsForRequisition(rnr.getModifiedBy(), AUTHORIZED); savedRnr.setSupervisoryNodeId(supervisoryNodeService.getFor(savedRnr.getFacility(), savedRnr.getProgram()).getId()); ProgramRnrTemplate template = rnrTemplateService.fetchProgramTemplate(savedRnr.getProgram().getId()); calculationService.perform(savedRnr, template); savedRnr.setFieldsForApproval(); return update(savedRnr); } @Transactional public Rnr approve(Rnr requisition, String name) { Rnr savedRnr = getFullRequisitionById(requisition.getId()); if (!savedRnr.isApprovable()) throw new DataException(APPROVAL_NOT_ALLOWED); if (!requisitionPermissionService.hasPermission(requisition.getModifiedBy(), savedRnr, APPROVE_REQUISITION)) { throw new DataException(RNR_OPERATION_UNAUTHORIZED); } savedRnr.validateForApproval(); savedRnr.calculateForApproval(); final SupervisoryNode parent = supervisoryNodeService.getParent(savedRnr.getSupervisoryNodeId()); boolean notifyStatusChange = true; if (parent == null) { savedRnr.prepareForFinalApproval(); } else { if (savedRnr.getStatus() == IN_APPROVAL) { notifyStatusChange = false; } savedRnr.approveAndAssignToNextSupervisoryNode(parent); } savedRnr.setModifiedBy(requisition.getModifiedBy()); requisitionRepository.approve(savedRnr); logStatusChangeAndNotify(savedRnr, notifyStatusChange, name); return savedRnr; } public void releaseRequisitionsAsOrder(List<Rnr> requisitions, Long userId) { for (Rnr requisition : requisitions) { Rnr loadedRequisition = requisitionRepository.getById(requisition.getId()); fillSupportingInfo(loadedRequisition); loadedRequisition.convertToOrder(userId); update(loadedRequisition); } } public List<Rnr> get(RequisitionSearchCriteria criteria) { RequisitionSearchStrategy strategy = requisitionSearchStrategyFactory.getSearchStrategy(criteria); List<Rnr> requisitions = strategy.search(); if (requisitions != null) { fillSupportingInfo(requisitions); } return requisitions; } private void fillSupportingInfo(List<Rnr> requisitions) { for (Rnr rnr : requisitions) { fillSupportingInfo(rnr); } } public List<LossesAndAdjustmentsType> getLossesAndAdjustmentsTypes() { return requisitionRepository.getLossesAndAdjustmentsTypes(); } public OpenLmisMessage getSubmitMessageBasedOnSupervisoryNode(Facility facility, Program program) { SupervisoryNode supervisoryNode = supervisoryNodeService.getFor(facility, program); String msg = (supervisoryNode == null) ? NO_SUPERVISORY_NODE_CONTACT_ADMIN : RNR_SUBMITTED_SUCCESSFULLY; return new OpenLmisMessage(msg); } public OpenLmisMessage getAuthorizeMessageBasedOnSupervisoryNode(Facility facility, Program program) { User approver = supervisoryNodeService.getApproverFor(facility, program); String msg = (approver == null) ? RNR_AUTHORIZED_SUCCESSFULLY_WITHOUT_SUPERVISOR : RNR_AUTHORIZED_SUCCESSFULLY; return new OpenLmisMessage(msg); } public OpenLmisMessage getApproveMessageBasedOnParentNode(Rnr rnr) { SupervisoryNode parent = supervisoryNodeService.getParent(rnr.getSupervisoryNodeId()); if (parent != null && supervisoryNodeService.getApproverForGivenSupervisoryNodeAndProgram(parent, rnr.getProgram()) == null) { return new OpenLmisMessage(RNR_APPROVED_SUCCESSFULLY_WITHOUT_SUPERVISOR); } return new OpenLmisMessage(RNR_APPROVED_SUCCESSFULLY); } public Rnr getFullRequisitionById(Long id) { Rnr savedRnr = requisitionRepository.getById(id); fillSupportingInfo(savedRnr); fillSupplyingDepot(savedRnr); savedRnr.setSubmittedDate(getOperationDateFor(savedRnr.getId(), RnrStatus.SUBMITTED.toString())); return savedRnr; } ProcessingPeriod findPeriod(Facility facility, Program program, Boolean emergency) { if (!(emergency || facility.getVirtualFacility())) { return getPeriodForInitiating(facility, program); } ProcessingPeriod currentPeriod = processingScheduleService.getCurrentPeriod(facility.getId(), program.getId(), programService.getProgramStartDate(facility.getId(), program.getId())); if (currentPeriod == null) throw new DataException("error.program.configuration.missing"); return currentPeriod; } public ProcessingPeriod getPeriodForInitiating(Facility facility, Program program) { Date programStartDate = programService.getProgramStartDate(facility.getId(), program.getId()); Rnr lastRegularRequisition = requisitionRepository.getLastRegularRequisition(facility, program); Long periodIdForLastRequisition = null; if (lastRegularRequisition != null) { if (lastRegularRequisition.preAuthorize()) { throw new DataException("error.rnr.previous.not.filled"); } periodIdForLastRequisition = lastRegularRequisition.getPeriod().getId(); } List<ProcessingPeriod> periods = processingScheduleService.getAllPeriodsAfterDateAndPeriod(facility.getId(), program.getId(), programStartDate, periodIdForLastRequisition); if (periods.size() == 0) { throw new DataException("error.program.configuration.missing"); } return periods.get(0); } public List<ProcessingPeriod> getAllPeriodsForInitiatingRequisition(Long facilityId, Long programId) { Date programStartDate = programService.getProgramStartDate(facilityId, programId); Rnr lastRequisitionToEnterThePostSubmitFlow = requisitionRepository.getLastRegularRequisitionToEnterThePostSubmitFlow(facilityId, programId); Long periodIdOfLastRequisitionToEnterPostSubmitFlow = lastRequisitionToEnterThePostSubmitFlow == null ? null : lastRequisitionToEnterThePostSubmitFlow.getPeriod().getId(); List<ProcessingPeriod> periods = processingScheduleService.getAllPeriodsAfterDateAndPeriod(facilityId, programId, programStartDate, periodIdOfLastRequisitionToEnterPostSubmitFlow); List<ProcessingPeriod> rejected = processingScheduleService.getOpenPeriods(facilityId, programId, periodIdOfLastRequisitionToEnterPostSubmitFlow); if (periods == null || periods.isEmpty()) { periods = rejected; } else { if (rejected != null && !rejected.isEmpty()) { periods.addAll(rejected); } } // find the distinct list Set<ProcessingPeriod> finalList = new HashSet<ProcessingPeriod>(periods); periods = new ArrayList<ProcessingPeriod>(finalList); // sort the list of periods by start date Collections.sort(periods, new Comparator<ProcessingPeriod>() { public int compare(ProcessingPeriod o1, ProcessingPeriod o2) { return o1.getStartDate().compareTo(o2.getStartDate()); } }); return periods; } private Rnr fillSupportingInfo(Rnr requisition) { if (requisition == null) { return null; } fillFacilityPeriodProgramWithAuditFields(asList(requisition)); return requisition; } private void fillSupplyingFacility(Rnr... requisitions) { for (Rnr requisition : requisitions) { fillSupplyingDepot(requisition); } } private void fillSupplyingDepot(Rnr requisition) { if (requisition.getSupervisoryNodeId() != null && requisition.getStatus().equals(RnrStatus.APPROVED)) { SupplyLine supplyLine = supplyLineService.getSupplyLineBy(new SupervisoryNode(requisition.getSupervisoryNodeId()), requisition.getProgram()); if (supplyLine != null) requisition.setSupplyingDepot(supplyLine.getSupplyingFacility()); } } @Deprecated public List<Rnr> listForApproval(Long userId) { List<RoleAssignment> assignments = roleAssignmentService.getRoleAssignments(APPROVE_REQUISITION, userId); List<Rnr> requisitionsForApproval = new ArrayList<>(); for (RoleAssignment assignment : assignments) { final List<Rnr> requisitions = requisitionRepository.getAuthorizedRequisitions(assignment); requisitionsForApproval.addAll(requisitions); } fillFacilityPeriodProgramWithAuditFields(requisitionsForApproval); return requisitionsForApproval; } public List<RnrDTO> listForApprovalDto(Long userId) { List<RoleAssignment> assignments = roleAssignmentService.getRoleAssignments(APPROVE_REQUISITION, userId); List<RnrDTO> requisitionsForApproval = new ArrayList<>(); for (RoleAssignment assignment : assignments) { final List<RnrDTO> requisitions = requisitionRepository.getAuthorizedRequisitionsDTOs(assignment); requisitionsForApproval.addAll(requisitions); } return requisitionsForApproval; } public List<RnrLineItem> getNRnrLineItems(String productCode, Rnr rnr, Integer n, Date startDate) { return requisitionRepository.getAuthorizedRegularUnSkippedLineItems(productCode, rnr, n, startDate); } private Rnr update(Rnr requisition) { requisitionRepository.update(requisition); logStatusChangeAndNotify(requisition, true, null); return requisition; } private void logStatusChangeAndNotify(Rnr requisition, boolean notifyStatusChange, String name) { requisitionRepository.logStatusChange(requisition, name); if (notifyStatusChange) { requisitionEventService.notifyForStatusChange(requisition); } // the function call above (notify for status implements sending of notificaiton email. // the benefit of the above call is that the email template is being taken from the administrative settings. // a call to the following method will do the same thing but takes the message template from the messages.properties file. //send RequisitionStatusChangeMail ( requisition ); } private void sendRequisitionStatusChangeMail(Rnr requisition) { List<User> userList = new ArrayList<>(); if (requisition.getStatus().equals(SUBMITTED)) { Long supervisoryNodeId = supervisoryNodeService.getFor(requisition.getFacility(), requisition.getProgram()).getId(); userList = userService.getUsersWithRightInHierarchyUsingBaseNode(supervisoryNodeId, requisition.getProgram(), AUTHORIZE_REQUISITION); userList.addAll(userService.getUsersWithRightInNodeForProgram(requisition.getProgram(), new SupervisoryNode(), AUTHORIZE_REQUISITION)); } else if (requisition.getStatus().equals(AUTHORIZED) || requisition.getStatus().equals(IN_APPROVAL)) { userList = userService.getUsersWithRightInNodeForProgram(requisition.getProgram(), new SupervisoryNode(requisition.getSupervisoryNodeId()), APPROVE_REQUISITION); } else if (requisition.getStatus().equals(APPROVED)) { SupervisoryNode baseSupervisoryNode = supervisoryNodeService.getFor(requisition.getFacility(), requisition.getProgram()); SupplyLine supplyLine = supplyLineService.getSupplyLineBy(new SupervisoryNode(baseSupervisoryNode.getId()), requisition.getProgram()); if (supplyLine != null) { userList = userService.getUsersWithRightOnWarehouse(supplyLine.getSupplyingFacility().getId(), CONVERT_TO_ORDER); } } ArrayList<User> activeUsersWithRight = userService.filterForActiveUsers(userList); statusChangeEventService.notifyUsers(activeUsersWithRight, requisition.getId(), requisition.getFacility(), requisition.getProgram(), requisition.getPeriod(), requisition.getStatus().toString()); } private void insert(Rnr requisition) { requisitionRepository.insert(requisition); logStatusChangeAndNotify(requisition, true, null); } public Integer getCategoryCount(Rnr requisition, boolean fullSupply) { return requisitionRepository.getCategoryCount(requisition, fullSupply); } public void insertComment(Comment comment) { requisitionRepository.insertComment(comment); } public List getCommentsByRnrId(Long rnrId) { List<Comment> comments = requisitionRepository.getCommentsByRnrID(rnrId); for (Comment comment : comments) { User user = userService.getById(comment.getAuthor().getId()); comment.setAuthor(user.basicInformation()); } return comments; } public Rnr getLWById(Long rnrId) { return requisitionRepository.getLWById(rnrId); } public Date getOperationDateFor(Long rnrId, String status) { return requisitionRepository.getOperationDateFor(rnrId, status); } public ProcessingPeriod getCurrentPeriod(RequisitionSearchCriteria criteria) { Date programStartDate = programService.getProgramStartDate(criteria.getFacilityId(), criteria.getProgramId()); return processingScheduleService.getCurrentPeriod(criteria.getFacilityId(), criteria.getProgramId(), programStartDate); } public List<Rnr> getApprovedRequisitionsForCriteriaAndPageNumber(String searchType, String searchVal, Integer pageNumber, Integer totalNumberOfPages, Long userId, String rightName, String sortBy, String sortDirection) { if (pageNumber.equals(1) && totalNumberOfPages.equals(0)) return new ArrayList<>(); if (pageNumber <= 0 || pageNumber > totalNumberOfPages) throw new DataException("error.page.not.found"); Integer pageSize = Integer.parseInt(staticReferenceDataService.getPropertyValue(CONVERT_TO_ORDER_PAGE_SIZE)); List<Rnr> requisitions = requisitionRepository.getApprovedRequisitionsForCriteriaAndPageNumber(searchType, searchVal, pageNumber, pageSize, userId, rightName, sortBy, sortDirection); fillFacilityPeriodProgramWithAuditFields(requisitions); fillSupplyingFacility(requisitions.toArray(new Rnr[requisitions.size()])); return requisitions; } public Integer getNumberOfPagesOfApprovedRequisitionsForCriteria(String searchType, String searchVal, Long userId, String rightName) { Integer approvedRequisitionsByCriteria = requisitionRepository.getCountOfApprovedRequisitionsForCriteria(searchType, searchVal, userId, rightName); Integer pageSize = Integer.parseInt(staticReferenceDataService.getPropertyValue(CONVERT_TO_ORDER_PAGE_SIZE)); return (int) Math.ceil(approvedRequisitionsByCriteria.doubleValue() / pageSize.doubleValue()); } public List<ProcessingPeriod> getProcessingPeriods(RequisitionSearchCriteria criteria) { if (!criteria.isEmergency()) { return getAllPeriodsForInitiatingRequisition(criteria.getFacilityId(), criteria.getProgramId()); } ProcessingPeriod currentPeriod = getCurrentPeriod(criteria); return currentPeriod == null ? null : asList(currentPeriod); } public List<Rnr> getRequisitionsFor(RequisitionSearchCriteria criteria, List<ProcessingPeriod> periodList) { if (isEmpty(periodList) && (!criteria.isEmergency())) { return emptyList(); } if (!criteria.isEmergency()) { criteria.setPeriodId(periodList.get(0).getId()); } criteria.setWithoutLineItems(true); return get(criteria); } public Long getFacilityId(Long id) { return requisitionRepository.getFacilityId(id); } private void fillFacilityPeriodProgramWithAuditFields(List<Rnr> requisitions) { for (Rnr requisition : requisitions) { Facility facility = facilityService.getById(requisition.getFacility().getId()); ProcessingPeriod period = processingScheduleService.getPeriodById(requisition.getPeriod().getId()); Program program = programService.getById(requisition.getProgram().getId()); requisition.fillBasicInformation(facility, program, period); requisition.setSubmittedDate(getOperationDateFor(requisition.getId(), SUBMITTED.toString())); } } public RnrLineItem getNonSkippedLineItem(Long rnrId, String productCode) { return requisitionRepository.getNonSkippedLineItem(rnrId, productCode); } public String deleteRnR(Long rnrId) { return requisitionRepository.deleteRnR(rnrId); } public void skipRnR(Long rnrId, Long userId) { Rnr rnr = this.getFullRequisitionById(rnrId); for (RnrLineItem li : rnr.getFullSupplyLineItems()) { li.setSkipped(true); } rnr.setModifiedBy(userId); rnr.setStatus(RnrStatus.SKIPPED); this.save(rnr); requisitionRepository.update(rnr); logStatusChangeAndNotify(rnr, false, RnrStatus.SKIPPED.toString()); } public void reOpenRnR(Long rnrId, Long userId) { Rnr rnr = this.getFullRequisitionById(rnrId); rnr.setModifiedBy(userId); for (RnrLineItem li : rnr.getFullSupplyLineItems()) { li.setSkipped(false); } rnr.setStatus(RnrStatus.INITIATED); requisitionRepository.update(rnr); this.save(rnr); logStatusChangeAndNotify(rnr, false, RnrStatus.INITIATED.toString()); } public void rejectRnR(Long rnrId, Long userId) { Rnr rnr = this.getFullRequisitionById(rnrId); rnr.setModifiedBy(userId); rnr.setStatus(RnrStatus.INITIATED); requisitionRepository.update(rnr); logStatusChangeAndNotify(rnr, false, RnrStatus.INITIATED.toString()); } public Integer findM(ProcessingPeriod period) { return processingScheduleService.findM(period); } public Long getProgramId(Long rnrId) { return requisitionRepository.getProgramId(rnrId); } @Transactional public void updateClientFields(Rnr rnr) { requisitionRepository.updateClientFields(rnr); } @Transactional public void insertPatientQuantificationLineItems(Rnr rnr) { requisitionRepository.insertPatientQuantificationLineItems(rnr); } public List<Rnr> getRequisitionsByFacility(Facility facility) { return requisitionRepository.getRequisitionDetailsByFacility(facility); } @Transactional public void insertRnrSignatures(Rnr rnr) { requisitionRepository.insertRnrSignatures(rnr); } }