001/* 002 * Copyright 2007 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 */ 016package org.kuali.ole.module.purap.document.web.struts; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.struts.action.ActionForm; 020import org.apache.struts.action.ActionForward; 021import org.apache.struts.action.ActionMapping; 022import org.kuali.ole.module.purap.PurapConstants; 023import org.kuali.ole.module.purap.PurapConstants.InvoiceStatuses; 024import org.kuali.ole.module.purap.PurapConstants.PRQSDocumentsStrings; 025import org.kuali.ole.module.purap.PurapKeyConstants; 026import org.kuali.ole.module.purap.PurapPropertyConstants; 027import org.kuali.ole.module.purap.document.AccountsPayableDocument; 028import org.kuali.ole.module.purap.document.InvoiceDocument; 029import org.kuali.ole.module.purap.document.PurchaseOrderDocument; 030import org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument; 031import org.kuali.ole.module.purap.document.service.InvoiceService; 032import org.kuali.ole.module.purap.document.service.PurapService; 033import org.kuali.ole.module.purap.document.service.PurchaseOrderService; 034import org.kuali.ole.module.purap.document.validation.event.AttributedCalculateAccountsPayableEvent; 035import org.kuali.ole.module.purap.document.validation.event.AttributedContinuePurapEvent; 036import org.kuali.ole.module.purap.document.validation.event.AttributedPreCalculateAccountsPayableEvent; 037import org.kuali.ole.module.purap.service.PurapAccountingService; 038import org.kuali.ole.module.purap.util.PurQuestionCallback; 039import org.kuali.ole.sys.OLEConstants; 040import org.kuali.ole.sys.OLEKeyConstants; 041import org.kuali.ole.sys.OLEPropertyConstants; 042import org.kuali.ole.sys.context.SpringContext; 043import org.kuali.ole.sys.service.UniversityDateService; 044import org.kuali.rice.core.api.config.property.ConfigurationService; 045import org.kuali.rice.core.api.util.RiceConstants; 046import org.kuali.rice.kew.api.exception.WorkflowException; 047import org.kuali.rice.kim.api.KimConstants; 048import org.kuali.rice.kns.question.ConfirmationQuestion; 049import org.kuali.rice.kns.service.DocumentHelperService; 050import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase; 051import org.kuali.rice.krad.service.KualiRuleService; 052import org.kuali.rice.krad.util.GlobalVariables; 053import org.kuali.rice.krad.util.KRADConstants; 054import org.kuali.rice.krad.util.ObjectUtils; 055 056import javax.servlet.http.HttpServletRequest; 057import javax.servlet.http.HttpServletResponse; 058import java.util.HashMap; 059 060/** 061 * Struts Action for Payment Request document. 062 */ 063public class InvoiceAction extends AccountsPayableActionBase { 064 static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(InvoiceAction.class); 065 066 /** 067 * Do initialization for a new payment request. 068 * 069 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#createDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase) 070 */ 071 @Override 072 protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException { 073 super.createDocument(kualiDocumentFormBase); 074 ((InvoiceDocument) kualiDocumentFormBase.getDocument()).initiateDocument(); 075 } 076 077 /** 078 * @see org.kuali.rice.kns.web.struts.action.KualiAction#refresh(org.apache.struts.action.ActionMapping, 079 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 080 */ 081 @Override 082 public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 083 InvoiceForm prqsForm = (InvoiceForm) form; 084 InvoiceDocument document = (InvoiceDocument) prqsForm.getDocument(); 085 086 return super.refresh(mapping, form, request, response); 087 } 088 089 /** 090 * Executes the continue action on a payment request. Populates and initializes the rest of the payment request besides what was 091 * shown on the init screen. 092 * 093 * @param mapping An ActionMapping 094 * @param form An ActionForm 095 * @param request The HttpServletRequest 096 * @param response The HttpServletResponse 097 * @return An ActionForward 098 * @throws Exception 099 */ 100 public ActionForward continuePRQS(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 101 LOG.debug("continuePRQS() method"); 102 InvoiceForm prqsForm = (InvoiceForm) form; 103 InvoiceDocument invoiceDocument = (InvoiceDocument) prqsForm.getDocument(); 104 105 boolean poNotNull = true; 106 107 boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedContinuePurapEvent(invoiceDocument)); 108 if (!rulePassed) { 109 return mapping.findForward(OLEConstants.MAPPING_BASIC); 110 } 111 112 GlobalVariables.getMessageMap().clearErrorPath(); 113 GlobalVariables.getMessageMap().addToErrorPath(OLEPropertyConstants.DOCUMENT); 114 115 //check for a po id 116 if (ObjectUtils.isNull(invoiceDocument.getPurchaseOrderIdentifier())) { 117 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.PURCHASE_ORDER_IDENTIFIER, OLEKeyConstants.ERROR_REQUIRED, PRQSDocumentsStrings.PURCHASE_ORDER_ID); 118 poNotNull = false; 119 } 120 121 if (ObjectUtils.isNull(invoiceDocument.getInvoiceDate())) { 122 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.INVOICE_DATE, OLEKeyConstants.ERROR_REQUIRED, PRQSDocumentsStrings.INVOICE_DATE); 123 poNotNull = false; 124 } 125 126 /*if (ObjectUtils.isNull(invoiceDocument.getInvoiceNumber())) { 127 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.INVOICE_NUMBER, OLEKeyConstants.ERROR_REQUIRED, PRQSDocumentsStrings.INVOICE_NUMBER); 128 poNotNull = false; 129 }*/ 130 invoiceDocument.setInvoiceNumber(invoiceDocument.getInvoiceNumber().toUpperCase()); 131 132 if (ObjectUtils.isNull(invoiceDocument.getVendorInvoiceAmount())) { 133 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.VENDOR_INVOICE_AMOUNT, OLEKeyConstants.ERROR_REQUIRED, PRQSDocumentsStrings.VENDOR_INVOICE_AMOUNT); 134 poNotNull = false; 135 } 136 137 //exit early as the po is null, no need to proceed further until this is taken care of 138 if (poNotNull == false) { 139 return mapping.findForward(OLEConstants.MAPPING_BASIC); 140 } 141 142 143 PurchaseOrderDocument po = SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(invoiceDocument.getPurchaseOrderIdentifier()); 144 if (ObjectUtils.isNotNull(po)) { 145 // 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 146 invoiceDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(po.getAccountsPayablePurchasingDocumentLinkIdentifier()); 147 148 //check to see if user is allowed to initiate doc based on PO sensitive data 149 if (!SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(invoiceDocument).isAuthorizedByTemplate(invoiceDocument, KRADConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.OPEN_DOCUMENT, GlobalVariables.getUserSession().getPrincipalId())) { 150 throw buildAuthorizationException("initiate document", invoiceDocument); 151 } 152 } 153 154 if (!SpringContext.getBean(InvoiceService.class).isPurchaseOrderValidForInvoiceDocumentCreation(invoiceDocument, po)) { 155 return mapping.findForward(OLEConstants.MAPPING_BASIC); 156 } 157 158 // perform duplicate check which will forward to a question prompt if one is found 159 ActionForward forward = performDuplicateInvoiceAndEncumberFiscalYearCheck(mapping, form, request, response, invoiceDocument); 160 if (forward != null) { 161 return forward; 162 } 163 164 // If we are here either there was no duplicate or there was a duplicate and the user hits continue, in either case we need 165 // to validate the business rules 166 SpringContext.getBean(InvoiceService.class).populateAndSaveInvoice(invoiceDocument); 167 168 // force calculation 169 prqsForm.setCalculated(false); 170 171 //TODO if better, move this to the action just before prqs goes into ATAX status 172 // force calculation for tax 173 prqsForm.setCalculatedTax(false); 174 175 // sort below the line 176 SpringContext.getBean(PurapService.class).sortBelowTheLine(invoiceDocument); 177 178 // update the counts on the form 179 prqsForm.updateItemCounts(); 180 181 return mapping.findForward(OLEConstants.MAPPING_BASIC); 182 } 183 184 185 /** 186 * Clears the initial fields on the <code>InvoiceDocument</code> which should be accessible from the given form. 187 * 188 * @param mapping An ActionMapping 189 * @param form An ActionForm, which must be a InvoiceForm 190 * @param request The HttpServletRequest 191 * @param response The HttpServletResponse 192 * @return An ActionForward 193 * @throws Exception 194 */ 195 public ActionForward clearInitFields(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 196 LOG.debug("clearInitValues() method"); 197 InvoiceForm prqsForm = (InvoiceForm) form; 198 InvoiceDocument invoiceDocument = (InvoiceDocument) prqsForm.getDocument(); 199 invoiceDocument.clearInitFields(); 200 201 return super.refresh(mapping, form, request, response); 202 } 203 204 /** 205 * This method runs two checks based on the user input on PRQS initiate screen: Encumber next fiscal year check and Duplicate 206 * payment request check. Encumber next fiscal year is checked first and will display a warning message to the user if it's the 207 * case. Duplicate payment request check calls <code>InvoiceService</code> to perform the duplicate payment request 208 * check. If one is found, a question is setup and control is forwarded to the question action method. Coming back from the 209 * question prompt the button that was clicked is checked and if 'no' was selected they are forward back to the page still in 210 * init mode. 211 * 212 * @param mapping An ActionMapping 213 * @param form An ActionForm 214 * @param request The HttpServletRequest 215 * @param response The HttpServletResponse 216 * @param invoiceDocument The InvoiceDocument 217 * @return An ActionForward 218 * @throws Exception 219 * @see org.kuali.ole.module.purap.document.service.InvoiceService 220 */ 221 protected ActionForward performDuplicateInvoiceAndEncumberFiscalYearCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, InvoiceDocument invoiceDocument) throws Exception { 222 ActionForward forward = null; 223 Object question = request.getParameter(OLEConstants.QUESTION_INST_ATTRIBUTE_NAME); 224 if (question == null) { 225 // perform encumber next fiscal year check and prompt warning message if needs 226 if (isEncumberNextFiscalYear(invoiceDocument)) { 227 String questionText = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(PurapKeyConstants.WARNING_ENCUMBER_NEXT_FY); 228 return this.performQuestionWithoutInput(mapping, form, request, response, PRQSDocumentsStrings.ENCUMBER_NEXT_FISCAL_YEAR_QUESTION, questionText, OLEConstants.CONFIRMATION_QUESTION, OLEConstants.ROUTE_METHOD, ""); 229 } else { 230 // perform duplicate payment request check 231 HashMap<String, String> duplicateMessages = SpringContext.getBean(InvoiceService.class).invoiceDuplicateMessages(invoiceDocument); 232 if (!duplicateMessages.isEmpty()) { 233 return this.performQuestionWithoutInput(mapping, form, request, response, PRQSDocumentsStrings.DUPLICATE_INVOICE_QUESTION, duplicateMessages.get(PRQSDocumentsStrings.DUPLICATE_INVOICE_QUESTION), OLEConstants.CONFIRMATION_QUESTION, OLEConstants.ROUTE_METHOD, ""); 234 } 235 } 236 } else { 237 Object buttonClicked = request.getParameter(OLEConstants.QUESTION_CLICKED_BUTTON); 238 // If the user replies 'Yes' to the encumber-next-year-question, proceed with duplicate payment check 239 if (PRQSDocumentsStrings.ENCUMBER_NEXT_FISCAL_YEAR_QUESTION.equals(question) && ConfirmationQuestion.YES.equals(buttonClicked)) { 240 HashMap<String, String> duplicateMessages = SpringContext.getBean(InvoiceService.class).invoiceDuplicateMessages(invoiceDocument); 241 if (!duplicateMessages.isEmpty()) { 242 return this.performQuestionWithoutInput(mapping, form, request, response, PRQSDocumentsStrings.DUPLICATE_INVOICE_QUESTION, duplicateMessages.get(PRQSDocumentsStrings.DUPLICATE_INVOICE_QUESTION), OLEConstants.CONFIRMATION_QUESTION, OLEConstants.ROUTE_METHOD, ""); 243 } 244 } 245 // If the user replies 'No' to either of the questions, redirect to the PRQS initiate page. 246 else if ((PRQSDocumentsStrings.ENCUMBER_NEXT_FISCAL_YEAR_QUESTION.equals(question) || PRQSDocumentsStrings.DUPLICATE_INVOICE_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) { 247 invoiceDocument.updateAndSaveAppDocStatus(InvoiceStatuses.APPDOC_INITIATE); 248 forward = mapping.findForward(OLEConstants.MAPPING_BASIC); 249 } 250 } 251 252 return forward; 253 } 254 255 /** 256 * Check if the current PRQS encumber next fiscal year from PO document. 257 * 258 * @param invoiceDocument 259 * @return 260 */ 261 protected boolean isEncumberNextFiscalYear(InvoiceDocument invoiceDocument) { 262 Integer fiscalYear = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear(); 263 if (invoiceDocument.getPurchaseOrderDocument().getPostingYear().intValue() > fiscalYear) { 264 return true; 265 } 266 return false; 267 } 268 269 /** 270 * Puts a payment on hold, prompting for a reason beforehand. This stops further approvals or routing. 271 * 272 * @param mapping An ActionMapping 273 * @param form An ActionForm 274 * @param request The HttpServletRequest 275 * @param response The HttpServletResponse 276 * @return An ActionForward 277 * @throws Exception 278 */ 279 public ActionForward addHoldOnPayment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 280 String operation = "Hold "; 281 282 PurQuestionCallback callback = new PurQuestionCallback() { 283 @Override 284 public AccountsPayableDocument doPostQuestion(AccountsPayableDocument document, String noteText) throws Exception { 285 document = SpringContext.getBean(InvoiceService.class).addHoldOnInvoice((InvoiceDocument) document, noteText); 286 return document; 287 } 288 }; 289 290 return askQuestionWithInput(mapping, form, request, response, PRQSDocumentsStrings.HOLD_PRQS_QUESTION, PRQSDocumentsStrings.HOLD_NOTE_PREFIX, operation, PurapKeyConstants.PAYMENT_REQUEST_MESSAGE_HOLD_DOCUMENT, callback); 291 } 292 293 /** 294 * Removes a hold on the payment request. 295 * 296 * @param mapping An ActionMapping 297 * @param form An ActionForm 298 * @param request The HttpServletRequest 299 * @param response The HttpServletResponse 300 * @return An ActionForward 301 * @throws Exception 302 */ 303 public ActionForward removeHoldFromPayment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 304 String operation = "Remove "; 305 306 PurQuestionCallback callback = new PurQuestionCallback() { 307 @Override 308 public AccountsPayableDocument doPostQuestion(AccountsPayableDocument document, String noteText) throws Exception { 309 document = SpringContext.getBean(InvoiceService.class).removeHoldOnInvoice((InvoiceDocument) document, noteText); 310 return document; 311 } 312 }; 313 314 return askQuestionWithInput(mapping, form, request, response, PRQSDocumentsStrings.REMOVE_HOLD_PRQS_QUESTION, PRQSDocumentsStrings.REMOVE_HOLD_NOTE_PREFIX, operation, PurapKeyConstants.PAYMENT_REQUEST_MESSAGE_REMOVE_HOLD_DOCUMENT, callback); 315 } 316 317 /** 318 * This action requests a cancel on a prqs, prompting for a reason before hand. This stops further approvals or routing. 319 * 320 * @param mapping An ActionMapping 321 * @param form An ActionForm 322 * @param request The HttpServletRequest 323 * @param response The HttpServletResponse 324 * @return An ActionForward 325 * @throws Exception 326 */ 327 public ActionForward requestCancelOnPayment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 328 String operation = "Cancel "; 329 330 PurQuestionCallback callback = new PurQuestionCallback() { 331 @Override 332 public AccountsPayableDocument doPostQuestion(AccountsPayableDocument document, String noteText) throws Exception { 333 SpringContext.getBean(InvoiceService.class).requestCancelOnInvoice((InvoiceDocument) document, noteText); 334 return document; 335 } 336 }; 337 338 return askQuestionWithInput(mapping, form, request, response, PRQSDocumentsStrings.CANCEL_PRQS_QUESTION, PRQSDocumentsStrings.CANCEL_NOTE_PREFIX, operation, PurapKeyConstants.PAYMENT_REQUEST_MESSAGE_CANCEL_DOCUMENT, callback); 339 } 340 341 /** 342 * @see AccountsPayableActionBase#cancelPOActionCallbackMethod() 343 */ 344// @Override 345// protected PurQuestionCallback cancelPOActionCallbackMethod() { 346// 347// return new PurQuestionCallback() { 348// public AccountsPayableDocument doPostQuestion(AccountsPayableDocument document, String noteText) throws Exception { 349// InvoiceDocument prqsDocument = (InvoiceDocument) document; 350// prqsDocument.setReopenPurchaseOrderIndicator(true); 351// return prqsDocument; 352// } 353// }; 354// } 355 356 /** 357 * Removes a request for cancel on a payment request. 358 * 359 * @param mapping An ActionMapping 360 * @param form An ActionForm 361 * @param request The HttpServletRequest 362 * @param response The HttpServletResponse 363 * @return An ActionForward 364 * @throws Exception 365 */ 366 public ActionForward removeCancelRequestFromPayment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 367 String operation = "Cancel "; 368 369 PurQuestionCallback callback = new PurQuestionCallback() { 370 @Override 371 public AccountsPayableDocument doPostQuestion(AccountsPayableDocument document, String noteText) throws Exception { 372 SpringContext.getBean(InvoiceService.class).removeRequestCancelOnInvoice((InvoiceDocument) document, noteText); 373 return document; 374 } 375 }; 376 377 return askQuestionWithInput(mapping, form, request, response, PRQSDocumentsStrings.REMOVE_CANCEL_PRQS_QUESTION, PRQSDocumentsStrings.REMOVE_CANCEL_NOTE_PREFIX, operation, PurapKeyConstants.PAYMENT_REQUEST_MESSAGE_REMOVE_CANCEL_DOCUMENT, callback); 378 } 379 380 /** 381 * Calls a service method to calculate for a payment request document. 382 * 383 * @param apDoc The AccountsPayableDocument 384 */ 385 @Override 386 protected void customCalculate(PurchasingAccountsPayableDocument apDoc) { 387 InvoiceDocument prqsDoc = (InvoiceDocument) apDoc; 388 389 // set amounts on any empty 390 prqsDoc.updateExtendedPriceOnItems(); 391 392 // calculation just for the tax area, only at tax review stage 393 // by now, the general calculation shall have been done. 394 if (StringUtils.equals(prqsDoc.getApplicationDocumentStatus(), InvoiceStatuses.APPDOC_AWAITING_TAX_REVIEW)) { 395 SpringContext.getBean(InvoiceService.class).calculateTaxArea(prqsDoc); 396 return; 397 } 398 399 // notice we're ignoring whether the boolean, because these are just warnings they shouldn't halt anything 400 //Calculate Payment request before rules since the rule check totalAmount. 401 SpringContext.getBean(InvoiceService.class).calculateInvoice(prqsDoc, true); 402 SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedCalculateAccountsPayableEvent(prqsDoc)); 403 } 404 405 /** 406 * @see AccountsPayableActionBase#getActionName() 407 */ 408 @Override 409 public String getActionName() { 410 return PurapConstants.INVOICE_ACTION_NAME; 411 } 412 413 public ActionForward useAlternateVendor(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 414 InvoiceForm prqsForm = (InvoiceForm) form; 415 InvoiceDocument document = (InvoiceDocument) prqsForm.getDocument(); 416 417 SpringContext.getBean(InvoiceService.class).changeVendor( 418 document, document.getAlternateVendorHeaderGeneratedIdentifier(), document.getAlternateVendorDetailAssignedIdentifier()); 419 420 return mapping.findForward(OLEConstants.MAPPING_BASIC); 421 } 422 423 public ActionForward useOriginalVendor(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 424 InvoiceForm prqsForm = (InvoiceForm) form; 425 InvoiceDocument document = (InvoiceDocument) prqsForm.getDocument(); 426 427 SpringContext.getBean(InvoiceService.class).changeVendor( 428 document, document.getOriginalVendorHeaderGeneratedIdentifier(), document.getOriginalVendorDetailAssignedIdentifier()); 429 430 return mapping.findForward(OLEConstants.MAPPING_BASIC); 431 } 432 433 @Override 434 public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 435 InvoiceDocument prqs = ((InvoiceForm) form).getInvoiceDocument(); 436 SpringContext.getBean(PurapService.class).prorateForTradeInAndFullOrderDiscount(prqs); 437 SpringContext.getBean(PurapAccountingService.class).updateAccountAmounts(prqs); 438 if (prqs.isClosePurchaseOrderIndicator()) { 439 PurchaseOrderDocument po = prqs.getPurchaseOrderDocument(); 440 if (po.canClosePOForTradeIn()) { 441 return super.route(mapping, form, request, response); 442 } else { 443 return mapping.findForward(OLEConstants.MAPPING_BASIC); 444 } 445 } else { 446 return super.route(mapping, form, request, response); 447 } 448 } 449 450 /** 451 * Overrides to invoke the updateAccountAmounts so that the account percentage will be 452 * correctly updated before validation for account percent is called. 453 * 454 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#approve(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 455 */ 456 @Override 457 public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 458 InvoiceDocument prqs = ((InvoiceForm) form).getInvoiceDocument(); 459 460 SpringContext.getBean(PurapService.class).prorateForTradeInAndFullOrderDiscount(prqs); 461 // if tax is required but not yet calculated, return and prompt user to calculate 462 if (requiresCalculateTax((InvoiceForm) form)) { 463 GlobalVariables.getMessageMap().putError(OLEConstants.DOCUMENT_ERRORS, PurapKeyConstants.ERROR_APPROVE_REQUIRES_CALCULATE); 464 return mapping.findForward(OLEConstants.MAPPING_BASIC); 465 } 466 467 // enforce calculating tax again upon approval, just in case user changes tax data without calculation 468 // other wise there will be a loophole, because the taxCalculated indicator is already set upon first calculation 469 // and thus system wouldn't know it's not re-calculated after tax data are changed 470 if (SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedPreCalculateAccountsPayableEvent(prqs))) { 471 // pre-calculation rules succeed, calculate tax again and go ahead with approval 472 customCalculate(prqs); 473 SpringContext.getBean(PurapAccountingService.class).updateAccountAmounts(prqs); 474 return super.approve(mapping, form, request, response); 475 } else { 476 // pre-calculation rules fail, go back to same page with error messages 477 return mapping.findForward(OLEConstants.MAPPING_BASIC); 478 } 479 } 480 481 /** 482 * Checks if tax calculation is required. 483 * Currently it is required when prqs is awaiting for tax approval and tax has not already been calculated. 484 * 485 * @param invoiceForm A Form, which must inherit from <code>AccountsPayableFormBase</code> 486 * @return true if calculation is required, false otherwise 487 */ 488 protected boolean requiresCalculateTax(InvoiceForm invoiceForm) { 489 InvoiceDocument prqs = (InvoiceDocument) invoiceForm.getDocument(); 490 boolean requiresCalculateTax = StringUtils.equals(prqs.getApplicationDocumentStatus(), InvoiceStatuses.APPDOC_AWAITING_TAX_REVIEW) && !invoiceForm.isCalculatedTax(); 491 return requiresCalculateTax; 492 } 493 494 public ActionForward changeUseTaxIndicator(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 495 PurchasingAccountsPayableDocument document = (PurchasingAccountsPayableDocument) ((PurchasingAccountsPayableFormBase) form).getDocument(); 496 497 //clear/recalculate tax and recreate GL entries 498 SpringContext.getBean(PurapService.class).updateUseTaxIndicator(document, !document.isUseTaxIndicator()); 499 SpringContext.getBean(PurapService.class).calculateTax(document); 500 501 //TODO: add recalculate GL entries hook here 502 503 return mapping.findForward(OLEConstants.MAPPING_BASIC); 504 } 505 506 /** 507 * Calls service to clear tax info. 508 */ 509 public ActionForward clearTaxInfo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 510 InvoiceForm prForm = (InvoiceForm) form; 511 InvoiceDocument document = (InvoiceDocument) prForm.getDocument(); 512 513 InvoiceService taxService = SpringContext.getBean(InvoiceService.class); 514 515 /* call service to clear previous lines */ 516 taxService.clearTax(document); 517 518 return mapping.findForward(OLEConstants.MAPPING_BASIC); 519 } 520 521 //MSU Contribution OLEMI-8558 DTT-3765 OLECNTRB-963 522 @Override 523 public ActionForward cancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 524 InvoiceForm prqsForm = (InvoiceForm) form; 525 526 InvoiceDocument prqsDocument = (InvoiceDocument) prqsForm.getDocument(); 527 528 ActionForward forward = mapping.findForward(RiceConstants.MAPPING_BASIC); 529 if (prqsDocument.getPurchaseOrderDocument().isPendingActionIndicator()) { 530 GlobalVariables.getMessageMap().putError( 531 OLEPropertyConstants.DOCUMENT + "." + OLEPropertyConstants.DOCUMENT_NUMBER, 532 PurapKeyConstants.ERROR_PAYMENT_REQUEST_CANNOT_BE_CANCELLED); 533 } else { 534 forward = super.cancel(mapping, form, request, response); 535 } 536 537 return forward; 538 } 539}