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.document;
017    
018    import java.util.ArrayList;
019    import java.util.Collection;
020    import java.util.List;
021    import java.util.Map;
022    
023    import org.apache.commons.lang.StringUtils;
024    import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService;
025    import org.kuali.kfs.module.cam.CamsConstants;
026    import org.kuali.kfs.module.cam.CamsKeyConstants;
027    import org.kuali.kfs.module.cam.CamsPropertyConstants;
028    import org.kuali.kfs.module.cam.businessobject.Asset;
029    import org.kuali.kfs.module.cam.businessobject.AssetPayment;
030    import org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal;
031    import org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobalDetail;
032    import org.kuali.kfs.module.cam.document.gl.AssetRetirementGeneralLedgerPendingEntrySource;
033    import org.kuali.kfs.module.cam.document.service.AssetPaymentService;
034    import org.kuali.kfs.module.cam.document.service.AssetRetirementService;
035    import org.kuali.kfs.module.cam.document.service.AssetService;
036    import org.kuali.kfs.sys.KFSConstants;
037    import org.kuali.kfs.sys.businessobject.FinancialSystemDocumentHeader;
038    import org.kuali.kfs.sys.context.SpringContext;
039    import org.kuali.kfs.sys.document.LedgerPostingMaintainable;
040    import org.kuali.rice.kns.bo.DocumentHeader;
041    import org.kuali.rice.kns.bo.PersistableBusinessObject;
042    import org.kuali.rice.kns.document.MaintenanceDocument;
043    import org.kuali.rice.kns.document.MaintenanceLock;
044    import org.kuali.rice.kns.service.BusinessObjectService;
045    import org.kuali.rice.kns.service.DateTimeService;
046    import org.kuali.rice.kns.util.GlobalVariables;
047    import org.kuali.rice.kns.util.KNSConstants;
048    import org.kuali.rice.kns.util.ObjectUtils;
049    import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument;
050    
051    
052    /**
053     * This class overrides the base {@link KualiGlobalMaintainableImpl} to generate the specific maintenance locks for Global location
054     * assets
055     */
056    public class AssetRetirementGlobalMaintainableImpl extends LedgerPostingMaintainable {
057    
058        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AssetRetirementGlobalMaintainableImpl.class);
059        private static final String RETIRED_ASSET_TRANSFERRED_EXTERNALLY = "RetiredAssetTransferredExternally";
060        private static final String RETIRED_ASSET_SOLD_OR_GIFTED = "RetiredAssetSoldOrGifted";
061    
062        /**
063         * @see org.kuali.kfs.sys.document.FinancialSystemGlobalMaintainable#answerSplitNodeQuestion(java.lang.String)
064         */
065        @Override
066        protected boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
067            String retirementReason = ((AssetRetirementGlobal) getBusinessObject()).getRetirementReasonCode();
068            if (this.RETIRED_ASSET_TRANSFERRED_EXTERNALLY.equals(nodeName)) {
069                return CamsConstants.AssetRetirementReasonCode.EXTERNAL_TRANSFER.equalsIgnoreCase(retirementReason);
070            }
071            if (this.RETIRED_ASSET_SOLD_OR_GIFTED.equals(nodeName)) {
072                return CamsConstants.AssetRetirementReasonCode.SOLD.equalsIgnoreCase(retirementReason) || CamsConstants.AssetRetirementReasonCode.GIFT.equalsIgnoreCase(retirementReason);
073            }
074            throw new UnsupportedOperationException("Cannot answer split question for this node you call \"" + nodeName + "\"");
075        }
076    
077        /**
078         * We are using a substitute mechanism for asset locking which can lock on assets when rule check passed. Return empty list from
079         * this method.
080         * 
081         * @see org.kuali.rice.kns.maintenance.Maintainable#generateMaintenanceLocks()
082         */
083        @Override
084        public List<MaintenanceLock> generateMaintenanceLocks() {
085            return new ArrayList<MaintenanceLock>();
086        }
087    
088        protected CapitalAssetManagementModuleService getCapitalAssetManagementModuleService() {
089            return SpringContext.getBean(CapitalAssetManagementModuleService.class);
090        }
091    
092    
093        @Override
094        public void setupNewFromExisting(MaintenanceDocument document, Map<String, String[]> parameters) {
095            super.setupNewFromExisting(document, parameters);
096    
097            AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject();
098            if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal)) {
099                if (ObjectUtils.isNotNull(assetRetirementGlobal.getMergedTargetCapitalAssetNumber())) {
100                    assetRetirementGlobal.setMergedTargetCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAsset().getCapitalAssetDescription());
101                }
102            }
103    
104            // add doc header description if retirement reason is "MERGED"
105            if (CamsConstants.AssetRetirementReasonCode.MERGED.equals(assetRetirementGlobal.getRetirementReasonCode())) {
106                document.getDocumentHeader().setDocumentDescription(CamsConstants.AssetRetirementGlobal.MERGE_AN_ASSET_DESCRIPTION);
107            }
108        }
109    
110        /**
111         * @see org.kuali.rice.kns.maintenance.KualiGlobalMaintainableImpl#processGlobalsAfterRetrieve()
112         */
113        @Override
114        protected void processGlobalsAfterRetrieve() {
115            super.processGlobalsAfterRetrieve();
116    
117            AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject();
118            List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails();
119    
120            for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) {
121                // Set non-persistent values. So the screen can show them after submit.
122                getAssetService().setAssetSummaryFields(assetRetirementGlobalDetail.getAsset());
123            }
124        }
125    
126        @Override
127        public void addMultipleValueLookupResults(MaintenanceDocument document, String collectionName, Collection<PersistableBusinessObject> rawValues, boolean needsBlank, PersistableBusinessObject bo) {
128            AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) document.getDocumentBusinessObject();
129            List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails();
130    
131            int nElements = assetRetirementGlobal.getAssetRetirementGlobalDetails().size() + rawValues.size();
132            if (!getAssetService().isDocumentEnrouting(document) && !getAssetRetirementService().isAllowedRetireMultipleAssets(document) && nElements > new Integer(1)) {
133                GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.Retirement.ERROR_MULTIPLE_ASSET_RETIRED);
134            }
135            else {
136                GlobalVariables.getMessageMap().clear();
137    
138                // Adding the selected asset.
139                super.addMultipleValueLookupResults(document, collectionName, rawValues, needsBlank, bo);
140            }
141        }
142    
143    
144        /**
145         * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#refresh(java.lang.String, java.util.Map,
146         *      org.kuali.rice.kns.document.MaintenanceDocument)
147         */
148        @Override
149        public void refresh(String refreshCaller, Map fieldValues, MaintenanceDocument document) {
150            super.refresh(refreshCaller, fieldValues, document);
151            AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) document.getDocumentBusinessObject();
152            List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails();
153    
154            if (KFSConstants.MULTIPLE_VALUE.equalsIgnoreCase(refreshCaller)) {
155                // Set non-persistent values in multiple lookup result collection. So the screen can show them when return from multiple
156                // lookup.
157                for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) {
158                    getAssetService().setAssetSummaryFields(assetRetirementGlobalDetail.getAsset());
159                }
160            }
161            else if (CamsConstants.AssetRetirementGlobal.ASSET_LOOKUPABLE_ID.equalsIgnoreCase(refreshCaller)) {
162                // Set non-persistent values in the result from asset lookup. So the screen can show them when return from single asset
163                // lookup.
164                String referencesToRefresh = (String) fieldValues.get(KNSConstants.REFERENCES_TO_REFRESH);
165                if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal) && CamsPropertyConstants.AssetRetirementGlobal.MERGED_TARGET_CAPITAL_ASSET.equals(referencesToRefresh)) {
166                    assetRetirementGlobal.setMergedTargetCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAsset().getCapitalAssetDescription());
167                }
168                AssetRetirementGlobalDetail newDetail = (AssetRetirementGlobalDetail) newCollectionLines.get(CamsPropertyConstants.AssetRetirementGlobal.ASSET_RETIREMENT_GLOBAL_DETAILS);
169                getAssetService().setAssetSummaryFields(newDetail.getAsset());
170            }
171        }
172    
173        /**
174         * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#doRouteStatusChange(org.kuali.rice.kns.bo.DocumentHeader)
175         */
176        @Override
177        public void doRouteStatusChange(DocumentHeader documentHeader) {
178            super.doRouteStatusChange(documentHeader);
179            AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject();
180    
181            if (documentHeader.getWorkflowDocument().stateIsEnroute()) {
182                // display a message for asset not generating ledger entries when it is federally owned
183                boolean allPaymentsFederalOwned = true;
184                List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails();
185                for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) {
186                    for (AssetPayment assetPayment : assetRetirementGlobalDetail.getAsset().getAssetPayments()) {
187                        if (!getAssetPaymentService().isPaymentFederalOwned(assetPayment)) {
188                            allPaymentsFederalOwned = false;
189                        }
190                    }
191                }
192    
193                if (allPaymentsFederalOwned) {
194                    GlobalVariables.getMessageList().add(CamsKeyConstants.Retirement.MESSAGE_NO_LEDGER_ENTRY_REQUIRED_RETIREMENT);
195                }
196    
197            }
198            // all approvals have been processed, the retirement date is set to the approval date
199            if (documentHeader.getWorkflowDocument().stateIsProcessed()) {
200                assetRetirementGlobal.setRetirementDate(SpringContext.getBean(DateTimeService.class).getCurrentSqlDate());
201                SpringContext.getBean(BusinessObjectService.class).save(assetRetirementGlobal);
202    
203                if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal)) {
204                    assetRetirementGlobal.getMergedTargetCapitalAsset().setCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAssetDescription());
205                    SpringContext.getBean(BusinessObjectService.class).save(assetRetirementGlobal.getMergedTargetCapitalAsset());
206                }
207    
208            }
209            new AssetRetirementGeneralLedgerPendingEntrySource((FinancialSystemDocumentHeader) documentHeader).doRouteStatusChange(assetRetirementGlobal.getGeneralLedgerPendingEntries());
210    
211            // release the lock when document status changed as following...
212            KualiWorkflowDocument workflowDoc = documentHeader.getWorkflowDocument();
213            if (workflowDoc.stateIsCanceled() || workflowDoc.stateIsDisapproved() || workflowDoc.stateIsProcessed() || workflowDoc.stateIsFinal()) {
214                this.getCapitalAssetManagementModuleService().deleteAssetLocks(documentNumber, null);
215            }
216        }
217    
218        /**
219         * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#addNewLineToCollection(java.lang.String)
220         */
221        @Override
222        public void addNewLineToCollection(String collectionName) {
223            super.addNewLineToCollection(collectionName);
224    
225            AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject();
226            if (StringUtils.isBlank(assetRetirementGlobal.getMergedTargetCapitalAssetDescription()) && ObjectUtils.isNotNull(assetRetirementGlobal.getMergedTargetCapitalAssetNumber())) {
227                assetRetirementGlobal.setMergedTargetCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAsset().getCapitalAssetDescription());
228            }
229        }
230    
231        @Override
232        public Class<? extends PersistableBusinessObject> getPrimaryEditedBusinessObjectClass() {
233            return Asset.class;
234        }
235    
236        @Override
237        public Map<String, String> populateNewCollectionLines( Map<String, String> fieldValues, MaintenanceDocument maintenanceDocument, String methodToCall ) {
238            String capitalAssetNumber = (String)fieldValues.get(CamsPropertyConstants.AssetRetirementGlobal.CAPITAL_ASSET_NUMBER);
239    
240            if (StringUtils.isNotBlank(capitalAssetNumber)) {
241                fieldValues.remove(CamsPropertyConstants.AssetRetirementGlobal.CAPITAL_ASSET_NUMBER);
242                fieldValues.put(CamsPropertyConstants.AssetRetirementGlobal.CAPITAL_ASSET_NUMBER, capitalAssetNumber.trim());
243                    }
244            return super.populateNewCollectionLines(fieldValues, maintenanceDocument, methodToCall);
245         
246        }
247    
248        private AssetRetirementService getAssetRetirementService() {
249            return SpringContext.getBean(AssetRetirementService.class);
250        }
251    
252        private AssetService getAssetService() {
253            return SpringContext.getBean(AssetService.class);
254        }
255    
256        private AssetPaymentService getAssetPaymentService() {
257            return SpringContext.getBean(AssetPaymentService.class);
258        }
259    
260    }