/*
* 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.businessobject.lookup;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.module.ar.ArConstants;
import org.kuali.kfs.module.ar.ArPropertyConstants;
import org.kuali.kfs.module.ar.businessobject.ContractsGrantsPaymentHistoryReport;
import org.kuali.kfs.module.ar.businessobject.InvoicePaidApplied;
import org.kuali.kfs.module.ar.document.ContractsGrantsInvoiceDocument;
import org.kuali.kfs.module.ar.document.PaymentApplicationDocument;
import org.kuali.kfs.sys.KFSKeyConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.document.service.FinancialSystemDocumentService;
import org.kuali.kfs.sys.util.KfsDateUtils;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.kuali.rice.core.web.format.CurrencyFormatter;
import org.kuali.rice.core.web.format.FormatException;
import org.kuali.rice.core.web.format.Formatter;
import org.kuali.rice.kew.api.exception.WorkflowException;
import org.kuali.rice.kns.web.struts.form.LookupForm;
import org.kuali.rice.krad.document.Document;
import org.kuali.rice.krad.service.DocumentService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
/**
* Defines a custom lookup for the Payment History Report.
*/
public class ContractsGrantsPaymentHistoryReportLookupableHelperServiceImpl extends ContractsGrantsReportLookupableHelperServiceImplBase {
protected DateTimeService dateTimeService;
protected DocumentService documentService;
protected FinancialSystemDocumentService financialSystemDocumentService;
/**
* Overridden to validate the invoie amount and payment date fields to make sure they are parsable
* @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map)
*/
@Override
public void validateSearchParameters(Map<String, String> fieldValues) {
if (!StringUtils.isBlank(fieldValues.get(ArPropertyConstants.PAYMENT_DATE))) {
validateDateField(fieldValues.get(ArPropertyConstants.PAYMENT_DATE), ArPropertyConstants.PAYMENT_DATE, getDateTimeService());
}
if (!StringUtils.isBlank(fieldValues.get(ArPropertyConstants.RANGE_LOWER_BOUND_KEY_PREFIX+ArPropertyConstants.PAYMENT_DATE))) {
validateDateField(fieldValues.get(ArPropertyConstants.RANGE_LOWER_BOUND_KEY_PREFIX+ArPropertyConstants.PAYMENT_DATE), ArPropertyConstants.RANGE_LOWER_BOUND_KEY_PREFIX+ArPropertyConstants.PAYMENT_DATE, getDateTimeService());
}
if (!StringUtils.isBlank(fieldValues.get(ArPropertyConstants.INVOICE_AMOUNT))) {
try {
Formatter f = new CurrencyFormatter();
f.format(fieldValues.get(ArPropertyConstants.INVOICE_AMOUNT));
} catch (FormatException fe) {
// we'll assume this was a parse exception
final String label = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), ArPropertyConstants.INVOICE_AMOUNT);
GlobalVariables.getMessageMap().putError(ArPropertyConstants.INVOICE_AMOUNT, KFSKeyConstants.ERROR_NUMERIC, label);
}
}
super.validateSearchParameters(fieldValues);
}
/**
* This method performs the lookup and returns a collection of lookup items
*
* @param lookupForm
* @param kualiLookupable
* @param resultTable
* @param bounded
* @return
*/
@Override
public Collection performLookup(LookupForm lookupForm, Collection resultTable, boolean bounded) {
Map lookupFormFields = lookupForm.getFieldsForLookup();
setBackLocation((String) lookupForm.getFieldsForLookup().get(KRADConstants.BACK_LOCATION));
setDocFormKey((String) lookupForm.getFieldsForLookup().get(KRADConstants.DOC_FORM_KEY));
Collection<ContractsGrantsPaymentHistoryReport> displayList = new ArrayList<ContractsGrantsPaymentHistoryReport>();
Map<String, String> invoiceAppliedLookupFields = new HashMap<>();
invoiceAppliedLookupFields.put(ArPropertyConstants.CUSTOMER_INVOICE_DOCUMENT+"."+KFSPropertyConstants.DOCUMENT_HEADER+"."+KFSPropertyConstants.WORKFLOW_DOCUMENT_TYPE_NAME, ArConstants.ArDocumentTypeCodes.CONTRACTS_GRANTS_INVOICE);
if (lookupFormFields.containsKey(ArPropertyConstants.PAYMENT_NUMBER)) {
invoiceAppliedLookupFields.put(KFSPropertyConstants.DOCUMENT_NUMBER, (String)lookupFormFields.get(ArPropertyConstants.PAYMENT_NUMBER));
}
if (lookupFormFields.containsKey(ArPropertyConstants.CustomerFields.CUSTOMER_NUMBER)) {
invoiceAppliedLookupFields.put(ArPropertyConstants.CUSTOMER_INVOICE_DOCUMENT+"."+ArPropertyConstants.CustomerFields.CUSTOMER_NUMBER, (String)lookupFormFields.get(ArPropertyConstants.CustomerFields.CUSTOMER_NUMBER));
}
if (lookupFormFields.containsKey(ArPropertyConstants.PAYMENT_AMOUNT)) {
invoiceAppliedLookupFields.put(ArPropertyConstants.CustomerInvoiceDetailFields.INVOICE_ITEM_APPLIED_AMOUNT, (String)lookupFormFields.get(ArPropertyConstants.PAYMENT_AMOUNT));
}
if (lookupFormFields.containsKey(ArPropertyConstants.INVOICE_NUMBER)) {
invoiceAppliedLookupFields.put(ArPropertyConstants.CustomerInvoiceDocumentFields.FINANCIAL_DOCUMENT_REF_INVOICE_NUMBER, (String)lookupFormFields.get(ArPropertyConstants.INVOICE_NUMBER));
}
Collection<InvoicePaidApplied> invoicePaidApplieds = getLookupService().findCollectionBySearchHelper(InvoicePaidApplied.class, invoiceAppliedLookupFields, true);
// build search result fields
// For each Cash Control doc, get a list of payment app doc numbers
try {
for (InvoicePaidApplied invoicePaidApplied : invoicePaidApplieds) {
boolean useInvoicePaidApplied = true;
final Document doc = getDocumentService().getByDocumentHeaderId(invoicePaidApplied.getDocumentNumber());
if (doc instanceof PaymentApplicationDocument) {
final PaymentApplicationDocument paymentApp = (PaymentApplicationDocument)doc;
if (getFinancialSystemDocumentService().getUnsuccessfulDocumentStatuses().contains(paymentApp.getFinancialSystemDocumentHeader().getWorkflowDocumentStatusCode())) {
useInvoicePaidApplied = false;
}
if (!StringUtils.isBlank((String)lookupFormFields.get(ArPropertyConstants.APPLIED_INDICATOR))) {
final String appliedIndicator = (String)lookupFormFields.get(ArPropertyConstants.APPLIED_INDICATOR);
if (KRADConstants.YES_INDICATOR_VALUE.equals(appliedIndicator) && !getFinancialSystemDocumentService().getSuccessfulDocumentStatuses().contains(paymentApp.getFinancialSystemDocumentHeader().getWorkflowDocumentStatusCode())) {
useInvoicePaidApplied = false;
} else if (KRADConstants.NO_INDICATOR_VALUE.equals(appliedIndicator) && !getFinancialSystemDocumentService().getPendingDocumentStatuses().contains(paymentApp.getFinancialSystemDocumentHeader().getWorkflowDocumentStatusCode())) {
useInvoicePaidApplied = false;
}
}
final java.util.Date paymentAppFinalDate = paymentApp.getDocumentHeader().getWorkflowDocument().getDateFinalized().toDate();
if (!StringUtils.isBlank((String)lookupFormFields.get(ArPropertyConstants.PAYMENT_DATE))) {
final java.util.Date toPaymentDate = getDateTimeService().convertToDate((String)lookupFormFields.get(ArPropertyConstants.PAYMENT_DATE));
if (!KfsDateUtils.isSameDay(paymentAppFinalDate, toPaymentDate) && toPaymentDate.before(paymentAppFinalDate)) {
useInvoicePaidApplied = false;
}
}
if (!StringUtils.isBlank((String)lookupFormFields.get(ArPropertyConstants.RANGE_LOWER_BOUND_KEY_PREFIX+ArPropertyConstants.PAYMENT_DATE))) {
final java.util.Date fromPaymentDate = getDateTimeService().convertToDate((String)lookupFormFields.get(ArPropertyConstants.RANGE_LOWER_BOUND_KEY_PREFIX+ArPropertyConstants.PAYMENT_DATE));
if (!KfsDateUtils.isSameDay(paymentAppFinalDate, fromPaymentDate) && fromPaymentDate.after(paymentAppFinalDate)) {
useInvoicePaidApplied = false;
}
}
final ContractsGrantsInvoiceDocument cgInvoiceDocument = getBusinessObjectService().findBySinglePrimaryKey(ContractsGrantsInvoiceDocument.class, invoicePaidApplied.getFinancialDocumentReferenceInvoiceNumber());
if (!StringUtils.isBlank((String)lookupFormFields.get(ArPropertyConstants.INVOICE_AMOUNT))) {
final KualiDecimal invoiceAmount = new KualiDecimal((String)lookupFormFields.get(ArPropertyConstants.INVOICE_AMOUNT));
if (!invoiceAmount.equals(cgInvoiceDocument.getTotalDollarAmount())) {
useInvoicePaidApplied = false;
}
}
if (!StringUtils.isBlank((String)lookupFormFields.get(KFSPropertyConstants.AWARD_NUMBER))) {
if (!StringUtils.equals(cgInvoiceDocument.getInvoiceGeneralDetail().getAward().getProposalNumber().toString(),(String)lookupFormFields.get(KFSPropertyConstants.AWARD_NUMBER))) {
useInvoicePaidApplied = false;
}
}
if (!StringUtils.isBlank((String)lookupFormFields.get(ArPropertyConstants.REVERSED_INDICATOR))) {
final String reversedIndicator = (String)lookupFormFields.get(ArPropertyConstants.REVERSED_INDICATOR);
if (KRADConstants.YES_INDICATOR_VALUE.equals(reversedIndicator) && !cgInvoiceDocument.isInvoiceReversal()) {
useInvoicePaidApplied = false;
} else if (KRADConstants.NO_INDICATOR_VALUE.equals(reversedIndicator) && cgInvoiceDocument.isInvoiceReversal()) {
useInvoicePaidApplied = false;
}
}
if (useInvoicePaidApplied) {
ContractsGrantsPaymentHistoryReport cgPaymentHistoryReport = new ContractsGrantsPaymentHistoryReport();
cgPaymentHistoryReport.setPaymentNumber(invoicePaidApplied.getDocumentNumber());
cgPaymentHistoryReport.setPaymentAmount(invoicePaidApplied.getInvoiceItemAppliedAmount());
cgPaymentHistoryReport.setInvoiceNumber(invoicePaidApplied.getFinancialDocumentReferenceInvoiceNumber());
cgPaymentHistoryReport.setPaymentDate(new java.sql.Date(paymentApp.getDocumentHeader().getWorkflowDocument().getDateFinalized().getMillis()));
cgPaymentHistoryReport.setAppliedIndicator(getFinancialSystemDocumentService().getSuccessfulDocumentStatuses().contains(paymentApp.getFinancialSystemDocumentHeader().getWorkflowDocumentStatusCode()));
cgPaymentHistoryReport.setAwardNumber(cgInvoiceDocument.getInvoiceGeneralDetail().getProposalNumber());
cgPaymentHistoryReport.setReversedIndicator(cgInvoiceDocument.isInvoiceReversal());
cgPaymentHistoryReport.setCustomerNumber(cgInvoiceDocument.getCustomerNumber());
cgPaymentHistoryReport.setCustomerName(cgInvoiceDocument.getCustomer().getCustomerName());
cgPaymentHistoryReport.setInvoiceAmount(cgInvoiceDocument.getTotalDollarAmount());
displayList.add(cgPaymentHistoryReport);
}
}
}
buildResultTable(lookupForm, displayList, resultTable);
}
catch (WorkflowException we) {
throw new RuntimeException("Could not open payment application document related to search", we);
}
catch (ParseException pe) {
throw new RuntimeException("I tried to validate the date and amount fields related to search, I really did. But...I guess I didn't try hard enough", pe);
}
return displayList;
}
public DateTimeService getDateTimeService() {
return dateTimeService;
}
public void setDateTimeService(DateTimeService dateTimeService) {
this.dateTimeService = dateTimeService;
}
public DocumentService getDocumentService() {
return documentService;
}
public void setDocumentService(DocumentService documentService) {
this.documentService = documentService;
}
public FinancialSystemDocumentService getFinancialSystemDocumentService() {
return financialSystemDocumentService;
}
public void setFinancialSystemDocumentService(FinancialSystemDocumentService financialSystemDocumentService) {
this.financialSystemDocumentService = financialSystemDocumentService;
}
}