/* * 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.sql.Timestamp; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.kuali.kfs.coa.businessobject.AccountingPeriod; import org.kuali.kfs.coa.service.AccountingPeriodService; import org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward; import org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAwardAccount; import org.kuali.kfs.integration.cg.ContractsAndGrantsBillingFrequency; import org.kuali.kfs.module.ar.ArConstants; import org.kuali.kfs.module.ar.ArPropertyConstants; import org.kuali.kfs.module.ar.batch.service.VerifyBillingFrequencyService; import org.kuali.kfs.module.ar.businessobject.*; import org.kuali.kfs.module.ar.document.ContractsGrantsInvoiceDocument; import org.kuali.kfs.module.ar.document.service.ContractsGrantsBillingAwardVerificationService; import org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService; import org.kuali.kfs.module.ar.document.service.CustomerService; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.document.service.FinancialSystemDocumentService; import org.kuali.kfs.sys.service.OptionsService; import org.kuali.kfs.sys.service.UniversityDateService; 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.service.KualiModuleService; import org.kuali.rice.krad.util.ObjectUtils; public class ContractsGrantsBillingAwardVerificationServiceImpl implements ContractsGrantsBillingAwardVerificationService { protected AccountingPeriodService accountingPeriodService; protected BusinessObjectService businessObjectService; protected ContractsGrantsInvoiceDocumentService contractsGrantsInvoiceDocumentService; protected CustomerService customerService; protected FinancialSystemDocumentService financialSystemDocumentService; protected KualiModuleService kualiModuleService; protected ParameterService parameterService; protected VerifyBillingFrequencyService verifyBillingFrequencyService; protected UniversityDateService universityDateService; protected OptionsService optionsService; /** * Check if Billing Frequency is set correctly. * * @param award * @return False if billing frequency code is blank, or set as predetermined billing schedule or milestone billing schedule * and award has no award account or more than 1 award accounts assigned. */ @Override public boolean isBillingFrequencySetCorrectly(ContractsAndGrantsBillingAward award) { if (StringUtils.isBlank(award.getBillingFrequencyCode()) || ((award.getBillingFrequencyCode().equalsIgnoreCase(ArConstants.PREDETERMINED_BILLING_SCHEDULE_CODE) || award.getBillingFrequencyCode().equalsIgnoreCase(ArConstants.MILESTONE_BILLING_SCHEDULE_CODE)) && award.getActiveAwardAccounts().size() != 1)) { return false; } return true; } /** * Check if the value of the billing frequency code is in the BillingFrequency value set. * * @param award * @return */ @Override public boolean isValueOfBillingFrequencyValid(ContractsAndGrantsBillingAward award) { if (!StringUtils.isBlank(award.getBillingFrequencyCode())) { Map<String, Object> criteria = new HashMap<String, Object>(); criteria.put(KFSPropertyConstants.FREQUENCY, award.getBillingFrequencyCode()); criteria.put(KFSPropertyConstants.ACTIVE, true); Collection<ContractsAndGrantsBillingFrequency> matchingBillingFrequencies = kualiModuleService.getResponsibleModuleService(ContractsAndGrantsBillingFrequency.class).getExternalizableBusinessObjectsList(ContractsAndGrantsBillingFrequency.class, criteria); if (matchingBillingFrequencies != null && matchingBillingFrequencies.size() > 0) { return true; } } return false; } /** * @see org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService#isAwardFinalInvoiceAlreadyBuilt(org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward) */ @Override public boolean isAwardFinalInvoiceAlreadyBuilt(ContractsAndGrantsBillingAward award) { for (ContractsAndGrantsBillingAwardAccount awardAccount : award.getActiveAwardAccounts()) { if (awardAccount.isFinalBilledIndicator()) { return true; } } return false; } /** * this method checks If all accounts of award has invoices in progress. * @param award * @return */ @Override public boolean isInvoiceInProgress(ContractsAndGrantsBillingAward award) { Map<String, Object> fieldValues = new HashMap<>(); fieldValues.put(ArPropertyConstants.ContractsGrantsInvoiceDocumentFields.PROPOSAL_NUMBER, award.getProposalNumber()); fieldValues.put(KFSPropertyConstants.DOCUMENT_HEADER+"."+KFSPropertyConstants.WORKFLOW_DOCUMENT_STATUS_CODE, getFinancialSystemDocumentService().getPendingDocumentStatuses()); return getBusinessObjectService().countMatching(ContractsGrantsInvoiceDocument.class, fieldValues) > 0; } /** * @see org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService#hasNoMilestonesToInvoice(org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward) */ @Override public boolean hasMilestonesToInvoice(ContractsAndGrantsBillingAward award) { boolean hasMilestonesToInvoice = true; if (award.getBillingFrequencyCode().equalsIgnoreCase(ArConstants.MILESTONE_BILLING_SCHEDULE_CODE)) { List<Milestone> milestones = new ArrayList<Milestone>(); List<Milestone> validMilestones = new ArrayList<Milestone>(); Map<String, Object> map = new HashMap<String, Object>(); map.put(KFSPropertyConstants.PROPOSAL_NUMBER, award.getProposalNumber()); map.put(KFSPropertyConstants.ACTIVE, true); milestones = (List<Milestone>) businessObjectService.findMatching(Milestone.class, map); // To retrieve the previous period end Date to check for milestones and billing schedule. Timestamp ts = new Timestamp(new java.util.Date().getTime()); java.sql.Date today = new java.sql.Date(ts.getTime()); AccountingPeriod currPeriod = accountingPeriodService.getByDate(today); BillingPeriod billingPeriod = verifyBillingFrequencyService.getStartDateAndEndDateOfPreviousBillingPeriod(award, currPeriod); java.sql.Date invoiceDate = billingPeriod.getEndDate(); for (Milestone awdMilestone : milestones) { if (awdMilestone.getMilestoneActualCompletionDate() != null && !invoiceDate.before(awdMilestone.getMilestoneActualCompletionDate()) && !awdMilestone.isBilled() && awdMilestone.getMilestoneAmount().isGreaterThan(KualiDecimal.ZERO)) { validMilestones.add(awdMilestone); } } if (CollectionUtils.isEmpty(validMilestones)) { hasMilestonesToInvoice = false; } } return hasMilestonesToInvoice; } /** * @see org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService#hasNoBillsToInvoice(org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward) */ @Override public boolean hasBillsToInvoice(ContractsAndGrantsBillingAward award) { boolean hasBillsToInvoice = true; if (award.getBillingFrequencyCode().equalsIgnoreCase(ArConstants.PREDETERMINED_BILLING_SCHEDULE_CODE)) { List<Bill> bills = new ArrayList<Bill>(); List<Bill> validBills = new ArrayList<Bill>(); Map<String, Object> map = new HashMap<String, Object>(); map.put(KFSPropertyConstants.PROPOSAL_NUMBER, award.getProposalNumber()); map.put(KFSPropertyConstants.ACTIVE, true); bills = (List<Bill>) businessObjectService.findMatching(Bill.class, map); // To retrieve the previous period end Date to check for milestones and billing schedule. Timestamp ts = new Timestamp(new java.util.Date().getTime()); java.sql.Date today = new java.sql.Date(ts.getTime()); AccountingPeriod currPeriod = accountingPeriodService.getByDate(today); BillingPeriod billingPeriod = verifyBillingFrequencyService.getStartDateAndEndDateOfPreviousBillingPeriod(award, currPeriod); java.sql.Date invoiceDate = billingPeriod.getEndDate(); for (Bill awdBill : bills) { if (awdBill.getBillDate() != null && !invoiceDate.before(awdBill.getBillDate()) && !awdBill.isBilled() && awdBill.getEstimatedAmount().isGreaterThan(KualiDecimal.ZERO)) { validBills.add(awdBill); } } if (CollectionUtils.isEmpty(validBills)) { hasBillsToInvoice = false; } } return hasBillsToInvoice; } /** * @see org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService#owningAgencyHasNoCustomerRecord(org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward) */ @Override public boolean owningAgencyHasCustomerRecord(ContractsAndGrantsBillingAward award) { boolean isValid = true; if (ObjectUtils.isNotNull(award.getAgency().getCustomerNumber())) { Customer customer = customerService.getByPrimaryKey(award.getAgency().getCustomerNumber()); return !ObjectUtils.isNull(customer); } return false; } /** * This method checks if the System Information and ORganization Accounting Default are setup for the Chart Code and Org Code * from the award accounts. * * @param award * @return */ @Override public boolean isChartAndOrgSetupForInvoicing(ContractsAndGrantsBillingAward award) { String coaCode = award.getPrimaryAwardOrganization().getChartOfAccountsCode(); String orgCode = award.getPrimaryAwardOrganization().getOrganizationCode(); String procCoaCode = null, procOrgCode = null; Integer currentYear = universityDateService.getCurrentFiscalYear(); Map<String, Object> criteria = new HashMap<String, Object>(); Map<String, Object> sysCriteria = new HashMap<String, Object>(); criteria.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, currentYear); sysCriteria.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, currentYear); criteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, coaCode); criteria.put(KFSPropertyConstants.ORGANIZATION_CODE, orgCode); // To retrieve processing codes based on billing codes using organization options List<String> procCodes = getContractsGrantsInvoiceDocumentService().getProcessingFromBillingCodes(coaCode, orgCode); if (!CollectionUtils.isEmpty(procCodes) && procCodes.size() > 1) { sysCriteria.put(ArPropertyConstants.OrganizationAccountingDefaultFields.PROCESSING_CHART_OF_ACCOUNTS_CODE, procCodes.get(0)); sysCriteria.put(ArPropertyConstants.OrganizationAccountingDefaultFields.PROCESSING_ORGANIZATION_CODE, procCodes.get(1)); OrganizationAccountingDefault organizationAccountingDefault = businessObjectService.findByPrimaryKey(OrganizationAccountingDefault.class, criteria); SystemInformation systemInformation = businessObjectService.findByPrimaryKey(SystemInformation.class, sysCriteria); if (ObjectUtils.isNotNull(organizationAccountingDefault) && ObjectUtils.isNotNull(systemInformation)) { return true; } } return false; } public AccountingPeriodService getAccountingPeriodService() { return accountingPeriodService; } public void setAccountingPeriodService(AccountingPeriodService accountingPeriodService) { this.accountingPeriodService = accountingPeriodService; } public BusinessObjectService getBusinessObjectService() { return businessObjectService; } public void setBusinessObjectService(BusinessObjectService businessObjectService) { this.businessObjectService = businessObjectService; } public ContractsGrantsInvoiceDocumentService getContractsGrantsInvoiceDocumentService() { return contractsGrantsInvoiceDocumentService; } public void setContractsGrantsInvoiceDocumentService(ContractsGrantsInvoiceDocumentService contractsGrantsInvoiceDocumentService) { this.contractsGrantsInvoiceDocumentService = contractsGrantsInvoiceDocumentService; } public CustomerService getCustomerService() { return customerService; } public void setCustomerService(CustomerService customerService) { this.customerService = customerService; } public FinancialSystemDocumentService getFinancialSystemDocumentService() { return financialSystemDocumentService; } public void setFinancialSystemDocumentService(FinancialSystemDocumentService financialSystemDocumentService) { this.financialSystemDocumentService = financialSystemDocumentService; } public KualiModuleService getKualiModuleService() { return kualiModuleService; } public void setKualiModuleService(KualiModuleService kualiModuleService) { this.kualiModuleService = kualiModuleService; } public ParameterService getParameterService() { return parameterService; } public void setParameterService(ParameterService parameterService) { this.parameterService = parameterService; } public VerifyBillingFrequencyService getVerifyBillingFrequencyService() { return verifyBillingFrequencyService; } public void setVerifyBillingFrequencyService(VerifyBillingFrequencyService verifyBillingFrequencyService) { this.verifyBillingFrequencyService = verifyBillingFrequencyService; } public UniversityDateService getUniversityDateService() { return universityDateService; } public void setUniversityDateService(UniversityDateService universityDateService) { this.universityDateService = universityDateService; } public OptionsService getOptionsService() { return optionsService; } public void setOptionsService(OptionsService optionsService) { this.optionsService = optionsService; } }