1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.kuali.ole.gl.batch.service.impl;
18
19 import java.io.BufferedReader;
20 import java.io.File;
21 import java.io.FileNotFoundException;
22 import java.io.FileReader;
23 import java.io.IOException;
24 import java.io.PrintStream;
25 import java.math.BigDecimal;
26 import java.sql.Date;
27 import java.text.DecimalFormat;
28 import java.text.MessageFormat;
29 import java.text.SimpleDateFormat;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36
37 import org.apache.commons.lang.StringUtils;
38 import org.kuali.ole.coa.businessobject.A21IndirectCostRecoveryAccount;
39 import org.kuali.ole.coa.businessobject.A21SubAccount;
40 import org.kuali.ole.coa.businessobject.Account;
41 import org.kuali.ole.coa.businessobject.AccountingPeriod;
42 import org.kuali.ole.coa.businessobject.IndirectCostRecoveryAccount;
43 import org.kuali.ole.coa.businessobject.IndirectCostRecoveryRate;
44 import org.kuali.ole.coa.businessobject.IndirectCostRecoveryRateDetail;
45 import org.kuali.ole.coa.businessobject.ObjectCode;
46 import org.kuali.ole.coa.businessobject.OffsetDefinition;
47 import org.kuali.ole.coa.businessobject.SubAccount;
48 import org.kuali.ole.coa.dataaccess.IndirectCostRecoveryRateDetailDao;
49 import org.kuali.ole.coa.service.AccountingPeriodService;
50 import org.kuali.ole.coa.service.ObjectCodeService;
51 import org.kuali.ole.coa.service.OffsetDefinitionService;
52 import org.kuali.ole.coa.service.SubAccountService;
53 import org.kuali.ole.gl.GeneralLedgerConstants;
54 import org.kuali.ole.gl.batch.PosterIndirectCostRecoveryEntriesStep;
55 import org.kuali.ole.gl.batch.service.AccountingCycleCachingService;
56 import org.kuali.ole.gl.batch.service.PostTransaction;
57 import org.kuali.ole.gl.batch.service.PosterService;
58 import org.kuali.ole.gl.batch.service.RunDateService;
59 import org.kuali.ole.gl.batch.service.VerifyTransaction;
60 import org.kuali.ole.gl.businessobject.ExpenditureTransaction;
61 import org.kuali.ole.gl.businessobject.OriginEntryFull;
62 import org.kuali.ole.gl.businessobject.OriginEntryInformation;
63 import org.kuali.ole.gl.businessobject.Reversal;
64 import org.kuali.ole.gl.businessobject.Transaction;
65 import org.kuali.ole.gl.dataaccess.ExpenditureTransactionDao;
66 import org.kuali.ole.gl.dataaccess.ReversalDao;
67 import org.kuali.ole.gl.report.LedgerSummaryReport;
68 import org.kuali.ole.gl.report.TransactionListingReport;
69 import org.kuali.ole.gl.service.OriginEntryGroupService;
70 import org.kuali.ole.gl.service.OriginEntryService;
71 import org.kuali.ole.sys.OLEConstants;
72 import org.kuali.ole.sys.OLEKeyConstants;
73 import org.kuali.ole.sys.OLEPropertyConstants;
74 import org.kuali.ole.sys.Message;
75 import org.kuali.ole.sys.businessobject.SystemOptions;
76 import org.kuali.ole.sys.businessobject.UniversityDate;
77 import org.kuali.ole.sys.context.SpringContext;
78 import org.kuali.ole.sys.dataaccess.UniversityDateDao;
79 import org.kuali.ole.sys.exception.InvalidFlexibleOffsetException;
80 import org.kuali.ole.sys.service.FlexibleOffsetAccountService;
81 import org.kuali.ole.sys.service.ReportWriterService;
82 import org.kuali.ole.sys.service.impl.OleParameterConstants;
83 import org.kuali.rice.core.api.config.property.ConfigurationService;
84 import org.kuali.rice.core.api.datetime.DateTimeService;
85 import org.kuali.rice.core.api.util.type.KualiDecimal;
86 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
87 import org.kuali.rice.kns.service.DataDictionaryService;
88 import org.kuali.rice.krad.service.BusinessObjectService;
89 import org.kuali.rice.krad.service.PersistenceService;
90 import org.kuali.rice.krad.service.PersistenceStructureService;
91 import org.kuali.rice.krad.util.ObjectUtils;
92 import org.springframework.transaction.annotation.Transactional;
93
94
95
96
97 @Transactional
98 public class PosterServiceImpl implements PosterService {
99 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PosterServiceImpl.class);
100
101 public static final KualiDecimal WARNING_MAX_DIFFERENCE = new KualiDecimal("0.03");
102 public static final String DATE_FORMAT_STRING = "yyyyMMdd";
103
104 private List transactionPosters;
105 private VerifyTransaction verifyTransaction;
106 private OriginEntryService originEntryService;
107 private OriginEntryGroupService originEntryGroupService;
108 private DateTimeService dateTimeService;
109 private ReversalDao reversalDao;
110 private UniversityDateDao universityDateDao;
111 private AccountingPeriodService accountingPeriodService;
112 private ExpenditureTransactionDao expenditureTransactionDao;
113 private IndirectCostRecoveryRateDetailDao indirectCostRecoveryRateDetailDao;
114 private ObjectCodeService objectCodeService;
115 private ParameterService parameterService;
116 private ConfigurationService configurationService;
117 private FlexibleOffsetAccountService flexibleOffsetAccountService;
118 private RunDateService runDateService;
119 private SubAccountService subAccountService;
120 private OffsetDefinitionService offsetDefinitionService;
121 private DataDictionaryService dataDictionaryService;
122 private BusinessObjectService businessObjectService;
123 private PersistenceStructureService persistenceStructureService;
124 private ReportWriterService reportWriterService;
125 private ReportWriterService errorListingReportWriterService;
126 private ReportWriterService reversalReportWriterService;
127 private ReportWriterService ledgerSummaryReportWriterService;
128
129
130
131
132 private String batchFileDirectoryName;
133
134
135 private AccountingCycleCachingService accountingCycleCachingService;
136
137
138
139
140 public void postMainEntries() {
141 LOG.debug("postMainEntries() started");
142 Date runDate = dateTimeService.getCurrentSqlDate();
143 try{
144 FileReader INPUT_GLE_FILE = new FileReader(batchFileDirectoryName + File.separator + GeneralLedgerConstants.BatchFileSystem.POSTER_INPUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION);
145 File OUTPUT_ERR_FILE = new File(batchFileDirectoryName + File.separator + GeneralLedgerConstants.BatchFileSystem.POSTER_ERROR_OUTPUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION);
146
147 postEntries(PosterService.MODE_ENTRIES, INPUT_GLE_FILE, null, OUTPUT_ERR_FILE);
148
149 INPUT_GLE_FILE.close();
150 } catch (FileNotFoundException e1) {
151 e1.printStackTrace();
152 throw new RuntimeException("PosterMainEntries Stopped: " + e1.getMessage(), e1);
153 } catch (IOException ioe) {
154 LOG.error("postMainEntries stopped due to: " + ioe.getMessage(), ioe);
155 throw new RuntimeException(ioe);
156 }
157 }
158
159
160
161
162 public void postReversalEntries() {
163 LOG.debug("postReversalEntries() started");
164 Date runDate = dateTimeService.getCurrentSqlDate();
165 try{
166 PrintStream OUTPUT_GLE_FILE_ps = new PrintStream(batchFileDirectoryName + File.separator + GeneralLedgerConstants.BatchFileSystem.REVERSAL_POSTER_VALID_OUTPUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION);
167 File OUTPUT_ERR_FILE = new File(batchFileDirectoryName + File.separator + GeneralLedgerConstants.BatchFileSystem.REVERSAL_POSTER_ERROR_OUTPUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION);
168
169 postEntries(PosterService.MODE_REVERSAL, null, OUTPUT_GLE_FILE_ps, OUTPUT_ERR_FILE);
170
171 OUTPUT_GLE_FILE_ps.close();
172 } catch (FileNotFoundException e1) {
173 e1.printStackTrace();
174 throw new RuntimeException("PosterReversalEntries Stopped: " + e1.getMessage(), e1);
175 }
176 }
177
178
179
180
181 public void postIcrEntries() {
182 LOG.debug("postIcrEntries() started");
183 Date runDate = dateTimeService.getCurrentSqlDate();
184 try{
185 FileReader INPUT_GLE_FILE = new FileReader(batchFileDirectoryName + File.separator + GeneralLedgerConstants.BatchFileSystem.ICR_POSTER_INPUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION);
186 File OUTPUT_ERR_FILE = new File(batchFileDirectoryName + File.separator + GeneralLedgerConstants.BatchFileSystem.ICR_POSTER_ERROR_OUTPUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION);
187
188 postEntries(PosterService.MODE_ICR, INPUT_GLE_FILE, null, OUTPUT_ERR_FILE);
189
190 INPUT_GLE_FILE.close();
191 } catch (FileNotFoundException e1) {
192 e1.printStackTrace();
193 throw new RuntimeException("PosterIcrEntries Stopped: " + e1.getMessage(), e1);
194 } catch (IOException ioe) {
195 LOG.error("postIcrEntries stopped due to: " + ioe.getMessage(), ioe);
196 throw new RuntimeException(ioe);
197 }
198 }
199
200
201
202
203
204
205 protected void postEntries(int mode, FileReader INPUT_GLE_FILE, PrintStream OUTPUT_GLE_FILE_ps, File OUTPUT_ERR_FILE) throws FileNotFoundException {
206 if (LOG.isDebugEnabled()) {
207 LOG.debug("postEntries() started");
208 }
209
210 PrintStream OUTPUT_ERR_FILE_ps = new PrintStream(OUTPUT_ERR_FILE);
211 BufferedReader INPUT_GLE_FILE_br = null;
212 if (INPUT_GLE_FILE != null) {
213 INPUT_GLE_FILE_br = new BufferedReader(INPUT_GLE_FILE);
214 }
215
216 String GLEN_RECORD;
217 Date executionDate = new Date(dateTimeService.getCurrentDate().getTime());
218 Date runDate = new Date(runDateService.calculateRunDate(executionDate).getTime());
219 UniversityDate runUniversityDate = (UniversityDate)SpringContext.getBean(BusinessObjectService.class).findBySinglePrimaryKey(UniversityDate.class, runDate);
220 LedgerSummaryReport ledgerSummaryReport = new LedgerSummaryReport();
221
222
223
224 Map reportSummary = new HashMap();
225 for (Iterator posterIter = transactionPosters.iterator(); posterIter.hasNext();) {
226 PostTransaction poster = (PostTransaction) posterIter.next();
227 reportSummary.put(poster.getDestinationName() + "," + GeneralLedgerConstants.DELETE_CODE, new Integer(0));
228 reportSummary.put(poster.getDestinationName() + "," + GeneralLedgerConstants.INSERT_CODE, new Integer(0));
229 reportSummary.put(poster.getDestinationName() + "," + GeneralLedgerConstants.UPDATE_CODE, new Integer(0));
230 }
231 int ecount = 0;
232
233 OriginEntryFull tran = null;
234 Transaction reversalTransaction = null;
235 try {
236 if ((mode == PosterService.MODE_ENTRIES) || (mode == PosterService.MODE_ICR)) {
237 LOG.debug("postEntries() Processing groups");
238 while ((GLEN_RECORD = INPUT_GLE_FILE_br.readLine()) != null) {
239 if (!org.apache.commons.lang.StringUtils.isEmpty(GLEN_RECORD) && !org.apache.commons.lang.StringUtils.isBlank(GLEN_RECORD.trim())) {
240 ecount++;
241
242 GLEN_RECORD = org.apache.commons.lang.StringUtils.rightPad(GLEN_RECORD, 183, ' ');
243 tran = new OriginEntryFull();
244
245
246 List<Message> parsingError = new ArrayList();
247 parsingError = tran.setFromTextFileForBatch(GLEN_RECORD, ecount);
248 if (parsingError.size() > 0) {
249 String messages = "";
250 for(Message msg : parsingError) {messages += msg + " ";}
251 throw new RuntimeException("Exception happened from parsing process: " + messages);
252 }
253
254 addReporting(reportSummary, "SEQUENTIAL", GeneralLedgerConstants.SELECT_CODE);
255 postTransaction(tran, mode, reportSummary, ledgerSummaryReport, OUTPUT_ERR_FILE_ps, runUniversityDate, GLEN_RECORD, OUTPUT_GLE_FILE_ps);
256
257 if (ecount % 1000 == 0) {
258 LOG.info("postEntries() Posted Entry " + ecount);
259 }
260 }
261 }
262 if (INPUT_GLE_FILE_br != null) {
263 INPUT_GLE_FILE_br.close();
264 }
265 OUTPUT_ERR_FILE_ps.close();
266 reportWriterService.writeStatisticLine("SEQUENTIAL RECORDS READ %,9d", reportSummary.get("SEQUENTIAL,S"));
267 }
268 else {
269 if (LOG.isDebugEnabled()) {
270 LOG.debug("postEntries() Processing reversal transactions");
271 }
272
273 final String GL_REVERSAL_T = getPersistenceStructureService().getTableName(Reversal.class);
274 Iterator reversalTransactions = reversalDao.getByDate(runDate);
275 TransactionListingReport reversalListingReport = new TransactionListingReport();
276 while (reversalTransactions.hasNext()) {
277 ecount++;
278 reversalTransaction = (Transaction) reversalTransactions.next();
279 addReporting(reportSummary, GL_REVERSAL_T, GeneralLedgerConstants.SELECT_CODE);
280
281 boolean posted = postTransaction(reversalTransaction, mode, reportSummary, ledgerSummaryReport, OUTPUT_ERR_FILE_ps, runUniversityDate, GL_REVERSAL_T, OUTPUT_GLE_FILE_ps);
282
283 if (posted) {
284 reversalListingReport.generateReport(reversalReportWriterService, reversalTransaction);
285 }
286
287 if (ecount % 1000 == 0) {
288 LOG.info("postEntries() Posted Entry " + ecount);
289 }
290 }
291
292 OUTPUT_ERR_FILE_ps.close();
293
294 reportWriterService.writeStatisticLine("GLRV RECORDS READ (GL_REVERSAL_T) %,9d", reportSummary.get("GL_REVERSAL_T,S"));
295 reversalListingReport.generateStatistics(reversalReportWriterService);
296 }
297
298
299 reportWriterService.writeStatisticLine("GLEN RECORDS INSERTED (GL_ENTRY_T) %,9d", reportSummary.get("GL_ENTRY_T,I"));
300 reportWriterService.writeStatisticLine("GLBL RECORDS INSERTED (GL_BALANCE_T) %,9d", reportSummary.get("GL_BALANCE_T,I"));
301 reportWriterService.writeStatisticLine("GLBL RECORDS UPDATED (GL_BALANCE_T) %,9d", reportSummary.get("GL_BALANCE_T,U"));
302 reportWriterService.writeStatisticLine("GLEX RECORDS INSERTED (GL_EXPEND_TRN_MT) %,9d", reportSummary.get("GL_EXPEND_TRN_MT,I"));
303 reportWriterService.writeStatisticLine("GLEX RECORDS UPDATED (GL_EXPEND_TRN_MT) %,9d", reportSummary.get("GL_EXPEND_TRN_MT,U"));
304 reportWriterService.writeStatisticLine("GLEC RECORDS INSERTED (GL_ENCUMBRANCE_T) %,9d", reportSummary.get("GL_ENCUMBRANCE_T,I"));
305 reportWriterService.writeStatisticLine("GLEC RECORDS UPDATED (GL_ENCUMBRANCE_T) %,9d", reportSummary.get("GL_ENCUMBRANCE_T,U"));
306 reportWriterService.writeStatisticLine("GLRV RECORDS INSERTED (GL_REVERSAL_T) %,9d", reportSummary.get("GL_REVERSAL_T,I"));
307 reportWriterService.writeStatisticLine("GLRV RECORDS DELETED (GL_REVERSAL_T) %,9d", reportSummary.get("GL_REVERSAL_T,D"));
308 reportWriterService.writeStatisticLine("SFBL RECORDS INSERTED (GL_SF_BALANCES_T) %,9d", reportSummary.get("GL_SF_BALANCES_T,I"));
309 reportWriterService.writeStatisticLine("SFBL RECORDS UPDATED (GL_SF_BALANCES_T) %,9d", reportSummary.get("GL_SF_BALANCES_T,U"));
310 reportWriterService.writeStatisticLine("ACBL RECORDS INSERTED (GL_ACCT_BALANCES_T) %,9d", reportSummary.get("GL_ACCT_BALANCES_T,I"));
311 reportWriterService.writeStatisticLine("ACBL RECORDS UPDATED (GL_ACCT_BALANCES_T) %,9d", reportSummary.get("GL_ACCT_BALANCES_T,U"));
312 reportWriterService.writeStatisticLine("ERROR RECORDS WRITTEN %,9d", reportSummary.get("WARNING,I"));
313 }
314 catch (RuntimeException re) {
315 LOG.error("postEntries stopped due to: " + re.getMessage() + " on line number : " + ecount, re);
316 LOG.error("tran failure occured on: " + tran == null ? null : tran.toString());
317 LOG.error("reversalTransaction failure occured on: " + reversalTransaction == null ? null : reversalTransaction.toString());
318 throw new RuntimeException("PosterService Stopped: " + re.getMessage(), re);
319 }
320 catch (IOException e) {
321 LOG.error("postEntries stopped due to: " + e.getMessage(), e);
322 throw new RuntimeException(e);
323 }
324 catch (Exception e) {
325
326 }
327
328 LOG.info("postEntries() done, total count = " + ecount);
329
330 ledgerSummaryReport.writeReport(ledgerSummaryReportWriterService);
331 new TransactionListingReport().generateReport(errorListingReportWriterService, new OriginEntryFileIterator(OUTPUT_ERR_FILE));
332 }
333
334
335
336
337
338
339
340
341
342
343
344
345
346 protected boolean postTransaction(Transaction tran, int mode, Map<String,Integer> reportSummary, LedgerSummaryReport ledgerSummaryReport, PrintStream invalidGroup, UniversityDate runUniversityDate, String line, PrintStream OUTPUT_GLE_FILE_ps) {
347
348 List<Message> errors = new ArrayList();
349 Transaction originalTransaction = tran;
350
351 try {
352 final String GL_ORIGIN_ENTRY_T = getPersistenceStructureService().getTableName(OriginEntryFull.class);
353
354
355 if ((mode == PosterService.MODE_ENTRIES) || (mode == PosterService.MODE_ICR)) {
356 addReporting(reportSummary, GL_ORIGIN_ENTRY_T, GeneralLedgerConstants.SELECT_CODE);
357 }
358
359
360 if (mode == PosterService.MODE_REVERSAL) {
361 Reversal reversal = new Reversal(tran);
362
363 if (OLEConstants.GL_DEBIT_CODE.equals(reversal.getTransactionDebitCreditCode())) {
364 reversal.setTransactionDebitCreditCode(OLEConstants.GL_CREDIT_CODE);
365 }
366 else if (OLEConstants.GL_CREDIT_CODE.equals(reversal.getTransactionDebitCreditCode())) {
367 reversal.setTransactionDebitCreditCode(OLEConstants.GL_DEBIT_CODE);
368 }
369 UniversityDate udate = (UniversityDate)SpringContext.getBean(BusinessObjectService.class).findBySinglePrimaryKey(UniversityDate.class, reversal.getFinancialDocumentReversalDate());
370
371 if (udate != null) {
372 reversal.setUniversityFiscalYear(udate.getUniversityFiscalYear());
373 reversal.setUniversityFiscalPeriodCode(udate.getUniversityFiscalAccountingPeriod());
374 AccountingPeriod ap = accountingPeriodService.getByPeriod(reversal.getUniversityFiscalPeriodCode(), reversal.getUniversityFiscalYear());
375 if (ap != null) {
376 if (!ap.isActive()) {
377 reversal.setUniversityFiscalYear(runUniversityDate.getUniversityFiscalYear());
378 reversal.setUniversityFiscalPeriodCode(runUniversityDate.getUniversityFiscalAccountingPeriod());
379 }
380 reversal.setFinancialDocumentReversalDate(null);
381 String newDescription = OLEConstants.GL_REVERSAL_DESCRIPTION_PREFIX + reversal.getTransactionLedgerEntryDescription();
382 if (newDescription.length() > 40) {
383 newDescription = newDescription.substring(0, 40);
384 }
385 reversal.setTransactionLedgerEntryDescription(newDescription);
386 }
387 else {
388 errors.add(new Message(configurationService.getPropertyValueAsString(OLEKeyConstants.ERROR_UNIV_DATE_NOT_IN_ACCOUNTING_PERIOD_TABLE), Message.TYPE_WARNING));
389 }
390 }
391 else {
392 errors.add(new Message (configurationService.getPropertyValueAsString(OLEKeyConstants.ERROR_REVERSAL_DATE_NOT_IN_UNIV_DATE_TABLE) , Message.TYPE_WARNING));
393 }
394
395 int maxSequenceId = accountingCycleCachingService.getMaxSequenceNumber(reversal);
396 reversal.setTransactionLedgerEntrySequenceNumber(new Integer(maxSequenceId + 1));
397
398 PersistenceService ps = SpringContext.getBean(PersistenceService.class);
399 ps.retrieveNonKeyFields(reversal);
400 tran = reversal;
401 }
402 else {
403 tran.setChart(accountingCycleCachingService.getChart(tran.getChartOfAccountsCode()));
404 tran.setAccount(accountingCycleCachingService.getAccount(tran.getChartOfAccountsCode(), tran.getAccountNumber()));
405 tran.setObjectType(accountingCycleCachingService.getObjectType(tran.getFinancialObjectTypeCode()));
406 tran.setBalanceType(accountingCycleCachingService.getBalanceType(tran.getFinancialBalanceTypeCode()));
407 tran.setOption(accountingCycleCachingService.getSystemOptions(tran.getUniversityFiscalYear()));
408
409 ObjectCode objectCode = accountingCycleCachingService.getObjectCode(tran.getUniversityFiscalYear(), tran.getChartOfAccountsCode(), tran.getFinancialObjectCode());
410 if (ObjectUtils.isNull(objectCode)) {
411 LOG.warn(configurationService.getPropertyValueAsString(OLEKeyConstants.ERROR_OBJECT_CODE_NOT_FOUND_FOR) + tran.getUniversityFiscalYear() + "," + tran.getChartOfAccountsCode() + "," + tran.getFinancialObjectCode());
412 errors.add(new Message(configurationService.getPropertyValueAsString(OLEKeyConstants.ERROR_OBJECT_CODE_NOT_FOUND_FOR) + tran.getUniversityFiscalYear() + "," + tran.getChartOfAccountsCode() + "," + tran.getFinancialObjectCode(), Message.TYPE_WARNING));
413 }
414 else {
415 tran.setFinancialObject(accountingCycleCachingService.getObjectCode(tran.getUniversityFiscalYear(), tran.getChartOfAccountsCode(), tran.getFinancialObjectCode()));
416 }
417
418
419 int maxSequenceId = accountingCycleCachingService.getMaxSequenceNumber(tran);
420 ((OriginEntryFull) tran).setTransactionLedgerEntrySequenceNumber(new Integer(maxSequenceId + 1));
421 }
422
423
424 AccountingPeriod originEntryAccountingPeriod = accountingCycleCachingService.getAccountingPeriod(tran.getUniversityFiscalYear(), tran.getUniversityFiscalPeriodCode());
425 if (originEntryAccountingPeriod == null) {
426 errors.add(new Message(configurationService.getPropertyValueAsString(OLEKeyConstants.ERROR_ACCOUNTING_PERIOD_NOT_FOUND) + " for " + tran.getUniversityFiscalYear() + "/" + tran.getUniversityFiscalPeriodCode(), Message.TYPE_FATAL));
427 }
428
429 if (errors.size() == 0) {
430 try {
431 errors = verifyTransaction.verifyTransaction(tran);
432 }
433 catch (Exception e) {
434 errors.add(new Message(e.toString() + " occurred for this record.", Message.TYPE_FATAL));
435 }
436 }
437
438 if (errors.size() > 0) {
439
440 reportWriterService.writeError(tran, errors);
441 addReporting(reportSummary, "WARNING", GeneralLedgerConstants.INSERT_CODE);
442 try {
443 writeErrorEntry(line, invalidGroup);
444 }
445 catch (IOException ioe) {
446 LOG.error("PosterServiceImpl Stopped: " + ioe.getMessage(), ioe);
447 throw new RuntimeException("PosterServiceImpl Stopped: " + ioe.getMessage(), ioe);
448 }
449 }
450 else {
451
452 for (Iterator posterIter = transactionPosters.iterator(); posterIter.hasNext();) {
453 PostTransaction poster = (PostTransaction) posterIter.next();
454 String actionCode = poster.post(tran, mode, runUniversityDate.getUniversityDate(), reportWriterService);
455
456 if (actionCode.startsWith(GeneralLedgerConstants.ERROR_CODE)) {
457 errors = new ArrayList<Message>();
458 errors.add(new Message(actionCode, Message.TYPE_WARNING));
459 reportWriterService.writeError(tran, errors);
460 }
461 else if (actionCode.indexOf(GeneralLedgerConstants.INSERT_CODE) >= 0) {
462 addReporting(reportSummary, poster.getDestinationName(), GeneralLedgerConstants.INSERT_CODE);
463 }
464 else if (actionCode.indexOf(GeneralLedgerConstants.UPDATE_CODE) >= 0) {
465 addReporting(reportSummary, poster.getDestinationName(), GeneralLedgerConstants.UPDATE_CODE);
466 }
467 else if (actionCode.indexOf(GeneralLedgerConstants.DELETE_CODE) >= 0) {
468 addReporting(reportSummary, poster.getDestinationName(), GeneralLedgerConstants.DELETE_CODE);
469 }
470 else if (actionCode.indexOf(GeneralLedgerConstants.SELECT_CODE) >= 0) {
471 addReporting(reportSummary, poster.getDestinationName(), GeneralLedgerConstants.SELECT_CODE);
472 }
473 }
474 if (errors.size() == 0) {
475
476 if (mode == PosterService.MODE_REVERSAL) {
477 createOutputEntry(tran, OUTPUT_GLE_FILE_ps);
478 reversalDao.delete((Reversal) originalTransaction);
479 addReporting(reportSummary, getPersistenceStructureService().getTableName(Reversal.class), GeneralLedgerConstants.DELETE_CODE);
480 }
481
482 ledgerSummaryReport.summarizeEntry(new OriginEntryFull(tran));
483 return true;
484 }
485 }
486
487 return false;
488 }
489 catch (IOException ioe) {
490 LOG.error("PosterServiceImpl Stopped: " + ioe.getMessage(), ioe);
491 throw new RuntimeException("PosterServiceImpl Stopped: " + ioe.getMessage(), ioe);
492
493 }
494 catch (RuntimeException re) {
495 LOG.error("PosterServiceImpl Stopped: " + re.getMessage(), re);
496 throw new RuntimeException("PosterServiceImpl Stopped: " + re.getMessage(), re);
497 }
498 }
499
500
501
502
503 public void generateIcrTransactions() {
504 LOG.debug("generateIcrTransactions() started");
505
506 Date executionDate = dateTimeService.getCurrentSqlDate();
507 Date runDate = new Date(runDateService.calculateRunDate(executionDate).getTime());
508
509 try {
510 PrintStream OUTPUT_GLE_FILE_ps = new PrintStream(batchFileDirectoryName + File.separator + GeneralLedgerConstants.BatchFileSystem.ICR_TRANSACTIONS_OUTPUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION);
511
512 int reportExpendTranRetrieved = 0;
513 int reportExpendTranDeleted = 0;
514 int reportExpendTranKept = 0;
515 int reportOriginEntryGenerated = 0;
516 Iterator expenditureTransactions;
517
518 try {
519 expenditureTransactions = expenditureTransactionDao.getAllExpenditureTransactions();
520 }
521 catch (RuntimeException re) {
522 LOG.error("generateIcrTransactions Stopped: " + re.getMessage());
523 throw new RuntimeException("generateIcrTransactions Stopped: " + re.getMessage(), re);
524 }
525
526 while (expenditureTransactions.hasNext()) {
527 ExpenditureTransaction et = new ExpenditureTransaction();
528 try {
529 et = (ExpenditureTransaction) expenditureTransactions.next();
530 reportExpendTranRetrieved++;
531
532 KualiDecimal transactionAmount = et.getAccountObjectDirectCostAmount();
533 KualiDecimal distributionAmount = KualiDecimal.ZERO;
534
535 if (shouldIgnoreExpenditureTransaction(et)) {
536
537 expenditureTransactionDao.delete(et);
538 reportExpendTranDeleted++;
539 continue;
540 }
541
542 IndirectCostRecoveryGenerationMetadata icrGenerationMetadata = retrieveSubAccountIndirectCostRecoveryMetadata(et);
543 if (icrGenerationMetadata == null) {
544
545 icrGenerationMetadata = retrieveAccountIndirectCostRecoveryMetadata(et);
546 }
547
548 Collection<IndirectCostRecoveryRateDetail> automatedEntries = indirectCostRecoveryRateDetailDao.getActiveRateDetailsByRate(et.getUniversityFiscalYear(), icrGenerationMetadata.getFinancialIcrSeriesIdentifier());
549 int automatedEntriesCount = automatedEntries.size();
550
551 if (automatedEntriesCount > 0) {
552 for (Iterator icrIter = automatedEntries.iterator(); icrIter.hasNext();) {
553 IndirectCostRecoveryRateDetail icrEntry = (IndirectCostRecoveryRateDetail) icrIter.next();
554 KualiDecimal generatedTransactionAmount = null;
555
556 if (!icrIter.hasNext()) {
557 generatedTransactionAmount = distributionAmount;
558
559
560 if (getPercentage(transactionAmount, icrEntry.getAwardIndrCostRcvyRatePct()).subtract(distributionAmount).abs().isGreaterThan(WARNING_MAX_DIFFERENCE)) {
561 List<Message> warnings = new ArrayList<Message>();
562 warnings.add(new Message("ADJUSTMENT GREATER THAN " + WARNING_MAX_DIFFERENCE, Message.TYPE_WARNING));
563 reportWriterService.writeError(et, warnings);
564 }
565 }
566 else if (icrEntry.getTransactionDebitIndicator().equals(OLEConstants.GL_DEBIT_CODE)) {
567 generatedTransactionAmount = getPercentage(transactionAmount, icrEntry.getAwardIndrCostRcvyRatePct());
568 distributionAmount = distributionAmount.add(generatedTransactionAmount);
569 }
570 else if (icrEntry.getTransactionDebitIndicator().equals(OLEConstants.GL_CREDIT_CODE)) {
571 generatedTransactionAmount = getPercentage(transactionAmount, icrEntry.getAwardIndrCostRcvyRatePct());
572 distributionAmount = distributionAmount.subtract(generatedTransactionAmount);
573 }
574 else {
575
576 List<Message> warnings = new ArrayList<Message>();
577 warnings.add(new Message("DEBIT OR CREDIT CODE NOT FOUND", Message.TYPE_FATAL));
578 reportWriterService.writeError(et, warnings);
579 }
580
581 generateTransactionsBySymbol(et, icrEntry, generatedTransactionAmount, runDate, OUTPUT_GLE_FILE_ps, icrGenerationMetadata);
582
583 reportOriginEntryGenerated = reportOriginEntryGenerated + 2;
584 }
585 }
586
587 expenditureTransactionDao.delete(et);
588 reportExpendTranDeleted++;
589
590 }
591 catch (RuntimeException re) {
592 LOG.error("generateIcrTransactions Stopped: " + re.getMessage());
593 throw new RuntimeException("generateIcrTransactions Stopped: " + re.getMessage(), re);
594 }
595 catch (Exception e) {
596 List errorList = new ArrayList();
597 errorList.add(new Message(e.toString() + " occurred for this record.", Message.TYPE_FATAL));
598 reportWriterService.writeError(et, errorList);
599 }
600 }
601 OUTPUT_GLE_FILE_ps.close();
602 reportWriterService.writeStatisticLine("GLEX RECORDS READ (GL_EXPEND_TRN_MT) %,9d", reportExpendTranRetrieved);
603 reportWriterService.writeStatisticLine("GLEX RECORDS DELETED (GL_EXPEND_TRN_MT) %,9d", reportExpendTranDeleted);
604 reportWriterService.writeStatisticLine("GLEX RECORDS KEPT DUE TO ERRORS (GL_EXPEND_TRN_MT) %,9d", reportExpendTranKept);
605 reportWriterService.writeStatisticLine("TRANSACTIONS GENERATED %,9d", reportOriginEntryGenerated);
606 }
607 catch (FileNotFoundException e) {
608 throw new RuntimeException("generateIcrTransactions Stopped: " + e.getMessage(), e);
609 }
610 }
611
612
613
614
615
616
617
618
619
620
621
622 private void generateTransactionsBySymbol(ExpenditureTransaction et, IndirectCostRecoveryRateDetail icrRateDetail, KualiDecimal generatedTransactionAmount, Date runDate, PrintStream group, IndirectCostRecoveryGenerationMetadata icrGenerationMetadata) {
623
624 KualiDecimal icrTransactionAmount;
625 KualiDecimal unappliedTransactionAmount = new KualiDecimal(generatedTransactionAmount.bigDecimalValue());
626
627
628 if (GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(icrRateDetail.getAccountNumber())) {
629
630 int icrCount = icrGenerationMetadata.getAccountLists().size();
631
632 for (IndirectCostRecoveryAccountDistributionMetadata meta : icrGenerationMetadata.getAccountLists()){
633
634
635 IndirectCostRecoveryGenerationMetadata icrMeta = new IndirectCostRecoveryGenerationMetadata(icrGenerationMetadata.getIndirectCostRecoveryTypeCode(),
636 icrGenerationMetadata.getFinancialIcrSeriesIdentifier());
637 icrMeta.setIndirectCostRcvyFinCoaCode(meta.getIndirectCostRecoveryFinCoaCode());
638 icrMeta.setIndirectCostRecoveryAcctNbr(meta.getIndirectCostRecoveryAccountNumber());
639
640
641 if (icrCount-- == 1) {
642
643 icrTransactionAmount = unappliedTransactionAmount;
644 }
645 else {
646
647 icrTransactionAmount = getPercentage(generatedTransactionAmount, meta.getAccountLinePercent());
648 unappliedTransactionAmount = unappliedTransactionAmount.subtract(icrTransactionAmount);
649 }
650
651
652 generateTransactions(et, icrRateDetail, icrTransactionAmount, runDate, group, icrMeta);
653 }
654 }else{
655
656
657 generateTransactions(et, icrRateDetail, generatedTransactionAmount, runDate, group, icrGenerationMetadata);
658 }
659
660 }
661
662
663
664
665
666
667
668
669
670
671 protected void generateTransactions(ExpenditureTransaction et, IndirectCostRecoveryRateDetail icrRateDetail, KualiDecimal generatedTransactionAmount, Date runDate, PrintStream group, IndirectCostRecoveryGenerationMetadata icrGenerationMetadata) {
672
673 BigDecimal pct = new BigDecimal(icrRateDetail.getAwardIndrCostRcvyRatePct().toString());
674 pct = pct.divide(BDONEHUNDRED);
675
676 OriginEntryFull e = new OriginEntryFull();
677 e.setTransactionLedgerEntrySequenceNumber(0);
678
679
680
681 if (GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(icrRateDetail.getFinancialObjectCode()) || GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(icrRateDetail.getFinancialObjectCode())) {
682 e.setFinancialObjectCode(et.getObjectCode());
683 e.setFinancialSubObjectCode(et.getSubObjectCode());
684 }
685 else {
686 e.setFinancialObjectCode(icrRateDetail.getFinancialObjectCode());
687 e.setFinancialSubObjectCode(icrRateDetail.getFinancialSubObjectCode());
688 }
689
690 if (GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(icrRateDetail.getAccountNumber())) {
691 e.setAccountNumber(et.getAccountNumber());
692 e.setChartOfAccountsCode(et.getChartOfAccountsCode());
693 e.setSubAccountNumber(et.getSubAccountNumber());
694 }
695 else if (GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(icrRateDetail.getAccountNumber())) {
696 e.setAccountNumber(icrGenerationMetadata.getIndirectCostRecoveryAcctNbr());
697 e.setChartOfAccountsCode(icrGenerationMetadata.getIndirectCostRcvyFinCoaCode());
698 e.setSubAccountNumber(OLEConstants.getDashSubAccountNumber());
699 }
700 else {
701 e.setAccountNumber(icrRateDetail.getAccountNumber());
702 e.setSubAccountNumber(icrRateDetail.getSubAccountNumber());
703 e.setChartOfAccountsCode(icrRateDetail.getChartOfAccountsCode());
704
705 }
706
707 if ((et.getAccountNumber().equals(e.getAccountNumber() )) &&
708 ( et.getChartOfAccountsCode().equals(e.getChartOfAccountsCode())) &&
709 (et.getSubAccountNumber().equals(e.getSubAccountNumber())) &&
710 (et.getObjectCode().equals(e.getFinancialObjectCode())) &&
711 (et.getSubObjectCode().equals(e.getFinancialSubObjectCode()))) {
712 List<Message> warnings = new ArrayList<Message>();
713 warnings.add(new Message("Infinite recursive encumbrance error " + et.getChartOfAccountsCode() + " " + et.getAccountNumber() + " " + et.getSubAccountNumber() + " " + et.getObjectCode() + " " + et.getSubObjectCode(), Message.TYPE_WARNING));
714 reportWriterService.writeError(et, warnings);
715 return;
716 }
717
718 e.setFinancialDocumentTypeCode(parameterService.getParameterValueAsString(PosterIndirectCostRecoveryEntriesStep.class, OLEConstants.SystemGroupParameterNames.GL_INDIRECT_COST_RECOVERY));
719 e.setFinancialSystemOriginationCode(parameterService.getParameterValueAsString(OleParameterConstants.GENERAL_LEDGER_BATCH.class, OLEConstants.SystemGroupParameterNames.GL_ORIGINATION_CODE));
720 SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_STRING);
721 e.setDocumentNumber(sdf.format(runDate));
722 if (OLEConstants.GL_DEBIT_CODE.equals(icrRateDetail.getTransactionDebitIndicator())) {
723 e.setTransactionLedgerEntryDescription(getChargeDescription(pct, et.getObjectCode(), icrGenerationMetadata.getIndirectCostRecoveryTypeCode(), et.getAccountObjectDirectCostAmount().abs()));
724 }
725 else {
726 e.setTransactionLedgerEntryDescription(getOffsetDescription(pct, et.getAccountObjectDirectCostAmount().abs(), et.getChartOfAccountsCode(), et.getAccountNumber()));
727 }
728 e.setTransactionDate(new java.sql.Date(runDate.getTime()));
729 e.setTransactionDebitCreditCode(icrRateDetail.getTransactionDebitIndicator());
730 e.setFinancialBalanceTypeCode(et.getBalanceTypeCode());
731 e.setUniversityFiscalYear(et.getUniversityFiscalYear());
732 e.setUniversityFiscalPeriodCode(et.getUniversityFiscalAccountingPeriod());
733
734 ObjectCode oc = objectCodeService.getByPrimaryId(e.getUniversityFiscalYear(), e.getChartOfAccountsCode(), e.getFinancialObjectCode());
735 if (oc == null) {
736 LOG.warn(configurationService.getPropertyValueAsString(OLEKeyConstants.ERROR_OBJECT_CODE_NOT_FOUND_FOR) + e.getUniversityFiscalYear() + "," + e.getChartOfAccountsCode() + "," + e.getFinancialObjectCode());
737 e.setFinancialObjectCode(icrRateDetail.getFinancialObjectCode());
738 } else {
739 e.setFinancialObjectTypeCode(oc.getFinancialObjectTypeCode());
740 }
741
742 if (generatedTransactionAmount.isNegative()) {
743 if (OLEConstants.GL_DEBIT_CODE.equals(icrRateDetail.getTransactionDebitIndicator())) {
744 e.setTransactionDebitCreditCode(OLEConstants.GL_CREDIT_CODE);
745 }
746 else {
747 e.setTransactionDebitCreditCode(OLEConstants.GL_DEBIT_CODE);
748 }
749 e.setTransactionLedgerEntryAmount(generatedTransactionAmount.negated());
750 }
751 else {
752 e.setTransactionLedgerEntryAmount(generatedTransactionAmount);
753 }
754
755 if (et.getBalanceTypeCode().equals(et.getOption().getExtrnlEncumFinBalanceTypCd()) || et.getBalanceTypeCode().equals(et.getOption().getIntrnlEncumFinBalanceTypCd()) || et.getBalanceTypeCode().equals(et.getOption().getPreencumbranceFinBalTypeCd()) || et.getBalanceTypeCode().equals(et.getOption().getCostShareEncumbranceBalanceTypeCd())) {
756 e.setDocumentNumber(parameterService.getParameterValueAsString(PosterIndirectCostRecoveryEntriesStep.class, OLEConstants.SystemGroupParameterNames.GL_INDIRECT_COST_RECOVERY));
757 }
758 e.setProjectCode(et.getProjectCode());
759 if (GeneralLedgerConstants.getDashOrganizationReferenceId().equals(et.getOrganizationReferenceId())) {
760 e.setOrganizationReferenceId(null);
761 }
762 else {
763 e.setOrganizationReferenceId(et.getOrganizationReferenceId());
764 }
765
766 try {
767 createOutputEntry(e, group);
768 }
769 catch (IOException ioe) {
770 LOG.error("generateTransactions Stopped: " + ioe.getMessage());
771 throw new RuntimeException("generateTransactions Stopped: " + ioe.getMessage(), ioe);
772 }
773
774
775 e = new OriginEntryFull(e);
776 if (OLEConstants.GL_DEBIT_CODE.equals(e.getTransactionDebitCreditCode())) {
777 e.setTransactionDebitCreditCode(OLEConstants.GL_CREDIT_CODE);
778 }
779 else {
780 e.setTransactionDebitCreditCode(OLEConstants.GL_DEBIT_CODE);
781 }
782 e.setFinancialSubObjectCode(OLEConstants.getDashFinancialSubObjectCode());
783
784 String offsetBalanceSheetObjectCodeNumber = determineIcrOffsetBalanceSheetObjectCodeNumber(e, et, icrRateDetail);
785 e.setFinancialObjectCode(offsetBalanceSheetObjectCodeNumber);
786 ObjectCode balSheetObjectCode = objectCodeService.getByPrimaryId(icrRateDetail.getUniversityFiscalYear(), e.getChartOfAccountsCode(), offsetBalanceSheetObjectCodeNumber);
787 if (balSheetObjectCode == null) {
788 List<Message> warnings = new ArrayList<Message>();
789 warnings.add(new Message(configurationService.getPropertyValueAsString(OLEKeyConstants.ERROR_INVALID_OFFSET_OBJECT_CODE) + icrRateDetail.getUniversityFiscalYear() + "-" + e.getChartOfAccountsCode() + "-" +offsetBalanceSheetObjectCodeNumber, Message.TYPE_WARNING));
790 reportWriterService.writeError(et, warnings);
791
792 }
793 else {
794 e.setFinancialObjectTypeCode(balSheetObjectCode.getFinancialObjectTypeCode());
795 }
796
797 if (OLEConstants.GL_DEBIT_CODE.equals(icrRateDetail.getTransactionDebitIndicator())) {
798 e.setTransactionLedgerEntryDescription(getChargeDescription(pct, et.getObjectCode(), icrGenerationMetadata.getIndirectCostRecoveryTypeCode(), et.getAccountObjectDirectCostAmount().abs()));
799 }
800 else {
801 e.setTransactionLedgerEntryDescription(getOffsetDescription(pct, et.getAccountObjectDirectCostAmount().abs(), et.getChartOfAccountsCode(), et.getAccountNumber()));
802 }
803
804 try {
805 flexibleOffsetAccountService.updateOffset(e);
806 }
807 catch (InvalidFlexibleOffsetException ex) {
808 List<Message> warnings = new ArrayList<Message>();
809 warnings.add(new Message("FAILED TO GENERATE FLEXIBLE OFFSETS " + ex.getMessage(), Message.TYPE_WARNING));
810 reportWriterService.writeError(et, warnings);
811 LOG.warn("FAILED TO GENERATE FLEXIBLE OFFSETS FOR EXPENDITURE TRANSACTION " + et.toString(), ex);
812 }
813
814 try {
815 createOutputEntry(e, group);
816 }
817 catch (IOException ioe) {
818 LOG.error("generateTransactions Stopped: " + ioe.getMessage());
819 throw new RuntimeException("generateTransactions Stopped: " + ioe.getMessage(), ioe);
820 }
821 }
822
823 public final static KualiDecimal ONEHUNDRED = new KualiDecimal("100");
824 public final static DecimalFormat DFPCT = new DecimalFormat("#0.000");
825 public final static DecimalFormat DFAMT = new DecimalFormat("##########.00");
826 public final static BigDecimal BDONEHUNDRED = new BigDecimal("100");
827
828
829
830
831
832
833
834
835
836 protected IndirectCostRecoveryGenerationMetadata retrieveSubAccountIndirectCostRecoveryMetadata(ExpenditureTransaction et) {
837 SubAccount subAccount = accountingCycleCachingService.getSubAccount(et.getChartOfAccountsCode(), et.getAccountNumber(), et.getSubAccountNumber());
838 if (ObjectUtils.isNotNull(subAccount)) {
839 subAccount.setA21SubAccount(accountingCycleCachingService.getA21SubAccount(et.getChartOfAccountsCode(), et.getAccountNumber(), et.getSubAccountNumber()));
840 }
841
842 if (ObjectUtils.isNotNull(subAccount) && ObjectUtils.isNotNull(subAccount.getA21SubAccount())) {
843 A21SubAccount a21SubAccount = subAccount.getA21SubAccount();
844 if (StringUtils.isBlank(a21SubAccount.getIndirectCostRecoveryTypeCode()) && StringUtils.isBlank(a21SubAccount.getFinancialIcrSeriesIdentifier()) &&
845 a21SubAccount.getA21ActiveIndirectCostRecoveryAccounts().isEmpty()) {
846
847 return null;
848 }
849
850 Account refreshSubAccount = null;
851 if (!StringUtils.isBlank(a21SubAccount.getChartOfAccountsCode()) && !StringUtils.isBlank(a21SubAccount.getAccountNumber())) {
852 refreshSubAccount = accountingCycleCachingService.getAccount(a21SubAccount.getChartOfAccountsCode(), a21SubAccount.getAccountNumber());
853 }
854
855
856 String warningMessagePattern = configurationService.getPropertyValueAsString(OLEKeyConstants.WARNING_ICR_GENERATION_PROBLEM_WITH_A21SUBACCOUNT_FIELD_BLANK_INVALID);
857 String subAccountBOLabel = dataDictionaryService.getDataDictionary().getBusinessObjectEntry(SubAccount.class.getName()).getObjectLabel();
858 String subAccountValue = subAccount.getChartOfAccountsCode() + "-" + subAccount.getAccountNumber() + "-" + subAccount.getSubAccountNumber();
859 String accountBOLabel = dataDictionaryService.getDataDictionary().getBusinessObjectEntry(Account.class.getName()).getObjectLabel();
860 String accountValue = et.getChartOfAccountsCode() + "-" + et.getAccountNumber();
861
862 boolean subAccountOK = true;
863
864
865 a21SubAccount.setIndirectCostRecoveryType(accountingCycleCachingService.getIndirectCostRecoveryType(a21SubAccount.getIndirectCostRecoveryTypeCode()));
866 if (StringUtils.isBlank(a21SubAccount.getIndirectCostRecoveryTypeCode()) || ObjectUtils.isNull(a21SubAccount.getIndirectCostRecoveryType())) {
867 String errorFieldName = dataDictionaryService.getAttributeShortLabel(A21SubAccount.class, OLEPropertyConstants.INDIRECT_COST_RECOVERY_TYPE_CODE);
868 String warningMessage = MessageFormat.format(warningMessagePattern, errorFieldName, subAccountBOLabel, subAccountValue, accountBOLabel, accountValue);
869 reportWriterService.writeError(et, new Message(warningMessage, Message.TYPE_WARNING));
870 subAccountOK = false;
871 }
872
873 if (StringUtils.isBlank(a21SubAccount.getFinancialIcrSeriesIdentifier())) {
874 Map<String, Object> icrRatePkMap = new HashMap<String, Object>();
875 icrRatePkMap.put(OLEPropertyConstants.UNIVERSITY_FISCAL_YEAR, et.getUniversityFiscalYear());
876 icrRatePkMap.put(OLEPropertyConstants.FINANCIAL_ICR_SERIES_IDENTIFIER, a21SubAccount.getFinancialIcrSeriesIdentifier());
877 IndirectCostRecoveryRate indirectCostRecoveryRate = (IndirectCostRecoveryRate) businessObjectService.findByPrimaryKey(IndirectCostRecoveryRate.class, icrRatePkMap);
878 if (indirectCostRecoveryRate == null) {
879 String errorFieldName = dataDictionaryService.getAttributeShortLabel(A21SubAccount.class, OLEPropertyConstants.FINANCIAL_ICR_SERIES_IDENTIFIER);
880 String warningMessage = MessageFormat.format(warningMessagePattern, errorFieldName, subAccountBOLabel, subAccountValue, accountBOLabel, accountValue);
881 reportWriterService.writeError(et, new Message(warningMessage, Message.TYPE_WARNING));
882 subAccountOK = false;
883 }
884 }
885
886 if (a21SubAccount.getA21ActiveIndirectCostRecoveryAccounts().isEmpty() || ObjectUtils.isNull(refreshSubAccount)) {
887 String errorFieldName = dataDictionaryService.getAttributeShortLabel(A21IndirectCostRecoveryAccount.class, OLEPropertyConstants.ICR_CHART_OF_ACCOUNTS_CODE) + "/" + dataDictionaryService.getAttributeShortLabel(A21IndirectCostRecoveryAccount.class, OLEPropertyConstants.ICR_ACCOUNT_NUMBER);
888 String warningMessage = MessageFormat.format(warningMessagePattern, errorFieldName, subAccountBOLabel, subAccountValue, accountBOLabel, accountValue);
889 reportWriterService.writeError(et, new Message(warningMessage, Message.TYPE_WARNING));
890 subAccountOK = false;
891 }
892
893 if (subAccountOK) {
894 IndirectCostRecoveryGenerationMetadata metadata = new IndirectCostRecoveryGenerationMetadata(a21SubAccount.getIndirectCostRecoveryTypeCode(),
895 a21SubAccount.getFinancialIcrSeriesIdentifier());
896
897 List<IndirectCostRecoveryAccountDistributionMetadata> icrAccountList = metadata.getAccountLists();
898 for (A21IndirectCostRecoveryAccount a21 : a21SubAccount.getA21ActiveIndirectCostRecoveryAccounts()){
899 icrAccountList.add(new IndirectCostRecoveryAccountDistributionMetadata(a21));
900 }
901 return metadata;
902 }
903 }
904 return null;
905 }
906
907
908 protected IndirectCostRecoveryGenerationMetadata retrieveAccountIndirectCostRecoveryMetadata(ExpenditureTransaction et) {
909 Account account = et.getAccount();
910
911 IndirectCostRecoveryGenerationMetadata metadata = new IndirectCostRecoveryGenerationMetadata(account.getAcctIndirectCostRcvyTypeCd(),
912 account.getFinancialIcrSeriesIdentifier());
913
914 List<IndirectCostRecoveryAccountDistributionMetadata> icrAccountList = metadata.getAccountLists();
915 for (IndirectCostRecoveryAccount icr : account.getActiveIndirectCostRecoveryAccounts()){
916 icrAccountList.add(new IndirectCostRecoveryAccountDistributionMetadata(icr));
917 }
918
919 return metadata;
920 }
921
922
923
924
925
926
927
928
929
930 protected KualiDecimal getPercentage(KualiDecimal amount, BigDecimal percent) {
931 BigDecimal result = amount.bigDecimalValue().multiply(percent).divide(BDONEHUNDRED, 2, BigDecimal.ROUND_DOWN);
932 return new KualiDecimal(result);
933 }
934
935
936
937
938
939
940
941
942
943
944 protected String getChargeDescription(BigDecimal rate, String objectCode, String type, KualiDecimal amount) {
945 BigDecimal newRate = rate.multiply(PosterServiceImpl.BDONEHUNDRED);
946
947 StringBuffer desc = new StringBuffer("CHG ");
948 if (newRate.doubleValue() < 10) {
949 desc.append(" ");
950 }
951 desc.append(DFPCT.format(newRate));
952 desc.append("% ON ");
953 desc.append(objectCode);
954 desc.append(" (");
955 desc.append(type);
956 desc.append(") ");
957 String amt = DFAMT.format(amount);
958 while (amt.length() < 13) {
959 amt = " " + amt;
960 }
961 desc.append(amt);
962 return desc.toString();
963 }
964
965
966
967
968
969
970
971
972
973
974 protected String getOffsetDescription(BigDecimal rate, KualiDecimal amount, String chartOfAccountsCode, String accountNumber) {
975 BigDecimal newRate = rate.multiply(PosterServiceImpl.BDONEHUNDRED);
976
977 StringBuffer desc = new StringBuffer("RCV ");
978 if (newRate.doubleValue() < 10) {
979 desc.append(" ");
980 }
981 desc.append(DFPCT.format(newRate));
982 desc.append("% ON ");
983 String amt = DFAMT.format(amount);
984 while (amt.length() < 13) {
985 amt = " " + amt;
986 }
987 desc.append(amt);
988 desc.append(" FRM ");
989
990
991 desc.append(accountNumber);
992 return desc.toString();
993 }
994
995
996
997
998
999
1000
1001
1002 protected void addReporting(Map reporting, String destination, String operation) {
1003 String key = destination + "," + operation;
1004
1005 if("GL_EXPEND_TRN_MT".equals(destination)){
1006 LOG.info("Counting GLEX operation: "+operation);
1007 }
1008 if (reporting.containsKey(key)) {
1009 Integer c = (Integer) reporting.get(key);
1010 reporting.put(key, new Integer(c.intValue() + 1));
1011 }
1012 else {
1013 reporting.put(key, new Integer(1));
1014 }
1015 }
1016
1017 protected String determineIcrOffsetBalanceSheetObjectCodeNumber(OriginEntryInformation offsetEntry, ExpenditureTransaction et, IndirectCostRecoveryRateDetail icrRateDetail) {
1018 String icrEntryDocumentType = parameterService.getParameterValueAsString(PosterIndirectCostRecoveryEntriesStep.class, OLEConstants.SystemGroupParameterNames.GL_INDIRECT_COST_RECOVERY);
1019 OffsetDefinition offsetDefinition = offsetDefinitionService.getByPrimaryId(offsetEntry.getUniversityFiscalYear(), offsetEntry.getChartOfAccountsCode(), icrEntryDocumentType, et.getBalanceTypeCode());
1020 if (!ObjectUtils.isNull(offsetDefinition)) {
1021 return offsetDefinition.getFinancialObjectCode();
1022 } else {
1023 return null;
1024 }
1025 }
1026
1027 public void setVerifyTransaction(VerifyTransaction vt) {
1028 verifyTransaction = vt;
1029 }
1030
1031 public void setTransactionPosters(List p) {
1032 transactionPosters = p;
1033 }
1034
1035 public void setOriginEntryService(OriginEntryService oes) {
1036 originEntryService = oes;
1037 }
1038
1039 public void setOriginEntryGroupService(OriginEntryGroupService oes) {
1040 originEntryGroupService = oes;
1041 }
1042
1043 public void setDateTimeService(DateTimeService dts) {
1044 dateTimeService = dts;
1045 }
1046
1047 public void setReversalDao(ReversalDao red) {
1048 reversalDao = red;
1049 }
1050
1051 public void setUniversityDateDao(UniversityDateDao udd) {
1052 universityDateDao = udd;
1053 }
1054
1055 public void setAccountingPeriodService(AccountingPeriodService aps) {
1056 accountingPeriodService = aps;
1057 }
1058
1059 public void setExpenditureTransactionDao(ExpenditureTransactionDao etd) {
1060 expenditureTransactionDao = etd;
1061 }
1062
1063 public void setIndirectCostRecoveryRateDetailDao(IndirectCostRecoveryRateDetailDao iaed) {
1064 indirectCostRecoveryRateDetailDao = iaed;
1065 }
1066
1067 public void setObjectCodeService(ObjectCodeService ocs) {
1068 objectCodeService = ocs;
1069 }
1070
1071 public void setConfigurationService(ConfigurationService configurationService) {
1072 this.configurationService = configurationService;
1073 }
1074
1075 public void setParameterService(ParameterService parameterService) {
1076 this.parameterService = parameterService;
1077 }
1078
1079 public void setFlexibleOffsetAccountService(FlexibleOffsetAccountService flexibleOffsetAccountService) {
1080 this.flexibleOffsetAccountService = flexibleOffsetAccountService;
1081 }
1082
1083 public RunDateService getRunDateService() {
1084 return runDateService;
1085 }
1086
1087 public void setRunDateService(RunDateService runDateService) {
1088 this.runDateService = runDateService;
1089 }
1090
1091 protected void createOutputEntry(Transaction entry, PrintStream group) throws IOException {
1092 OriginEntryFull oef = new OriginEntryFull();
1093 oef.copyFieldsFromTransaction(entry);
1094 try {
1095 group.printf("%s\n", oef.getLine());
1096 }
1097 catch (Exception e) {
1098 throw new IOException(e.toString());
1099 }
1100 }
1101
1102 protected void writeErrorEntry(String line, PrintStream invaliGroup) throws IOException {
1103 try {
1104 invaliGroup.printf("%s\n", line);
1105 } catch (Exception e) {
1106 throw new IOException(e.toString());
1107 }
1108 }
1109
1110 public AccountingCycleCachingService getAccountingCycleCachingService() {
1111 return accountingCycleCachingService;
1112 }
1113
1114 public void setAccountingCycleCachingService(AccountingCycleCachingService accountingCycleCachingService) {
1115 this.accountingCycleCachingService = accountingCycleCachingService;
1116 }
1117
1118 public void setSubAccountService(SubAccountService subAccountService) {
1119 this.subAccountService = subAccountService;
1120 }
1121
1122 public void setOffsetDefinitionService(OffsetDefinitionService offsetDefinitionService) {
1123 this.offsetDefinitionService = offsetDefinitionService;
1124 }
1125
1126 protected DataDictionaryService getDataDictionaryService() {
1127 return dataDictionaryService;
1128 }
1129
1130 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
1131 this.dataDictionaryService = dataDictionaryService;
1132 }
1133
1134 protected BusinessObjectService getBusinessObjectService() {
1135 return businessObjectService;
1136 }
1137
1138 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
1139 this.businessObjectService = businessObjectService;
1140 }
1141
1142 protected boolean shouldIgnoreExpenditureTransaction(ExpenditureTransaction et) {
1143 if (ObjectUtils.isNotNull(et.getOption())) {
1144 SystemOptions options = et.getOption();
1145 return StringUtils.isNotBlank(options.getActualFinancialBalanceTypeCd()) && !options.getActualFinancialBalanceTypeCd().equals(et.getBalanceTypeCode());
1146 }
1147 return true;
1148 }
1149
1150 public void setBatchFileDirectoryName(String batchFileDirectoryName) {
1151 this.batchFileDirectoryName = batchFileDirectoryName;
1152 }
1153
1154 public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
1155 this.persistenceStructureService = persistenceStructureService;
1156 }
1157
1158
1159
1160
1161
1162 public PersistenceStructureService getPersistenceStructureService() {
1163 return persistenceStructureService;
1164 }
1165
1166 public void setReportWriterService(ReportWriterService reportWriterService) {
1167 this.reportWriterService = reportWriterService;
1168 }
1169
1170 public void setErrorListingReportWriterService(ReportWriterService errorListingReportWriterService) {
1171 this.errorListingReportWriterService = errorListingReportWriterService;
1172 }
1173
1174 public void setReversalReportWriterService(ReportWriterService reversalReportWriterService) {
1175 this.reversalReportWriterService = reversalReportWriterService;
1176 }
1177
1178 public void setLedgerSummaryReportWriterService(ReportWriterService ledgerSummaryReportWriterService) {
1179 this.ledgerSummaryReportWriterService = ledgerSummaryReportWriterService;
1180 }
1181 }