org.kuali.kfs.module.cab.businessobject.lookup.PurApReportLookupableHelperServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.kfs.module.cab.businessobject.lookup.PurApReportLookupableHelperServiceImpl.java

Source

/*
 * 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.cab.businessobject.lookup;

import java.sql.Date;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.module.cab.CabConstants;
import org.kuali.kfs.module.cab.CabPropertyConstants;
import org.kuali.kfs.module.cab.businessobject.GeneralLedgerEntry;
import org.kuali.kfs.module.cab.businessobject.PurchasingAccountsPayableDocument;
import org.kuali.kfs.module.cab.businessobject.PurchasingAccountsPayableProcessingReport;
import org.kuali.kfs.module.cab.service.PurchasingAccountsPayableReportService;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.kuali.rice.kim.api.KimConstants;
import org.kuali.rice.kim.api.services.IdentityManagementService;
import org.kuali.rice.kns.lookup.HtmlData;
import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl;
import org.kuali.rice.kns.lookup.LookupUtils;
import org.kuali.rice.krad.bo.BusinessObject;
import org.kuali.rice.krad.lookup.CollectionIncomplete;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
import org.kuali.rice.krad.util.ObjectUtils;
import org.kuali.rice.krad.util.UrlFactory;

/**
 * This class overrids the base getActionUrls method
 */
public class PurApReportLookupableHelperServiceImpl extends KualiLookupableHelperServiceImpl {
    private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
            .getLogger(PurApReportLookupableHelperServiceImpl.class);

    private PurchasingAccountsPayableReportService purApReportService;

    /**
     * Custom action urls for CAB PurAp lines.
     *
     * @see org.kuali.rice.kns.lookup.LookupableHelperService#getCustomActionUrls(org.kuali.rice.krad.bo.BusinessObject,
     *      java.util.List, java.util.List pkNames)
     */
    @Override
    public List<HtmlData> getCustomActionUrls(BusinessObject bo, List pkNames) {
        Map<String, String> permissionDetails = new HashMap<String, String>();
        permissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, "KFS-CAB");
        permissionDetails.put(KimConstants.AttributeConstants.ACTION_CLASS, "PurApLineAction");

        if (!SpringContext.getBean(IdentityManagementService.class).isAuthorizedByTemplateName(
                GlobalVariables.getUserSession().getPrincipalId(), KRADConstants.KNS_NAMESPACE,
                KimConstants.PermissionTemplateNames.USE_SCREEN, permissionDetails, null)) {
            return super.getEmptyActionUrls();
        }

        GeneralLedgerEntry glEntry = (GeneralLedgerEntry) bo;

