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 */ 016 017package org.kuali.ole.module.purap.document; 018 019import org.apache.commons.lang.StringUtils; 020import org.kuali.ole.module.purap.PurapConstants; 021import org.kuali.ole.module.purap.PurapConstants.InvoiceStatuses; 022import org.kuali.ole.module.purap.PurapConstants.PurapDocTypeCodes; 023import org.kuali.ole.module.purap.PurapParameterConstants; 024import org.kuali.ole.module.purap.PurapPropertyConstants; 025import org.kuali.ole.module.purap.PurapWorkflowConstants; 026import org.kuali.ole.module.purap.businessobject.*; 027import org.kuali.ole.module.purap.document.service.*; 028import org.kuali.ole.module.purap.service.PurapGeneralLedgerService; 029import org.kuali.ole.module.purap.util.ExpiredOrClosedAccountEntry; 030import org.kuali.ole.select.businessobject.OleLineItemReceivingItem; 031import org.kuali.ole.select.businessobject.OlePurchaseOrderItem; 032import org.kuali.ole.select.document.OleLineItemReceivingDocument; 033import org.kuali.ole.select.document.OlePurchaseOrderDocument; 034import org.kuali.ole.select.document.service.OleInvoiceService; 035import org.kuali.ole.sys.OLEConstants; 036import org.kuali.ole.sys.businessobject.AccountingLine; 037import org.kuali.ole.sys.businessobject.Bank; 038import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry; 039import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail; 040import org.kuali.ole.sys.context.SpringContext; 041import org.kuali.ole.sys.service.BankService; 042import org.kuali.ole.sys.service.UniversityDateService; 043import org.kuali.ole.sys.service.impl.OleParameterConstants; 044import org.kuali.ole.vnd.VendorPropertyConstants; 045import org.kuali.ole.vnd.businessobject.PaymentTermType; 046import org.kuali.ole.vnd.businessobject.PurchaseOrderCostSource; 047import org.kuali.ole.vnd.businessobject.ShippingPaymentTerms; 048import org.kuali.ole.vnd.businessobject.VendorDetail; 049import org.kuali.ole.vnd.document.service.VendorService; 050import org.kuali.rice.core.api.datetime.DateTimeService; 051import org.kuali.rice.core.api.util.type.KualiDecimal; 052import org.kuali.rice.coreservice.framework.parameter.ParameterService; 053import org.kuali.rice.kew.api.WorkflowDocument; 054import org.kuali.rice.kew.api.exception.WorkflowException; 055import org.kuali.rice.kew.framework.postprocessor.ActionTakenEvent; 056import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange; 057import org.kuali.rice.kim.api.identity.Person; 058import org.kuali.rice.kns.service.DataDictionaryService; 059import org.kuali.rice.krad.bo.Note; 060import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent; 061import org.kuali.rice.krad.service.DocumentHeaderService; 062import org.kuali.rice.krad.util.GlobalVariables; 063import org.kuali.rice.krad.util.ObjectUtils; 064import org.kuali.rice.krad.workflow.service.WorkflowDocumentService; 065 066import java.math.BigDecimal; 067import java.sql.Date; 068import java.sql.Timestamp; 069import java.text.SimpleDateFormat; 070import java.util.*; 071 072/** 073 * Payment Request Document Business Object. Contains the fields associated with the main document table. 074 */ 075public class InvoiceDocument extends AccountsPayableDocumentBase { 076 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(InvoiceDocument.class); 077 078 protected Date invoiceDate; 079 protected String invoiceNumber; 080 protected KualiDecimal vendorInvoiceAmount; 081 protected String vendorPaymentTermsCode; 082 protected String vendorShippingPaymentTermsCode; 083 protected Date invoicePayDate; 084 protected String invoiceCostSourceCode; 085 protected boolean invoiceCancelIndicator; 086 protected boolean paymentAttachmentIndicator; 087 protected boolean immediatePaymentIndicator; 088 protected String specialHandlingInstructionLine1Text; 089 protected String specialHandlingInstructionLine2Text; 090 protected String specialHandlingInstructionLine3Text; 091 protected Timestamp paymentPaidTimestamp; 092 protected boolean invoiceElectronicInvoiceIndicator; 093 protected String accountsPayableRequestCancelIdentifier; 094 protected Integer originalVendorHeaderGeneratedIdentifier; 095 protected Integer originalVendorDetailAssignedIdentifier; 096 protected Integer alternateVendorHeaderGeneratedIdentifier; 097 protected Integer alternateVendorDetailAssignedIdentifier; 098 protected String purchaseOrderNotes; 099 protected String recurringPaymentTypeCode; 100 protected boolean receivingDocumentRequiredIndicator; 101 protected boolean invoicePositiveApprovalIndicator; 102 103 // TAX EDIT AREA FIELDS 104 protected String taxClassificationCode; 105 protected String taxCountryCode; 106 protected String taxNQIId; 107 protected BigDecimal taxFederalPercent; // number is in whole form so 5% is 5.00 108 protected BigDecimal taxStatePercent; // number is in whole form so 5% is 5.00 109 protected KualiDecimal taxSpecialW4Amount; 110 protected Boolean taxGrossUpIndicator; 111 protected Boolean taxExemptTreatyIndicator; 112 protected Boolean taxForeignSourceIndicator; 113 protected Boolean taxUSAIDPerDiemIndicator; 114 protected Boolean taxOtherExemptIndicator; 115 116 // NOT PERSISTED IN DB 117 protected String vendorShippingTitleCode; 118 protected Date purchaseOrderEndDate; 119 protected String primaryVendorName; 120 121 // BELOW USED BY ROUTING 122 protected Integer requisitionIdentifier; 123 124 // REFERENCE OBJECTS 125 protected PaymentTermType vendorPaymentTerms; 126 protected ShippingPaymentTerms vendorShippingPaymentTerms; 127 protected PurchaseOrderCostSource invoiceCostSource; 128 protected RecurringPaymentType recurringPaymentType; 129 private List<OlePurchaseOrderDocument> purchaseOrderDocuments = new ArrayList<OlePurchaseOrderDocument>(); 130 131 public List<OlePurchaseOrderDocument> getPurchaseOrderDocuments() { 132 return purchaseOrderDocuments; 133 } 134 135 public void setPurchaseOrderDocuments(List<OlePurchaseOrderDocument> purchaseOrderDocuments) { 136 this.purchaseOrderDocuments = purchaseOrderDocuments; 137 } 138 139 /*private InvoiceService invoiceService;*/ 140 141 142 /** 143 * Default constructor. 144 */ 145 public InvoiceDocument() { 146 super(); 147 } 148 149 /** 150 * @see org.kuali.rice.krad.bo.PersistableBusinessObjectBase#isBoNotesSupport() 151 */ 152 public boolean isBoNotesSupport() { 153 return true; 154 } 155 156 public Integer getPostingYearPriorOrCurrent() { 157 if (SpringContext.getBean(InvoiceService.class).allowBackpost(this)) { 158 // allow prior; use it 159 return SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear() - 1; 160 } 161 // don't allow prior; use CURRENT 162 return SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear(); 163 } 164 165 166 /** 167 * Overrides the method in PurchasingAccountsPayableDocumentBase to add the criteria specific to Payment Request Document. 168 * 169 * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#isInquiryRendered() 170 */ 171 @Override 172 public boolean isInquiryRendered() { 173 if (isPostingYearPrior() && (getApplicationDocumentStatus().equals(InvoiceStatuses.APPDOC_DEPARTMENT_APPROVED) || getApplicationDocumentStatus().equals(InvoiceStatuses.APPDOC_AUTO_APPROVED) || getApplicationDocumentStatus().equals(InvoiceStatuses.APPDOC_CANCELLED_POST_AP_APPROVE) || getApplicationDocumentStatus().equals(InvoiceStatuses.APPDOC_CANCELLED_IN_PROCESS))) { 174 return false; 175 } else { 176 return true; 177 } 178 } 179 180 public Integer getRequisitionIdentifier() { 181 return getPurchaseOrderDocument().getRequisitionIdentifier(); 182 } 183 184 public void setRequisitionIdentifier(Integer requisitionIdentifier) { 185 this.requisitionIdentifier = requisitionIdentifier; 186 } 187 188 /** 189 * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#populateDocumentForRouting() 190 */ 191 /* @Override 192 public void populateDocumentForRouting() { 193 this.setRequisitionIdentifier(getPurchaseOrderDocument().getRequisitionIdentifier()); 194 super.populateDocumentForRouting(); 195 }*/ 196 197 /** 198 * Decides whether receivingDocumentRequiredIndicator functionality shall be enabled according to the controlling parameter. 199 */ 200 public boolean isEnableReceivingDocumentRequiredIndicator() { 201 return SpringContext.getBean(OleInvoiceService.class).getParameterBoolean(OLEConstants.OptionalModuleNamespaces.PURCHASING_ACCOUNTS_PAYABLE, OleParameterConstants.DOCUMENT_COMPONENT,PurapParameterConstants.RECEIVING_DOCUMENT_REQUIRED_IND); 202 } 203 204 /** 205 * Decides whether invoicePositiveApprovalIndicator functionality shall be enabled according to the controlling parameter. 206 */ 207 public boolean isEnableInvoicePositiveApprovalIndicator() { 208 return SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.PAYMENT_REQUEST_POSITIVE_APPROVAL_IND); 209 } 210 211 public Date getInvoiceDate() { 212 return invoiceDate; 213 } 214 215 public void setInvoiceDate(Date invoiceDate) { 216 this.invoiceDate = invoiceDate; 217 } 218 219 public String getInvoiceNumber() { 220 return invoiceNumber; 221 } 222 223 public void setInvoiceNumber(String invoiceNumber) { 224 if (!StringUtils.isEmpty(invoiceNumber)) { 225 this.invoiceNumber = invoiceNumber.toUpperCase(); 226 } else { 227 this.invoiceNumber = invoiceNumber; 228 } 229 } 230 231 public KualiDecimal getVendorInvoiceAmount() { 232 return vendorInvoiceAmount; 233 } 234 235 public void setVendorInvoiceAmount(KualiDecimal vendorInvoiceAmount) { 236 this.vendorInvoiceAmount = vendorInvoiceAmount; 237 } 238 239 public String getVendorPaymentTermsCode() { 240 return vendorPaymentTermsCode; 241 } 242 243 public void setVendorPaymentTermsCode(String vendorPaymentTermsCode) { 244 this.vendorPaymentTermsCode = vendorPaymentTermsCode; 245 refreshReferenceObject("vendorPaymentTerms"); 246 } 247 248 public PaymentTermType getVendorPaymentTerms() { 249 if (ObjectUtils.isNull(vendorPaymentTerms) || !StringUtils.equalsIgnoreCase(getVendorPaymentTermsCode(), vendorPaymentTerms.getVendorPaymentTermsCode())) { 250 refreshReferenceObject(VendorPropertyConstants.VENDOR_PAYMENT_TERMS); 251 } 252 return vendorPaymentTerms; 253 } 254 255 public void setVendorPaymentTerms(PaymentTermType vendorPaymentTerms) { 256 this.vendorPaymentTerms = vendorPaymentTerms; 257 } 258 259 public String getVendorShippingPaymentTermsCode() { 260 if (ObjectUtils.isNull(vendorPaymentTerms)) { 261 refreshReferenceObject(VendorPropertyConstants.VENDOR_SHIPPING_PAYMENT_TERMS); 262 } 263 return vendorShippingPaymentTermsCode; 264 } 265 266 public void setVendorShippingPaymentTermsCode(String vendorShippingPaymentTermsCode) { 267 this.vendorShippingPaymentTermsCode = vendorShippingPaymentTermsCode; 268 } 269 270 public Date getInvoicePayDate() { 271 return invoicePayDate; 272 } 273 274 public void setInvoicePayDate(Date invoicePayDate) { 275 this.invoicePayDate = invoicePayDate; 276 } 277 278 public String getInvoiceCostSourceCode() { 279 return invoiceCostSourceCode; 280 } 281 282 public void setInvoiceCostSourceCode(String invoiceCostSourceCode) { 283 this.invoiceCostSourceCode = invoiceCostSourceCode; 284 } 285 286 public boolean getInvoiceCancelIndicator() { 287 return invoiceCancelIndicator; 288 } 289 290 public boolean isInvoiceCancelIndicator() { 291 return invoiceCancelIndicator; 292 } 293 294 public void setInvoiceCancelIndicator(boolean invoiceCancelIndicator) { 295 this.invoiceCancelIndicator = invoiceCancelIndicator; 296 } 297 298 public boolean getPaymentAttachmentIndicator() { 299 return paymentAttachmentIndicator; 300 } 301 302 public void setPaymentAttachmentIndicator(boolean paymentAttachmentIndicator) { 303 this.paymentAttachmentIndicator = paymentAttachmentIndicator; 304 } 305 306 public boolean getImmediatePaymentIndicator() { 307 return immediatePaymentIndicator; 308 } 309 310 public void setImmediatePaymentIndicator(boolean immediatePaymentIndicator) { 311 this.immediatePaymentIndicator = immediatePaymentIndicator; 312 } 313 314 public String getSpecialHandlingInstructionLine1Text() { 315 return specialHandlingInstructionLine1Text; 316 } 317 318 public void setSpecialHandlingInstructionLine1Text(String specialHandlingInstructionLine1Text) { 319 this.specialHandlingInstructionLine1Text = specialHandlingInstructionLine1Text; 320 } 321 322 public String getSpecialHandlingInstructionLine2Text() { 323 return specialHandlingInstructionLine2Text; 324 } 325 326 public void setSpecialHandlingInstructionLine2Text(String specialHandlingInstructionLine2Text) { 327 this.specialHandlingInstructionLine2Text = specialHandlingInstructionLine2Text; 328 } 329 330 public String getSpecialHandlingInstructionLine3Text() { 331 return specialHandlingInstructionLine3Text; 332 } 333 334 public void setSpecialHandlingInstructionLine3Text(String specialHandlingInstructionLine3Text) { 335 this.specialHandlingInstructionLine3Text = specialHandlingInstructionLine3Text; 336 } 337 338 public Timestamp getPaymentPaidTimestamp() { 339 return paymentPaidTimestamp; 340 } 341 342 public void setPaymentPaidTimestamp(Timestamp paymentPaidTimestamp) { 343 this.paymentPaidTimestamp = paymentPaidTimestamp; 344 } 345 346 public boolean getInvoiceElectronicInvoiceIndicator() { 347 return invoiceElectronicInvoiceIndicator; 348 } 349 350 public void setInvoiceElectronicInvoiceIndicator(boolean invoiceElectronicInvoiceIndicator) { 351 this.invoiceElectronicInvoiceIndicator = invoiceElectronicInvoiceIndicator; 352 } 353 354 public String getAccountsPayableRequestCancelIdentifier() { 355 return accountsPayableRequestCancelIdentifier; 356 } 357 358 public void setAccountsPayableRequestCancelIdentifier(String accountsPayableRequestCancelIdentifier) { 359 this.accountsPayableRequestCancelIdentifier = accountsPayableRequestCancelIdentifier; 360 } 361 362 public Integer getOriginalVendorHeaderGeneratedIdentifier() { 363 return originalVendorHeaderGeneratedIdentifier; 364 } 365 366 public void setOriginalVendorHeaderGeneratedIdentifier(Integer originalVendorHeaderGeneratedIdentifier) { 367 this.originalVendorHeaderGeneratedIdentifier = originalVendorHeaderGeneratedIdentifier; 368 } 369 370 public Integer getOriginalVendorDetailAssignedIdentifier() { 371 return originalVendorDetailAssignedIdentifier; 372 } 373 374 public void setOriginalVendorDetailAssignedIdentifier(Integer originalVendorDetailAssignedIdentifier) { 375 this.originalVendorDetailAssignedIdentifier = originalVendorDetailAssignedIdentifier; 376 } 377 378 public Integer getAlternateVendorHeaderGeneratedIdentifier() { 379 return alternateVendorHeaderGeneratedIdentifier; 380 } 381 382 public void setAlternateVendorHeaderGeneratedIdentifier(Integer alternateVendorHeaderGeneratedIdentifier) { 383 this.alternateVendorHeaderGeneratedIdentifier = alternateVendorHeaderGeneratedIdentifier; 384 } 385 386 public Integer getAlternateVendorDetailAssignedIdentifier() { 387 return alternateVendorDetailAssignedIdentifier; 388 } 389 390 public void setAlternateVendorDetailAssignedIdentifier(Integer alternateVendorDetailAssignedIdentifier) { 391 this.alternateVendorDetailAssignedIdentifier = alternateVendorDetailAssignedIdentifier; 392 } 393 394 public ShippingPaymentTerms getVendorShippingPaymentTerms() { 395 return vendorShippingPaymentTerms; 396 } 397 398 public void setVendorShippingPaymentTerms(ShippingPaymentTerms vendorShippingPaymentTerms) { 399 this.vendorShippingPaymentTerms = vendorShippingPaymentTerms; 400 } 401 402 public String getVendorShippingTitleCode() { 403 if (ObjectUtils.isNotNull(this.getPurchaseOrderDocument())) { 404 return this.getPurchaseOrderDocument().getVendorShippingTitleCode(); 405 } 406 return vendorShippingTitleCode; 407 } 408 409 public void setVendorShippingTitleCode(String vendorShippingTitleCode) { 410 this.vendorShippingTitleCode = vendorShippingTitleCode; 411 } 412 413 public Date getPurchaseOrderEndDate() { 414 return purchaseOrderEndDate; 415 } 416 417 public void setPurchaseOrderEndDate(Date purchaseOrderEndDate) { 418 this.purchaseOrderEndDate = purchaseOrderEndDate; 419 } 420 421 /** 422 * Gets the invoicePositiveApprovalIndicator attribute. 423 * 424 * @return Returns the invoicePositiveApprovalIndicator. 425 */ 426 public boolean isInvoicePositiveApprovalIndicator() { 427 return invoicePositiveApprovalIndicator; 428 } 429 430 /** 431 * Sets the invoicePositiveApprovalIndicator attribute value. 432 * 433 * @param invoicePositiveApprovalIndicator 434 * The invoicePositiveApprovalIndicator to set. 435 */ 436 public void setInvoicePositiveApprovalIndicator(boolean invoicePositiveApprovalIndicator) { 437 // if invoicePositiveApprovalIndicator functionality is disabled, always set it to false, overriding the passed-in value 438 if (!isEnableInvoicePositiveApprovalIndicator()) { 439 invoicePositiveApprovalIndicator = false; 440 } else { 441 this.invoicePositiveApprovalIndicator = invoicePositiveApprovalIndicator; 442 } 443 } 444 445 /** 446 * Gets the receivingDocumentRequiredIndicator attribute. 447 * 448 * @return Returns the receivingDocumentRequiredIndicator. 449 */ 450 public boolean isReceivingDocumentRequiredIndicator() { 451 return receivingDocumentRequiredIndicator; 452 } 453 454 /** 455 * Sets the receivingDocumentRequiredIndicator attribute value. 456 * 457 * @param receivingDocumentRequiredIndicator 458 * The receivingDocumentRequiredIndicator to set. 459 */ 460 public void setReceivingDocumentRequiredIndicator(boolean receivingDocumentRequiredIndicator) { 461 // if receivingDocumentRequiredIndicator functionality is disabled, always set it to false, overriding the passed-in value 462 if (!isEnableReceivingDocumentRequiredIndicator()) { 463 this.receivingDocumentRequiredIndicator = false; 464 } else { 465 this.receivingDocumentRequiredIndicator = receivingDocumentRequiredIndicator; 466 } 467 } 468 469 /** 470 * Perform logic needed to initiate PRQS Document 471 */ 472 public void initiateDocument() throws WorkflowException { 473 LOG.debug("initiateDocument() started"); 474 Person currentUser = GlobalVariables.getUserSession().getPerson(); 475 if (this.getDocumentHeader().getDocumentNumber() == null) { 476 this.setDocumentHeader(SpringContext.getBean(DocumentHeaderService.class).getDocumentHeaderById(getDocumentNumber())); 477 } 478 //oleInvoiceDocument.setItems(items); 479 UniversityDateService universityDateService = SpringContext.getBean(UniversityDateService.class); 480 this.setPostingYear(universityDateService.getCurrentUniversityDate().getUniversityFiscalYear()); 481 Bank defaultBank = SpringContext.getBean(BankService.class).getDefaultBankByDocType(this.getClass()); 482 if (defaultBank != null) { 483 this.setBankCode(defaultBank.getBankCode()); 484 this.setBank(defaultBank); 485 } 486 updateAndSaveAppDocStatus(InvoiceStatuses.APPDOC_INITIATE); 487 this.setAccountsPayableProcessorIdentifier(currentUser.getPrincipalId()); 488 this.setProcessingCampusCode(currentUser.getCampusCode()); 489 this.refreshNonUpdateableReferences(); 490 this.getDocumentHeader().setDocumentDescription(" New Invoice Document "); 491 } 492 493 /** 494 * Perform logic needed to clear the initial fields on a PRQS Document 495 */ 496 public void clearInitFields() { 497 LOG.debug("clearDocument() started"); 498 // Clearing document overview fields 499 this.getDocumentHeader().setDocumentDescription(null); 500 this.getDocumentHeader().setExplanation(null); 501 this.getFinancialSystemDocumentHeader().setFinancialDocumentTotalAmount(null); 502 this.getDocumentHeader().setOrganizationDocumentNumber(null); 503 504 // Clearing document Init fields 505 //this.setPurchaseOrderIdentifier(null); 506 this.setInvoiceNumber(null); 507 this.setInvoiceDate(null); 508 this.setVendorInvoiceAmount(null); 509 this.setSpecialHandlingInstructionLine1Text(null); 510 this.setSpecialHandlingInstructionLine2Text(null); 511 this.setSpecialHandlingInstructionLine3Text(null); 512 } 513 514 /** 515 * Populates a preq from a PO - delegate method 516 * 517 * @param po - 518 */ 519 public void populateInvoiceFromPurchaseOrder(PurchaseOrderDocument po) { 520 populateInvoiceFromPurchaseOrder(po, new HashMap<String, ExpiredOrClosedAccountEntry>()); 521 } 522 523 524 /** 525 * Populates a preq from a PO 526 * 527 * @param po Purchase Order Document used for populating the PRQS 528 * @param expiredOrClosedAccountList a list of closed or expired accounts 529 */ 530 public void populateInvoiceFromPurchaseOrder(PurchaseOrderDocument po, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) { 531 //this.setPurchaseOrderIdentifier(po.getPurapDocumentIdentifier()); 532 this.getDocumentHeader().setOrganizationDocumentNumber(po.getDocumentHeader().getOrganizationDocumentNumber()); 533 this.setPostingYear(this.getPostingYearPriorOrCurrent()); 534 this.setReceivingDocumentRequiredIndicator(po.isReceivingDocumentRequiredIndicator()); 535 //this.setUseTaxIndicator(po.isUseTaxIndicator()); 536 this.setInvoicePositiveApprovalIndicator(po.isPaymentRequestPositiveApprovalIndicator()); 537 //this.setVendorCustomerNumber(po.getVendorCustomerNumber()); 538 //this.setAccountDistributionMethod(po.getAccountDistributionMethod()); 539 540 if (po.getPurchaseOrderCostSource() != null) { 541 this.setInvoiceCostSource(po.getPurchaseOrderCostSource()); 542 this.setInvoiceCostSourceCode(po.getPurchaseOrderCostSourceCode()); 543 } 544 545 if (po.getVendorShippingPaymentTerms() != null) { 546 this.setVendorShippingPaymentTerms(po.getVendorShippingPaymentTerms()); 547 this.setVendorShippingPaymentTermsCode(po.getVendorShippingPaymentTermsCode()); 548 } 549 550 if (po.getVendorPaymentTerms() != null) { 551 this.setVendorPaymentTermsCode(po.getVendorPaymentTermsCode()); 552 this.setVendorPaymentTerms(po.getVendorPaymentTerms()); 553 } 554 555 if (po.getRecurringPaymentType() != null) { 556 this.setRecurringPaymentType(po.getRecurringPaymentType()); 557 this.setRecurringPaymentTypeCode(po.getRecurringPaymentTypeCode()); 558 } 559 560 /*this.setVendorHeaderGeneratedIdentifier(po.getVendorHeaderGeneratedIdentifier()); 561 this.setVendorDetailAssignedIdentifier(po.getVendorDetailAssignedIdentifier()); 562 this.setVendorCustomerNumber(po.getVendorCustomerNumber()); 563 this.setVendorName(po.getVendorName());*/ 564 565 // set original vendor 566 this.setOriginalVendorHeaderGeneratedIdentifier(po.getVendorHeaderGeneratedIdentifier()); 567 this.setOriginalVendorDetailAssignedIdentifier(po.getVendorDetailAssignedIdentifier()); 568 569 // set alternate vendor info as well 570 this.setAlternateVendorHeaderGeneratedIdentifier(po.getAlternateVendorHeaderGeneratedIdentifier()); 571 this.setAlternateVendorDetailAssignedIdentifier(po.getAlternateVendorDetailAssignedIdentifier()); 572 573 // populate preq vendor address with the default remit address type for the vendor if found 574 String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode(); 575 /*VendorAddress vendorAddress = SpringContext.getBean(VendorService.class).getVendorDefaultAddress(po.getVendorHeaderGeneratedIdentifier(), po.getVendorDetailAssignedIdentifier(), VendorConstants.AddressTypes.REMIT, userCampus); 576 if (vendorAddress != null) { 577 this.templateVendorAddress(vendorAddress); 578 this.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier()); 579 setVendorAttentionName(StringUtils.defaultString(vendorAddress.getVendorAttentionName())); 580 } 581 else { 582 // set address from PO 583 this.setVendorAddressGeneratedIdentifier(po.getVendorAddressGeneratedIdentifier()); 584 this.setVendorLine1Address(po.getVendorLine1Address()); 585 this.setVendorLine2Address(po.getVendorLine2Address()); 586 this.setVendorCityName(po.getVendorCityName()); 587 this.setVendorAddressInternationalProvinceName(po.getVendorAddressInternationalProvinceName()); 588 this.setVendorStateCode(po.getVendorStateCode()); 589 this.setVendorPostalCode(po.getVendorPostalCode()); 590 this.setVendorCountryCode(po.getVendorCountryCode()); 591 592 boolean blankAttentionLine = StringUtils.equalsIgnoreCase("Y", SpringContext.getBean(ParameterService.class).getParameterValueAsString(PurapConstants.PURAP_NAMESPACE, "Document", PurapParameterConstants.BLANK_ATTENTION_LINE_FOR_PO_TYPE_ADDRESS)); 593 594 if (blankAttentionLine) { 595 setVendorAttentionName(StringUtils.EMPTY); 596 } 597 else { 598 setVendorAttentionName(StringUtils.defaultString(po.getVendorAttentionName())); 599 } 600 }*/ 601 602 this.setInvoicePayDate(SpringContext.getBean(InvoiceService.class).calculatePayDate(this.getInvoiceDate(), this.getVendorPaymentTerms())); 603 604 AccountsPayableService accountsPayableService = SpringContext.getBean(AccountsPayableService.class); 605 606 if (SpringContext.getBean(InvoiceService.class).encumberedItemExistsForInvoicing(po)) { 607 for (PurchaseOrderItem poi : (List<PurchaseOrderItem>) po.getItems()) { 608 // check to make sure it's eligible for payment (i.e. active and has encumbrance available 609 if (getDocumentSpecificService().poItemEligibleForAp(this, poi)) { 610 InvoiceItem invoiceItem = new InvoiceItem(poi, this, expiredOrClosedAccountList); 611 invoiceItem.setReceivingDocumentRequiredIndicator(po.isReceivingDocumentRequiredIndicator()); 612 this.getItems().add(invoiceItem); 613 PurchasingCapitalAssetItem purchasingCAMSItem = po.getPurchasingCapitalAssetItemByItemIdentifier(poi.getItemIdentifier()); 614 if (purchasingCAMSItem != null) { 615 invoiceItem.setCapitalAssetTransactionTypeCode(purchasingCAMSItem.getCapitalAssetTransactionTypeCode()); 616 } 617 618 /* 619 // copy usetaxitems over 620 invoiceItem.getUseTaxItems().clear(); 621 for (PurApItemUseTax useTax : poi.getUseTaxItems()) { 622 invoiceItem.getUseTaxItems().add(useTax); 623 } 624 */ 625 } 626 } 627 } 628 629 // add missing below the line 630 SpringContext.getBean(PurapService.class).addBelowLineItems(this); 631 this.setAccountsPayablePurchasingDocumentLinkIdentifier(po.getAccountsPayablePurchasingDocumentLinkIdentifier()); 632 633 //fix up below the line items 634 SpringContext.getBean(InvoiceService.class).removeIneligibleAdditionalCharges(this); 635 636 this.fixItemReferences(); 637 this.refreshNonUpdateableReferences(); 638 } 639 640 /** 641 * @see org.kuali.rice.krad.document.DocumentBase#getDocumentTitle() 642 */ 643 @Override 644 public String getDocumentTitle() { 645 if (SpringContext.getBean(OleInvoiceService.class).getParameterBoolean(OLEConstants.OptionalModuleNamespaces.PURCHASING_ACCOUNTS_PAYABLE, OLEConstants.InvoiceDocument.CMPNT_CD, PurapParameterConstants.PURAP_OVERRIDE_PRQS_DOC_TITLE)) { 646 return getCustomDocumentTitle(); 647 } 648 return this.buildDocumentTitle(super.getDocumentTitle()); 649 } 650 651 /** 652 * Returns a custom document title based on the workflow document title. Depending on what route level the document is currently 653 * in, the PO, vendor, amount, account number, dept, campus may be added to the documents title. 654 * 655 * @return - Customized document title text dependent upon route level. 656 */ 657 protected String getCustomDocumentTitle() { 658 659 // set the workflow document title 660 //String poNumber = getPurchaseOrderIdentifier().toString(); 661 String vendorName = StringUtils.trimToEmpty(getVendorName()); 662 String preqAmount = getGrandTotal().toString(); 663 664 String documentTitle = ""; 665 Set<String> nodeNames = this.getFinancialSystemDocumentHeader().getWorkflowDocument().getCurrentNodeNames(); 666 667 // if this doc is final or will be final 668 if (nodeNames.size() == 0 || this.getFinancialSystemDocumentHeader().getWorkflowDocument().isFinal()) { 669 // documentTitle = (new StringBuffer("PO: ")).append(poNumber).append(" Vendor: ").append(vendorName).append(" Amount: ").append(preqAmount).toString(); 670 documentTitle = (new StringBuffer()).append(" Vendor: ").append(vendorName).append(" Amount: ").append(preqAmount).toString(); 671 } else { 672 PurApAccountingLine theAccount = getFirstAccount(); 673 String accountNumber = (theAccount != null ? StringUtils.trimToEmpty(theAccount.getAccountNumber()) : "n/a"); 674 String accountChart = (theAccount != null ? theAccount.getChartOfAccountsCode() : ""); 675 String payDate = (new SimpleDateFormat("MM/dd/yyyy")).format(getInvoicePayDate()); 676 String indicator = getTitleIndicator(); 677 678 // set title to: PO# - VendorName - Chart/Account - total amt - Pay Date - Indicator (ie Hold, Request Cancel) 679 documentTitle = (new StringBuffer()).append(" Vendor: ").append(vendorName).append(" Account: ").append(accountChart).append(" ").append(accountNumber).append(" Amount: ").append(preqAmount).append(" Pay Date: ").append(payDate).append(" ").append(indicator).toString(); 680 } 681 return documentTitle; 682 } 683 684 /** 685 * Returns the first payment item's first account (assuming the item list is sequentially ordered). 686 * 687 * @return - Accounting Line object for first account of first payment item. 688 */ 689 public PurApAccountingLine getFirstAccount() { 690 // loop through items, and pick the first item 691 if ((getItems() != null) && (!getItems().isEmpty())) { 692 InvoiceItem itemToUse = null; 693 for (Iterator iter = getItems().iterator(); iter.hasNext(); ) { 694 InvoiceItem item = (InvoiceItem) iter.next(); 695 if ((item.isConsideredEntered()) && ((item.getSourceAccountingLines() != null) && (!item.getSourceAccountingLines().isEmpty()))) { 696 // accounting lines are not empty so pick the first account 697 PurApAccountingLine accountLine = item.getSourceAccountingLine(0); 698 accountLine.refreshNonUpdateableReferences(); 699 return accountLine; 700 } 701 /* 702 if (((item.getExtendedPrice() != null) && item.getExtendedPrice().compareTo(BigDecimal.ZERO) > 0) && ((item.getAccounts() != null) && (!item.getAccounts().isEmpty()))) { 703 // accounting lines are not empty so pick the first account 704 List accts = (List)item.getAccounts(); 705 InvoiceAccount accountLine = (InvoiceAccount)accts.get(0); 706 return accountLine.getFinancialChartOfAccountsCode() + "-" + accountLine.getAccountNumber(); 707 } 708 */ 709 } 710 } 711 return null; 712 } 713 714 /** 715 * Determines the indicator text that will appear in the workflow document title 716 * 717 * @return - Text of hold or request cancel 718 */ 719 protected String getTitleIndicator() { 720 if (isHoldIndicator()) { 721 return PurapConstants.InvoiceIndicatorText.HOLD; 722 } else if (isInvoiceCancelIndicator()) { 723 return PurapConstants.InvoiceIndicatorText.REQUEST_CANCEL; 724 } 725 return ""; 726 } 727 728 729 /** 730 * @see org.kuali.rice.krad.document.DocumentBase#doRouteStatusChange(org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange) 731 */ 732 @Override 733 public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) { 734 LOG.debug("doRouteStatusChange() started"); 735 736 super.doRouteStatusChange(statusChangeEvent); 737 try { 738 // DOCUMENT PROCESSED 739 if (this.getFinancialSystemDocumentHeader().getWorkflowDocument().isProcessed()) { 740 if (!InvoiceStatuses.APPDOC_AUTO_APPROVED.equals(getApplicationDocumentStatus())) { 741 populateDocumentForRouting(); 742 updateAndSaveAppDocStatus(InvoiceStatuses.APPDOC_DEPARTMENT_APPROVED); 743 744 //PurchaseOrderDocument purchaseOrderDocument = this.getPurchaseOrderDocument(); 745 /*if (purchaseOrderDocument.getOrderType().getPurchaseOrderType().equals(OLEConstants.ORD_TYPE_FIRM_FIX) || purchaseOrderDocument.getOrderType().getPurchaseOrderType().equals(OLEConstants.APPROVAL) || purchaseOrderDocument.getOrderType().getPurchaseOrderType().equals(OLEConstants.FIRM_MUL_PART)) { 746 DocumentHeader invoiceDocumentHeader = this.getDocumentHeader(); 747 closePurchaseOrder(); 748 this.setDocumentHeader(invoiceDocumentHeader); 749 } */ 750 751 } 752 } 753 754 // DOCUMENT DISAPPROVED 755 else if (this.getFinancialSystemDocumentHeader().getWorkflowDocument().isDisapproved()) { 756 String nodeName = SpringContext.getBean(WorkflowDocumentService.class).getCurrentRouteLevelName(getDocumentHeader().getWorkflowDocument()); 757 String disapprovalStatus = InvoiceStatuses.getInvoiceAppDocDisapproveStatuses().get(nodeName); 758 759 if (ObjectUtils.isNotNull(nodeName)) { 760 if (((StringUtils.isBlank(disapprovalStatus)) && ((InvoiceStatuses.APPDOC_INITIATE.equals(getApplicationDocumentStatus())) || (InvoiceStatuses.APPDOC_IN_PROCESS.equals(getApplicationDocumentStatus()))))) { 761 disapprovalStatus = InvoiceStatuses.APPDOC_CANCELLED_IN_PROCESS; 762 } 763 if (StringUtils.isNotBlank(disapprovalStatus)) { 764 SpringContext.getBean(AccountsPayableService.class).cancelAccountsPayableDocument(this, nodeName); 765 } 766 } else { 767 logAndThrowRuntimeException("No status found to set for document being disapproved in node '" + nodeName + "'"); 768 } 769 } 770 // DOCUMENT CANCELED 771 else if (this.getFinancialSystemDocumentHeader().getWorkflowDocument().isCanceled()) { 772 String currentNodeName = SpringContext.getBean(WorkflowDocumentService.class).getCurrentRouteLevelName(this.getDocumentHeader().getWorkflowDocument()); 773 String cancelledStatus = InvoiceStatuses.getInvoiceAppDocDisapproveStatuses().get(currentNodeName); 774 775 //**START AZ** KATTS-37 KevinMcO 776 if (StringUtils.isBlank(cancelledStatus) && 777 StringUtils.isBlank(InvoiceStatuses.getInvoiceAppDocDisapproveStatuses().get(currentNodeName)) && 778 (InvoiceStatuses.APPDOC_INITIATE.equals(getStatusCode()) || InvoiceStatuses.APPDOC_IN_PROCESS.equals(getStatusCode()))) { 779 cancelledStatus = InvoiceStatuses.APPDOC_CANCELLED_IN_PROCESS; 780 } 781 //**END AZ** 782 783 if (ObjectUtils.isNotNull(cancelledStatus)) { 784 SpringContext.getBean(AccountsPayableService.class).cancelAccountsPayableDocument(this, currentNodeName); 785 updateAndSaveAppDocStatus(cancelledStatus); 786 } else { 787 logAndThrowRuntimeException("No status found to set for document being canceled in node '" + currentNodeName + "'"); 788 } 789 } 790 } catch (WorkflowException e) { 791 logAndThrowRuntimeException("Error saving routing data while saving document with id " + getDocumentNumber(), e); 792 } 793 } 794 795 /** 796 * Generates correcting entries to the GL if accounts are modified. 797 * 798 * @see org.kuali.rice.krad.document.Document#doActionTaken(org.kuali.rice.kew.framework.postprocessor.ActionTakenEvent) 799 */ 800 @Override 801 public void doActionTaken(ActionTakenEvent event) { 802 super.doActionTaken(event); 803 WorkflowDocument workflowDocument = getDocumentHeader().getWorkflowDocument(); 804 String currentNode = null; 805 Object[] names = workflowDocument.getCurrentNodeNames().toArray(); 806 if (names.length > 0) { 807 currentNode = (String) names[0]; 808 } 809 810 // everything in the below list requires correcting entries to be written to the GL 811 // if (InvoiceStatuses.getNodesRequiringCorrectingGeneralLedgerEntries().contains(currentNode)) { 812 // SpringContext.getBean(PurapGeneralLedgerService.class).generateEntriesModifyInvoice(this); 813 // } 814 } 815 816 /** 817 * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#processNodeChange(String, String) 818 */ 819 @Override 820 public boolean processNodeChange(String newNodeName, String oldNodeName) { 821 if (InvoiceStatuses.APPDOC_AUTO_APPROVED.equals(getApplicationDocumentStatus())) { 822 // do nothing for an auto approval 823 return false; 824 } 825 if (InvoiceStatuses.NODE_ADHOC_REVIEW.equals(oldNodeName)) { 826 SpringContext.getBean(AccountsPayableService.class).performLogicForFullEntryCompleted(this); 827 } 828 return true; 829 } 830 831 /** 832 * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#saveDocumentFromPostProcessing() 833 */ 834 @Override 835 public void saveDocumentFromPostProcessing() { 836 SpringContext.getBean(PurapService.class).saveDocumentNoValidation(this); 837 838 // if we've hit full entry completed then close/reopen po 839 if (SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(this) && this.isClosePurchaseOrderIndicator()) { 840 SpringContext.getBean(PurapService.class).performLogicForCloseReopenPO(this); 841 } 842 } 843 844 /** 845 * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getItemClass() 846 */ 847 @Override 848 public Class getItemClass() { 849 return InvoiceItem.class; 850 } 851 852 @Override 853 public Class getItemUseTaxClass() { 854 return InvoiceItemUseTax.class; 855 } 856 857 /** 858 * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getPurApSourceDocumentIfPossible() 859 */ 860 @Override 861 public PurchaseOrderDocument getPurApSourceDocumentIfPossible() { 862 return getPurchaseOrderDocument(); 863 } 864 865 /** 866 * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getPurApSourceDocumentLabelIfPossible() 867 */ 868 @Override 869 public String getPurApSourceDocumentLabelIfPossible() { 870 return SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByTypeName(OLEConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER); 871 } 872 873 public String getPurchaseOrderNotes() { 874 875 ArrayList poNotes = (ArrayList) this.getPurchaseOrderDocument().getNotes(); 876 877 if (poNotes.size() > 0) { 878 return "Yes"; 879 } 880 return "No"; 881 } 882 883 public void setPurchaseOrderNotes(String purchaseOrderNotes) { 884 this.purchaseOrderNotes = purchaseOrderNotes; 885 } 886 887 public String getRecurringPaymentTypeCode() { 888 return recurringPaymentTypeCode; 889 } 890 891 public void setRecurringPaymentTypeCode(String recurringPaymentTypeCode) { 892 this.recurringPaymentTypeCode = recurringPaymentTypeCode; 893 } 894 895 /** 896 * Returns the total encumbered amount from the purchase order excluding below the line. 897 * 898 * @return Total cost excluding below the line 899 */ 900 public KualiDecimal getItemTotalPoEncumbranceAmount() { 901 // get total from po excluding below the line and inactive 902 return this.getPurchaseOrderDocument().getTotalDollarAmount(false, false); 903 } 904 905 public KualiDecimal getItemTotalPoEncumbranceAmountRelieved() { 906 return getItemTotalPoEncumbranceAmountRelieved(false); 907 } 908 909 public KualiDecimal getItemTotalPoEncumbranceAmountRelieved(boolean includeBelowTheLine) { 910 911 KualiDecimal total = KualiDecimal.ZERO; 912 913 for (PurchaseOrderItem item : (List<PurchaseOrderItem>) getPurchaseOrderDocument().getItems()) { 914 ItemType it = item.getItemType(); 915 if (includeBelowTheLine || it.isLineItemIndicator()) { 916 total = total.add(item.getItemEncumbranceRelievedAmount()); 917 } 918 } 919 return total; 920 } 921 922 public KualiDecimal getLineItemTotal() { 923 return this.getTotalDollarAmountAboveLineItems(); 924 } 925 926 public KualiDecimal getLineItemPreTaxTotal() { 927 return this.getTotalPreTaxDollarAmountAboveLineItems(); 928 } 929 930 public KualiDecimal getLineItemTaxAmount() { 931 return this.getTotalTaxAmountAboveLineItems(); 932 } 933 934 @Override 935 public KualiDecimal getGrandTotal() { 936 return this.getTotalDollarAmount(); 937 } 938 939 public KualiDecimal getGrandTotalExcludingDiscount() { 940 String[] discountCode = new String[]{PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE}; 941 return this.getTotalDollarAmountWithExclusions(discountCode, true); 942 } 943 944 /** 945 * This method is here due to a setter requirement by the htmlControlAttribute 946 * 947 * @param amount - Grand total for document, excluding discount 948 */ 949 public void setGrandTotalExcludingDiscount(KualiDecimal amount) { 950 // do nothing 951 } 952 953 public KualiDecimal getGrandPreTaxTotal() { 954 return this.getTotalPreTaxDollarAmount(); 955 } 956 957 public KualiDecimal getGrandPreTaxTotalExcludingDiscount() { 958 String[] discountCode = new String[]{PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE}; 959 return this.getTotalPreTaxDollarAmountWithExclusions(discountCode, true); 960 } 961 962 public KualiDecimal getGrandTaxAmount() { 963 return this.getTotalTaxAmount(); 964 } 965 966 public KualiDecimal getGrandTaxAmountExcludingDiscount() { 967 String[] discountCode = new String[]{PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE}; 968 return this.getTotalTaxAmountWithExclusions(discountCode, true); 969 } 970 971 public boolean isDiscount() { 972 return SpringContext.getBean(InvoiceService.class).hasDiscountItem(this); 973 } 974 975 /** 976 * The total that was paid on the po excluding below the line 977 * 978 * @return total paid 979 */ 980 public KualiDecimal getItemTotalPoPaidAmount() { 981 KualiDecimal total = KualiDecimal.ZERO; 982 for (PurchaseOrderItem item : (List<PurchaseOrderItem>) getPurchaseOrderDocument().getItems()) { 983 ItemType iT = item.getItemType(); 984 if (iT.isLineItemIndicator()) { 985 KualiDecimal itemPaid = item.getItemPaidAmount(); 986 total = total.add(itemPaid); 987 } 988 } 989 return total; 990 } 991 992 /** 993 * Returns the name of who requested cancel. 994 * 995 * @return - name of who requested cancel. 996 */ 997 public String getAccountsPayableRequestCancelPersonName() { 998 String personName = null; 999 Person user = SpringContext.getBean(org.kuali.rice.kim.api.identity.PersonService.class).getPerson(getAccountsPayableRequestCancelIdentifier()); 1000 if (user != null) { 1001 personName = user.getName(); 1002 } else { 1003 personName = ""; 1004 } 1005 1006 return personName; 1007 } 1008 1009 /** 1010 * Exists due to a setter requirement by the htmlControlAttribute 1011 * 1012 * @param amount - total po amount paid 1013 */ 1014 public void setItemTotalPoPaidAmount(KualiDecimal amount) { 1015 // do nothing 1016 } 1017 1018 /** 1019 * Exists due to a setter requirement by the htmlControlAttribute 1020 * 1021 * @param amount - total po encumbrance 1022 */ 1023 public void setItemTotalPoEncumbranceAmount(KualiDecimal amount) { 1024 // do nothing 1025 } 1026 1027 /** 1028 * Exists due to a setter requirement by the htmlControlAttribute 1029 * 1030 * @param amount - total po encumbrance amount relieved 1031 */ 1032 public void setItemTotalPoEncumbranceAmountRelieved(KualiDecimal amount) { 1033 // do nothing 1034 } 1035 1036 /** 1037 * Determinines the route levels for a given document. 1038 * 1039 * @param workflowDocument - work flow document 1040 * @return List - list of route levels 1041 */ 1042 protected List<String> getCurrentRouteLevels(WorkflowDocument workflowDocument) { 1043 Set<String> names = workflowDocument.getCurrentNodeNames(); 1044 return new ArrayList<String>(names); 1045 } 1046 1047 public RecurringPaymentType getRecurringPaymentType() { 1048 /*if (ObjectUtils.isNull(recurringPaymentType)) { 1049 refreshReferenceObject(PurapPropertyConstants.RECURRING_PAYMENT_TYPE); 1050 }*/ 1051 return recurringPaymentType; 1052 } 1053 1054 public void setRecurringPaymentType(RecurringPaymentType recurringPaymentType) { 1055 this.recurringPaymentType = recurringPaymentType; 1056 } 1057 1058 public PurchaseOrderCostSource getInvoiceCostSource() { 1059 return invoiceCostSource; 1060 } 1061 1062 public void setInvoiceCostSource(PurchaseOrderCostSource invoiceCostSource) { 1063 this.invoiceCostSource = invoiceCostSource; 1064 } 1065 1066 /** 1067 * @see AccountsPayableDocumentBase#getPoDocumentTypeForAccountsPayableDocumentCancel() 1068 */ 1069 @Override 1070 public String getPoDocumentTypeForAccountsPayableDocumentCancel() { 1071 return PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_REOPEN_DOCUMENT; 1072 } 1073 1074 /** 1075 * @see AccountsPayableDocumentBase#getInitialAmount() 1076 */ 1077 @Override 1078 public KualiDecimal getInitialAmount() { 1079 return this.getVendorInvoiceAmount(); 1080 } 1081 1082 /** 1083 * Populates the payment request document, then continues with preparing for save. 1084 * 1085 * @see org.kuali.rice.krad.document.Document#prepareForSave(org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent) 1086 */ 1087 @Override 1088 public void prepareForSave(KualiDocumentEvent event) { 1089 WorkflowDocument workflowDocument = this.getDocumentHeader().getWorkflowDocument(); 1090 String workflowDocumentTitle = this.buildDocumentTitle(workflowDocument.getTitle()); 1091 1092 this.getFinancialSystemDocumentHeader().getWorkflowDocument().setTitle(workflowDocumentTitle); 1093 1094 // first populate, then call super 1095 /*if (event instanceof AttributedContinuePurapEvent) { 1096 SpringContext.getBean(InvoiceService.class).populateInvoice(this); 1097 }*/ 1098 super.prepareForSave(event); 1099 1100 } 1101 1102 /** 1103 * @see AccountsPayableDocumentBase#isAttachmentRequired() 1104 */ 1105 @Override 1106 protected boolean isAttachmentRequired() { 1107 if (getInvoiceElectronicInvoiceIndicator()) { 1108 return false; 1109 } 1110 return StringUtils.equalsIgnoreCase("Y", SpringContext.getBean(OleInvoiceService.class).getParameter(OLEConstants.OptionalModuleNamespaces.PURCHASING_ACCOUNTS_PAYABLE, OLEConstants.InvoiceDocument.CMPNT_CD,PurapParameterConstants.PURAP_PRQS_REQUIRE_ATTACHMENT)); 1111 } 1112 1113 /** 1114 * @see AccountsPayableDocument#getDocumentSpecificService() 1115 */ 1116 @Override 1117 public AccountsPayableDocumentSpecificService getDocumentSpecificService() { 1118 return SpringContext.getBean(InvoiceService.class); 1119 } 1120 1121 /** 1122 * @see PurchasingAccountsPayableDocumentBase#getItem(int) 1123 */ 1124 @Override 1125 public PurApItem getItem(int pos) { 1126 InvoiceItem item = (InvoiceItem) super.getItem(pos); 1127 if (item.getInvoice() == null) { 1128 item.setInvoice(this); 1129 } 1130 return item; 1131 } 1132 1133 public String getPrimaryVendorName() { 1134 1135 if (primaryVendorName == null) { 1136 VendorDetail vd = SpringContext.getBean(VendorService.class).getVendorDetail(this.getOriginalVendorHeaderGeneratedIdentifier(), this.getOriginalVendorDetailAssignedIdentifier()); 1137 1138 if (vd != null) { 1139 primaryVendorName = vd.getVendorName(); 1140 } 1141 } 1142 1143 return primaryVendorName; 1144 } 1145 1146 /** 1147 * @deprecated 1148 */ 1149 @Deprecated 1150 public void setPrimaryVendorName(String primaryVendorName) { 1151 } 1152 1153 /** 1154 * Forces general ledger entries to be approved, does not wait for payment request document final approval. 1155 * 1156 * @see org.kuali.module.purap.rules.PurapAccountingDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.ole.sys.document.AccountingDocument, 1157 * org.kuali.ole.sys.businessobject.AccountingLine, org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry) 1158 */ 1159 @Override 1160 public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) { 1161 super.customizeExplicitGeneralLedgerPendingEntry(postable, explicitEntry); 1162 1163 SpringContext.getBean(PurapGeneralLedgerService.class).customizeGeneralLedgerPendingEntry(this, (AccountingLine) postable, explicitEntry, getPurchaseOrderIdentifier(), getDebitCreditCodeForGLEntries(), PurapDocTypeCodes.INVOICE_DOCUMENT, isGenerateEncumbranceEntries()); 1164 1165 // PRQSs do not wait for document final approval to post GL entries; here we are forcing them to be APPROVED 1166 explicitEntry.setFinancialDocumentApprovedCode(OLEConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.APPROVED); 1167 } 1168 1169 /** 1170 * Provides answers to the following splits: PurchaseWasReceived VendorIsEmployeeOrNonResidentAlien 1171 * 1172 * @see org.kuali.ole.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(String) 1173 */ 1174 @Override 1175 public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException { 1176 if (nodeName.equals(PurapWorkflowConstants.REQUIRES_IMAGE_ATTACHMENT)) { 1177 return requiresAccountsPayableReviewRouting(); 1178 } 1179 if (nodeName.equals(PurapWorkflowConstants.PURCHASE_WAS_RECEIVED)) { 1180 return shouldWaitForReceiving(); 1181 } 1182 if (nodeName.equals(PurapWorkflowConstants.VENDOR_IS_EMPLOYEE_OR_NON_RESIDENT_ALIEN)) { 1183 return isVendorEmployeeOrNonResidentAlien(); 1184 } 1185 throw new UnsupportedOperationException("Cannot answer split question for this node you call \"" + nodeName + "\""); 1186 } 1187 1188 protected boolean isVendorEmployeeOrNonResidentAlien() { 1189 String vendorHeaderGeneratedId = this.getVendorHeaderGeneratedIdentifier().toString(); 1190 if (StringUtils.isBlank(vendorHeaderGeneratedId)) { 1191 // no vendor header id so can't check for proper tax routing 1192 return false; 1193 } 1194 VendorService vendorService = SpringContext.getBean(VendorService.class); 1195 boolean routeDocumentAsEmployeeVendor = vendorService.isVendorInstitutionEmployee(Integer.valueOf(vendorHeaderGeneratedId)); 1196 boolean routeDocumentAsForeignVendor = vendorService.isVendorForeign(Integer.valueOf(vendorHeaderGeneratedId)); 1197 if ((!routeDocumentAsEmployeeVendor) && (!routeDocumentAsForeignVendor)) { 1198 // no need to route 1199 return false; 1200 } 1201 1202 return true; 1203 } 1204 1205 /** 1206 * Payment Request needs to wait for receiving if the receiving requirements have NOT been met. 1207 * 1208 * @return 1209 */ 1210 protected boolean shouldWaitForReceiving() { 1211 // only require if PO was marked to require receiving 1212 if (isReceivingDocumentRequiredIndicator()) { 1213 return !isReceivingRequirementMet(); 1214 } 1215 1216 //receiving is not required or has already been fulfilled, no need to stop for routing 1217 return false; 1218 } 1219 1220 /** 1221 * Determine if the receiving requirement has been met for all items on the payment request. If any item does not have receiving 1222 * requirements met, return false. Receiving requirement has NOT been met if the quantity invoiced on the Payment Request is 1223 * greater than the quantity of "unpaid and received" items determined by (poQtyReceived - (poQtyInvoiced)). 1224 * 1225 * @return boolean return true if the receiving requirement has been met for all items on the payment request; false if 1226 * requirement has not been met 1227 */ 1228 public boolean isReceivingRequirementMet() { 1229 1230 for (Iterator iter = getItems().iterator(); iter.hasNext(); ) { 1231 InvoiceItem prqsItem = (InvoiceItem) iter.next(); 1232 1233 if (prqsItem.getItemType().isQuantityBasedGeneralLedgerIndicator()) { 1234 PurchaseOrderItem poItem = prqsItem.getPurchaseOrderItem(); 1235 KualiDecimal prqsQuantityInvoiced = prqsItem.getItemQuantity() == null ? KualiDecimal.ZERO : prqsItem.getItemQuantity(); 1236 KualiDecimal poQuantityReceived = poItem.getItemReceivedTotalQuantity() == null ? KualiDecimal.ZERO : poItem.getItemReceivedTotalQuantity(); 1237 KualiDecimal poQuantityInvoiced = poItem.getItemInvoicedTotalQuantity() == null ? KualiDecimal.ZERO : poItem.getItemInvoicedTotalQuantity(); 1238 1239 // receiving has NOT been met if prqsQtyInvoiced is greater than (poQtyReceived & (poQtyInvoiced & prqsQtyInvoiced)) 1240 if (prqsQuantityInvoiced.compareTo(poQuantityReceived.subtract(poQuantityInvoiced)) > 0) { 1241 return false; 1242 } 1243 } 1244 } 1245 1246 return true; 1247 } 1248 1249 @Override 1250 public Date getTransactionTaxDate() { 1251 return getInvoiceDate(); 1252 } 1253 1254 public String getTaxClassificationCode() { 1255 return taxClassificationCode; 1256 } 1257 1258 public void setTaxClassificationCode(String taxClassificationCode) { 1259 this.taxClassificationCode = taxClassificationCode; 1260 } 1261 1262 public KualiDecimal getTaxFederalPercentShort() { 1263 return new KualiDecimal(taxFederalPercent); 1264 } 1265 1266 public BigDecimal getTaxFederalPercent() { 1267 return taxFederalPercent; 1268 } 1269 1270 public void setTaxFederalPercent(BigDecimal taxFederalPercent) { 1271 this.taxFederalPercent = taxFederalPercent; 1272 } 1273 1274 public KualiDecimal getTaxStatePercentShort() { 1275 return new KualiDecimal(taxStatePercent); 1276 } 1277 1278 public BigDecimal getTaxStatePercent() { 1279 return taxStatePercent; 1280 } 1281 1282 public void setTaxStatePercent(BigDecimal taxStatePercent) { 1283 this.taxStatePercent = taxStatePercent; 1284 } 1285 1286 public String getTaxCountryCode() { 1287 return taxCountryCode; 1288 } 1289 1290 public void setTaxCountryCode(String taxCountryCode) { 1291 this.taxCountryCode = taxCountryCode; 1292 } 1293 1294 public Boolean getTaxGrossUpIndicator() { 1295 return taxGrossUpIndicator; 1296 } 1297 1298 public void setTaxGrossUpIndicator(Boolean taxGrossUpIndicator) { 1299 this.taxGrossUpIndicator = taxGrossUpIndicator; 1300 } 1301 1302 public Boolean getTaxExemptTreatyIndicator() { 1303 return taxExemptTreatyIndicator; 1304 } 1305 1306 public void setTaxExemptTreatyIndicator(Boolean taxExemptTreatyIndicator) { 1307 this.taxExemptTreatyIndicator = taxExemptTreatyIndicator; 1308 } 1309 1310 public Boolean getTaxForeignSourceIndicator() { 1311 return taxForeignSourceIndicator; 1312 } 1313 1314 public void setTaxForeignSourceIndicator(Boolean taxForeignSourceIndicator) { 1315 this.taxForeignSourceIndicator = taxForeignSourceIndicator; 1316 } 1317 1318 public KualiDecimal getTaxSpecialW4Amount() { 1319 return taxSpecialW4Amount; 1320 } 1321 1322 public void setTaxSpecialW4Amount(KualiDecimal taxSpecialW4Amount) { 1323 this.taxSpecialW4Amount = taxSpecialW4Amount; 1324 } 1325 1326 public Boolean getTaxUSAIDPerDiemIndicator() { 1327 return taxUSAIDPerDiemIndicator; 1328 } 1329 1330 public void setTaxUSAIDPerDiemIndicator(Boolean taxUSAIDPerDiemIndicator) { 1331 this.taxUSAIDPerDiemIndicator = taxUSAIDPerDiemIndicator; 1332 } 1333 1334 public Boolean getTaxOtherExemptIndicator() { 1335 return taxOtherExemptIndicator; 1336 } 1337 1338 public void setTaxOtherExemptIndicator(Boolean taxOtherExemptIndicator) { 1339 this.taxOtherExemptIndicator = taxOtherExemptIndicator; 1340 } 1341 1342 public String getTaxNQIId() { 1343 return taxNQIId; 1344 } 1345 1346 public void setTaxNQIId(String taxNQIId) { 1347 this.taxNQIId = taxNQIId; 1348 } 1349 1350 public boolean isInvoiceCancelIndicatorForSearching() { 1351 return invoiceCancelIndicator; 1352 } 1353 1354 /** 1355 * @return the payment request positive approval indicator 1356 */ 1357 public boolean getInvoicePositiveApprovalIndicatorForSearching() { 1358 return invoicePositiveApprovalIndicator; 1359 } 1360 1361 /** 1362 * @return the receiving document required indicator 1363 */ 1364 public boolean getReceivingDocumentRequiredIndicatorForSearching() { 1365 return receivingDocumentRequiredIndicator; 1366 } 1367 1368 1369 public String getRequestCancelIndicatorForResult() { 1370 return isInvoiceCancelIndicator() ? "Yes" : "No"; 1371 } 1372 1373 public String getPaidIndicatorForResult() { 1374 return getPaymentPaidTimestamp() != null ? "Yes" : "No"; 1375 } 1376 1377 public Date getAccountsPayableApprovalDateForSearching() { 1378 if (this.getAccountsPayableApprovalTimestamp() == null) { 1379 return null; 1380 } 1381 try { 1382 Date date = SpringContext.getBean(DateTimeService.class).convertToSqlDate(this.getAccountsPayableApprovalTimestamp()); 1383 if (LOG.isDebugEnabled()) { 1384 LOG.debug("getAccountsPayableApprovalDateForSearching() returns " + date); 1385 } 1386 return date; 1387 } catch (Exception e) { 1388 return new Date(this.getAccountsPayableApprovalTimestamp().getTime()); 1389 } 1390 } 1391 1392 /** 1393 * Checks all documents notes for attachments. 1394 * 1395 * @return - true if document does not have an image attached, false otherwise 1396 */ 1397 @Override 1398 public boolean documentHasNoImagesAttached() { 1399 List boNotes = this.getNotes(); 1400 if (ObjectUtils.isNotNull(boNotes)) { 1401 for (Object obj : boNotes) { 1402 Note note = (Note) obj; 1403 1404 note.refreshReferenceObject("attachment"); 1405 if (ObjectUtils.isNotNull(note.getAttachment()) && PurapConstants.AttachmentTypeCodes.ATTACHMENT_TYPE_INVOICE_IMAGE.equals(note.getAttachment().getAttachmentTypeCode())) { 1406 return false; 1407 } 1408 } 1409 } 1410 return true; 1411 } 1412 1413 protected void closePurchaseOrder() { 1414 //Added for jira OLE-3529 Starts 1415 Integer poIdentifier = purchaseOrderDocument.getPurapDocumentIdentifier(); 1416 String docNumber = purchaseOrderDocument.getDocumentNumber(); 1417 Map purchaseOrderMap = new HashMap(); 1418 purchaseOrderMap.put("documentNumber", docNumber); 1419 purchaseOrderMap.put("itemTypeCode", OLEConstants.ITEM); 1420 KualiDecimal itemQuantity = new KualiDecimal(0); 1421 KualiDecimal itemOrderQuantity = new KualiDecimal(0); 1422 List<OlePurchaseOrderItem> olePurchaseOrderItemList = (List<OlePurchaseOrderItem>) getBusinessObjectService().findMatching(OlePurchaseOrderItem.class, purchaseOrderMap); 1423 for (OlePurchaseOrderItem olePurchaseOrderItem : olePurchaseOrderItemList) { 1424 itemQuantity = itemQuantity.add(olePurchaseOrderItem.getItemQuantity()); 1425 } 1426 Map lineItemReceivingMap = new HashMap(); 1427 lineItemReceivingMap.put("purchaseOrderIdentifier", poIdentifier); 1428 List<OleLineItemReceivingDocument> oleLineItemReceivingDocumentList = (List<OleLineItemReceivingDocument>) getBusinessObjectService().findMatching(OleLineItemReceivingDocument.class, lineItemReceivingMap); 1429 for (OleLineItemReceivingDocument oleLineItemReceivingDocument : oleLineItemReceivingDocumentList) { 1430 String docId = oleLineItemReceivingDocument.getDocumentNumber(); 1431 Map docIdMap = new HashMap(); 1432 docIdMap.put("documentNumber", docId); 1433 List<OleLineItemReceivingItem> oleLineItemReceivingItemList = (List<OleLineItemReceivingItem>) getBusinessObjectService().findMatching(OleLineItemReceivingItem.class, docIdMap); 1434 for (OleLineItemReceivingItem oleLineItemReceivingItem : oleLineItemReceivingItemList) { 1435 itemOrderQuantity = itemOrderQuantity.add(oleLineItemReceivingItem.getItemOrderedQuantity()); 1436 } 1437 if (itemQuantity.equals(itemOrderQuantity)) { 1438 try { 1439 this.setDocumentHeader(purchaseOrderDocument.getDocumentHeader()); 1440 updateAndSaveAppDocStatus(PurapConstants.PurchaseOrderStatuses.APPDOC_CLOSED); 1441 } catch (WorkflowException e) { 1442 logAndThrowRuntimeException("Error while Closing the PO from Payment Request " 1443 + getDocumentNumber(), e); 1444 } 1445 } 1446 } 1447 //End 1448 } 1449 1450 /** 1451 * @see AccountsPayableDocument#getPurchaseOrderDocument() 1452 */ 1453 @Override 1454 public PurchaseOrderDocument getPurchaseOrderDocument() { 1455 if ((ObjectUtils.isNull(purchaseOrderDocument) || ObjectUtils.isNull(purchaseOrderDocument.getPurapDocumentIdentifier())) && (ObjectUtils.isNotNull(getPurchaseOrderIdentifier()))) { 1456 Map map = new HashMap(); 1457 map.put("purapDocumentIdentifier",this.getPurchaseOrderIdentifier()); 1458 List<OlePurchaseOrderDocument> purchaseOrderDocumentList = (List<OlePurchaseOrderDocument>)getBusinessObjectService().findMatching(OlePurchaseOrderDocument.class,map); 1459 if(purchaseOrderDocumentList!=null && purchaseOrderDocumentList.size()>0){ 1460 setPurchaseOrderDocument(purchaseOrderDocumentList.get(0)); 1461 } 1462 } 1463 return purchaseOrderDocument; 1464 } 1465 1466 /** 1467 * @see AccountsPayableDocument#getPurchaseOrderDocument() 1468 */ 1469 1470 public PurchaseOrderDocument getPurchaseOrderDocument(Integer poID) { 1471 if (ObjectUtils.isNull(purchaseOrderDocument) || ObjectUtils.isNull(purchaseOrderDocument.getPurapDocumentIdentifier())) { 1472 // && (ObjectUtils.isNotNull(getPurchaseOrderIdentifier()))) { 1473 Map map = new HashMap(); 1474 map.put("purapDocumentIdentifier",poID); 1475 List<OlePurchaseOrderDocument> purchaseOrderDocumentList = (List<OlePurchaseOrderDocument>)getBusinessObjectService().findMatching(OlePurchaseOrderDocument.class,map); 1476 if(purchaseOrderDocumentList!=null && purchaseOrderDocumentList.size()>0){ 1477 setPurchaseOrderDocument(purchaseOrderDocumentList.get(0)); 1478 } 1479 // setPurchaseOrderDocument(SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(poID)); 1480 } 1481 return purchaseOrderDocument; 1482 } 1483 1484 1485 /* private InvoiceService getInvoiceService() { 1486 if (invoiceService == null ) { 1487 invoiceService = SpringContext.getBean(OleInvoiceService.class); 1488 } 1489 return invoiceService; 1490 } 1491*/ 1492 1493}