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