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.fp.document;
017    
018    import static org.kuali.kfs.sys.KFSConstants.FROM;
019    import static org.kuali.kfs.sys.KFSConstants.TO;
020    
021    import java.util.List;
022    
023    import org.apache.commons.lang.StringUtils;
024    import org.kuali.kfs.fp.businessobject.CapitalAssetInformation;
025    import org.kuali.kfs.fp.businessobject.GECSourceAccountingLine;
026    import org.kuali.kfs.fp.businessobject.GECTargetAccountingLine;
027    import org.kuali.kfs.fp.businessobject.GeneralErrorCorrectionDocumentAccountingLineParser;
028    import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService;
029    import org.kuali.kfs.sys.businessobject.AccountingLine;
030    import org.kuali.kfs.sys.businessobject.AccountingLineParser;
031    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
032    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
033    import org.kuali.kfs.sys.context.SpringContext;
034    import org.kuali.kfs.sys.document.AccountingDocumentBase;
035    import org.kuali.kfs.sys.document.AmountTotaling;
036    import org.kuali.kfs.sys.document.Correctable;
037    import org.kuali.kfs.sys.document.service.DebitDeterminerService;
038    import org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE;
039    import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO;
040    import org.kuali.rice.kns.document.Copyable;
041    import org.kuali.rice.kns.rule.event.KualiDocumentEvent;
042    import org.kuali.rice.kns.rule.event.SaveDocumentEvent;
043    import org.kuali.rice.kns.service.DataDictionaryService;
044    import org.kuali.rice.kns.util.ObjectUtils;
045    
046    
047    /**
048     * This is the business object that represents the GeneralErrorCorrectionDocument in Kuali. This is a transactional document that
049     * will eventually post transactions to the G/L. It integrates with workflow and also contains two groupings of accounting lines:
050     * from and to. From lines are the source lines, to lines are the target lines.
051     */
052    public class GeneralErrorCorrectionDocument extends AccountingDocumentBase implements Copyable, Correctable, AmountTotaling, CapitalAssetEditable {
053    
054        protected CapitalAssetInformation capitalAssetInformation;
055        protected transient CapitalAssetManagementModuleService capitalAssetManagementModuleService;
056    
057        /**
058         * Initializes the array lists and some basic info.
059         */
060        public GeneralErrorCorrectionDocument() {
061            super();
062        }
063    
064        /**
065         * @see org.kuali.kfs.sys.document.AccountingDocumentBase#buildListOfDeletionAwareLists()
066         */
067        @Override
068        public List buildListOfDeletionAwareLists() {
069            List<List> managedLists = super.buildListOfDeletionAwareLists();
070            if (ObjectUtils.isNotNull(capitalAssetInformation) && ObjectUtils.isNotNull(capitalAssetInformation.getCapitalAssetInformationDetails())) {
071                managedLists.add(capitalAssetInformation.getCapitalAssetInformationDetails());
072            }
073            return managedLists;
074        }
075    
076        /**
077         * Overrides the base implementation to return "From".
078         * 
079         * @see org.kuali.kfs.sys.document.AccountingDocument#getSourceAccountingLinesSectionTitle()
080         */
081        @Override
082        public String getSourceAccountingLinesSectionTitle() {
083            return FROM;
084        }
085    
086        /**
087         * Overrides the base implementation to return "To".
088         * 
089         * @see org.kuali.kfs.sys.document.AccountingDocument#getTargetAccountingLinesSectionTitle()
090         */
091        @Override
092        public String getTargetAccountingLinesSectionTitle() {
093            return TO;
094        }
095    
096        /**
097         * @see org.kuali.kfs.sys.document.AccountingDocumentBase#getSourceAccountingLineClass()
098         */
099        @Override
100        public Class getSourceAccountingLineClass() {
101            return GECSourceAccountingLine.class;
102        }
103    
104        /**
105         * @see org.kuali.kfs.sys.document.AccountingDocumentBase#getTargetAccountingLineClass()
106         */
107        @Override
108        public Class getTargetAccountingLineClass() {
109            return GECTargetAccountingLine.class;
110        }
111    
112        /**
113         * Returns true if accounting line is debit
114         * 
115         * @param transactionalDocument submitted accounting document
116         * @param accountingLine accounting line in account document
117         * @see IsDebitUtils#isDebitConsideringSectionAndTypePositiveOnly(FinancialDocumentRuleBase, FinancialDocument, AccountingLine)
118         * @see org.kuali.rice.kns.rule.AccountingLineRule#isDebit(org.kuali.rice.kns.document.FinancialDocument,
119         *      org.kuali.rice.kns.bo.AccountingLine)
120         */
121        public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
122            DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
123            return isDebitUtils.isDebitConsideringSectionAndTypePositiveOnly(this, (AccountingLine) postable);
124        }
125    
126        /**
127         * Customizes a GLPE by setting financial document number, financial system origination code and document type code to null
128         * 
129         * @param transactionalDocument submitted accounting document
130         * @param accountingLine accounting line in document
131         * @param explicitEntry general ledger pending entry
132         * @see FinancialDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(FinancialDocument, AccountingLine,
133         *      GeneralLedgerPendingEntry)
134         */
135        @Override
136        public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) {
137            explicitEntry.setTransactionLedgerEntryDescription(buildTransactionLedgerEntryDescriptionUsingRefOriginAndRefDocNumber(postable));
138    
139            // Clearing fields that are already handled by the parent algorithm - we don't actually want
140            // these to copy over from the accounting lines b/c they don't belong in the GLPEs
141            // if the aren't nulled, then GECs fail to post
142            explicitEntry.setReferenceFinancialDocumentNumber(null);
143            explicitEntry.setReferenceFinancialSystemOriginationCode(null);
144            explicitEntry.setReferenceFinancialDocumentTypeCode(null);
145        }
146    
147        /**
148         * Builds an appropriately formatted string to be used for the <code>transactionLedgerEntryDescription</code>. It is built
149         * using information from the <code>{@link AccountingLine}</code>. Format is "01-12345: blah blah blah".
150         * 
151         * @param line accounting line
152         * @param transactionalDocument submitted accounting document
153         * @return String formatted string to be used for transaction ledger entry description
154         */
155        protected String buildTransactionLedgerEntryDescriptionUsingRefOriginAndRefDocNumber(GeneralLedgerPendingEntrySourceDetail line) {
156            String description = "";
157            description = line.getReferenceOriginCode() + "-" + line.getReferenceNumber();
158    
159            if (StringUtils.isNotBlank(line.getFinancialDocumentLineDescription())) {
160                description += ": " + line.getFinancialDocumentLineDescription();
161            }
162            else {
163                description += ": " + getDocumentHeader().getDocumentDescription();
164            }
165    
166            if (description.length() > GENERAL_LEDGER_PENDING_ENTRY_CODE.GLPE_DESCRIPTION_MAX_LENGTH) {
167                description = description.substring(0, GENERAL_LEDGER_PENDING_ENTRY_CODE.GLPE_DESCRIPTION_MAX_LENGTH - 3) + "...";
168            }
169    
170            return description;
171        }
172    
173        /**
174         * Gets the capitalAssetInformation attribute.
175         * 
176         * @return Returns the capitalAssetInformation.
177         */
178        public CapitalAssetInformation getCapitalAssetInformation() {
179            return ObjectUtils.isNull(capitalAssetInformation) ? null : capitalAssetInformation;
180        }
181    
182        /**
183         * Sets the capitalAssetInformation attribute value.
184         * 
185         * @param capitalAssetInformation The capitalAssetInformation to set.
186         */
187        @Deprecated
188        public void setCapitalAssetInformation(CapitalAssetInformation capitalAssetInformation) {
189            this.capitalAssetInformation = capitalAssetInformation;
190        }
191    
192        /**
193         * @see org.kuali.kfs.sys.document.GeneralLedgerPostingDocumentBase#doRouteStatusChange()
194         */
195        @Override
196        public void doRouteStatusChange(DocumentRouteStatusChangeDTO statusChangeEvent) {
197            super.doRouteStatusChange(statusChangeEvent);
198            this.getCapitalAssetManagementModuleService().deleteDocumentAssetLocks(this);
199        }
200    
201    
202        /**
203         * @see org.kuali.rice.kns.document.DocumentBase#postProcessSave(org.kuali.rice.kns.rule.event.KualiDocumentEvent)
204         */
205        @Override
206        public void postProcessSave(KualiDocumentEvent event) {
207            super.postProcessSave(event);
208            if (!(event instanceof SaveDocumentEvent)) { // don't lock until they route
209                String documentTypeName = SpringContext.getBean(DataDictionaryService.class).getDocumentTypeNameByClass(this.getClass());
210                this.getCapitalAssetManagementModuleService().generateCapitalAssetLock(this, documentTypeName);
211            }
212        }
213    
214        /**
215         * @return CapitalAssetManagementModuleService
216         */
217        public CapitalAssetManagementModuleService getCapitalAssetManagementModuleService() {
218            if (capitalAssetManagementModuleService == null) {
219                capitalAssetManagementModuleService = SpringContext.getBean(CapitalAssetManagementModuleService.class);
220            }
221            return capitalAssetManagementModuleService;
222        }
223    }