/* * 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.math.BigDecimal; 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.module.ar.ArConstants; import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail; import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceItemCode; import org.kuali.kfs.module.ar.businessobject.OrganizationAccountingDefault; import org.kuali.kfs.module.ar.businessobject.SystemInformation; import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument; import org.kuali.kfs.module.ar.document.service.AccountsReceivablePendingEntryService; import org.kuali.kfs.module.ar.document.service.AccountsReceivableTaxService; import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService; import org.kuali.kfs.module.ar.document.service.InvoicePaidAppliedService; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.businessobject.ChartOrgHolder; import org.kuali.kfs.sys.service.FinancialSystemUserService; import org.kuali.kfs.sys.service.TaxService; 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.krad.service.BusinessObjectService; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.ObjectUtils; import org.springframework.cache.annotation.Cacheable; import org.springframework.transaction.annotation.Transactional; @Transactional public class CustomerInvoiceDetailServiceImpl implements CustomerInvoiceDetailService { protected AccountsReceivablePendingEntryService accountsReceivablePendingEntryService; protected DateTimeService dateTimeService; protected UniversityDateService universityDateService; protected BusinessObjectService businessObjectService; protected FinancialSystemUserService financialSystemUserService; protected ParameterService parameterService; protected InvoicePaidAppliedService invoicePaidAppliedService; protected AccountsReceivableTaxService accountsReceivableTaxService; protected TaxService taxService; /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#getAddCustomerInvoiceDetail(java.lang.Integer, * java.lang.String, java.lang.String) */ @Override public CustomerInvoiceDetail getCustomerInvoiceDetailFromOrganizationAccountingDefault(Integer universityFiscalYear, String chartOfAccountsCode, String organizationCode) { CustomerInvoiceDetail customerInvoiceDetail = new CustomerInvoiceDetail(); Map<String, Object> criteria = new HashMap<String, Object>(); criteria.put("universityFiscalYear", universityFiscalYear); criteria.put("chartOfAccountsCode", chartOfAccountsCode); criteria.put("organizationCode", organizationCode); OrganizationAccountingDefault organizationAccountingDefault = businessObjectService.findByPrimaryKey(OrganizationAccountingDefault.class, criteria); if (ObjectUtils.isNotNull(organizationAccountingDefault)) { customerInvoiceDetail.setChartOfAccountsCode(organizationAccountingDefault.getDefaultInvoiceChartOfAccountsCode()); customerInvoiceDetail.setAccountNumber(organizationAccountingDefault.getDefaultInvoiceAccountNumber()); customerInvoiceDetail.setSubAccountNumber(organizationAccountingDefault.getDefaultInvoiceSubAccountNumber()); customerInvoiceDetail.setFinancialObjectCode(organizationAccountingDefault.getDefaultInvoiceFinancialObjectCode()); customerInvoiceDetail.setFinancialSubObjectCode(organizationAccountingDefault.getDefaultInvoiceFinancialSubObjectCode()); customerInvoiceDetail.setProjectCode(organizationAccountingDefault.getDefaultInvoiceProjectCode()); customerInvoiceDetail.setOrganizationReferenceId(organizationAccountingDefault.getDefaultInvoiceOrganizationReferenceIdentifier()); } customerInvoiceDetail.setInvoiceItemTaxAmount(new KualiDecimal(0.00)); customerInvoiceDetail.setInvoiceItemQuantity(new BigDecimal(1)); customerInvoiceDetail.setInvoiceItemUnitOfMeasureCode(ArConstants.CUSTOMER_INVOICE_DETAIL_UOM_DEFAULT); // KULAR-448 customerInvoiceDetail.setInvoiceItemServiceDate(dateTimeService.getCurrentSqlDate()); customerInvoiceDetail.setTaxableIndicator(false); return customerInvoiceDetail; } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#getAddLineCustomerInvoiceDetailForCurrentUserAndYear() */ @Override public CustomerInvoiceDetail getCustomerInvoiceDetailFromOrganizationAccountingDefaultForCurrentYear() { Integer currentUniversityFiscalYear = universityDateService.getCurrentFiscalYear(); ChartOrgHolder currentUser = financialSystemUserService.getPrimaryOrganization(GlobalVariables.getUserSession().getPerson(), ArConstants.AR_NAMESPACE_CODE); return getCustomerInvoiceDetailFromOrganizationAccountingDefault(currentUniversityFiscalYear, currentUser.getChartOfAccountsCode(), currentUser.getOrganizationCode()); } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#getCustomerInvoiceDetailFromCustomerInvoiceItemCode(java.lang.String, * java.lang.String, java.lang.String) */ @Override public CustomerInvoiceDetail getCustomerInvoiceDetailFromCustomerInvoiceItemCode(String invoiceItemCode, String chartOfAccountsCode, String organizationCode) { Map<String, String> criteria = new HashMap<String, String>(); criteria.put("invoiceItemCode", invoiceItemCode); criteria.put("chartOfAccountsCode", chartOfAccountsCode); criteria.put("organizationCode", organizationCode); CustomerInvoiceItemCode customerInvoiceItemCode = businessObjectService.findByPrimaryKey(CustomerInvoiceItemCode.class, criteria); CustomerInvoiceDetail customerInvoiceDetail = null; if (ObjectUtils.isNotNull(customerInvoiceItemCode)) { customerInvoiceDetail = new CustomerInvoiceDetail(); customerInvoiceDetail.setChartOfAccountsCode(customerInvoiceItemCode.getDefaultInvoiceChartOfAccountsCode()); customerInvoiceDetail.setAccountNumber(customerInvoiceItemCode.getDefaultInvoiceAccountNumber()); customerInvoiceDetail.setSubAccountNumber(customerInvoiceItemCode.getDefaultInvoiceSubAccountNumber()); customerInvoiceDetail.setFinancialObjectCode(customerInvoiceItemCode.getDefaultInvoiceFinancialObjectCode()); customerInvoiceDetail.setFinancialSubObjectCode(customerInvoiceItemCode.getDefaultInvoiceFinancialSubObjectCode()); customerInvoiceDetail.setProjectCode(customerInvoiceItemCode.getDefaultInvoiceProjectCode()); customerInvoiceDetail.setOrganizationReferenceId(customerInvoiceItemCode.getDefaultInvoiceOrganizationReferenceIdentifier()); customerInvoiceDetail.setInvoiceItemCode(customerInvoiceItemCode.getInvoiceItemCode()); customerInvoiceDetail.setInvoiceItemDescription(customerInvoiceItemCode.getInvoiceItemDescription()); customerInvoiceDetail.setInvoiceItemUnitPrice(customerInvoiceItemCode.getItemDefaultPrice()); customerInvoiceDetail.setInvoiceItemUnitOfMeasureCode(customerInvoiceItemCode.getDefaultUnitOfMeasureCode()); customerInvoiceDetail.setInvoiceItemQuantity(customerInvoiceItemCode.getItemDefaultQuantity()); customerInvoiceDetail.setTaxableIndicator(customerInvoiceItemCode.isTaxableIndicator()); // KULAR-448 customerInvoiceDetail.setInvoiceItemServiceDate(dateTimeService.getCurrentSqlDate()); // TODO set sales tax accordingly customerInvoiceDetail.setInvoiceItemTaxAmount(new KualiDecimal(0.00)); // set amount = unit price * quantity customerInvoiceDetail.updateAmountBasedOnQuantityAndUnitPrice(); } return customerInvoiceDetail; } @Override public List<String> getCustomerInvoiceDocumentNumbersByAccountNumber(String accountNumber) { Map<String, String> fieldValues = new HashMap<String, String>(); fieldValues.put("accountNumber", accountNumber); Collection<CustomerInvoiceDetail> customerInvoiceDetails = businessObjectService.findMatching(CustomerInvoiceDetail.class, fieldValues); List<String> docNumbers = new ArrayList<String>(); for (CustomerInvoiceDetail detail : customerInvoiceDetails) { docNumbers.add(detail.getDocumentNumber()); } return docNumbers; } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#getCustomerInvoiceDetailFromCustomerInvoiceItemCodeForCurrentUser(java.lang.String) */ @Override public CustomerInvoiceDetail getCustomerInvoiceDetailFromCustomerInvoiceItemCodeForCurrentUser(String invoiceItemCode) { ChartOrgHolder currentUser = financialSystemUserService.getPrimaryOrganization(GlobalVariables.getUserSession().getPerson(), ArConstants.AR_NAMESPACE_CODE); return getCustomerInvoiceDetailFromCustomerInvoiceItemCode(invoiceItemCode, currentUser.getChartOfAccountsCode(), currentUser.getOrganizationCode()); } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#getDiscountCustomerInvoiceDetail(org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail, * java.lang.Integer, java.lang.String, java.lang.String) */ @Override public CustomerInvoiceDetail getDiscountCustomerInvoiceDetail(CustomerInvoiceDetail customerInvoiceDetail, Integer universityFiscalYear, String chartOfAccountsCode, String organizationCode) { CustomerInvoiceDetail discountCustomerInvoiceDetail = (CustomerInvoiceDetail) ObjectUtils.deepCopy(customerInvoiceDetail); discountCustomerInvoiceDetail.setInvoiceItemUnitPriceToNegative(); discountCustomerInvoiceDetail.updateAmountBasedOnQuantityAndUnitPrice(); discountCustomerInvoiceDetail.setInvoiceItemDescription(ArConstants.DISCOUNT_PREFIX + StringUtils.trimToEmpty(customerInvoiceDetail.getInvoiceItemDescription())); Map<String, Object> criteria = new HashMap<String, Object>(); criteria.put("universityFiscalYear", universityFiscalYear); criteria.put("processingChartOfAccountCode", chartOfAccountsCode); criteria.put("processingOrganizationCode", organizationCode); SystemInformation systemInformation = businessObjectService.findByPrimaryKey(SystemInformation.class, criteria); if (ObjectUtils.isNotNull(systemInformation)) { discountCustomerInvoiceDetail.setFinancialObjectCode(systemInformation.getDiscountObjectCode()); } return discountCustomerInvoiceDetail; } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#getDiscountCustomerInvoiceDetailForCurrentYear(org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail) */ @Override public CustomerInvoiceDetail getDiscountCustomerInvoiceDetailForCurrentYear(CustomerInvoiceDetail customerInvoiceDetail, CustomerInvoiceDocument customerInvoiceDocument) { Integer currentUniversityFiscalYear = universityDateService.getCurrentFiscalYear(); String processingChartOfAccountsCode = customerInvoiceDocument.getAccountsReceivableDocumentHeader().getProcessingChartOfAccountCode(); String processingOrganizationCode = customerInvoiceDocument.getAccountsReceivableDocumentHeader().getProcessingOrganizationCode(); return getDiscountCustomerInvoiceDetail(customerInvoiceDetail, currentUniversityFiscalYear, processingChartOfAccountsCode, processingOrganizationCode); } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#recalculateCustomerInvoiceDetail(org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail) */ @Override public void recalculateCustomerInvoiceDetail(CustomerInvoiceDocument customerInvoiceDocument, CustomerInvoiceDetail customerInvoiceDetail) { // make sure amounts are negative when they are supposed to be if (!customerInvoiceDocument.isInvoiceReversal() && customerInvoiceDetail.isDiscountLine()) { customerInvoiceDetail.setInvoiceItemUnitPriceToNegative(); } else if (customerInvoiceDocument.isInvoiceReversal() && !customerInvoiceDetail.isDiscountLine()) { customerInvoiceDetail.setInvoiceItemUnitPriceToNegative(); } KualiDecimal pretaxAmount = customerInvoiceDetail.getInvoiceItemPreTaxAmount(); KualiDecimal taxAmount = KualiDecimal.ZERO; if (accountsReceivableTaxService.isCustomerInvoiceDetailTaxable(customerInvoiceDocument, customerInvoiceDetail)) { String postalCode = accountsReceivableTaxService.getPostalCodeForTaxation(customerInvoiceDocument); taxAmount = taxService.getTotalSalesTaxAmount(dateTimeService.getCurrentSqlDate(), postalCode, pretaxAmount); } customerInvoiceDetail.setInvoiceItemTaxAmount(taxAmount); customerInvoiceDetail.setAmount(taxAmount.add(pretaxAmount)); } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#updateAccountsForCorrespondingDiscount(org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail) */ @Override public void updateAccountsForCorrespondingDiscount(CustomerInvoiceDetail parent) { CustomerInvoiceDetail discount = parent.getDiscountCustomerInvoiceDetail(); if (ObjectUtils.isNotNull(discount)) { if (StringUtils.isNotEmpty(parent.getAccountNumber())) { discount.setAccountNumber(parent.getAccountNumber()); } if (StringUtils.isNotEmpty(parent.getSubAccountNumber())) { discount.setSubAccountNumber(parent.getSubAccountNumber()); } } } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#getCustomerInvoiceDetail(java.lang.String, * java.lang.Integer) */ @Override @SuppressWarnings("unchecked") public CustomerInvoiceDetail getCustomerInvoiceDetail(String documentNumber, Integer sequenceNumber) { Map<String, String> criteria = new HashMap<String, String>(); criteria.put(KFSPropertyConstants.DOCUMENT_NUMBER, documentNumber); criteria.put("sequenceNumber", sequenceNumber.toString()); return businessObjectService.findByPrimaryKey(CustomerInvoiceDetail.class, criteria); } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#getCustomerInvoiceDetailsForInvoice(java.lang.String) */ @Override public Collection<CustomerInvoiceDetail> getCustomerInvoiceDetailsForInvoice(String customerInvoiceDocumentNumber) { Map<String, String> criteria = new HashMap<String, String>(); criteria.put(KFSPropertyConstants.DOCUMENT_NUMBER, customerInvoiceDocumentNumber); return businessObjectService.findMatching(CustomerInvoiceDetail.class, criteria); } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#getCustomerInvoiceDetailsForInvoiceWithCaching(java.lang.String) */ @Override @Cacheable(value=CustomerInvoiceDetail.CACHE_NAME, key="'{getCustomerInvoiceDetailsForInvoiceWithCaching}'+#p0") public Collection<CustomerInvoiceDetail> getCustomerInvoiceDetailsForInvoiceWithCaching(String customerInvoiceDocumentNumber) { Map<String, String> criteria = new HashMap<String, String>(); criteria.put(KFSPropertyConstants.DOCUMENT_NUMBER, customerInvoiceDocumentNumber); return businessObjectService.findMatching(CustomerInvoiceDetail.class, criteria); } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#getCustomerInvoiceDetailsForInvoice(org.kuali.kfs.module.ar.document.CustomerInvoiceDocument) */ @Override public Collection<CustomerInvoiceDetail> getCustomerInvoiceDetailsForInvoice(CustomerInvoiceDocument customerInvoiceDocument) { if (null == customerInvoiceDocument) { return new ArrayList<CustomerInvoiceDetail>(); } return getCustomerInvoiceDetailsForInvoice(customerInvoiceDocument.getDocumentNumber()); } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#updateAccountsReceivableObjectCode(org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail) */ @Override public void updateAccountsReceivableObjectCode(CustomerInvoiceDetail customerInvoiceDetail) { customerInvoiceDetail.setAccountsReceivableObjectCode(getAccountsReceivablePendingEntryService().getAccountsReceivableObjectCode(customerInvoiceDetail)); } /** * @see org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService#prepareCustomerInvoiceDetailForAdd(org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail, * org.kuali.kfs.module.ar.document.CustomerInvoiceDocument) */ @Override public void prepareCustomerInvoiceDetailForAdd(CustomerInvoiceDetail customerInvoiceDetail, CustomerInvoiceDocument customerInvoiceDocument) { recalculateCustomerInvoiceDetail(customerInvoiceDocument, customerInvoiceDetail); updateAccountsReceivableObjectCode(customerInvoiceDetail); } public DateTimeService getDateTimeService() { return dateTimeService; } public void setDateTimeService(DateTimeService dateTimeService) { this.dateTimeService = dateTimeService; } public UniversityDateService getUniversityDateService() { return universityDateService; } public void setUniversityDateService(UniversityDateService universityDateService) { this.universityDateService = universityDateService; } public BusinessObjectService getBusinessObjectService() { return businessObjectService; } public void setBusinessObjectService(BusinessObjectService businessObjectService) { this.businessObjectService = businessObjectService; } public ParameterService getParameterService() { return parameterService; } public void setParameterService(ParameterService parameterService) { this.parameterService = parameterService; } /** * @param invoicePaidAppliedService */ public void setInvoicePaidAppliedService(InvoicePaidAppliedService invoicePaidAppliedService) { this.invoicePaidAppliedService = invoicePaidAppliedService; } public InvoicePaidAppliedService getInvoicePaidAppliedService() { return invoicePaidAppliedService; } public TaxService getTaxService() { return taxService; } public void setTaxService(TaxService taxService) { this.taxService = taxService; } public AccountsReceivableTaxService getAccountsReceivableTaxService() { return accountsReceivableTaxService; } public void setAccountsReceivableTaxService(AccountsReceivableTaxService accountsReceivableTaxService) { this.accountsReceivableTaxService = accountsReceivableTaxService; } public FinancialSystemUserService getFinancialSystemUserService() { return financialSystemUserService; } public void setFinancialSystemUserService(FinancialSystemUserService financialSystemUserService) { this.financialSystemUserService = financialSystemUserService; } public AccountsReceivablePendingEntryService getAccountsReceivablePendingEntryService() { return accountsReceivablePendingEntryService; } public void setAccountsReceivablePendingEntryService(AccountsReceivablePendingEntryService accountsReceivablePendingEntryService) { this.accountsReceivablePendingEntryService = accountsReceivablePendingEntryService; } }