View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    * 
4    * Copyright 2005-2014 The Kuali Foundation
5    * 
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   * 
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.kfs.module.cam.document;
20  
21  import java.text.ParseException;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.apache.commons.lang.StringUtils;
28  import org.kuali.kfs.gl.GeneralLedgerConstants;
29  import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService;
30  import org.kuali.kfs.module.cam.CamsConstants;
31  import org.kuali.kfs.module.cam.CamsKeyConstants;
32  import org.kuali.kfs.module.cam.CamsPropertyConstants;
33  import org.kuali.kfs.module.cam.businessobject.Asset;
34  import org.kuali.kfs.module.cam.businessobject.AssetPayment;
35  import org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal;
36  import org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobalDetail;
37  import org.kuali.kfs.module.cam.document.gl.AssetRetirementGeneralLedgerPendingEntrySource;
38  import org.kuali.kfs.module.cam.document.service.AssetGlobalService;
39  import org.kuali.kfs.module.cam.document.service.AssetPaymentService;
40  import org.kuali.kfs.module.cam.document.service.AssetRetirementService;
41  import org.kuali.kfs.module.cam.document.service.AssetService;
42  import org.kuali.kfs.sys.KFSConstants;
43  import org.kuali.kfs.sys.businessobject.FinancialSystemDocumentHeader;
44  import org.kuali.kfs.sys.context.SpringContext;
45  import org.kuali.kfs.sys.document.LedgerPostingMaintainable;
46  import org.kuali.kfs.sys.service.impl.KfsParameterConstants;
47  import org.kuali.rice.core.api.datetime.DateTimeService;
48  import org.kuali.rice.core.api.parameter.ParameterEvaluator;
49  import org.kuali.rice.core.api.parameter.ParameterEvaluatorService;
50  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
51  import org.kuali.rice.kew.api.WorkflowDocument;
52  import org.kuali.rice.kns.document.MaintenanceDocument;
53  import org.kuali.rice.kns.util.KNSGlobalVariables;
54  import org.kuali.rice.krad.bo.DocumentHeader;
55  import org.kuali.rice.krad.bo.PersistableBusinessObject;
56  import org.kuali.rice.krad.maintenance.MaintenanceLock;
57  import org.kuali.rice.krad.service.BusinessObjectService;
58  import org.kuali.rice.krad.util.GlobalVariables;
59  import org.kuali.rice.krad.util.KRADConstants;
60  import org.kuali.rice.krad.util.ObjectUtils;
61  
62  
63  /**
64   * This class overrides the base {@link KualiGlobalMaintainableImpl} to generate the specific maintenance locks for Global location
65   * assets
66   */
67  public class AssetRetirementGlobalMaintainableImpl extends LedgerPostingMaintainable {
68  
69      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AssetRetirementGlobalMaintainableImpl.class);
70      protected static final String RETIRED_ASSET_TRANSFERRED_EXTERNALLY = "RetiredAssetTransferredExternally";
71      protected static final String RETIRED_ASSET_SOLD_OR_GIFTED = "RetiredAssetSoldOrGifted";
72  
73  
74      /**
75       * @see org.kuali.kfs.sys.document.FinancialSystemGlobalMaintainable#answerSplitNodeQuestion(java.lang.String)
76       */
77      @Override
78      protected boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
79          String retirementReason = ((AssetRetirementGlobal) getBusinessObject()).getRetirementReasonCode();
80          if (this.RETIRED_ASSET_TRANSFERRED_EXTERNALLY.equals(nodeName)) {
81              return CamsConstants.AssetRetirementReasonCode.EXTERNAL_TRANSFER.equalsIgnoreCase(retirementReason);
82          }
83          if (this.RETIRED_ASSET_SOLD_OR_GIFTED.equals(nodeName)) {
84              return CamsConstants.AssetRetirementReasonCode.SOLD.equalsIgnoreCase(retirementReason) || CamsConstants.AssetRetirementReasonCode.GIFT.equalsIgnoreCase(retirementReason);
85          }
86          throw new UnsupportedOperationException("Cannot answer split question for this node you call \"" + nodeName + "\"");
87      }
88  
89      /**
90       * We are using a substitute mechanism for asset locking which can lock on assets when rule check passed. Return empty list from
91       * this method.
92       *
93       * @see org.kuali.rice.kns.maintenance.Maintainable#generateMaintenanceLocks()
94       */
95      @Override
96      public List<MaintenanceLock> generateMaintenanceLocks() {
97          return new ArrayList<MaintenanceLock>();
98      }
99  
100     protected CapitalAssetManagementModuleService getCapitalAssetManagementModuleService() {
101         return SpringContext.getBean(CapitalAssetManagementModuleService.class);
102     }
103 
104 
105     @Override
106     public void setupNewFromExisting(MaintenanceDocument document, Map<String, String[]> parameters) {
107         super.setupNewFromExisting(document, parameters);
108 
109         AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject();
110         if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal)) {
111             if (ObjectUtils.isNotNull(assetRetirementGlobal.getMergedTargetCapitalAssetNumber())) {
112                 assetRetirementGlobal.setMergedTargetCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAsset().getCapitalAssetDescription());
113             }
114         }
115 
116         // add doc header description if retirement reason is "MERGED"
117         if (CamsConstants.AssetRetirementReasonCode.MERGED.equals(assetRetirementGlobal.getRetirementReasonCode())) {
118             document.getDocumentHeader().setDocumentDescription(CamsConstants.AssetRetirementGlobal.MERGE_AN_ASSET_DESCRIPTION);
119         }
120 
121         // Fiscal Year End modifications
122         String docType = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
123         ParameterEvaluatorService parameterEvaluatorService = SpringContext.getBean(ParameterEvaluatorService.class);
124         ParameterEvaluator evaluator = parameterEvaluatorService.getParameterEvaluator(KFSConstants.CoreModuleNamespaces.KFS, KfsParameterConstants.YEAR_END_ACCOUNTING_PERIOD_PARAMETER_NAMES.DETAIL_PARAMETER_TYPE, KfsParameterConstants.YEAR_END_ACCOUNTING_PERIOD_PARAMETER_NAMES.FISCAL_PERIOD_SELECTION_DOCUMENT_TYPES, docType);
125         if (evaluator.evaluationSucceeds() && isPeriod13(assetRetirementGlobal) ) {
126             Integer closingYear = new Integer(SpringContext.getBean(ParameterService.class).getParameterValueAsString(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, GeneralLedgerConstants.ANNUAL_CLOSING_FISCAL_YEAR_PARM));
127             String closingDate = getClosingDate(closingYear);
128             try {
129                 if (ObjectUtils.isNotNull(assetRetirementGlobal.getPostingYear()) ) {
130                     assetRetirementGlobal.setAccountingPeriodCompositeString(assetRetirementGlobal.getAccountingPeriod().getUniversityFiscalPeriodCode()+assetRetirementGlobal.getPostingYear());
131                 }
132                 updateAssetRetirementGlobalForPeriod13(assetRetirementGlobal, closingYear, closingDate);
133                 assetRetirementGlobal.refreshNonUpdateableReferences();
134             } catch (Exception e) {
135                 LOG.error(e);
136             }
137         }
138 
139     }
140 
141     /**
142      * @see org.kuali.rice.kns.maintenance.KualiGlobalMaintainableImpl#processGlobalsAfterRetrieve()
143      */
144     @Override
145     protected void processGlobalsAfterRetrieve() {
146         super.processGlobalsAfterRetrieve();
147 
148         AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject();
149         List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails();
150 
151         for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) {
152             // Set non-persistent values. So the screen can show them after submit.
153             getAssetService().setAssetSummaryFields(assetRetirementGlobalDetail.getAsset());
154         }
155     }
156 
157     @Override
158     public void addMultipleValueLookupResults(MaintenanceDocument document, String collectionName, Collection<PersistableBusinessObject> rawValues, boolean needsBlank, PersistableBusinessObject bo) {
159         AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) document.getDocumentBusinessObject();
160         List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails();
161 
162         int nElements = assetRetirementGlobal.getAssetRetirementGlobalDetails().size() + rawValues.size();
163         if (!getAssetService().isDocumentEnrouting(document) && !getAssetRetirementService().isAllowedRetireMultipleAssets(document) && nElements > new Integer(1)) {
164             GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.Retirement.ERROR_MULTIPLE_ASSET_RETIRED);
165         }
166         else {
167             GlobalVariables.getMessageMap().clearErrorMessages();
168 
169             // Adding the selected asset.
170             super.addMultipleValueLookupResults(document, collectionName, rawValues, needsBlank, bo);
171         }
172     }
173 
174 
175     /**
176      * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#refresh(java.lang.String, java.util.Map,
177      *      org.kuali.rice.kns.document.MaintenanceDocument)
178      */
179     @Override
180     public void refresh(String refreshCaller, Map fieldValues, MaintenanceDocument document) {
181         super.refresh(refreshCaller, fieldValues, document);
182         AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) document.getDocumentBusinessObject();
183         List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails();
184 
185         if (KFSConstants.MULTIPLE_VALUE.equalsIgnoreCase(refreshCaller)) {
186             // Set non-persistent values in multiple lookup result collection. So the screen can show them when return from multiple
187             // lookup.
188             for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) {
189                 getAssetService().setAssetSummaryFields(assetRetirementGlobalDetail.getAsset());
190             }
191         }
192         else if (CamsConstants.AssetRetirementGlobal.ASSET_LOOKUPABLE_ID.equalsIgnoreCase(refreshCaller)) {
193             // Set non-persistent values in the result from asset lookup. So the screen can show them when return from single asset
194             // lookup.
195             String referencesToRefresh = (String) fieldValues.get(KRADConstants.REFERENCES_TO_REFRESH);
196             if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal) && CamsPropertyConstants.AssetRetirementGlobal.MERGED_TARGET_CAPITAL_ASSET.equals(referencesToRefresh)) {
197                 assetRetirementGlobal.setMergedTargetCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAsset().getCapitalAssetDescription());
198             }
199             AssetRetirementGlobalDetail newDetail = (AssetRetirementGlobalDetail) newCollectionLines.get(CamsPropertyConstants.AssetRetirementGlobal.ASSET_RETIREMENT_GLOBAL_DETAILS);
200             getAssetService().setAssetSummaryFields(newDetail.getAsset());
201         }
202     }
203 
204     /**
205      * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#doRouteStatusChange(org.kuali.rice.krad.bo.DocumentHeader)
206      */
207     @Override
208     public void doRouteStatusChange(DocumentHeader documentHeader) {
209         super.doRouteStatusChange(documentHeader);
210         AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject();
211 
212         if (documentHeader.getWorkflowDocument().isEnroute()) {
213             // display a message for asset not generating ledger entries when it is federally owned
214             boolean allPaymentsFederalOwned = true;
215             List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails();
216             for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) {
217                 for (AssetPayment assetPayment : assetRetirementGlobalDetail.getAsset().getAssetPayments()) {
218                     if (!getAssetPaymentService().isPaymentFederalOwned(assetPayment)) {
219                         allPaymentsFederalOwned = false;
220                     }
221                 }
222             }
223 
224             if (allPaymentsFederalOwned) {
225                 KNSGlobalVariables.getMessageList().add(CamsKeyConstants.Retirement.MESSAGE_NO_LEDGER_ENTRY_REQUIRED_RETIREMENT);
226             }
227 
228         }
229         // all approvals have been processed, the retirement date is set to the approval date
230         if (documentHeader.getWorkflowDocument().isProcessed()) {
231             assetRetirementGlobal.setRetirementDate(SpringContext.getBean(DateTimeService.class).getCurrentSqlDate());
232             SpringContext.getBean(BusinessObjectService.class).save(assetRetirementGlobal);
233 
234             if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal)) {
235                 assetRetirementGlobal.getMergedTargetCapitalAsset().setCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAssetDescription());
236                 SpringContext.getBean(BusinessObjectService.class).save(assetRetirementGlobal.getMergedTargetCapitalAsset());
237             }
238 
239         }
240         new AssetRetirementGeneralLedgerPendingEntrySource((FinancialSystemDocumentHeader) documentHeader).doRouteStatusChange(assetRetirementGlobal.getGeneralLedgerPendingEntries());
241 
242         // release the lock when document status changed as following...
243         WorkflowDocument workflowDoc = documentHeader.getWorkflowDocument();
244         if (workflowDoc.isCanceled() || workflowDoc.isDisapproved() || workflowDoc.isProcessed() || workflowDoc.isFinal()) {
245             this.getCapitalAssetManagementModuleService().deleteAssetLocks(getDocumentNumber(), null);
246         }
247     }
248 
249     /**
250      * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#addNewLineToCollection(java.lang.String)
251      */
252     @Override
253     public void addNewLineToCollection(String collectionName) {
254         super.addNewLineToCollection(collectionName);
255 
256         AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject();
257         if (StringUtils.isBlank(assetRetirementGlobal.getMergedTargetCapitalAssetDescription()) && ObjectUtils.isNotNull(assetRetirementGlobal.getMergedTargetCapitalAssetNumber())) {
258             assetRetirementGlobal.setMergedTargetCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAsset().getCapitalAssetDescription());
259         }
260     }
261 
262     @Override
263     public Class<? extends PersistableBusinessObject> getPrimaryEditedBusinessObjectClass() {
264         return Asset.class;
265     }
266 
267     @Override
268     public Map<String, String> populateNewCollectionLines( Map<String, String> fieldValues, MaintenanceDocument maintenanceDocument, String methodToCall ) {
269         String capitalAssetNumber = (String)fieldValues.get(CamsPropertyConstants.AssetRetirementGlobal.CAPITAL_ASSET_NUMBER);
270 
271         if (StringUtils.isNotBlank(capitalAssetNumber)) {
272             fieldValues.remove(CamsPropertyConstants.AssetRetirementGlobal.CAPITAL_ASSET_NUMBER);
273             fieldValues.put(CamsPropertyConstants.AssetRetirementGlobal.CAPITAL_ASSET_NUMBER, capitalAssetNumber.trim());
274 		}
275         return super.populateNewCollectionLines(fieldValues, maintenanceDocument, methodToCall);
276 
277     }
278 
279     private AssetRetirementService getAssetRetirementService() {
280         return SpringContext.getBean(AssetRetirementService.class);
281     }
282 
283     private AssetService getAssetService() {
284         return SpringContext.getBean(AssetService.class);
285     }
286 
287     private AssetPaymentService getAssetPaymentService() {
288         return SpringContext.getBean(AssetPaymentService.class);
289     }
290 
291     /**
292      * Checks for Accounting Period 13
293      * @param assetRetirementGlobal
294      * @return true if the accountingPeriod in assetRetirementGlobal is 13.
295      * TODO Remove hardcoding
296      */
297     private boolean isPeriod13(AssetRetirementGlobal assetRetirementGlobal) {
298         if (ObjectUtils.isNull(assetRetirementGlobal.getAccountingPeriod())) {
299             return false;
300         }
301         return "13".equals(assetRetirementGlobal.getAccountingPeriod().getUniversityFiscalPeriodCode());
302     }
303 
304     /**
305      * Return the closing date as mm/dd/yyyy
306      * @param closingYear
307      * @return the closing date as mm/dd/yyyy
308 
309      */
310     private String getClosingDate(Integer closingYear) {
311         return SpringContext.getBean(AssetGlobalService.class).getFiscalYearEndDayAndMonth() + closingYear.toString();
312     }
313 
314 
315     /**
316      * Return the calendar Date for the closing year
317      * @param closingYear
318      * @return 01/01/[closing year]
319      * TODO Remove hardcoding
320      */
321     private String getClosingCalendarDate(Integer closingYear) {
322         return "01/01/" + closingYear.toString();
323     }
324 
325     /**
326      * Convenience method to reduce clutter
327      * @return {@link DateTimeService}
328      */
329     private DateTimeService getDateTimeService() {
330         return SpringContext.getBean(DateTimeService.class);
331     }
332 
333     /**
334      * Perform changes to assetRetirementGlobal on period 13.
335      * @param assetRetirementGlobal
336      */
337     private void doPeriod13Changes(AssetRetirementGlobal assetRetirementGlobal) {
338         if (isPeriod13(assetRetirementGlobal)) {
339             Integer closingYear = new Integer(SpringContext.getBean(ParameterService.class).getParameterValueAsString(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, GeneralLedgerConstants.ANNUAL_CLOSING_FISCAL_YEAR_PARM));
340             String closingDate = getClosingDate(closingYear);
341             try {
342                 updateAssetRetirementGlobalForPeriod13(assetRetirementGlobal, closingYear, closingDate);
343             } catch (Exception e) {
344                 LOG.error(e);
345             }
346         }
347     }
348 
349 
350     /**
351      * Update assetRetirementGlobal fields for period 13
352      * @param assetRetirementGlobal
353      * @param closingYear
354      * @param closingDate
355      * @throws ParseException
356      */
357     private void updateAssetRetirementGlobalForPeriod13(AssetRetirementGlobal assetRetirementGlobal, Integer closingYear, String closingDate) throws ParseException {
358         // TODO what, if anything needs to be here?
359 //        assetRetirementGlobal.setCreateDate(getDateTimeService().getCurrentSqlDate());
360 //        assetRetirementGlobal.setCapitalAssetInServiceDate(getDateTimeService().convertToSqlDate(closingDate));
361 //        assetRetirementGlobal.setCreateDate(getDateTimeService().convertToSqlDate(closingDate));
362 //        assetRetirementGlobal.setCapitalAssetDepreciationDate(getDateTimeService().convertToSqlDate(getClosingCalendarDate(closingYear)));
363 //        assetRetirementGlobal.setLastInventoryDate(getDateTimeService().getCurrentSqlDate());
364     }
365 }