/*
* 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.cg.web.struts;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.kuali.kfs.module.cg.CGConstants;
import org.kuali.kfs.module.cg.businessobject.Award;
import org.kuali.kfs.module.cg.businessobject.ContractsGrantsAwardBalancesReport;
import org.kuali.kfs.module.cg.report.ContractsGrantsAwardBalancesReportDetailDataHolder;
import org.kuali.kfs.module.cg.report.ContractsGrantsReportDataHolder;
import org.kuali.kfs.module.cg.report.ContractsGrantsReportSearchCriteriaDataHolder;
import org.kuali.kfs.module.cg.report.service.ContractsGrantsAwardBalancesReportService;
import org.kuali.kfs.sys.DynamicCollectionComparator;
import org.kuali.kfs.sys.DynamicCollectionComparator.SortOrder;
import org.kuali.kfs.sys.KFSConstants.ReportGeneration;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.kuali.rice.kns.lookup.Lookupable;
import org.kuali.rice.kns.service.DataDictionaryService;
import org.kuali.rice.kns.util.WebUtils;
import org.kuali.rice.kns.web.struts.action.KualiLookupAction;
import org.kuali.rice.kns.web.ui.ResultRow;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
import org.kuali.rice.krad.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* Action Class for Contracts & Grants Award Balances Report Lookup.
*/
public class ContractsGrantsAwardBalancesReportLookupAction extends KualiLookupAction {
/**
* @see org.kuali.rice.kns.web.struts.action.KualiLookupAction#execute(org.apache.struts.action.ActionMapping,
* org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
String sortIndexParameter = request.getParameter("d-16544-s");
if (sortIndexParameter != null) {
// to store how many times user clicks sort links
Integer clickedSession = ObjectUtils.isNull(GlobalVariables.getUserSession().retrieveObject(CGConstants.NUM_SORT_INDEX_CLICK_SESSION_KEY)) ? new Integer(1) : (Integer) GlobalVariables.getUserSession().retrieveObject(CGConstants.NUM_SORT_INDEX_CLICK_SESSION_KEY);
if (ObjectUtils.isNotNull(GlobalVariables.getUserSession().retrieveObject(CGConstants.SORT_INDEX_SESSION_KEY)) && GlobalVariables.getUserSession().retrieveObject(CGConstants.SORT_INDEX_SESSION_KEY).toString().equals(sortIndexParameter)) {
GlobalVariables.getUserSession().addObject(CGConstants.NUM_SORT_INDEX_CLICK_SESSION_KEY, new Integer(clickedSession + 1));
}
GlobalVariables.getUserSession().addObject(CGConstants.SORT_INDEX_SESSION_KEY, sortIndexParameter);
}
return super.execute(mapping, form, request, response);
}
/**
* @param index
* @param businessObjectName
* @return
*/
protected String getFieldNameForSorting(int index, String businessObjectName) {
org.kuali.rice.kns.datadictionary.BusinessObjectEntry boe = (org.kuali.rice.kns.datadictionary.BusinessObjectEntry) SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getBusinessObjectEntry(businessObjectName);
List<String> lookupResultFields = boe.getLookupDefinition().getResultFieldNames();
return lookupResultFields.get(index);
}
/**
* @param list
* @param propertyName
* @return
*/
protected List<String> getListOfValuesSortedProperties(List list, String propertyName) {
List<String> returnList = new ArrayList<String>();
for (Object object : list) {
if (!returnList.contains(getPropertyValue(object, propertyName))) {
returnList.add(getPropertyValue(object, propertyName));
}
}
return returnList;
}
/**
* @param object
* @param propertyName
* @return
*/
protected String getPropertyValue(Object object, String propertyName) {
Object fieldValue = ObjectUtils.getPropertyValue(object, propertyName);
return (ObjectUtils.isNull(fieldValue)) ? "" : StringUtils.trimAllWhitespace(fieldValue.toString());
}
/**
* @param searchCriteria
* @param fieldsForLookup
*/
protected void buildReportForSearchCriteia(List<ContractsGrantsReportSearchCriteriaDataHolder> searchCriteria, Map fieldsForLookup) {
DataDictionaryService dataDictionaryService = SpringContext.getBean(DataDictionaryService.class);
for (Object field : fieldsForLookup.keySet()) {
String fieldString = (ObjectUtils.isNull(field)) ? "" : field.toString();
String valueString = (ObjectUtils.isNull(fieldsForLookup.get(field))) ? "" : fieldsForLookup.get(field).toString();
if (!fieldString.equals("") && !valueString.equals("") && !CGConstants.ReportsConstants.reportSearchCriteriaExceptionList.contains(fieldString)) {
ContractsGrantsReportSearchCriteriaDataHolder criteriaData = new ContractsGrantsReportSearchCriteriaDataHolder();
String label = dataDictionaryService.getAttributeLabel(Award.class, fieldString);
criteriaData.setSearchFieldLabel(label);
criteriaData.setSearchFieldValue(valueString);
searchCriteria.add(criteriaData);
}
}
}
/**
* This method sorts the report.
*
* @param displayList
* @param sortPropertyName
*/
protected void sortReport(List displayList, String sortPropertyName) {
Integer numSortIndexClick = (ObjectUtils.isNull(GlobalVariables.getUserSession().retrieveObject(CGConstants.NUM_SORT_INDEX_CLICK_SESSION_KEY))) ? 1 : new Integer(GlobalVariables.getUserSession().retrieveObject(CGConstants.NUM_SORT_INDEX_CLICK_SESSION_KEY).toString());
if (((numSortIndexClick) % 2) == 0) {
DynamicCollectionComparator.sort(displayList, SortOrder.DESC, sortPropertyName);
}
else {
DynamicCollectionComparator.sort(displayList, SortOrder.ASC, sortPropertyName);
}
}
/**
* This service is used to print the report.
*
* @param mapping
* @param form
* @param request
* @param response
* @return
* @throws Exception
*/
public ActionForward print(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
ContractsGrantsAwardBalancesReportLookupForm awardBalancesReportLookupForm = (ContractsGrantsAwardBalancesReportLookupForm) form;
String methodToCall = findMethodToCall(form, request);
if (methodToCall.equalsIgnoreCase(KRADConstants.SEARCH_METHOD)) {
GlobalVariables.getUserSession().removeObjectsByPrefix(KRADConstants.SEARCH_METHOD);
}
Lookupable kualiLookupable = awardBalancesReportLookupForm.getLookupable();
if (kualiLookupable == null) {
throw new RuntimeException("Lookupable is null.");
}
List<ResultRow> resultTable = new ArrayList<ResultRow>();
// validate search parameters
kualiLookupable.validateSearchParameters(awardBalancesReportLookupForm.getFields());
// this is for 200 limit. turn it off for report.
boolean isUnbounded = true;
List<ContractsGrantsAwardBalancesReport> displayList = (List<ContractsGrantsAwardBalancesReport>) kualiLookupable.performLookup(awardBalancesReportLookupForm, resultTable, isUnbounded);
Object sortIndexObject = GlobalVariables.getUserSession().retrieveObject(CGConstants.SORT_INDEX_SESSION_KEY);
if (ObjectUtils.isNull(sortIndexObject) || sortIndexObject.toString() == "0") {
sortIndexObject = "0";
}
// get sort property
String sortPropertyName = getFieldNameForSorting(Integer.parseInt(sortIndexObject.toString()), "ContractsGrantsAwardBalancesReport");
// sort list
sortReport(displayList, sortPropertyName);
// check field is valid for subtotal
boolean isFieldSubtotalRequired = CGConstants.ReportsConstants.awardBalancesReportSubtotalFieldsList.contains(sortPropertyName);
Map<String, KualiDecimal> subTotalMap = new HashMap<String, KualiDecimal>();
if (isFieldSubtotalRequired) {
subTotalMap = buildSubTotalMap(displayList, sortPropertyName);
}
// build report
ContractsGrantsReportDataHolder awardBalancesReportDataHolder = new ContractsGrantsReportDataHolder();
List<ContractsGrantsAwardBalancesReportDetailDataHolder> details = awardBalancesReportDataHolder.getDetails();
for (ContractsGrantsAwardBalancesReport awardBalancesReportEntry : displayList) {
ContractsGrantsAwardBalancesReportDetailDataHolder reportDetail = new ContractsGrantsAwardBalancesReportDetailDataHolder();
// set report data
setReportDate(awardBalancesReportEntry, reportDetail);
if (isFieldSubtotalRequired) {
// set sortedFieldValue for grouping in the report
reportDetail.setSortedFieldValue(getPropertyValue(awardBalancesReportEntry, sortPropertyName));
reportDetail.setDisplaySubtotal(true);
// set subTotal from subTotalMap
reportDetail.setSubTotal(subTotalMap.get(getPropertyValue(awardBalancesReportEntry, sortPropertyName)).bigDecimalValue());
}
else {
// set this to empty string for not displaying subtotal
reportDetail.setDisplaySubtotal(false);
}
details.add(reportDetail);
}
awardBalancesReportDataHolder.setDetails(details);
// build search criteria for report
buildReportForSearchCriteia(awardBalancesReportDataHolder.getSearchCriteria(), awardBalancesReportLookupForm.getFieldsForLookup());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String reportFileName = SpringContext.getBean(ContractsGrantsAwardBalancesReportService.class).generateReport(awardBalancesReportDataHolder, baos);
WebUtils.saveMimeOutputStreamAsFile(response, ReportGeneration.PDF_MIME_TYPE, baos, reportFileName + ReportGeneration.PDF_FILE_EXTENSION);
return null;
}
/**
* @param displayList
* @param sortPropertyName
* @return
*/
private Map<String, KualiDecimal> buildSubTotalMap(List<ContractsGrantsAwardBalancesReport> displayList, String sortPropertyName) {
Map<String, KualiDecimal> returnSubTotalMap = new HashMap<String, KualiDecimal>();
// get list of sort fields
List<String> valuesOfsortProperty = getListOfValuesSortedProperties(displayList, sortPropertyName);
// calculate sub_total and build subTotalMap
for (String value : valuesOfsortProperty) {
KualiDecimal subTotal = KualiDecimal.ZERO;
for (ContractsGrantsAwardBalancesReport awardBalancesReportEntry : displayList) {
// set fieldValue as "" when it is null
if (value.equals(getPropertyValue(awardBalancesReportEntry, sortPropertyName))) {
subTotal = subTotal.add(awardBalancesReportEntry.getAwardTotalAmount());
}
}
returnSubTotalMap.put(value, subTotal);
}
return returnSubTotalMap;
}
/**
* @param awardBalancesReportEntry
* @param reportDetail
*/
private void setReportDate(ContractsGrantsAwardBalancesReport awardBalancesReportEntry, ContractsGrantsAwardBalancesReportDetailDataHolder reportDetail) {
reportDetail.setProposalNumber(awardBalancesReportEntry.getProposalNumber());
String agencyName = (ObjectUtils.isNull(awardBalancesReportEntry.getAgency())) ? null : awardBalancesReportEntry.getAgency().getReportingName();
reportDetail.setAgencyName(agencyName);
reportDetail.setAwardProjectTitle(awardBalancesReportEntry.getAwardProjectTitle());
reportDetail.setAwardStatusCode(awardBalancesReportEntry.getAwardStatusCode());
reportDetail.setAwardBeginningDate(awardBalancesReportEntry.getAwardBeginningDate());
reportDetail.setAwardEndingDate(awardBalancesReportEntry.getAwardEndingDate());
reportDetail.setPrimaryProjectDirector(awardBalancesReportEntry.getAwardPrimaryProjectDirectorName());
reportDetail.setPrimaryFundManager(awardBalancesReportEntry.getAwardPrimaryFundManagerName());
BigDecimal awardTotalAmount = (ObjectUtils.isNull(awardBalancesReportEntry.getAwardTotalAmountForReport())) ? BigDecimal.ZERO : awardBalancesReportEntry.getAwardTotalAmountForReport().bigDecimalValue();
reportDetail.setAwardTotalAmount(awardTotalAmount);
BigDecimal totalBilledToDate = (ObjectUtils.isNull(awardBalancesReportEntry.getTotalBilledToDate())) ? BigDecimal.ZERO : awardBalancesReportEntry.getTotalBilledToDate().bigDecimalValue();
reportDetail.setTotalBilledToDate(totalBilledToDate);
BigDecimal totalPaymentsToDate = (ObjectUtils.isNull(awardBalancesReportEntry.getTotalPaymentsToDate())) ? BigDecimal.ZERO : awardBalancesReportEntry.getTotalPaymentsToDate().bigDecimalValue();
reportDetail.setTotalPaymentsToDate(totalPaymentsToDate);
reportDetail.setAmountCurrentlyDue(totalBilledToDate.subtract(totalPaymentsToDate));
}
}