        Properties parameters = new Properties();
        parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, CabConstants.Actions.START);
        if (glEntry.getReferenceFinancialDocumentNumber() != null) {
            parameters.put(CabPropertyConstants.PurchasingAccountsPayableDocument.PURCHASE_ORDER_IDENTIFIER,
                    glEntry.getReferenceFinancialDocumentNumber());
        }

        String href = UrlFactory.parameterizeUrl(CabConstants.CB_INVOICE_LINE_ACTION_URL, parameters);
        List<HtmlData> anchorHtmlDataList = new ArrayList<HtmlData>();
        AnchorHtmlData anchorHtmlData = new AnchorHtmlData(href, CabConstants.Actions.START,
                CabConstants.ActivityStatusCode.PROCESSED_IN_CAMS.equalsIgnoreCase(glEntry.getActivityStatusCode())
                        ? CabConstants.Actions.VIEW
                        : CabConstants.Actions.PROCESS);
        anchorHtmlData.setTarget(KFSConstants.NEW_WINDOW_URL_TARGET);
        anchorHtmlDataList.add(anchorHtmlData);
        return anchorHtmlDataList;
    }

    /**
     * @see org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl#getSearchResults(java.util.Map)
     */
    @Override
    public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
        setBackLocation(fieldValues.get(KFSConstants.BACK_LOCATION));
        setDocFormKey(fieldValues.get(KFSConstants.DOC_FORM_KEY));

        // purapDocumentIdentifier should query PurchasingAccountsPayableDocument
        String purapDocumentIdentifier = getSelectedField(fieldValues,
                CabPropertyConstants.PurchasingAccountsPayableProcessingReport.PURAP_DOCUMENT_IDENTIFIER);

        // Get the user selects 'Y' for "processed by CAMs". We will search for all status GL lines. This is because of the partial
        // submitted GL lines when GL is 'N'(new) or 'M'(modified), partial GL lines could submit to CAMs. we should include these
        // lines into the search result.
        String active = getSelectedField(fieldValues, CabPropertyConstants.GeneralLedgerEntry.ACTIVITY_STATUS_CODE);
        if (KFSConstants.ACTIVE_INDICATOR.equalsIgnoreCase(active)) {
            fieldValues.remove(CabPropertyConstants.GeneralLedgerEntry.ACTIVITY_STATUS_CODE);
        }
        // search for GeneralLedgerEntry BO.
        Iterator searchResultIterator = purApReportService.findGeneralLedgers(fieldValues);
        // create PurchasingAccountsPayableProcessingReport search result collection.
        List<PurchasingAccountsPayableProcessingReport> purApReportList = buildGlEntrySearchResultCollection(
                searchResultIterator, active);

        // purapDocumentIdentifier is the attribute in PurchasingAccountsPayableDocument. We need to generate a new lookup for that
        // BO, then join search results with the generalLedgerCollection to get the correct search result collection.
        if (StringUtils.isNotBlank(purapDocumentIdentifier)) {
            // construct the lookup criteria for PurchasingAccountsPayableDocument from user input
            Map<String, String> purapDocumentLookupFields = getPurApDocumentLookupFields(fieldValues,
                    purapDocumentIdentifier);

            Collection purApDocs = purApReportService
                    .findPurchasingAccountsPayableDocuments(purapDocumentLookupFields);

            Map<String, Integer> purApDocNumberMap = buildDocumentNumberMap(purApDocs);

            purApReportList = updatePurApReportListByPurApDocs(purApReportList, purApDocNumberMap);
        } else {
            purApReportList = updateResultList(purApReportList);
        }

        return buildSearchResultList(purApReportList);
    }

    /**
     * Get PurapDocumentIdentifier from PurchasingAccountsPayableDocument and add it to the search result.
     *
     * @param purApReportCollection
     */
    private List<PurchasingAccountsPayableProcessingReport> updateResultList(
            List<PurchasingAccountsPayableProcessingReport> purApReportList) {
        List<PurchasingAccountsPayableProcessingReport> newResultList = new ArrayList<PurchasingAccountsPayableProcessingReport>();
        BusinessObjectService boService = this.getBusinessObjectService();
        Map pKeys = new HashMap<String, String>();

        for (PurchasingAccountsPayableProcessingReport report : purApReportList) {
            pKeys.put(CabPropertyConstants.PurchasingAccountsPayableDocument.DOCUMENT_NUMBER,
                    report.getDocumentNumber());
            PurchasingAccountsPayableDocument purApDocument = boService
                    .findByPrimaryKey(PurchasingAccountsPayableDocument.class, pKeys);
            if (ObjectUtils.isNotNull(purApDocument)) {
                report.setPurapDocumentIdentifier(purApDocument.getPurapDocumentIdentifier());
                newResultList.add(report);
            }
            pKeys.clear();
        }
        return newResultList;
    }

    /**
     * Build the search result list.
     *
     * @param purApReportCollection
     * @return
     */
    private List<? extends BusinessObject> buildSearchResultList(List purApReportList) {
        List<? extends BusinessObject> searchResults = null;

        Integer searchResultsLimit = LookupUtils
                .getSearchResultsLimit(PurchasingAccountsPayableProcessingReport.class);
        Long matchingResultsCount = Long.valueOf(purApReportList.size());

        // apply results set limit if necessary
        if (searchResultsLimit > 0 && matchingResultsCount.intValue() > searchResultsLimit.intValue()) {
            searchResults = new CollectionIncomplete(purApReportList.subList(0, searchResultsLimit),
                    matchingResultsCount);
        } else {
            searchResults = new CollectionIncomplete(purApReportList, 0L);
        }

        return searchResults;
    }

    /**
     * Build a HashMap for documentNumbers from the PurchasingAccountsPayableDocument search results
     *
     * @param purApDocs
     * @return
     */
    private Map<String, Integer> buildDocumentNumberMap(Collection purApDocs) {
        Map<String, Integer> purApDocNumbers = new HashMap<String, Integer>();
        for (Iterator iterator = purApDocs.iterator(); iterator.hasNext();) {
            PurchasingAccountsPayableDocument purApdoc = (PurchasingAccountsPayableDocument) iterator.next();
            purApDocNumbers.put(purApdoc.getDocumentNumber(), purApdoc.getPurapDocumentIdentifier());
        }
        return purApDocNumbers;
    }

    /**
     * Build lookup fields for PurchasingAccountsPayableDocument lookup.
     *
     * @param fieldValues
     * @param purapDocumentIdentifier
     * @return
     */
    private Map<String, String> getPurApDocumentLookupFields(Map<String, String> fieldValues,
            String purapDocumentIdentifier) {
        Map<String, String> purapDocumentLookupFields = new HashMap<String, String>();
        purapDocumentLookupFields.put(
                CabPropertyConstants.PurchasingAccountsPayableDocument.PURAP_DOCUMENT_IDENTIFIER,
                purapDocumentIdentifier);
        purapDocumentLookupFields.put(CabPropertyConstants.PurchasingAccountsPayableDocument.DOCUMENT_NUMBER,
                fieldValues.get(CabPropertyConstants.GeneralLedgerEntry.DOCUMENT_NUMBER));
        purapDocumentLookupFields.put(
                CabPropertyConstants.PurchasingAccountsPayableDocument.PURCHASE_ORDER_IDENTIFIER,
                fieldValues.get(CabPropertyConstants.GeneralLedgerEntry.REFERENCE_FINANCIAL_DOCUMENT_NUMBER));
        return purapDocumentLookupFields;
    }

    /**
     * Join PurapReportCollection and PurApDocsCollection by documentNumber and remove from PurapReportCollection for mismatch.
     *
     * @param purApReportCollection
     * @param purApDocNumbers
     */
    private List<PurchasingAccountsPayableProcessingReport> updatePurApReportListByPurApDocs(
            List<PurchasingAccountsPayableProcessingReport> purApReportList,
            Map<String, Integer> purApDocNumberMap) {
        List<PurchasingAccountsPayableProcessingReport> newReportsList = new ArrayList<PurchasingAccountsPayableProcessingReport>();

        for (PurchasingAccountsPayableProcessingReport report : purApReportList) {
            if (purApDocNumberMap.containsKey(report.getDocumentNumber())) {
                report.setPurapDocumentIdentifier(purApDocNumberMap.get(report.getDocumentNumber()));
                newReportsList.add(report);
            }
        }
        // remove from report collection
        return newReportsList;
    }

    /**
     * Build search result collection as PurchasingAccountsPayableProcessingReport collection.
     *
     * @param searchResultIterator
     * @return
     */
    private List<PurchasingAccountsPayableProcessingReport> buildGlEntrySearchResultCollection(
            Iterator searchResultIterator, String activeSelection) {
        List<PurchasingAccountsPayableProcessingReport> purApReportList = new ArrayList();

        while (searchResultIterator.hasNext()) {
            Object glEntry = searchResultIterator.next();

            if (glEntry.getClass().isArray()) {
                int i = 0;
                Object[] columnValues = (Object[]) glEntry;

                PurchasingAccountsPayableProcessingReport newReport = new PurchasingAccountsPayableProcessingReport();

                newReport.setUniversityFiscalYear(new Integer(columnValues[i++].toString()));
                newReport.setUniversityFiscalPeriodCode(columnValues[i++].toString());
                newReport.setChartOfAccountsCode(columnValues[i++].toString());
                newReport.setAccountNumber(columnValues[i++].toString());
                newReport.setFinancialObjectCode(columnValues[i++].toString());
                newReport.setFinancialDocumentTypeCode(columnValues[i++].toString());
                newReport.setDocumentNumber(columnValues[i++].toString());
                newReport
                        .setTransactionDebitCreditCode(columnValues[i] == null ? null : columnValues[i].toString());
                i++;
                newReport.setTransactionLedgerEntryAmount(
                        columnValues[i] == null ? null : new KualiDecimal(columnValues[i].toString()));
                i++;
                newReport.setReferenceFinancialDocumentNumber(
                        columnValues[i] == null ? null : columnValues[i].toString());
                i++;
                newReport.setTransactionDate(columnValues[i] == null ? null : getDate(columnValues[i]));
                i++;
                newReport.setTransactionLedgerSubmitAmount(
                        columnValues[i] == null ? null : new KualiDecimal(columnValues[i].toString()));
                i++;
                newReport.setActivityStatusCode(columnValues[i] == null ? null : columnValues[i].toString());

                if (!excludeFromSearchResults(newReport, activeSelection)) {
                    if (newReport.getActivityStatusCode() != null && newReport.isActive()) {
                        // adjust amount if the activity_status_code is 'N' or 'M'
                        if (newReport.getTransactionLedgerEntryAmount() != null) {
                            setReportAmount(activeSelection, newReport);
                        }
                    } else {
                        // set report amount by transactional Amount
                        newReport.setReportAmount(newReport.getAmount());
                    }
                    purApReportList.add(newReport);
                }
            }
        }
        return purApReportList;
    }

    /**
     * Get the Date instance. Why we need this? Looks OJB returns different type of instance when connect to MySql and Oracle:
     * Oracle returns Date instance while MySql returns TimeStamp instance.
     *
     * @param obj
     * @return
     */
    private Date getDate(Object obj) {
        if (obj instanceof Date) {
            return (Date) obj;
        } else if (obj instanceof Timestamp) {
            Timestamp tsp = (Timestamp) obj;
            return new Date(tsp.getTime());
        } else {
            return null;
        }
    }

    /**
     * To decide if the the given newReport should be added to the search result collection.
     *
     * @param newReport
     * @param activeSelection
     * @return
     */
    private boolean excludeFromSearchResults(PurchasingAccountsPayableProcessingReport newReport,
            String activeSelection) {
        // If the user selects processed by CAMs, we should exclude the GL lines which have no submit amount as the search result
        if ((KFSConstants.ACTIVE_INDICATOR.equalsIgnoreCase(activeSelection)
                && (newReport.getTransactionLedgerSubmitAmount() == null
                        || newReport.getTransactionLedgerSubmitAmount().isZero()))) {
            return true;
        }
        return false;
    }

    /**
     * set partial commit report amount
     *
     * @param active
     * @param newReport
     */
    private void setReportAmount(String active, PurchasingAccountsPayableProcessingReport newReport) {
        if (KFSConstants.ACTIVE_INDICATOR.equalsIgnoreCase(active)) {
            // Processed in CAMS: set report amount as submitted amount
            newReport.setReportAmount(newReport.getTransactionLedgerSubmitAmount());
        } else if ((KFSConstants.NON_ACTIVE_INDICATOR.equalsIgnoreCase(active))) {
            // Not Processed in CAMS: set report amount by transactionLedgerEntryAmount excluding submitted amount
            KualiDecimal reportAmount = newReport.getAmount();
            if (reportAmount != null && newReport.getTransactionLedgerSubmitAmount() != null) {
                newReport.setReportAmount(reportAmount.subtract(newReport.getTransactionLedgerSubmitAmount()));
            } else {
                newReport.setReportAmount(reportAmount);
            }
        } else {
            // both processed/non processed: set report amount by transactional amount
            newReport.setReportAmount(newReport.getAmount());
        }
    }

    /**
     * Return and remove the selected field from the user input.
     *
     * @param fieldValues
     * @param fieldName
     * @return
     */
    private String getSelectedField(Map fieldValues, String fieldName) {
        String fieldValue = null;

        if (fieldValues.containsKey(fieldName)) {
            fieldValue = (String) fieldValues.get(fieldName);
        }
        return fieldValue == null ? "" : fieldValue;
    }

    /**
     * Gets the purApReportService attribute.
     *
     * @return Returns the purApReportService.
     */
    public PurchasingAccountsPayableReportService getPurApReportService() {
        return purApReportService;
    }

    /**
     * Sets the purApReportService attribute value.
     *
     * @param purApReportService The purApReportService to set.
     */
    public void setPurApReportService(PurchasingAccountsPayableReportService purApReportService) {
        this.purApReportService = purApReportService;
    }

    @Override
    public BusinessObjectService getBusinessObjectService() {
        return SpringContext.getBean(BusinessObjectService.class);
    }
}