001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.module.purap.document.web.struts; 017 018 import java.util.HashMap; 019 import java.util.Map; 020 021 import javax.servlet.http.HttpServletRequest; 022 import javax.servlet.http.HttpServletResponse; 023 024 import org.apache.commons.lang.StringUtils; 025 import org.apache.struts.action.ActionForm; 026 import org.apache.struts.action.ActionForward; 027 import org.apache.struts.action.ActionMapping; 028 import org.kuali.kfs.module.purap.PurapConstants; 029 import org.kuali.kfs.module.purap.PurapKeyConstants; 030 import org.kuali.kfs.module.purap.PurapConstants.CMDocumentsStrings; 031 import org.kuali.kfs.module.purap.document.AccountsPayableDocument; 032 import org.kuali.kfs.module.purap.document.PaymentRequestDocument; 033 import org.kuali.kfs.module.purap.document.PurchaseOrderDocument; 034 import org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument; 035 import org.kuali.kfs.module.purap.document.VendorCreditMemoDocument; 036 import org.kuali.kfs.module.purap.document.service.CreditMemoService; 037 import org.kuali.kfs.module.purap.document.service.PaymentRequestService; 038 import org.kuali.kfs.module.purap.document.service.PurapService; 039 import org.kuali.kfs.module.purap.document.service.PurchaseOrderService; 040 import org.kuali.kfs.module.purap.document.validation.event.AttributedCalculateAccountsPayableEvent; 041 import org.kuali.kfs.module.purap.document.validation.event.AttributedContinuePurapEvent; 042 import org.kuali.kfs.module.purap.util.PurQuestionCallback; 043 import org.kuali.kfs.sys.KFSConstants; 044 import org.kuali.kfs.sys.context.SpringContext; 045 import org.kuali.rice.kew.exception.WorkflowException; 046 import org.kuali.rice.kew.util.KEWConstants; 047 import org.kuali.rice.kim.util.KimConstants; 048 import org.kuali.rice.kns.document.Document; 049 import org.kuali.rice.kns.document.authorization.DocumentAuthorizer; 050 import org.kuali.rice.kns.question.ConfirmationQuestion; 051 import org.kuali.rice.kns.service.DocumentHelperService; 052 import org.kuali.rice.kns.service.KualiRuleService; 053 import org.kuali.rice.kns.util.GlobalVariables; 054 import org.kuali.rice.kns.util.KNSConstants; 055 import org.kuali.rice.kns.util.ObjectUtils; 056 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase; 057 058 /** 059 * Struts Action for Credit Memo document. 060 */ 061 public class VendorCreditMemoAction extends AccountsPayableActionBase { 062 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(VendorCreditMemoAction.class); 063 064 /** 065 * Do initialization for a new credit memo. 066 * 067 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#createDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase) 068 */ 069 @Override 070 protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException { 071 super.createDocument(kualiDocumentFormBase); 072 ((VendorCreditMemoDocument) kualiDocumentFormBase.getDocument()).initiateDocument(); 073 } 074 075 /** 076 * Handles continue request. This request comes from the initial screen which gives indicates whether the type is payment 077 * request, purchase order, or vendor. Based on that, the credit memo is initially populated and the remaining tabs shown. 078 * 079 * @param mapping An ActionMapping 080 * @param form An ActionForm 081 * @param request The HttpServletRequest 082 * @param response The HttpServletResponse 083 * @throws Exception 084 * @return An ActionForward 085 */ 086 public ActionForward continueCreditMemo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 087 VendorCreditMemoForm cmForm = (VendorCreditMemoForm) form; 088 VendorCreditMemoDocument creditMemoDocument = (VendorCreditMemoDocument) cmForm.getDocument(); 089 090 boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedContinuePurapEvent(creditMemoDocument)); 091 if (!rulePassed){ 092 return mapping.findForward(KFSConstants.MAPPING_BASIC); 093 } 094 095 if (creditMemoDocument.isSourceDocumentPaymentRequest()) { 096 PaymentRequestDocument preq = SpringContext.getBean(PaymentRequestService.class).getPaymentRequestById(creditMemoDocument.getPaymentRequestIdentifier()); 097 if (ObjectUtils.isNotNull(preq)) { 098 // TODO figure out a more straightforward way to do this. ailish put this in so the link id would be set and the perm check would work 099 creditMemoDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(preq.getAccountsPayablePurchasingDocumentLinkIdentifier()); 100 101 if (!SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(creditMemoDocument).isAuthorizedByTemplate(creditMemoDocument, KNSConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.OPEN_DOCUMENT, GlobalVariables.getUserSession().getPrincipalId())) { 102 throw buildAuthorizationException("initiate document", creditMemoDocument); 103 } 104 } 105 } 106 else if (creditMemoDocument.isSourceDocumentPurchaseOrder()) { 107 PurchaseOrderDocument po = SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(creditMemoDocument.getPurchaseOrderIdentifier()); 108 if (ObjectUtils.isNotNull(po)) { 109 // TODO figure out a more straightforward way to do this. ailish put this in so the link id would be set and the perm check would work 110 creditMemoDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(po.getAccountsPayablePurchasingDocumentLinkIdentifier()); 111 112 if (!SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(creditMemoDocument).isAuthorizedByTemplate(creditMemoDocument, KNSConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.OPEN_DOCUMENT, GlobalVariables.getUserSession().getPrincipalId())) { 113 throw buildAuthorizationException("initiate document", creditMemoDocument); 114 } 115 } 116 } 117 else { 118 //do nothing for credit memos against a vendor; no link to PO means no need to hide doc based on sensitive data 119 } 120 121 122 // preform duplicate check which will forward to a question prompt if one is found 123 ActionForward forward = performDuplicateCreditMemoCheck(mapping, form, request, response, creditMemoDocument); 124 if (forward != null) { 125 return forward; 126 } 127 128 // perform validation of init tab 129 SpringContext.getBean(CreditMemoService.class).populateAndSaveCreditMemo(creditMemoDocument); 130 131 // sort below the line (doesn't really need to be done on CM, but will help if we ever bring btl from other docs) 132 SpringContext.getBean(PurapService.class).sortBelowTheLine(creditMemoDocument); 133 134 // update the counts on the form 135 cmForm.updateItemCounts(); 136 137 //if source is (PREQ or PO) and the PO status is CLOSED, automatically reopen the PO 138 PurchaseOrderDocument po = creditMemoDocument.getPurchaseOrderDocument(); 139 if ((creditMemoDocument.isSourceDocumentPaymentRequest() || creditMemoDocument.isSourceDocumentPurchaseOrder()) && PurapConstants.PurchaseOrderStatuses.CLOSED.equals(po.getStatusCode())) { 140 initiateReopenPurchaseOrder(po, cmForm.getAnnotation()); 141 } 142 143 return mapping.findForward(KFSConstants.MAPPING_BASIC); 144 } 145 146 /** 147 * Clears out fields of the init tab. 148 * 149 * @param mapping An ActionMapping 150 * @param form An ActionForm 151 * @param request The HttpServletRequest 152 * @param response The HttpServletResponse 153 * @throws Exception 154 * @return An ActionForward 155 */ 156 public ActionForward clearInitFields(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 157 VendorCreditMemoForm cmForm = (VendorCreditMemoForm) form; 158 VendorCreditMemoDocument creditMemoDocument = (VendorCreditMemoDocument) cmForm.getDocument(); 159 creditMemoDocument.clearInitFields(); 160 161 return super.refresh(mapping, form, request, response); 162 } 163 164 /** 165 * Calls <code>CreditMemoService</code> to perform the duplicate credit memo check. If one is found, a question is setup and 166 * control is forwarded to the question action method. Coming back from the question prompt, the button that was clicked is 167 * checked, and if 'no' was selected, they are forward back to the page still in init mode. 168 * 169 * @param mapping An ActionMapping 170 * @param form An ActionForm 171 * @param request The HttpServletRequest 172 * @param response The HttpServletResponse 173 * @param creditMemoDocument The CreditMemoDocument 174 * @throws Exception 175 * @return An ActionForward 176 * @see org.kuali.kfs.module.purap.document.service.CreditMemoService 177 */ 178 protected ActionForward performDuplicateCreditMemoCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, VendorCreditMemoDocument creditMemoDocument) throws Exception { 179 ActionForward forward = null; 180 String duplicateMessage = SpringContext.getBean(CreditMemoService.class).creditMemoDuplicateMessages(creditMemoDocument); 181 if (StringUtils.isNotBlank(duplicateMessage)) { 182 Object question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME); 183 if (question == null) { 184 185 return this.performQuestionWithoutInput(mapping, form, request, response, PurapConstants.PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION, duplicateMessage, KFSConstants.CONFIRMATION_QUESTION, "continueCreditMemo", ""); 186 } 187 188 Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON); 189 if ((PurapConstants.PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) { 190 forward = mapping.findForward(KFSConstants.MAPPING_BASIC); 191 } 192 } 193 194 return forward; 195 } 196 197 /** 198 * Calls methods to perform credit allowed calculation and total credit memo amount. 199 * 200 * @param apDoc An AccountsPayableDocument 201 */ 202 @Override 203 protected void customCalculate(PurchasingAccountsPayableDocument apDoc) { 204 VendorCreditMemoDocument cmDocument = (VendorCreditMemoDocument) apDoc; 205 206 // call service method to finish up calculation 207 SpringContext.getBean(CreditMemoService.class).calculateCreditMemo(cmDocument); 208 209 // notice we're ignoring the boolean because these are just warnings they shouldn't halt anything 210 SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedCalculateAccountsPayableEvent(cmDocument)); 211 // } 212 } 213 214 /** 215 * Puts a credit memo on hold, prompting for a reason before hand. This stops further approvals or routing. 216 * 217 * @param mapping An ActionMapping 218 * @param form An ActionForm 219 * @param request The HttpServletRequest 220 * @param response The HttpServletResponse 221 * @throws Exception 222 * @return An ActionForward 223 */ 224 public ActionForward addHoldOnCreditMemo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 225 String operation = "Hold "; 226 227 PurQuestionCallback callback = new PurQuestionCallback() { 228 public AccountsPayableDocument doPostQuestion(AccountsPayableDocument document, String noteText) throws Exception { 229 VendorCreditMemoDocument cmDocument = SpringContext.getBean(CreditMemoService.class).addHoldOnCreditMemo((VendorCreditMemoDocument) document, noteText); 230 return cmDocument; 231 } 232 }; 233 234 return askQuestionWithInput(mapping, form, request, response, CMDocumentsStrings.HOLD_CM_QUESTION, operation, CMDocumentsStrings.HOLD_NOTE_PREFIX, PurapKeyConstants.CREDIT_MEMO_QUESTION_HOLD_DOCUMENT, callback); 235 } 236 237 /** 238 * Removes a hold on the credit memo. 239 * 240 * @param mapping An ActionMapping 241 * @param form An ActionForm 242 * @param request The HttpServletRequest 243 * @param response The HttpServletResponse 244 * @throws Exception 245 * @return An ActionForward 246 */ 247 public ActionForward removeHoldFromCreditMemo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 248 String operation = "Remove Hold "; 249 250 PurQuestionCallback callback = new PurQuestionCallback() { 251 public AccountsPayableDocument doPostQuestion(AccountsPayableDocument document, String noteText) throws Exception { 252 VendorCreditMemoDocument cmDocument = SpringContext.getBean(CreditMemoService.class).removeHoldOnCreditMemo((VendorCreditMemoDocument) document, noteText); 253 return cmDocument; 254 } 255 }; 256 257 return askQuestionWithInput(mapping, form, request, response, CMDocumentsStrings.REMOVE_HOLD_CM_QUESTION, operation, CMDocumentsStrings.REMOVE_HOLD_NOTE_PREFIX, PurapKeyConstants.CREDIT_MEMO_QUESTION_REMOVE_HOLD_DOCUMENT, callback); 258 } 259 260 /** 261 * @see org.kuali.kfs.module.purap.document.web.struts.AccountsPayableActionBase#cancelPOActionCallbackMethod() 262 */ 263 // @Override 264 // protected PurQuestionCallback cancelPOActionCallbackMethod() { 265 // return new PurQuestionCallback() { 266 // public AccountsPayableDocument doPostQuestion(AccountsPayableDocument document, String noteText) throws Exception { 267 // VendorCreditMemoDocument cmDocument = (VendorCreditMemoDocument) document; 268 // cmDocument.setClosePurchaseOrderIndicator(true); 269 // return cmDocument; 270 // } 271 // }; 272 // } 273 274 /** 275 * @see org.kuali.kfs.module.purap.document.web.struts.AccountsPayableActionBase#getActionName() 276 */ 277 @Override 278 public String getActionName() { 279 return PurapConstants.CREDIT_MEMO_ACTION_NAME; 280 } 281 282 @Override 283 protected void populateAdHocActionRequestCodes(KualiDocumentFormBase formBase){ 284 Document document = formBase.getDocument(); 285 DocumentAuthorizer documentAuthorizer = getDocumentHelperService().getDocumentAuthorizer(document); 286 Map<String,String> adHocActionRequestCodes = new HashMap<String,String>(); 287 288 if (documentAuthorizer.canSendAdHocRequests(document, KEWConstants.ACTION_REQUEST_FYI_REQ, GlobalVariables.getUserSession().getPerson())) { 289 adHocActionRequestCodes.put(KEWConstants.ACTION_REQUEST_FYI_REQ, KEWConstants.ACTION_REQUEST_FYI_REQ_LABEL); 290 } 291 if ( (document.getDocumentHeader().getWorkflowDocument().stateIsInitiated() 292 || document.getDocumentHeader().getWorkflowDocument().stateIsSaved() 293 || document.getDocumentHeader().getWorkflowDocument().stateIsEnroute() 294 )&& documentAuthorizer.canSendAdHocRequests(document, KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, GlobalVariables.getUserSession().getPerson())) { 295 adHocActionRequestCodes.put(KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ_LABEL); 296 } 297 formBase.setAdHocActionRequestCodes(adHocActionRequestCodes); 298 299 } 300 }