/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.module.purap.document;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.module.purap.PurapConstants;
import org.kuali.kfs.module.purap.PurapConstants.PaymentRequestStatuses;
import org.kuali.kfs.module.purap.PurapConstants.PurapDocTypeCodes;
import org.kuali.kfs.module.purap.PurapParameterConstants;
import org.kuali.kfs.module.purap.PurapPropertyConstants;
import org.kuali.kfs.module.purap.PurapWorkflowConstants;
import org.kuali.kfs.module.purap.businessobject.ItemType;
import org.kuali.kfs.module.purap.businessobject.PaymentRequestItem;
import org.kuali.kfs.module.purap.businessobject.PaymentRequestItemUseTax;
import org.kuali.kfs.module.purap.businessobject.PurApAccountingLine;
import org.kuali.kfs.module.purap.businessobject.PurApItem;
import org.kuali.kfs.module.purap.businessobject.PurchaseOrderItem;
import org.kuali.kfs.module.purap.businessobject.PurchasingCapitalAssetItem;
import org.kuali.kfs.module.purap.businessobject.RecurringPaymentType;
import org.kuali.kfs.module.purap.document.service.AccountsPayableDocumentSpecificService;
import org.kuali.kfs.module.purap.document.service.AccountsPayableService;
import org.kuali.kfs.module.purap.document.service.PaymentRequestService;
import org.kuali.kfs.module.purap.document.service.PurapService;
import org.kuali.kfs.module.purap.document.validation.event.AttributedContinuePurapEvent;
import org.kuali.kfs.module.purap.service.PurapGeneralLedgerService;
import org.kuali.kfs.module.purap.util.ExpiredOrClosedAccountEntry;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.businessobject.AccountingLine;
import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.service.UniversityDateService;
import org.kuali.kfs.sys.service.impl.KfsParameterConstants;
import org.kuali.kfs.vnd.VendorConstants;
import org.kuali.kfs.vnd.VendorPropertyConstants;
import org.kuali.kfs.vnd.businessobject.PaymentTermType;
import org.kuali.kfs.vnd.businessobject.PurchaseOrderCostSource;
import org.kuali.kfs.vnd.businessobject.ShippingPaymentTerms;
import org.kuali.kfs.vnd.businessobject.VendorAddress;
import org.kuali.kfs.vnd.businessobject.VendorDetail;
import org.kuali.kfs.vnd.document.service.VendorService;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.kuali.rice.coreservice.framework.parameter.ParameterService;
import org.kuali.rice.kew.api.WorkflowDocument;
import org.kuali.rice.kew.api.exception.WorkflowException;
import org.kuali.rice.kew.framework.postprocessor.ActionTakenEvent;
import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
import org.kuali.rice.kim.api.identity.Person;
import org.kuali.rice.kns.service.DataDictionaryService;
import org.kuali.rice.krad.bo.Note;
import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.ObjectUtils;
import org.kuali.rice.krad.workflow.service.WorkflowDocumentService;
/**
* Payment Request Document Business Object. Contains the fields associated with the main document table.
*/
public class PaymentRequestDocument extends AccountsPayableDocumentBase {
protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PaymentRequestDocument.class);
protected Date invoiceDate;
protected String invoiceNumber;
protected KualiDecimal vendorInvoiceAmount;
protected String vendorPaymentTermsCode;
protected String vendorShippingPaymentTermsCode;
protected Date paymentRequestPayDate;
protected String paymentRequestCostSourceCode;
protected boolean paymentRequestedCancelIndicator;
protected boolean paymentAttachmentIndicator;
protected boolean immediatePaymentIndicator;
protected String specialHandlingInstructionLine1Text;
protected String specialHandlingInstructionLine2Text;
protected String specialHandlingInstructionLine3Text;
protected Timestamp paymentPaidTimestamp;
protected boolean paymentRequestElectronicInvoiceIndicator;
protected String accountsPayableRequestCancelIdentifier;
protected Integer originalVendorHeaderGeneratedIdentifier;
protected Integer originalVendorDetailAssignedIdentifier;
protected Integer alternateVendorHeaderGeneratedIdentifier;
protected Integer alternateVendorDetailAssignedIdentifier;
protected String purchaseOrderNotes;
protected String recurringPaymentTypeCode;
protected boolean receivingDocumentRequiredIndicator;
protected boolean paymentRequestPositiveApprovalIndicator;
//KFSCNTRB-1207 - UMD - Muddu -- start
//the indicator which tells if the preq has been auto approved and this value will be used
//by the doRouteStatus method to change the app doc status.
protected boolean autoApprovedIndicator;
//KFSCNTRB-1207 - UMD - Muddu -- end
// TAX EDIT AREA FIELDS
protected String taxClassificationCode;
protected String taxCountryCode;
protected String taxNQIId;
protected BigDecimal taxFederalPercent; // number is in whole form so 5% is 5.00
protected BigDecimal taxStatePercent; // number is in whole form so 5% is 5.00
protected KualiDecimal taxSpecialW4Amount;
protected Boolean taxGrossUpIndicator;
protected Boolean taxExemptTreatyIndicator;
protected Boolean taxForeignSourceIndicator;
protected Boolean taxUSAIDPerDiemIndicator;
protected Boolean taxOtherExemptIndicator;
protected String justification;
// NOT PERSISTED IN DB
protected String vendorShippingTitleCode;
protected Date purchaseOrderEndDate;
protected String primaryVendorName;
// BELOW USED BY ROUTING
protected Integer requisitionIdentifier;
// REFERENCE OBJECTS
protected PaymentTermType vendorPaymentTerms;
protected ShippingPaymentTerms vendorShippingPaymentTerms;
protected PurchaseOrderCostSource paymentRequestCostSource;
protected RecurringPaymentType recurringPaymentType;
/**
* Default constructor.
*/
public PaymentRequestDocument() {
super();
//KFSCNTRB-12207 - UMD - Muddu
this.setAutoApprovedIndicator(false);
}
/**
* @see org.kuali.rice.krad.bo.PersistableBusinessObjectBase#isBoNotesSupport()
*/
public boolean isBoNotesSupport() {
return true;
}
public Integer getPostingYearPriorOrCurrent() {
if (SpringContext.getBean(PaymentRequestService.class).allowBackpost(this)) {
// allow prior; use it
return SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear() - 1;
}
// don't allow prior; use CURRENT
return SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear();
}
/**
* Overrides the method in PurchasingAccountsPayableDocumentBase to add the criteria specific to Payment Request Document.
*
* @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocumentBase#isInquiryRendered()
*/
@Override
public boolean isInquiryRendered() {
if (isPostingYearPrior() && (getApplicationDocumentStatus().equals(PurapConstants.PaymentRequestStatuses.APPDOC_DEPARTMENT_APPROVED) || getApplicationDocumentStatus().equals(PurapConstants.PaymentRequestStatuses.APPDOC_AUTO_APPROVED) || getApplicationDocumentStatus().equals(PurapConstants.PaymentRequestStatuses.APPDOC_CANCELLED_POST_AP_APPROVE) || getApplicationDocumentStatus().equals(PurapConstants.PaymentRequestStatuses.APPDOC_CANCELLED_IN_PROCESS))) {
return false;
}
else {
return true;
}
}
public Integer getRequisitionIdentifier() {
return getPurchaseOrderDocument().getRequisitionIdentifier();
}
public void setRequisitionIdentifier(Integer requisitionIdentifier) {
this.requisitionIdentifier = requisitionIdentifier;
}
/**
* @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#populateDocumentForRouting()
*/
@Override
public void populateDocumentForRouting() {
this.setRequisitionIdentifier(getPurchaseOrderDocument().getRequisitionIdentifier());
super.populateDocumentForRouting();
}
/**
* Decides whether receivingDocumentRequiredIndicator functionality shall be enabled according to the controlling parameter.
*/
public boolean isEnableReceivingDocumentRequiredIndicator() {
return SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.RECEIVING_DOCUMENT_REQUIRED_IND);
}
/**
* Decides whether paymentRequestPositiveApprovalIndicator functionality shall be enabled according to the controlling parameter.
*/
public boolean isEnablePaymentRequestPositiveApprovalIndicator() {
return SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.PAYMENT_REQUEST_POSITIVE_APPROVAL_IND);
}
public Date getInvoiceDate() {
return invoiceDate;
}
public void setInvoiceDate(Date invoiceDate) {
this.invoiceDate = invoiceDate;
}
public String getInvoiceNumber() {
return invoiceNumber;
}
public void setInvoiceNumber(String invoiceNumber) {
if (!StringUtils.isEmpty(invoiceNumber)) {
this.invoiceNumber = invoiceNumber.toUpperCase();
}
else {
this.invoiceNumber = invoiceNumber;
}
}
public KualiDecimal getVendorInvoiceAmount() {
return vendorInvoiceAmount;
}
public void setVendorInvoiceAmount(KualiDecimal vendorInvoiceAmount) {
this.vendorInvoiceAmount = vendorInvoiceAmount;
}
public String getVendorPaymentTermsCode() {
return vendorPaymentTermsCode;
}
public void setVendorPaymentTermsCode(String vendorPaymentTermsCode) {
this.vendorPaymentTermsCode = vendorPaymentTermsCode;
refreshReferenceObject("vendorPaymentTerms");
}
public PaymentTermType getVendorPaymentTerms() {
if (ObjectUtils.isNull(vendorPaymentTerms) || !StringUtils.equalsIgnoreCase(getVendorPaymentTermsCode(), vendorPaymentTerms.getVendorPaymentTermsCode())) {
refreshReferenceObject(VendorPropertyConstants.VENDOR_PAYMENT_TERMS);
}
return vendorPaymentTerms;
}
public void setVendorPaymentTerms(PaymentTermType vendorPaymentTerms) {
this.vendorPaymentTerms = vendorPaymentTerms;
}
public String getVendorShippingPaymentTermsCode() {
if (ObjectUtils.isNull(vendorPaymentTerms)) {
refreshReferenceObject(VendorPropertyConstants.VENDOR_SHIPPING_PAYMENT_TERMS);
}
return vendorShippingPaymentTermsCode;
}
public void setVendorShippingPaymentTermsCode(String vendorShippingPaymentTermsCode) {
this.vendorShippingPaymentTermsCode = vendorShippingPaymentTermsCode;
}
public Date getPaymentRequestPayDate() {
return paymentRequestPayDate;
}
public void setPaymentRequestPayDate(Date paymentRequestPayDate) {
this.paymentRequestPayDate = paymentRequestPayDate;
}
public String getPaymentRequestCostSourceCode() {
return paymentRequestCostSourceCode;
}
public void setPaymentRequestCostSourceCode(String paymentRequestCostSourceCode) {
this.paymentRequestCostSourceCode = paymentRequestCostSourceCode;
}
public boolean getPaymentRequestedCancelIndicator() {
return paymentRequestedCancelIndicator;
}
public boolean isPaymentRequestedCancelIndicator() {
return paymentRequestedCancelIndicator;
}
public void setPaymentRequestedCancelIndicator(boolean paymentRequestedCancelIndicator) {
this.paymentRequestedCancelIndicator = paymentRequestedCancelIndicator;
}
public boolean getPaymentAttachmentIndicator() {
return paymentAttachmentIndicator;
}
public void setPaymentAttachmentIndicator(boolean paymentAttachmentIndicator) {
this.paymentAttachmentIndicator = paymentAttachmentIndicator;
}
public boolean getImmediatePaymentIndicator() {
return immediatePaymentIndicator;
}
public void setImmediatePaymentIndicator(boolean immediatePaymentIndicator) {
this.immediatePaymentIndicator = immediatePaymentIndicator;
}
public String getSpecialHandlingInstructionLine1Text() {
return specialHandlingInstructionLine1Text;
}
public void setSpecialHandlingInstructionLine1Text(String specialHandlingInstructionLine1Text) {
this.specialHandlingInstructionLine1Text = specialHandlingInstructionLine1Text;
}
public String getSpecialHandlingInstructionLine2Text() {
return specialHandlingInstructionLine2Text;
}
public void setSpecialHandlingInstructionLine2Text(String specialHandlingInstructionLine2Text) {
this.specialHandlingInstructionLine2Text = specialHandlingInstructionLine2Text;
}
public String getSpecialHandlingInstructionLine3Text() {
return specialHandlingInstructionLine3Text;
}
public void setSpecialHandlingInstructionLine3Text(String specialHandlingInstructionLine3Text) {
this.specialHandlingInstructionLine3Text = specialHandlingInstructionLine3Text;
}
public Timestamp getPaymentPaidTimestamp() {
return paymentPaidTimestamp;
}
public void setPaymentPaidTimestamp(Timestamp paymentPaidTimestamp) {
this.paymentPaidTimestamp = paymentPaidTimestamp;
}
public boolean getPaymentRequestElectronicInvoiceIndicator() {
return paymentRequestElectronicInvoiceIndicator;
}
public void setPaymentRequestElectronicInvoiceIndicator(boolean paymentRequestElectronicInvoiceIndicator) {
this.paymentRequestElectronicInvoiceIndicator = paymentRequestElectronicInvoiceIndicator;
}
public String getAccountsPayableRequestCancelIdentifier() {
return accountsPayableRequestCancelIdentifier;
}
public void setAccountsPayableRequestCancelIdentifier(String accountsPayableRequestCancelIdentifier) {
this.accountsPayableRequestCancelIdentifier = accountsPayableRequestCancelIdentifier;
}
public Integer getOriginalVendorHeaderGeneratedIdentifier() {
return originalVendorHeaderGeneratedIdentifier;
}
public void setOriginalVendorHeaderGeneratedIdentifier(Integer originalVendorHeaderGeneratedIdentifier) {
this.originalVendorHeaderGeneratedIdentifier = originalVendorHeaderGeneratedIdentifier;
}
public Integer getOriginalVendorDetailAssignedIdentifier() {
return originalVendorDetailAssignedIdentifier;
}
public void setOriginalVendorDetailAssignedIdentifier(Integer originalVendorDetailAssignedIdentifier) {
this.originalVendorDetailAssignedIdentifier = originalVendorDetailAssignedIdentifier;
}
public Integer getAlternateVendorHeaderGeneratedIdentifier() {
return alternateVendorHeaderGeneratedIdentifier;
}
public void setAlternateVendorHeaderGeneratedIdentifier(Integer alternateVendorHeaderGeneratedIdentifier) {
this.alternateVendorHeaderGeneratedIdentifier = alternateVendorHeaderGeneratedIdentifier;
}
public Integer getAlternateVendorDetailAssignedIdentifier() {
return alternateVendorDetailAssignedIdentifier;
}
public void setAlternateVendorDetailAssignedIdentifier(Integer alternateVendorDetailAssignedIdentifier) {
this.alternateVendorDetailAssignedIdentifier = alternateVendorDetailAssignedIdentifier;
}
public ShippingPaymentTerms getVendorShippingPaymentTerms() {
return vendorShippingPaymentTerms;
}
public void setVendorShippingPaymentTerms(ShippingPaymentTerms vendorShippingPaymentTerms) {
this.vendorShippingPaymentTerms = vendorShippingPaymentTerms;
}
public String getVendorShippingTitleCode() {
if (ObjectUtils.isNotNull(this.getPurchaseOrderDocument())) {
return this.getPurchaseOrderDocument().getVendorShippingTitleCode();
}
return vendorShippingTitleCode;
}
public void setVendorShippingTitleCode(String vendorShippingTitleCode) {
this.vendorShippingTitleCode = vendorShippingTitleCode;
}
public Date getPurchaseOrderEndDate() {
return purchaseOrderEndDate;
}
public void setPurchaseOrderEndDate(Date purchaseOrderEndDate) {
this.purchaseOrderEndDate = purchaseOrderEndDate;
}
/**
* Gets the paymentRequestPositiveApprovalIndicator attribute.
*
* @return Returns the paymentRequestPositiveApprovalIndicator.
*/
public boolean isPaymentRequestPositiveApprovalIndicator() {
return paymentRequestPositiveApprovalIndicator;
}
/**
* Sets the paymentRequestPositiveApprovalIndicator attribute value.
*
* @param paymentRequestPositiveApprovalIndicator The paymentRequestPositiveApprovalIndicator to set.
*/
public void setPaymentRequestPositiveApprovalIndicator(boolean paymentRequestPositiveApprovalIndicator) {
// if paymentRequestPositiveApprovalIndicator functionality is disabled, always set it to false, overriding the passed-in value
if (!isEnablePaymentRequestPositiveApprovalIndicator()) {
paymentRequestPositiveApprovalIndicator = false;
}
else {
this.paymentRequestPositiveApprovalIndicator = paymentRequestPositiveApprovalIndicator;
}
}
/**
* Gets the receivingDocumentRequiredIndicator attribute.
*
* @return Returns the receivingDocumentRequiredIndicator.
*/
public boolean isReceivingDocumentRequiredIndicator() {
return receivingDocumentRequiredIndicator;
}
/**
* Sets the receivingDocumentRequiredIndicator attribute value.
*
* @param receivingDocumentRequiredIndicator The receivingDocumentRequiredIndicator to set.
*/
public void setReceivingDocumentRequiredIndicator(boolean receivingDocumentRequiredIndicator) {
// if receivingDocumentRequiredIndicator functionality is disabled, always set it to false, overriding the passed-in value
if (!isEnableReceivingDocumentRequiredIndicator()) {
receivingDocumentRequiredIndicator = false;
}
else {
this.receivingDocumentRequiredIndicator = receivingDocumentRequiredIndicator;
}
}
/**
* Perform logic needed to initiate PREQ Document
*/
public void initiateDocument() throws WorkflowException {
LOG.debug("initiateDocument() started");
Person currentUser = GlobalVariables.getUserSession().getPerson();
updateAndSaveAppDocStatus(PurapConstants.PaymentRequestStatuses.APPDOC_INITIATE);
this.setAccountsPayableProcessorIdentifier(currentUser.getPrincipalId());
this.setProcessingCampusCode(currentUser.getCampusCode());
this.refreshNonUpdateableReferences();
}
/**
* Perform logic needed to clear the initial fields on a PREQ Document
*/
public void clearInitFields() {
LOG.debug("clearDocument() started");
// Clearing document overview fields
this.getDocumentHeader().setDocumentDescription(null);
this.getDocumentHeader().setExplanation(null);
this.getFinancialSystemDocumentHeader().setFinancialDocumentTotalAmount(null);
this.getDocumentHeader().setOrganizationDocumentNumber(null);
// Clearing document Init fields
this.setPurchaseOrderIdentifier(null);
this.setInvoiceNumber(null);
this.setInvoiceDate(null);
this.setVendorInvoiceAmount(null);
this.setSpecialHandlingInstructionLine1Text(null);
this.setSpecialHandlingInstructionLine2Text(null);
this.setSpecialHandlingInstructionLine3Text(null);
}
/**
* Populates a preq from a PO - delegate method
*
* @param po -
*/
public void populatePaymentRequestFromPurchaseOrder(PurchaseOrderDocument po) {
populatePaymentRequestFromPurchaseOrder(po, new HashMap<String, ExpiredOrClosedAccountEntry>());
}
/**
* Populates a preq from a PO
*
* @param po Purchase Order Document used for populating the PREQ
* @param expiredOrClosedAccountList a list of closed or expired accounts
*/
public void populatePaymentRequestFromPurchaseOrder(PurchaseOrderDocument po, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
this.setPurchaseOrderIdentifier(po.getPurapDocumentIdentifier());
this.getDocumentHeader().setOrganizationDocumentNumber(po.getDocumentHeader().getOrganizationDocumentNumber());
this.setPostingYear(po.getPostingYear());
this.setReceivingDocumentRequiredIndicator(po.isReceivingDocumentRequiredIndicator());
this.setUseTaxIndicator(po.isUseTaxIndicator());
this.setPaymentRequestPositiveApprovalIndicator(po.isPaymentRequestPositiveApprovalIndicator());
this.setVendorCustomerNumber(po.getVendorCustomerNumber());
this.setAccountDistributionMethod(po.getAccountDistributionMethod());
if (po.getPurchaseOrderCostSource() != null) {
this.setPaymentRequestCostSource(po.getPurchaseOrderCostSource());
this.setPaymentRequestCostSourceCode(po.getPurchaseOrderCostSourceCode());
}
if (po.getVendorShippingPaymentTerms() != null) {
this.setVendorShippingPaymentTerms(po.getVendorShippingPaymentTerms());
this.setVendorShippingPaymentTermsCode(po.getVendorShippingPaymentTermsCode());
}
if (po.getVendorPaymentTerms() != null) {
this.setVendorPaymentTermsCode(po.getVendorPaymentTermsCode());
this.setVendorPaymentTerms(po.getVendorPaymentTerms());
}
if (po.getRecurringPaymentType() != null) {
this.setRecurringPaymentType(po.getRecurringPaymentType());
this.setRecurringPaymentTypeCode(po.getRecurringPaymentTypeCode());
}
this.setVendorHeaderGeneratedIdentifier(po.getVendorHeaderGeneratedIdentifier());
this.setVendorDetailAssignedIdentifier(po.getVendorDetailAssignedIdentifier());
this.setVendorCustomerNumber(po.getVendorCustomerNumber());
this.setVendorName(po.getVendorName());
// set original vendor
this.setOriginalVendorHeaderGeneratedIdentifier(po.getVendorHeaderGeneratedIdentifier());
this.setOriginalVendorDetailAssignedIdentifier(po.getVendorDetailAssignedIdentifier());
// set alternate vendor info as well
this.setAlternateVendorHeaderGeneratedIdentifier(po.getAlternateVendorHeaderGeneratedIdentifier());
this.setAlternateVendorDetailAssignedIdentifier(po.getAlternateVendorDetailAssignedIdentifier());
// populate preq vendor address with the default remit address type for the vendor if found
String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode();
VendorAddress vendorAddress = SpringContext.getBean(VendorService.class).getVendorDefaultAddress(po.getVendorHeaderGeneratedIdentifier(), po.getVendorDetailAssignedIdentifier(), VendorConstants.AddressTypes.REMIT, userCampus);
if (vendorAddress != null) {
this.templateVendorAddress(vendorAddress);
this.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier());
setVendorAttentionName(StringUtils.defaultString(vendorAddress.getVendorAttentionName()));
}
else {
// set address from PO
this.setVendorAddressGeneratedIdentifier(po.getVendorAddressGeneratedIdentifier());
this.setVendorLine1Address(po.getVendorLine1Address());
this.setVendorLine2Address(po.getVendorLine2Address());
this.setVendorCityName(po.getVendorCityName());
this.setVendorAddressInternationalProvinceName(po.getVendorAddressInternationalProvinceName());
this.setVendorStateCode(po.getVendorStateCode());
this.setVendorPostalCode(po.getVendorPostalCode());
this.setVendorCountryCode(po.getVendorCountryCode());
boolean blankAttentionLine = StringUtils.equalsIgnoreCase("Y", SpringContext.getBean(ParameterService.class).getParameterValueAsString(PurapConstants.PURAP_NAMESPACE, "Document", PurapParameterConstants.BLANK_ATTENTION_LINE_FOR_PO_TYPE_ADDRESS));
if (blankAttentionLine) {
setVendorAttentionName(StringUtils.EMPTY);
}
else {
setVendorAttentionName(StringUtils.defaultString(po.getVendorAttentionName()));
}
}
this.setPaymentRequestPayDate(SpringContext.getBean(PaymentRequestService.class).calculatePayDate(this.getInvoiceDate(), this.getVendorPaymentTerms()));
AccountsPayableService accountsPayableService = SpringContext.getBean(AccountsPayableService.class);
if(SpringContext.getBean(PaymentRequestService.class).encumberedItemExistsForInvoicing(po))
{
for (PurchaseOrderItem poi : (List<PurchaseOrderItem>) po.getItems()) {
// check to make sure it's eligible for payment (i.e. active and has encumbrance available
if (getDocumentSpecificService().poItemEligibleForAp(this, poi)) {
PaymentRequestItem paymentRequestItem = new PaymentRequestItem(poi, this, expiredOrClosedAccountList);
this.getItems().add(paymentRequestItem);
PurchasingCapitalAssetItem purchasingCAMSItem = po.getPurchasingCapitalAssetItemByItemIdentifier(poi.getItemIdentifier());
if (purchasingCAMSItem != null) {
paymentRequestItem.setCapitalAssetTransactionTypeCode(purchasingCAMSItem.getCapitalAssetTransactionTypeCode());
}
/*
// copy usetaxitems over
paymentRequestItem.getUseTaxItems().clear();
for (PurApItemUseTax useTax : poi.getUseTaxItems()) {
paymentRequestItem.getUseTaxItems().add(useTax);
}
*/
}
}
}
// add missing below the line
SpringContext.getBean(PurapService.class).addBelowLineItems(this);
this.setAccountsPayablePurchasingDocumentLinkIdentifier(po.getAccountsPayablePurchasingDocumentLinkIdentifier());
//fix up below the line items
SpringContext.getBean(PaymentRequestService.class).removeIneligibleAdditionalCharges(this);
this.fixItemReferences();
this.refreshNonUpdateableReferences();
}
/**
* @see org.kuali.rice.krad.document.DocumentBase#getDocumentTitle()
*/
@Override
public String getDocumentTitle() {
if (SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(PaymentRequestDocument.class, PurapParameterConstants.PURAP_OVERRIDE_PREQ_DOC_TITLE)) {
return getCustomDocumentTitle();
}
return this.buildDocumentTitle(super.getDocumentTitle());
}
/**
* Returns a custom document title based on the workflow document title. Depending on what route level the document is currently
* in, the PO, vendor, amount, account number, dept, campus may be added to the documents title.
*
* @return - Customized document title text dependent upon route level.
*/
protected String getCustomDocumentTitle() {
// set the workflow document title
String poNumber = getPurchaseOrderIdentifier().toString();
String vendorName = StringUtils.trimToEmpty(getVendorName());
String preqAmount = getGrandTotal().toString();
String documentTitle = "";
Set<String> nodeNames = this.getFinancialSystemDocumentHeader().getWorkflowDocument().getCurrentNodeNames();
// if this doc is final or will be final
if (CollectionUtils.isEmpty(nodeNames) || this.getFinancialSystemDocumentHeader().getWorkflowDocument().isFinal()) {
documentTitle = (new StringBuilder("PO: ")).append(poNumber).append(" Vendor: ").append(vendorName).append(" Amount: ").append(preqAmount).toString();
}
else {
PurApAccountingLine theAccount = getFirstAccount();
String accountNumber = (theAccount != null ? StringUtils.trimToEmpty(theAccount.getAccountNumber()) : "n/a");
String subAccountNumber = (theAccount != null ? StringUtils.trimToEmpty(theAccount.getSubAccountNumber()) : "");
String accountChart = (theAccount != null ? theAccount.getChartOfAccountsCode() : "");
String payDate = getDateTimeService().toDateString(getPaymentRequestPayDate());
String indicator = getTitleIndicator();
// set title to: PO# - VendorName - Chart/Account - total amt - Pay Date - Indicator (ie Hold, Request Cancel)
documentTitle = (new StringBuilder("PO: ")).append(poNumber).append(" Vendor: ").append(vendorName).
append(" Account: ").append(accountChart).append(" ").append(accountNumber).append(" ").append(subAccountNumber)
.append(" Amount: ").append(preqAmount).append(" Pay Date: ").append(payDate).append(" ").append(indicator).toString();
}
return documentTitle;
}
/**
* Returns the first payment item's first account (assuming the item list is sequentially ordered).
*
* @return - Accounting Line object for first account of first payment item.
*/
public PurApAccountingLine getFirstAccount() {
// loop through items, and pick the first item
if ((getItems() != null) && (!getItems().isEmpty())) {
PaymentRequestItem itemToUse = null;
for (Iterator iter = getItems().iterator(); iter.hasNext();) {
PaymentRequestItem item = (PaymentRequestItem) iter.next();
if ((item.isConsideredEntered()) && ((item.getSourceAccountingLines() != null) && (!item.getSourceAccountingLines().isEmpty()))) {
// accounting lines are not empty so pick the first account
PurApAccountingLine accountLine = item.getSourceAccountingLine(0);
accountLine.refreshNonUpdateableReferences();
return accountLine;
}
/*
if (((item.getExtendedPrice() != null) && item.getExtendedPrice().compareTo(BigDecimal.ZERO) > 0) && ((item.getAccounts() != null) && (!item.getAccounts().isEmpty()))) {
// accounting lines are not empty so pick the first account
List accts = (List)item.getAccounts();
PaymentRequestAccount accountLine = (PaymentRequestAccount)accts.get(0);
return accountLine.getFinancialChartOfAccountsCode() + "-" + accountLine.getAccountNumber();
}
*/
}
}
return null;
}
/**
* Determines the indicator text that will appear in the workflow document title
*
* @return - Text of hold or request cancel
*/
protected String getTitleIndicator() {
if (isHoldIndicator()) {
return PurapConstants.PaymentRequestIndicatorText.HOLD;
}
else if (isPaymentRequestedCancelIndicator()) {
return PurapConstants.PaymentRequestIndicatorText.REQUEST_CANCEL;
}
return "";
}
/**
* @see org.kuali.rice.krad.document.DocumentBase#doRouteStatusChange()
*/
@Override
public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) {
LOG.debug("doRouteStatusChange() started");
super.doRouteStatusChange(statusChangeEvent);
try{
//KFSCNTRB-1207 - UMD - Muddu -- start
// if the document was processed but approved by the auto approve payment request job
// then all we want to do is to change the application document status to auto-approved
// by looking at the autoApprovedIndicator on the preq.
// DOCUEMNT PROCESSED BY THE AUTOAPPROVEPAYMENTREQUEST JOB...
if (this.isAutoApprovedIndicator()) {
updateAndSaveAppDocStatus(PurapConstants.PaymentRequestStatuses.APPDOC_AUTO_APPROVED);
} // DOCUMENT PROCESSED .. //KFSCNTRB-1207 - UMD - Muddu -- end
else if (this.getFinancialSystemDocumentHeader().getWorkflowDocument().isProcessed()) {
if (!PaymentRequestStatuses.APPDOC_AUTO_APPROVED.equals(getApplicationDocumentStatus())) {
populateDocumentForRouting();
updateAndSaveAppDocStatus(PurapConstants.PaymentRequestStatuses.APPDOC_DEPARTMENT_APPROVED);
}
}
// DOCUMENT DISAPPROVED
else if (this.getFinancialSystemDocumentHeader().getWorkflowDocument().isDisapproved()) {
String nodeName = SpringContext.getBean(WorkflowDocumentService.class).getCurrentRouteLevelName(getDocumentHeader().getWorkflowDocument());
String disapprovalStatus = PurapConstants.PaymentRequestStatuses.getPaymentRequestAppDocDisapproveStatuses().get(nodeName);
if (ObjectUtils.isNotNull(nodeName)) {
if (((StringUtils.isBlank(disapprovalStatus)) && ((PaymentRequestStatuses.APPDOC_INITIATE.equals(getApplicationDocumentStatus())) || (PaymentRequestStatuses.APPDOC_IN_PROCESS.equals(getApplicationDocumentStatus()))))) {
disapprovalStatus = PaymentRequestStatuses.APPDOC_CANCELLED_IN_PROCESS;
}
if (StringUtils.isNotBlank(disapprovalStatus)) {
SpringContext.getBean(AccountsPayableService.class).cancelAccountsPayableDocument(this, nodeName);
}
}
else {
logAndThrowRuntimeException("No status found to set for document being disapproved in node '" + nodeName + "'");
}
}
// DOCUMENT CANCELED
else if (this.getFinancialSystemDocumentHeader().getWorkflowDocument().isCanceled()) {
String currentNodeName = SpringContext.getBean(WorkflowDocumentService.class).getCurrentRouteLevelName(this.getDocumentHeader().getWorkflowDocument());
String cancelledStatus = PurapConstants.PaymentRequestStatuses.getPaymentRequestAppDocDisapproveStatuses().get(currentNodeName);
//**START AZ** KATTS-37 KevinMcO
if (StringUtils.isBlank(cancelledStatus) &&
StringUtils.isBlank(PurapConstants.PaymentRequestStatuses.getPaymentRequestAppDocDisapproveStatuses().get(currentNodeName)) &&
(PaymentRequestStatuses.APPDOC_INITIATE.equals(getApplicationDocumentStatus()) || PaymentRequestStatuses.APPDOC_IN_PROCESS.equals(getApplicationDocumentStatus()))) {
cancelledStatus = PaymentRequestStatuses.APPDOC_CANCELLED_IN_PROCESS;
}
//**END AZ**
if (ObjectUtils.isNotNull(cancelledStatus)) {
SpringContext.getBean(AccountsPayableService.class).cancelAccountsPayableDocument(this, currentNodeName);
updateAndSaveAppDocStatus(cancelledStatus);
}
else {
logAndThrowRuntimeException("No status found to set for document being canceled in node '" + currentNodeName + "'");
}
}
}
catch (WorkflowException e) {
logAndThrowRuntimeException("Error saving routing data while saving document with id " + getDocumentNumber(), e);
}
}
/**
* Generates correcting entries to the GL if accounts are modified.
*
* @see org.kuali.rice.krad.document.Document#doActionTaken(org.kuali.rice.kew.clientapp.vo.ActionTakenEventDTO)
*/
@Override
public void doActionTaken(ActionTakenEvent event) {
super.doActionTaken(event);
WorkflowDocument workflowDocument = getDocumentHeader().getWorkflowDocument();
String currentNode = null;
Set<String> currentNodes = workflowDocument.getCurrentNodeNames();
if (CollectionUtils.isNotEmpty(currentNodes)) {
Object[] names = currentNodes.toArray();
if (names.length > 0) {
currentNode = (String)names[0];
}
}
// everything in the below list requires correcting entries to be written to the GL
if (PaymentRequestStatuses.getNodesRequiringCorrectingGeneralLedgerEntries().contains(currentNode)) {
SpringContext.getBean(PurapGeneralLedgerService.class).generateEntriesModifyPaymentRequest(this);
}
}
/**
* @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#processNodeChange(java.lang.String, java.lang.String)
*/
@Override
public boolean processNodeChange(String newNodeName, String oldNodeName) {
if (PaymentRequestStatuses.APPDOC_AUTO_APPROVED.equals(getApplicationDocumentStatus())) {
// do nothing for an auto approval
return false;
}
if (PaymentRequestStatuses.NODE_ADHOC_REVIEW.equals(oldNodeName)) {
SpringContext.getBean(AccountsPayableService.class).performLogicForFullEntryCompleted(this);
}
return true;
}
/**
* @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#saveDocumentFromPostProcessing()
*/
@Override
public void saveDocumentFromPostProcessing() {
SpringContext.getBean(PurapService.class).saveDocumentNoValidation(this);
// if we've hit full entry completed then close/reopen po
if (SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(this) && this.isClosePurchaseOrderIndicator()) {
SpringContext.getBean(PurapService.class).performLogicForCloseReopenPO(this);
}
}
/**
* @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocumentBase#getItemClass()
*/
@Override
public Class getItemClass() {
return PaymentRequestItem.class;
}
@Override
public Class getItemUseTaxClass() {
return PaymentRequestItemUseTax.class;
}
/**
* @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocumentBase#getPurApSourceDocumentIfPossible()
*/
@Override
public PurchaseOrderDocument getPurApSourceDocumentIfPossible() {
return getPurchaseOrderDocument();
}
/**
* @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocumentBase#getPurApSourceDocumentLabelIfPossible()
*/
@Override
public String getPurApSourceDocumentLabelIfPossible() {
return SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByTypeName(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER);
}
public String getPurchaseOrderNotes() {
ArrayList poNotes = (ArrayList) this.getPurchaseOrderDocument().getNotes();
if (poNotes.size() > 0) {
return "Yes";
}
return "No";
}
public void setPurchaseOrderNotes(String purchaseOrderNotes) {
this.purchaseOrderNotes = purchaseOrderNotes;
}
public String getRecurringPaymentTypeCode() {
return recurringPaymentTypeCode;
}
public void setRecurringPaymentTypeCode(String recurringPaymentTypeCode) {
this.recurringPaymentTypeCode = recurringPaymentTypeCode;
}
/**
* Returns the total encumbered amount from the purchase order excluding below the line.
*
* @return Total cost excluding below the line
*/
public KualiDecimal getItemTotalPoEncumbranceAmount() {
// get total from po excluding below the line and inactive
return this.getPurchaseOrderDocument().getTotalDollarAmount(false, false);
}
public KualiDecimal getItemTotalPoEncumbranceAmountRelieved() {
return getItemTotalPoEncumbranceAmountRelieved(false);
}
public KualiDecimal getItemTotalPoEncumbranceAmountRelieved(boolean includeBelowTheLine) {
KualiDecimal total = KualiDecimal.ZERO;
for (PurchaseOrderItem item : (List<PurchaseOrderItem>) getPurchaseOrderDocument().getItems()) {
ItemType it = item.getItemType();
if (includeBelowTheLine || it.isLineItemIndicator()) {
total = total.add(item.getItemEncumbranceRelievedAmount());
}
}
return total;
}
public KualiDecimal getLineItemTotal() {
return this.getTotalDollarAmountAboveLineItems();
}
public KualiDecimal getLineItemPreTaxTotal() {
return this.getTotalPreTaxDollarAmountAboveLineItems();
}
public KualiDecimal getLineItemTaxAmount() {
return this.getTotalTaxAmountAboveLineItems();
}
@Override
public KualiDecimal getGrandTotal() {
return this.getTotalDollarAmount();
}
public KualiDecimal getGrandTotalExcludingDiscount() {
String[] discountCode = new String[] { PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE };
return this.getTotalDollarAmountWithExclusions(discountCode, true);
}
/**
* This method is here due to a setter requirement by the htmlControlAttribute
*
* @param amount - Grand total for document, excluding discount
*/
public void setGrandTotalExcludingDiscount(KualiDecimal amount) {
// do nothing
}
public KualiDecimal getGrandPreTaxTotal() {
return this.getTotalPreTaxDollarAmount();
}
public KualiDecimal getGrandPreTaxTotalExcludingDiscount() {
String[] discountCode = new String[] { PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE };
return this.getTotalPreTaxDollarAmountWithExclusions(discountCode, true);
}
public KualiDecimal getGrandTaxAmount() {
return this.getTotalTaxAmount();
}
public KualiDecimal getGrandTaxAmountExcludingDiscount() {
String[] discountCode = new String[] { PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE };
return this.getTotalTaxAmountWithExclusions(discountCode, true);
}
public boolean isDiscount() {
return SpringContext.getBean(PaymentRequestService.class).hasDiscountItem(this);
}
/**
* The total that was paid on the po excluding below the line
*
* @return total paid
*/
public KualiDecimal getItemTotalPoPaidAmount() {
KualiDecimal total = KualiDecimal.ZERO;
for (PurchaseOrderItem item : (List<PurchaseOrderItem>) getPurchaseOrderDocument().getItems()) {
ItemType iT = item.getItemType();
if (iT.isLineItemIndicator()) {
KualiDecimal itemPaid = item.getItemPaidAmount();
total = total.add(itemPaid);
}
}
return total;
}
/**
* Returns the name of who requested cancel.
*
* @return - name of who requested cancel.
*/
public String getAccountsPayableRequestCancelPersonName() {
String personName = null;
Person user = SpringContext.getBean(org.kuali.rice.kim.api.identity.PersonService.class).getPerson(getAccountsPayableRequestCancelIdentifier());
if (user != null) {
personName = user.getName();
}
else {
personName = "";
}
return personName;
}
/**
* Exists due to a setter requirement by the htmlControlAttribute
*
* @param amount - total po amount paid
*/
public void setItemTotalPoPaidAmount(KualiDecimal amount) {
// do nothing
}
/**
* Exists due to a setter requirement by the htmlControlAttribute
*
* @param amount - total po encumbrance
*/
public void setItemTotalPoEncumbranceAmount(KualiDecimal amount) {
// do nothing
}
/**
* Exists due to a setter requirement by the htmlControlAttribute
*
* @param amount - total po encumbrance amount relieved
*/
public void setItemTotalPoEncumbranceAmountRelieved(KualiDecimal amount) {
// do nothing
}
/**
* Determinines the route levels for a given document.
*
* @param workflowDocument - work flow document
* @return List - list of route levels
*/
protected List<String> getCurrentRouteLevels(WorkflowDocument workflowDocument) {
Set<String> names = workflowDocument.getCurrentNodeNames();
if (CollectionUtils.isNotEmpty(names)) {
return new ArrayList<String>(names);
}
return null;
}
public RecurringPaymentType getRecurringPaymentType() {
if (ObjectUtils.isNull(recurringPaymentType)) {
refreshReferenceObject(PurapPropertyConstants.RECURRING_PAYMENT_TYPE);
}
return recurringPaymentType;
}
public void setRecurringPaymentType(RecurringPaymentType recurringPaymentType) {
this.recurringPaymentType = recurringPaymentType;
}
public PurchaseOrderCostSource getPaymentRequestCostSource() {
return paymentRequestCostSource;
}
public void setPaymentRequestCostSource(PurchaseOrderCostSource paymentRequestCostSource) {
this.paymentRequestCostSource = paymentRequestCostSource;
}
/**
* @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#getPoDocumentTypeForAccountsPayableDocumentApprove()
*/
@Override
public String getPoDocumentTypeForAccountsPayableDocumentCancel() {
return PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_REOPEN_DOCUMENT;
}
/**
* @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#getInitialAmount()
*/
@Override
public KualiDecimal getInitialAmount() {
return this.getVendorInvoiceAmount();
}
/**
* Populates the payment request document, then continues with preparing for save.
*
* @see org.kuali.rice.krad.document.Document#prepareForSave(org.kuali.rice.krad.rule.event.KualiDocumentEvent)
*/
@Override
public void prepareForSave(KualiDocumentEvent event) {
WorkflowDocument workflowDocument = this.getDocumentHeader().getWorkflowDocument();
String workflowDocumentTitle = this.buildDocumentTitle(workflowDocument.getTitle());
this.getFinancialSystemDocumentHeader().getWorkflowDocument().setTitle(workflowDocumentTitle);
// first populate, then call super
if (event instanceof AttributedContinuePurapEvent) {
SpringContext.getBean(PaymentRequestService.class).populatePaymentRequest(this);
}
super.prepareForSave(event);
}
/**
* @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#isAttachmentRequired()
*/
@Override
protected boolean isAttachmentRequired() {
if (getPaymentRequestElectronicInvoiceIndicator()) {
return false;
}
return StringUtils.equalsIgnoreCase("Y", SpringContext.getBean(ParameterService.class).getParameterValueAsString(PaymentRequestDocument.class, PurapParameterConstants.PURAP_PREQ_REQUIRE_ATTACHMENT));
}
/**
* @see org.kuali.kfs.module.purap.document.AccountsPayableDocument#getDocumentSpecificService()
*/
@Override
public AccountsPayableDocumentSpecificService getDocumentSpecificService() {
return SpringContext.getBean(PaymentRequestService.class);
}
/**
* @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocumentBase#getItem(int)
*/
@Override
public PurApItem getItem(int pos) {
PaymentRequestItem item = (PaymentRequestItem) super.getItem(pos);
if (item.getPaymentRequest() == null) {
item.setPaymentRequest(this);
}
return item;
}
public String getPrimaryVendorName() {
if (primaryVendorName == null) {
VendorDetail vd = SpringContext.getBean(VendorService.class).getVendorDetail(this.getOriginalVendorHeaderGeneratedIdentifier(), this.getOriginalVendorDetailAssignedIdentifier());
if (vd != null) {
primaryVendorName = vd.getVendorName();
}
}
return primaryVendorName;
}
/**
* @deprecated
*/
@Deprecated
public void setPrimaryVendorName(String primaryVendorName) {
}
/**
* Forces general ledger entries to be approved, does not wait for payment request document final approval.
*
* @see org.kuali.module.purap.rules.PurapAccountingDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.kfs.sys.document.AccountingDocument,
* org.kuali.kfs.sys.businessobject.AccountingLine, org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry)
*/
@Override
public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) {
super.customizeExplicitGeneralLedgerPendingEntry(postable, explicitEntry);
SpringContext.getBean(PurapGeneralLedgerService.class).customizeGeneralLedgerPendingEntry(this, (AccountingLine) postable, explicitEntry, getPurchaseOrderIdentifier(), getDebitCreditCodeForGLEntries(), PurapDocTypeCodes.PAYMENT_REQUEST_DOCUMENT, isGenerateEncumbranceEntries());
// PREQs do not wait for document final approval to post GL entries; here we are forcing them to be APPROVED
explicitEntry.setFinancialDocumentApprovedCode(KFSConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.APPROVED);
}
/**
* Provides answers to the following splits: PurchaseWasReceived VendorIsEmployeeOrNonResidentAlien
*
* @see org.kuali.kfs.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String)
*/
@Override
public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
if (nodeName.equals(PurapWorkflowConstants.REQUIRES_IMAGE_ATTACHMENT)) {
return requiresAccountsPayableReviewRouting();
}
if (nodeName.equals(PurapWorkflowConstants.PURCHASE_WAS_RECEIVED)) {
return shouldWaitForReceiving();
}
if (nodeName.equals(PurapWorkflowConstants.VENDOR_IS_EMPLOYEE_OR_NON_RESIDENT_ALIEN)) {
return isVendorEmployeeOrNonResidentAlien();
}
if (nodeName.equals(PurapWorkflowConstants.IS_DOCUMENT_AUTO_APPROVED)) {
return isAutoApprovedIndicator();
}
throw new UnsupportedOperationException("Cannot answer split question for this node you call \"" + nodeName + "\"");
}
protected boolean isVendorEmployeeOrNonResidentAlien() {
String vendorHeaderGeneratedId = this.getVendorHeaderGeneratedIdentifier().toString();
if (StringUtils.isBlank(vendorHeaderGeneratedId)) {
// no vendor header id so can't check for proper tax routing
return false;
}
VendorService vendorService = SpringContext.getBean(VendorService.class);
boolean routeDocumentAsEmployeeVendor = vendorService.isVendorInstitutionEmployee(Integer.valueOf(vendorHeaderGeneratedId));
boolean routeDocumentAsForeignVendor = vendorService.isVendorForeign(Integer.valueOf(vendorHeaderGeneratedId));
if ((!routeDocumentAsEmployeeVendor) && (!routeDocumentAsForeignVendor)) {
// no need to route
return false;
}
return true;
}
/**
* Payment Request needs to wait for receiving if the receiving requirements have NOT been met.
*
* @return
*/
protected boolean shouldWaitForReceiving() {
// only require if PO was marked to require receiving
if (isReceivingDocumentRequiredIndicator()) {
return !isReceivingRequirementMet();
}
//receiving is not required or has already been fulfilled, no need to stop for routing
return false;
}
/**
* Determine if the receiving requirement has been met for all items on the payment request. If any item does not have receiving
* requirements met, return false. Receiving requirement has NOT been met if the quantity invoiced on the Payment Request is
* greater than the quantity of "unpaid and received" items determined by (poQtyReceived - (poQtyInvoiced - preqQtyInvoiced)).
* We have to subtract preqQtyInvoiced from the poQtyInvoiced because this payment request has already updated the totals on the
* po.
*
* @return boolean return true if the receiving requirement has been met for all items on the payment request; false if
* requirement has not been met
*/
public boolean isReceivingRequirementMet() {
for (Iterator iter = getItems().iterator(); iter.hasNext();) {
PaymentRequestItem preqItem = (PaymentRequestItem) iter.next();
if (preqItem.getItemType().isQuantityBasedGeneralLedgerIndicator()) {
PurchaseOrderItem poItem = preqItem.getPurchaseOrderItem();
KualiDecimal preqQuantityInvoiced = preqItem.getItemQuantity() == null ? KualiDecimal.ZERO : preqItem.getItemQuantity();
KualiDecimal poQuantityReceived = poItem.getItemReceivedTotalQuantity() == null ? KualiDecimal.ZERO : poItem.getItemReceivedTotalQuantity();
KualiDecimal poQuantityInvoiced = poItem.getItemInvoicedTotalQuantity() == null ? KualiDecimal.ZERO : poItem.getItemInvoicedTotalQuantity();
// receiving has NOT been met if preqQtyInvoiced is greater than (poQtyReceived & (poQtyInvoiced & preqQtyInvoiced))
if (preqQuantityInvoiced.compareTo(poQuantityReceived.subtract(poQuantityInvoiced.subtract(preqQuantityInvoiced))) > 0) {
return false;
}
}
}
return true;
}
@Override
public Date getTransactionTaxDate() {
return getInvoiceDate();
}
public String getTaxClassificationCode() {
return taxClassificationCode;
}
public void setTaxClassificationCode(String taxClassificationCode) {
this.taxClassificationCode = taxClassificationCode;
}
public KualiDecimal getTaxFederalPercentShort() {
return new KualiDecimal(taxFederalPercent);
}
public BigDecimal getTaxFederalPercent() {
return taxFederalPercent;
}
public void setTaxFederalPercent(BigDecimal taxFederalPercent) {
this.taxFederalPercent = taxFederalPercent;
}
public KualiDecimal getTaxStatePercentShort() {
return new KualiDecimal(taxStatePercent);
}
public BigDecimal getTaxStatePercent() {
return taxStatePercent;
}
public void setTaxStatePercent(BigDecimal taxStatePercent) {
this.taxStatePercent = taxStatePercent;
}
public String getTaxCountryCode() {
return taxCountryCode;
}
public void setTaxCountryCode(String taxCountryCode) {
this.taxCountryCode = taxCountryCode;
}
public Boolean getTaxGrossUpIndicator() {
return taxGrossUpIndicator;
}
public void setTaxGrossUpIndicator(Boolean taxGrossUpIndicator) {
this.taxGrossUpIndicator = taxGrossUpIndicator;
}
public Boolean getTaxExemptTreatyIndicator() {
return taxExemptTreatyIndicator;
}
public void setTaxExemptTreatyIndicator(Boolean taxExemptTreatyIndicator) {
this.taxExemptTreatyIndicator = taxExemptTreatyIndicator;
}
public Boolean getTaxForeignSourceIndicator() {
return taxForeignSourceIndicator;
}
public void setTaxForeignSourceIndicator(Boolean taxForeignSourceIndicator) {
this.taxForeignSourceIndicator = taxForeignSourceIndicator;
}
public KualiDecimal getTaxSpecialW4Amount() {
return taxSpecialW4Amount;
}
public void setTaxSpecialW4Amount(KualiDecimal taxSpecialW4Amount) {
this.taxSpecialW4Amount = taxSpecialW4Amount;
}
public Boolean getTaxUSAIDPerDiemIndicator() {
return taxUSAIDPerDiemIndicator;
}
public void setTaxUSAIDPerDiemIndicator(Boolean taxUSAIDPerDiemIndicator) {
this.taxUSAIDPerDiemIndicator = taxUSAIDPerDiemIndicator;
}
public Boolean getTaxOtherExemptIndicator() {
return taxOtherExemptIndicator;
}
public void setTaxOtherExemptIndicator(Boolean taxOtherExemptIndicator) {
this.taxOtherExemptIndicator = taxOtherExemptIndicator;
}
public String getTaxNQIId() {
return taxNQIId;
}
public void setTaxNQIId(String taxNQIId) {
this.taxNQIId = taxNQIId;
}
public boolean isPaymentRequestedCancelIndicatorForSearching() {
return paymentRequestedCancelIndicator;
}
/**
* @return the payment request positive approval indicator
*/
public boolean getPaymentRequestPositiveApprovalIndicatorForSearching() {
return paymentRequestPositiveApprovalIndicator;
}
/**
* @return the receiving document required indicator
*/
public boolean getReceivingDocumentRequiredIndicatorForSearching() {
return receivingDocumentRequiredIndicator;
}
public String getRequestCancelIndicatorForResult() {
return isPaymentRequestedCancelIndicator() ? "Yes" : "No";
}
public String getPaidIndicatorForResult() {
return getPaymentPaidTimestamp() != null ? "Yes" : "No";
}
public Date getAccountsPayableApprovalDateForSearching() {
if (this.getAccountsPayableApprovalTimestamp() == null) {
return null;
}
try {
Date date = SpringContext.getBean(DateTimeService.class).convertToSqlDate(this.getAccountsPayableApprovalTimestamp());
if (LOG.isDebugEnabled()) {
LOG.debug("getAccountsPayableApprovalDateForSearching() returns " + date);
}
return date;
}
catch (Exception e) {
return new Date(this.getAccountsPayableApprovalTimestamp().getTime());
}
}
/**
* Checks all documents notes for attachments.
*
* @return - true if document does not have an image attached, false otherwise
*/
@Override
public boolean documentHasNoImagesAttached() {
List boNotes = this.getNotes();
if (ObjectUtils.isNotNull(boNotes)) {
for (Object obj : boNotes) {
Note note = (Note) obj;
note.refreshReferenceObject("attachment");
if (ObjectUtils.isNotNull(note.getAttachment()) && PurapConstants.AttachmentTypeCodes.ATTACHMENT_TYPE_INVOICE_IMAGE.equals(note.getAttachment().getAttachmentTypeCode())) {
return false;
}
}
}
return true;
}
/**
* Gets the justification attribute.
* @return Returns the justification.
*/
public String getJustification() {
return justification;
}
/**
* Sets the justification attribute value.
* @param justification The justification to set.
*/
public void setJustification(String justification) {
this.justification = justification;
}
//KFSCNTRB-1207 - UMD - Muddu -- start
/**
* Gets the autoApprovedIndicator attribute.
*
* @return Returns the autoApprovedIndicator
*/
public boolean isAutoApprovedIndicator() {
return autoApprovedIndicator;
}
/**
* Sets the autoApprovedIndicator attribute.
*
* @param autoApprovedIndicator The autoApprovedIndicator to set.
*/
public void setAutoApprovedIndicator(boolean autoApprovedIndicator) {
this.autoApprovedIndicator = autoApprovedIndicator;
}
//KFSCNTRB-1207 - UMD - Muddu -- end
@Override
public void processAfterRetrieve() {
super.processAfterRetrieve();
// KFSMI-9022 : JHK : This is a bit of a hack, but it seems that the document header is not being loaded properly from
// within the post-processor and causes problems.
if ( ObjectUtils.isNull( getDocumentHeader() ) || StringUtils.isBlank( getDocumentHeader().getDocumentNumber() ) ) {
WorkflowDocument workflowDocument = null;
if ( getDocumentHeader().hasWorkflowDocument() ) {
workflowDocument = getDocumentHeader().getWorkflowDocument();
}
refreshReferenceObject(KFSPropertyConstants.DOCUMENT_HEADER);
if ( !ObjectUtils.isNull(getDocumentHeader()) ) {
getDocumentHeader().setWorkflowDocument(workflowDocument);
}
}
}
}