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.module.endow.batch.service.impl;
017
018 import java.util.ArrayList;
019 import java.util.List;
020
021 import org.kuali.kfs.module.endow.EndowConstants;
022 import org.kuali.kfs.module.endow.EndowParameterKeyConstants;
023 import org.kuali.kfs.module.endow.batch.PooledFundControlTransactionsStep;
024 import org.kuali.kfs.module.endow.batch.service.PooledFundControlTransactionsService;
025 import org.kuali.kfs.module.endow.businessobject.EndowmentSourceTransactionLine;
026 import org.kuali.kfs.module.endow.businessobject.EndowmentTargetTransactionLine;
027 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLineBase;
028 import org.kuali.kfs.module.endow.businessobject.PooledFundControl;
029 import org.kuali.kfs.module.endow.businessobject.TransactionArchive;
030 import org.kuali.kfs.module.endow.businessobject.TransactionArchiveSecurity;
031 import org.kuali.kfs.module.endow.businessobject.TransactionDocumentExceptionReportLine;
032 import org.kuali.kfs.module.endow.businessobject.TransactionDocumentTotalReportLine;
033 import org.kuali.kfs.module.endow.dataaccess.PooledFundControlTransactionsDao;
034 import org.kuali.kfs.module.endow.document.CashDecreaseDocument;
035 import org.kuali.kfs.module.endow.document.CashIncreaseDocument;
036 import org.kuali.kfs.module.endow.document.EndowmentSecurityDetailsDocumentBase;
037 import org.kuali.kfs.module.endow.document.service.KEMService;
038 import org.kuali.kfs.module.endow.document.validation.event.AddTransactionLineEvent;
039 import org.kuali.kfs.module.endow.util.GloabalVariablesExtractHelper;
040 import org.kuali.kfs.sys.context.SpringContext;
041 import org.kuali.kfs.sys.service.ReportWriterService;
042 import org.kuali.rice.kew.exception.WorkflowException;
043 import org.kuali.rice.kns.rule.event.RouteDocumentEvent;
044 import org.kuali.rice.kns.service.BusinessObjectService;
045 import org.kuali.rice.kns.service.DocumentService;
046 import org.kuali.rice.kns.service.KualiRuleService;
047 import org.kuali.rice.kns.service.ParameterService;
048 import org.kuali.rice.kns.service.TransactionalDocumentDictionaryService;
049 import org.kuali.rice.kns.util.GlobalVariables;
050 import org.kuali.rice.kns.util.KualiDecimal;
051 import org.kuali.rice.kns.util.ObjectUtils;
052 import org.springframework.transaction.annotation.Transactional;
053
054 /*
055 * This class is the implementation of the Bach Generate Pooled fund Control Transactions
056 */
057 @Transactional
058 public class PooledFundControlTransactionsServiceImpl implements PooledFundControlTransactionsService {
059
060 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PooledFundControlTransactionsServiceImpl.class);
061
062 protected BusinessObjectService businessObjectService;
063 protected DocumentService documentService;
064 protected ParameterService parameterService;
065 protected KualiRuleService kualiRuleService;
066
067 protected KEMService kemService;
068
069 protected PooledFundControlTransactionsDao pooledFundControlTransactionsDao;
070
071 protected ReportWriterService pooledFundControlTransactionsExceptionReportWriterService;
072 protected ReportWriterService pooledFundControlTransactionsTotalReportWriterService;
073
074 private TransactionDocumentTotalReportLine totalReportLine = null;
075 private TransactionDocumentExceptionReportLine exceptionReportLine = null;
076
077 /*
078 * @see org.kuali.kfs.module.endow.batch.service.PooledFundControlTransactionsService#generatePooledFundControlTransactions()
079 */
080 public boolean generatePooledFundControlTransactions() {
081
082 LOG.info("Begin the batch Generate Pooled Fund Control Transactions ...");
083
084 // prepare for reports
085 initializeReports();
086
087 // All the jobs below should be attempted regardless of the status of another.
088 // In fact, all jobs in the process could be run concurrently.
089 // The job, itself, does not fail but completes with exceptions.
090 createCashDocumentForPurchase();
091 createCashDocumentForSale();
092 createCashDocumentForSaleGainLoss();
093 createCashDocumentForIncomeDistribution();
094
095 LOG.info("The batch Generate Pooled Fund Control Transactions was finished");
096
097 return true;
098 }
099
100 /**
101 * Creates an ECI or an ECDD eDoc according to the total amount of holding cost for EAI
102 */
103 protected boolean createCashDocumentForPurchase() {
104 return createCashDocumentBasedOnHoldingCost(EndowConstants.DocumentTypeNames.ENDOWMENT_ASSET_INCREASE, EndowParameterKeyConstants.PURCHASE_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_TARGET, EndowParameterKeyConstants.PURCHASE_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.PRINCIPAL);
105 }
106
107 /**
108 * Creates an ECI or an ECDD eDoc according to the total amount of holding cost for EAD
109 */
110 protected boolean createCashDocumentForSale() {
111 return createCashDocumentBasedOnHoldingCost(EndowConstants.DocumentTypeNames.ENDOWMENT_ASSET_DECREASE, EndowParameterKeyConstants.SALE_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE, EndowParameterKeyConstants.SALE_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.PRINCIPAL);
112 }
113
114 /**
115 * Creates an ECI or an ECDD eDoc according to the total amount of holding cost
116 * @param documentName
117 * @param DocDescription
118 * @param noRouteInd
119 * @param ipInd
120 */
121 protected boolean createCashDocumentBasedOnHoldingCost(String documentName, String DocDescription, String securityLineType, String noRouteInd, String ipInd) {
122
123 List<String> documentTypeNames = new ArrayList<String>();
124 documentTypeNames.add(documentName);
125 List<PooledFundControl> pooledFundControlRecords = (List<PooledFundControl>) pooledFundControlTransactionsDao.getAllPooledFundControlTransaction();
126 //if (pooledFundControlRecords == null) return;
127
128 // generate a cash document per each PooledFundControl
129 // If one should fail, that would be an exception to report and the remainder that does not fail should continue.
130 for (PooledFundControl pooledFundControl : pooledFundControlRecords) {
131 KualiDecimal totalAmount = KualiDecimal.ZERO;
132 // get the list of TransactionArchiveSecurity that has the same security id and document name
133 List<TransactionArchiveSecurity> transactionArchiveSecurityRecords = pooledFundControlTransactionsDao.getTransactionArchiveSecurityWithSecurityId(pooledFundControl, documentTypeNames, kemService.getCurrentDate());
134 if (transactionArchiveSecurityRecords != null) {
135 // get the total of security cost
136 for (TransactionArchiveSecurity transactionArchiveSecurity : transactionArchiveSecurityRecords) {
137 totalAmount = totalAmount.add(new KualiDecimal(transactionArchiveSecurity.getHoldingCost()));
138 }
139 }
140
141 // create a cash document per security id of pooled fund control
142 if (totalAmount.isPositive()) {
143 createECI(pooledFundControl, totalAmount, DocDescription, securityLineType, noRouteInd, ipInd);
144 } else if (totalAmount.isNegative()) {
145 totalAmount = totalAmount.negated();
146 createECDD(pooledFundControl, totalAmount, DocDescription, securityLineType, noRouteInd, ipInd);
147 }
148 }
149
150 return true;
151 }
152
153 /**
154 * Creates an ECI or an ECDD eDoc according to the total amount of gain/loss for transaction type EAD
155 */
156 protected boolean createCashDocumentForSaleGainLoss() {
157
158 List<String> documentTypeNames = new ArrayList<String>();
159 documentTypeNames.add(EndowConstants.DocumentTypeNames.ENDOWMENT_ASSET_DECREASE);
160 List<PooledFundControl> pooledFundControlRecords = (List<PooledFundControl>) pooledFundControlTransactionsDao.getAllPooledFundControlTransaction();
161 //if (pooledFundControlRecords == null) return;
162
163 // generate a cash document per each PooledFundControl
164 // If one should fail, that would be an exception to report and the remainder that does not fail should continue.
165 for (PooledFundControl pooledFundControl : pooledFundControlRecords) {
166 KualiDecimal totalAmount = KualiDecimal.ZERO;
167 // get the list of TransactionArchiveSecurity that has the same security id and document name
168 List<TransactionArchiveSecurity> transactionArchiveSecurityRecords = pooledFundControlTransactionsDao.getTransactionArchiveSecurityWithSecurityId(pooledFundControl, documentTypeNames, kemService.getCurrentDate());
169 // get the total of security long term and short term gain and loss
170 if (transactionArchiveSecurityRecords != null) {
171 for (TransactionArchiveSecurity transactionArchiveSecurity : transactionArchiveSecurityRecords) {
172 totalAmount = totalAmount.add(new KualiDecimal(transactionArchiveSecurity.getLongTermGainLoss()).add(new KualiDecimal(transactionArchiveSecurity.getShortTermGainLoss())));
173 }
174 }
175 // create a cash document per security id of pooled fund control
176 // If the pool is paying out gains, the net value of the pool must be reduced (ECDD).
177 // If it is 'recovering' (paying out) Losses, we must increase the value of the pool (ECI).
178 if (totalAmount.isPositive()) {
179 createECDD(pooledFundControl, totalAmount, EndowParameterKeyConstants.GAIN_LOSS_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE, EndowParameterKeyConstants.GAIN_LOSS_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.PRINCIPAL);
180 } else if (totalAmount.isNegative()) {
181 totalAmount = totalAmount.negated();
182 createECI(pooledFundControl, totalAmount, EndowParameterKeyConstants.GAIN_LOSS_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE, EndowParameterKeyConstants.GAIN_LOSS_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.PRINCIPAL);
183 }
184 }
185
186 return true;
187 }
188
189 /**
190 * Creates an ECI or an ECDD eDoc according to the total amount of income/principle cash for transaction type ECI and ECDD
191 */
192 protected boolean createCashDocumentForIncomeDistribution() {
193
194 List<String> documentTypeNames = new ArrayList<String>();
195 documentTypeNames.add(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE);
196 documentTypeNames.add(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE);
197 List<PooledFundControl> pooledFundControlRecords = (List<PooledFundControl>) pooledFundControlTransactionsDao.getAllPooledFundControlTransaction();
198 //if (pooledFundControlRecords == null) return;
199
200 // If one should fail, that would be an exception to report and the remainder that does not fail should continue.
201 for (PooledFundControl pooledFundControl : pooledFundControlRecords) {
202 KualiDecimal totalAmount = KualiDecimal.ZERO;
203 List<TransactionArchive> transactionArchiveRecords = pooledFundControlTransactionsDao.getTransactionArchiveWithSecurityAndDocNames(pooledFundControl, documentTypeNames, kemService.getCurrentDate());
204 if (transactionArchiveRecords != null) {
205 for (TransactionArchive transactionArchive : transactionArchiveRecords) {
206 totalAmount = totalAmount.add(new KualiDecimal(transactionArchive.getIncomeCashAmount())).add(new KualiDecimal(transactionArchive.getPrincipalCashAmount()));
207 }
208 }
209
210 // create a cash document per security id of pooled fund control
211 if (totalAmount.isPositive()) {
212 createECDD(pooledFundControl, totalAmount, EndowParameterKeyConstants.INCOME_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE, EndowParameterKeyConstants.INCOME_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.INCOME);
213 } else if (totalAmount.isNegative()) {
214 totalAmount = totalAmount.negated();
215 createECI(pooledFundControl, totalAmount, EndowParameterKeyConstants.INCOME_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE, EndowParameterKeyConstants.INCOME_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.INCOME);
216 }
217 }
218
219 return true;
220 }
221
222 /**
223 * Creates ECI
224 * @param pooledFundControl
225 * @param totalAmount
226 * @param paramDescriptionName
227 * @param securityLineType
228 * @param paramNoRouteInd
229 * @param incomePrincipalIndicator
230 * @return
231 */
232 protected boolean createECI(PooledFundControl pooledFundControl, KualiDecimal totalAmount, String paramDescriptionName, String securityLineTypeCode, String paramNoRouteInd, String incomePrincipalIndicator) {
233
234 LOG.info("Creating ECI ...");
235
236 boolean success = true;
237 CashIncreaseDocument cashIncreaseDocument = null;
238
239 // initialize CashIncreaseDocument
240 cashIncreaseDocument = initializeCashDocument(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE, EndowConstants.MAXMUM_NUMBER_OF_EDOC_INITIALIZATION_TRY);
241 if (ObjectUtils.isNull(cashIncreaseDocument)) {
242 return false;
243 }
244 cashIncreaseDocument.getDocumentHeader().setDocumentDescription(parameterService.getParameterValue(PooledFundControlTransactionsStep.class, paramDescriptionName));
245 cashIncreaseDocument.setTransactionSourceTypeCode(EndowConstants.TransactionSourceTypeCode.AUTOMATED);
246
247 // set security and add a transaction line
248 String etranTypeCode = getEtranTypeCode(pooledFundControl, paramDescriptionName);
249 populateECI(cashIncreaseDocument, pooledFundControl, totalAmount, securityLineTypeCode, incomePrincipalIndicator, etranTypeCode);
250
251 // if there are transaction lines, proceed.
252 if (cashIncreaseDocument.getNextTargetLineNumber() > 1) {
253 // validate and submit it. Since we have only one transaction line for each ECI, we do not need to validate the transaction line separately
254 GlobalVariables.clear();
255 if (validateECI(cashIncreaseDocument)) {
256 success = submitCashDocument(cashIncreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE, paramNoRouteInd);
257 if (success) {
258 writeTotalReport(cashIncreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE, incomePrincipalIndicator);
259 LOG.info("Submitted an ECI successfully: document# " + cashIncreaseDocument.getDocumentNumber());
260 }
261 } else {
262 success = false;
263 writeDocumentValdiationErrorReport(cashIncreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE);
264 LOG.error("createECI() Validation Error: Document# " + cashIncreaseDocument.getDocumentHeader().getDocumentNumber());
265 try {
266 documentService.saveDocument(cashIncreaseDocument);
267 } catch (WorkflowException wfe) {
268 LOG.error("createECI() Saving Error: Document# " + cashIncreaseDocument.getDocumentHeader().getDocumentNumber() + " : " + wfe.getMessage());
269 }
270 }
271 } else {
272 LOG.error("ECI was not sumitted because no transaction lines are found in document# " + cashIncreaseDocument.getDocumentNumber());
273 }
274
275 return success;
276 }
277
278 /**
279 * Creates ECDD
280 * @param pooledFundControl
281 * @param totalAmount
282 * @param paramDescriptionName
283 * @param securityLineType
284 * @param paramNoRouteInd
285 * @param incomePrincipalIndicator
286 * @return
287 */
288 protected boolean createECDD(PooledFundControl pooledFundControl, KualiDecimal totalAmount, String paramDescriptionName, String securityLineType, String paramNoRouteInd, String incomePrincipalIndicator) {
289
290 LOG.info("Creating ECDD ...");
291
292 boolean success = true;
293 CashDecreaseDocument cashDecreaseDocument = null;
294
295 // initialize CashDecreaseDocument
296 cashDecreaseDocument = initializeCashDocument(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE, EndowConstants.MAXMUM_NUMBER_OF_EDOC_INITIALIZATION_TRY);
297 if (ObjectUtils.isNull(cashDecreaseDocument)) {
298 return false;
299 }
300 cashDecreaseDocument.getDocumentHeader().setDocumentDescription(parameterService.getParameterValue(PooledFundControlTransactionsStep.class, paramDescriptionName));
301 cashDecreaseDocument.setTransactionSourceTypeCode(EndowConstants.TransactionSourceTypeCode.AUTOMATED);
302
303 // set security and a transaction line
304 String etranTypeCode = getEtranTypeCode(pooledFundControl, paramDescriptionName);
305 populateECDD(cashDecreaseDocument, pooledFundControl, totalAmount, securityLineType, incomePrincipalIndicator, etranTypeCode);
306
307 // if there are transaction lines, proceed.
308 if (cashDecreaseDocument.getNextSourceLineNumber() > 1) {
309 // validate and submit it. Since we have only one transaction line for each ECDD, we do not need to validate the transaction line separately
310 GlobalVariables.clear();
311 if (validateECDD(cashDecreaseDocument)) {
312 success = submitCashDocument(cashDecreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE, paramNoRouteInd);
313 if (success) {
314 writeTotalReport(cashDecreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE, incomePrincipalIndicator);
315 LOG.info("Submitted an ECDD successfully: document# " + cashDecreaseDocument.getDocumentNumber());
316 }
317 } else {
318 success = false;
319 writeDocumentValdiationErrorReport(cashDecreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE);
320 LOG.error("createECDD() Validation Error: Document# " + cashDecreaseDocument.getDocumentHeader().getDocumentNumber());
321 try {
322 documentService.saveDocument(cashDecreaseDocument);
323 } catch (WorkflowException wfe) {
324 LOG.error("createECDD() Saving Error: Document# " + cashDecreaseDocument.getDocumentHeader().getDocumentNumber() + " : " + wfe.getMessage());
325 }
326 }
327 } else {
328 LOG.error("ECDD was not sumitted because no transaction lines are found in document# " + cashDecreaseDocument.getDocumentNumber());
329 }
330
331 return success;
332 }
333
334 /**
335 * Populates security and transaction lines
336 * @param cashIncreaseDocument
337 * @param pooledFundControl
338 * @param totalAmount
339 * @param securityLineTypeCode
340 * @param transactionIPIndicatorCode
341 */
342 protected void populateECI(CashIncreaseDocument cashIncreaseDocument, PooledFundControl pooledFundControl, KualiDecimal totalAmount, String securityLineTypeCode, String transactionIPIndicatorCode, String etranTypeCode) {
343
344 // create a transaction line - needs only one for this batch job
345 EndowmentTargetTransactionLine endowmentTargetTransactionLine = new EndowmentTargetTransactionLine();
346 endowmentTargetTransactionLine.setTransactionLineNumber(new Integer(1));
347 endowmentTargetTransactionLine.setKemid(pooledFundControl.getFundKEMID());
348 endowmentTargetTransactionLine.setEtranCode(etranTypeCode);
349 endowmentTargetTransactionLine.setTransactionIPIndicatorCode(transactionIPIndicatorCode);
350 endowmentTargetTransactionLine.setTransactionAmount(totalAmount);
351
352 GlobalVariables.clear();
353 if (validateTransactionLine(cashIncreaseDocument, endowmentTargetTransactionLine, EndowConstants.NEW_TARGET_TRAN_LINE_PROPERTY_NAME)) {
354 // add a transaction line - only one for this batch
355 cashIncreaseDocument.addTargetTransactionLine(endowmentTargetTransactionLine);
356 // set security
357 cashIncreaseDocument.getTargetTransactionSecurity().setSecurityLineTypeCode(securityLineTypeCode);
358 cashIncreaseDocument.getTargetTransactionSecurity().setSecurityID(pooledFundControl.getPooledSecurityID());
359 cashIncreaseDocument.getTargetTransactionSecurity().setRegistrationCode(pooledFundControl.getFundRegistrationCode()); //
360
361 } else {
362 writeTransactionLineValidationErrorReport(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE, cashIncreaseDocument.getDocumentNumber(), cashIncreaseDocument.getTargetTransactionSecurity().getSecurityID(), pooledFundControl.getFundKEMID(), totalAmount);
363 }
364 }
365
366 /**
367 * Populates security and transaction lines
368 * @param cashDecreaseDocument
369 * @param pooledFundControl
370 * @param totalAmount
371 * @param securityLineTypeCode
372 * @param transactionIPIndicatorCode
373 */
374 protected void populateECDD(CashDecreaseDocument cashDecreaseDocument, PooledFundControl pooledFundControl, KualiDecimal totalAmount, String securityLineTypeCode, String transactionIPIndicatorCode, String etranTypeCode) {
375
376 // create a transaction line - needs only one for this batch job
377 EndowmentSourceTransactionLine endowmentSourceTransactionLine = new EndowmentSourceTransactionLine();
378 endowmentSourceTransactionLine.setTransactionLineNumber(new Integer(1));
379 endowmentSourceTransactionLine.setKemid(pooledFundControl.getFundKEMID());
380 endowmentSourceTransactionLine.setEtranCode(etranTypeCode);
381 endowmentSourceTransactionLine.setTransactionIPIndicatorCode(transactionIPIndicatorCode);
382 //endowmentSourceTransactionLine.setTransactionLineTypeCode(securityLineTypeCode);
383 endowmentSourceTransactionLine.setTransactionAmount(totalAmount);
384
385 GlobalVariables.clear();
386 if (validateTransactionLine(cashDecreaseDocument, endowmentSourceTransactionLine, EndowConstants.NEW_SOURCE_TRAN_LINE_PROPERTY_NAME)) {
387 // add transaction line
388 cashDecreaseDocument.addSourceTransactionLine(endowmentSourceTransactionLine);
389 // set security
390 cashDecreaseDocument.getSourceTransactionSecurity().setSecurityLineTypeCode(securityLineTypeCode);
391 cashDecreaseDocument.getSourceTransactionSecurity().setSecurityID(pooledFundControl.getPooledSecurityID());
392 cashDecreaseDocument.getSourceTransactionSecurity().setRegistrationCode(pooledFundControl.getFundRegistrationCode());
393 } else {
394 writeTransactionLineValidationErrorReport(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE, cashDecreaseDocument.getDocumentNumber(), cashDecreaseDocument.getSourceTransactionSecurity().getSecurityID(), pooledFundControl.getFundKEMID(), totalAmount);
395 }
396 }
397
398 /**
399 * Initialize a cash document. If fails, try as many times as EndowConstants.MAXMUM_NUMBER_OF_EDOC_INITILIZATION_TRY.
400 * @param <C>
401 * @param documentType
402 * @param counter
403 * @return
404 */
405 protected <C extends EndowmentSecurityDetailsDocumentBase> C initializeCashDocument(String documentType, int counter) {
406
407 C cashDocument = null;
408
409 if (counter > 0) {
410 try {
411 cashDocument = (C) getDocumentService().getNewDocument(SpringContext.getBean(TransactionalDocumentDictionaryService.class).getDocumentClassByName(documentType));
412 } catch (WorkflowException e) {
413 LOG.error( (EndowConstants.MAXMUM_NUMBER_OF_EDOC_INITIALIZATION_TRY - counter + 1) + ": The creation of " + documentType + " failed. Tyring it again ...");
414 cashDocument = (C) initializeCashDocument(documentType, --counter);
415 }
416 }
417
418 return cashDocument;
419 }
420
421 /**
422 * Submits the document
423 * @param <T>
424 * @param cashDocument
425 * @param documentType
426 * @param paramNoRouteInd
427 * @return
428 */
429 protected <T extends EndowmentSecurityDetailsDocumentBase> boolean submitCashDocument(T cashDocument, String documentType, String paramNoRouteInd) {
430
431 boolean success = false;
432
433 try {
434 cashDocument.setNoRouteIndicator(isNoRoute(paramNoRouteInd));
435 documentService.routeDocument(cashDocument, "Submitted by the batch job", null);
436 success = true;
437 } catch (WorkflowException wfe) {
438 writeSubmissionErrorReport(cashDocument, documentType, wfe.getMessage());
439 LOG.error("submitCashDocument() Routing Error: Document# " + cashDocument.getDocumentHeader().getDocumentNumber() + " : " + wfe.getMessage());
440 try {
441 documentService.saveDocument(cashDocument);
442 } catch (WorkflowException wfe2) {
443 LOG.error("submitCashDocument() Saving Error: Document# " + cashDocument.getDocumentHeader().getDocumentNumber() + " : " + wfe2.getMessage());
444 }
445 } catch (Exception e) { // in case
446 writeSubmissionErrorReport(cashDocument, documentType, e.getMessage());
447 LOG.error("submitCashDocument() Runtime Error: Document# " + cashDocument.getDocumentHeader().getDocumentNumber() + " : " + e.getMessage());
448 try {
449 documentService.saveDocument(cashDocument);
450 } catch (WorkflowException wfe3) {
451 LOG.error("submitCashDocument() Saving Error: Document# " + cashDocument.getDocumentHeader().getDocumentNumber() + " : " + wfe3.getMessage());
452 }
453 }
454
455 return success;
456 }
457
458 /**
459 * Validate Cash Transaction line
460 * @param <C>
461 * @param <T>
462 * @param cashDocument
463 * @param endowmentTransactionLine
464 * @param trnsactionPropertyName
465 * @return
466 */
467 protected <C extends EndowmentSecurityDetailsDocumentBase, T extends EndowmentTransactionLineBase> boolean validateTransactionLine(C cashDocument, T endowmentTransactionLine, String trnsactionPropertyName) {
468 return kualiRuleService.applyRules(new AddTransactionLineEvent(trnsactionPropertyName, cashDocument, endowmentTransactionLine));
469 }
470
471 /**
472 * validate the ECI business rules
473 * @param cashIncreaseDocument
474 * @return boolean
475 */
476 protected boolean validateECI(CashIncreaseDocument cashIncreaseDocument) {
477 return kualiRuleService.applyRules(new RouteDocumentEvent(cashIncreaseDocument));
478 }
479
480 /**
481 * validate the ECDD business rules
482 * @param cashDecreaseDocument
483 * @return boolean
484 */
485 protected boolean validateECDD(CashDecreaseDocument cashDecreaseDocument) {
486 return kualiRuleService.applyRules(new RouteDocumentEvent(cashDecreaseDocument));
487 }
488
489 /**
490 * Gets the transaction type code based on the document component type
491 * @param pooledFundControl
492 * @param docComponentType
493 * @return
494 */
495 protected String getEtranTypeCode(PooledFundControl pooledFundControl, String docComponentType) {
496 String etranTypeCode = "";
497 if (docComponentType.equalsIgnoreCase(EndowParameterKeyConstants.PURCHASE_DESCRIPTION)) {
498 etranTypeCode = pooledFundControl.getFundAssetPurchaseOffsetTranCode();
499 } else if (docComponentType.equalsIgnoreCase(EndowParameterKeyConstants.SALE_DESCRIPTION)) {
500 etranTypeCode = pooledFundControl.getFundAssetSaleOffsetTranCode();
501 } else if (docComponentType.equalsIgnoreCase(EndowParameterKeyConstants.GAIN_LOSS_DESCRIPTION)) {
502 etranTypeCode = pooledFundControl.getFundSaleGainLossOffsetTranCode();
503 } else if (docComponentType.equalsIgnoreCase(EndowParameterKeyConstants.INCOME_DESCRIPTION)) {
504 etranTypeCode = pooledFundControl.getFundCashDepositOffsetTranCode();
505 }
506
507 return etranTypeCode;
508 }
509
510 /**
511 * check if it is no route
512 * @return boolean
513 */
514 public boolean isNoRoute(String paramNoRouteInd) {
515 return parameterService.getIndicatorParameter(PooledFundControlTransactionsStep.class, paramNoRouteInd);
516 }
517
518 /**
519 * Writes the total report
520 * @param <C>
521 * @param cashDocument
522 * @param documentType
523 */
524 protected <C extends EndowmentSecurityDetailsDocumentBase> void writeTotalReport(C cashDocument, String documentType, String incomePrincipalIndicator) {
525 totalReportLine.setDocumentType(documentType);
526 totalReportLine.setDocumentId(cashDocument.getDocumentNumber());
527 totalReportLine.setSecurityId(cashDocument.getTargetTransactionSecurity().getSecurityID());
528 if (incomePrincipalIndicator.equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) {
529 totalReportLine.setPrincipalAmount(cashDocument.getTargetPrincipalTotal().add(cashDocument.getSourcePrincipalTotal()));
530 totalReportLine.setPrincipalUnits(cashDocument.getTargetPrincipalTotalUnits().add(cashDocument.getSourcePrincipalTotalUnits()));
531 } else if (incomePrincipalIndicator.equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) {
532 totalReportLine.setIncomeAmount(cashDocument.getTargetIncomeTotal().add(cashDocument.getSourceIncomeTotal()));
533 totalReportLine.setIncomeUnits(cashDocument.getTargetIncomeTotalUnits().add(cashDocument.getSourceIncomeTotalUnits()));
534 }
535 if (cashDocument.getNextTargetLineNumber() > 1) {
536 totalReportLine.setTotalNumberOfTransactionLines(cashDocument.getNextTargetLineNumber() - 1);
537 } else {
538 totalReportLine.setTotalNumberOfTransactionLines(cashDocument.getNextSourceLineNumber() - 1);
539 }
540 pooledFundControlTransactionsTotalReportWriterService.writeTableRow(totalReportLine);
541
542 // reset for the next total report
543 totalReportLine.setTotalNumberOfTransactionLines(0);
544 totalReportLine.setPrincipalAmount(KualiDecimal.ZERO);
545 totalReportLine.setPrincipalUnits(KualiDecimal.ZERO);
546 totalReportLine.setIncomeAmount(KualiDecimal.ZERO);
547 totalReportLine.setIncomeUnits(KualiDecimal.ZERO);
548 }
549
550 /**
551 * Writes transaction line validation errors per each
552 * @param documentType
553 * @param kemid
554 * @param transactionAmount
555 */
556 protected void writeTransactionLineValidationErrorReport(String documentType, String documentId, String securityId, String kemid, KualiDecimal transactionAmount) {
557 exceptionReportLine.setDocumentType(documentType);
558 exceptionReportLine.setDocumentId(documentId);
559 exceptionReportLine.setSecurityId(securityId);
560 exceptionReportLine.setKemid(kemid);
561 exceptionReportLine.setIncomeAmount(transactionAmount);
562 pooledFundControlTransactionsExceptionReportWriterService.writeTableRow(exceptionReportLine);
563
564 List<String> errorMessages = GloabalVariablesExtractHelper.extractGlobalVariableErrors();
565 for (String errorMessage : errorMessages) {
566 pooledFundControlTransactionsExceptionReportWriterService.writeFormattedMessageLine("Reason: %s", errorMessage);
567 }
568 pooledFundControlTransactionsExceptionReportWriterService.writeNewLines(1);
569 }
570
571 /**
572 * Writes document validation errors
573 * @param <T>
574 * @param cashDocument
575 * @param documentType
576 */
577 protected <T extends EndowmentSecurityDetailsDocumentBase> void writeDocumentValdiationErrorReport(T cashDocument, String documentType) {
578 exceptionReportLine.setDocumentType(documentType);
579 exceptionReportLine.setDocumentId(cashDocument.getDocumentNumber());
580 exceptionReportLine.setSecurityId(cashDocument.getTargetTransactionSecurity().getSecurityID());
581 exceptionReportLine.setIncomeAmount(cashDocument.getTargetIncomeTotal());
582 pooledFundControlTransactionsExceptionReportWriterService.writeTableRow(exceptionReportLine);
583
584 List<String> errorMessages = GloabalVariablesExtractHelper.extractGlobalVariableErrors();
585 for (String errorMessage : errorMessages) {
586 pooledFundControlTransactionsExceptionReportWriterService.writeFormattedMessageLine("Reason: %s", errorMessage);
587 }
588 pooledFundControlTransactionsExceptionReportWriterService.writeNewLines(1);
589 }
590
591 /**
592 * Writes the submission errors
593 * @param <T>
594 * @param cashDocument
595 * @param documentType
596 */
597 protected <T extends EndowmentSecurityDetailsDocumentBase> void writeSubmissionErrorReport(T cashDocument, String documentType, String errorMessage) {
598 exceptionReportLine.setDocumentType(documentType);
599 exceptionReportLine.setDocumentId(cashDocument.getDocumentNumber());
600 exceptionReportLine.setSecurityId(cashDocument.getTargetTransactionSecurity().getSecurityID());
601 exceptionReportLine.setIncomeAmount(cashDocument.getTargetIncomeTotal());
602 pooledFundControlTransactionsExceptionReportWriterService.writeTableRow(exceptionReportLine);
603 pooledFundControlTransactionsExceptionReportWriterService.writeFormattedMessageLine("Reason: %s", errorMessage);
604 pooledFundControlTransactionsExceptionReportWriterService.writeNewLines(1);
605 }
606
607 /**
608 * Initializes reports
609 */
610 protected void initializeReports() {
611
612 // initialize totalReportLine
613 this.totalReportLine = new TransactionDocumentTotalReportLine();
614 pooledFundControlTransactionsTotalReportWriterService.writeSubTitle("<pooledFundControlTransactionsJob> Totals Processed");
615 pooledFundControlTransactionsTotalReportWriterService.writeNewLines(1);
616 pooledFundControlTransactionsTotalReportWriterService.writeTableHeader(totalReportLine);
617
618 // initialize exceptionReportLine
619 this.exceptionReportLine = new TransactionDocumentExceptionReportLine();
620 pooledFundControlTransactionsExceptionReportWriterService.writeSubTitle("<pooledFundControlTransactionsJob> Exception Report");
621 pooledFundControlTransactionsExceptionReportWriterService.writeNewLines(1);
622 pooledFundControlTransactionsExceptionReportWriterService.writeTableHeader(exceptionReportLine);
623 }
624
625 /**
626 * Sets the businessObjectService attribute value.
627 * @param businessObjectService The businessObjectService to set.
628 */
629 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
630 this.businessObjectService = businessObjectService;
631 }
632
633 /**
634 * Sets the pooledFundControlTransactionsDaoOjb attribute value.
635 * @param pooledFundControlTransactionsDaoOjb The pooledFundControlTransactionsDaoOjb to set.
636 */
637 public void setPooledFundControlTransactionsDao(PooledFundControlTransactionsDao pooledFundControlTransactionsDao) {
638 this.pooledFundControlTransactionsDao = pooledFundControlTransactionsDao;
639 }
640
641 /**
642 * Gets the documentService attribute.
643 * @return Returns the documentService.
644 */
645 public DocumentService getDocumentService() {
646 return documentService;
647 }
648
649 /**
650 * Sets the documentService attribute value.
651 * @param documentService The documentService to set.
652 */
653 public void setDocumentService(DocumentService documentService) {
654 this.documentService = documentService;
655 }
656
657 /**
658 * Sets the kualiRuleService attribute value.
659 * @param kualiRuleService The kualiRuleService to set.
660 */
661 public void setKualiRuleService(KualiRuleService kualiRuleService) {
662 this.kualiRuleService = kualiRuleService;
663 }
664
665 /**
666 * Sets the parameterService attribute value.
667 * @param parameterService The parameterService to set.
668 */
669 public void setParameterService(ParameterService parameterService) {
670 this.parameterService = parameterService;
671 }
672
673 /**
674 * Sets the pooledFundControlTransactionsExceptionReportWriterService attribute value.
675 * @param pooledFundControlTransactionsExceptionReportWriterService The pooledFundControlTransactionsExceptionReportWriterService to set.
676 */
677 public void setPooledFundControlTransactionsExceptionReportWriterService(ReportWriterService pooledFundControlTransactionsExceptionReportWriterService) {
678 this.pooledFundControlTransactionsExceptionReportWriterService = pooledFundControlTransactionsExceptionReportWriterService;
679 }
680
681 /**
682 * Sets the pooledFundControlTransactionsTotalReportWriterService attribute value.
683 * @param pooledFundControlTransactionsTotalReportWriterService The pooledFundControlTransactionsTotalReportWriterService to set.
684 */
685 public void setPooledFundControlTransactionsTotalReportWriterService(ReportWriterService pooledFundControlTransactionsTotalReportWriterService) {
686 this.pooledFundControlTransactionsTotalReportWriterService = pooledFundControlTransactionsTotalReportWriterService;
687 }
688
689 /**
690 * Sets the kemService attribute value.
691 * @param kemService The kemService to set.
692 */
693 public void setKemService(KEMService kemService) {
694 this.kemService = kemService;
695 }
696
697 }