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.sql.Date;
019    import java.util.List;
020    import java.util.Map;
021    
022    import org.apache.log4j.Logger;
023    import org.kuali.kfs.coa.service.ObjectTypeService;
024    import org.kuali.kfs.gl.GeneralLedgerConstants;
025    import org.kuali.kfs.gl.ObjectHelper;
026    import org.kuali.kfs.gl.batch.service.impl.exception.FatalErrorException;
027    import org.kuali.kfs.gl.businessobject.Balance;
028    import org.kuali.kfs.gl.businessobject.OriginEntryFull;
029    import org.kuali.kfs.sys.KFSConstants;
030    import org.kuali.kfs.sys.KFSKeyConstants;
031    import org.kuali.kfs.sys.context.SpringContext;
032    import org.kuali.kfs.sys.service.FlexibleOffsetAccountService;
033    import org.kuali.kfs.sys.service.impl.KfsParameterConstants;
034    import org.kuali.rice.kns.service.KualiConfigurationService;
035    import org.kuali.rice.kns.service.ParameterService;
036    
037    /**
038     * This class helps generate the entries for the nominal activity closing year end job.
039     */
040    public class NominalActivityClosingHelper {
041        private Integer fiscalYear;
042        private Date transactionDate;
043        private String varNetExpenseObjectCode;
044        private String varNetRevenueObjectCode;
045        private String varFundBalanceObjectCode;
046        private String varFundBalanceObjectTypeCode;
047        private String[] expenseObjectCodeTypes;
048        private ParameterService parameterService;
049        private KualiConfigurationService configurationService;
050        private FlexibleOffsetAccountService flexibleOffsetService;
051        private Logger LOG = Logger.getLogger(NominalActivityClosingHelper.class);
052        private int nonFatalErrorCount;
053        
054        /**
055         * Constructs a NominalActivityClosingHelper
056         * @param fiscalYear the fiscal year this job is being run for
057         * @param transactionDate the transaction date that origin entries should hit the ledger
058         * @param parameterService an implementation of the ParameterService
059         * @param configurationService an implementation of the KualiConfigurationService
060         */
061        public NominalActivityClosingHelper(Integer fiscalYear, Date transactionDate, ParameterService parameterService, KualiConfigurationService configurationService) {
062            this.fiscalYear = fiscalYear;
063            this.transactionDate = transactionDate;
064            this.parameterService = parameterService;
065            this.configurationService = configurationService;
066            this.flexibleOffsetService = SpringContext.getBean(FlexibleOffsetAccountService.class);
067            this.nonFatalErrorCount = 0;
068            
069            ObjectTypeService objectTypeService = (ObjectTypeService) SpringContext.getBean(ObjectTypeService.class);
070            List<String> objectTypes = objectTypeService.getExpenseObjectTypes(fiscalYear);
071            expenseObjectCodeTypes = objectTypes.toArray(new String[0]);
072            
073            // 682 003690 DISPLAY "NET_EXP_OBJECT_CD" UPON ENVIRONMENT-NAME.
074            // 683 003700 ACCEPT VAR-NET-EXP-OBJECT-CD FROM ENVIRONMENT-VALUE.
075    
076            varNetExpenseObjectCode = parameterService.getParameterValue(NominalActivityClosingStep.class, "NET_EXPENSE_OBJECT_CODE");
077            varNetRevenueObjectCode = parameterService.getParameterValue(NominalActivityClosingStep.class, "NET_REVENUE_OBJECT_CODE");
078            varFundBalanceObjectCode = parameterService.getParameterValue(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, GeneralLedgerConstants.ANNUAL_CLOSING_FUND_BALANCE_OBJECT_CODE_PARM);
079            varFundBalanceObjectTypeCode = parameterService.getParameterValue(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, GeneralLedgerConstants.ANNUAL_CLOSING_FUND_BALANCE_OBJECT_TYPE_PARM);
080    
081        }
082        
083        /**
084         * Generates an origin entry that will summarize close out of nominal items (income and expense)
085         * @param balance the balance this activity closing entry needs to be created for
086         * @param sequenceNumber the sequence number of the origin entry
087         * @return an origin entry which will close out nominal activity on a balance
088         * @throws FatalErrorException thrown if the given balance lacks an object type code
089         */
090        public OriginEntryFull generateActivityEntry(Balance balance, Integer sequenceNumber) throws FatalErrorException {
091            // 847 005300 4100-WRITE-ACTIVITY.
092    
093            OriginEntryFull activityEntry = new OriginEntryFull();
094    
095            // 848 005310 MOVE SPACES TO GLEN-RECORD.
096            // 849 005320 MOVE VAR-UNIV-FISCAL-YR
097            // 850 005330 TO UNIV-FISCAL-YR OF GLEN-RECORD.
098    
099            activityEntry.setUniversityFiscalYear(fiscalYear);
100    
101            // 851 005340 MOVE GLGLBL-FIN-COA-CD
102            // 852 005350 TO FIN-COA-CD OF GLEN-RECORD.
103    
104            activityEntry.setChartOfAccountsCode(balance.getChartOfAccountsCode());
105    
106            // 853 005360 MOVE GLGLBL-ACCOUNT-NBR
107            // 854 005370 TO ACCOUNT-NBR OF GLEN-RECORD.
108    
109            activityEntry.setAccountNumber(balance.getAccountNumber());
110    
111            // 855 005380 MOVE GLGLBL-SUB-ACCT-NBR
112            // 856 005390 TO SUB-ACCT-NBR OF GLEN-RECORD.
113    
114            activityEntry.setSubAccountNumber(balance.getSubAccountNumber());
115    
116            // 857 005400* FOR OBJECT TYPES = 'ES' OR 'EX' OR 'EE' USE THE NEXT EXPENSE
117            // 858 005410* OBJECT FROM THE INPUT VAR. ELSE USE THE NET REVENUE OBJECT
118            // 859 005420* FROM THE INPUT VAR.
119    
120            // 860 005430 IF GLGLBL-FIN-OBJ-TYP-CD = 'ES' OR 'EX' OR 'EE'
121            // 861 005440 OR 'TE'
122    
123            if (ObjectHelper.isOneOf(balance.getObjectTypeCode(), expenseObjectCodeTypes)) {
124    
125                // 862 005450 MOVE VAR-NET-EXP-OBJECT-CD
126                // 863 005460 TO FIN-OBJECT-CD OF GLEN-RECORD
127    
128                activityEntry.setFinancialObjectCode(varNetExpenseObjectCode);
129    
130                // 864 005470 ELSE
131    
132            }
133            else {
134    
135                // 865 005480 MOVE VAR-NET-REV-OBJECT-CD
136                // 866 005490 TO FIN-OBJECT-CD OF GLEN-RECORD.
137    
138                activityEntry.setFinancialObjectCode(varNetRevenueObjectCode);
139    
140            }
141    
142            activityEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
143            activityEntry.setFinancialBalanceTypeCode(balance.getOption().getNominalFinancialBalanceTypeCd());
144    
145            if (null == balance.getObjectTypeCode()) {
146                throw new FatalErrorException(" BALANCE SELECTED FOR PROCESSING IS MISSING ITS OBJECT TYPE CODE ");
147    
148            }
149    
150            activityEntry.setFinancialObjectTypeCode(balance.getObjectTypeCode());
151    
152            // 913 005940 MOVE '13'
153            // 914 005950 TO UNIV-FISCAL-PRD-CD OF GLEN-RECORD.
154    
155            activityEntry.setUniversityFiscalPeriodCode(KFSConstants.MONTH13);
156    
157            // 915 005960 MOVE 'ACLO'
158            // 916 005970 TO FDOC-TYP-CD OF GLEN-RECORD.
159    
160            activityEntry.setFinancialDocumentTypeCode(parameterService.getParameterValue(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, KFSConstants.SystemGroupParameterNames.GL_ANNUAL_CLOSING_DOC_TYPE));
161    
162            // 917 005980 MOVE 'MF'
163            // 918 005990 TO FS-ORIGIN-CD OF GLEN-RECORD.
164    
165            activityEntry.setFinancialSystemOriginationCode(parameterService.getParameterValue(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, KFSConstants.SystemGroupParameterNames.GL_ORIGINATION_CODE));
166    
167            // 919 006000 STRING 'AC'
168            // 920 006010 GLGLBL-ACCOUNT-NBR
169            // 921 006020 RP-BLANK-LINE
170            // 922 006030 DELIMITED BY SIZE
171            // 923 006040 INTO FDOC-NBR OF GLEN-RECORD.
172            activityEntry.setDocumentNumber(new StringBuffer(balance.getOption().getActualFinancialBalanceTypeCd()).append(balance.getAccountNumber()).toString());
173    
174            // 924 006050 MOVE WS-SEQ-NBR
175            // 925 006060 TO TRN-ENTR-SEQ-NBR OF GLEN-RECORD.
176    
177            activityEntry.setTransactionLedgerEntrySequenceNumber(sequenceNumber);
178    
179            // 926 006070 IF GLGLBL-FIN-OBJ-TYP-CD = 'EX' OR 'ES' OR 'EE'
180            // 927 006080 OR 'TE'
181    
182            if (ObjectHelper.isOneOf(balance.getObjectTypeCode(), expenseObjectCodeTypes)) {
183    
184                // 928 006090 STRING 'CLS ENT TO NE FOR '
185                // 929 006100 GLGLBL-SUB-ACCT-NBR
186                // 930 006110 '-'
187                // 931 006120 GLGLBL-FIN-OBJECT-CD
188                // 932 006130 '-'
189                // 933 006140 GLGLBL-FIN-SUB-OBJ-CD
190                // 934 006150 '-'
191                // 935 006160 GLGLBL-FIN-OBJ-TYP-CD
192                // 936 006170 RP-BLANK-LINE
193                // 937 006180 DELIMITED BY SIZE INTO
194                // 938 006190 TRN-LDGR-ENTR-DESC OF GLEN-RECORD
195    
196                activityEntry.setTransactionLedgerEntryDescription(this.createTransactionLedgerEntryDescription(configurationService.getPropertyString(KFSKeyConstants.MSG_CLOSE_ENTRY_TO_NOMINAL_EXPENSE), balance));
197    
198                // 939 006200 ELSE
199    
200            }
201            else {
202    
203                // 940 006210 STRING 'CLS ENT TO NR FOR '
204                // 941 006220 GLGLBL-SUB-ACCT-NBR
205                // 942 006230 '-'
206                // 943 006240 GLGLBL-FIN-OBJECT-CD
207                // 944 006250 '-'
208                // 945 006260 GLGLBL-FIN-SUB-OBJ-CD
209                // 946 006270 '-'
210                // 947 006280 GLGLBL-FIN-OBJ-TYP-CD
211                // 948 006290 RP-BLANK-LINE
212                // 949 006300 DELIMITED BY SIZE INTO
213                // 950 006310 TRN-LDGR-ENTR-DESC OF GLEN-RECORD.
214    
215                activityEntry.setTransactionLedgerEntryDescription(this.createTransactionLedgerEntryDescription(configurationService.getPropertyString(KFSKeyConstants.MSG_CLOSE_ENTRY_TO_NOMINAL_REVENUE), balance));
216    
217            }
218    
219            // 951 006320 MOVE GLGLBL-ACLN-ANNL-BAL-AMT
220            // 952 006330 TO TRN-LDGR-ENTR-AMT OF GLEN-RECORD.
221    
222            activityEntry.setTransactionLedgerEntryAmount(balance.getAccountLineAnnualBalanceAmount());
223    
224            // 953 006340 MOVE GLGLBL-FIN-OBJ-TYP-CD
225            // 954 006350 TO CAOTYP-FIN-OBJ-TYP-CD.
226    
227            activityEntry.setFinancialObjectTypeCode(balance.getObjectTypeCode());
228    
229            // 955 006360 EXEC SQL
230            // 956 006370 SELECT FIN_OBJTYP_DBCR_CD
231            // 957 006380 INTO :CAOTYP-FIN-OBJTYP-DBCR-CD :CAOTYP-FODC-I
232            // 958 006390 FROM CA_OBJ_TYPE_T
233            // 959 006400 WHERE FIN_OBJ_TYP_CD = RTRIM(:CAOTYP-FIN-OBJ-TYP-CD)
234            // 960 006410 END-EXEC.
235            // 961 IF RETURN-CODE NOT = ZERO
236            // 962 DISPLAY ' RETURN CODE 6410 ' RETURN-CODE.
237            // 963
238            // 964 006420 IF CAOTYP-FODC-I < ZERO
239            // 965 006430 MOVE SPACE TO CAOTYP-FIN-OBJTYP-DBCR-CD
240            // 966 006440 END-IF
241            // 967 006450 EVALUATE SQLCODE
242            // 968 006460 WHEN 0
243    
244            String debitCreditCode = null;
245    
246            if (null != balance.getObjectType()) {
247    
248                // 969 006470 IF CAOTYP-FIN-OBJTYP-DBCR-CD = 'C' OR 'D'
249    
250                if (ObjectHelper.isOneOf(balance.getObjectType().getFinObjectTypeDebitcreditCd(), new String[] { KFSConstants.GL_CREDIT_CODE, KFSConstants.GL_DEBIT_CODE })) {
251    
252                    // 970 006480 MOVE CAOTYP-FIN-OBJTYP-DBCR-CD
253                    // 971 006490 TO WS-FIN-OBJTYP-DBCR-CD
254    
255                    debitCreditCode = balance.getObjectType().getFinObjectTypeDebitcreditCd();
256    
257                    // 972 006500 ELSE
258    
259                }
260                else {
261    
262                    // 973 006510 MOVE 'C' TO WS-FIN-OBJTYP-DBCR-CD
263    
264                    debitCreditCode = KFSConstants.GL_CREDIT_CODE;
265    
266                    // 974 006520 END-IF
267    
268                }
269    
270                // 975 006530 IF TRN-LDGR-ENTR-AMT OF GLEN-RECORD < ZERO
271    
272                // NOTE (laran) The amount on the origin entry is set to this value above.
273                // NOTE (laran) I'm using the balance value here because to me it was easier than remembering the
274                // indirection.
275                if (balance.getAccountLineAnnualBalanceAmount().isNegative()) {
276    
277                    // 976 006540 IF CAOTYP-FIN-OBJTYP-DBCR-CD = 'C' OR 'D'
278    
279                    if (ObjectHelper.isOneOf(balance.getObjectType().getFinObjectTypeDebitcreditCd(), new String[] { KFSConstants.GL_CREDIT_CODE, KFSConstants.GL_DEBIT_CODE })) {
280    
281                        // 977 006550 MOVE CAOTYP-FIN-OBJTYP-DBCR-CD
282                        // 978 006560 TO TRN-DEBIT-CRDT-CD OF GLEN-RECORD
283    
284                        activityEntry.setTransactionDebitCreditCode(balance.getObjectType().getFinObjectTypeDebitcreditCd());
285    
286                        // 979 006570 ELSE
287    
288                    }
289                    else {
290    
291                        // 980 006580 MOVE 'C' TO TRN-DEBIT-CRDT-CD OF GLEN-RECORD
292    
293                        activityEntry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
294    
295                        // 981 006590 MOVE LIT-KEY TO RP-ERROR-LABEL OF RP-ERROR-LINE-1
296    
297                        // TODO figure out what this bit re: the LIT-KEY means.
298    
299                        // 982 006600 MOVE CAOBJT-FIN-OBJ-TYP-CD TO
300                        // 983 006610 RP-ERROR-MSG OF RP-ERROR-LINE-1
301                        // 984 006620 MOVE RP-ERROR-LINE-1 TO PRINT-DATA
302                        // 985 006630 WRITE PRINT-DATA
303    
304                        // TODO figure out how to handle this little flourish of error handling code here.
305    
306                    }
307    
308                    // 986 006640 PERFORM CK-PRINT-STATUS THRU CK-PRINT-STATUS-EXIT
309                    // 987 006650 MOVE 'Y' TO WS-NON-FATAL-ERROR-FLAG
310                    // 988 006660 ADD +1 TO NON-FATAL-COUNT
311                    // 989 006670 ELSE
312    
313                }
314                else {
315    
316                    // 990 006680 IF CAOTYP-FIN-OBJTYP-DBCR-CD = 'C'
317    
318                    if (KFSConstants.GL_CREDIT_CODE.equals(balance.getObjectType().getFinObjectTypeDebitcreditCd())) {
319    
320                        // 991 006690 MOVE 'D' TO TRN-DEBIT-CRDT-CD OF GLEN-RECORD
321    
322                        activityEntry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
323    
324                        // 992 006700 ELSE
325    
326                    }
327                    else {
328    
329                        // 993 006710 IF CAOTYP-FIN-OBJTYP-DBCR-CD = 'D'
330    
331                        if (KFSConstants.GL_DEBIT_CODE.equals(balance.getObjectType().getFinObjectTypeDebitcreditCd())) {
332    
333                            // 994 006720 MOVE 'C' TO TRN-DEBIT-CRDT-CD OF GLEN-RECORD
334    
335                            activityEntry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
336    
337                            // 995 006730 ELSE
338    
339                        }
340                        else {
341    
342                            // 996 006740 MOVE 'D' TO TRN-DEBIT-CRDT-CD OF GLEN-RECORD
343    
344                            activityEntry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
345    
346                            // 997 006750 MOVE LIT-KEY TO RP-ERROR-LABEL OF RP-ERROR-LINE-1
347    
348                            // TODO figure out what this bit re: the LIT-KEY means.
349    
350                            // 998 006760 MOVE CAOBJT-FIN-OBJ-TYP-CD TO
351                            // 999 006770 RP-ERROR-MSG OF RP-ERROR-LINE-1
352                            // 1000 006780 MOVE RP-ERROR-LINE-1 TO PRINT-DATA
353                            // 1001 006790 WRITE PRINT-DATA
354    
355                            // TODO figure out how to handle this little flourish of error handling code here.
356    
357                        }
358    
359                        // 1002 006800 PERFORM CK-PRINT-STATUS THRU CK-PRINT-STATUS-EXIT
360                        // 1003 006810 MOVE 'Y' TO WS-NON-FATAL-ERROR-FLAG
361                        // 1004 006820 ADD +1 TO NON-FATAL-COUNT
362    
363                        // TODO figure out how to handle this CK-PRINT-STATUS/non-fatal error business
364    
365                        // 1005 006830 END-IF
366    
367                    }
368    
369                    // 1006 006840 END-IF
370    
371                }
372    
373                // 1007 006850 END-IF
374    
375                // 1008 006860 WHEN +100
376                // 1009 006870 WHEN +1403
377    
378            }
379            else {
380    
381                // 1010 006880 MOVE 'C' TO WS-FIN-OBJTYP-DBCR-CD
382    
383                // 1011 006890 IF TRN-LDGR-ENTR-AMT OF GLEN-RECORD < ZERO
384    
385                if (balance.getAccountLineAnnualBalanceAmount().isNegative()) {
386    
387                    // 1012 006900 MOVE 'C' TO TRN-DEBIT-CRDT-CD OF GLEN-RECORD
388    
389                    activityEntry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
390    
391                    // 1013 006910 ELSE
392    
393                }
394                else {
395    
396                    // 1014 006920 MOVE 'D' TO TRN-DEBIT-CRDT-CD OF GLEN-RECORD
397    
398                    activityEntry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
399    
400                    // 1015 006930 END-IF
401    
402                }
403    
404                nonFatalErrorCount += 1;
405    
406                // 1018 006960 MOVE 'FIN OBJ TYP CODE ' TO PRINT-DATA
407                // 1019 006970 MOVE CAOTYP-FIN-OBJ-TYP-CD TO PRINT-DATA (19:2)
408                // 1020 006980 MOVE ' NOT IN TABLE' TO PRINT-DATA (22:13)
409                // 1021 006990 WRITE PRINT-DATA
410    
411                LOG.info(new StringBuffer("FIN OBJ TYP CODE ").append(balance.getObjectTypeCode()).append(" NOT IN TABLE").toString());
412    
413                // 1022 007000 PERFORM CK-PRINT-STATUS THRU CK-PRINT-STATUS-EXIT
414    
415                // TODO work out this non-fatal-error handling bit here
416    
417                // 1023 007010 WHEN OTHER
418                // 1024 007020 DISPLAY ' ERROR ACCESSING OBJECT TYPE TABLE FOR '
419                // 1025 007030 CAOTYP-FIN-OBJ-TYP-CD
420                // 1026 007040 MOVE 'Y' TO WS-FATAL-ERROR-FLAG
421                // 1027 007050 GO TO 4100-WRITE-ACTIVITY-EXIT
422                // 1028 007060 END-EVALUATE.
423    
424            }
425    
426            // 1029 007070 MOVE VAR-TRANSACTION-DT
427            // 1030 007080 TO TRANSACTION-DT OF GLEN-RECORD.
428    
429            activityEntry.setTransactionDate(transactionDate);
430    
431            // 1031 007090 MOVE SPACES
432            // 1032 007100 TO ORG-DOC-NBR OF GLEN-RECORD.
433    
434            activityEntry.setOrganizationDocumentNumber(null);
435    
436            // 1033 007110 MOVE ALL '-'
437            // 1034 007120 TO PROJECT-CD OF GLEN-RECORD.
438    
439            activityEntry.setProjectCode(KFSConstants.getDashProjectCode());
440    
441            // 1035 007130 MOVE SPACES
442            // 1036 007140 TO ORG-REFERENCE-ID OF GLEN-RECORD.
443    
444            activityEntry.setOrganizationReferenceId(null);
445    
446            // 1037 007150 MOVE SPACES
447            // 1038 007160 TO FDOC-REF-TYP-CD OF GLEN-RECORD.
448    
449            activityEntry.setReferenceFinancialDocumentTypeCode(null);
450    
451            // 1039 007170 MOVE SPACES
452            // 1040 007180 TO FS-REF-ORIGIN-CD OF GLEN-RECORD.
453    
454            activityEntry.setReferenceFinancialSystemOriginationCode(null);
455    
456            // 1041 007190 MOVE SPACES
457            // 1042 007200 TO FDOC-REF-NBR OF GLEN-RECORD.
458    
459            activityEntry.setReferenceFinancialDocumentNumber(null);
460    
461            // 1043 007210 MOVE SPACES
462            // 1044 007220 TO FDOC-REVERSAL-DT OF GLEN-RECORD.
463    
464            activityEntry.setReversalDate(null);
465    
466            // 1045 007230 MOVE SPACES
467            // 1046 007240 TO TRN-ENCUM-UPDT-CD OF GLEN-RECORD.
468    
469            activityEntry.setTransactionEncumbranceUpdateCode(null);
470    
471            // 1047 007250 IF TRN-LDGR-ENTR-AMT OF GLEN-RECORD < 0
472    
473            if (balance.getAccountLineAnnualBalanceAmount().isNegative()) {
474    
475                // 1048 007260 COMPUTE
476                // 1049 007270 TRN-LDGR-ENTR-AMT OF GLEN-RECORD =
477                // 1050 007280 TRN-LDGR-ENTR-AMT OF GLEN-RECORD * -1.
478    
479                activityEntry.setTransactionLedgerEntryAmount(balance.getAccountLineAnnualBalanceAmount().negated());
480    
481            }
482    
483            return activityEntry;
484    
485        }
486        
487        /**
488         * Genereates an origin entry to update a fund balance as a result of closing income and expense
489         * @param balance the balance this offset needs to be created for
490         * @param sequenceNumber the sequence number of the origin entry full
491         * @return an origin entry which will offset the nominal closing activity
492         * @throws FatalErrorException thrown if the given balance lacks an object type code
493         */
494        public OriginEntryFull generateOffset(Balance balance, Integer sequenceNumber) throws FatalErrorException {
495            String debitCreditCode = null;
496            
497            // 969 006470 IF CAOTYP-FIN-OBJTYP-DBCR-CD = 'C' OR 'D'
498            
499            if (null == balance.getObjectTypeCode()) {
500                throw new FatalErrorException(" BALANCE SELECTED FOR PROCESSING IS MISSING ITS OBJECT TYPE CODE ");
501    
502            }
503    
504            if (ObjectHelper.isOneOf(balance.getObjectType().getFinObjectTypeDebitcreditCd(), new String[] { KFSConstants.GL_CREDIT_CODE, KFSConstants.GL_DEBIT_CODE })) {
505    
506                // 970 006480 MOVE CAOTYP-FIN-OBJTYP-DBCR-CD
507                // 971 006490 TO WS-FIN-OBJTYP-DBCR-CD
508    
509                debitCreditCode = balance.getObjectType().getFinObjectTypeDebitcreditCd();
510    
511                // 972 006500 ELSE
512    
513            }
514            else {
515    
516                // 973 006510 MOVE 'C' TO WS-FIN-OBJTYP-DBCR-CD
517    
518                debitCreditCode = KFSConstants.GL_CREDIT_CODE;
519    
520                // 974 006520 END-IF
521    
522            }
523            
524            // 1068 007430 4200-WRITE-OFFSET.
525            // 1069 007440 MOVE SPACES TO GLEN-RECORD.
526    
527            OriginEntryFull offsetEntry = new OriginEntryFull();
528    
529            // 1070 007450 MOVE VAR-UNIV-FISCAL-YR
530            // 1071 007460 TO UNIV-FISCAL-YR OF GLEN-RECORD.
531    
532            offsetEntry.setUniversityFiscalYear(fiscalYear);
533    
534            // 1072 007470 MOVE GLGLBL-FIN-COA-CD
535            // 1073 007480 TO FIN-COA-CD OF GLEN-RECORD.
536    
537            offsetEntry.setChartOfAccountsCode(balance.getChartOfAccountsCode());
538    
539            // 1074 007490 MOVE GLGLBL-ACCOUNT-NBR
540            // 1075 007500 TO ACCOUNT-NBR OF GLEN-RECORD.
541    
542            offsetEntry.setAccountNumber(balance.getAccountNumber());
543    
544            // 1076 007510 MOVE GLGLBL-SUB-ACCT-NBR
545            // 1077 007520 TO SUB-ACCT-NBR OF GLEN-RECORD.
546    
547            offsetEntry.setSubAccountNumber(balance.getSubAccountNumber());
548    
549            // 1078 007530 MOVE VAR-FUND-BAL-OBJECT-CD
550            // 1079 007540 TO FIN-OBJECT-CD OF GLEN-RECORD.
551    
552            offsetEntry.setFinancialObjectCode(varFundBalanceObjectCode);
553    
554            // 1080 007550 MOVE ALL '-'
555            // 1081 007560 TO FIN-SUB-OBJ-CD OF GLEN-RECORD.
556    
557            offsetEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
558    
559            // 1082 007570 MOVE 'NB'
560            // 1083 007580 TO FIN-BALANCE-TYP-CD OF GLEN-RECORD.
561    
562            offsetEntry.setFinancialBalanceTypeCode(balance.getOption().getNominalFinancialBalanceTypeCd());
563    
564            // 1084 007590 MOVE VAR-FUND-BAL-OBJ-TYP-CD
565            // 1085 007600 TO FIN-OBJ-TYP-CD OF GLEN-RECORD.
566    
567            offsetEntry.setFinancialObjectTypeCode(varFundBalanceObjectTypeCode);
568    
569            // 1086 007610 MOVE '13'
570            // 1087 007620 TO UNIV-FISCAL-PRD-CD OF GLEN-RECORD.
571    
572            offsetEntry.setUniversityFiscalPeriodCode(KFSConstants.MONTH13);
573    
574            // 1088 007630 MOVE 'ACLO'
575            // 1089 007640 TO FDOC-TYP-CD OF GLEN-RECORD.
576    
577            offsetEntry.setFinancialDocumentTypeCode(parameterService.getParameterValue(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, KFSConstants.SystemGroupParameterNames.GL_ANNUAL_CLOSING_DOC_TYPE));
578    
579            // 1090 007650 MOVE 'MF'
580            // 1091 007660 TO FS-ORIGIN-CD OF GLEN-RECORD.
581    
582            offsetEntry.setFinancialSystemOriginationCode(parameterService.getParameterValue(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, KFSConstants.SystemGroupParameterNames.GL_ORIGINATION_CODE));
583    
584            // 1092 007670 STRING 'AC'
585            // 1093 007680 GLGLBL-ACCOUNT-NBR
586            // 1094 007690 RP-BLANK-LINE
587            // 1095 007700 DELIMITED BY SIZE
588            // 1096 007710 INTO FDOC-NBR OF GLEN-RECORD.
589    
590            offsetEntry.setDocumentNumber(new StringBuffer(balance.getOption().getActualFinancialBalanceTypeCd()).append(balance.getAccountNumber()).toString());
591    
592            // 1097 007720 MOVE WS-SEQ-NBR
593            // 1098 007730 TO TRN-ENTR-SEQ-NBR OF GLEN-RECORD.
594    
595            offsetEntry.setTransactionLedgerEntrySequenceNumber(new Integer(sequenceNumber.intValue()));
596    
597            // 1099 007740 STRING 'CLS ENT TO FB FOR '
598            // 1100 007750 GLGLBL-SUB-ACCT-NBR
599            // 1101 007760 '-'
600            // 1102 007770 GLGLBL-FIN-OBJECT-CD
601            // 1103 007780 '-'
602            // 1104 007790 GLGLBL-FIN-SUB-OBJ-CD
603            // 1105 007800 '-'
604            // 1106 007810 GLGLBL-FIN-OBJ-TYP-CD
605            // 1107 007820 RP-BLANK-LINE
606            // 1108 007830 DELIMITED BY SIZE INTO
607            // 1109 007840 TRN-LDGR-ENTR-DESC OF GLEN-RECORD.
608    
609            offsetEntry.setTransactionLedgerEntryDescription(this.createTransactionLedgerEntryDescription(configurationService.getPropertyString(KFSKeyConstants.MSG_CLOSE_ENTRY_TO_FUND_BALANCE), balance));
610    
611            // 1110 007850 MOVE GLGLBL-ACLN-ANNL-BAL-AMT
612            // 1111 007860 TO TRN-LDGR-ENTR-AMT OF GLEN-RECORD.
613    
614            offsetEntry.setTransactionLedgerEntryAmount(balance.getAccountLineAnnualBalanceAmount());
615    
616            // 1112 007870 MOVE WS-FIN-OBJTYP-DBCR-CD
617            // 1113 007880 TO TRN-DEBIT-CRDT-CD OF GLEN-RECORD.
618    
619            offsetEntry.setTransactionDebitCreditCode(debitCreditCode);
620    
621            // 1114 007890 MOVE VAR-TRANSACTION-DT
622            // 1115 007900 TO TRANSACTION-DT OF GLEN-RECORD.
623    
624            offsetEntry.setTransactionDate(transactionDate);
625    
626            // 1116 007910 MOVE SPACES
627            // 1117 007920 TO ORG-DOC-NBR OF GLEN-RECORD.
628    
629            offsetEntry.setOrganizationDocumentNumber(null);
630    
631            // 1118 007930 MOVE ALL '-'
632            // 1119 007940 TO PROJECT-CD OF GLEN-RECORD.
633    
634            offsetEntry.setProjectCode(KFSConstants.getDashProjectCode());
635    
636            // 1120 007950 MOVE SPACES
637            // 1121 007960 TO ORG-REFERENCE-ID OF GLEN-RECORD.
638    
639            offsetEntry.setOrganizationReferenceId(null);
640    
641            // 1122 007970 MOVE SPACES
642            // 1123 007980 TO FDOC-REF-TYP-CD OF GLEN-RECORD.
643    
644            offsetEntry.setReferenceFinancialDocumentTypeCode(null);
645    
646            // 1124 007990 MOVE SPACES
647            // 1125 008000 TO FS-REF-ORIGIN-CD OF GLEN-RECORD.
648    
649            offsetEntry.setReferenceFinancialSystemOriginationCode(null);
650    
651            // 1126 008010 MOVE SPACES
652            // 1127 008020 TO FDOC-REF-NBR OF GLEN-RECORD.
653    
654            offsetEntry.setReferenceFinancialDocumentNumber(null);
655    
656            // 1128 008030 MOVE SPACES
657            // 1129 008040 TO FDOC-REVERSAL-DT OF GLEN-RECORD.
658    
659            offsetEntry.setFinancialDocumentReversalDate(null);
660    
661            // 1130 008050 MOVE SPACES
662            // 1131 008060 TO TRN-ENCUM-UPDT-CD OF GLEN-RECORD.
663    
664            offsetEntry.setTransactionEncumbranceUpdateCode(null);
665    
666            // 1132 008070 IF TRN-LDGR-ENTR-AMT OF GLEN-RECORD < 0
667    
668            if (balance.getAccountLineAnnualBalanceAmount().isNegative()) {
669    
670                // 1133 008080 IF TRN-DEBIT-CRDT-CD OF GLEN-RECORD = 'C'
671    
672                if (KFSConstants.GL_CREDIT_CODE.equals(debitCreditCode)) {
673    
674                    // 1134 008090 MOVE 'D' TO TRN-DEBIT-CRDT-CD OF GLEN-RECORD
675    
676                    offsetEntry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
677    
678                    // 1135 008100 ELSE
679    
680                }
681                else {
682    
683                    // 1136 008110 MOVE 'C' TO TRN-DEBIT-CRDT-CD OF GLEN-RECORD.
684    
685                    offsetEntry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
686    
687                }
688    
689            }
690    
691            // 1137 008120 IF TRN-LDGR-ENTR-AMT OF GLEN-RECORD < 0
692    
693            if (balance.getAccountLineAnnualBalanceAmount().isNegative()) {
694    
695                // 1138 008130 COMPUTE
696                // 1139 008140 TRN-LDGR-ENTR-AMT OF GLEN-RECORD =
697                // 1140 008150 TRN-LDGR-ENTR-AMT OF GLEN-RECORD * -1.
698    
699                offsetEntry.setTransactionLedgerEntryAmount(balance.getAccountLineAnnualBalanceAmount().negated());
700    
701            }
702            
703            flexibleOffsetService.updateOffset(offsetEntry);
704            
705            return offsetEntry;
706        }
707        
708        /**
709         * Adds the job parameters used to generate the origin entries to the given map
710         * @param nominalClosingJobParameters a map of batch job parameters to add nominal activity closing parameters to
711         */
712        public void addNominalClosingJobParameters(Map nominalClosingJobParameters) {
713            nominalClosingJobParameters.put(GeneralLedgerConstants.ColumnNames.UNIVERSITY_FISCAL_YEAR, fiscalYear);
714            nominalClosingJobParameters.put(GeneralLedgerConstants.ColumnNames.NET_EXP_OBJECT_CD, varNetExpenseObjectCode);
715            nominalClosingJobParameters.put(GeneralLedgerConstants.ColumnNames.NET_REV_OBJECT_CD, varNetRevenueObjectCode);
716            nominalClosingJobParameters.put(GeneralLedgerConstants.ColumnNames.FUND_BAL_OBJECT_CD, varFundBalanceObjectCode);
717            nominalClosingJobParameters.put(GeneralLedgerConstants.ColumnNames.FUND_BAL_OBJ_TYP_CD, varFundBalanceObjectTypeCode);
718        }
719        
720        /**
721         * Generates the transaction ledger entry description for a given balance
722         * 
723         * @param descriptorIntro the introduction to the description
724         * @param balance the balance the transaction description will refer to
725         * @return the generated transaction ledger entry description
726         */
727        private String createTransactionLedgerEntryDescription(String descriptorIntro, Balance balance) {
728            StringBuilder description = new StringBuilder();
729            description.append(descriptorIntro.trim()).append(' ');
730            return description.append(getSizedField(5, balance.getSubAccountNumber())).append("-").append(getSizedField(4, balance.getObjectCode())).append("-").append(getSizedField(3, balance.getSubObjectCode())).append("-").append(getSizedField(2, balance.getObjectTypeCode())).toString();
731        }
732    
733        /**
734         * Pads out a string so that it will be a certain length
735         * 
736         * @param size the size to pad to
737         * @param value the String being padded
738         * @return the padded String
739         */
740        private StringBuilder getSizedField(int size, String value) {
741            StringBuilder fieldString = new StringBuilder();
742            if (value != null) {
743                fieldString.append(value);
744                while (fieldString.length() < size) {
745                    fieldString.append(' ');
746                }
747            }
748            else {
749                while (fieldString.length() < size) {
750                    fieldString.append('-');
751                }
752            }
753            return fieldString;
754        }
755        
756        /**
757         * Returns the count of non-fatal errors encountered during the process by this helper
758         * @return the count of non-fatal errors
759         */
760        public Integer getNonFatalErrorCount() {
761            return new Integer(this.nonFatalErrorCount);
762        }
763    }