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 }