View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    * 
4    * Copyright 2005-2014 The Kuali Foundation
5    * 
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   * 
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.kfs.module.ar.document.service.impl;
20  
21  import java.sql.Timestamp;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.commons.collections.CollectionUtils;
29  import org.apache.commons.lang.StringUtils;
30  import org.kuali.kfs.coa.businessobject.AccountingPeriod;
31  import org.kuali.kfs.coa.service.AccountingPeriodService;
32  import org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward;
33  import org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAwardAccount;
34  import org.kuali.kfs.integration.cg.ContractsAndGrantsBillingFrequency;
35  import org.kuali.kfs.module.ar.ArConstants;
36  import org.kuali.kfs.module.ar.ArPropertyConstants;
37  import org.kuali.kfs.module.ar.batch.service.VerifyBillingFrequencyService;
38  import org.kuali.kfs.module.ar.businessobject.Bill;
39  import org.kuali.kfs.module.ar.businessobject.Customer;
40  import org.kuali.kfs.module.ar.businessobject.Milestone;
41  import org.kuali.kfs.module.ar.businessobject.OrganizationAccountingDefault;
42  import org.kuali.kfs.module.ar.businessobject.SystemInformation;
43  import org.kuali.kfs.module.ar.document.ContractsGrantsInvoiceDocument;
44  import org.kuali.kfs.module.ar.document.service.ContractsGrantsBillingAwardVerificationService;
45  import org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService;
46  import org.kuali.kfs.module.ar.document.service.CustomerService;
47  import org.kuali.kfs.sys.KFSPropertyConstants;
48  import org.kuali.kfs.sys.document.service.FinancialSystemDocumentService;
49  import org.kuali.kfs.sys.service.OptionsService;
50  import org.kuali.kfs.sys.service.UniversityDateService;
51  import org.kuali.rice.core.api.util.type.KualiDecimal;
52  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
53  import org.kuali.rice.krad.service.BusinessObjectService;
54  import org.kuali.rice.krad.service.KualiModuleService;
55  import org.kuali.rice.krad.util.ObjectUtils;
56  
57  public class ContractsGrantsBillingAwardVerificationServiceImpl implements ContractsGrantsBillingAwardVerificationService {
58      protected AccountingPeriodService accountingPeriodService;
59      protected BusinessObjectService businessObjectService;
60      protected ContractsGrantsInvoiceDocumentService contractsGrantsInvoiceDocumentService;
61      protected CustomerService customerService;
62      protected FinancialSystemDocumentService financialSystemDocumentService;
63      protected KualiModuleService kualiModuleService;
64      protected ParameterService parameterService;
65      protected VerifyBillingFrequencyService verifyBillingFrequencyService;
66      protected UniversityDateService universityDateService;
67      protected OptionsService optionsService;
68  
69      /**
70       * Check if Billing Frequency is set correctly.
71       *
72       * @param award
73       * @return False if billing frequency code is blank, or set as predetermined billing schedule or milestone billing schedule
74       *         and award has no award account or more than 1 award accounts assigned.
75       */
76      @Override
77      public boolean isBillingFrequencySetCorrectly(ContractsAndGrantsBillingAward award) {
78  
79          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)) {
80              return false;
81          }
82          return true;
83      }
84  
85  
86      /**
87       * Check if the value of the billing frequency code is in the BillingFrequency value set.
88       *
89       * @param award
90       * @return
91       */
92      @Override
93      public boolean isValueOfBillingFrequencyValid(ContractsAndGrantsBillingAward award) {
94          if (!StringUtils.isBlank(award.getBillingFrequencyCode())) {
95              Map<String, Object> criteria = new HashMap<String, Object>();
96              criteria.put(KFSPropertyConstants.FREQUENCY, award.getBillingFrequencyCode());
97              criteria.put(KFSPropertyConstants.ACTIVE, true);
98              Collection<ContractsAndGrantsBillingFrequency> matchingBillingFrequencies = kualiModuleService.getResponsibleModuleService(ContractsAndGrantsBillingFrequency.class).getExternalizableBusinessObjectsList(ContractsAndGrantsBillingFrequency.class, criteria);
99  
100             if (matchingBillingFrequencies != null && matchingBillingFrequencies.size() > 0) {
101                 return true;
102             }
103         }
104 
105         return false;
106     }
107 
108 
109 
110     /**
111      * @see org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService#isAwardFinalInvoiceAlreadyBuilt(org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward)
112      */
113     @Override
114     public boolean isAwardFinalInvoiceAlreadyBuilt(ContractsAndGrantsBillingAward award) {
115         for (ContractsAndGrantsBillingAwardAccount awardAccount : award.getActiveAwardAccounts()) {
116             if (awardAccount.isFinalBilledIndicator()) {
117                 return true;
118             }
119         }
120 
121         return false;
122     }
123 
124     /**
125      * this method checks If all accounts of award has invoices in progress.
126      * @param award
127      * @return
128      */
129     @Override
130     public boolean isInvoiceInProgress(ContractsAndGrantsBillingAward award) {
131         Map<String, Object> fieldValues = new HashMap<>();
132         fieldValues.put(ArPropertyConstants.ContractsGrantsInvoiceDocumentFields.PROPOSAL_NUMBER, award.getProposalNumber());
133         fieldValues.put(KFSPropertyConstants.DOCUMENT_HEADER+"."+KFSPropertyConstants.WORKFLOW_DOCUMENT_STATUS_CODE, getFinancialSystemDocumentService().getPendingDocumentStatuses());
134 
135         return getBusinessObjectService().countMatching(ContractsGrantsInvoiceDocument.class, fieldValues) > 0;
136     }
137 
138     /**
139      * @see org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService#hasNoMilestonesToInvoice(org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward)
140      */
141     @Override
142     public boolean hasMilestonesToInvoice(ContractsAndGrantsBillingAward award) {
143         boolean hasMilestonesToInvoice = true;
144         if (award.getBillingFrequencyCode().equalsIgnoreCase(ArConstants.MILESTONE_BILLING_SCHEDULE_CODE)) {
145             List<Milestone> milestones = new ArrayList<Milestone>();
146             List<Milestone> validMilestones = new ArrayList<Milestone>();
147 
148             Map<String, Object> map = new HashMap<String, Object>();
149             map.put(KFSPropertyConstants.PROPOSAL_NUMBER, award.getProposalNumber());
150             map.put(KFSPropertyConstants.ACTIVE, true);
151             milestones = (List<Milestone>) businessObjectService.findMatching(Milestone.class, map);
152 
153             // To retrieve the previous period end Date to check for milestones and billing schedule.
154 
155             Timestamp ts = new Timestamp(new java.util.Date().getTime());
156             java.sql.Date today = new java.sql.Date(ts.getTime());
157             AccountingPeriod currPeriod = accountingPeriodService.getByDate(today);
158             java.sql.Date[] pair = verifyBillingFrequencyService.getStartDateAndEndDateOfPreviousBillingPeriod(award, currPeriod);
159             java.sql.Date invoiceDate = pair[1];
160 
161 
162             for (Milestone awdMilestone : milestones) {
163                 if (awdMilestone.getMilestoneActualCompletionDate() != null && !invoiceDate.before(awdMilestone.getMilestoneActualCompletionDate()) && !awdMilestone.isBilled() && awdMilestone.getMilestoneAmount().isGreaterThan(KualiDecimal.ZERO)) {
164                     validMilestones.add(awdMilestone);
165                 }
166             }
167             if (CollectionUtils.isEmpty(validMilestones)) {
168                 hasMilestonesToInvoice = false;
169             }
170         }
171         return hasMilestonesToInvoice;
172     }
173 
174     /**
175      * @see org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService#hasNoBillsToInvoice(org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward)
176      */
177     @Override
178     public boolean hasBillsToInvoice(ContractsAndGrantsBillingAward award) {
179         boolean hasBillsToInvoice = true;
180         if (award.getBillingFrequencyCode().equalsIgnoreCase(ArConstants.PREDETERMINED_BILLING_SCHEDULE_CODE)) {
181 
182             List<Bill> bills = new ArrayList<Bill>();
183             List<Bill> validBills = new ArrayList<Bill>();
184             Map<String, Object> map = new HashMap<String, Object>();
185             map.put(KFSPropertyConstants.PROPOSAL_NUMBER, award.getProposalNumber());
186             map.put(KFSPropertyConstants.ACTIVE, true);
187 
188             bills = (List<Bill>) businessObjectService.findMatching(Bill.class, map);
189             // To retrieve the previous period end Date to check for milestones and billing schedule.
190 
191             Timestamp ts = new Timestamp(new java.util.Date().getTime());
192             java.sql.Date today = new java.sql.Date(ts.getTime());
193             AccountingPeriod currPeriod = accountingPeriodService.getByDate(today);
194             java.sql.Date[] pair = verifyBillingFrequencyService.getStartDateAndEndDateOfPreviousBillingPeriod(award, currPeriod);
195             java.sql.Date invoiceDate = pair[1];
196 
197             for (Bill awdBill : bills) {
198                 if (awdBill.getBillDate() != null && !invoiceDate.before(awdBill.getBillDate()) && !awdBill.isBilled() && awdBill.getEstimatedAmount().isGreaterThan(KualiDecimal.ZERO)) {
199                     validBills.add(awdBill);
200                 }
201             }
202             if (CollectionUtils.isEmpty(validBills)) {
203                 hasBillsToInvoice = false;
204             }
205         }
206         return hasBillsToInvoice;
207     }
208 
209     /**
210      * @see org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService#owningAgencyHasNoCustomerRecord(org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward)
211      */
212     @Override
213     public boolean owningAgencyHasCustomerRecord(ContractsAndGrantsBillingAward award) {
214         boolean isValid = true;
215         if (ObjectUtils.isNotNull(award.getAgency().getCustomerNumber())) {
216             Customer customer = customerService.getByPrimaryKey(award.getAgency().getCustomerNumber());
217             return !ObjectUtils.isNull(customer);
218         }
219 
220         return false;
221     }
222 
223     /**
224      * This method checks if the System Information and ORganization Accounting Default are setup for the Chart Code and Org Code
225      * from the award accounts.
226      *
227      * @param award
228      * @return
229      */
230     @Override
231     public boolean isChartAndOrgSetupForInvoicing(ContractsAndGrantsBillingAward award) {
232         String coaCode = award.getPrimaryAwardOrganization().getChartOfAccountsCode();
233         String orgCode = award.getPrimaryAwardOrganization().getOrganizationCode();
234         String procCoaCode = null, procOrgCode = null;
235         Integer currentYear = universityDateService.getCurrentFiscalYear();
236 
237         Map<String, Object> criteria = new HashMap<String, Object>();
238         Map<String, Object> sysCriteria = new HashMap<String, Object>();
239         criteria.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, currentYear);
240         sysCriteria.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, currentYear);
241         criteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, coaCode);
242         criteria.put(KFSPropertyConstants.ORGANIZATION_CODE, orgCode);
243 
244 
245         // To retrieve processing codes based on billing codes using organization options
246         List<String> procCodes = getContractsGrantsInvoiceDocumentService().getProcessingFromBillingCodes(coaCode, orgCode);
247         if (!CollectionUtils.isEmpty(procCodes) && procCodes.size() > 1) {
248 
249             sysCriteria.put(ArPropertyConstants.OrganizationAccountingDefaultFields.PROCESSING_CHART_OF_ACCOUNTS_CODE, procCodes.get(0));
250             sysCriteria.put(ArPropertyConstants.OrganizationAccountingDefaultFields.PROCESSING_ORGANIZATION_CODE, procCodes.get(1));
251             OrganizationAccountingDefault organizationAccountingDefault = businessObjectService.findByPrimaryKey(OrganizationAccountingDefault.class, criteria);
252 
253             SystemInformation systemInformation = businessObjectService.findByPrimaryKey(SystemInformation.class, sysCriteria);
254             if (ObjectUtils.isNotNull(organizationAccountingDefault) && ObjectUtils.isNotNull(systemInformation)) {
255                 return true;
256             }
257         }
258         return false;
259 
260     }
261 
262     public AccountingPeriodService getAccountingPeriodService() {
263         return accountingPeriodService;
264     }
265 
266     public void setAccountingPeriodService(AccountingPeriodService accountingPeriodService) {
267         this.accountingPeriodService = accountingPeriodService;
268     }
269 
270     public BusinessObjectService getBusinessObjectService() {
271         return businessObjectService;
272     }
273 
274     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
275         this.businessObjectService = businessObjectService;
276     }
277 
278     public ContractsGrantsInvoiceDocumentService getContractsGrantsInvoiceDocumentService() {
279         return contractsGrantsInvoiceDocumentService;
280     }
281 
282     public void setContractsGrantsInvoiceDocumentService(ContractsGrantsInvoiceDocumentService contractsGrantsInvoiceDocumentService) {
283         this.contractsGrantsInvoiceDocumentService = contractsGrantsInvoiceDocumentService;
284     }
285 
286     public CustomerService getCustomerService() {
287         return customerService;
288     }
289 
290     public void setCustomerService(CustomerService customerService) {
291         this.customerService = customerService;
292     }
293 
294     public FinancialSystemDocumentService getFinancialSystemDocumentService() {
295         return financialSystemDocumentService;
296     }
297 
298     public void setFinancialSystemDocumentService(FinancialSystemDocumentService financialSystemDocumentService) {
299         this.financialSystemDocumentService = financialSystemDocumentService;
300     }
301 
302     public KualiModuleService getKualiModuleService() {
303         return kualiModuleService;
304     }
305 
306     public void setKualiModuleService(KualiModuleService kualiModuleService) {
307         this.kualiModuleService = kualiModuleService;
308     }
309 
310     public ParameterService getParameterService() {
311         return parameterService;
312     }
313 
314     public void setParameterService(ParameterService parameterService) {
315         this.parameterService = parameterService;
316     }
317 
318     public VerifyBillingFrequencyService getVerifyBillingFrequencyService() {
319         return verifyBillingFrequencyService;
320     }
321 
322     public void setVerifyBillingFrequencyService(VerifyBillingFrequencyService verifyBillingFrequencyService) {
323         this.verifyBillingFrequencyService = verifyBillingFrequencyService;
324     }
325 
326     public UniversityDateService getUniversityDateService() {
327         return universityDateService;
328     }
329 
330     public void setUniversityDateService(UniversityDateService universityDateService) {
331         this.universityDateService = universityDateService;
332     }
333 
334     public OptionsService getOptionsService() {
335         return optionsService;
336     }
337 
338     public void setOptionsService(OptionsService optionsService) {
339         this.optionsService = optionsService;
340     }
341 }