/* * This program is part of the OpenLMIS logistics management information system platform software. * Copyright © 2013 VillageReach * * 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.  For additional information contact info@OpenLMIS.org.  */ package org.openlmis.web.controller; import lombok.NoArgsConstructor; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.openlmis.core.domain.Facility; import org.openlmis.core.domain.ProcessingPeriod; import org.openlmis.core.domain.Program; import org.openlmis.core.domain.User; import org.openlmis.core.exception.DataException; import org.openlmis.core.web.OpenLmisResponse; import org.openlmis.core.web.controller.BaseController; import org.openlmis.rnr.domain.Comment; import org.openlmis.rnr.domain.Rnr; import org.openlmis.rnr.domain.RnrLineItem; import org.openlmis.rnr.dto.RnrDTO; import org.openlmis.rnr.search.criteria.RequisitionSearchCriteria; import org.openlmis.rnr.service.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PostAuthorize; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import java.util.List; import static org.openlmis.core.domain.RightName.APPROVE_REQUISITION; import static org.openlmis.core.domain.RightName.CONVERT_TO_ORDER; import static org.openlmis.core.web.OpenLmisResponse.*; import static org.openlmis.rnr.dto.RnrDTO.*; import static org.openlmis.rnr.service.RequisitionService.NUMBER_OF_PAGES; import static org.openlmis.rnr.service.RequisitionService.SEARCH_ALL; import static org.springframework.http.HttpStatus.*; import static org.springframework.web.bind.annotation.RequestMethod.*; /** * This controller handles endpoint related to requisition operations like initialize, save, submit, authorize, approve, * print, view Rnr, save comments. */ @Controller @NoArgsConstructor public class RequisitionController extends BaseController { public static final String RNR = "rnr"; public static final String RNR_SAVE_SUCCESS = "msg.rnr.save.success"; public static final String RNR_LIST = "rnr_list"; public static final String RNR_TEMPLATE = "rnr_template"; public static final String PERIODS = "periods"; public static final String CURRENCY = "currency"; public static final String COMMENTS = "comments"; public static final String REGIMEN_TEMPLATE = "regimen_template"; public static final String LOSS_ADJUSTMENT_TYPES = "lossAdjustmentTypes"; public static final String STATUS_CHANGES = "statusChanges"; public static final String IS_EMERGENCY = "is_emergency"; public static final String LOSSES_AND_ADJUSTMENT_TYPES = "lossesAndAdjustmentTypes"; public static final String NUMBER_OF_MONTHS = "numberOfMonths"; public static final String CAN_APPROVE_RNR = "canApproveRnr"; private static final Logger logger = LoggerFactory.getLogger(RequisitionController.class); @Autowired private RequisitionService requisitionService; @Autowired private RnrTemplateService rnrTemplateService; @Autowired private RequisitionStatusChangeService requisitionStatusChangeService; @Autowired private RegimenColumnService regimenColumnService; @Autowired private RequisitionPermissionService requisitionPermissionService; @RequestMapping(value = "/requisitions", method = POST, headers = ACCEPT_JSON) public ResponseEntity<OpenLmisResponse> initiateRnr(@RequestParam("facilityId") Long facilityId, @RequestParam("programId") Long programId, @RequestParam("emergency") Boolean emergency, HttpServletRequest request) { try { Rnr initiatedRnr = requisitionService.initiate(new Facility(facilityId), new Program(programId), loggedInUserId(request), emergency, null, "WEB_UI"); ResponseEntity<OpenLmisResponse> response = response(RNR, initiatedRnr); response.getBody().addData(NUMBER_OF_MONTHS, requisitionService.findM(initiatedRnr.getPeriod())); return response; } catch (DataException e) { return error(e, BAD_REQUEST); } } @RequestMapping(value = "/requisitions/{id}", method = GET) @PostAuthorize("@requisitionPermissionService.hasPermission(principal, returnObject.body.data.get(\"rnr\"), 'VIEW_REQUISITION')") public ResponseEntity<OpenLmisResponse> getById(@PathVariable Long id, HttpServletRequest request) { try { Rnr rnr = requisitionService.getFullRequisitionById(id); ResponseEntity<OpenLmisResponse> response = response(RNR, rnr); response.getBody().addData(NUMBER_OF_MONTHS, requisitionService.findM(rnr.getPeriod())); boolean canApproveRnr = (rnr.isApprovable() && requisitionPermissionService.hasPermission(loggedInUserId(request), rnr, APPROVE_REQUISITION)); response.getBody().addData(CAN_APPROVE_RNR, canApproveRnr); return response; } catch (DataException dataException) { return error(dataException, NOT_FOUND); } } @RequestMapping(value = "/requisitions/{id}/skipped", method = GET) @PostAuthorize("@requisitionPermissionService.hasPermission(principal, returnObject.body.data.get(\"rnr\"), 'VIEW_REQUISITION')") public ResponseEntity<OpenLmisResponse> getByIdWithOutSkippedItems(@PathVariable Long id, HttpServletRequest request) { try { Rnr rnr = requisitionService.getFullRequisitionById(id); List<RnrLineItem> allRnrLineItems= rnr.getFullSupplyLineItems(); CollectionUtils.filter(allRnrLineItems, new Predicate() { @Override public boolean evaluate(Object o) { RnrLineItem rnrLineItem = (RnrLineItem) o; return !rnrLineItem.getSkipped(); } }); return response(RNR, rnr); } catch (DataException dataException) { return error(dataException, NOT_FOUND); } } @RequestMapping(value = "/requisitions/{id}/save", method = PUT, headers = ACCEPT_JSON) public ResponseEntity<OpenLmisResponse> saveRnr(@RequestBody Rnr rnr, @PathVariable("id") Long id, HttpServletRequest request) { try { rnr.setId(id); rnr.setModifiedBy(loggedInUserId(request)); requisitionService.save(rnr); return OpenLmisResponse.success(messageService.message(RNR_SAVE_SUCCESS)); } catch (DataException e) { return OpenLmisResponse.error(e, BAD_REQUEST); } } @RequestMapping(value = "/requisitions/{id}/submit", method = PUT, headers = ACCEPT_JSON) public ResponseEntity<OpenLmisResponse> submit(@PathVariable("id") Long id, HttpServletRequest request) { try { Rnr rnr = new Rnr(id); rnr.setModifiedBy(loggedInUserId(request)); Rnr submittedRnr = requisitionService.submit(rnr); return success(messageService.message(requisitionService.getSubmitMessageBasedOnSupervisoryNode(submittedRnr.getFacility(), submittedRnr.getProgram()))); } catch (DataException e) { return error(e, BAD_REQUEST); } } @RequestMapping(value = "/requisitions/{id}/authorize", method = PUT, headers = ACCEPT_JSON) public ResponseEntity<OpenLmisResponse> authorize(@PathVariable("id") Long id, HttpServletRequest request) { try { Rnr rnr = new Rnr(id); rnr.setModifiedBy(loggedInUserId(request)); Rnr authorizedRnr = requisitionService.authorize(rnr); return success(messageService.message(requisitionService.getAuthorizeMessageBasedOnSupervisoryNode( authorizedRnr.getFacility(), authorizedRnr.getProgram()))); } catch (DataException e) { return error(e, BAD_REQUEST); } } @RequestMapping(value = "/requisitions/{id}/approve", method = PUT, headers = ACCEPT_JSON) public ResponseEntity<OpenLmisResponse> approve(@PathVariable("id") Long id, HttpServletRequest request) { Rnr rnr = new Rnr(id); rnr.setModifiedBy(loggedInUserId(request)); try { Rnr approvedRnr = requisitionService.approve(rnr, null); return success(messageService.message(requisitionService.getApproveMessageBasedOnParentNode(approvedRnr))); } catch (DataException dataException) { logger.warn("Error in approving requisition #{}", id, dataException); return error(dataException, BAD_REQUEST); } } @RequestMapping(value = "/requisitions/lossAndAdjustments/reference-data", method = GET, headers = ACCEPT_JSON) @PreAuthorize("@permissionEvaluator.hasPermission(principal,'CREATE_REQUISITION, AUTHORIZE_REQUISITION, APPROVE_REQUISITION')") public ResponseEntity<OpenLmisResponse> getReferenceData() { OpenLmisResponse referenceData = new OpenLmisResponse(); referenceData.addData(LOSS_ADJUSTMENT_TYPES, requisitionService.getLossesAndAdjustmentsTypes()); return referenceData.response(OK); } @RequestMapping(value = "/requisitions", method = GET, headers = ACCEPT_JSON) @PreAuthorize("@permissionEvaluator.hasPermission(principal,'VIEW_REQUISITION')") public ResponseEntity<OpenLmisResponse> getRequisitionsForView(RequisitionSearchCriteria criteria, HttpServletRequest request) { criteria.setUserId(loggedInUserId(request)); return response(RNR_LIST, prepareForView(requisitionService.get(criteria))); } @RequestMapping(value = "/requisitions-for-approval", method = GET, headers = ACCEPT_JSON) @PreAuthorize("@permissionEvaluator.hasPermission(principal, 'APPROVE_REQUISITION')") public ResponseEntity<OpenLmisResponse> listForApproval(HttpServletRequest request) { List<RnrDTO> requisitions = requisitionService.listForApprovalDto(loggedInUserId(request)); return response(RNR_LIST, prepareDTOsForListApproval(requisitions)); } @RequestMapping(value = "/requisitions-for-convert-to-order", method = GET, headers = ACCEPT_JSON) @PreAuthorize("@permissionEvaluator.hasPermission(principal, 'CONVERT_TO_ORDER')") //TODO: move request params into form public ResponseEntity<OpenLmisResponse> listForConvertToOrder(@RequestParam(value = "searchType", required = false, defaultValue = SEARCH_ALL) String searchType, @RequestParam(value = "searchVal", required = false, defaultValue = "") String searchVal, @RequestParam(value = "page", required = true, defaultValue = "1") Integer page, @RequestParam(value = "sortBy", required = false, defaultValue = "submittedDate") String sortBy, @RequestParam(value = "sortDirection", required = false, defaultValue = "asc") String sortDirection, HttpServletRequest request) { try { Integer numberOfPages = requisitionService.getNumberOfPagesOfApprovedRequisitionsForCriteria(searchType, searchVal, loggedInUserId(request), CONVERT_TO_ORDER); List<Rnr> approvedRequisitions = requisitionService.getApprovedRequisitionsForCriteriaAndPageNumber( searchType, searchVal, page, numberOfPages, loggedInUserId(request), CONVERT_TO_ORDER, sortBy, sortDirection); List<RnrDTO> rnrDTOs = prepareForListApproval(approvedRequisitions); OpenLmisResponse response = new OpenLmisResponse(RNR_LIST, rnrDTOs); response.addData(NUMBER_OF_PAGES, numberOfPages); return new ResponseEntity<>(response, HttpStatus.OK); } catch (Exception e) { return error(new DataException(e.getMessage()), NOT_FOUND); } } @RequestMapping(value = "/logistics/periods", method = GET, headers = ACCEPT_JSON) @PreAuthorize("@permissionEvaluator.hasPermission(principal, 'CREATE_REQUISITION, AUTHORIZE_REQUISITION')") public ResponseEntity<OpenLmisResponse> getAllPeriodsForInitiatingRequisitionWithRequisitionStatus( RequisitionSearchCriteria criteria, HttpServletRequest request) { criteria.setUserId(loggedInUserId(request)); try { List<ProcessingPeriod> periodList = requisitionService.getProcessingPeriods(criteria); List<Rnr> requisitions = requisitionService.getRequisitionsFor(criteria, periodList); OpenLmisResponse response = new OpenLmisResponse(PERIODS, periodList); response.addData(RNR_LIST, requisitions); response.addData(IS_EMERGENCY, criteria.isEmergency()); return new ResponseEntity<>(response, OK); } catch (DataException e) { return error(e, CONFLICT); } } @RequestMapping(value = "/requisitions/{id}/print", method = GET, headers = ACCEPT_PDF) @PostAuthorize("@requisitionPermissionService.hasPermission(principal, returnObject.model.get(\"rnr\"), 'VIEW_REQUISITION')") public ModelAndView printRequisition(@PathVariable Long id) { ModelAndView modelAndView = new ModelAndView("requisitionPDF"); Rnr requisition = requisitionService.getFullRequisitionById(id); modelAndView.addObject(RNR, requisition); modelAndView.addObject(LOSSES_AND_ADJUSTMENT_TYPES, requisitionService.getLossesAndAdjustmentsTypes()); Long programId = requisition.getProgram().getId(); modelAndView.addObject(RNR_TEMPLATE, rnrTemplateService.fetchColumnsForRequisition(programId)); modelAndView.addObject(REGIMEN_TEMPLATE, regimenColumnService.getRegimenColumnsForPrintByProgramId(programId)); modelAndView.addObject(STATUS_CHANGES, requisitionStatusChangeService.getByRnrId(id)); modelAndView.addObject(NUMBER_OF_MONTHS, requisitionService.findM(requisition.getPeriod())); return modelAndView; } @RequestMapping(value = "/requisitions/{id}/comments", method = POST, headers = ACCEPT_JSON) @PreAuthorize("@permissionEvaluator.hasPermission(principal, 'CREATE_REQUISITION, AUTHORIZE_REQUISITION, APPROVE_REQUISITION')") public ResponseEntity<OpenLmisResponse> insertComment(@RequestBody Comment comment, @PathVariable("id") Long id, HttpServletRequest request) { comment.setRnrId(id); User author = new User(); author.setId(loggedInUserId(request)); comment.setAuthor(author); requisitionService.insertComment(comment); return OpenLmisResponse.response(COMMENTS, requisitionService.getCommentsByRnrId(id)); } @RequestMapping(value = "/requisitions/{id}/comments", method = GET, headers = ACCEPT_JSON) public ResponseEntity<OpenLmisResponse> getCommentsForARnr(@PathVariable Long id) { return response(COMMENTS, requisitionService.getCommentsByRnrId(id)); } @RequestMapping(value = "/requisitions/delete/{id}", method = POST, headers = ACCEPT_JSON) @PreAuthorize("@permissionEvaluator.hasPermission(principal, 'DELETE_REQUISITION')") public ResponseEntity<OpenLmisResponse> deleteRnR(@PathVariable("id") Long rnrId) { requisitionService.deleteRnR(rnrId); return OpenLmisResponse.success(messageService.message("msg.rnr.deleted")); } @RequestMapping(value = "/requisitions/skip/{id}", method = POST, headers = ACCEPT_JSON) @PreAuthorize("@permissionEvaluator.hasPermission(principal, 'CREATE_REQUISITION')") public ResponseEntity<OpenLmisResponse> skipRnR(@PathVariable("id") Long rnrId, HttpServletRequest request) { requisitionService.skipRnR(rnrId, loggedInUserId(request)); return OpenLmisResponse.success(messageService.message("msg.rnr.skipped")); } @RequestMapping(value = "/requisitions/reject/{id}", method = POST, headers = ACCEPT_JSON) @PreAuthorize("@permissionEvaluator.hasPermission(principal, 'CREATE_REQUISITION')") public ResponseEntity<OpenLmisResponse> rejectRnR(@PathVariable("id") Long rnrId, HttpServletRequest request) { requisitionService.rejectRnR(rnrId, loggedInUserId(request)); return OpenLmisResponse.success(messageService.message("msg.rnr.returned")); } @RequestMapping(value = "/requisitions/reopen/{id}", method = POST, headers = ACCEPT_JSON) @PreAuthorize("@permissionEvaluator.hasPermission(principal, 'CREATE_REQUISITION')") public ResponseEntity<OpenLmisResponse> reopenRnR(@PathVariable("id") Long rnrId, HttpServletRequest request) { requisitionService.reOpenRnR(rnrId, loggedInUserId(request)); return OpenLmisResponse.success(messageService.message("msg.rnr.reopened")); } }