001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.kfs.module.cam.service.impl;
017    
018    import java.util.ArrayList;
019    import java.util.List;
020    
021    import org.apache.commons.lang.StringUtils;
022    import org.kuali.kfs.fp.businessobject.CapitalAssetInformation;
023    import org.kuali.kfs.fp.document.CapitalAssetEditable;
024    import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService;
025    import org.kuali.kfs.module.cab.CabConstants;
026    import org.kuali.kfs.module.cam.CamsConstants;
027    import org.kuali.kfs.module.cam.businessobject.AssetLock;
028    import org.kuali.kfs.module.cam.service.AssetLockService;
029    import org.kuali.kfs.sys.businessobject.AccountingLineBase;
030    import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
031    import org.kuali.kfs.sys.businessobject.TargetAccountingLine;
032    import org.kuali.kfs.sys.context.SpringContext;
033    import org.kuali.kfs.sys.document.AccountingDocument;
034    import org.kuali.kfs.sys.service.impl.KfsParameterConstants;
035    import org.kuali.rice.kns.document.Document;
036    import org.kuali.rice.kns.exception.ValidationException;
037    import org.kuali.rice.kns.service.ParameterService;
038    import org.kuali.rice.kns.util.ObjectUtils;
039    import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument;
040    
041    public class CapitalAssetManagementModuleServiceImpl implements CapitalAssetManagementModuleService {
042        /**
043         * @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#storeAssetLocks(java.util.List, java.lang.String,
044         *      java.lang.String, java.lang.String)
045         */
046        public boolean storeAssetLocks(List<Long> capitalAssetNumbers, String documentNumber, String documentType, String lockingInformation) {
047            List<AssetLock> assetLocks = getAssetLockService().buildAssetLockHelper(capitalAssetNumbers, documentNumber, documentType, StringUtils.isBlank(lockingInformation) ? CamsConstants.defaultLockingInformation : lockingInformation);
048            return getAssetLockService().checkAndSetAssetLocks(assetLocks);
049        }
050    
051        /**
052         * @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#deleteAssetLocks(java.lang.String, java.lang.String)
053         */
054        public void deleteAssetLocks(String documentNumber, String lockingInformation) {
055            getAssetLockService().deleteAssetLocks(documentNumber, lockingInformation == null ? CamsConstants.defaultLockingInformation : lockingInformation);
056        }
057    
058        protected AssetLockService getAssetLockService() {
059            return SpringContext.getBean(AssetLockService.class);
060        }
061    
062        /**
063         * @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#isAssetLockedByDocument(java.lang.String,
064         *      java.lang.String)
065         */
066        public boolean isAssetLockedByCurrentDocument(String documentNumber, String lockingInformation) {
067            return getAssetLockService().isAssetLockedByCurrentDocument(documentNumber, lockingInformation == null ? CamsConstants.defaultLockingInformation : lockingInformation);
068        }
069    
070        /**
071         * @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#isAssetLocked(java.util.List, java.lang.String,
072         *      java.lang.String)
073         */
074        public boolean isAssetLocked(List<Long> assetNumbers, String documentTypeName, String excludingDocumentNumber) {
075            return getAssetLockService().isAssetLocked(assetNumbers, documentTypeName, excludingDocumentNumber);
076        }
077    
078        /**
079         * @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#generateCapitalAssetLock(org.kuali.rice.kns.document.Document)
080         */
081        public void generateCapitalAssetLock(Document document, String documentTypeName) {
082            CapitalAssetInformation capitalAssetInformation = ((CapitalAssetEditable) document).getCapitalAssetInformation();
083    
084            if (ObjectUtils.isNotNull(capitalAssetInformation) && ObjectUtils.isNotNull(capitalAssetInformation.getCapitalAssetNumber())) {
085                ArrayList<Long> capitalAssetNumbers = new ArrayList<Long>();
086                capitalAssetNumbers.add(capitalAssetInformation.getCapitalAssetNumber());
087    
088                if (document instanceof AccountingDocument) {
089                    if (isFpDocumentEligibleForAssetLock((AccountingDocument) document, documentTypeName) && !this.storeAssetLocks(capitalAssetNumbers, document.getDocumentNumber(), documentTypeName, null)) {
090                        throw new ValidationException("Asset " + capitalAssetNumbers.toString() + " is being locked by other documents.");
091                    }
092                }
093            }
094        }
095    
096        /**
097         * FP document eligible for asset lock when any of its accounting line is taken into CAB during CAB batch.
098         * 
099         * @param accountingDocument
100         * @return
101         */
102        public boolean isFpDocumentEligibleForAssetLock(AccountingDocument accountingDocument, String documentType) {
103            // get the system parameter values first so we don't need to repeat this step for each accounting line check
104            ParameterService parameterService = SpringContext.getBean(ParameterService.class);
105    
106            List<String> excludedDocTypeCodes = parameterService.getParameterValues(KfsParameterConstants.CAPITAL_ASSET_BUILDER_BATCH.class, CabConstants.Parameters.DOCUMENT_TYPES);
107            // check with the docTypeCodes system parameter
108            if (!excludedDocTypeCodes.isEmpty() && excludedDocTypeCodes.contains(documentType)) {
109                return false;
110            }
111    
112            List<String> includedFinancialObjectSubTypeCodes = parameterService.getParameterValues(KfsParameterConstants.CAPITAL_ASSET_BUILDER_BATCH.class, CabConstants.Parameters.OBJECT_SUB_TYPES);
113            List<String> excludedChartCodes = parameterService.getParameterValues(KfsParameterConstants.CAPITAL_ASSET_BUILDER_BATCH.class, CabConstants.Parameters.CHARTS);
114            List<String> excludedSubFundCodes = parameterService.getParameterValues(KfsParameterConstants.CAPITAL_ASSET_BUILDER_BATCH.class, CabConstants.Parameters.SUB_FUND_GROUPS);
115    
116            List<SourceAccountingLine> sAccountingLines = accountingDocument.getSourceAccountingLines();
117            for (SourceAccountingLine sourceAccountingLine : sAccountingLines) {
118                if (isAccountLineEligibleForCABBatch(includedFinancialObjectSubTypeCodes, excludedChartCodes, excludedSubFundCodes, sourceAccountingLine)) {
119                    return true;
120                }
121    
122            }
123    
124            List<TargetAccountingLine> tAccountingLines = accountingDocument.getTargetAccountingLines();
125            for (TargetAccountingLine targetAccountingLine : tAccountingLines) {
126                if (isAccountLineEligibleForCABBatch(includedFinancialObjectSubTypeCodes, excludedChartCodes, excludedSubFundCodes, targetAccountingLine)) {
127                    return true;
128                }
129            }
130            // If none of the accounting line eligible for CAB batch, CAB batch won't take the FP document into CAB
131            return false;
132        }
133    
134        /**
135         * This method check if accounting line eligible for CAB batch taking into CAB
136         * 
137         * @param includedFinancialBalanceTypeCodes
138         * @param includedFinancialObjectSubTypeCodes
139         * @param excludedChartCodes
140         * @param excludedDocTypeCodes
141         * @param excludedSubFundCodes
142         * @param accountingLine
143         * @return
144         */
145        protected boolean isAccountLineEligibleForCABBatch(List<String> includedFinancialObjectSubTypeCodes, List<String> excludedChartCodes, List<String> excludedSubFundCodes, AccountingLineBase accountingLine) {
146            // check with the financialObjectSubTypeCodes system parameter
147            if (!includedFinancialObjectSubTypeCodes.isEmpty() && !includedFinancialObjectSubTypeCodes.contains(accountingLine.getObjectCode().getFinancialObjectSubTypeCode())) {
148                return false;
149            }
150    
151            // check with the charOfAccountCode system parameter
152            if (!excludedChartCodes.isEmpty() && excludedChartCodes.contains(accountingLine.getChartOfAccountsCode())) {
153                return false;
154            }
155    
156            // check with the subFundCodes system parameter
157            if (!excludedSubFundCodes.isEmpty() && excludedSubFundCodes.contains(accountingLine.getAccount().getSubFundGroupCode())) {
158                return false;
159            }
160    
161            return true;
162        }
163    
164    
165        /**
166         * @see org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService#deleteDocumentAssetLocks(org.kuali.rice.kns.document.Document)
167         */
168        public void deleteDocumentAssetLocks(Document document) {
169            KualiWorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
170            CapitalAssetInformation capitalAssetInformation = ((CapitalAssetEditable) document).getCapitalAssetInformation();
171    
172            // Deleting document lock
173            if (workflowDocument.stateIsCanceled() || workflowDocument.stateIsDisapproved()) {
174                if (ObjectUtils.isNotNull(capitalAssetInformation) && isAssetLockedByCurrentDocument(document.getDocumentNumber(), null)) {
175                    this.deleteAssetLocks(document.getDocumentNumber(), null);
176                }
177            }
178        }
179    }