/*
* 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.ar.document;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.coa.businessobject.Account;
import org.kuali.kfs.coa.businessobject.ObjectCode;
import org.kuali.kfs.coa.businessobject.ObjectCodeCurrent;
import org.kuali.kfs.coa.businessobject.OffsetDefinition;
import org.kuali.kfs.coa.service.BalanceTypeService;
import org.kuali.kfs.coa.service.ObjectCodeService;
import org.kuali.kfs.coa.service.OffsetDefinitionService;
import org.kuali.kfs.module.ar.ArConstants;
import org.kuali.kfs.module.ar.businessobject.AccountsReceivableDocumentHeader;
import org.kuali.kfs.module.ar.businessobject.CashControlDetail;
import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail;
import org.kuali.kfs.module.ar.businessobject.InvoicePaidApplied;
import org.kuali.kfs.module.ar.businessobject.NonAppliedDistribution;
import org.kuali.kfs.module.ar.businessobject.NonAppliedHolding;
import org.kuali.kfs.module.ar.businessobject.NonInvoiced;
import org.kuali.kfs.module.ar.businessobject.NonInvoicedDistribution;
import org.kuali.kfs.module.ar.businessobject.ReceivableCustomerInvoiceDetail;
import org.kuali.kfs.module.ar.businessobject.SystemInformation;
import org.kuali.kfs.module.ar.document.service.AccountsReceivablePendingEntryService;
import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService;
import org.kuali.kfs.module.ar.document.service.NonAppliedHoldingService;
import org.kuali.kfs.module.ar.document.service.PaymentApplicationDocumentService;
import org.kuali.kfs.module.ar.document.service.SystemInformationService;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.businessobject.ChartOrgHolder;
import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.document.AmountTotaling;
import org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource;
import org.kuali.kfs.sys.document.GeneralLedgerPostingDocumentBase;
import org.kuali.kfs.sys.service.FinancialSystemUserService;
import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService;
import org.kuali.kfs.sys.service.UniversityDateService;
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.exception.WorkflowException;
import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
import org.kuali.rice.kim.api.identity.Person;
import org.kuali.rice.kim.api.identity.principal.Principal;
import org.kuali.rice.kim.api.services.KimApiServiceLocator;
import org.kuali.rice.kns.service.DataDictionaryService;
import org.kuali.rice.krad.document.Document;
import org.kuali.rice.krad.exception.ValidationException;
import org.kuali.rice.krad.rules.rule.event.BlanketApproveDocumentEvent;
import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent;
import org.kuali.rice.krad.rules.rule.event.RouteDocumentEvent;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.service.DocumentService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.ObjectUtils;
/**
* Payment Application Document.
*/
public class PaymentApplicationDocument extends GeneralLedgerPostingDocumentBase implements GeneralLedgerPendingEntrySource, AmountTotaling {
protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PaymentApplicationDocument.class);
protected static final String LAUNCHED_FROM_BATCH = "LaunchedBySystemUser";
protected String hiddenFieldForErrors;
protected List<InvoicePaidApplied> invoicePaidApplieds;
protected List<NonInvoiced> nonInvoiceds;
protected Collection<NonInvoicedDistribution> nonInvoicedDistributions;
protected Collection<NonAppliedDistribution> nonAppliedDistributions;
protected NonAppliedHolding nonAppliedHolding;
protected AccountsReceivableDocumentHeader accountsReceivableDocumentHeader;
protected String invoiceDocumentType;// this document type variable would help in differentiating Customer and CG Invoices
protected String letterOfCreditCreationType;// To categorize the CG Invoices based on Award LOC Type
protected Long proposalNumber;// For loc creation type = Award
protected String letterOfCreditFundGroupCode;// for loc creation type = LOC fund
protected String letterOfCreditFundCode;// for loc creation type = LOC fund group
protected transient PaymentApplicationDocumentService paymentApplicationDocumentService;
protected transient CashControlDetail cashControlDetail;
protected transient FinancialSystemUserService fsUserService;
protected transient CustomerInvoiceDocumentService invoiceDocService;
protected transient DocumentService docService;
protected transient NonAppliedHoldingService nonAppliedHoldingService;
protected transient BusinessObjectService boService;
private static volatile transient AccountsReceivablePendingEntryService accountsReceivablePendingEntryService;
// used for non-cash-control payapps
protected ArrayList<NonAppliedHolding> nonAppliedHoldingsForCustomer; // control docs for non-cash-control payapps
public PaymentApplicationDocument() {
super();
this.invoicePaidApplieds = new ArrayList<InvoicePaidApplied>();
this.nonInvoiceds = new ArrayList<NonInvoiced>();
this.nonInvoicedDistributions = new ArrayList<NonInvoicedDistribution>();
this.nonAppliedDistributions = new ArrayList<NonAppliedDistribution>();
this.nonAppliedHoldingsForCustomer = new ArrayList<NonAppliedHolding>();
}
/**
* Returns the PaymentMediumIdentifier on the associated CashControlDetail, if one exists, otherwise returns null.
*
* @return CustomerPaymentMediumIdentifier from the associated CashControlDetail if one exists, otherwise null.
*/
public String getPaymentNumber() {
return hasCashControlDetail() ? getCashControlDetail().getCustomerPaymentMediumIdentifier() : null;
}
/**
* @return
*/
public boolean hasCashControlDocument() {
return (getCashControlDocument() != null);
}
/**
* @return
* @throws WorkflowException
*/
public CashControlDocument getCashControlDocument() {
CashControlDetail cashControlDetail = getCashControlDetail();
if (ObjectUtils.isNull(cashControlDetail)) {
return null;
}
return cashControlDetail.getCashControlDocument();
}
/**
* @return
*/
public boolean hasCashControlDetail() {
return (null != getCashControlDetail());
}
/**
* @return
* @throws WorkflowException
*/
public CashControlDetail getCashControlDetail() {
if (cashControlDetail == null) {
cashControlDetail = getPaymentApplicationDocumentService().getCashControlDetailForPayAppDocNumber(getDocumentNumber());
}
return cashControlDetail;
}
/**
* @param cashControlDetail
*/
public void setCashControlDetail(CashControlDetail cashControlDetail) {
this.cashControlDetail = cashControlDetail;
}
/**
* This method calculates the total amount available to be applied on this document.
*
* @return The total from the cash control detail if this is a cash-control based payapp. Otherwise, it just returns the total
* available to be applied from previously unapplied holdings.
*/
public KualiDecimal getTotalFromControl() {
if (hasCashControlDetail()) {
return getCashControlDetail().getFinancialDocumentLineAmount();
}
else {
return getNonAppliedControlAvailableUnappliedAmount();
}
}
/**
* This method calculates the total amount available to be applied from previously unapplied funds for the associated customer.
*
* @return The total amount of previously NonApplied funds available to apply to invoices and other applications on this
* document.
*/
public KualiDecimal getNonAppliedControlAvailableUnappliedAmount() {
KualiDecimal amount = KualiDecimal.ZERO;
for (NonAppliedHolding nonAppliedHolding : nonAppliedHoldingsForCustomer) {
amount = amount.add(nonAppliedHolding.getAvailableUnappliedAmount());
}
return amount;
}
/**
* @return the sum of all invoice paid applieds.
*/
public KualiDecimal getSumOfInvoicePaidApplieds() {
KualiDecimal amount = KualiDecimal.ZERO;
for (InvoicePaidApplied payment : getInvoicePaidApplieds()) {
KualiDecimal invoiceItemAppliedAmount = payment.getInvoiceItemAppliedAmount();
if (null == invoiceItemAppliedAmount) {
invoiceItemAppliedAmount = KualiDecimal.ZERO;
}
amount = amount.add(invoiceItemAppliedAmount);
}
return amount;
}
/**
* @return the sum of all non-invoiced amounts
*/
public KualiDecimal getSumOfNonInvoiceds() {
KualiDecimal total = KualiDecimal.ZERO;
for (NonInvoiced payment : getNonInvoiceds()) {
total = total.add(payment.getFinancialDocumentLineAmount());
}
return total;
}
/**
* @return the sum of all non-invoiced distributions
*/
public KualiDecimal getSumOfNonInvoicedDistributions() {
KualiDecimal amount = KualiDecimal.ZERO;
for (NonInvoicedDistribution nonInvoicedDistribution : getNonInvoicedDistributions()) {
amount = amount.add(nonInvoicedDistribution.getFinancialDocumentLineAmount());
}
return amount;
}
/**
* @return the sum of all non-applied distributions
*/
public KualiDecimal getSumOfNonAppliedDistributions() {
KualiDecimal amount = KualiDecimal.ZERO;
for (NonAppliedDistribution nonAppliedDistribution : getNonAppliedDistributions()) {
amount = amount.add(nonAppliedDistribution.getFinancialDocumentLineAmount());
}
return amount;
}
/**
* @return the non-applied holding total.
*/
public KualiDecimal getNonAppliedHoldingAmount() {
if (ObjectUtils.isNull(getNonAppliedHolding())) {
return KualiDecimal.ZERO;
}
if (ObjectUtils.isNull(getNonAppliedHolding().getFinancialDocumentLineAmount())) {
return KualiDecimal.ZERO;
}
return getNonAppliedHolding().getFinancialDocumentLineAmount();
}
/**
* This method returns the total amount allocated against the cash control total.
*
* @return
*/
public KualiDecimal getTotalApplied() {
KualiDecimal amount = KualiDecimal.ZERO;
amount = amount.add(getSumOfInvoicePaidApplieds());
amount = amount.add(getSumOfNonInvoiceds());
amount = amount.add(getNonAppliedHoldingAmount());
return amount;
}
/**
* @see org.kuali.kfs.sys.document.AmountTotaling#getTotalDollarAmount()
*/
@Override
public KualiDecimal getTotalDollarAmount() {
return getTotalFromControl();
}
/**
* This method subtracts the sum of the invoice paid applieds, non-ar and
* unapplied totals from the outstanding amount received via the cash
* control document.
*
* NOTE this method is not useful for a non-cash control PayApp, as it
* doesnt have access to the control documents until it is saved. Use
* the same named method on the Form instead.
*
* @return
* @throws WorkflowException
*/
public KualiDecimal getUnallocatedBalance() {
KualiDecimal amount = getTotalFromControl();
amount = amount.subtract(getTotalApplied());
return amount;
}
/**
* @return
*/
public KualiDecimal getNonArTotal() {
KualiDecimal total = KualiDecimal.ZERO;
for (NonInvoiced item : getNonInvoiceds()) {
total = total.add(item.getFinancialDocumentLineAmount());
}
return total;
}
/**
* @return
*/
public boolean isFinal() {
return isApproved();
}
/**
* @return
*/
public boolean isApproved() {
return getDocumentHeader().getWorkflowDocument().isApproved();
}
/**
* This method is very specialized for a specific use. It retrieves the list of invoices that have been paid-applied by this
* PayApp document. It is only used to retrieve what invoices were applied to it, when the document is being viewed in Final
* state.
*
* @return
*/
public List<CustomerInvoiceDocument> getInvoicesPaidAgainst() {
List<CustomerInvoiceDocument> invoices = new ArrayList<CustomerInvoiceDocument>();
// short circuit if no paidapplieds available
if (invoicePaidApplieds == null || invoicePaidApplieds.isEmpty()) {
return invoices;
}
// get the list of invoice docnumbers from paidapplieds
List<String> invoiceDocNumbers = new ArrayList<String>();
for (InvoicePaidApplied paidApplied : invoicePaidApplieds) {
invoiceDocNumbers.add(paidApplied.getFinancialDocumentReferenceInvoiceNumber());
}
// attempt to retrieve all the invoices paid applied against
try {
for (Document doc : getDocService().getDocumentsByListOfDocumentHeaderIds(CustomerInvoiceDocument.class, invoiceDocNumbers)) {
invoices.add((CustomerInvoiceDocument) doc);
}
}
catch (WorkflowException e) {
throw new RuntimeException("A WorkflowException was thrown while trying to retrieve documents.", e);
}
return invoices;
}
/**
* This is a very specialized method, that is only intended to be used once the document is in a Final/Approved state. It
* retrieves the PaymentApplication documents that were used as a control source for this document, if any, or none, if none.
*
* @return
*/
public List<PaymentApplicationDocument> getPaymentApplicationDocumentsUsedAsControlDocuments() {
List<PaymentApplicationDocument> payApps = new ArrayList<PaymentApplicationDocument>();
// short circuit if no non-applied-distributions available
if ((nonAppliedDistributions == null || nonAppliedDistributions.isEmpty()) && (nonInvoicedDistributions == null || nonInvoicedDistributions.isEmpty())) {
return payApps;
}
// get the list of payapp docnumbers from non-applied-distributions
List<String> payAppDocNumbers = new ArrayList<String>();
for (NonAppliedDistribution nonAppliedDistribution : nonAppliedDistributions) {
if (!payAppDocNumbers.contains(nonAppliedDistribution.getReferenceFinancialDocumentNumber())) {
payAppDocNumbers.add(nonAppliedDistribution.getReferenceFinancialDocumentNumber());
}
}
// get the list of payapp docnumbers from non-applied-distributions
for (NonInvoicedDistribution nonInvoicedDistribution : nonInvoicedDistributions) {
if (!payAppDocNumbers.contains(nonInvoicedDistribution.getReferenceFinancialDocumentNumber())) {
payAppDocNumbers.add(nonInvoicedDistribution.getReferenceFinancialDocumentNumber());
}
}
// exit out if no results, dont even try to retrieve
if (payAppDocNumbers.isEmpty()) {
return payApps;
}
// attempt to retrieve all the invoices paid applied against
try {
for (Document doc : getDocService().getDocumentsByListOfDocumentHeaderIds(PaymentApplicationDocument.class, payAppDocNumbers)) {
payApps.add((PaymentApplicationDocument) doc);
}
}
catch (WorkflowException e) {
throw new RuntimeException("A WorkflowException was thrown while trying to retrieve documents.", e);
}
return payApps;
}
/**
* @return
*/
public List<NonAppliedHolding> getNonAppliedHoldingsUsedAsControls() {
List<NonAppliedHolding> nonAppliedHoldingControls = new ArrayList<NonAppliedHolding>();
// short circuit if no non-applied-distributions available
if ((nonAppliedDistributions == null || nonAppliedDistributions.isEmpty()) && (nonInvoicedDistributions == null || nonInvoicedDistributions.isEmpty())) {
return nonAppliedHoldingControls;
}
// get the list of payapp docnumbers from non-applied-distributions
List<String> payAppDocNumbers = new ArrayList<String>();
for (NonAppliedDistribution nonAppliedDistribution : nonAppliedDistributions) {
if (!payAppDocNumbers.contains(nonAppliedDistribution.getReferenceFinancialDocumentNumber())) {
payAppDocNumbers.add(nonAppliedDistribution.getReferenceFinancialDocumentNumber());
}
}
// get the list of non-invoiced/non-ar distro payapp doc numbers
for (NonInvoicedDistribution nonInvoicedDistribution : nonInvoicedDistributions) {
if (!payAppDocNumbers.contains(nonInvoicedDistribution.getReferenceFinancialDocumentNumber())) {
payAppDocNumbers.add(nonInvoicedDistribution.getReferenceFinancialDocumentNumber());
}
}
// attempt to retrieve all the non applied holdings used as controls
if (!payAppDocNumbers.isEmpty()) {
nonAppliedHoldingControls.addAll(getNonAppliedHoldingService().getNonAppliedHoldingsByListOfDocumentNumbers(payAppDocNumbers));
}
return nonAppliedHoldingControls;
}
/**
* @return
*/
public List<InvoicePaidApplied> getInvoicePaidApplieds() {
return invoicePaidApplieds;
}
/**
* @param appliedPayments
*/
public void setInvoicePaidApplieds(List<InvoicePaidApplied> appliedPayments) {
this.invoicePaidApplieds = appliedPayments;
}
/**
* @return
*/
public List<NonInvoiced> getNonInvoiceds() {
return nonInvoiceds;
}
/**
* @param nonInvoiceds
*/
public void setNonInvoiceds(List<NonInvoiced> nonInvoiceds) {
this.nonInvoiceds = nonInvoiceds;
}
/**
* @return
*/
public Collection<NonInvoicedDistribution> getNonInvoicedDistributions() {
return nonInvoicedDistributions;
}
/**
* @param nonInvoicedDistributions
*/
public void setNonInvoicedDistributions(Collection<NonInvoicedDistribution> nonInvoicedDistributions) {
this.nonInvoicedDistributions = nonInvoicedDistributions;
}
/**
* @return
*/
public Collection<NonAppliedDistribution> getNonAppliedDistributions() {
return nonAppliedDistributions;
}
/**
* @param nonAppliedDistributions
*/
public void setNonAppliedDistributions(Collection<NonAppliedDistribution> nonAppliedDistributions) {
this.nonAppliedDistributions = nonAppliedDistributions;
}
/**
* @return
*/
public NonAppliedHolding getNonAppliedHolding() {
return nonAppliedHolding;
}
/**
* @param nonAppliedHolding
*/
public void setNonAppliedHolding(NonAppliedHolding nonAppliedHolding) {
this.nonAppliedHolding = nonAppliedHolding;
}
/**
* @return
*/
public AccountsReceivableDocumentHeader getAccountsReceivableDocumentHeader() {
return accountsReceivableDocumentHeader;
}
/**
* @param accountsReceivableDocumentHeader
*/
public void setAccountsReceivableDocumentHeader(AccountsReceivableDocumentHeader accountsReceivableDocumentHeader) {
this.accountsReceivableDocumentHeader = accountsReceivableDocumentHeader;
}
/**
* This method retrieves a specific applied payment from the list, by array index
*
* @param index the index of the applied payment to retrieve
* @return an InvoicePaidApplied
*/
public InvoicePaidApplied getInvoicePaidApplied(int index) {
return index < getInvoicePaidApplieds().size() ? getInvoicePaidApplieds().get(index) : new InvoicePaidApplied();
}
/**
* This method retrieves a specific non invoiced payment from the list, by array index
*
* @param index the index of the non invoiced payment to retrieve
* @return an NonInvoiced
*/
public NonInvoiced getNonInvoiced(int index) {
return index < getNonInvoiceds().size() ? getNonInvoiceds().get(index) : new NonInvoiced();
}
/**
* This method gets an ObjectCode from an invoice document.
*
* @param invoicePaidApplied
* @return
* @throws WorkflowException
*/
protected ObjectCode getInvoiceReceivableObjectCode(InvoicePaidApplied invoicePaidApplied) throws WorkflowException {
CustomerInvoiceDocument customerInvoiceDocument = invoicePaidApplied.getCustomerInvoiceDocument();
CustomerInvoiceDetail customerInvoiceDetail = invoicePaidApplied.getInvoiceDetail();
ReceivableCustomerInvoiceDetail receivableInvoiceDetail = new ReceivableCustomerInvoiceDetail(customerInvoiceDetail, customerInvoiceDocument);
ObjectCode objectCode = null;
if (ObjectUtils.isNotNull(receivableInvoiceDetail) && ObjectUtils.isNotNull(receivableInvoiceDetail.getFinancialObjectCode())) {
objectCode = receivableInvoiceDetail.getObjectCode();
if (ObjectUtils.isNull(objectCode)) {
Map<String, Object> fieldKeys = new HashMap<>();
fieldKeys.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, receivableInvoiceDetail.getChartOfAccountsCode());
fieldKeys.put(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, receivableInvoiceDetail.getFinancialObjectCode());
objectCode = getBusinessObjectService().findByPrimaryKey(ObjectCodeCurrent.class, fieldKeys);
}
}
return objectCode;
}
/**
* @param sequenceHelper
* @return the pending entries for the document
*/
protected List<GeneralLedgerPendingEntry> createPendingEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper) throws WorkflowException {
// Collection of all generated entries
List<GeneralLedgerPendingEntry> generatedEntries = new ArrayList<GeneralLedgerPendingEntry>();
// Get handles to the services we need
GeneralLedgerPendingEntryService glpeService = SpringContext.getBean(GeneralLedgerPendingEntryService.class);
BalanceTypeService balanceTypeService = SpringContext.getBean(BalanceTypeService.class);
UniversityDateService universityDateService = SpringContext.getBean(UniversityDateService.class);
SystemInformationService systemInformationService = SpringContext.getBean(SystemInformationService.class);
OffsetDefinitionService offsetDefinitionService = SpringContext.getBean(OffsetDefinitionService.class);
ParameterService parameterService = SpringContext.getBean(ParameterService.class);
DataDictionaryService dataDictionaryService = SpringContext.getBean(DataDictionaryService.class);
// Current fiscal year
Integer currentFiscalYear = universityDateService.getCurrentFiscalYear();
// Document type codes
String cashControlDocumentTypeCode = dataDictionaryService.getDocumentTypeNameByClass(CashControlDocument.class);
String paymentApplicationDocumentTypeCode = dataDictionaryService.getDocumentTypeNameByClass(PaymentApplicationDocument.class);
// The processing chart and org comes from the the cash control document if there is one.
// If the payment application document is created from scratch though, then we pull it
// from the current user. Note that we're not checking here that the user actually belongs
// to a billing or processing org, we're assuming that is handled elsewhere.
String processingChartCode = null;
String processingOrganizationCode = null;
if (hasCashControlDocument()) {
processingChartCode = getCashControlDocument().getAccountsReceivableDocumentHeader().getProcessingChartOfAccountCode();
processingOrganizationCode = getCashControlDocument().getAccountsReceivableDocumentHeader().getProcessingOrganizationCode();
}
else {
Person currentUser = GlobalVariables.getUserSession().getPerson();
ChartOrgHolder userOrg = getFsUserService().getPrimaryOrganization(currentUser.getPrincipalId(), ArConstants.AR_NAMESPACE_CODE);
processingChartCode = userOrg.getChartOfAccountsCode();
processingOrganizationCode = userOrg.getOrganizationCode();
}
// Some information comes from the cash control document
CashControlDocument cashControlDocument = getCashControlDocument();
// Get the System Information
SystemInformation unappliedSystemInformation = systemInformationService.getByProcessingChartOrgAndFiscalYear(processingChartCode, processingOrganizationCode, currentFiscalYear);
// Get the university clearing account
unappliedSystemInformation.refreshReferenceObject("universityClearingAccount");
Account universityClearingAccount = unappliedSystemInformation.getUniversityClearingAccount();
// Get the university clearing object, object type and sub-object code
String unappliedSubAccountNumber = unappliedSystemInformation.getUniversityClearingSubAccountNumber();
String unappliedObjectCode = unappliedSystemInformation.getUniversityClearingObjectCode();
String unappliedObjectTypeCode = unappliedSystemInformation.getUniversityClearingObject().getFinancialObjectTypeCode();
String unappliedSubObjectCode = unappliedSystemInformation.getUniversityClearingSubObjectCode();
// Get the object code for the university clearing account.
SystemInformation universityClearingAccountSystemInformation = systemInformationService.getByProcessingChartOrgAndFiscalYear(processingChartCode, processingOrganizationCode, currentFiscalYear);
String universityClearingAccountObjectCode = universityClearingAccountSystemInformation.getUniversityClearingObjectCode();
// Generate glpes for unapplied
NonAppliedHolding holding = getNonAppliedHolding();
if (ObjectUtils.isNotNull(holding)) {
GeneralLedgerPendingEntry actualCreditUnapplied = new GeneralLedgerPendingEntry();
actualCreditUnapplied.setUniversityFiscalYear(getPostingYear());
actualCreditUnapplied.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
actualCreditUnapplied.setChartOfAccountsCode(universityClearingAccount.getChartOfAccountsCode());
actualCreditUnapplied.setAccountNumber(universityClearingAccount.getAccountNumber());
actualCreditUnapplied.setFinancialObjectCode(unappliedObjectCode);
actualCreditUnapplied.setFinancialObjectTypeCode(unappliedObjectTypeCode);
actualCreditUnapplied.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
actualCreditUnapplied.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
actualCreditUnapplied.setTransactionLedgerEntryAmount(holding.getFinancialDocumentLineAmount().abs());
if (StringUtils.isBlank(unappliedSubAccountNumber)) {
actualCreditUnapplied.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
}
else {
actualCreditUnapplied.setSubAccountNumber(unappliedSubAccountNumber);
}
if (StringUtils.isBlank(unappliedSubObjectCode)) {
actualCreditUnapplied.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
}
else {
actualCreditUnapplied.setFinancialSubObjectCode(unappliedSubObjectCode);
}
actualCreditUnapplied.setProjectCode(KFSConstants.getDashProjectCode());
actualCreditUnapplied.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
actualCreditUnapplied.setTransactionLedgerEntryDescription(getDocumentHeader().getDocumentDescription());
generatedEntries.add(actualCreditUnapplied);
sequenceHelper.increment();
GeneralLedgerPendingEntry offsetDebitUnapplied = new GeneralLedgerPendingEntry();
offsetDebitUnapplied.setUniversityFiscalYear(actualCreditUnapplied.getUniversityFiscalYear());
offsetDebitUnapplied.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
offsetDebitUnapplied.setChartOfAccountsCode(actualCreditUnapplied.getChartOfAccountsCode());
offsetDebitUnapplied.setAccountNumber(actualCreditUnapplied.getAccountNumber());
OffsetDefinition offsetDebitDefinition = offsetDefinitionService.getByPrimaryId(getPostingYear(), universityClearingAccount.getChartOfAccountsCode(), paymentApplicationDocumentTypeCode, KFSConstants.BALANCE_TYPE_ACTUAL);
offsetDebitDefinition.refreshReferenceObject("financialObject");
offsetDebitUnapplied.setFinancialObjectCode(offsetDebitDefinition.getFinancialObjectCode());
offsetDebitUnapplied.setFinancialObjectTypeCode(offsetDebitDefinition.getFinancialObject().getFinancialObjectTypeCode());
offsetDebitUnapplied.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
offsetDebitUnapplied.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
offsetDebitUnapplied.setTransactionLedgerEntryAmount(actualCreditUnapplied.getTransactionLedgerEntryAmount().abs());
offsetDebitUnapplied.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
offsetDebitUnapplied.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
offsetDebitUnapplied.setProjectCode(KFSConstants.getDashProjectCode());
offsetDebitUnapplied.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
offsetDebitUnapplied.setTransactionLedgerEntryDescription(getDocumentHeader().getDocumentDescription());
generatedEntries.add(offsetDebitUnapplied);
sequenceHelper.increment();
GeneralLedgerPendingEntry actualDebitUnapplied = new GeneralLedgerPendingEntry();
actualDebitUnapplied.setUniversityFiscalYear(getPostingYear());
actualDebitUnapplied.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
actualDebitUnapplied.setChartOfAccountsCode(universityClearingAccount.getChartOfAccountsCode());
actualDebitUnapplied.setAccountNumber(universityClearingAccount.getAccountNumber());
actualDebitUnapplied.setFinancialObjectCode(unappliedObjectCode);
actualDebitUnapplied.setFinancialObjectTypeCode(unappliedObjectTypeCode);
actualDebitUnapplied.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
actualDebitUnapplied.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
actualDebitUnapplied.setTransactionLedgerEntryAmount(holding.getFinancialDocumentLineAmount().abs());
if (StringUtils.isBlank(unappliedSubAccountNumber)) {
actualDebitUnapplied.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
}
else {
actualDebitUnapplied.setSubAccountNumber(unappliedSubAccountNumber);
}
actualDebitUnapplied.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
actualDebitUnapplied.setProjectCode(KFSConstants.getDashProjectCode());
actualDebitUnapplied.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
actualDebitUnapplied.setTransactionLedgerEntryDescription(getDocumentHeader().getDocumentDescription());
generatedEntries.add(actualDebitUnapplied);
sequenceHelper.increment();
// Offsets for unapplied entries are just offsets to themselves, same info.
// So set the values into the offsets based on the values in the actuals.
GeneralLedgerPendingEntry offsetCreditUnapplied = new GeneralLedgerPendingEntry();
offsetCreditUnapplied.setUniversityFiscalYear(actualDebitUnapplied.getUniversityFiscalYear());
offsetCreditUnapplied.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
offsetCreditUnapplied.setChartOfAccountsCode(actualDebitUnapplied.getChartOfAccountsCode());
offsetCreditUnapplied.setAccountNumber(actualDebitUnapplied.getAccountNumber());
OffsetDefinition offsetCreditDefinition = offsetDefinitionService.getByPrimaryId(getPostingYear(), universityClearingAccount.getChartOfAccountsCode(), paymentApplicationDocumentTypeCode, KFSConstants.BALANCE_TYPE_ACTUAL);
offsetCreditDefinition.refreshReferenceObject("financialObject");
offsetCreditUnapplied.setFinancialObjectCode(offsetCreditDefinition.getFinancialObjectCode());
offsetCreditUnapplied.setFinancialObjectTypeCode(offsetCreditDefinition.getFinancialObject().getFinancialObjectTypeCode());
offsetCreditUnapplied.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
offsetCreditUnapplied.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
offsetCreditUnapplied.setTransactionLedgerEntryAmount(actualDebitUnapplied.getTransactionLedgerEntryAmount().abs());
offsetCreditUnapplied.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
offsetCreditUnapplied.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
offsetCreditUnapplied.setProjectCode(KFSConstants.getDashProjectCode());
offsetCreditUnapplied.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
offsetCreditUnapplied.setTransactionLedgerEntryDescription(getDocumentHeader().getDocumentDescription());
generatedEntries.add(offsetCreditUnapplied);
sequenceHelper.increment();
}
// Generate glpes for non-ar
for (NonInvoiced nonInvoiced : getNonInvoiceds()) {
// Actual entries
GeneralLedgerPendingEntry actualCreditEntry = new GeneralLedgerPendingEntry();
actualCreditEntry.setUniversityFiscalYear(getPostingYear());
actualCreditEntry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
actualCreditEntry.setChartOfAccountsCode(nonInvoiced.getChartOfAccountsCode());
actualCreditEntry.setAccountNumber(nonInvoiced.getAccountNumber());
actualCreditEntry.setFinancialObjectCode(nonInvoiced.getFinancialObjectCode());
nonInvoiced.refreshReferenceObject("financialObject");
actualCreditEntry.setFinancialObjectTypeCode(nonInvoiced.getFinancialObject().getFinancialObjectTypeCode());
actualCreditEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
actualCreditEntry.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
actualCreditEntry.setTransactionLedgerEntryAmount(nonInvoiced.getFinancialDocumentLineAmount().abs());
if (StringUtils.isBlank(nonInvoiced.getSubAccountNumber())) {
actualCreditEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
}
else {
actualCreditEntry.setSubAccountNumber(nonInvoiced.getSubAccountNumber());
}
if (StringUtils.isBlank(nonInvoiced.getFinancialSubObjectCode())) {
actualCreditEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
}
else {
actualCreditEntry.setFinancialSubObjectCode(nonInvoiced.getFinancialSubObjectCode());
}
if (StringUtils.isBlank(nonInvoiced.getProjectCode())) {
actualCreditEntry.setProjectCode(KFSConstants.getDashProjectCode());
}
else {
actualCreditEntry.setProjectCode(nonInvoiced.getProjectCode());
}
actualCreditEntry.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
actualCreditEntry.setTransactionLedgerEntryDescription(getDocumentHeader().getDocumentDescription());
generatedEntries.add(actualCreditEntry);
sequenceHelper.increment();
GeneralLedgerPendingEntry actualDebitEntry = new GeneralLedgerPendingEntry();
actualDebitEntry.setUniversityFiscalYear(getPostingYear());
actualDebitEntry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
actualDebitEntry.setChartOfAccountsCode(universityClearingAccount.getChartOfAccountsCode());
actualDebitEntry.setAccountNumber(universityClearingAccount.getAccountNumber());
if (hasCashControlDocument()) {
actualDebitEntry.setFinancialObjectCode(universityClearingAccountObjectCode);
ObjectCodeService objectCodeService = SpringContext.getBean(ObjectCodeService.class);
ObjectCode objectCode = objectCodeService.getByPrimaryIdWithCaching(getPostingYear(), universityClearingAccountSystemInformation.getUniversityClearingChartOfAccounts().getChartOfAccountsCode(), universityClearingAccountObjectCode);
actualDebitEntry.setFinancialObjectTypeCode(objectCode.getFinancialObjectTypeCode());
actualDebitEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
}
else {
actualDebitEntry.setFinancialObjectCode(unappliedObjectCode);
actualDebitEntry.setFinancialObjectTypeCode(unappliedObjectTypeCode);
if (StringUtils.isBlank(unappliedSubObjectCode)) {
actualDebitEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
}
else {
actualDebitEntry.setFinancialSubObjectCode(unappliedSubObjectCode);
}
}
actualDebitEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
actualDebitEntry.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
actualDebitEntry.setTransactionLedgerEntryAmount(nonInvoiced.getFinancialDocumentLineAmount().abs());
if (StringUtils.isBlank(unappliedSubAccountNumber)) {
actualDebitEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
}
else {
actualDebitEntry.setSubAccountNumber(unappliedSubAccountNumber);
}
actualDebitEntry.setProjectCode(KFSConstants.getDashProjectCode());
actualDebitEntry.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
actualDebitEntry.setTransactionLedgerEntryDescription(getDocumentHeader().getDocumentDescription());
generatedEntries.add(actualDebitEntry);
sequenceHelper.increment();
// Offset entries
GeneralLedgerPendingEntry offsetDebitEntry = new GeneralLedgerPendingEntry();
offsetDebitEntry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
offsetDebitEntry.setChartOfAccountsCode(nonInvoiced.getChartOfAccountsCode());
offsetDebitEntry.setAccountNumber(nonInvoiced.getAccountNumber());
offsetDebitEntry.setUniversityFiscalYear(getPostingYear());
OffsetDefinition debitOffsetDefinition = offsetDefinitionService.getByPrimaryId(getPostingYear(), nonInvoiced.getChartOfAccountsCode(), paymentApplicationDocumentTypeCode, KFSConstants.BALANCE_TYPE_ACTUAL);
debitOffsetDefinition.refreshReferenceObject("financialObject");
offsetDebitEntry.setFinancialObjectCode(debitOffsetDefinition.getFinancialObjectCode());
offsetDebitEntry.setFinancialObjectTypeCode(debitOffsetDefinition.getFinancialObject().getFinancialObjectTypeCode());
offsetDebitEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
offsetDebitEntry.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
offsetDebitEntry.setTransactionLedgerEntryAmount(nonInvoiced.getFinancialDocumentLineAmount().abs());
offsetDebitEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
offsetDebitEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
offsetDebitEntry.setProjectCode(KFSConstants.getDashProjectCode());
offsetDebitEntry.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
offsetDebitEntry.setTransactionLedgerEntryDescription(getDocumentHeader().getDocumentDescription());
generatedEntries.add(offsetDebitEntry);
sequenceHelper.increment();
GeneralLedgerPendingEntry offsetCreditEntry = new GeneralLedgerPendingEntry();
offsetCreditEntry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
offsetCreditEntry.setUniversityFiscalYear(getPostingYear());
offsetCreditEntry.setChartOfAccountsCode(universityClearingAccount.getChartOfAccountsCode());
offsetCreditEntry.setAccountNumber(universityClearingAccount.getAccountNumber());
Integer fiscalYearForCreditOffsetDefinition = null == cashControlDocument ? currentFiscalYear : cashControlDocument.getUniversityFiscalYear();
OffsetDefinition creditOffsetDefinition = offsetDefinitionService.getByPrimaryId(fiscalYearForCreditOffsetDefinition, processingChartCode, paymentApplicationDocumentTypeCode, KFSConstants.BALANCE_TYPE_ACTUAL);
creditOffsetDefinition.refreshReferenceObject("financialObject");
offsetCreditEntry.setFinancialObjectCode(creditOffsetDefinition.getFinancialObjectCode());
offsetCreditEntry.setFinancialObjectTypeCode(creditOffsetDefinition.getFinancialObject().getFinancialObjectTypeCode());
offsetCreditEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
offsetCreditEntry.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
offsetCreditEntry.setTransactionLedgerEntryAmount(nonInvoiced.getFinancialDocumentLineAmount().abs());
offsetCreditEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
offsetCreditEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
offsetCreditEntry.setProjectCode(KFSConstants.getDashProjectCode());
offsetCreditEntry.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
offsetCreditEntry.setTransactionLedgerEntryDescription(getDocumentHeader().getDocumentDescription());
generatedEntries.add(offsetCreditEntry);
sequenceHelper.increment();
}
// Generate GLPEs for applied payments
List<InvoicePaidApplied> appliedPayments = getInvoicePaidApplieds();
for (InvoicePaidApplied ipa : appliedPayments) {
// Skip payments for 0 dollar amount
if (KualiDecimal.ZERO.equals(ipa.getInvoiceItemAppliedAmount())) {
continue;
}
ipa.refreshNonUpdateableReferences();
Account billingOrganizationAccount = ipa.getInvoiceDetail().getAccount();
ObjectCode invoiceObjectCode = getInvoiceReceivableObjectCode(ipa);
ObjectUtils.isNull(invoiceObjectCode); // Refresh
ObjectCode accountsReceivableObjectCode = getAccountsReceivablePendingEntryService().getAccountsReceivableObjectCode(ipa);
ObjectCode unappliedCashObjectCode = ipa.getSystemInformation().getUniversityClearingObject();
GeneralLedgerPendingEntry actualDebitEntry = new GeneralLedgerPendingEntry();
actualDebitEntry.setUniversityFiscalYear(getPostingYear());
actualDebitEntry.setChartOfAccountsCode(universityClearingAccount.getChartOfAccountsCode());
actualDebitEntry.setAccountNumber(universityClearingAccount.getAccountNumber());
actualDebitEntry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
actualDebitEntry.setTransactionLedgerEntryAmount(ipa.getInvoiceItemAppliedAmount().abs());
if (hasCashControlDocument()) {
actualDebitEntry.setFinancialObjectCode(unappliedCashObjectCode.getFinancialObjectCode());
actualDebitEntry.setFinancialObjectTypeCode(unappliedCashObjectCode.getFinancialObjectTypeCode());
actualDebitEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
}
else {
actualDebitEntry.setFinancialObjectCode(unappliedObjectCode);
actualDebitEntry.setFinancialObjectTypeCode(unappliedObjectTypeCode);
if (StringUtils.isBlank(unappliedSubObjectCode)) {
actualDebitEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
}
else {
actualDebitEntry.setFinancialSubObjectCode(unappliedSubObjectCode);
}
}
if (StringUtils.isBlank(unappliedSubAccountNumber)) {
actualDebitEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
}
else {
actualDebitEntry.setSubAccountNumber(unappliedSubAccountNumber);
}
actualDebitEntry.setProjectCode(KFSConstants.getDashProjectCode());
actualDebitEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
actualDebitEntry.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
actualDebitEntry.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
actualDebitEntry.setTransactionLedgerEntryDescription(getDocumentHeader().getDocumentDescription());
generatedEntries.add(actualDebitEntry);
sequenceHelper.increment();
GeneralLedgerPendingEntry actualCreditEntry = new GeneralLedgerPendingEntry();
actualCreditEntry.setUniversityFiscalYear(getPostingYear());
actualCreditEntry.setChartOfAccountsCode(universityClearingAccount.getChartOfAccountsCode());
actualCreditEntry.setAccountNumber(universityClearingAccount.getAccountNumber());
actualCreditEntry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
actualCreditEntry.setTransactionLedgerEntryAmount(ipa.getInvoiceItemAppliedAmount().abs());
actualCreditEntry.setFinancialObjectCode(invoiceObjectCode.getFinancialObjectCode());
actualCreditEntry.setFinancialObjectTypeCode(invoiceObjectCode.getFinancialObjectTypeCode());
actualCreditEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
actualCreditEntry.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
actualCreditEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
actualCreditEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
actualCreditEntry.setProjectCode(KFSConstants.getDashProjectCode());
glpeService.populateOffsetGeneralLedgerPendingEntry(getPostingYear(), actualDebitEntry, sequenceHelper, actualCreditEntry);
actualCreditEntry.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
generatedEntries.add(actualCreditEntry);
sequenceHelper.increment();
GeneralLedgerPendingEntry offsetDebitEntry = new GeneralLedgerPendingEntry();
offsetDebitEntry.setUniversityFiscalYear(getPostingYear());
offsetDebitEntry.setAccountNumber(billingOrganizationAccount.getAccountNumber());
offsetDebitEntry.setChartOfAccountsCode(billingOrganizationAccount.getChartOfAccountsCode());
offsetDebitEntry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
offsetDebitEntry.setTransactionLedgerEntryAmount(ipa.getInvoiceItemAppliedAmount().abs());
offsetDebitEntry.setFinancialObjectCode(invoiceObjectCode.getFinancialObjectCode());
offsetDebitEntry.setFinancialObjectTypeCode(invoiceObjectCode.getFinancialObjectTypeCode());
offsetDebitEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
offsetDebitEntry.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
if (StringUtils.isBlank(ipa.getInvoiceDetail().getSubAccountNumber())) {
offsetDebitEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
}
else {
offsetDebitEntry.setSubAccountNumber(ipa.getInvoiceDetail().getSubAccountNumber());
}
if (StringUtils.isBlank(ipa.getInvoiceDetail().getFinancialSubObjectCode())) {
offsetDebitEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
}
else {
offsetDebitEntry.setFinancialSubObjectCode(ipa.getInvoiceDetail().getFinancialSubObjectCode());
}
if (StringUtils.isBlank(ipa.getInvoiceDetail().getProjectCode())) {
offsetDebitEntry.setProjectCode(KFSConstants.getDashProjectCode());
}
else {
offsetDebitEntry.setProjectCode(ipa.getInvoiceDetail().getProjectCode());
}
offsetDebitEntry.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter());
offsetDebitEntry.setTransactionLedgerEntryDescription(getDocumentHeader().getDocumentDescription());
generatedEntries.add(offsetDebitEntry);
sequenceHelper.increment();
GeneralLedgerPendingEntry offsetCreditEntry = new GeneralLedgerPendingEntry();
offsetCreditEntry.setUniversityFiscalYear(getPostingYear());
offsetCreditEntry.setAccountNumber(billingOrganizationAccount.getAccountNumber());
offsetCreditEntry.setChartOfAccountsCode(billingOrganizationAccount.getChartOfAccountsCode());
offsetCreditEntry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
offsetCreditEntry.setTransactionLedgerEntryAmount(ipa.getInvoiceItemAppliedAmount().abs());
offsetCreditEntry.setFinancialObjectCode(accountsReceivableObjectCode.getFinancialObjectCode());
offsetCreditEntry.setFinancialObjectTypeCode(accountsReceivableObjectCode.getFinancialObjectTypeCode());
offsetCreditEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
offsetCreditEntry.setFinancialDocumentTypeCode(paymentApplicationDocumentTypeCode);
if (StringUtils.isBlank(ipa.getInvoiceDetail().getSubAccountNumber())) {
offsetCreditEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
}
else {
offsetCreditEntry.setSubAccountNumber(ipa.getInvoiceDetail().getSubAccountNumber());
}
offsetCreditEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
offsetCreditEntry.setProjectCode(KFSConstants.getDashProjectCode());
offsetCreditEntry.refreshNonUpdateableReferences();
glpeService.populateOffsetGeneralLedgerPendingEntry(getPostingYear(), offsetDebitEntry, sequenceHelper, offsetCreditEntry);
generatedEntries.add(offsetCreditEntry);
sequenceHelper.increment();
}
// Set the origination code for all entries.
for (GeneralLedgerPendingEntry entry : generatedEntries) {
entry.setFinancialSystemOriginationCode("01");
}
return generatedEntries;
}
/**
* @see org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource#generateDocumentGeneralLedgerPendingEntries(org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
*/
@Override
public boolean generateDocumentGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
try {
List<GeneralLedgerPendingEntry> entries = createPendingEntries(sequenceHelper);
for (GeneralLedgerPendingEntry entry : entries) {
addPendingEntry(entry);
}
}
catch (Throwable t) {
LOG.error("Exception encountered while generating pending entries.", t);
return false;
}
return true;
}
/**
* @see org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource#generateGeneralLedgerPendingEntries(org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail,
* org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
*/
@Override
public boolean generateGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
return true;
}
/**
* @see org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource#getGeneralLedgerPendingEntryAmountForDetail(org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
*/
@Override
public KualiDecimal getGeneralLedgerPendingEntryAmountForDetail(GeneralLedgerPendingEntrySourceDetail glpeSourceDetail) {
return null;
}
/**
* @see org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource#getGeneralLedgerPendingEntrySourceDetails()
*/
@Override
public List<GeneralLedgerPendingEntrySourceDetail> getGeneralLedgerPendingEntrySourceDetails() {
return new ArrayList<GeneralLedgerPendingEntrySourceDetail>();
}
/**
* @see org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource#isDebit(org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
*/
@Override
public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
return false;
}
/**
* This method is used ONLY for handleRouteStatus change and other postProcessor related tasks (like
* getWorkflowEngineDocumentIdsToLock()) and should not otherwise be used. The reason this is its own method is to make sure
* that handleRouteStatusChange and getWorkflowEngineDocumentIdsToLock use the same method to retrieve what invoices to update.
*
* @return
*/
protected List<String> getInvoiceNumbersToUpdateOnFinal() {
List<String> docIds = new ArrayList<String>();
for (InvoicePaidApplied ipa : getInvoicePaidApplieds()) {
docIds.add(ipa.getFinancialDocumentReferenceInvoiceNumber());
}
return docIds;
}
/**
* @see org.kuali.rice.krad.document.DocumentBase#getWorkflowEngineDocumentIdsToLock()
*/
@Override
public List<String> getWorkflowEngineDocumentIdsToLock() {
List<String> docIdStrings = getInvoiceNumbersToUpdateOnFinal();
if (docIdStrings == null || docIdStrings.isEmpty()) {
return null;
}
return docIdStrings;
}
/**
* @see org.kuali.kfs.sys.document.GeneralLedgerPostingDocumentBase#doRouteStatusChange(org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO)
*/
@Override
public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) {
super.doRouteStatusChange(statusChangeEvent);
if (getDocumentHeader().getWorkflowDocument().isFinal()) {
DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class);
// get the now time to stamp invoices with
java.sql.Date today = new java.sql.Date(dateTimeService.getCurrentDate().getTime());
List<String> invoiceDocNumbers = getInvoiceNumbersToUpdateOnFinal();
for (String invoiceDocumentNumber : invoiceDocNumbers) {
CustomerInvoiceDocument invoice = null;
// attempt to retrieve the invoice doc
try {
invoice = (CustomerInvoiceDocument) getDocService().getByDocumentHeaderId(invoiceDocumentNumber);
}
catch (WorkflowException we) {
LOG.error("Failed to load the Invoice document due to a WorkflowException.", we);
}
if (invoice == null) {
throw new RuntimeException("DocumentService returned a Null CustomerInvoice Document for Doc# " + invoiceDocumentNumber + ".");
}
// KULAR-384 - close the invoice if its open and the openAmount is zero
if (invoice.getOpenAmount().isZero() && invoice.isOpenInvoiceIndicator()) {
invoice.setClosedDate(today);
getInvoiceDocService().addCloseNote(invoice, getDocumentHeader().getWorkflowDocument());
invoice.setOpenInvoiceIndicator(false);
getDocService().updateDocument(invoice);
}
}
}
}
/**
* @see org.kuali.rice.krad.bo.PersistableBusinessObjectBase#buildListOfDeletionAwareLists()
*/
@Override
public List buildListOfDeletionAwareLists() {
List deletionAwareLists = super.buildListOfDeletionAwareLists();
if (invoicePaidApplieds != null) {
deletionAwareLists.add(invoicePaidApplieds);
}
if (nonInvoiceds != null) {
deletionAwareLists.add(nonInvoiceds);
}
if (nonInvoicedDistributions != null) {
deletionAwareLists.add(nonInvoicedDistributions);
}
if (nonAppliedDistributions != null) {
deletionAwareLists.add(nonAppliedDistributions);
}
return deletionAwareLists;
}
/**
* @see org.kuali.kfs.sys.document.GeneralLedgerPostingDocumentBase#prepareForSave(org.kuali.rice.krad.rule.event.KualiDocumentEvent)
*/
@Override
public void prepareForSave(KualiDocumentEvent event) {
super.prepareForSave(event);
// set primary key for NonAppliedHolding if data entered
if (ObjectUtils.isNotNull(this.nonAppliedHolding)) {
if (ObjectUtils.isNull(this.nonAppliedHolding.getReferenceFinancialDocumentNumber())) {
this.nonAppliedHolding.setReferenceFinancialDocumentNumber(this.documentNumber);
}
}
// generate GLPEs only when routing or blanket approving
if (event instanceof RouteDocumentEvent || event instanceof BlanketApproveDocumentEvent) {
// if this document is not generated thru CashControl,
// create nonApplied and nonInvoiced Distributions
if (!this.hasCashControlDetail()) {
createDistributions();
}
GeneralLedgerPendingEntryService glpeService = SpringContext.getBean(GeneralLedgerPendingEntryService.class);
if (!glpeService.generateGeneralLedgerPendingEntries(this)) {
logErrors();
throw new ValidationException("general ledger GLPE generation failed");
}
}
}
/**
* @return
*/
public PaymentApplicationDocumentService getPaymentApplicationDocumentService() {
if (null == paymentApplicationDocumentService) {
paymentApplicationDocumentService = SpringContext.getBean(PaymentApplicationDocumentService.class);
}
return paymentApplicationDocumentService;
}
/**
* @return
*/
protected FinancialSystemUserService getFsUserService() {
if (fsUserService == null) {
fsUserService = SpringContext.getBean(FinancialSystemUserService.class);
}
return fsUserService;
}
/**
* @return
*/
protected CustomerInvoiceDocumentService getInvoiceDocService() {
if (invoiceDocService == null) {
invoiceDocService = SpringContext.getBean(CustomerInvoiceDocumentService.class);
}
return invoiceDocService;
}
/**
* @return
*/
protected DocumentService getDocService() {
if (docService == null) {
docService = SpringContext.getBean(DocumentService.class);
}
return docService;
}
/**
* @return
*/
protected NonAppliedHoldingService getNonAppliedHoldingService() {
if (nonAppliedHoldingService == null) {
nonAppliedHoldingService = SpringContext.getBean(NonAppliedHoldingService.class);
}
return nonAppliedHoldingService;
}
protected BusinessObjectService getBoService() {
if (boService == null) {
boService = SpringContext.getBean(BusinessObjectService.class);
}
return boService;
}
public String getHiddenFieldForErrors() {
return hiddenFieldForErrors;
}
public void setHiddenFieldForErrors(String hiddenFieldForErrors) {
this.hiddenFieldForErrors = hiddenFieldForErrors;
}
/**
* Retrieves the NonApplied Holdings that are the Controls for this PaymentApplication. Note that this is dangerous to use and
* should not be relied upon. The data is never persisted to the database, so will always be null/empty when retrieved fresh. It
* is only populated while the document is live from the website, or while its in flight in workflow, due to the fact that it
* has been serialized. You should probably not be using this method unless you are sure you know what you are doing.
*
* @return
*/
public Collection<NonAppliedHolding> getNonAppliedHoldingsForCustomer() {
return nonAppliedHoldingsForCustomer;
}
/**
* Warning, this property is not ever persisted to the database, and is only used during workflow processing (since its been
* serialized) and during presentation of the document on the webapp. You should probably not be using this method unless you
* are sure you know what you are doing.
*
* @param nonApplieds
*/
public void setNonAppliedHoldingsForCustomer(ArrayList<NonAppliedHolding> nonApplieds) {
this.nonAppliedHoldingsForCustomer = nonApplieds;
}
/**
* Collects and returns the combined distributions from NonInvoiced/NonAr and Unapplied. This method is intended to be used only
* when the document has gone to final, to show what control documents were issued what funds. The return value is a
* Map<String,KualiDecimal> where the key is the NonAppliedHolding's ReferenceFinancialDocumentNumber and the value is the
* Amount to be applied.
*
* @return
*/
public Map<String, KualiDecimal> getDistributionsFromControlDocuments() {
if (!isFinal()) {
throw new UnsupportedOperationException("This method should only be used once the document has been approved/gone to final.");
}
Map<String, KualiDecimal> distributions = new HashMap<String, KualiDecimal>();
// short circuit if no non-applied-distributions available
if ((nonAppliedDistributions == null || nonAppliedDistributions.isEmpty()) && (nonInvoicedDistributions == null || nonInvoicedDistributions.isEmpty())) {
return distributions;
}
// get the list of payapp docnumbers from non-applied-distributions
for (NonAppliedDistribution nonAppliedDistribution : nonAppliedDistributions) {
String refDocNbr = nonAppliedDistribution.getReferenceFinancialDocumentNumber();
if (distributions.containsKey(refDocNbr)) {
distributions.put(refDocNbr, (distributions.get(refDocNbr).add(nonAppliedDistribution.getFinancialDocumentLineAmount())));
}
else {
distributions.put(refDocNbr, nonAppliedDistribution.getFinancialDocumentLineAmount());
}
}
// get the list of payapp docnumbers from non-applied-distributions
for (NonInvoicedDistribution nonInvoicedDistribution : nonInvoicedDistributions) {
String refDocNbr = nonInvoicedDistribution.getReferenceFinancialDocumentNumber();
if (distributions.containsKey(refDocNbr)) {
distributions.put(refDocNbr, (distributions.get(refDocNbr).add(nonInvoicedDistribution.getFinancialDocumentLineAmount())));
}
else {
distributions.put(refDocNbr, nonInvoicedDistribution.getFinancialDocumentLineAmount());
}
}
return distributions;
}
/**
* Walks through the nonAppliedHoldings passed in (the control docs) and allocates how the funding should be allocated. This
* function is intended to be used when the document is still live, ie not for when its been finalized. The return value is a
* Map<String,KualiDecimal> where the key is the NonAppliedHolding's ReferenceFinancialDocumentNumber and the value is the
* Amount to be applied.
*/
public Map<String, KualiDecimal> allocateFundsFromUnappliedControls(List<NonAppliedHolding> nonAppliedHoldings, KualiDecimal amountToBeApplied) {
if (nonAppliedHoldings == null) {
throw new IllegalArgumentException("A null value for the parameter [nonAppliedHoldings] was passed in.");
}
if (amountToBeApplied == null) {
throw new IllegalArgumentException("A null ovalue for the parameter [amountToBeApplied] was passed in.");
}
if (isFinal()) {
throw new UnsupportedOperationException("This method should not be used when the document has been approved/gone to final.");
}
// special-case the situation where the amountToBeApplied is negative, then make all allocations zero
if (amountToBeApplied.isNegative()) {
Map<String, KualiDecimal> allocations = new HashMap<String, KualiDecimal>();
for (NonAppliedHolding nonAppliedHolding : nonAppliedHoldings) {
allocations.put(nonAppliedHolding.getReferenceFinancialDocumentNumber(), KualiDecimal.ZERO);
}
return allocations;
}
Map<String, KualiDecimal> allocations = new HashMap<String, KualiDecimal>();
KualiDecimal remainingAmount = new KualiDecimal(amountToBeApplied.toString()); // clone it
// due to the way the control list is generated, this will result in applying
// from the oldest to newest, which is the ordering desired. If this ever changes,
// then the internal logic here should be to apply to the oldest doc first, and then
// move forward in time until you run out of money or docs
for (NonAppliedHolding nonAppliedHolding : nonAppliedHoldings) {
String refDocNumber = nonAppliedHolding.getReferenceFinancialDocumentNumber();
// this shouldnt ever happen, but lets sanity check it
if (allocations.containsKey(nonAppliedHolding.getReferenceFinancialDocumentNumber())) {
throw new RuntimeException("The same NonAppliedHolding RefDocNumber came up twice, which should never happen.");
}
else {
allocations.put(refDocNumber, KualiDecimal.ZERO);
}
if (remainingAmount.isGreaterThan(KualiDecimal.ZERO)) {
if (nonAppliedHoldings.iterator().hasNext()) {
if (remainingAmount.isLessEqual(nonAppliedHolding.getAvailableUnappliedAmount())) {
allocations.put(refDocNumber, remainingAmount);
remainingAmount = remainingAmount.subtract(remainingAmount);
}
else {
allocations.put(refDocNumber, nonAppliedHolding.getAvailableUnappliedAmount());
remainingAmount = remainingAmount.subtract(nonAppliedHolding.getAvailableUnappliedAmount());
}
}
}
}
return allocations;
}
// this method is only used by Unapplied PayApp.
// create nonApplied and nonInvoiced Distributions
public void createDistributions() {
// if there are non nonApplieds, then we have nothing to do
if (nonAppliedHoldingsForCustomer == null || nonAppliedHoldingsForCustomer.isEmpty()) {
return;
}
Collection<InvoicePaidApplied> invoicePaidAppliedsForCurrentDoc = this.getInvoicePaidApplieds();
Collection<NonInvoiced> nonInvoicedsForCurrentDoc = this.getNonInvoiceds();
for (NonAppliedHolding nonAppliedHoldings : this.getNonAppliedHoldingsForCustomer()) {
// check if payment has been applied to Invoices
// create Unapplied Distribution for each PaidApplied
KualiDecimal remainingUnappliedForDistribution = nonAppliedHoldings.getAvailableUnappliedAmount();
for (InvoicePaidApplied invoicePaidAppliedForCurrentDoc : invoicePaidAppliedsForCurrentDoc) {
KualiDecimal paidAppliedDistributionAmount = invoicePaidAppliedForCurrentDoc.getPaidAppiedDistributionAmount();
KualiDecimal remainingPaidAppliedForDistribution = invoicePaidAppliedForCurrentDoc.getInvoiceItemAppliedAmount().subtract(paidAppliedDistributionAmount);
if (remainingPaidAppliedForDistribution.equals(KualiDecimal.ZERO) || remainingUnappliedForDistribution.equals(KualiDecimal.ZERO)) {
continue;
}
// set NonAppliedDistributions for the current document
NonAppliedDistribution nonAppliedDistribution = new NonAppliedDistribution();
nonAppliedDistribution.setDocumentNumber(invoicePaidAppliedForCurrentDoc.getDocumentNumber());
nonAppliedDistribution.setPaidAppliedItemNumber(invoicePaidAppliedForCurrentDoc.getPaidAppliedItemNumber());
nonAppliedDistribution.setReferenceFinancialDocumentNumber(nonAppliedHoldings.getReferenceFinancialDocumentNumber());
if (remainingPaidAppliedForDistribution.isLessEqual(remainingUnappliedForDistribution)) {
nonAppliedDistribution.setFinancialDocumentLineAmount(remainingPaidAppliedForDistribution);
remainingUnappliedForDistribution = remainingUnappliedForDistribution.subtract(remainingPaidAppliedForDistribution);
invoicePaidAppliedForCurrentDoc.setPaidAppiedDistributionAmount(paidAppliedDistributionAmount.add(remainingPaidAppliedForDistribution));
}
else {
nonAppliedDistribution.setFinancialDocumentLineAmount(remainingUnappliedForDistribution);
invoicePaidAppliedForCurrentDoc.setPaidAppiedDistributionAmount(paidAppliedDistributionAmount.add(remainingUnappliedForDistribution));
remainingUnappliedForDistribution = KualiDecimal.ZERO;
}
this.nonAppliedDistributions.add(nonAppliedDistribution);
}
// check if payment has been applied to NonAR
// create NonAR distribution for each NonAR Applied row
for (NonInvoiced nonInvoicedForCurrentDoc : nonInvoicedsForCurrentDoc) {
KualiDecimal nonInvoicedDistributionAmount = nonInvoicedForCurrentDoc.getNonInvoicedDistributionAmount();
KualiDecimal remainingNonInvoicedForDistribution = nonInvoicedForCurrentDoc.getFinancialDocumentLineAmount().subtract(nonInvoicedDistributionAmount);
if (remainingNonInvoicedForDistribution.equals(KualiDecimal.ZERO) || remainingUnappliedForDistribution.equals(KualiDecimal.ZERO)) {
continue;
}
// set NonAppliedDistributions for the current document
NonInvoicedDistribution nonInvoicedDistribution = new NonInvoicedDistribution();
nonInvoicedDistribution.setDocumentNumber(nonInvoicedForCurrentDoc.getDocumentNumber());
nonInvoicedDistribution.setFinancialDocumentLineNumber(nonInvoicedForCurrentDoc.getFinancialDocumentLineNumber());
nonInvoicedDistribution.setReferenceFinancialDocumentNumber(nonAppliedHoldings.getReferenceFinancialDocumentNumber());
if (remainingNonInvoicedForDistribution.isLessEqual(remainingUnappliedForDistribution)) {
nonInvoicedDistribution.setFinancialDocumentLineAmount(remainingNonInvoicedForDistribution);
remainingUnappliedForDistribution = remainingUnappliedForDistribution.subtract(remainingNonInvoicedForDistribution);
nonInvoicedForCurrentDoc.setNonInvoicedDistributionAmount(nonInvoicedDistributionAmount.add(remainingNonInvoicedForDistribution));
}
else {
nonInvoicedDistribution.setFinancialDocumentLineAmount(remainingUnappliedForDistribution);
nonInvoicedForCurrentDoc.setNonInvoicedDistributionAmount(nonInvoicedDistributionAmount.add(remainingUnappliedForDistribution));
remainingUnappliedForDistribution = KualiDecimal.ZERO;
}
this.nonInvoicedDistributions.add(nonInvoicedDistribution);
}
}
}
/**
* @see org.kuali.kfs.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String)
*/
@Override
public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
if (LAUNCHED_FROM_BATCH.equals(nodeName)) {
return launchedFromBatch();
}
throw new UnsupportedOperationException("answerSplitNode('" + nodeName + "') was called but no handler for nodeName specified.");
}
// determines if the doc was launched by SYSTEM_USER, if so, then it was launched from batch
protected boolean launchedFromBatch() {
boolean result = false;
Principal initiator = KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(KFSConstants.SYSTEM_USER);
result = initiator.getPrincipalId().equalsIgnoreCase(getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId());
return result;
}
/** CUSTOM SEARCH HELPER METHODS **/
/**
* This method is defined to assist in the custom search implementation.
*
* @return
*/
public String getUnappliedCustomerNumber() {
if (nonAppliedHolding == null) {
return "";
}
return nonAppliedHolding.getCustomerNumber();
}
/**
* This method is defined to assist in the custom search implementation.
*
* @return
*/
public String getUnappliedCustomerName() {
if (nonAppliedHolding == null) {
return "";
}
return nonAppliedHolding.getCustomer().getCustomerName();
}
/**
* This method is defined to assist in the custom search implementation.
*
* @return
*/
public String getInvoiceAppliedCustomerNumber() {
return getAccountsReceivableDocumentHeader().getCustomerNumber();
}
/**
* This method is defined to assist in the custom search implementation.
*
* @return
*/
public String getInvoiceAppliedCustomerName() {
return getAccountsReceivableDocumentHeader().getCustomer().getCustomerName();
}
/**
* Gets the invoiceDocumentType attribute.
*
* @return Returns the invoiceDocumentType.
*/
public String getInvoiceDocumentType() {
return invoiceDocumentType;
}
/**
* Sets the invoiceDocumentType attribute value.
*
* @param invoiceDocumentType The invoiceDocumentType to set.
*/
public void setInvoiceDocumentType(String invoiceDocumentType) {
this.invoiceDocumentType = invoiceDocumentType;
}
/**
* Gets the letterOfCreditCreationType attribute.
*
* @return Returns the letterOfCreditCreationType.
*/
public String getLetterOfCreditCreationType() {
return letterOfCreditCreationType;
}
/**
* Sets the letterOfCreditCreationType attribute value.
*
* @param letterOfCreditCreationType The letterOfCreditCreationType to set.
*/
public void setLetterOfCreditCreationType(String letterOfCreditCreationType) {
this.letterOfCreditCreationType = letterOfCreditCreationType;
}
/**
* Gets the proposalNumber attribute.
*
* @return Returns the proposalNumber.
*/
public Long getProposalNumber() {
return proposalNumber;
}
/**
* Sets the proposalNumber attribute value.
*
* @param proposalNumber The proposalNumber to set.
*/
public void setProposalNumber(Long proposalNumber) {
this.proposalNumber = proposalNumber;
}
/**
* Gets the letterOfCreditFundGroupCode attribute.
*
* @return Returns the letterOfCreditFundGroupCode.
*/
public String getLetterOfCreditFundGroupCode() {
return letterOfCreditFundGroupCode;
}
/**
* Sets the letterOfCreditFundGroupCode attribute value.
*
* @param letterOfCreditFundGroupCode The letterOfCreditFundGroupCode to set.
*/
public void setLetterOfCreditFundGroupCode(String letterOfCreditFundGroupCode) {
this.letterOfCreditFundGroupCode = letterOfCreditFundGroupCode;
}
/**
* Gets the letterOfCreditFundCode attribute.
*
* @return Returns the letterOfCreditFundCode.
*/
public String getLetterOfCreditFundCode() {
return letterOfCreditFundCode;
}
/**
* Sets the letterOfCreditFundCode attribute value.
*
* @param letterOfCreditFundCode The letterOfCreditFundCode to set.
*/
public void setLetterOfCreditFundCode(String letterOfCreditFundCode) {
this.letterOfCreditFundCode = letterOfCreditFundCode;
}
public static AccountsReceivablePendingEntryService getAccountsReceivablePendingEntryService() {
if (accountsReceivablePendingEntryService == null) {
accountsReceivablePendingEntryService = SpringContext.getBean(AccountsReceivablePendingEntryService.class);
}
return accountsReceivablePendingEntryService;
}
}