/*
* 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.service.impl;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.kuali.kfs.module.ar.businessobject.AccountsReceivableDocumentHeader;
import org.kuali.kfs.module.ar.businessobject.AppliedPayment;
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.NonAppliedHolding;
import org.kuali.kfs.module.ar.document.CashControlDocument;
import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument;
import org.kuali.kfs.module.ar.document.PaymentApplicationDocument;
import org.kuali.kfs.module.ar.document.dataaccess.CashControlDetailDao;
import org.kuali.kfs.module.ar.document.service.CustomerAddressService;
import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService;
import org.kuali.kfs.module.ar.document.service.InvoicePaidAppliedService;
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.service.UniversityDateService;
import org.kuali.rice.core.api.config.property.ConfigurationService;
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.kim.api.identity.PersonService;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.service.DocumentService;
import org.kuali.rice.krad.service.KualiRuleService;
import org.springframework.transaction.annotation.Transactional;
/**
* Service method implementations for Payment Application Document.
*/
@Transactional
public class PaymentApplicationDocumentServiceImpl implements PaymentApplicationDocumentService {
private static Logger LOG = org.apache.log4j.Logger.getLogger(PaymentApplicationDocumentServiceImpl.class);;
private DocumentService documentService;
private BusinessObjectService businessObjectService;
private NonAppliedHoldingService nonAppliedHoldingService;
private InvoicePaidAppliedService<AppliedPayment> invoicePaidAppliedService;
private UniversityDateService universityDateService;
private CashControlDetailDao cashControlDetailDao;
private ConfigurationService kualiConfigurationService;
private SystemInformationService systemInformationService;
private CustomerAddressService customerAddressService;
private ParameterService parameterService;
private PersonService personService;
private CustomerInvoiceDocumentService customerInvoiceDocumentService;
private KualiRuleService kualiRuleService;
/**
*
* @param customerInvoiceDocument
* @return
* @throws WorkflowException
*/
@Override
public PaymentApplicationDocument createPaymentApplicationToMatchInvoice(CustomerInvoiceDocument customerInvoiceDocument) throws WorkflowException {
PaymentApplicationDocument applicationDocument = (PaymentApplicationDocument) documentService.getNewDocument(PaymentApplicationDocument.class);
// get the processing chart & org off the invoice, we'll create the payapp with the same processing org
String processingChartCode = customerInvoiceDocument.getAccountsReceivableDocumentHeader().getProcessingChartOfAccountCode();
String processingOrgCode = customerInvoiceDocument.getAccountsReceivableDocumentHeader().getProcessingOrganizationCode();
AccountsReceivableDocumentHeader arDocHeader = new AccountsReceivableDocumentHeader();
arDocHeader.setProcessingChartOfAccountCode(processingChartCode);
arDocHeader.setProcessingOrganizationCode(processingOrgCode);
arDocHeader.setDocumentNumber(applicationDocument.getDocumentNumber());
applicationDocument.setAccountsReceivableDocumentHeader(arDocHeader);
// This code is basically copied from PaymentApplicationDocumentAction.quickApply
int paidAppliedItemNumber = 1;
for (CustomerInvoiceDetail customerInvoiceDetail : customerInvoiceDocument.getCustomerInvoiceDetailsWithoutDiscounts()) {
InvoicePaidApplied invoicePaidApplied = createInvoicePaidAppliedForInvoiceDetail(customerInvoiceDetail, applicationDocument, paidAppliedItemNumber);
// if there was not another invoice paid applied already created for the current detail then invoicePaidApplied will not
// be null
if (invoicePaidApplied != null) {
// add it to the payment application document list of applied payments
applicationDocument.getInvoicePaidApplieds().add(invoicePaidApplied);
paidAppliedItemNumber++;
}
}
return applicationDocument;
}
/**
* @param customerInvoiceDocument
* @return
* @throws WorkflowException
*/
@Override
public PaymentApplicationDocument createAndSavePaymentApplicationToMatchInvoice(CustomerInvoiceDocument customerInvoiceDocument) throws WorkflowException {
PaymentApplicationDocument applicationDocument = createPaymentApplicationToMatchInvoice(customerInvoiceDocument);
documentService.saveDocument(applicationDocument);
return applicationDocument;
}
/**
* @param customerInvoiceDocument
* @param approvalAnnotation
* @param workflowNotificationRecipients
* @return
* @throws WorkflowException
*/
@Override
public PaymentApplicationDocument createSaveAndApprovePaymentApplicationToMatchInvoice(CustomerInvoiceDocument customerInvoiceDocument, String approvalAnnotation, List workflowNotificationRecipients) throws WorkflowException {
PaymentApplicationDocument applicationDocument = createAndSavePaymentApplicationToMatchInvoice(customerInvoiceDocument);
documentService.approveDocument(applicationDocument, approvalAnnotation, workflowNotificationRecipients);
return applicationDocument;
}
/**
* @param document
* @return
*/
public KualiDecimal getTotalAppliedAmountForPaymentApplicationDocument(PaymentApplicationDocument document) {
KualiDecimal total = KualiDecimal.ZERO;
Collection<InvoicePaidApplied> invoicePaidApplieds = document.getInvoicePaidApplieds();
for (InvoicePaidApplied invoicePaidApplied : invoicePaidApplieds) {
total = total.add(invoicePaidApplied.getInvoiceItemAppliedAmount());
}
// Include non-ar funds as well
total = total.add(document.getSumOfNonInvoiceds());
return total;
}
/**
* @param document
* @return
*/
public KualiDecimal getTotalUnappliedFundsForPaymentApplicationDocument(PaymentApplicationDocument document) {
KualiDecimal total = KualiDecimal.ZERO;
String customerNumber = document.getAccountsReceivableDocumentHeader().getCustomerNumber();
Collection<NonAppliedHolding> nonAppliedHoldings = nonAppliedHoldingService.getNonAppliedHoldingsForCustomer(customerNumber);
for (NonAppliedHolding nonAppliedHolding : nonAppliedHoldings) {
total = total.add(nonAppliedHolding.getFinancialDocumentLineAmount());
}
// Add the amount for this document, if it's set
NonAppliedHolding nonAppliedHolding = document.getNonAppliedHolding();
if (null != nonAppliedHolding) {
KualiDecimal amount = nonAppliedHolding.getFinancialDocumentLineAmount();
if (null != amount) {
total = total.add(amount);
}
}
return total;
}
/**
* @param document
* @return
*/
public KualiDecimal getTotalUnappliedFundsToBeAppliedForPaymentApplicationDocument(PaymentApplicationDocument document) {
KualiDecimal totalUnapplied = getTotalUnappliedFundsForPaymentApplicationDocument(document);
KualiDecimal totalApplied = getTotalAppliedAmountForPaymentApplicationDocument(document);
return totalUnapplied.subtract(totalApplied);
}
/**
*
* @see org.kuali.kfs.module.ar.document.service.PaymentApplicationDocumentService#getCashControlDocumentForPaymentApplicationDocument(org.kuali.kfs.module.ar.document.PaymentApplicationDocument)
*/
@Override
public CashControlDocument getCashControlDocumentForPaymentApplicationDocument(PaymentApplicationDocument paymentApplicationDocument) {
if (paymentApplicationDocument == null) {
throw new IllegalArgumentException("A null paymentApplicationDocument parameter was passed in.");
}
String payAppDocNumber = paymentApplicationDocument.getDocumentHeader().getDocumentNumber();
return getCashControlDocumentForPayAppDocNumber(payAppDocNumber);
}
/**
*
* @see org.kuali.kfs.module.ar.document.service.PaymentApplicationDocumentService#getCashControlDocumentForPayAppDocNumber(java.lang.String)
*/
@Override
public CashControlDocument getCashControlDocumentForPayAppDocNumber(String paymentApplicationDocumentNumber) {
if (StringUtils.isBlank(paymentApplicationDocumentNumber)) {
throw new IllegalArgumentException("A null or blank paymentApplicationDocumentNumber paraemter was passed in.");
}
CashControlDetail cashControlDetail = getCashControlDetailForPayAppDocNumber(paymentApplicationDocumentNumber);
if (cashControlDetail == null) {
return null;
}
CashControlDocument cashControlDocument = null;
try {
cashControlDocument = (CashControlDocument) documentService.getByDocumentHeaderId(cashControlDetail.getDocumentNumber());
}
catch (WorkflowException e) {
// TODO we may need to swallow this ...
throw new RuntimeException("A workflow exception was thrown when trying to retrieve document [" + cashControlDetail.getDocumentNumber() + "].", e);
}
return cashControlDocument;
}
/**
* @see org.kuali.kfs.module.ar.document.service.PaymentApplicationDocumentService#getCashControlDetailForPaymentApplicationDocument(org.kuali.kfs.module.ar.document.PaymentApplicationDocument)
*/
@Override
public CashControlDetail getCashControlDetailForPaymentApplicationDocument(PaymentApplicationDocument document) {
if (document == null) {
throw new IllegalArgumentException("A null paymentApplicationDocument parameter was passed in.");
}
String payAppDocumentNumber = document.getDocumentNumber();
CashControlDetail cashControlDetail = getCashControlDetailForPayAppDocNumber(payAppDocumentNumber);
return cashControlDetail;
}
/**
*
* @see org.kuali.kfs.module.ar.document.service.PaymentApplicationDocumentService#getCashControlDetailForPayAppDocNumber(java.lang.String)
*/
@Override
public CashControlDetail getCashControlDetailForPayAppDocNumber(String payAppDocNumber) {
if (StringUtils.isBlank(payAppDocNumber)) {
throw new IllegalArgumentException("A null or blank payAppDocNumber parameter was passed in.");
}
CashControlDetail cashControlDetail = cashControlDetailDao.getCashControlDetailByRefDocNumber(payAppDocNumber);
return cashControlDetail;
}
/**
* @param businessObjectService
*/
public void setBusinessObjectService(BusinessObjectService businessObjectService) {
this.businessObjectService = businessObjectService;
}
/**
* @see org.kuali.kfs.module.ar.document.service.PaymentApplicationDocumentService#createInvoicePaidAppliedsForEntireInvoiceDocument(org.kuali.kfs.module.ar.document.CustomerInvoiceDocument,
* org.kuali.kfs.module.ar.document.PaymentApplicationDocument)
*/
@Override
public PaymentApplicationDocument createInvoicePaidAppliedsForEntireInvoiceDocument(CustomerInvoiceDocument customerInvoiceDocument, PaymentApplicationDocument paymentApplicationDocument) {
// clear any existing paidapplieds
paymentApplicationDocument.getInvoicePaidApplieds().clear();
int paidAppliedItemNumber = 1;
for (CustomerInvoiceDetail detail : customerInvoiceDocument.getCustomerInvoiceDetailsWithoutDiscounts()) {
// create the new paidapplied
InvoicePaidApplied invoicePaidApplied = createInvoicePaidAppliedForInvoiceDetail(detail, paymentApplicationDocument, paidAppliedItemNumber);
// add it to the payment application document list of applied payments
paymentApplicationDocument.getInvoicePaidApplieds().add(invoicePaidApplied);
paidAppliedItemNumber++;
}
return paymentApplicationDocument;
}
/**
* @see org.kuali.kfs.module.ar.document.service.PaymentApplicationDocumentService#createInvoicePaidAppliedForInvoiceDetail(org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail,
* org.kuali.rice.core.api.util.type.KualiDecimal)
*/
@Override
public InvoicePaidApplied createInvoicePaidAppliedForInvoiceDetail(CustomerInvoiceDetail customerInvoiceDetail, PaymentApplicationDocument paymentApplicationDocument, Integer paidAppliedItemNumber) {
Integer universityFiscalYear = universityDateService.getCurrentFiscalYear();
String universityFiscalPeriodCode = universityDateService.getCurrentUniversityDate().getAccountingPeriod().getUniversityFiscalPeriodCode();
InvoicePaidApplied invoicePaidApplied = new InvoicePaidApplied();
// set the document number for the invoice paid applied to the payment application document number.
invoicePaidApplied.setDocumentNumber(paymentApplicationDocument.getDocumentNumber());
// Set the invoice paid applied ref doc number to the document number for the customer invoice document
invoicePaidApplied.setFinancialDocumentReferenceInvoiceNumber(customerInvoiceDetail.getDocumentNumber());
invoicePaidApplied.setInvoiceItemNumber(customerInvoiceDetail.getSequenceNumber());
invoicePaidApplied.setInvoiceItemAppliedAmount(customerInvoiceDetail.getAmountOpen());
invoicePaidApplied.setUniversityFiscalYear(universityFiscalYear);
invoicePaidApplied.setUniversityFiscalPeriodCode(universityFiscalPeriodCode);
invoicePaidApplied.setPaidAppliedItemNumber(paidAppliedItemNumber);
return invoicePaidApplied;
}
/**
* @see org.kuali.kfs.module.ar.document.service.PaymentApplicationDocumentService#customerInvoiceDetailPairsWithInvoicePaidApplied(org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail,
* org.kuali.kfs.module.ar.businessobject.InvoicePaidApplied)
*/
@Override
public boolean customerInvoiceDetailPairsWithInvoicePaidApplied(CustomerInvoiceDetail customerInvoiceDetail, InvoicePaidApplied invoicePaidApplied) {
boolean pairs = true;
pairs &= customerInvoiceDetail.getSequenceNumber().equals(invoicePaidApplied.getInvoiceItemNumber());
pairs &= customerInvoiceDetail.getDocumentNumber().equals(invoicePaidApplied.getFinancialDocumentReferenceInvoiceNumber());
return pairs;
}
public DocumentService getDocumentService() {
return documentService;
}
public void setDocumentService(DocumentService documentService) {
this.documentService = documentService;
}
public void setInvoicePaidAppliedService(InvoicePaidAppliedService invoicePaidAppliedService) {
this.invoicePaidAppliedService = invoicePaidAppliedService;
}
public BusinessObjectService getBusinessObjectService() {
return businessObjectService;
}
public NonAppliedHoldingService getNonAppliedHoldingService() {
return nonAppliedHoldingService;
}
public void setNonAppliedHoldingService(NonAppliedHoldingService nonAppliedHoldingService) {
this.nonAppliedHoldingService = nonAppliedHoldingService;
}
public void setUniversityDateService(UniversityDateService universityDateService) {
this.universityDateService = universityDateService;
}
public void setCashControlDetailDao(CashControlDetailDao cashControlDetailDao) {
this.cashControlDetailDao = cashControlDetailDao;
}
public ConfigurationService getKualiConfigurationService() {
return kualiConfigurationService;
}
public void setKualiConfigurationService(ConfigurationService kualiConfigurationService) {
this.kualiConfigurationService = kualiConfigurationService;
}
protected SystemInformationService getSystemInformationService() {
return systemInformationService;
}
public void setSystemInformationService(SystemInformationService systemInformationService) {
this.systemInformationService = systemInformationService;
}
protected CustomerAddressService getCustomerAddressService() {
return customerAddressService;
}
public void setCustomerAddressService(CustomerAddressService customerAddressService) {
this.customerAddressService = customerAddressService;
}
protected ParameterService getParameterService() {
return parameterService;
}
public void setParameterService(ParameterService parameterService) {
this.parameterService = parameterService;
}
public PersonService getPersonService() {
return personService;
}
public void setPersonService(PersonService personService) {
this.personService = personService;
}
public void setCustomerInvoiceDocumentService(CustomerInvoiceDocumentService customerInvoiceDocumentService) {
this.customerInvoiceDocumentService = customerInvoiceDocumentService;
}
public void setKualiRuleService(KualiRuleService ruleService) {
this.kualiRuleService = ruleService;
}
}