/*
* 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.cam.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.fp.businessobject.CapitalAssetInformation;
import org.kuali.kfs.fp.document.CapitalAssetEditable;
import org.kuali.kfs.fp.document.CapitalAssetInformationDocumentBase;
import org.kuali.kfs.integration.cab.CapitalAssetBuilderModuleService;
import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService;
import org.kuali.kfs.module.cab.CabConstants;
import org.kuali.kfs.module.cam.CamsConstants;
import org.kuali.kfs.module.cam.businessobject.AssetLock;
import org.kuali.kfs.module.cam.service.AssetLockService;
import org.kuali.kfs.sys.businessobject.AccountingLineBase;
import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
import org.kuali.kfs.sys.businessobject.TargetAccountingLine;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.document.AccountingDocument;
import org.kuali.kfs.sys.service.impl.KfsParameterConstants;
import org.kuali.rice.coreservice.framework.parameter.ParameterService;
import org.kuali.rice.kew.api.WorkflowDocument;
import org.kuali.rice.kns.service.DataDictionaryService;
import org.kuali.rice.krad.document.Document;
import org.kuali.rice.krad.exception.ValidationException;
import org.kuali.rice.krad.util.ObjectUtils;
public class CapitalAssetManagementModuleServiceImpl implements CapitalAssetManagementModuleService {
protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CapitalAssetManagementModuleServiceImpl.class);
protected CapitalAssetBuilderModuleService capitalAssetBuilderModuleService;
/**
* @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#storeAssetLocks(java.util.List, java.lang.String,
* java.lang.String, java.lang.String)
*/
@Override
public boolean storeAssetLocks(List<Long> capitalAssetNumbers, String documentNumber, String documentType, String lockingInformation) {
/* Asset locking information may take valid information about asset lock from original
* document. It should not be reset to another value.
* It's required to fix for PREQ/CM Individual Asset system locking issue.
*/
List<AssetLock> assetLocks = getAssetLockService().buildAssetLockHelper(capitalAssetNumbers, documentNumber, documentType, StringUtils.isBlank(lockingInformation) ? CamsConstants.defaultLockingInformation : lockingInformation);
return getAssetLockService().checkAndSetAssetLocks(assetLocks, false);
}
/**
* @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#deleteAssetLocks(java.lang.String, java.lang.String)
*/
@Override
public void deleteAssetLocks(String documentNumber, String lockingInformation) {
getAssetLockService().deleteAssetLocks(documentNumber, lockingInformation);
}
protected AssetLockService getAssetLockService() {
return SpringContext.getBean(AssetLockService.class);
}
/**
* @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#isAssetLockedByDocument(java.lang.String,
* java.lang.String)
*/
@Override
public boolean isAssetLockedByCurrentDocument(String documentNumber, String lockingInformation) {
//return getAssetLockService().isAssetLockedByCurrentDocument(documentNumber, lockingInformation == null ? CamsConstants.defaultLockingInformation : lockingInformation);
return getAssetLockService().isAssetLockedByCurrentDocument(documentNumber, lockingInformation);
}
/**
* @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#isAssetLocked(java.util.List, java.lang.String,
* java.lang.String)
*/
@Override
public boolean isAssetLocked(List<Long> assetNumbers, String documentTypeName, String excludingDocumentNumber) {
return getAssetLockService().isAssetLocked(assetNumbers, documentTypeName, excludingDocumentNumber);
}
/**
* Generate asset locks for FP document if it collects capital
* asset number(s) and has capital asset transactions eligible for CAB
* batch.
*
* Creating asset lock is based on each capital asset line rather
* than the whole FP document.
*
* @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#generateCapitalAssetLock(org.kuali.rice.krad.document.Document)
*/
@Override
public void generateCapitalAssetLock(Document document, String documentTypeName) {
List<AssetLock> assetLocks = new ArrayList<AssetLock>();
StringBuilder capitalAssetToBeLocked = new StringBuilder();
if (document instanceof CapitalAssetEditable) {
List<CapitalAssetInformation> capitalAssets = ((CapitalAssetEditable) document).getCapitalAssetInformation();
if (capitalAssetBuilderModuleService.isDocumentEligibleForCABBatch(documentTypeName)) {
List<String> includedObjectSubTypeCodes = capitalAssetBuilderModuleService.getBatchIncludedObjectSubTypes();
List<String> excludedChartCodes = capitalAssetBuilderModuleService.getBatchExcludedChartCodes();
List<String> excludedSubFundCodes = capitalAssetBuilderModuleService.getBatchExcludedSubFundCodes();
for (CapitalAssetInformation assetLine : capitalAssets) {
// Can skip asset locking if it's creating new asset instead
Long capitalAssetNumber = assetLine.getCapitalAssetNumber();
if (capitalAssetNumber != null) {
if (capitalAssetBuilderModuleService.isAssetLineEligibleForCABBatch(assetLine, ((CapitalAssetInformationDocumentBase)document).getPostingYear(), includedObjectSubTypeCodes, excludedChartCodes, excludedSubFundCodes)) {
AssetLock newLock = new AssetLock(document.getDocumentNumber(), capitalAssetNumber, assetLine.getCapitalAssetLineNumber() == null? CamsConstants.defaultLockingInformation : assetLine.getCapitalAssetLineNumber().toString(), documentTypeName);
assetLocks.add(newLock);
if (!capitalAssetToBeLocked.toString().isEmpty()) {
capitalAssetToBeLocked.append(",");
}
capitalAssetToBeLocked.append(capitalAssetNumber.toString());
}
}
}
if (!getAssetLockService().checkAndSetAssetLocks(assetLocks, true) ) {
throw new ValidationException("Asset " + capitalAssetToBeLocked.toString() + " is being locked by other documents.");
}
}
}
}
/**
* FP document eligible for asset lock when any of its accounting line is taken into CAB during CAB batch.
*
* @param accountingDocument
* @return
*/
@Override
public boolean isFpDocumentEligibleForAssetLock(AccountingDocument accountingDocument, String documentType) {
// get the system parameter values first so we don't need to repeat this step for each accounting line check
ParameterService parameterService = SpringContext.getBean(ParameterService.class);
List<String> excludedDocTypeCodes = new ArrayList<String>( parameterService.getParameterValuesAsString(KfsParameterConstants.CAPITAL_ASSET_BUILDER_BATCH.class, CabConstants.Parameters.DOCUMENT_TYPES) );
// check with the docTypeCodes system parameter
if (!excludedDocTypeCodes.isEmpty() && excludedDocTypeCodes.contains(documentType)) {
return false;
}
List<String> includedFinancialObjectSubTypeCodes = new ArrayList<String>( parameterService.getParameterValuesAsString(KfsParameterConstants.CAPITAL_ASSET_BUILDER_BATCH.class, CabConstants.Parameters.OBJECT_SUB_TYPES) );
List<String> excludedChartCodes = new ArrayList<String>( parameterService.getParameterValuesAsString(KfsParameterConstants.CAPITAL_ASSET_BUILDER_BATCH.class, CabConstants.Parameters.CHARTS) );
List<String> excludedSubFundCodes = new ArrayList<String>( parameterService.getParameterValuesAsString(KfsParameterConstants.CAPITAL_ASSET_BUILDER_BATCH.class, CabConstants.Parameters.SUB_FUND_GROUPS) );
List<SourceAccountingLine> sAccountingLines = accountingDocument.getSourceAccountingLines();
for (SourceAccountingLine sourceAccountingLine : sAccountingLines) {
if (isAccountLineEligibleForCABBatch(includedFinancialObjectSubTypeCodes, excludedChartCodes, excludedSubFundCodes, sourceAccountingLine)) {
return true;
}
}
List<TargetAccountingLine> tAccountingLines = accountingDocument.getTargetAccountingLines();
for (TargetAccountingLine targetAccountingLine : tAccountingLines) {
if (isAccountLineEligibleForCABBatch(includedFinancialObjectSubTypeCodes, excludedChartCodes, excludedSubFundCodes, targetAccountingLine)) {
return true;
}
}
// If none of the accounting line eligible for CAB batch, CAB batch won't take the FP document into CAB
return false;
}
/**
* This method check if accounting line eligible for CAB batch taking into CAB
*
* @param includedFinancialBalanceTypeCodes
* @param includedFinancialObjectSubTypeCodes
* @param excludedChartCodes
* @param excludedDocTypeCodes
* @param excludedSubFundCodes
* @param accountingLine
* @return
*/
protected boolean isAccountLineEligibleForCABBatch(List<String> includedFinancialObjectSubTypeCodes, List<String> excludedChartCodes, List<String> excludedSubFundCodes, AccountingLineBase accountingLine) {
// check with the financialObjectSubTypeCodes system parameter
if (!includedFinancialObjectSubTypeCodes.isEmpty() && !includedFinancialObjectSubTypeCodes.contains(accountingLine.getObjectCode().getFinancialObjectSubTypeCode())) {
return false;
}
// check with the charOfAccountCode system parameter
if (!excludedChartCodes.isEmpty() && excludedChartCodes.contains(accountingLine.getChartOfAccountsCode())) {
return false;
}
// check with the subFundCodes system parameter
if (!excludedSubFundCodes.isEmpty() && excludedSubFundCodes.contains(accountingLine.getAccount().getSubFundGroupCode())) {
return false;
}
return true;
}
/**
* Remove asset locks if document won't move towards Final status.
*
* @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#deleteDocumentAssetLocks(org.kuali.rice.krad.document.Document)
*/
@Override
public void deleteDocumentAssetLocks(Document document) {
WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
// remove all current locks owned by the document
if (workflowDocument.isCanceled() || workflowDocument.isDisapproved() || workflowDocument.isRecalled() || workflowDocument.isException()) {
this.deleteAssetLocks(document.getDocumentNumber(), null);
}
}
/**
* @return the capitalAssetBuilderModuleService
*/
public CapitalAssetBuilderModuleService getCapitalAssetBuilderModuleService() {
return capitalAssetBuilderModuleService;
}
/**
* @param capitalAssetBuilderModuleService the capitalAssetBuilderModuleService to set
*/
public void setCapitalAssetBuilderModuleService(
CapitalAssetBuilderModuleService capitalAssetBuilderModuleService) {
this.capitalAssetBuilderModuleService = capitalAssetBuilderModuleService;
}
}