/**
  * This method calculates the total credits for the customers.
  *
  * @param cgMapByCustomer
  * @param knownCustomers
  */
 private void calculateTotalCreditsForCustomers(
     Map<String, List<ContractsGrantsInvoiceDocument>> cgMapByCustomer,
     Map<String, ContractsAndGrantsAgingReport> knownCustomers) {
   Set<String> customerIds = cgMapByCustomer.keySet();
   KualiDecimal credits = KualiDecimal.ZERO;
   for (String customer : customerIds) {
     ContractsAndGrantsAgingReport agingReportDetail =
         pickContractsGrantsAgingReportDetail(knownCustomers, customer);
     List<ContractsGrantsInvoiceDocument> cgDocs = cgMapByCustomer.get(customer);
     if (ObjectUtils.isNotNull(cgDocs) && !cgDocs.isEmpty()) {
       credits = KualiDecimal.ZERO;
       for (ContractsGrantsInvoiceDocument cgDoc : cgDocs) {
         Collection<CustomerCreditMemoDocument> creditDocs =
             customerCreditMemoDocumentService.getCustomerCreditMemoDocumentByInvoiceDocument(
                 cgDoc.getDocumentNumber());
         if (ObjectUtils.isNotNull(creditDocs) && !creditDocs.isEmpty()) {
           for (CustomerCreditMemoDocument cm : creditDocs) {
             for (CustomerCreditMemoDetail cmDetail : cm.getCreditMemoDetails()) {
               credits = credits.add(cmDetail.getCreditMemoItemTotalAmount());
             }
           }
         }
       }
     }
     agingReportDetail.setTotalCredits(credits);
     totalCredits = totalCredits.add(credits);
   }
 }
 /**
  * This method...
  *
  * @param knownCustomers
  * @param customer
  * @return
  */
 private ContractsAndGrantsAgingReport pickContractsGrantsAgingReportDetail(
     Map<String, ContractsAndGrantsAgingReport> knownCustomers, String customer) {
   ContractsAndGrantsAgingReport agingReportDetail = null;
   if (ObjectUtils.isNull(agingReportDetail = knownCustomers.get(customer))) {
     agingReportDetail = new ContractsAndGrantsAgingReport();
     agingReportDetail.setCustomerNumber(customer.substring(0, customer.indexOf('-')));
     agingReportDetail.setCustomerName(customer.substring(customer.indexOf('-') + 1));
     knownCustomers.put(customer, agingReportDetail);
   }
   return agingReportDetail;
 }
 /**
  * This method returns the Agency inquiry url
  *
  * @param bo business object
  * @param columnTitle
  * @return Returns the url for the Agency Inquiry
  */
 private String getAgencyInquiryUrl(BusinessObject bo, String columnTitle) {
   Properties params = new Properties();
   ContractsAndGrantsAgingReport detail = (ContractsAndGrantsAgingReport) bo;
   params.put(
       KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE,
       ContractsAndGrantsBillingAgency.class.getName());
   params.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, "continueWithInquiry");
   params.put(KFSConstants.DOC_FORM_KEY, "88888888");
   params.put(KFSConstants.HIDE_LOOKUP_RETURN_LINK, "true");
   params.put(KFSPropertyConstants.AGENCY_NUMBER, detail.getAgencyNumber());
   return UrlFactory.parameterizeUrl(KFSConstants.INQUIRY_ACTION, params);
 }
 /**
  * This method returns the url for the paid invoice of the customer
  *
  * @param bo
  * @param columnTitle
  * @return Returns the url for the Payment Application search.
  */
 private String getCreditMemoDocSearchUrl(BusinessObject bo, String columnTitle) {
   Properties params = new Properties();
   ContractsAndGrantsAgingReport detail = (ContractsAndGrantsAgingReport) bo;
   //      Note
   params.put(
       KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, DocumentSearchCriteriaBo.class.getName());
   params.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.START_METHOD);
   params.put(KFSConstants.DOC_FORM_KEY, "88888888");
   params.put(KFSConstants.HIDE_LOOKUP_RETURN_LINK, "true");
   params.put(KFSConstants.DOCUMENT_TYPE_FULL_NAME, "CRM");
   params.put(ArPropertyConstants.CustomerFields.CUSTOMER_NUMBER, detail.getCustomerNumber());
   return UrlFactory.parameterizeUrl(KFSConstants.LOOKUP_ACTION, params);
 }
 /**
  * This method...
  *
  * @param agingReportDao
  * @param begin
  * @param end
  * @param knownCustomers
  */
 private void computeFor0To30DaysByBillingChartAndOrg(
     Map<String, List<ContractsGrantsInvoiceDocument>> cgMapByCustomer,
     java.sql.Date begin,
     java.sql.Date end,
     Map<String, ContractsAndGrantsAgingReport> knownCustomers) {
   Set<String> customerIds = cgMapByCustomer.keySet();
   for (String customer : customerIds) {
     ContractsAndGrantsAgingReport agingReportDetail =
         pickContractsGrantsAgingReportDetail(knownCustomers, customer);
     KualiDecimal amount =
         calculateInvoiceAmountForCustomer(cgMapByCustomer.get(customer), begin, end);
     agingReportDetail.setUnpaidBalance0to30(amount);
     total0to30 = total0to30.add(amount);
   }
 }
 /**
  * This method returns the customer lookup url
  *
  * @param bo business object
  * @param columnTitle
  * @return Returns the url for the customer lookup
  */
 private String getCustomerLookupUrl(BusinessObject bo, String columnTitle) {
   Properties params = new Properties();
   ContractsAndGrantsAgingReport detail = (ContractsAndGrantsAgingReport) bo;
   params.put(KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, Customer.class.getName());
   params.put(KFSConstants.RETURN_LOCATION_PARAMETER, "portal.do");
   params.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.START_METHOD);
   params.put(KFSConstants.DOC_FORM_KEY, "88888888");
   params.put(KFSConstants.HIDE_LOOKUP_RETURN_LINK, "true");
   params.put(
       ArPropertyConstants.CustomerInvoiceWriteoffLookupResultFields.CUSTOMER_NUMBER,
       detail.getCustomerNumber());
   params.put(
       ArPropertyConstants.CustomerInvoiceWriteoffLookupResultFields.CUSTOMER_NAME,
       detail.getCustomerName());
   return UrlFactory.parameterizeUrl(KFSConstants.LOOKUP_ACTION, params);
 }
  private String getCustomerOpenInvoicesReportUrl(
      BusinessObject bo, String columnTitle, Map<String, String> fieldsMap) {

    Properties parameters = new Properties();

    ContractsAndGrantsAgingReport detail = (ContractsAndGrantsAgingReport) bo;

    parameters.put(
        KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE,
        ContractsGrantsAgingOpenInvoicesReport.class.getName());
    parameters.put(
        "lookupableImplementaionServiceName", "arContractsGrantsAgingOpenInvoicesReportLookupable");
    parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.SEARCH_METHOD);
    parameters.put(
        "reportName", ArConstants.ContractsGrantsAgingReportFields.OPEN_INVOCE_REPORT_NAME);
    parameters.put(KFSConstants.DOC_FORM_KEY, "88888888");

    if (ObjectUtils.isNotNull(fieldsMap) && !fieldsMap.isEmpty()) {
      for (String key : fieldsMap.keySet()) {
        String val = fieldsMap.get(key);
        // put if val is not blank or null
        if (ObjectUtils.isNotNull(val) && StringUtils.isNotEmpty(val)) {
          parameters.put(key.toString(), fieldsMap.get(key).toString());
        }
      }
    }

    parameters.put(KFSPropertyConstants.CUSTOMER_NUMBER, detail.getCustomerNumber());
    parameters.put(KFSPropertyConstants.CUSTOMER_NAME, detail.getCustomerName());

    // Report Option
    if (ObjectUtils.isNotNull(reportOption)) {

      parameters.put(
          ArPropertyConstants.ContractsGrantsAgingReportFields.REPORT_OPTION, reportOption);
    }
    // Report Run Date
    DateFormatter dateFormatter = new DateFormatter();
    parameters.put(
        ArPropertyConstants.ContractsGrantsAgingReportFields.REPORT_RUN_DATE,
        dateFormatter.format(reportRunDate).toString());

    // put bucket dates
    if (StringUtils.equals(columnTitle, customerNumberLabel)) {
      parameters.put("columnTitle", KFSConstants.CustomerOpenItemReport.ALL_DAYS);
      parameters.put("startDate", "");
      parameters.put("endDate", dateFormatter.format(reportRunDate).toString());
    } else {
      if (StringUtils.equals(columnTitle, cutoffdate30Label)) {
        parameters.put(
            "startDate", dateFormatter.format(DateUtils.addDays(reportRunDate, -30)).toString());
        parameters.put("endDate", dateFormatter.format(reportRunDate).toString());
      } else if (StringUtils.equals(columnTitle, cutoffdate60Label)) {
        parameters.put(
            "startDate", dateFormatter.format(DateUtils.addDays(reportRunDate, -60)).toString());
        parameters.put(
            "endDate", dateFormatter.format(DateUtils.addDays(reportRunDate, -31)).toString());
      } else if (StringUtils.equals(columnTitle, cutoffdate90Label)) {
        parameters.put(
            "startDate", dateFormatter.format(DateUtils.addDays(reportRunDate, -90)).toString());
        parameters.put("endDate", dateFormatter.format(DateUtils.addDays(reportRunDate, -61)));
      } else if (StringUtils.equals(columnTitle, cutoffdate91toSYSPRlabel)) {
        parameters.put(
            "startDate", dateFormatter.format(DateUtils.addDays(reportRunDate, -120)).toString());
        parameters.put(
            "endDate", dateFormatter.format(DateUtils.addDays(reportRunDate, -91)).toString());
      } else if (StringUtils.equals(columnTitle, cutoffdateSYSPRplus1orMorelabel)) {
        parameters.put("startDate", "");
        parameters.put(
            "endDate", dateFormatter.format(DateUtils.addDays(reportRunDate, -121)).toString());
        columnTitle =
            Integer.toString((Integer.parseInt(nbrDaysForLastBucket)) + 1) + " days and older";
      } else {
        parameters.put("startDate", "");
        parameters.put("endDate", dateFormatter.format(reportRunDate).toString());
      }
      parameters.put("columnTitle", columnTitle);
    }
    return UrlFactory.parameterizeUrl(
        "arContractsGrantsAgingOpenInvoicesReportLookup.do", parameters);
  }
  /**
   * Get the search results that meet the input search criteria.
   *
   * @param fieldValues - Map containing prop name keys and search values
   * @return a List of found business objects
   */
  @Override
  public List getSearchResults(Map fieldValues) {
    List<ContractsAndGrantsAgingReport> results = new ArrayList<ContractsAndGrantsAgingReport>();
    setBackLocation((String) fieldValues.get(KFSConstants.BACK_LOCATION));
    setDocFormKey((String) fieldValues.get(KFSConstants.DOC_FORM_KEY));

    total0to30 = KualiDecimal.ZERO;
    total31to60 = KualiDecimal.ZERO;
    total61to90 = KualiDecimal.ZERO;
    total91toSYSPR = KualiDecimal.ZERO;
    totalSYSPRplus1orMore = KualiDecimal.ZERO;
    totalOpenInvoices = KualiDecimal.ZERO;
    totalWriteOffs = KualiDecimal.ZERO;
    totalCredits = KualiDecimal.ZERO;

    Collection<CustomerInvoiceDocument> invoices = new ArrayList<CustomerInvoiceDocument>();
    Map<String, ContractsAndGrantsAgingReport> knownCustomers =
        new HashMap<String, ContractsAndGrantsAgingReport>();
    ContractsAndGrantsAgingReport custDetail;

    DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
    dateFormat.setLenient(false);

    Date today = getDateTimeService().getCurrentDate();
    String reportRunDateStr =
        (String) fieldValues.get(ArPropertyConstants.CustomerAgingReportFields.REPORT_RUN_DATE);
    try {

      if (ObjectUtils.isNull(reportRunDateStr) || reportRunDateStr.isEmpty()) {
        reportRunDate = today;
      } else {
        reportRunDate = dateFormat.parse(reportRunDateStr);
      }
      // set dates for buckets
      Date cutoffdate30 = DateUtils.addDays(reportRunDate, -30);
      Date cutoffdate31 = DateUtils.addDays(reportRunDate, -31);
      Date cutoffdate60 = DateUtils.addDays(reportRunDate, -60);
      Date cutoffdate61 = DateUtils.addDays(reportRunDate, -61);
      Date cutoffdate90 = DateUtils.addDays(reportRunDate, -90);
      Date cutoffdate91 = DateUtils.addDays(reportRunDate, -91);
      Date cutoffdate120 =
          DateUtils.addDays(reportRunDate, -1 * Integer.parseInt(nbrDaysForLastBucket));
      Date cutoffdate121 = DateUtils.addDays(cutoffdate120, -1);

      // retrieve filtered data according to the lookup
      Map<String, List<ContractsGrantsInvoiceDocument>> cgMapByCustomer =
          contractsGrantsAgingReportService.filterContractsGrantsAgingReport(
              fieldValues, null, new java.sql.Date(reportRunDate.getTime()));
      if (ObjectUtils.isNotNull(cgMapByCustomer) && !cgMapByCustomer.isEmpty()) {
        // 30 days
        computeFor0To30DaysByBillingChartAndOrg(
            cgMapByCustomer,
            new java.sql.Date(cutoffdate30.getTime()),
            new java.sql.Date(reportRunDate.getTime()),
            knownCustomers);
        // 60 days
        computeFor31To60DaysByBillingChartAndOrg(
            cgMapByCustomer,
            new java.sql.Date(cutoffdate60.getTime()),
            new java.sql.Date(cutoffdate31.getTime()),
            knownCustomers);
        // 90 days
        computeFor61To90DaysByBillingChartAndOrg(
            cgMapByCustomer,
            new java.sql.Date(cutoffdate90.getTime()),
            new java.sql.Date(cutoffdate61.getTime()),
            knownCustomers);
        // 120 days
        computeFor91ToSYSPRDaysByBillingChartAndOrg(
            cgMapByCustomer,
            new java.sql.Date(cutoffdate120.getTime()),
            new java.sql.Date(cutoffdate91.getTime()),
            knownCustomers);
        // 120 + older
        computeForSYSPRplus1orMoreDaysByBillingChartAndOrg(
            cgMapByCustomer, null, new java.sql.Date(cutoffdate121.getTime()), knownCustomers);
        // credits
        calculateTotalCreditsForCustomers(cgMapByCustomer, knownCustomers);
      }

      CustomerAgingReportDao agingReportDao = SpringContext.getBean(CustomerAgingReportDao.class);
      // prepare customer map.

      for (ContractsAndGrantsAgingReport detail : knownCustomers.values()) {

        // get agency name for customer
        ContractsAndGrantsBillingAgency agencyObj = getAgencyByCustomer(detail.getCustomerNumber());
        if (ObjectUtils.isNotNull(agencyObj)) {
          detail.setReportingName(agencyObj.getReportingName());
          detail.setAgencyNumber(agencyObj.getAgencyNumber());
        }

        // set total open invoices
        KualiDecimal amount =
            detail
                .getUnpaidBalance0to30()
                .add(detail.getUnpaidBalance31to60())
                .add(detail.getUnpaidBalance61to90())
                .add(
                    detail
                        .getUnpaidBalance91toSYSPR()
                        .add(detail.getUnpaidBalanceSYSPRplus1orMore()));
        detail.setTotalOpenInvoices(amount);
        totalOpenInvoices = totalOpenInvoices.add(amount);

        // find total writeoff
        KualiDecimal writeOffAmt =
            agingReportDao.findWriteOffAmountByCustomerNumber(detail.getCustomerNumber());
        if (ObjectUtils.isNotNull(writeOffAmt)) {
          totalWriteOffs = totalWriteOffs.add(writeOffAmt);
        } else {
          writeOffAmt = KualiDecimal.ZERO;
        }
        detail.setTotalWriteOff(writeOffAmt);

        // calculate total credits
        results.add(detail);
      }
    } catch (Exception ex) {
      LOG.error(
          "problem during ContractsGrantsAgingReportLookupableHelperServiceImpl.getSearchResults()",
          ex);
    }
    return new CollectionIncomplete<ContractsAndGrantsAgingReport>(results, (long) results.size());
  }