1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.gl.batch.service.impl;
17
18 import java.io.BufferedReader;
19 import java.io.File;
20 import java.io.FileReader;
21 import java.lang.reflect.ParameterizedType;
22 import java.util.HashMap;
23 import java.util.Iterator;
24 import java.util.Map;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.kuali.ole.gl.batch.dataaccess.LedgerEntryBalanceCachingDao;
28 import org.kuali.ole.gl.batch.service.BalancingService;
29 import org.kuali.ole.gl.batch.service.PosterService;
30 import org.kuali.ole.gl.businessobject.Balance;
31 import org.kuali.ole.gl.businessobject.Entry;
32 import org.kuali.ole.gl.businessobject.OriginEntryInformation;
33 import org.kuali.ole.gl.dataaccess.LedgerBalanceBalancingDao;
34 import org.kuali.ole.gl.dataaccess.LedgerBalanceHistoryBalancingDao;
35 import org.kuali.ole.gl.dataaccess.LedgerBalancingDao;
36 import org.kuali.ole.gl.dataaccess.LedgerEntryBalancingDao;
37 import org.kuali.ole.gl.dataaccess.LedgerEntryHistoryBalancingDao;
38 import org.kuali.ole.sys.OLEKeyConstants;
39 import org.kuali.ole.sys.OLEPropertyConstants;
40 import org.kuali.ole.sys.Message;
41 import org.kuali.ole.sys.service.ReportWriterService;
42 import org.kuali.ole.sys.service.UniversityDateService;
43 import org.kuali.rice.core.api.config.property.ConfigurationService;
44 import org.kuali.rice.core.api.datetime.DateTimeService;
45 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
46 import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
47 import org.kuali.rice.krad.service.BusinessObjectService;
48 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
49 import org.kuali.rice.krad.service.PersistenceStructureService;
50 import org.kuali.rice.krad.util.ObjectUtils;
51 import org.springframework.transaction.annotation.Transactional;
52
53
54
55
56
57 @Transactional
58 public abstract class BalancingServiceBaseImpl<T extends Entry, S extends Balance> implements BalancingService {
59 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(BalancingServiceBaseImpl.class);
60
61
62 protected Class<T> entryHistoryPersistentClass;
63 protected Class<S> balanceHistoryPersistentClass;
64
65 protected ParameterService parameterService;
66 protected PersistenceStructureService persistenceStructureService;
67 protected ConfigurationService kualiConfigurationService;
68 protected BusinessObjectService businessObjectService;
69 protected DateTimeService dateTimeService;
70 protected UniversityDateService universityDateService;
71 protected LedgerBalancingDao ledgerBalancingDao;
72 protected LedgerEntryBalancingDao ledgerEntryBalancingDao;
73 protected LedgerEntryBalanceCachingDao ledgerEntryBalanceCachingDao;
74 protected LedgerBalanceBalancingDao ledgerBalanceBalancingDao;
75 protected LedgerBalanceHistoryBalancingDao ledgerBalanceHistoryBalancingDao;
76 protected LedgerEntryHistoryBalancingDao ledgerEntryHistoryBalancingDao;
77 protected ReportWriterService reportWriterService;
78 protected String batchFileDirectoryName;
79
80
81
82
83 public BalancingServiceBaseImpl() {
84 super();
85 this.entryHistoryPersistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
86 this.balanceHistoryPersistentClass = (Class<S>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
87 }
88
89
90
91
92 @Override
93 public boolean runBalancing() {
94
95 Integer currentUniversityFiscalYear = universityDateService.getCurrentFiscalYear();
96 int startUniversityFiscalYear = currentUniversityFiscalYear - this.getPastFiscalYearsToConsider();
97
98 LOG.debug("Checking files required for balancing process are present.");
99 if (!this.isFilesReady()) {
100 reportWriterService.writeFormattedMessageLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.ERROR_BATCH_BALANCING_FILES));
101
102 return false;
103 }
104
105 LOG.debug("Checking data required for balancing process is present.");
106 boolean historyTablesPopulated = false;
107
108
109 if (this.getHistoryCount(null, entryHistoryPersistentClass) == 0 || this.getHistoryCount(null, balanceHistoryPersistentClass) == 0) {
110 reportWriterService.writeFormattedMessageLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.MESSAGE_BATCH_BALANCING_DATA_INSERT), entryHistoryPersistentClass.getSimpleName(), balanceHistoryPersistentClass.getSimpleName());
111 reportWriterService.writeNewLines(1);
112
113 ledgerBalancingDao.populateLedgerEntryHistory(startUniversityFiscalYear);
114 ledgerBalancingDao.populateLedgerBalanceHistory(startUniversityFiscalYear);
115 this.customPopulateHistoryTables(startUniversityFiscalYear);
116
117 historyTablesPopulated = true;
118 }
119
120 LOG.debug("Checking if obsolete historic data present. Deleting if yes.");
121
122
123
124 boolean obsoleteUniversityFiscalYearDeleted = false;
125 int obsoleteUniversityFiscalYear = startUniversityFiscalYear - 1;
126 if (this.getHistoryCount(obsoleteUniversityFiscalYear, entryHistoryPersistentClass) != 0 || this.getHistoryCount(obsoleteUniversityFiscalYear, balanceHistoryPersistentClass) != 0 || this.doesCustomHistoryExist(obsoleteUniversityFiscalYear)) {
127 reportWriterService.writeFormattedMessageLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.MESSAGE_BATCH_BALANCING_OBSOLETE_FISCAL_YEAR_DATA_DELETED), entryHistoryPersistentClass.getSimpleName(), balanceHistoryPersistentClass.getSimpleName(), obsoleteUniversityFiscalYear);
128 reportWriterService.writeNewLines(1);
129 this.deleteHistory(obsoleteUniversityFiscalYear, entryHistoryPersistentClass);
130 this.deleteHistory(obsoleteUniversityFiscalYear, balanceHistoryPersistentClass);
131 this.deleteCustomHistory(obsoleteUniversityFiscalYear);
132 obsoleteUniversityFiscalYearDeleted = true;
133 }
134
135
136
137 int updateRecordsIgnored = 0;
138 if (!historyTablesPopulated) {
139 LOG.debug("Getting postable records and save them to history tables.");
140 updateRecordsIgnored = this.updateHistoriesHelper(PosterService.MODE_ENTRIES, startUniversityFiscalYear, this.getPosterInputFile(), this.getPosterErrorOutputFile());
141 updateRecordsIgnored += this.updateHistoriesHelper(PosterService.MODE_REVERSAL, startUniversityFiscalYear, this.getReversalInputFile(), this.getReversalErrorOutputFile());
142 updateRecordsIgnored += this.updateHistoriesHelper(PosterService.MODE_ICR, startUniversityFiscalYear, this.getICRInputFile(), this.getICRErrorOutputFile());
143 }
144
145 LOG.debug("Comparing entry history table with the PRD counterpart.");
146 int countEntryComparisionFailure = this.compareEntryHistory();
147 if (countEntryComparisionFailure != 0) {
148 reportWriterService.writeNewLines(1);
149 reportWriterService.writeFormattedMessageLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.MESSAGE_BATCH_BALANCING_FAILURE_COUNT), entryHistoryPersistentClass.getSimpleName(), countEntryComparisionFailure, this.getComparisonFailuresToPrintPerReport());
150 }
151
152 LOG.debug("Comparing balance history table with the PRD counterpart.");
153 int countBalanceComparisionFailure = this.compareBalanceHistory();
154 if (countBalanceComparisionFailure != 0) {
155 reportWriterService.writeNewLines(1);
156 reportWriterService.writeFormattedMessageLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.MESSAGE_BATCH_BALANCING_FAILURE_COUNT), balanceHistoryPersistentClass.getSimpleName(), countBalanceComparisionFailure, this.getComparisonFailuresToPrintPerReport());
157 }
158
159 LOG.debug("Comparing custom, if any, history table with the PRD counterpart.");
160 Map<String, Integer> countCustomComparisionFailures = this.customCompareHistory();
161
162 if (!historyTablesPopulated) {
163 reportWriterService.writeNewLines(1);
164 reportWriterService.writeFormattedMessageLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.MESSAGE_BATCH_BALANCING_FILE_LISTING), this.getFilenames());
165 }
166
167 LOG.debug("Writing statistics section");
168 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_FISCAL_YEARS_INCLUDED), ledgerBalanceHistoryBalancingDao.findDistinctFiscalYears());
169 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_HISTORY_TABLES_INITIALIZED), historyTablesPopulated ? "Yes" : "No");
170 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_OBSOLETE_DELETED), obsoleteUniversityFiscalYearDeleted ? "Yes (" + obsoleteUniversityFiscalYear + ")" : "No");
171 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_UPDATED_SKIPPED), updateRecordsIgnored);
172 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_COMPARISION_FAILURE), this.getShortTableLabel(entryHistoryPersistentClass.getSimpleName()), "(" + entryHistoryPersistentClass.getSimpleName() + ")", countEntryComparisionFailure);
173 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_COMPARISION_FAILURE), this.getShortTableLabel(balanceHistoryPersistentClass.getSimpleName()), "(" + balanceHistoryPersistentClass.getSimpleName() + ")", countBalanceComparisionFailure);
174 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_ENTRY_SUM_ROW_COUNT_HISTORY), this.getShortTableLabel(entryHistoryPersistentClass.getSimpleName()), "(" + entryHistoryPersistentClass.getSimpleName() + ")", ledgerEntryHistoryBalancingDao.findSumRowCountGreaterOrEqualThan(startUniversityFiscalYear));
175 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_ENTRY_ROW_COUNT_PRODUCTION), this.getShortTableLabel((Entry.class).getSimpleName()), ledgerEntryBalancingDao.findCountGreaterOrEqualThan(startUniversityFiscalYear));
176 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_BALANCE_ROW_COUNT_HISTORY), this.getShortTableLabel(balanceHistoryPersistentClass.getSimpleName()), "(" + balanceHistoryPersistentClass.getSimpleName() + ")", this.getHistoryCount(null, balanceHistoryPersistentClass));
177 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_BALANCE_ROW_COUNT_PRODUCTION), this.getShortTableLabel((Balance.class).getSimpleName()), ledgerBalanceBalancingDao.findCountGreaterOrEqualThan(startUniversityFiscalYear));
178
179 if (ObjectUtils.isNotNull(countCustomComparisionFailures)) {
180 for (Iterator<String> names = countCustomComparisionFailures.keySet().iterator(); names.hasNext();) {
181 String name = names.next();
182 int count = countCustomComparisionFailures.get(name);
183
184 reportWriterService.writeStatisticLine(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.REPORT_COMPARISION_FAILURE), this.getShortTableLabel(name), "(" + name + ")", count);
185 }
186 }
187 this.customPrintRowCountHistory(startUniversityFiscalYear);
188
189 return true;
190 }
191
192
193
194
195 protected boolean isFilesReady() {
196 File inputFile = this.getPosterInputFile();
197 File errorFile = this.getPosterErrorOutputFile();
198
199 return inputFile != null && errorFile != null && inputFile.exists() && errorFile.exists() && inputFile.canRead() && errorFile.canRead();
200 }
201
202
203
204
205
206
207
208 protected void deleteHistory(Integer universityFiscalYear, Class<? extends PersistableBusinessObjectBase> persistentClass) {
209 Map<String, Object> fieldValues = new HashMap<String, Object>();
210 fieldValues.put(OLEPropertyConstants.UNIVERSITY_FISCAL_YEAR, universityFiscalYear);
211
212 KRADServiceLocatorWeb.getLegacyDataAdapter().deleteMatching(persistentClass, fieldValues);
213 }
214
215
216
217
218
219
220
221
222 protected int getHistoryCount(Integer fiscalYear, Class<? extends PersistableBusinessObjectBase> persistentClass) {
223 Map<String, String> keyMap = new HashMap<String, String>();
224
225 if (fiscalYear != null) {
226 keyMap.put(OLEPropertyConstants.UNIVERSITY_FISCAL_YEAR, fiscalYear.toString());
227 }
228
229 return (KRADServiceLocatorWeb.getLegacyDataAdapter().findMatching(persistentClass, keyMap)).size();
230 }
231
232
233
234
235
236
237
238 protected int updateHistoriesHelper(Integer postMode, Integer startUniversityFiscalYear, File inputFile, File errorFile) {
239 int ignoredRecordsFound = 0;
240 int lineNumber = 0;
241
242 if (inputFile == null || errorFile == null) {
243 return 0;
244 }
245 try {
246 FileReader posterInputFileReader = new FileReader(inputFile);
247 BufferedReader posterInputBufferedReader = new BufferedReader(posterInputFileReader);
248 FileReader posterErrorFileReader = new FileReader(errorFile);
249 BufferedReader posterErrorBufferedReader = new BufferedReader(posterErrorFileReader);
250
251
252 String currentInputLine = posterInputBufferedReader.readLine();
253 String currentErrorLine = posterErrorBufferedReader.readLine();
254
255 while (currentInputLine != null) {
256 lineNumber++;
257
258 if (!StringUtils.isEmpty(currentInputLine) && !StringUtils.isBlank(currentInputLine.trim())) {
259
260 if (currentInputLine.equals(currentErrorLine)) {
261
262 currentErrorLine = posterErrorBufferedReader.readLine();
263 }
264 else {
265
266 OriginEntryInformation originEntry = this.getOriginEntry(currentInputLine, lineNumber);
267
268 if (originEntry.getUniversityFiscalYear() >= startUniversityFiscalYear) {
269
270 this.updateEntryHistory(postMode, originEntry);
271 this.updateBalanceHistory(postMode, originEntry);
272 this.updateCustomHistory(postMode, originEntry);
273 }
274 else {
275
276 ignoredRecordsFound++;
277 reportWriterService.writeError(originEntry, new Message(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.MESSAGE_BATCH_BALANCING_RECORD_BEFORE_FISCAL_YEAR), Message.TYPE_WARNING, startUniversityFiscalYear));
278 }
279 }
280 }
281
282 currentInputLine = posterInputBufferedReader.readLine();
283 }
284
285 posterInputFileReader.close();
286 posterInputBufferedReader.close();
287 posterErrorFileReader.close();
288 posterErrorBufferedReader.close();
289 }
290 catch (Exception e) {
291 LOG.fatal(String.format(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.ERROR_BATCH_BALANCING_UNKNOWN_FAILURE), e.getMessage(), lineNumber), e);
292 reportWriterService.writeFormattedMessageLine(String.format(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.ERROR_BATCH_BALANCING_UNKNOWN_FAILURE), e.getMessage(), lineNumber));
293 throw new RuntimeException(String.format(kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Balancing.ERROR_BATCH_BALANCING_UNKNOWN_FAILURE), e.getMessage(), lineNumber), e);
294 }
295
296 return ignoredRecordsFound;
297 }
298
299 abstract protected Integer compareBalanceHistory();
300
301 abstract protected Integer compareEntryHistory();
302
303
304
305
306
307 protected int getFiscalYear(){
308 return universityDateService.getCurrentFiscalYear()-getPastFiscalYearsToConsider();
309 }
310
311
312
313
314
315
316
317 public void customPopulateHistoryTables(Integer fiscalYear) {
318 return;
319 }
320
321
322
323
324
325
326
327 protected boolean doesCustomHistoryExist(Integer fiscalYear) {
328 return false;
329 }
330
331
332
333
334
335
336
337 protected void deleteCustomHistory(Integer fiscalYear) {
338 return;
339 }
340
341
342
343
344
345
346 protected void updateCustomHistory(Integer postMode, OriginEntryInformation originEntry) {
347 return;
348 }
349
350
351
352
353
354
355 protected Map<String, Integer> customCompareHistory() {
356 return null;
357 }
358
359
360
361
362
363
364 protected void customPrintRowCountHistory(Integer fiscalYear) {
365 return;
366 }
367
368
369
370
371
372
373 public void setParameterService(ParameterService parameterService) {
374 this.parameterService = parameterService;
375 }
376
377
378
379
380
381
382 public void setConfigurationService(ConfigurationService kualiConfigurationService) {
383 this.kualiConfigurationService = kualiConfigurationService;
384 }
385
386
387
388
389
390
391 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
392 this.businessObjectService = businessObjectService;
393 }
394
395
396
397
398
399
400 public void setDateTimeService(DateTimeService dateTimeService) {
401 this.dateTimeService = dateTimeService;
402 }
403
404
405
406
407
408
409 public void setUniversityDateService(UniversityDateService universityDateService) {
410 this.universityDateService = universityDateService;
411 }
412
413
414
415
416
417
418 public void setLedgerBalancingDao(LedgerBalancingDao ledgerBalancingDao) {
419 this.ledgerBalancingDao = ledgerBalancingDao;
420 }
421
422
423
424
425
426
427 public void setLedgerEntryBalancingDao(LedgerEntryBalancingDao ledgerEntryBalancingDao) {
428 this.ledgerEntryBalancingDao = ledgerEntryBalancingDao;
429 }
430
431
432
433
434
435
436 public void setLedgerBalanceBalancingDao(LedgerBalanceBalancingDao ledgerBalanceBalancingDao) {
437 this.ledgerBalanceBalancingDao = ledgerBalanceBalancingDao;
438 }
439
440
441
442
443
444
445 public void setLedgerBalanceHistoryBalancingDao(LedgerBalanceHistoryBalancingDao ledgerBalanceHistoryBalancingDao) {
446 this.ledgerBalanceHistoryBalancingDao = ledgerBalanceHistoryBalancingDao;
447 }
448
449
450
451
452
453
454 public void setLedgerEntryHistoryBalancingDao(LedgerEntryHistoryBalancingDao ledgerEntryHistoryBalancingDao) {
455 this.ledgerEntryHistoryBalancingDao = ledgerEntryHistoryBalancingDao;
456 }
457
458
459
460
461
462
463 public void setReportWriterService(ReportWriterService reportWriterService) {
464 this.reportWriterService = reportWriterService;
465 }
466
467
468
469
470
471
472 public void setBatchFileDirectoryName(String batchFileDirectoryName) {
473 this.batchFileDirectoryName = batchFileDirectoryName;
474 }
475
476
477
478
479
480
481 public void setLedgerEntryBalanceCachingDao(LedgerEntryBalanceCachingDao ledgerEntryBalanceCachingDao) {
482 this.ledgerEntryBalanceCachingDao = ledgerEntryBalanceCachingDao;
483 }
484
485
486
487
488
489
490 public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
491 this.persistenceStructureService = persistenceStructureService;
492 }
493 }