/*
* 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.report.service.impl;
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 org.apache.commons.collections.CollectionUtils;
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.CollectionActivityReport;
import org.kuali.kfs.module.ar.businessobject.CollectionActivityType;
import org.kuali.kfs.module.ar.businessobject.CollectionEvent;
import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail;
import org.kuali.kfs.module.ar.document.ContractsGrantsInvoiceDocument;
import org.kuali.kfs.module.ar.document.service.ContractsGrantsInvoiceDocumentService;
import org.kuali.kfs.module.ar.report.service.CollectionActivityReportService;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.document.service.FinancialSystemDocumentService;
import org.kuali.kfs.sys.service.NonTransactional;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.kim.api.identity.Person;
import org.kuali.rice.kim.api.identity.PersonService;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.ObjectUtils;
import org.springframework.transaction.annotation.Transactional;
/**
* This class is used to get the services for PDF generation and other services for Collection Activity Report
*/
public class CollectionActivityReportServiceImpl implements CollectionActivityReportService {
protected ContractsGrantsInvoiceDocumentService contractsGrantsInvoiceDocumentService;
protected ContractsAndGrantsModuleBillingService contractsAndGrantsModuleBillingService;
protected BusinessObjectService businessObjectService;
protected DateTimeService dateTimeService;
protected FinancialSystemDocumentService financialSystemDocumentService;
protected PersonService personService;
private final static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CollectionActivityReportServiceImpl.class);
/**
* @see org.kuali.kfs.module.ar.report.service.ContractsGrantsAgingReportService#filterContractsGrantsAgingReport(java.util.Map)
*/
@Override
@Transactional
public List<CollectionActivityReport> filterEventsForCollectionActivity(Map lookupFormFields) {
List<CollectionActivityReport> displayList = new ArrayList<>();
Map<String,String> fieldValues = new HashMap<>();
String collectorPrincName = (String)lookupFormFields.get(ArPropertyConstants.COLLECTOR_PRINC_NAME);
String collector = (String)lookupFormFields.get(ArPropertyConstants.CollectionActivityReportFields.COLLECTOR);
String proposalNumber = (String)lookupFormFields.get(KFSPropertyConstants.PROPOSAL_NUMBER);
String agencyNumber = (String)lookupFormFields.get(ArPropertyConstants.CollectionActivityReportFields.AGENCY_NUMBER);
String invoiceNumber = (String)lookupFormFields.get(ArPropertyConstants.INVOICE_NUMBER);
String accountNumber = (String)lookupFormFields.get(KFSPropertyConstants.ACCOUNT_NUMBER);
String activityType = (String)lookupFormFields.get(ArPropertyConstants.CollectionActivityReportFields.ACTIVITY_TYPE);
// Getting final docs
fieldValues.put(KFSPropertyConstants.DOCUMENT_HEADER+"."+KFSPropertyConstants.WORKFLOW_DOCUMENT_STATUS_CODE, StringUtils.join(getFinancialSystemDocumentService().getSuccessfulDocumentStatuses(), "|"));
fieldValues.put(KFSPropertyConstants.DOCUMENT_HEADER+"."+KFSPropertyConstants.WORKFLOW_DOCUMENT_TYPE_NAME, ArConstants.ArDocumentTypeCodes.CONTRACTS_GRANTS_INVOICE);
if (!StringUtils.isBlank(proposalNumber)) {
fieldValues.put(KFSPropertyConstants.PROPOSAL_NUMBER, proposalNumber);
}
if (!StringUtils.isBlank(invoiceNumber)) {
fieldValues.put(KFSPropertyConstants.DOCUMENT_NUMBER, invoiceNumber);
}
if (!StringUtils.isBlank(accountNumber)) {
fieldValues.put(ArPropertyConstants.CustomerInvoiceDocumentFields.ACCOUNT_NUMBER, accountNumber);
}
// Filter Invoice docs according to criteria.
Collection<ContractsGrantsInvoiceDocument> contractsGrantsInvoiceDocs = contractsGrantsInvoiceDocumentService.retrieveAllCGInvoicesByCriteria(fieldValues);
if (!CollectionUtils.isEmpty(contractsGrantsInvoiceDocs)) {
String collectorPrincipalId = null;
if (StringUtils.isNotEmpty(collectorPrincName.trim())) {
Person collUser = personService.getPersonByPrincipalName(collectorPrincName);
if (ObjectUtils.isNotNull(collUser)) {
collectorPrincipalId = collUser.getPrincipalId();
}
}
Set<String> agencyNumbers = null;
if (!StringUtils.isBlank(agencyNumber)) {
agencyNumbers = this.getMatchingAgencyNumbers(agencyNumber);
}
for (Iterator<ContractsGrantsInvoiceDocument> iter = contractsGrantsInvoiceDocs.iterator(); iter.hasNext();) {
ContractsGrantsInvoiceDocument document = iter.next();
if (!canDocumentBeViewed(document, collectorPrincipalId)) {
iter.remove();
}
else if (!CollectionUtils.isEmpty(agencyNumbers) && !matchesAgencyNumber(document, agencyNumbers)) {
iter.remove();
}
}
}
if (!CollectionUtils.isEmpty(contractsGrantsInvoiceDocs)) {
for (ContractsGrantsInvoiceDocument cgInvoiceDocument : contractsGrantsInvoiceDocs) {
List<CollectionEvent> events = cgInvoiceDocument.getCollectionEvents();
List<CustomerInvoiceDetail> details = cgInvoiceDocument.getSourceAccountingLines();
final String accountNum = (!CollectionUtils.isEmpty(details) && !ObjectUtils.isNull(details.get(0))) ? details.get(0).getAccountNumber() : "";
if (CollectionUtils.isNotEmpty(events)) {
for (CollectionEvent event : events) {
if (StringUtils.isBlank(activityType) || StringUtils.equals(event.getActivityCode(), activityType)) {
CollectionActivityReport collectionActivityReport = new CollectionActivityReport();
collectionActivityReport.setAccountNumber(accountNum);
convertEventToCollectionActivityReport(collectionActivityReport, event);
displayList.add(collectionActivityReport);
}
}
}
}
}
return displayList;
}
/**
* Determines if the given CINV can be viewed for the given collector and by the current user
* @param document the CINV document to test
* @param collectorPrincipalId the collector principal id to test if it exists
* @return true if the document can be viewed, false otherwise
*/
protected boolean canDocumentBeViewed(ContractsGrantsInvoiceDocument document, String collectorPrincipalId) {
final Person user = GlobalVariables.getUserSession().getPerson();
return (StringUtils.isBlank(collectorPrincipalId) || contractsGrantsInvoiceDocumentService.canViewInvoice(document, collectorPrincipalId))
&& contractsGrantsInvoiceDocumentService.canViewInvoice(document, user.getPrincipalId());
}
/**
* Assuming that the given agencyNumberLookup may have wildcard characters, attempts to look up all matching agency numbers
* @param agencyNumberLookup the agency number from the lookup to find agency numbers on actual awards for
* @return any matching agency numbers from matching awards
*/
protected Set<String> getMatchingAgencyNumbers(String agencyNumberLookup) {
Set<String> matchingAgencyNumbers = new HashSet<>();
Map<String, String> agencyLookupFields = new HashMap<>();
agencyLookupFields.put(KFSPropertyConstants.AGENCY_NUMBER, agencyNumberLookup);
List<? extends ContractsAndGrantsAward> awards = getContractsAndGrantsModuleBillingService().lookupAwards(agencyLookupFields, true);
if (!CollectionUtils.isEmpty(awards)) {
for (ContractsAndGrantsAward award : awards) {
if (award instanceof ContractsAndGrantsBillingAward) {
matchingAgencyNumbers.add(((ContractsAndGrantsBillingAward)award).getAgencyNumber());
}
}
}
if (matchingAgencyNumbers.isEmpty()) {
return null; // we'll assume that the return is null...
}
return matchingAgencyNumbers;
}
/**
* Determines if the given document matches the passed in agency number
* @param document the document to check
* @param agencyNumber the agency number to verify against
* @return true if the document matches the given agency number, false otherwise
*/
protected boolean matchesAgencyNumber(ContractsGrantsInvoiceDocument document, Set<String> agencyNumbers) {
if (!ObjectUtils.isNull(document) && !ObjectUtils.isNull(document.getInvoiceGeneralDetail().getAward()) && !StringUtils.isBlank(document.getInvoiceGeneralDetail().getAward().getAgencyNumber())) {
final String documentAgencyNumber = document.getInvoiceGeneralDetail().getAward().getAgencyNumber();
return agencyNumbers.contains(documentAgencyNumber);
}
return false;
}
/**
* This method is used to convert the CollectionEvent Object into collection activity report.
*
* @param collectionActivityReport
* @param collectionEvent
* @return Returns the Object of CollectionActivityReport class.
*/
protected CollectionActivityReport convertEventToCollectionActivityReport(CollectionActivityReport collectionActivityReport, CollectionEvent collectionEvent) {
if (ObjectUtils.isNull(collectionEvent)) {
LOG.error("an invalid(null) argument was given");
throw new IllegalArgumentException("an invalid(null) argument was given");
}
collectionActivityReport.setEventId(collectionEvent.getId());
// account no
collectionActivityReport.setInvoiceNumber(collectionEvent.getInvoiceNumber());
collectionActivityReport.setActivityDate(collectionEvent.getActivityDate());
// Activity Type
CollectionActivityType collectionActivityType = collectionEvent.getCollectionActivityType();
if (ObjectUtils.isNotNull(collectionActivityType)) {
collectionActivityReport.setActivityType(collectionActivityType.getActivityDescription());
}
collectionActivityReport.setActivityComment(collectionEvent.getActivityText());
collectionActivityReport.setFollowupDate(collectionEvent.getFollowupDate());
collectionActivityReport.setProposalNumber(collectionEvent.getInvoiceDocument().getInvoiceGeneralDetail().getProposalNumber());
collectionActivityReport.setCompletedDate(collectionEvent.getCompletedDate());
String userPrincId = collectionEvent.getUserPrincipalId();
Person person = personService.getPerson(userPrincId);
if (ObjectUtils.isNotNull(person)) {
collectionActivityReport.setUserPrincipalId(person.getName());
}
if (ObjectUtils.isNotNull(collectionEvent.getInvoiceDocument())) {
collectionActivityReport.setChartOfAccountsCode(collectionEvent.getInvoiceDocument().getBillByChartOfAccountCode());
}
if (ObjectUtils.isNotNull(collectionEvent.getInvoiceDocument().getInvoiceGeneralDetail()) && ObjectUtils.isNotNull(collectionEvent.getInvoiceDocument().getInvoiceGeneralDetail().getAward()) && ObjectUtils.isNotNull(collectionEvent.getInvoiceDocument().getInvoiceGeneralDetail().getAward().getAgency())) {
collectionActivityReport.setAgencyNumber(collectionEvent.getInvoiceDocument().getInvoiceGeneralDetail().getAward().getAgency().getAgencyNumber());
collectionActivityReport.setAgencyName(collectionEvent.getInvoiceDocument().getInvoiceGeneralDetail().getAward().getAgency().getFullName());
}
return collectionActivityReport;
}
@NonTransactional
public PersonService getPersonService() {
return personService;
}
@NonTransactional
public void setPersonService(PersonService personService) {
this.personService = personService;
}
public FinancialSystemDocumentService getFinancialSystemDocumentService() {
return financialSystemDocumentService;
}
public void setFinancialSystemDocumentService(FinancialSystemDocumentService financialSystemDocumentService) {
this.financialSystemDocumentService = financialSystemDocumentService;
}
public ContractsAndGrantsModuleBillingService getContractsAndGrantsModuleBillingService() {
return contractsAndGrantsModuleBillingService;
}
public void setContractsAndGrantsModuleBillingService(ContractsAndGrantsModuleBillingService contractsAndGrantsModuleBillingService) {
this.contractsAndGrantsModuleBillingService = contractsAndGrantsModuleBillingService;
}
/**
* Gets the businessObjectService attribute.
*
* @return Returns the businessObjectService.
*/
@NonTransactional
public BusinessObjectService getBusinessObjectService() {
return businessObjectService;
}
/**
* Sets the businessObjectService attribute value.
*
* @param businessObjectService The businessObjectService to set.
*/
@NonTransactional
public void setBusinessObjectService(BusinessObjectService businessObjectService) {
this.businessObjectService = businessObjectService;
}
/**
* Gets the contractsGrantsInvoiceDocumentService attribute.
*
* @return Returns the contractsGrantsInvoiceDocumentService.
*/
@NonTransactional
public ContractsGrantsInvoiceDocumentService getContractsGrantsInvoiceDocumentService() {
return contractsGrantsInvoiceDocumentService;
}
/**
* Sets the contractsGrantsInvoiceDocumentService attribute value.
*
* @param contractsGrantsInvoiceDocumentService The contractsGrantsInvoiceDocumentService to set.
*/
@NonTransactional
public void setContractsGrantsInvoiceDocumentService(ContractsGrantsInvoiceDocumentService contractsGrantsInvoiceDocumentService) {
this.contractsGrantsInvoiceDocumentService = contractsGrantsInvoiceDocumentService;
}
}