/*
* 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.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.integration.cg.ContractsAndGrantsAward;
import org.kuali.kfs.integration.cg.ContractsAndGrantsBillingAward;
import org.kuali.kfs.integration.cg.ContractsAndGrantsModuleBillingService;
import org.kuali.kfs.module.ar.ArConstants;
import org.kuali.kfs.module.ar.ArPropertyConstants;
import org.kuali.kfs.module.ar.businessobject.ContractsGrantsInvoiceReport;
import org.kuali.kfs.module.ar.businessobject.ContractsGrantsSuspendedInvoiceDetailReport;
import org.kuali.kfs.module.ar.businessobject.InvoiceSuspensionCategory;
import org.kuali.kfs.module.ar.document.ContractsGrantsInvoiceDocument;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.rice.core.api.search.SearchOperator;
import org.kuali.rice.kim.api.KimConstants;
import org.kuali.rice.kim.api.identity.Person;
import org.kuali.rice.kim.api.identity.PersonService;
import org.kuali.rice.kns.document.authorization.BusinessObjectRestrictions;
import org.kuali.rice.kns.lookup.HtmlData;
import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
import org.kuali.rice.kns.web.comparator.CellComparatorHelper;
import org.kuali.rice.kns.web.struts.form.LookupForm;
import org.kuali.rice.kns.web.ui.Column;
import org.kuali.rice.kns.web.ui.ResultRow;
import org.kuali.rice.krad.bo.BusinessObject;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
import org.kuali.rice.krad.util.ObjectUtils;
/**
* Defines a lookupable helper class for Suspended Invoice Detail Report.
*/
public class ContractsGrantsSuspendedInvoiceDetailReportLookupableHelperServiceImpl extends ContractsGrantsSuspendedInvoiceReportLookupableHelperServiceImplBase {
private org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ContractsGrantsSuspendedInvoiceDetailReportLookupableHelperServiceImpl.class);
protected PersonService personService;
protected ContractsAndGrantsModuleBillingService contractsAndGrantsModuleBillingService;
/**
* 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));
List<ContractsGrantsSuspendedInvoiceDetailReport> displayList = new ArrayList<ContractsGrantsSuspendedInvoiceDetailReport>();
Map<String, String> invoiceDocumentCriteria = new HashMap<>();
final String suspensionCategoryCode = (String)lookupFormFields.get(ArPropertyConstants.SuspensionCategoryReportFields.SUSPENSION_CATEGORY_CODE);
if (StringUtils.isNotBlank(suspensionCategoryCode)) {
invoiceDocumentCriteria.put(ArPropertyConstants.SuspensionCategoryReportFields.CONTRACTS_GRANTS_INVOICE_DOCUMENT_SUSPENSION_CATEGORY_CODE, suspensionCategoryCode);
}
final String documentNumber = (String)lookupFormFields.get(KFSPropertyConstants.DOCUMENT_NUMBER);
final List<? extends ContractsAndGrantsAward> matchingAwards = lookupMatchingAwards(lookupFormFields);
if (matchingAwards != null) { // null means that no award-based criteria were used in the search and therefore, these values should not be used for document selection
if (matchingAwards.isEmpty()) { //we searched on awards, but didn't find any. So we can't find any matching documents
return displayList;
}
final String proposalNumbers = harvestIdsFromAwards(matchingAwards);
if (!StringUtils.isBlank(proposalNumbers)) {
invoiceDocumentCriteria.put(ArPropertyConstants.ContractsGrantsInvoiceDocumentFields.PROPOSAL_NUMBER, proposalNumbers);
}
}
final String processingDocumentStatuses = buildProcessingDocumentStatusesForLookup();
invoiceDocumentCriteria.put(KFSPropertyConstants.DOCUMENT_HEADER+"."+KFSPropertyConstants.WORKFLOW_DOCUMENT_STATUS_CODE, processingDocumentStatuses);
Collection<ContractsGrantsInvoiceDocument> cgInvoiceDocuments = getLookupService().findCollectionBySearchHelper(ContractsGrantsInvoiceDocument.class, invoiceDocumentCriteria, true);
for (ContractsGrantsInvoiceDocument cgInvoiceDoc : cgInvoiceDocuments) {
if (!ObjectUtils.isNull(cgInvoiceDoc.getInvoiceSuspensionCategories()) && !cgInvoiceDoc.getInvoiceSuspensionCategories().isEmpty()) { // only report on documents which have suspension categories associated
if (StringUtils.isBlank(documentNumber) || StringUtils.equals(documentNumber, cgInvoiceDoc.getDocumentNumber())) {
for (InvoiceSuspensionCategory invoiceSuspensionCategory : cgInvoiceDoc.getInvoiceSuspensionCategories()) {
Pattern suspensionCategoryCodePattern = null;
if (!StringUtils.isBlank(suspensionCategoryCode)) {
suspensionCategoryCodePattern = Pattern.compile(suspensionCategoryCode.replace("*", ".*"), Pattern.CASE_INSENSITIVE);
}
if (StringUtils.isBlank(suspensionCategoryCode) ||
(suspensionCategoryCodePattern != null && suspensionCategoryCodePattern.matcher(invoiceSuspensionCategory.getSuspensionCategoryCode()).matches())) {
ContractsGrantsSuspendedInvoiceDetailReport cgSuspendedInvoiceDetailReport = new ContractsGrantsSuspendedInvoiceDetailReport();
cgSuspendedInvoiceDetailReport.setSuspensionCategoryCode(invoiceSuspensionCategory.getSuspensionCategoryCode());
cgSuspendedInvoiceDetailReport.setDocumentNumber(cgInvoiceDoc.getDocumentNumber());
cgSuspendedInvoiceDetailReport.setLetterOfCreditFundGroupCode(null);
if (ObjectUtils.isNotNull(cgInvoiceDoc.getInvoiceGeneralDetail().getAward())) {
if (ObjectUtils.isNotNull(cgInvoiceDoc.getInvoiceGeneralDetail().getAward().getLetterOfCreditFund())) {
cgSuspendedInvoiceDetailReport.setLetterOfCreditFundGroupCode(cgInvoiceDoc.getInvoiceGeneralDetail().getAward().getLetterOfCreditFund().getLetterOfCreditFundGroupCode());
}
}
ContractsAndGrantsBillingAward award = cgInvoiceDoc.getInvoiceGeneralDetail().getAward();
Person fundManager = award.getAwardPrimaryFundManager().getFundManager();
String fundManagerPrincipalName = fundManager.getPrincipalName();
Person projectDirector = award.getAwardPrimaryProjectDirector().getProjectDirector();
String projectDirectorPrincipalName = projectDirector.getPrincipalName();
cgSuspendedInvoiceDetailReport.setAwardFundManager(fundManager);
cgSuspendedInvoiceDetailReport.setAwardProjectDirector(projectDirector);
cgSuspendedInvoiceDetailReport.setFundManagerPrincipalName(fundManagerPrincipalName);
cgSuspendedInvoiceDetailReport.setProjectDirectorPrincipalName(projectDirectorPrincipalName);
cgSuspendedInvoiceDetailReport.setAwardTotal(award.getAwardTotalAmount());
if (!displayList.contains(cgSuspendedInvoiceDetailReport)) {
displayList.add(cgSuspendedInvoiceDetailReport);
}
}
}
}
}
}
buildResultTable(lookupForm, displayList, resultTable);
return displayList;
}
/**
* Substitutes the fields on the lookup to match what the ORM is actually expecting
* @param lookupFields the lookup fields to substitute column names for prior to the lookup
*/
protected List<? extends ContractsAndGrantsAward> lookupMatchingAwards(@SuppressWarnings("rawtypes") Map lookupFields) {
Map<String, String> awardLookupFields = new HashMap<String, String>();
List<ContractsAndGrantsAward> filteredAwards = new ArrayList<ContractsAndGrantsAward>();
// letterOfCreditFundGroupCode should be award.letterOfCreditFund.letterOfCreditFundGroupCode
final String letterOfCreditFundGroupCode = (String)lookupFields.get(ArPropertyConstants.LETTER_OF_CREDIT_FUND_GROUP_CODE);
if (!StringUtils.isBlank(letterOfCreditFundGroupCode)) {
awardLookupFields.put(ArPropertyConstants.LETTER_OF_CREDIT_FUND+"."+ArPropertyConstants.LETTER_OF_CREDIT_FUND_GROUP_CODE, letterOfCreditFundGroupCode);
}
// awardTotal should be award.awardTotalAmount
final String awardTotal = (String)lookupFields.get(ArConstants.AWARD_TOTAL);
if (!StringUtils.isBlank(awardTotal)) {
awardLookupFields.put(ArConstants.AWARD_TOTAL, awardTotal);
}
// awardFundManager.principalName should be award.awardPrimaryFundManager.fundManager.principalId
final String fundManagerPrincipalName = (String)lookupFields.get(ArConstants.AWARD_FUND_MANAGER+"."+KimConstants.UniqueKeyConstants.PRINCIPAL_NAME);
final Set<String> fundManagerPrincipalIds = getContractsGrantsReportHelperService().lookupPrincipalIds(fundManagerPrincipalName);
if (StringUtils.isNotBlank(fundManagerPrincipalName)) {
if (fundManagerPrincipalIds.isEmpty()) {
// no fund manager found, invalid name, return empty list to get no records found message
return filteredAwards;
} else {
final String joinedFundManagerPrincipalIds = StringUtils.join(fundManagerPrincipalIds, SearchOperator.OR.op());
awardLookupFields.put(ArConstants.AWARD_FUND_MANAGERS+"."+KFSPropertyConstants.PRINCIPAL_ID, joinedFundManagerPrincipalIds);
}
}
// awardProjectDirector.principalName should be award.awardPrimaryProjectDirector.projectDirector.principalId
final String projectDirectorPrincipalName = (String)lookupFields.get(ArConstants.AWARD_PROJECT_DIRECTOR+"."+KimConstants.UniqueKeyConstants.PRINCIPAL_NAME);
final Set<String> projectDirectorPrincipalIds = getContractsGrantsReportHelperService().lookupPrincipalIds(projectDirectorPrincipalName);
if (StringUtils.isNotBlank(projectDirectorPrincipalName)) {
if (projectDirectorPrincipalIds.isEmpty()) {
// no fund manager found, invalid name, return empty list to get no records found message
return filteredAwards;
} else {
final String joinedProjectDirectorPrincipalIds = StringUtils.join(projectDirectorPrincipalIds, SearchOperator.OR.op());
awardLookupFields.put(ArConstants.AWARD_PROJECT_DIRECTORS+"."+KFSPropertyConstants.PRINCIPAL_ID, joinedProjectDirectorPrincipalIds);
}
}
if (awardLookupFields.isEmpty()) {
return null; // nothing to lookup, so send back null to signal that we shouldn't even filter based on awards
}
// add active check
awardLookupFields.put(KFSPropertyConstants.ACTIVE, KFSConstants.ACTIVE_INDICATOR);
final List<? extends ContractsAndGrantsAward> awards = getContractsAndGrantsModuleBillingService().lookupAwards(awardLookupFields, true);
return awards;
}
/**
* Harvests the proposal ids from the given awards and builds a lookup ready String of proposal id's
* @param awards the awards to harvest ids from
* @return a lookup ready String of proposal id's, or'd together
*/
protected String harvestIdsFromAwards(List<? extends ContractsAndGrantsAward> awards) {
if (awards.isEmpty()) {
return KFSConstants.EMPTY_STRING;
}
Set<String> proposalIdsSet = new HashSet<String>();
for (ContractsAndGrantsAward award : awards) {
proposalIdsSet.add(award.getProposalNumber().toString());
}
final String proposalIdsForLookup = StringUtils.join(proposalIdsSet, SearchOperator.OR.op());
return proposalIdsForLookup;
}
@Override
protected void buildResultTable(LookupForm lookupForm, Collection displayList, Collection resultTable) {
Person user = GlobalVariables.getUserSession().getPerson();
boolean hasReturnableRow = false;
// iterate through result list and wrap rows with return url and action urls
for (Iterator iter = displayList.iterator(); iter.hasNext();) {
BusinessObject element = (BusinessObject) iter.next();
BusinessObjectRestrictions businessObjectRestrictions = getBusinessObjectAuthorizationService().getLookupResultRestrictions(element, user);
List<Column> columns = getColumns();
for (Iterator iterator = columns.iterator(); iterator.hasNext();) {
Column col = (Column) iterator.next();
String propValue = ObjectUtils.getFormattedPropertyValue(element, col.getPropertyName(), col.getFormatter());
Class propClass = getPropertyClass(element, col.getPropertyName());
col.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(propClass));
col.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(propClass));
String propValueBeforePotientalMasking = propValue;
propValue = maskValueIfNecessary(element.getClass(), col.getPropertyName(), propValue, businessObjectRestrictions);
col.setPropertyValue(propValue);
// Add url when property is documentNumber
if (col.getPropertyName().equals(KFSPropertyConstants.DOCUMENT_NUMBER)) {
String url = contractsGrantsReportHelperService.getDocSearchUrl(propValue);
Map<String, String> fieldList = new HashMap<String, String>();
fieldList.put(KFSPropertyConstants.DOCUMENT_NUMBER, propValue);
AnchorHtmlData a = new AnchorHtmlData(url, KRADConstants.EMPTY_STRING);
a.setTitle(HtmlData.getTitleText(getContractsGrantsReportHelperService().createTitleText(ContractsGrantsInvoiceReport.class), ContractsGrantsInvoiceReport.class, fieldList));
col.setColumnAnchor(a);
}
}
ResultRow row = new ResultRow(columns, "", ACTION_URLS_EMPTY);
if (getBusinessObjectDictionaryService().isExportable(getBusinessObjectClass())) {
row.setBusinessObject(element);
}
boolean isRowReturnable = isResultReturnable(element);
row.setRowReturnable(isRowReturnable);
if (isRowReturnable) {
hasReturnableRow = true;
}
resultTable.add(row);
}
lookupForm.setHasReturnableRow(hasReturnableRow);
}
public PersonService getPersonService() {
return personService;
}
public void setPersonService(PersonService personService) {
this.personService = personService;
}
public ContractsAndGrantsModuleBillingService getContractsAndGrantsModuleBillingService() {
return contractsAndGrantsModuleBillingService;
}
public void setContractsAndGrantsModuleBillingService(ContractsAndGrantsModuleBillingService contractsAndGrantsModuleBillingService) {
this.contractsAndGrantsModuleBillingService = contractsAndGrantsModuleBillingService;
}
}