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.service.impl;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.kuali.kfs.coa.businessobject.ObjectCode;
020    import org.kuali.kfs.coa.businessobject.OffsetDefinition;
021    import org.kuali.kfs.coa.service.OffsetDefinitionService;
022    import org.kuali.kfs.fp.document.YearEndDocument;
023    import org.kuali.kfs.fp.document.service.YearEndPendingEntryService;
024    import org.kuali.kfs.gl.service.SufficientFundsService;
025    import org.kuali.kfs.sys.KFSPropertyConstants;
026    import org.kuali.kfs.sys.businessobject.AccountingLine;
027    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
028    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
029    import org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBaseConstants;
030    import org.kuali.kfs.sys.service.UniversityDateService;
031    import org.kuali.rice.kns.document.TransactionalDocument;
032    import org.kuali.rice.kns.exception.ReferentialIntegrityException;
033    import org.kuali.rice.kns.util.ObjectUtils;
034    
035    /**
036     * The default implementation of the YearEndPendingEntryService
037     */
038    public class YearEndPendingEntryServiceImpl implements YearEndPendingEntryService {
039        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(YearEndPendingEntryServiceImpl.class);
040        
041        private static final String FINAL_ACCOUNTING_PERIOD = "13";
042        
043        protected UniversityDateService universityDateService;
044        protected SufficientFundsService sufficientFundsService;
045        protected OffsetDefinitionService offsetDefinitionService;
046    
047        /**
048         * @see org.kuali.kfs.fp.document.service.YearEndPendingEntryService#customizeExplicitGeneralLedgerPendingEntry(org.kuali.rice.kns.document.TransactionalDocument, org.kuali.kfs.sys.businessobject.AccountingLine, org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry)
049         */
050        public void customizeExplicitGeneralLedgerPendingEntry(TransactionalDocument transactionalDocument, AccountingLine accountingLine, GeneralLedgerPendingEntry explicitEntry) {
051            if (!YearEndDocument.class.isAssignableFrom(transactionalDocument.getClass())) {
052                throw new IllegalArgumentException("invalid (not a year end document) for class:" + transactionalDocument.getClass());
053            }
054            YearEndDocument yearEndDocument = (YearEndDocument) transactionalDocument;
055            explicitEntry.setUniversityFiscalPeriodCode(getAccountingPeriodForYearEndEntry());
056            explicitEntry.setUniversityFiscalYear(getPreviousFiscalYear());
057        }
058    
059        /**
060         * @see org.kuali.kfs.fp.document.service.YearEndPendingEntryService#customizeOffsetGeneralLedgerPendingEntry(org.kuali.rice.kns.document.TransactionalDocument, org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail, org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry, org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry)
061         */
062        public boolean customizeOffsetGeneralLedgerPendingEntry(TransactionalDocument transactionalDocument, GeneralLedgerPendingEntrySourceDetail accountingLine, GeneralLedgerPendingEntry explicitEntry, GeneralLedgerPendingEntry offsetEntry) {
063            if (!(transactionalDocument instanceof YearEndDocument)) {
064                throw new IllegalArgumentException("invalid (not a year end document) for class:" + transactionalDocument.getClass());
065            }
066            OffsetDefinition offsetDefinition = getOffsetDefinitionService().getByPrimaryId(getPreviousFiscalYear(), explicitEntry.getChartOfAccountsCode(), explicitEntry.getFinancialDocumentTypeCode(), explicitEntry.getFinancialBalanceTypeCode());
067            if (!ObjectUtils.isNull(offsetDefinition)) {
068                String offsetObjectCode = getOffsetFinancialObjectCode(offsetDefinition);
069                offsetEntry.setFinancialObjectCode(offsetObjectCode);
070                if (offsetObjectCode.equals(AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode())) {
071                    // no BO, so punt
072                    offsetEntry.setAcctSufficientFundsFinObjCd(AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode());
073                }
074                else {
075                    offsetDefinition.refreshReferenceObject(KFSPropertyConstants.FINANCIAL_OBJECT);
076                    ObjectCode financialObject = offsetDefinition.getFinancialObject();
077                    // The ObjectCode reference may be invalid because a flexible offset account changed its chart code.
078                    if (ObjectUtils.isNull(financialObject)) {
079                        throw new ReferentialIntegrityException("offset object code " + offsetEntry.getUniversityFiscalYear() + "-" + offsetEntry.getChartOfAccountsCode() + "-" + offsetEntry.getFinancialObjectCode());
080                    }
081                    offsetEntry.refreshReferenceObject(KFSPropertyConstants.ACCOUNT);
082                    offsetEntry.setAcctSufficientFundsFinObjCd(getSufficientFundsService().getSufficientFundsObjectCode(financialObject, offsetEntry.getAccount().getAccountSufficientFundsCode()));
083                }
084    
085                offsetEntry.setFinancialObjectTypeCode(getOffsetFinancialObjectTypeCode(offsetDefinition));
086                
087                return true;
088            }
089            return false;
090        }
091    
092        /**
093         * @see org.kuali.kfs.fp.document.service.YearEndPendingEntryService#getFinalAccountingPeriod()
094         */
095        public String getFinalAccountingPeriod() {
096            return FINAL_ACCOUNTING_PERIOD;
097        }
098        
099        /**
100         * @return the accounting period the year end entry should be populated with
101         */
102        protected String getAccountingPeriodForYearEndEntry() {
103            return getFinalAccountingPeriod();
104        }
105    
106        /**
107         * @see org.kuali.kfs.fp.document.service.YearEndPendingEntryService#getPreviousFiscalYear()
108         */
109        public Integer getPreviousFiscalYear() {
110            int i = getUniversityDateService().getCurrentFiscalYear().intValue() - 1;
111            return new Integer(i);
112        }
113        
114        /**
115         * Helper method that determines the offset entry's financial object code.
116         * 
117         * @param offsetDefinition
118         * @return String
119         */
120        protected String getOffsetFinancialObjectCode(OffsetDefinition offsetDefinition) {
121            LOG.debug("getOffsetFinancialObjectCode(OffsetDefinition) - start");
122    
123            if (null != offsetDefinition) {
124                String returnString = (!StringUtils.isBlank(offsetDefinition.getFinancialObjectCode())) ? offsetDefinition.getFinancialObjectCode() : AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode();
125                LOG.debug("getOffsetFinancialObjectCode(OffsetDefinition) - end");
126                return returnString;
127            }
128            else {
129                LOG.debug("getOffsetFinancialObjectCode(OffsetDefinition) - end");
130                return AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode();
131            }
132    
133        }
134        
135        /**
136         * Helper method that determines the offset entry's financial object type code.
137         * 
138         * @param offsetDefinition
139         * @return String
140         */
141        protected String getOffsetFinancialObjectTypeCode(OffsetDefinition offsetDefinition) {
142            LOG.debug("getOffsetFinancialObjectTypeCode(OffsetDefinition) - start");
143    
144            if (null != offsetDefinition && null != offsetDefinition.getFinancialObject()) {
145                String returnString = (!StringUtils.isBlank(offsetDefinition.getFinancialObject().getFinancialObjectTypeCode())) ? offsetDefinition.getFinancialObject().getFinancialObjectTypeCode() : AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectType();
146                LOG.debug("getOffsetFinancialObjectTypeCode(OffsetDefinition) - end");
147                return returnString;
148            }
149            else {
150                LOG.debug("getOffsetFinancialObjectTypeCode(OffsetDefinition) - end");
151                return AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectType();
152            }
153    
154        }
155    
156        public UniversityDateService getUniversityDateService() {
157            return universityDateService;
158        }
159    
160        public void setUniversityDateService(UniversityDateService universityDateService) {
161            this.universityDateService = universityDateService;
162        }
163    
164        public SufficientFundsService getSufficientFundsService() {
165            return sufficientFundsService;
166        }
167    
168        public void setSufficientFundsService(SufficientFundsService sufficientFundsService) {
169            this.sufficientFundsService = sufficientFundsService;
170        }
171    
172        public OffsetDefinitionService getOffsetDefinitionService() {
173            return offsetDefinitionService;
174        }
175    
176        public void setOffsetDefinitionService(OffsetDefinitionService offsetDefinitionService) {
177            this.offsetDefinitionService = offsetDefinitionService;
178        }
179    
180    }