001 /*
002 * Copyright 2011 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.kfs.module.ar.document.service.impl;
017
018 import java.sql.Timestamp;
019 import java.text.DateFormat;
020 import java.text.ParseException;
021 import java.text.SimpleDateFormat;
022 import java.util.ArrayList;
023 import java.util.Calendar;
024 import java.util.Collection;
025 import java.util.Date;
026 import java.util.Hashtable;
027 import java.util.Iterator;
028 import java.util.List;
029 import java.util.Map;
030
031 import org.apache.commons.lang.StringUtils;
032 import org.kuali.kfs.module.ar.ArConstants;
033 import org.kuali.kfs.module.ar.businessobject.AccountsReceivableDocumentHeader;
034 import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail;
035 import org.kuali.kfs.module.ar.businessobject.CustomerOpenItemReportDetail;
036 import org.kuali.kfs.module.ar.businessobject.NonAppliedHolding;
037 import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument;
038 import org.kuali.kfs.module.ar.document.PaymentApplicationDocument;
039 import org.kuali.kfs.module.ar.document.dataaccess.AccountsReceivableDocumentHeaderDao;
040 import org.kuali.kfs.module.ar.document.dataaccess.CustomerInvoiceDetailDao;
041 import org.kuali.kfs.module.ar.document.dataaccess.NonAppliedHoldingDao;
042 import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService;
043 import org.kuali.kfs.module.ar.document.service.CustomerOpenItemReportService;
044 import org.kuali.kfs.sys.KFSConstants;
045 import org.kuali.kfs.sys.businessobject.FinancialSystemDocumentHeader;
046 import org.kuali.kfs.sys.context.SpringContext;
047 import org.kuali.kfs.sys.document.dataaccess.FinancialSystemDocumentHeaderDao;
048 import org.kuali.rice.kew.exception.WorkflowException;
049 import org.kuali.rice.kim.bo.Person;
050 import org.kuali.rice.kns.exception.InfrastructureException;
051 import org.kuali.rice.kns.exception.UnknownDocumentIdException;
052 import org.kuali.rice.kns.service.DateTimeService;
053 import org.kuali.rice.kns.service.DocumentService;
054 import org.kuali.rice.kns.util.GlobalVariables;
055 import org.kuali.rice.kns.util.KualiDecimal;
056 import org.kuali.rice.kns.util.ObjectUtils;
057 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument;
058 import org.kuali.rice.kns.workflow.service.WorkflowDocumentService;
059 import org.springframework.transaction.annotation.Transactional;
060
061 @Transactional
062 public class CustomerOpenItemReportServiceImpl implements CustomerOpenItemReportService {
063
064 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CustomerOpenItemReportServiceImpl.class);
065
066 private AccountsReceivableDocumentHeaderDao accountsReceivableDocumentHeaderDao;
067 private WorkflowDocumentService workflowDocumentService;
068 private CustomerInvoiceDocumentService customerInvoiceDocumentService;
069 private FinancialSystemDocumentHeaderDao financialSystemDocumentHeaderDao;
070 private DocumentService documentService;
071 private DateTimeService dateTimeService;
072 private CustomerInvoiceDetailDao customerInvoiceDetailDao;
073 private NonAppliedHoldingDao nonAppliedHoldingDao;
074
075 /**
076 * This method populates CustomerOpenItemReportDetails (Customer History Report).
077 *
078 * @param customerNumber
079 */
080 public List getPopulatedReportDetails(String customerNumber) {
081 List results = new ArrayList();
082
083 Collection arDocumentHeaders = accountsReceivableDocumentHeaderDao.getARDocumentHeadersByCustomerNumber(customerNumber);
084 if (arDocumentHeaders.size() == 0)
085 return results;
086
087 Person user = GlobalVariables.getUserSession().getPerson();
088
089 List finSysDocHeaderIds = new ArrayList();
090 List invoiceIds = new ArrayList();
091 List paymentApplicationIds = new ArrayList();
092 List unappliedHoldingIds = new ArrayList();
093
094 Hashtable details = new Hashtable();
095 KualiWorkflowDocument workflowDocument;
096
097
098 for (Iterator itr = arDocumentHeaders.iterator(); itr.hasNext();) {
099 AccountsReceivableDocumentHeader documentHeader = (AccountsReceivableDocumentHeader) itr.next();
100 CustomerOpenItemReportDetail detail = new CustomerOpenItemReportDetail();
101
102 // populate workflow document
103 try {
104 workflowDocument = workflowDocumentService.createWorkflowDocument(Long.valueOf(documentHeader.getDocumentNumber()), user);
105 }
106 catch (WorkflowException e) {
107 throw new UnknownDocumentIdException("No document found for documentHeaderId '" + documentHeader.getDocumentNumber() + "'", e);
108 }
109
110 // do not display not approved documents
111 Date approvedDate = getSqlDate(workflowDocument.getRouteHeader().getDateApproved());
112 if (ObjectUtils.isNull(approvedDate)) {
113 continue;
114 }
115
116 // Document Type
117 String documentType = workflowDocument.getDocumentType();
118 detail.setDocumentType(documentType);
119
120 // Document Number
121 String documentNumber = documentHeader.getDocumentNumber();
122 detail.setDocumentNumber(documentNumber);
123
124 if (documentType.equals("INV"))
125 invoiceIds.add(documentNumber);
126 else {
127 // Approved Date -> for invoices Due Date, for all other documents Approved Date
128 detail.setDueApprovedDate(approvedDate);
129
130 if (documentType.equals("APP"))
131 paymentApplicationIds.add(documentNumber);
132 else
133 finSysDocHeaderIds.add(documentNumber);
134 }
135 details.put(documentNumber, detail);
136 }
137
138 // add Unapplied Payment Applications
139 Collection<NonAppliedHolding> arNonAppliedHoldings = nonAppliedHoldingDao.getNonAppliedHoldingsForCustomer(customerNumber);
140 for (NonAppliedHolding nonAppliedHolding : arNonAppliedHoldings) {
141 // populate workflow document
142 try {
143 workflowDocument = workflowDocumentService.createWorkflowDocument(Long.valueOf(nonAppliedHolding.getReferenceFinancialDocumentNumber()), user);
144 }
145 catch (WorkflowException e) {
146 throw new UnknownDocumentIdException("No document found for documentHeaderId '" + nonAppliedHolding.getReferenceFinancialDocumentNumber() + "'", e);
147 }
148
149 CustomerOpenItemReportDetail detail = new CustomerOpenItemReportDetail();
150 detail.setDocumentType("APP");
151 detail.setDocumentNumber(nonAppliedHolding.getReferenceFinancialDocumentNumber());
152 Date documentApprovedDate = getSqlDate(workflowDocument.getRouteHeader().getDateApproved());
153 detail.setDueApprovedDate(documentApprovedDate);
154 details.put(nonAppliedHolding.getReferenceFinancialDocumentNumber(), detail);
155 unappliedHoldingIds.add(nonAppliedHolding.getReferenceFinancialDocumentNumber());
156 }
157
158 // for invoices
159 if (invoiceIds.size() > 0)
160 populateReportDetailsForInvoices(invoiceIds, results, details);
161
162 // for payment applications
163 if (paymentApplicationIds.size() > 0) {
164 try {
165 populateReportDetailsForPaymentApplications(paymentApplicationIds, results, details);
166 } catch(WorkflowException w) {
167 LOG.error("WorkflowException while populating report details for PaymentApplicationDocument", w);
168 }
169 }
170
171 // for unapplied payment applications
172 if (unappliedHoldingIds.size() > 0) {
173 try {
174 populateReportDetailsForUnappliedPaymentApplications(unappliedHoldingIds, results, details);
175 } catch(WorkflowException w) {
176 LOG.error("WorkflowException while populating report details for PaymentApplicationDocument", w);
177 }
178 }
179
180 // for all other documents
181 if (finSysDocHeaderIds.size() > 0)
182 populateReportDetails(finSysDocHeaderIds, results, details);
183
184 return results;
185 }
186
187 /**
188 * This method populates CustomerOpenItemReportDetails for CustomerInvoiceDocuments (Customer History Report).
189 *
190 * @param finSysDocHeaderIds <=> documentNumbers of CustomerInvoiceDocuments
191 * @param results <=> CustomerOpenItemReportDetails to display in the report
192 * @param details <=> <key = documentNumber, value = customerOpenItemReportDetail>
193 */
194 protected void populateReportDetailsForInvoices(List invoiceIds, List results, Hashtable details) {
195 CustomerInvoiceDocumentService customerInvoiceDocumentService = SpringContext.getBean(CustomerInvoiceDocumentService.class);
196 Collection invoices = getDocuments(CustomerInvoiceDocument.class, invoiceIds);
197
198 for (Iterator itr = invoices.iterator(); itr.hasNext();) {
199 CustomerInvoiceDocument invoice = (CustomerInvoiceDocument) itr.next();
200 String documentNumber = invoice.getDocumentNumber();
201
202 CustomerOpenItemReportDetail detail = (CustomerOpenItemReportDetail) details.get(documentNumber);
203
204 // Document Description
205 String documentDescription = invoice.getDocumentHeader().getDocumentDescription();
206 if (ObjectUtils.isNotNull(documentDescription))
207 detail.setDocumentDescription(documentDescription);
208 else
209 detail.setDocumentDescription("");
210
211 // Billing Date
212 detail.setBillingDate(invoice.getBillingDate());
213
214 // Due/Approved Date -> for invoice it is Due Date, and for all other documents Approved Date
215 detail.setDueApprovedDate(invoice.getInvoiceDueDate());
216
217 // Document Payment Amount
218 detail.setDocumentPaymentAmount(invoice.getDocumentHeader().getFinancialDocumentTotalAmount());
219
220 // Unpaid/Unapplied Amount
221 detail.setUnpaidUnappliedAmount(customerInvoiceDocumentService.getOpenAmountForCustomerInvoiceDocument(invoice));
222
223 results.add(detail);
224 }
225 }
226
227 /**
228 * This method populates CustomerOpenItemReportDetails for PaymentApplicationDocuments (Customer History Report).
229 *
230 * @param paymentApplicationIds <=> documentNumbers of PaymentApplicationDocuments
231 * @param results <=> CustomerOpenItemReportDetails to display in the report
232 * @param details <=> <key = documentNumber, value = customerOpenItemReportDetail>
233 */
234 protected void populateReportDetailsForPaymentApplications(List paymentApplicationIds, List results, Hashtable details) throws WorkflowException {
235 Collection paymentApplications = getDocuments(PaymentApplicationDocument.class, paymentApplicationIds);
236
237 for (Iterator itr = paymentApplications.iterator(); itr.hasNext();) {
238 PaymentApplicationDocument paymentApplication = (PaymentApplicationDocument) itr.next();
239 String documentNumber = paymentApplication.getDocumentNumber();
240
241 CustomerOpenItemReportDetail detail = (CustomerOpenItemReportDetail) details.get(documentNumber);
242
243 // populate Document Description
244 String documentDescription = paymentApplication.getDocumentHeader().getDocumentDescription();
245 if (ObjectUtils.isNotNull(documentDescription))
246 detail.setDocumentDescription(documentDescription);
247 else
248 detail.setDocumentDescription("");
249
250 // populate Document Payment Amount
251 detail.setDocumentPaymentAmount(paymentApplication.getDocumentHeader().getFinancialDocumentTotalAmount().negated());
252
253 // populate Unpaid/Unapplied Amount if the customer number is the same
254 if (ObjectUtils.isNotNull(paymentApplication.getNonAppliedHolding())) {
255 if (paymentApplication.getNonAppliedHolding().getCustomerNumber().equals(paymentApplication.getAccountsReceivableDocumentHeader().getCustomerNumber())) {
256 detail.setUnpaidUnappliedAmount(paymentApplication.getNonAppliedHolding().getAvailableUnappliedAmount().negated());
257 }
258 }
259
260 results.add(detail);
261 }
262 }
263
264 /**
265 * This method populates CustomerOpenItemReportDetails for UnappliedPaymentApplicationDocuments (Customer History Report).
266 *
267 * @param unappliedHoldingIds <=> documentNumbers of UnappliedPaymentApplicationDocuments
268 * @param results <=> CustomerOpenItemReportDetails to display in the report
269 * @param details <=> <key = documentNumber, value = customerOpenItemReportDetail>
270 */
271 protected void populateReportDetailsForUnappliedPaymentApplications(List unappliedHoldingIds, List results, Hashtable details) throws WorkflowException {
272 Collection paymentApplications = getDocuments(PaymentApplicationDocument.class, unappliedHoldingIds);
273
274 for (Iterator itr = paymentApplications.iterator(); itr.hasNext();) {
275 PaymentApplicationDocument paymentApplication = (PaymentApplicationDocument) itr.next();
276 String documentNumber = paymentApplication.getDocumentNumber();
277
278 if ((paymentApplication.getNonAppliedHolding().getCustomerNumber().equals(paymentApplication.getAccountsReceivableDocumentHeader().getCustomerNumber()))) {
279 continue;
280 }
281
282 CustomerOpenItemReportDetail detail = (CustomerOpenItemReportDetail) details.get(documentNumber);
283
284 // populate Document Description
285 String documentDescription = paymentApplication.getDocumentHeader().getDocumentDescription();
286 if (ObjectUtils.isNotNull(documentDescription))
287 detail.setDocumentDescription(documentDescription);
288 else
289 detail.setDocumentDescription("");
290
291 // populate Document Payment Amount
292 detail.setDocumentPaymentAmount(KualiDecimal.ZERO);
293
294 // populate Unpaid/Unapplied Amount if the customer number is not the same
295 detail.setUnpaidUnappliedAmount(paymentApplication.getNonAppliedHoldingAmount().negated());
296
297 results.add(detail);
298 }
299 }
300
301 /**
302 * This method populates CustomerOpenItemReportDetails for CustomerCreditMemoDocuments and WriteOffDocuments <=> all documents
303 * but CustomerInvoiceDocument and PaymentApplicationDocument (Customer History Report).
304 *
305 * @param finSysDocHeaderIds <=> documentNumbers of FinancialSystemDocumentHeaders
306 * @param results <=> CustomerOpenItemReportDetails to display in the report
307 * @param details <=> <key = documentNumber, value = customerOpenItemReportDetail>
308 */
309 public void populateReportDetails(List finSysDocHeaderIds, List results, Hashtable details) {
310 Collection financialSystemDocHeaders = financialSystemDocumentHeaderDao.getByDocumentNumbers(finSysDocHeaderIds);
311
312 for (Iterator itr = financialSystemDocHeaders.iterator(); itr.hasNext();) {
313 FinancialSystemDocumentHeader fsDocumentHeader = (FinancialSystemDocumentHeader) itr.next();
314 String documentNumber = fsDocumentHeader.getDocumentNumber();
315
316 CustomerOpenItemReportDetail detail = (CustomerOpenItemReportDetail) details.get(documentNumber);
317
318 // populate Document Description
319 String documentDescription = fsDocumentHeader.getDocumentDescription();
320 if (ObjectUtils.isNotNull(documentDescription))
321 detail.setDocumentDescription(documentDescription);
322 else
323 detail.setDocumentDescription("");
324
325 // populate Document Payment Amount
326 detail.setDocumentPaymentAmount(fsDocumentHeader.getFinancialDocumentTotalAmount().negated());
327
328 // Unpaid/Unapplied Amount
329 detail.setUnpaidUnappliedAmount(KualiDecimal.ZERO);
330
331 results.add(detail);
332 }
333 }
334
335 /**
336 * This method returns collection of documents of type classToSearchFrom Note: can be used for documents only, not for
337 * *DocumentHeaders @param documentNumbers
338 */
339 public Collection getDocuments(Class classToSearchFrom, List documentNumbers) {
340 List docs;
341
342 try {
343 docs = documentService.getDocumentsByListOfDocumentHeaderIds(classToSearchFrom, documentNumbers);
344 }
345 catch (WorkflowException e) {
346 throw new InfrastructureException("Unable to retrieve documents", e);
347 }
348 return docs;
349 }
350
351 protected Date getSqlDate(Calendar cal) {
352 Date sqlDueDate = null;
353
354 if (ObjectUtils.isNull(cal))
355 return sqlDueDate;
356 try {
357 sqlDueDate = dateTimeService.convertToSqlDate(new Timestamp(cal.getTime().getTime()));
358 }
359 catch (ParseException e) {
360 // TODO: throw an error here, but don't die
361 }
362 return sqlDueDate;
363 }
364
365 /**
366 * This method populates CustomerOpenItemReportDetails (Customer Open Item Report)
367 *
368 * @param urlParameters
369 */
370 public List getPopulatedReportDetails(Map urlParameters) {
371 List results = new ArrayList();
372
373 // get arDocumentHeaders
374 Collection<AccountsReceivableDocumentHeader> arDocumentHeaders = getARDocumentHeaders(urlParameters);
375 if (arDocumentHeaders.size() == 0)
376 return results;
377
378 // get ids of arDocumentHeaders
379 List<String> arDocumentHeaderIds = new ArrayList<String>();
380 for (AccountsReceivableDocumentHeader arDocHeader : arDocumentHeaders) {
381 arDocumentHeaderIds.add(arDocHeader.getDocumentNumber());
382 }
383
384 // get invoices
385 String reportOption = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.REPORT_OPTION))[0];
386 Collection<CustomerInvoiceDocument> invoices;
387 Collection<CustomerInvoiceDetail> details = null;
388 if (StringUtils.equals(reportOption, ArConstants.CustomerAgingReportFields.ACCT)) {
389 String accountNumber = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.ACCOUNT_NUMBER))[0];
390 details = customerInvoiceDetailDao.getCustomerInvoiceDetailsByAccountNumberByInvoiceDocumentNumbers(accountNumber, arDocumentHeaderIds);
391 invoices = getInvoicesByAccountNumberByDocumentIds(accountNumber, arDocumentHeaderIds, details);
392 }
393 else {
394 invoices = getDocuments(CustomerInvoiceDocument.class, arDocumentHeaderIds);
395 }
396 if (ObjectUtils.isNull(invoices) | invoices.size()==0 )
397 return results;
398
399 List<CustomerInvoiceDocument> selectedInvoices = new ArrayList();
400
401 String columnTitle = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.COLUMN_TITLE))[0];
402 DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
403
404 java.util.Date reportRunDate= null;
405 java.util.Date beginDate = null;
406 java.util.Date endDate = null;
407 try {
408 reportRunDate = dateFormat.parse(((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.REPORT_RUN_DATE))[0]);
409 if (!StringUtils.equals(columnTitle, KFSConstants.CustomerOpenItemReport.ALL_DAYS)) {
410 endDate = dateFormat.parse(((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.REPORT_END_DATE))[0]);
411 String strBeginDate = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.REPORT_BEGIN_DATE))[0];
412 if (StringUtils.isNotEmpty(strBeginDate))
413 beginDate = dateFormat.parse(strBeginDate);
414 }
415 }
416 catch (ParseException e) {
417 e.printStackTrace();
418 }
419
420 // Billing Organization
421 if (StringUtils.equals(reportOption, ArConstants.CustomerAgingReportFields.BILLING_ORG)) {
422 // All days
423 // 1. invoice open amount > 0
424 // 2. billingDate <= reportRunDate
425 // 3. billByChartOfAccountsCode = processingOrBillingChartCode
426 // 4. billbyOrganizationCode = orgCode
427 String chartCode = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.PROCESSING_OR_BILLING_CHART_CODE))[0];
428 String orgCode = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.ORGANIZATION_CODE))[0];
429 if (StringUtils.equals(columnTitle, KFSConstants.CustomerOpenItemReport.ALL_DAYS)) {
430 for (CustomerInvoiceDocument invoice:invoices) {
431 // get only invoices with open amounts
432 if (ObjectUtils.isNull(invoice.getClosedDate())&& ObjectUtils.isNotNull(invoice.getBillingDate()) && !reportRunDate.before(invoice.getBillingDate()) && StringUtils.equals(chartCode, invoice.getBillByChartOfAccountCode()) && StringUtils.equals(orgCode, invoice.getBilledByOrganizationCode()) )
433 selectedInvoices.add(invoice);
434 }
435 }
436 // *days
437 // 1. invoice open amount > 0
438 // 2. beginDate <= invoice billing date <= endDate
439 // 3. billByChartOfAccountsCode = chartCode
440 // 4. billbyOrganizationCode = orgCode
441 else {
442 for (CustomerInvoiceDocument invoice:invoices) {
443 if (ObjectUtils.isNull(invoice.getClosedDate())&& ObjectUtils.isNotNull(invoice.getBillingDate()) && StringUtils.equals(chartCode, invoice.getBillByChartOfAccountCode()) && StringUtils.equals(orgCode, invoice.getBilledByOrganizationCode()) )
444 if ( (ObjectUtils.isNotNull(beginDate) && !beginDate.after(invoice.getBillingDate()) && !endDate.before(invoice.getBillingDate())) || (ObjectUtils.isNull(beginDate) && !endDate.before(invoice.getBillingDate())) )
445 selectedInvoices.add(invoice);
446 }
447 }
448 }
449 // Processing Organization or Account
450 else {
451 // All days
452 // 1. invoice open amount > 0
453 // 2. invoice billing dates <= reportRunDate
454 if (StringUtils.equals(columnTitle, KFSConstants.CustomerOpenItemReport.ALL_DAYS)) {
455 for (CustomerInvoiceDocument invoice:invoices) {
456 if (ObjectUtils.isNull(invoice.getClosedDate()) && ObjectUtils.isNotNull(invoice.getBillingDate())&& !reportRunDate.before(invoice.getBillingDate()))
457 selectedInvoices.add(invoice);
458 }
459 }
460 // *days
461 // 1. invoice open amount > 0
462 // 2. beginDate <= invoice billing date <= endDate
463 else {
464 for (CustomerInvoiceDocument invoice:invoices) {
465 if (ObjectUtils.isNull(invoice.getClosedDate())&& ObjectUtils.isNotNull(invoice.getBillingDate()))
466 if ( (ObjectUtils.isNotNull(beginDate) && !beginDate.after(invoice.getBillingDate()) && !endDate.before(invoice.getBillingDate())) || (ObjectUtils.isNull(beginDate) && !endDate.before(invoice.getBillingDate())) )
467 selectedInvoices.add(invoice);
468 }
469 }
470 }
471
472 if (selectedInvoices.size() == 0)
473 return results;
474
475 if (StringUtils.equals(reportOption, ArConstants.CustomerAgingReportFields.ACCT))
476 populateReporDetails(selectedInvoices,results,details);
477 else
478 populateReportDetails(selectedInvoices,results);
479
480 return results;
481 }
482
483 /**
484 * This method retrieves ARDocumentHeader objects for "Customer Open Item Report"
485 *
486 * @param urlParameters
487 * @return ARDocumentHeader objects meeting the search criteria
488 */
489 protected Collection getARDocumentHeaders(Map urlParameters) {
490 Collection arDocumentHeaders;
491
492 String reportOption = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.REPORT_OPTION))[0];
493 String customerNumber = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.CUSTOMER_NUMBER))[0];
494
495 if (StringUtils.equals(reportOption, ArConstants.CustomerAgingReportFields.PROCESSING_ORG)) {
496 String processingChartCode = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.PROCESSING_OR_BILLING_CHART_CODE))[0];
497 String processingOrganizationCode = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.ORGANIZATION_CODE))[0];
498 arDocumentHeaders = accountsReceivableDocumentHeaderDao.getARDocumentHeadersByCustomerNumberByProcessingOrgCodeAndChartCode(customerNumber, processingChartCode, processingOrganizationCode);
499 } // reportOption is "Billing Organization" or "Account"
500 else {
501 arDocumentHeaders = accountsReceivableDocumentHeaderDao.getARDocumentHeadersByCustomerNumber(customerNumber);
502 }
503 return arDocumentHeaders;
504 }
505
506 /*
507 * This method gets called only if reportOption is Account
508 * Gets invoices based on the selected invoice details <=> invoice details meeting search criteria i.e. the accountNumber and the list of documentIds
509 * @param accountNumber
510 * @param arDocumentHeaderIds
511 * @param details (will get populated here)
512 * @return invoices
513 */
514 protected Collection<CustomerInvoiceDocument> getInvoicesByAccountNumberByDocumentIds(String accountNumber, List arDocumentHeaderIds, Collection<CustomerInvoiceDetail> details) {
515 Collection<CustomerInvoiceDocument> invoices = null;
516
517 if (ObjectUtils.isNull(details) | details.size()==0)
518 return invoices;
519
520 // get list of invoice document ids (eliminate duplicate invoice document ids)
521 List<String> documentIds = new ArrayList();
522 for (CustomerInvoiceDetail detail:details) {
523 String documentNumber = ((CustomerInvoiceDetail)detail).getDocumentNumber();
524 if (!documentIds.contains(documentNumber))
525 documentIds.add(documentNumber);
526 }
527
528 // get invoices for the document ids list
529 if (documentIds.size() != 0)
530 invoices = getDocuments(CustomerInvoiceDocument.class, documentIds);
531
532 return invoices;
533 }
534
535 protected void populateReporDetails(List<CustomerInvoiceDocument> selectedInvoices,List results, Collection<CustomerInvoiceDetail> invoiceDetails) {
536
537 for (Iterator<CustomerInvoiceDocument> iter = selectedInvoices.iterator(); iter.hasNext();) {
538 CustomerInvoiceDocument invoice = iter.next();
539 String documentNumber = invoice.getDocumentNumber();
540
541 KualiDecimal amount = KualiDecimal.ZERO;
542 KualiDecimal taxAmount = KualiDecimal.ZERO;
543 KualiDecimal openAmount = KualiDecimal.ZERO;
544
545 boolean foundFlag = false;
546
547 for (CustomerInvoiceDetail invoiceDetail:invoiceDetails) {
548 String tempDocumentNumber = ((CustomerInvoiceDetail)invoiceDetail).getDocumentNumber();
549 if (!StringUtils.equals(documentNumber, tempDocumentNumber))
550 continue;
551 foundFlag = true;
552
553 KualiDecimal itemAmount = ((CustomerInvoiceDetail)invoiceDetail).getAmount();
554 if (ObjectUtils.isNotNull(itemAmount))
555 amount = amount.add(itemAmount);
556
557 KualiDecimal itemTaxAmount = ((CustomerInvoiceDetail)invoiceDetail).getInvoiceItemTaxAmount();
558 if (ObjectUtils.isNotNull(itemTaxAmount))
559 taxAmount = taxAmount.add(itemTaxAmount);
560
561 KualiDecimal openItemAmount = ((CustomerInvoiceDetail)invoiceDetail).getAmountOpen();
562 if (ObjectUtils.isNotNull(openItemAmount))
563 openAmount = openAmount.add(openItemAmount);
564 }
565 // How is this possible?
566 // invoiceDetails are for the list of invoices(invoices) meeting seach criteria including accountNumber and selected arDocumentHeaders
567 // -> list of invoices gets modified based on report run date and chosen date bucket -> selectedInvoices
568 // selectedInvoices.size() <= invoices.size()
569 if (!foundFlag)
570 continue;
571
572 CustomerOpenItemReportDetail detail = new CustomerOpenItemReportDetail();
573 // Document Type
574 detail.setDocumentType(invoice.getDocumentHeader().getWorkflowDocument().getDocumentType());
575 // Document Number
576 detail.setDocumentNumber(documentNumber);
577 // Document Description
578 String documentDescription = invoice.getDocumentHeader().getDocumentDescription();
579 if (ObjectUtils.isNotNull(documentDescription))
580 detail.setDocumentDescription(documentDescription);
581 else
582 detail.setDocumentDescription("");
583 // Billing Date
584 detail.setBillingDate(invoice.getBillingDate());
585 // Due Date
586 detail.setDueApprovedDate(invoice.getInvoiceDueDate());
587 // Document Payment Amount
588 detail.setDocumentPaymentAmount(amount.add(taxAmount));
589 // Unpaid/Unapplied Amount
590 detail.setUnpaidUnappliedAmount(openAmount);
591 results.add(detail);
592 }
593 }
594
595 protected void populateReportDetails(List<CustomerInvoiceDocument> invoices, List results) {
596 for (CustomerInvoiceDocument invoice:invoices) {
597 CustomerOpenItemReportDetail detail = new CustomerOpenItemReportDetail();
598 // Document Type
599 detail.setDocumentType(invoice.getDocumentHeader().getWorkflowDocument().getDocumentType());
600 // Document Number
601 detail.setDocumentNumber(invoice.getDocumentNumber());
602 // Document Description
603 String documentDescription = invoice.getDocumentHeader().getDocumentDescription();
604 if (ObjectUtils.isNotNull(documentDescription))
605 detail.setDocumentDescription(documentDescription);
606 else
607 detail.setDocumentDescription("");
608 // Billing Date
609 detail.setBillingDate(invoice.getBillingDate());
610 // Due Date
611 detail.setDueApprovedDate(invoice.getInvoiceDueDate());
612 // Document Payment Amount
613 detail.setDocumentPaymentAmount(invoice.getDocumentHeader().getFinancialDocumentTotalAmount());
614 // Unpaid/Unapplied Amount
615 detail.setUnpaidUnappliedAmount(customerInvoiceDocumentService.getOpenAmountForCustomerInvoiceDocument(invoice));
616 results.add(detail);
617
618 }
619 }
620
621 public void setAccountsReceivableDocumentHeaderDao(AccountsReceivableDocumentHeaderDao accountsReceivableDocumentHeaderDao) {
622 this.accountsReceivableDocumentHeaderDao = accountsReceivableDocumentHeaderDao;
623 }
624
625 public void setWorkflowDocumentService(WorkflowDocumentService workflowDocumentService) {
626 this.workflowDocumentService = workflowDocumentService;
627 }
628
629 public void setCustomerInvoiceDocumentService(CustomerInvoiceDocumentService customerInvoiceDocumentService) {
630 this.customerInvoiceDocumentService = customerInvoiceDocumentService;
631 }
632
633 public void setFinancialSystemDocumentHeaderDao(FinancialSystemDocumentHeaderDao financialSystemDocumentHeaderDao) {
634 this.financialSystemDocumentHeaderDao = financialSystemDocumentHeaderDao;
635 }
636
637 public void setDocumentService(DocumentService documentService) {
638 this.documentService = documentService;
639 }
640
641 public void setDateTimeService(DateTimeService dateTimeService) {
642 this.dateTimeService = dateTimeService;
643 }
644
645 public void setCustomerInvoiceDetailDao(CustomerInvoiceDetailDao customerInvoiceDetailDao) {
646 this.customerInvoiceDetailDao = customerInvoiceDetailDao;
647 }
648
649 public void setNonAppliedHoldingDao(NonAppliedHoldingDao nonAppliedHoldingDao) {
650 this.nonAppliedHoldingDao = nonAppliedHoldingDao;
651 }
652 }
653