/* * 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.document; import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.kuali.kfs.gl.GeneralLedgerConstants; import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService; import org.kuali.kfs.module.cam.CamsConstants; import org.kuali.kfs.module.cam.CamsKeyConstants; import org.kuali.kfs.module.cam.CamsPropertyConstants; import org.kuali.kfs.module.cam.businessobject.Asset; import org.kuali.kfs.module.cam.businessobject.AssetPayment; import org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal; import org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobalDetail; import org.kuali.kfs.module.cam.document.gl.AssetRetirementGeneralLedgerPendingEntrySource; import org.kuali.kfs.module.cam.document.service.AssetGlobalService; import org.kuali.kfs.module.cam.document.service.AssetPaymentService; import org.kuali.kfs.module.cam.document.service.AssetRetirementService; import org.kuali.kfs.module.cam.document.service.AssetService; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.businessobject.FinancialSystemDocumentHeader; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.document.LedgerPostingMaintainable; import org.kuali.kfs.sys.service.impl.KfsParameterConstants; import org.kuali.rice.core.api.datetime.DateTimeService; import org.kuali.rice.core.api.parameter.ParameterEvaluator; import org.kuali.rice.core.api.parameter.ParameterEvaluatorService; import org.kuali.rice.coreservice.framework.parameter.ParameterService; import org.kuali.rice.kew.api.WorkflowDocument; import org.kuali.rice.kns.document.MaintenanceDocument; import org.kuali.rice.kns.util.KNSGlobalVariables; import org.kuali.rice.krad.bo.DocumentHeader; import org.kuali.rice.krad.bo.PersistableBusinessObject; import org.kuali.rice.krad.maintenance.MaintenanceLock; import org.kuali.rice.krad.service.BusinessObjectService; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.KRADConstants; import org.kuali.rice.krad.util.ObjectUtils; /** * This class overrides the base {@link KualiGlobalMaintainableImpl} to generate the specific maintenance locks for Global location * assets */ public class AssetRetirementGlobalMaintainableImpl extends LedgerPostingMaintainable { private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AssetRetirementGlobalMaintainableImpl.class); protected static final String RETIRED_ASSET_TRANSFERRED_EXTERNALLY = "RetiredAssetTransferredExternally"; protected static final String RETIRED_ASSET_SOLD_OR_GIFTED = "RetiredAssetSoldOrGifted"; /** * @see org.kuali.kfs.sys.document.FinancialSystemGlobalMaintainable#answerSplitNodeQuestion(java.lang.String) */ @Override protected boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException { String retirementReason = ((AssetRetirementGlobal) getBusinessObject()).getRetirementReasonCode(); if (this.RETIRED_ASSET_TRANSFERRED_EXTERNALLY.equals(nodeName)) { return CamsConstants.AssetRetirementReasonCode.EXTERNAL_TRANSFER.equalsIgnoreCase(retirementReason); } if (this.RETIRED_ASSET_SOLD_OR_GIFTED.equals(nodeName)) { return CamsConstants.AssetRetirementReasonCode.SOLD.equalsIgnoreCase(retirementReason) || CamsConstants.AssetRetirementReasonCode.GIFT.equalsIgnoreCase(retirementReason); } throw new UnsupportedOperationException("Cannot answer split question for this node you call \"" + nodeName + "\""); } /** * We are using a substitute mechanism for asset locking which can lock on assets when rule check passed. Return empty list from * this method. * * @see org.kuali.rice.kns.maintenance.Maintainable#generateMaintenanceLocks() */ @Override public List<MaintenanceLock> generateMaintenanceLocks() { return new ArrayList<MaintenanceLock>(); } protected CapitalAssetManagementModuleService getCapitalAssetManagementModuleService() { return SpringContext.getBean(CapitalAssetManagementModuleService.class); } @Override public void setupNewFromExisting(MaintenanceDocument document, Map<String, String[]> parameters) { super.setupNewFromExisting(document, parameters); AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject(); if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal)) { if (ObjectUtils.isNotNull(assetRetirementGlobal.getMergedTargetCapitalAssetNumber())) { assetRetirementGlobal.setMergedTargetCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAsset().getCapitalAssetDescription()); } } // add doc header description if retirement reason is "MERGED" if (CamsConstants.AssetRetirementReasonCode.MERGED.equals(assetRetirementGlobal.getRetirementReasonCode())) { document.getDocumentHeader().setDocumentDescription(CamsConstants.AssetRetirementGlobal.MERGE_AN_ASSET_DESCRIPTION); } // Fiscal Year End modifications String docType = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName(); ParameterEvaluatorService parameterEvaluatorService = SpringContext.getBean(ParameterEvaluatorService.class); 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); if (evaluator.evaluationSucceeds() && isPeriod13(assetRetirementGlobal) ) { Integer closingYear = new Integer(SpringContext.getBean(ParameterService.class).getParameterValueAsString(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, GeneralLedgerConstants.ANNUAL_CLOSING_FISCAL_YEAR_PARM)); String closingDate = getClosingDate(closingYear); try { if (ObjectUtils.isNotNull(assetRetirementGlobal.getPostingYear()) ) { assetRetirementGlobal.setAccountingPeriodCompositeString(assetRetirementGlobal.getAccountingPeriod().getUniversityFiscalPeriodCode()+assetRetirementGlobal.getPostingYear()); } updateAssetRetirementGlobalForPeriod13(assetRetirementGlobal, closingYear, closingDate); assetRetirementGlobal.refreshNonUpdateableReferences(); } catch (Exception e) { LOG.error(e); } } } /** * @see org.kuali.rice.kns.maintenance.KualiGlobalMaintainableImpl#processGlobalsAfterRetrieve() */ @Override protected void processGlobalsAfterRetrieve() { super.processGlobalsAfterRetrieve(); AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject(); List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails(); for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) { // Set non-persistent values. So the screen can show them after submit. getAssetService().setAssetSummaryFields(assetRetirementGlobalDetail.getAsset()); } } @Override public void addMultipleValueLookupResults(MaintenanceDocument document, String collectionName, Collection<PersistableBusinessObject> rawValues, boolean needsBlank, PersistableBusinessObject bo) { AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) document.getDocumentBusinessObject(); List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails(); int nElements = assetRetirementGlobal.getAssetRetirementGlobalDetails().size() + rawValues.size(); if (!getAssetService().isDocumentEnrouting(document) && !getAssetRetirementService().isAllowedRetireMultipleAssets(document) && nElements > new Integer(1)) { GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.Retirement.ERROR_MULTIPLE_ASSET_RETIRED); } else { GlobalVariables.getMessageMap().clearErrorMessages(); // Adding the selected asset. super.addMultipleValueLookupResults(document, collectionName, rawValues, needsBlank, bo); } } /** * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#refresh(java.lang.String, java.util.Map, * org.kuali.rice.kns.document.MaintenanceDocument) */ @Override public void refresh(String refreshCaller, Map fieldValues, MaintenanceDocument document) { super.refresh(refreshCaller, fieldValues, document); AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) document.getDocumentBusinessObject(); List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails(); if (KFSConstants.MULTIPLE_VALUE.equalsIgnoreCase(refreshCaller)) { // Set non-persistent values in multiple lookup result collection. So the screen can show them when return from multiple // lookup. for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) { getAssetService().setAssetSummaryFields(assetRetirementGlobalDetail.getAsset()); } } else if (CamsConstants.AssetRetirementGlobal.ASSET_LOOKUPABLE_ID.equalsIgnoreCase(refreshCaller)) { // Set non-persistent values in the result from asset lookup. So the screen can show them when return from single asset // lookup. String referencesToRefresh = (String) fieldValues.get(KRADConstants.REFERENCES_TO_REFRESH); if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal) && CamsPropertyConstants.AssetRetirementGlobal.MERGED_TARGET_CAPITAL_ASSET.equals(referencesToRefresh)) { assetRetirementGlobal.setMergedTargetCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAsset().getCapitalAssetDescription()); } AssetRetirementGlobalDetail newDetail = (AssetRetirementGlobalDetail) newCollectionLines.get(CamsPropertyConstants.AssetRetirementGlobal.ASSET_RETIREMENT_GLOBAL_DETAILS); getAssetService().setAssetSummaryFields(newDetail.getAsset()); } } /** * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#doRouteStatusChange(org.kuali.rice.krad.bo.DocumentHeader) */ @Override public void doRouteStatusChange(DocumentHeader documentHeader) { super.doRouteStatusChange(documentHeader); AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject(); if (documentHeader.getWorkflowDocument().isEnroute()) { // display a message for asset not generating ledger entries when it is federally owned boolean allPaymentsFederalOwned = true; List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails(); for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) { for (AssetPayment assetPayment : assetRetirementGlobalDetail.getAsset().getAssetPayments()) { if (!getAssetPaymentService().isPaymentFederalOwned(assetPayment)) { allPaymentsFederalOwned = false; } } } if (allPaymentsFederalOwned) { KNSGlobalVariables.getMessageList().add(CamsKeyConstants.Retirement.MESSAGE_NO_LEDGER_ENTRY_REQUIRED_RETIREMENT); } } // all approvals have been processed, the retirement date is set to the approval date if (documentHeader.getWorkflowDocument().isProcessed()) { assetRetirementGlobal.setRetirementDate(SpringContext.getBean(DateTimeService.class).getCurrentSqlDate()); SpringContext.getBean(BusinessObjectService.class).save(assetRetirementGlobal); if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal)) { assetRetirementGlobal.getMergedTargetCapitalAsset().setCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAssetDescription()); SpringContext.getBean(BusinessObjectService.class).save(assetRetirementGlobal.getMergedTargetCapitalAsset()); } } new AssetRetirementGeneralLedgerPendingEntrySource((FinancialSystemDocumentHeader) documentHeader).doRouteStatusChange(assetRetirementGlobal.getGeneralLedgerPendingEntries()); // release the lock when document status changed as following... WorkflowDocument workflowDoc = documentHeader.getWorkflowDocument(); if (workflowDoc.isCanceled() || workflowDoc.isDisapproved() || workflowDoc.isProcessed() || workflowDoc.isFinal()) { this.getCapitalAssetManagementModuleService().deleteAssetLocks(getDocumentNumber(), null); } } /** * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#addNewLineToCollection(java.lang.String) */ @Override public void addNewLineToCollection(String collectionName) { super.addNewLineToCollection(collectionName); AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) getBusinessObject(); if (StringUtils.isBlank(assetRetirementGlobal.getMergedTargetCapitalAssetDescription()) && ObjectUtils.isNotNull(assetRetirementGlobal.getMergedTargetCapitalAssetNumber())) { assetRetirementGlobal.setMergedTargetCapitalAssetDescription(assetRetirementGlobal.getMergedTargetCapitalAsset().getCapitalAssetDescription()); } } @Override public Class<? extends PersistableBusinessObject> getPrimaryEditedBusinessObjectClass() { return Asset.class; } @Override public Map<String, String> populateNewCollectionLines( Map<String, String> fieldValues, MaintenanceDocument maintenanceDocument, String methodToCall ) { String capitalAssetNumber = (String)fieldValues.get(CamsPropertyConstants.AssetRetirementGlobal.CAPITAL_ASSET_NUMBER); if (StringUtils.isNotBlank(capitalAssetNumber)) { fieldValues.remove(CamsPropertyConstants.AssetRetirementGlobal.CAPITAL_ASSET_NUMBER); fieldValues.put(CamsPropertyConstants.AssetRetirementGlobal.CAPITAL_ASSET_NUMBER, capitalAssetNumber.trim()); } return super.populateNewCollectionLines(fieldValues, maintenanceDocument, methodToCall); } private AssetRetirementService getAssetRetirementService() { return SpringContext.getBean(AssetRetirementService.class); } private AssetService getAssetService() { return SpringContext.getBean(AssetService.class); } private AssetPaymentService getAssetPaymentService() { return SpringContext.getBean(AssetPaymentService.class); } /** * Checks for Accounting Period 13 * @param assetRetirementGlobal * @return true if the accountingPeriod in assetRetirementGlobal is 13. * TODO Remove hardcoding */ private boolean isPeriod13(AssetRetirementGlobal assetRetirementGlobal) { if (ObjectUtils.isNull(assetRetirementGlobal.getAccountingPeriod())) { return false; } return "13".equals(assetRetirementGlobal.getAccountingPeriod().getUniversityFiscalPeriodCode()); } /** * Return the closing date as mm/dd/yyyy * @param closingYear * @return the closing date as mm/dd/yyyy */ private String getClosingDate(Integer closingYear) { return SpringContext.getBean(AssetGlobalService.class).getFiscalYearEndDayAndMonth() + closingYear.toString(); } /** * Return the calendar Date for the closing year * @param closingYear * @return 01/01/[closing year] * TODO Remove hardcoding */ private String getClosingCalendarDate(Integer closingYear) { return "01/01/" + closingYear.toString(); } /** * Convenience method to reduce clutter * @return {@link DateTimeService} */ private DateTimeService getDateTimeService() { return SpringContext.getBean(DateTimeService.class); } /** * Perform changes to assetRetirementGlobal on period 13. * @param assetRetirementGlobal */ private void doPeriod13Changes(AssetRetirementGlobal assetRetirementGlobal) { if (isPeriod13(assetRetirementGlobal)) { Integer closingYear = new Integer(SpringContext.getBean(ParameterService.class).getParameterValueAsString(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, GeneralLedgerConstants.ANNUAL_CLOSING_FISCAL_YEAR_PARM)); String closingDate = getClosingDate(closingYear); try { updateAssetRetirementGlobalForPeriod13(assetRetirementGlobal, closingYear, closingDate); } catch (Exception e) { LOG.error(e); } } } /** * Update assetRetirementGlobal fields for period 13 * @param assetRetirementGlobal * @param closingYear * @param closingDate * @throws ParseException */ private void updateAssetRetirementGlobalForPeriod13(AssetRetirementGlobal assetRetirementGlobal, Integer closingYear, String closingDate) throws ParseException { // TODO what, if anything needs to be here? // assetRetirementGlobal.setCreateDate(getDateTimeService().getCurrentSqlDate()); // assetRetirementGlobal.setCapitalAssetInServiceDate(getDateTimeService().convertToSqlDate(closingDate)); // assetRetirementGlobal.setCreateDate(getDateTimeService().convertToSqlDate(closingDate)); // assetRetirementGlobal.setCapitalAssetDepreciationDate(getDateTimeService().convertToSqlDate(getClosingCalendarDate(closingYear))); // assetRetirementGlobal.setLastInventoryDate(getDateTimeService().getCurrentSqlDate()); } }