/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * 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.kuali.kfs.pdp.web.struts; import java.text.MessageFormat; import java.util.List; import java.util.Properties; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.kuali.kfs.pdp.PdpKeyConstants; import org.kuali.kfs.pdp.PdpParameterConstants; import org.kuali.kfs.pdp.PdpPropertyConstants; import org.kuali.kfs.pdp.businessobject.Batch; import org.kuali.kfs.pdp.service.BatchMaintenanceService; import org.kuali.kfs.pdp.util.PdpBatchQuestionCallback; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.rice.core.api.config.property.ConfigurationService; import org.kuali.rice.kim.api.identity.Person; import org.kuali.rice.kns.question.ConfirmationQuestion; import org.kuali.rice.kns.web.struts.action.KualiAction; import org.kuali.rice.krad.util.ErrorMessage; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.KRADConstants; import org.kuali.rice.krad.util.MessageMap; import org.kuali.rice.krad.util.UrlFactory; /** * This class defines actions for Batch (cancel, hold, remove hold). */ public class BatchAction extends KualiAction { private BatchMaintenanceService batchMaintenanceService; /** * Constructs a BatchAction.java. */ public BatchAction() { setBatchMaintenanceService(SpringContext.getBean(BatchMaintenanceService.class)); } /** * This method confirms and performs batch cancel. * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward confirmAndCancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { PdpBatchQuestionCallback callback = new PdpBatchQuestionCallback() { public boolean doPostQuestion(String batchIdString, String cancelNote, Person user) { return performCancel(batchIdString, cancelNote, user); } }; return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.BatchConstants.Confirmation.CANCEL_BATCH_QUESTION, PdpKeyConstants.BatchConstants.Confirmation.CANCEL_BATCH_MESSAGE, PdpKeyConstants.BatchConstants.Messages.BATCH_SUCCESSFULLY_CANCELED, "confirmAndCancel", callback); } /** * This method cancels a batch. * * @param batchIdString a string representing the batch id * @param cancelNote the cancelation note entered by the user * @param user the current user */ private boolean performCancel(String batchIdString, String cancelNote, Person user) { try { Integer batchId = Integer.parseInt(batchIdString); return batchMaintenanceService.cancelPendingBatch(batchId, cancelNote, user); } catch (NumberFormatException e) { GlobalVariables.getMessageMap().putError(PdpPropertyConstants.BatchConstants.BATCH_ID, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_BATCH_ID_IS_NOT_NUMERIC); return false; } } /** * This method confirms and performs batch hold. * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward confirmAndHold(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { PdpBatchQuestionCallback callback = new PdpBatchQuestionCallback() { public boolean doPostQuestion(String batchIdString, String note, Person user) { return performHold(batchIdString, note, user); } }; return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.BatchConstants.Confirmation.HOLD_BATCH_QUESTION, PdpKeyConstants.BatchConstants.Confirmation.HOLD_BATCH_MESSAGE, PdpKeyConstants.BatchConstants.Messages.BATCH_SUCCESSFULLY_HOLD, "confirmAndHold", callback); } /** * This method holds a batch * * @param batchIdString * @param holdNote * @param user * @throws PdpException */ private boolean performHold(String batchIdString, String holdNote, Person user) { try { Integer batchId = Integer.parseInt(batchIdString); return batchMaintenanceService.holdPendingBatch(batchId, holdNote, user); } catch (NumberFormatException e) { GlobalVariables.getMessageMap().putError(PdpPropertyConstants.BatchConstants.BATCH_ID, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_BATCH_ID_IS_NOT_NUMERIC); return false; } } /** * This method confirms and peforms remove hold on batch action. * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward confirmAndRemoveHold(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { PdpBatchQuestionCallback callback = new PdpBatchQuestionCallback() { public boolean doPostQuestion(String batchIdString, String note, Person user) { return performRemoveHold(batchIdString, note, user); } }; return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.BatchConstants.Confirmation.REMOVE_HOLD_BATCH_QUESTION, PdpKeyConstants.BatchConstants.Confirmation.REMOVE_HOLD_BATCH_MESSAGE, PdpKeyConstants.BatchConstants.Messages.HOLD_SUCCESSFULLY_REMOVED_ON_BATCH, "confirmAndRemoveHold", callback); } /** * This method removes a batch hold. * * @param batchIdString * @param changeText * @param user * @throws PdpException */ private boolean performRemoveHold(String batchIdString, String changeText, Person user) { try { Integer batchId = Integer.parseInt(batchIdString); return batchMaintenanceService.removeBatchHold(batchId, changeText, user); } catch (NumberFormatException e) { GlobalVariables.getMessageMap().putError(PdpPropertyConstants.BatchConstants.BATCH_ID, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_BATCH_ID_IS_NOT_NUMERIC); return false; } } /** * This method prompts for a reason to perfomr an action on a batch (cancel, hold, remove hold). * * @param mapping * @param form * @param request * @param response * @param confirmationQuestion * @param confirmationText * @param caller * @param callback * @return * @throws Exception */ private ActionForward askQuestionWithInput(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String confirmationQuestion, String confirmationText, String successMessage, String caller, PdpBatchQuestionCallback callback) throws Exception { Object question = request.getParameter(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME); String reason = request.getParameter(KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME); String noteText = KFSConstants.EMPTY_STRING; Person person = GlobalVariables.getUserSession().getPerson(); boolean actionStatus; String message = KFSConstants.EMPTY_STRING; String batchId = request.getParameter(PdpParameterConstants.BatchConstants.BATCH_ID_PARAM); if (batchId == null) { batchId = request.getParameter(KRADConstants.QUESTION_CONTEXT); } ConfigurationService kualiConfiguration = SpringContext.getBean(ConfigurationService.class); confirmationText = kualiConfiguration.getPropertyValueAsString(confirmationText); confirmationText = MessageFormat.format(confirmationText, batchId); if (question == null) { // ask question if not already asked return this.performQuestionWithInput(mapping, form, request, response, confirmationQuestion, confirmationText, KRADConstants.CONFIRMATION_QUESTION, caller, batchId); } else { Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON); if ((confirmationQuestion.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) { actionStatus = false; } else { noteText = reason; int noteTextLength = (reason == null) ? 0 : noteText.length(); int noteTextMaxLength = PdpKeyConstants.BatchConstants.Confirmation.NOTE_TEXT_MAX_LENGTH; if (StringUtils.isBlank(reason)) { if (reason == null) { // prevent a NPE by setting the reason to a blank string reason = KFSConstants.EMPTY_STRING; } return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, confirmationQuestion, confirmationText, KRADConstants.CONFIRMATION_QUESTION, KFSConstants.MAPPING_BASIC, batchId, reason, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_NOTE_EMPTY, KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, ""); } else if (noteTextLength > noteTextMaxLength) { return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, confirmationQuestion, confirmationText, KRADConstants.CONFIRMATION_QUESTION, KFSConstants.MAPPING_BASIC, batchId, reason, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_NOTE_TOO_LONG, KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, ""); } actionStatus = callback.doPostQuestion(batchId, noteText, person); if (actionStatus) { message = successMessage; } } } String returnUrl = buildUrl(batchId, actionStatus, message, buildErrorMesageKeyList()); return new ActionForward(returnUrl, true); } /** * This method builds the forward url. * * @param batchId the batch id * @param success action status: true if success, false otherwise * @param message the message for the user * @return the build url */ private String buildUrl(String batchId, boolean success, String message, String errorList) { String basePath = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(KFSConstants.APPLICATION_URL_KEY); Properties parameters = new Properties(); parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.SEARCH_METHOD); parameters.put(KFSConstants.BACK_LOCATION, basePath + "/" + KFSConstants.MAPPING_PORTAL + ".do"); parameters.put(KRADConstants.DOC_FORM_KEY, "88888888"); parameters.put(KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, Batch.class.getName()); parameters.put(KFSConstants.HIDE_LOOKUP_RETURN_LINK, "true"); parameters.put(KFSConstants.SUPPRESS_ACTIONS, "false"); parameters.put(PdpPropertyConstants.BatchConstants.BATCH_ID, batchId); parameters.put(PdpParameterConstants.ACTION_SUCCESSFUL_PARAM, String.valueOf(success)); if (message != null && !message.equalsIgnoreCase(KFSConstants.EMPTY_STRING)) { parameters.put(PdpParameterConstants.MESSAGE_PARAM, message); } if (StringUtils.isNotEmpty(errorList)) { parameters.put(PdpParameterConstants.ERROR_KEY_LIST_PARAM, errorList); } String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + KFSConstants.LOOKUP_ACTION, parameters); return lookupUrl; } /** * This method build a string list of error message keys out of the error map in GlobalVariables * * @return a String representing the list of error message keys */ private String buildErrorMesageKeyList() { MessageMap errorMap = GlobalVariables.getMessageMap(); StringBuffer errorList = new StringBuffer(); for (String errorKey : (List<String>) errorMap.getPropertiesWithErrors()) { for (ErrorMessage errorMessage : (List<ErrorMessage>) errorMap.getMessages(errorKey)) { errorList.append(errorMessage.getErrorKey()); errorList.append(PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR); } } if (errorList.length() > 0) { errorList.replace(errorList.lastIndexOf(PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR), errorList.lastIndexOf(PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR) + PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR.length(), ""); } return errorList.toString(); } /** * This method gets the batch maintenance service. * * @return the BatchMaintenanceService */ public BatchMaintenanceService getBatchMaintenanceService() { return batchMaintenanceService; } /** * This method sets the batch maintenance service. * * @param batchMaintenanceService */ public void setBatchMaintenanceService(BatchMaintenanceService batchMaintenanceService) { this.batchMaintenanceService = batchMaintenanceService; } }