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.gl.batch;
017    
018    import java.io.PrintStream;
019    import java.sql.Date;
020    import java.util.HashMap;
021    import java.util.Map;
022    
023    import org.kuali.kfs.coa.businessobject.BalanceType;
024    import org.kuali.kfs.coa.businessobject.PriorYearAccount;
025    import org.kuali.kfs.coa.service.BalanceTypeService;
026    import org.kuali.kfs.coa.service.PriorYearAccountService;
027    import org.kuali.kfs.coa.service.SubFundGroupService;
028    import org.kuali.kfs.gl.ObjectHelper;
029    import org.kuali.kfs.gl.batch.service.impl.exception.NonFatalErrorException;
030    import org.kuali.kfs.gl.businessobject.Balance;
031    import org.kuali.kfs.gl.businessobject.OriginEntryFull;
032    import org.kuali.kfs.gl.report.LedgerSummaryReport;
033    import org.kuali.kfs.gl.service.OriginEntryService;
034    import org.kuali.kfs.sys.KFSConstants;
035    import org.kuali.kfs.sys.businessobject.SystemOptions;
036    import org.kuali.kfs.sys.context.SpringContext;
037    import org.kuali.kfs.sys.exception.InvalidFlexibleOffsetException;
038    import org.kuali.kfs.sys.service.FlexibleOffsetAccountService;
039    import org.kuali.kfs.sys.service.OptionsService;
040    import org.kuali.kfs.sys.service.ReportWriterService;
041    import org.kuali.kfs.sys.service.impl.KfsParameterConstants;
042    import org.kuali.rice.kns.service.ParameterService;
043    import org.kuali.rice.kns.util.KualiDecimal;
044    import org.kuali.rice.kns.util.ObjectUtils;
045    
046    /**
047     * A class to hold significant state for a balance forward job; it also has the methods that actually accomplish the job
048     */
049    public class BalanceForwardRuleHelper {
050        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(BalanceForwardRuleHelper.class);
051        private FlexibleOffsetAccountService flexibleOffsetAccountService;
052    
053        /**
054         * A container for the state of the balance forward process. The way state is handled is heavily dependent upon the way in which
055         * YearEndServiceImpl.forwardBalancesForFiscalYear works.
056         */
057        public static class BalanceForwardProcessState {
058            private int globalReadCount;
059            private int globalSelectCount;
060            private int sequenceNumber;
061            private int sequenceClosedCount;
062            private int sequenceWriteCount;
063            private String accountNumberHold;
064            private int nonFatalCount;
065    
066            public String getAccountNumberHold() {
067                return accountNumberHold;
068            }
069    
070            public void setAccountNumberHold(String accountNumberHold) {
071                this.accountNumberHold = accountNumberHold;
072            }
073    
074            public void incrementGlobalReadCount() {
075                globalReadCount++;
076            }
077    
078            public void incrementGlobalSelectCount() {
079                globalSelectCount++;
080            }
081    
082            public void incrementSequenceNumber() {
083                sequenceNumber++;
084            }
085    
086            public void incrementSequenceClosedCount() {
087                sequenceClosedCount++;
088            }
089    
090            public void incrementSequenceWriteCount() {
091                sequenceWriteCount++;
092            }
093    
094            public void incrementNonFatalCount() {
095                nonFatalCount += 1;
096            }
097    
098            public int getGlobalReadCount() {
099                return globalReadCount;
100            }
101    
102            public void setGlobalReadCount(int globalReadCount) {
103                this.globalReadCount = globalReadCount;
104            }
105    
106            public int getGlobalSelectCount() {
107                return globalSelectCount;
108            }
109    
110            public void setGlobalSelectCount(int globalSelectCount) {
111                this.globalSelectCount = globalSelectCount;
112            }
113    
114            public int getSequenceClosedCount() {
115                return sequenceClosedCount;
116            }
117    
118            public int getNonFatalCount() {
119                return nonFatalCount;
120            }
121    
122            public void setSequenceClosedCount(int sequenceClosedCount) {
123                this.sequenceClosedCount = sequenceClosedCount;
124            }
125    
126            public int getSequenceNumber() {
127                return sequenceNumber;
128            }
129    
130            public void setSequenceNumber(int sequenceNumber) {
131                this.sequenceNumber = sequenceNumber;
132            }
133    
134            public int getSequenceWriteCount() {
135                return sequenceWriteCount;
136            }
137    
138            public void setSequenceWriteCount(int sequenceWriteCount) {
139                this.sequenceWriteCount = sequenceWriteCount;
140            }
141    
142            public void setNonFatalCount(int nonFatalCount) {
143                this.nonFatalCount = nonFatalCount;
144            }
145        }
146    
147        private Integer closingFiscalYear;
148        private Date transactionDate;
149        
150        private String balanceForwardsUnclosedFileName; 
151        private String balanceForwardsclosedFileName;
152        
153        private PriorYearAccountService priorYearAccountService;
154        private SubFundGroupService subFundGroupService;
155        private OriginEntryService originEntryService;
156        private ParameterService parameterService;
157        private SystemOptions currentYearOptions;
158        private LedgerSummaryReport openAccountForwardBalanceLedgerReport;
159        private LedgerSummaryReport closedAccountForwardBalanceLedgerReport;
160        private String[] priorYearAccountObjectTypes;
161        private String[] generalSwObjectTypes;
162        private String annualClosingDocType;
163        private String glOriginationCode;
164        private Map<String, Boolean> balanceTypeEncumbranceIndicators;
165    
166        private BalanceForwardProcessState state;
167    
168        /**
169         * Constructs a BalanceForwardRuleHelper
170         */
171        public BalanceForwardRuleHelper() {
172            super();
173            state = new BalanceForwardProcessState();
174            flexibleOffsetAccountService = SpringContext.getBean(FlexibleOffsetAccountService.class);
175            parameterService = SpringContext.getBean(ParameterService.class);
176            annualClosingDocType = parameterService.getParameterValue(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, KFSConstants.SystemGroupParameterNames.GL_ANNUAL_CLOSING_DOC_TYPE);
177            glOriginationCode = parameterService.getParameterValue(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, KFSConstants.SystemGroupParameterNames.GL_ORIGINATION_CODE);
178            openAccountForwardBalanceLedgerReport = new LedgerSummaryReport();
179            closedAccountForwardBalanceLedgerReport = new LedgerSummaryReport();
180        }
181    
182        /**
183         * Constructs a BalanceForwardRuleHelper, using a fiscal year. This also initializes object type arrays based on the options of
184         * the closing fiscal year
185         * 
186         * @param closingFiscalYear the fiscal year that is closing out
187         */
188        public BalanceForwardRuleHelper(Integer closingFiscalYear) {
189            this();
190            setClosingFiscalYear(closingFiscalYear);
191    
192            SystemOptions jobYearRunOptions = SpringContext.getBean(OptionsService.class).getOptions(closingFiscalYear);
193    
194            generalSwObjectTypes = new String[3];
195            generalSwObjectTypes[0] = jobYearRunOptions.getFinancialObjectTypeAssetsCd();
196            generalSwObjectTypes[1] = jobYearRunOptions.getFinObjectTypeLiabilitiesCode();
197            generalSwObjectTypes[2] = jobYearRunOptions.getFinObjectTypeFundBalanceCd();
198    
199            // "EE", "ES", "EX", "IC", "TE", "TI", "IN", "CH"
200            priorYearAccountObjectTypes = new String[8];
201            priorYearAccountObjectTypes[0] = jobYearRunOptions.getFinObjTypeExpendNotExpCode();
202            priorYearAccountObjectTypes[1] = jobYearRunOptions.getFinObjTypeExpNotExpendCode();
203            priorYearAccountObjectTypes[2] = jobYearRunOptions.getFinObjTypeExpenditureexpCd();
204            priorYearAccountObjectTypes[3] = jobYearRunOptions.getFinObjTypeIncomeNotCashCd();
205            priorYearAccountObjectTypes[4] = jobYearRunOptions.getFinancialObjectTypeTransferExpenseCd();
206            priorYearAccountObjectTypes[5] = jobYearRunOptions.getFinancialObjectTypeTransferIncomeCd();
207            priorYearAccountObjectTypes[6] = jobYearRunOptions.getFinObjectTypeIncomecashCode();
208            priorYearAccountObjectTypes[7] = jobYearRunOptions.getFinObjTypeCshNotIncomeCd();
209        }
210    
211        /**
212         * Constructs a BalanceForwardRuleHelper, but this one goes whole hog: initializes all of the relevant parameters and the
213         * balance types to process
214         * 
215         * @param closingFiscalYear the fiscal year to close
216         * @param transactionDate the date this job is being run
217         * @param closedPriorYearAccountGroup the group to put balance forwarding origin entries with closed accounts into
218         * @param unclosedPriorYearAccountGroup the group to put balance forwarding origin entries with open accounts into
219         */
220        public BalanceForwardRuleHelper(Integer closingFiscalYear, Date transactionDate, String balanceForwardsclosedFileName, String balanceForwardsUnclosedFileName) {
221            this(closingFiscalYear);
222            setTransactionDate(transactionDate);
223            setClosingFiscalYear(closingFiscalYear);
224            
225            setBalanceForwardsclosedFileName(balanceForwardsclosedFileName);
226            setBalanceForwardsUnclosedFileName(balanceForwardsUnclosedFileName);
227            currentYearOptions = SpringContext.getBean(OptionsService.class).getCurrentYearOptions();
228    
229            balanceTypeEncumbranceIndicators = new HashMap<String, Boolean>();
230            for (Object balanceTypAsObj : SpringContext.getBean(BalanceTypeService.class).getAllBalanceTypes()) {
231                BalanceType balanceType = (BalanceType) balanceTypAsObj;
232                balanceTypeEncumbranceIndicators.put(balanceType.getCode(), (balanceType.isFinBalanceTypeEncumIndicator() ? Boolean.TRUE : Boolean.FALSE));
233            }
234        }
235    
236    
237        /**
238         * The balance to create a general balance forward origin entry for
239         * 
240         * @param balance a balance to create an origin entry for
241         * @param closedPriorYearAccountGroup the group to put balance forwarding origin entries with closed accounts into
242         * @param unclosedPriorYearAccountGroup the group to put balance forwarding origin entries with open accounts into
243         * @throws FatalErrorException
244         */
245        public void processGeneralForwardBalance(Balance balance, PrintStream closedPs, PrintStream unclosedPs) {
246            if (ObjectUtils.isNull(balance.getPriorYearAccount())) {
247                LOG.info(("COULD NOT RETRIEVE INFORMATION ON ACCOUNT " + balance.getChartOfAccountsCode() + "-" + balance.getAccountNumber()));
248            } 
249            else {
250                if ((null == balance.getAccountNumber() && null == state.getAccountNumberHold()) || (null != balance.getAccountNumber() && balance.getAccountNumber().equals(state.getAccountNumberHold()))) {
251                    state.incrementSequenceNumber();
252                }
253                else {
254                    state.setSequenceNumber(1);
255                }
256                state.incrementGlobalSelectCount();
257                OriginEntryFull entry = generateGeneralForwardOriginEntry(balance);
258                saveForwardingEntry(balance, entry, closedPs, unclosedPs);
259            }
260        }
261    
262        /**
263         * This method creates an origin entry for a cumulative balance forward and saves it in its proper origin entry group
264         * 
265         * @param balance a balance which needs to have a cumulative origin entry generated for it
266         * @param closedPriorYearAccountGroup the origin entry group where forwarding origin entries with closed prior year accounts go
267         * @param unclosedPriorYearAcocuntGroup the origin entry group where forwarding origin entries with open prior year accounts go
268         */
269        public void processCumulativeForwardBalance(Balance balance, PrintStream closedPs, PrintStream unclosedPs) {
270            if ((null == balance.getAccountNumber() && null == state.getAccountNumberHold()) || (null != balance.getAccountNumber() && balance.getAccountNumber().equals(state.getAccountNumberHold()))) {
271                state.incrementSequenceNumber();
272            }
273            else {
274                state.setSequenceNumber(1);
275            }
276            state.incrementGlobalSelectCount();
277            OriginEntryFull activeEntry = generateCumulativeForwardOriginEntry(balance);
278            saveForwardingEntry(balance, activeEntry, closedPs, unclosedPs);
279        }
280    
281        /**
282         * This method generates an origin entry for a given cumulative balance forward balance
283         * 
284         * @param balance a balance to foward, cumulative style
285         * @return an OriginEntryFull to forward the given balance
286         */
287        public OriginEntryFull generateCumulativeForwardOriginEntry(Balance balance) {
288            OriginEntryFull activeEntry = new OriginEntryFull();
289            activeEntry.setUniversityFiscalYear(new Integer(closingFiscalYear.intValue() + 1));
290            activeEntry.setChartOfAccountsCode(balance.getChartOfAccountsCode());
291            activeEntry.setAccountNumber(balance.getAccountNumber());
292            activeEntry.setSubAccountNumber(balance.getSubAccountNumber());
293            activeEntry.setFinancialObjectCode(balance.getObjectCode());
294            activeEntry.setFinancialSubObjectCode(balance.getSubObjectCode());
295            activeEntry.setFinancialBalanceTypeCode(balance.getBalanceTypeCode());
296            activeEntry.setFinancialObjectTypeCode(balance.getObjectTypeCode());
297    
298            try {
299                flexibleOffsetAccountService.updateOffset(activeEntry);
300            }
301            catch (InvalidFlexibleOffsetException e) {
302                LOG.debug("processBalance() Balance Forward Flexible Offset Error: " + e.getMessage());
303            }
304            activeEntry.setUniversityFiscalPeriodCode(KFSConstants.PERIOD_CODE_CG_BEGINNING_BALANCE);
305            activeEntry.setFinancialDocumentTypeCode(this.annualClosingDocType);
306            activeEntry.setFinancialSystemOriginationCode(this.glOriginationCode);
307            activeEntry.setDocumentNumber(new StringBuffer(KFSConstants.BALANCE_TYPE_ACTUAL).append(balance.getAccountNumber()).toString());
308            activeEntry.setTransactionLedgerEntrySequenceNumber(new Integer(state.getSequenceNumber()));
309            activeEntry.setTransactionLedgerEntryDescription(new StringBuffer("BEG C & G BAL BROUGHT FORWARD FROM ").append(closingFiscalYear).toString());
310            activeEntry.setTransactionLedgerEntryAmount(balance.getAccountLineAnnualBalanceAmount().add(balance.getContractsGrantsBeginningBalanceAmount()));
311            if (KFSConstants.BALANCE_TYPE_CURRENT_BUDGET.equals(balance.getBalanceTypeCode()) 
312                    || KFSConstants.BALANCE_TYPE_BASE_BUDGET.equals(balance.getBalanceTypeCode())  ) {
313                activeEntry.setTransactionDebitCreditCode(null);
314            }
315            else {
316    
317                String wsFinancialObjectTypeDebitCreditCode = null;
318    
319                try {
320                    wsFinancialObjectTypeDebitCreditCode = getFinancialObjectTypeDebitCreditCode(balance);
321                }
322                catch (NonFatalErrorException nfee) {
323                    getState().incrementNonFatalCount();
324                    wsFinancialObjectTypeDebitCreditCode = KFSConstants.GL_CREDIT_CODE;
325                    LOG.info(nfee.getMessage());
326                }
327                if (activeEntry.getTransactionLedgerEntryAmount().isNegative()) {
328                    if (KFSConstants.GL_CREDIT_CODE.equals(wsFinancialObjectTypeDebitCreditCode)) {
329                        activeEntry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
330                    }
331                    else {
332                        activeEntry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
333                    }
334                }
335                else {
336                    activeEntry.setTransactionDebitCreditCode(wsFinancialObjectTypeDebitCreditCode);
337                }
338    
339            }
340            activeEntry.setTransactionDate(transactionDate);
341            activeEntry.setOrganizationDocumentNumber(null);
342            activeEntry.setProjectCode(KFSConstants.getDashProjectCode());
343            activeEntry.setOrganizationReferenceId(null);
344            activeEntry.setReferenceFinancialDocumentNumber(null);
345            activeEntry.setReferenceFinancialSystemOriginationCode(null);
346            activeEntry.setReferenceFinancialDocumentNumber(null);
347            activeEntry.setReversalDate(null);
348            String transactionEncumbranceUpdateCode = null;
349            try {
350                transactionEncumbranceUpdateCode = getTransactionEncumbranceUpdateCode(balance);
351            }
352            catch (NonFatalErrorException nfee) {
353                getState().incrementNonFatalCount();
354                LOG.info(nfee.getMessage());
355            }
356    
357            activeEntry.setTransactionEncumbranceUpdateCode(transactionEncumbranceUpdateCode);
358            if (KFSConstants.BALANCE_TYPE_AUDIT_TRAIL.equals(balance.getBalanceTypeCode())) {
359                activeEntry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
360            }
361            if (activeEntry.getTransactionLedgerEntryAmount().isNegative()) {
362                if (KFSConstants.BALANCE_TYPE_ACTUAL.equals(activeEntry.getFinancialBalanceTypeCode())) {
363                    activeEntry.setTransactionLedgerEntryAmount(activeEntry.getTransactionLedgerEntryAmount().negated());
364                }
365            }
366    
367            return activeEntry;
368        }
369    
370        /**
371         * Creates an origin entry that will forward this "general" balance
372         * 
373         * @param balance the balance to create a general origin entry for
374         * @return the generated origin entry
375         */
376        public OriginEntryFull generateGeneralForwardOriginEntry(Balance balance) {
377    
378            OriginEntryFull entry = new OriginEntryFull();
379            entry.setUniversityFiscalYear(new Integer(closingFiscalYear.intValue() + 1));
380            entry.setChartOfAccountsCode(balance.getChartOfAccountsCode());
381            entry.setAccountNumber(balance.getAccountNumber());
382            entry.setSubAccountNumber(balance.getSubAccountNumber());
383            entry.setFinancialObjectCode(balance.getObjectCode());
384            entry.setFinancialSubObjectCode(balance.getSubObjectCode());
385            entry.setFinancialBalanceTypeCode(balance.getBalanceTypeCode());
386            if (currentYearOptions.getFinObjTypeExpendNotExpCode().equals(balance.getObjectTypeCode())) {
387                entry.setFinancialObjectTypeCode(currentYearOptions.getFinancialObjectTypeAssetsCd());
388            }
389            else {
390                entry.setFinancialObjectTypeCode(balance.getObjectTypeCode());
391            }
392            entry.setUniversityFiscalPeriodCode(KFSConstants.PERIOD_CODE_BEGINNING_BALANCE);
393            entry.setFinancialDocumentTypeCode(this.annualClosingDocType);
394            entry.setFinancialSystemOriginationCode(this.glOriginationCode);
395    
396            // FIXME Once tests are running properly uncomment the code to include the
397            // chartOfAccountsCode in the document number. It will cause the tests to
398            // break given the current framework but is desired as an enhancement for Kuali.
399            entry.setDocumentNumber(new StringBuffer(KFSConstants.BALANCE_TYPE_ACTUAL).append(balance.getAccountNumber())/* .append(balance.getChartOfAccountsCode()) */.toString());
400            entry.setTransactionLedgerEntrySequenceNumber(new Integer(state.getSequenceNumber()));
401            entry.setTransactionLedgerEntryDescription(new StringBuffer("BEG BAL BROUGHT FORWARD FROM ").append(closingFiscalYear).toString());
402    
403            String transactionEncumbranceUpdateCode = null;
404            try {
405                transactionEncumbranceUpdateCode = getTransactionEncumbranceUpdateCode(balance);
406            }
407            catch (NonFatalErrorException nfee) {
408                getState().incrementNonFatalCount();
409                LOG.info(nfee.getMessage());
410            }
411            entry.setTransactionEncumbranceUpdateCode(transactionEncumbranceUpdateCode);
412            KualiDecimal transactionLedgerEntryAmount = KualiDecimal.ZERO;
413            transactionLedgerEntryAmount = transactionLedgerEntryAmount.add(balance.getAccountLineAnnualBalanceAmount()).add(balance.getBeginningBalanceLineAmount()).add(balance.getContractsGrantsBeginningBalanceAmount());
414    
415            String wsFinancialObjectTypeDebitCreditCode = null;
416            try {
417                wsFinancialObjectTypeDebitCreditCode = getFinancialObjectTypeDebitCreditCode(balance);
418            }
419            catch (NonFatalErrorException nfee) {
420                getState().incrementNonFatalCount();
421                wsFinancialObjectTypeDebitCreditCode = KFSConstants.GL_CREDIT_CODE;
422                LOG.info(nfee.getMessage());
423            }
424    
425            if (transactionLedgerEntryAmount.isNegative()) {
426                if (KFSConstants.GL_DEBIT_CODE.equals(wsFinancialObjectTypeDebitCreditCode)) {
427                    entry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
428                }
429                else {
430                    entry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
431                }
432            }
433            else {
434                entry.setTransactionDebitCreditCode(wsFinancialObjectTypeDebitCreditCode);
435            }
436            entry.setTransactionDate(transactionDate);
437            entry.setOrganizationDocumentNumber(null);
438            entry.setProjectCode(KFSConstants.getDashProjectCode());
439            entry.setOrganizationReferenceId(null);
440            entry.setReferenceFinancialDocumentTypeCode(null);
441            entry.setReferenceFinancialSystemOriginationCode(null);
442            entry.setReferenceFinancialDocumentNumber(null);
443            entry.setFinancialDocumentReversalDate(null);
444            if (KFSConstants.BALANCE_TYPE_AUDIT_TRAIL.equals(entry.getFinancialBalanceTypeCode())) {
445                entry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL);
446            }
447            if (transactionLedgerEntryAmount.isNegative()) {
448                if (KFSConstants.BALANCE_TYPE_ACTUAL.equals(entry.getFinancialBalanceTypeCode())) {
449                    transactionLedgerEntryAmount = transactionLedgerEntryAmount.negated();
450                }
451            }
452            entry.setTransactionLedgerEntryAmount(transactionLedgerEntryAmount);
453            return entry;
454        }
455    
456        /**
457         * Retrieves the transaction encumbrance update code, based on the balance type code of the balance. These codes are cached,
458         * based off a cache generated in the big constructor
459         * 
460         * @param balance the balance to find the encumbrance update code for
461         * @return the transaction update code
462         * @throws NonFatalErrorException if an encumbrance update code cannot be found for this balance
463         */
464        private String getTransactionEncumbranceUpdateCode(Balance balance) throws NonFatalErrorException {
465            String updateCode = null;
466            Boolean encumIndicator = this.balanceTypeEncumbranceIndicators.get(balance.getBalanceTypeCode());
467            if (encumIndicator == null) {
468                throw new NonFatalErrorException(new StringBuffer(" ERROR ").append(balance.getBalanceTypeCode()).append(" NOT ON TABLE ").toString());
469            }
470            else if (encumIndicator.booleanValue()) {
471                updateCode = KFSConstants.ENCUMB_UPDT_NO_ENCUMBRANCE_CD;
472            }
473    
474            return updateCode;
475        }
476    
477        /**
478         * This method attempts to determine the debit/credit code of a given balance based on the object type
479         * 
480         * @param balance the balance to determin the debit/credit code for
481         * @return the debit or credit code
482         */
483        private String getFinancialObjectTypeDebitCreditCode(Balance balance) throws NonFatalErrorException {
484            String balanceObjectTypeDebitCreditCode = null != balance.getObjectType() ? balance.getObjectType().getFinObjectTypeDebitcreditCd() : null;
485    
486            String wsFinancialObjectTypeDebitCreditCode = null;
487    
488            if (null != balanceObjectTypeDebitCreditCode) {
489                if (ObjectHelper.isOneOf(balanceObjectTypeDebitCreditCode, new String[] { KFSConstants.GL_CREDIT_CODE, KFSConstants.GL_DEBIT_CODE })) {
490                    wsFinancialObjectTypeDebitCreditCode = balanceObjectTypeDebitCreditCode;
491                }
492                else {
493                    wsFinancialObjectTypeDebitCreditCode = KFSConstants.GL_CREDIT_CODE;
494                }
495            }
496            else {
497                throw new NonFatalErrorException(new StringBuffer("FIN OBJ TYP CODE ").append(balance.getObjectTypeCode()).append(" NOT IN TABLE").toString());
498            }
499            return wsFinancialObjectTypeDebitCreditCode;
500        }
501    
502        /**
503         * Saves a generated origin entry to the database, within the proper group
504         * 
505         * @param balance the original balance, which still has the account to check if it is closed or not
506         * @param entry the origin entry to save
507         * @param closedPriorYearAccountGroup the group to put balance forwarding origin entries with closed accounts into
508         * @param unclosedPriorYearAccountGroup the group to put balance forwarding origin entries with open accounts into
509         */
510        private void saveForwardingEntry(Balance balance, OriginEntryFull entry, PrintStream closedPs, PrintStream unclosedPs) {
511            final PriorYearAccount account = priorYearAccountService.getByPrimaryKey(balance.getChartOfAccountsCode(), balance.getAccountNumber());
512            if (ObjectUtils.isNotNull(account) && !account.isClosed()) {
513                if (LOG.isDebugEnabled()) {
514                    LOG.debug("Prior Year Account "+account.getChartOfAccountsCode()+"-"+account.getAccountNumber()+" is not closed");
515                }
516                originEntryService.createEntry(entry, unclosedPs);
517                state.incrementSequenceWriteCount();
518                openAccountForwardBalanceLedgerReport.summarizeEntry(entry);
519    
520                if (0 == state.getSequenceWriteCount() % 1000) {
521                    LOG.info("  SEQUENTIAL RECORDS WRITTEN = " + state.getSequenceWriteCount());
522                }
523            }
524            else {
525                if (LOG.isDebugEnabled()) {
526                    if (ObjectUtils.isNull(account)) {
527                        LOG.debug("Prior Year Account for "+balance.getChartOfAccountsCode()+"-"+balance.getAccountNumber()+" cannot be found");
528                    } else {
529                        LOG.debug("Prior Year Account "+account.getChartOfAccountsCode()+"-"+account.getAccountNumber()+" is closed");
530                    }
531                }
532                originEntryService.createEntry(entry, closedPs);
533                state.incrementSequenceClosedCount();
534                closedAccountForwardBalanceLedgerReport.summarizeEntry(entry);
535                if (0 == state.getSequenceClosedCount() % 1000) {
536                    LOG.info("  CLOSED SEQUENTIAL RECORDS WRITTEN = " + state.getSequenceClosedCount());
537                }
538            }
539        }
540    
541        /**
542         * Writes the ledger report for general balance forward entries to the given reportWriterService
543         * @param reportWriteService the reportWriterService to write to
544         */
545        public void writeOpenAccountBalanceForwardLedgerSummaryReport(ReportWriterService reportWriterService) {
546            openAccountForwardBalanceLedgerReport.writeReport(reportWriterService);
547        }
548        
549        /**
550         * Writes the ledger report for cumulative balance forward entries to the given reportWriterService
551         * @param reportWriteService the reportWriterService to write to
552         */
553        public void writeClosedAccountBalanceForwardLedgerSummaryReport(ReportWriterService reportWriterService) {
554            closedAccountForwardBalanceLedgerReport.writeReport(reportWriterService);
555        }
556        
557        /**
558         * @param priorYearAccountService The priorYearAccountService to set.
559         */
560        public void setPriorYearAccountService(PriorYearAccountService priorYearAccountService) {
561            this.priorYearAccountService = priorYearAccountService;
562        }
563    
564        /**
565         * @param subFundGroupService The subFundGroupService to set.
566         */
567        public void setSubFundGroupService(SubFundGroupService subFundGroupService) {
568            this.subFundGroupService = subFundGroupService;
569        }
570    
571        /**
572         * @param originEntryService The originEntryService to set.
573         */
574        public void setOriginEntryService(OriginEntryService originEntryService) {
575            this.originEntryService = originEntryService;
576        }
577    
578        public Integer getClosingFiscalYear() {
579            return closingFiscalYear;
580        }
581    
582        public void setClosingFiscalYear(Integer fiscalYear) {
583            this.closingFiscalYear = fiscalYear;
584        }
585    
586        public Date getTransactionDate() {
587            return transactionDate;
588        }
589    
590        public void setTransactionDate(Date transactionDate) {
591            this.transactionDate = transactionDate;
592        }
593    
594        public String getBalanceForwardsUnclosedFileName() {
595            return balanceForwardsUnclosedFileName;
596        }
597    
598        public void setBalanceForwardsUnclosedFileName(String balanceForwardsUnclosedFileName) {
599            this.balanceForwardsUnclosedFileName = balanceForwardsUnclosedFileName;
600        }
601    
602        public String getBalanceForwardsclosedFileName() {
603            return balanceForwardsclosedFileName;
604        }
605    
606        public void setBalanceForwardsclosedFileName(String balanceForwardsclosedFileName) {
607            this.balanceForwardsclosedFileName = balanceForwardsclosedFileName;
608        }
609    
610        public BalanceForwardProcessState getState() {
611            return state;
612        }
613    
614        /**
615         * Gets the glOriginationCode attribute. 
616         * @return Returns the glOriginationCode.
617         */
618        public String getGlOriginationCode() {
619            return glOriginationCode;
620        }
621    
622        /**
623         * Gets the annualClosingDocType attribute. 
624         * @return Returns the annualClosingDocType.
625         */
626        public String getAnnualClosingDocType() {
627            return annualClosingDocType;
628        }
629    }