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 static org.kuali.kfs.module.endow.EndowConstants.NEW_SOURCE_TRAN_LINE_PROPERTY_NAME;
019 import static org.kuali.kfs.module.endow.EndowConstants.NEW_TARGET_TRAN_LINE_PROPERTY_NAME;
020
021 import java.math.BigDecimal;
022 import java.math.BigInteger;
023 import java.math.RoundingMode;
024 import java.util.ArrayList;
025 import java.util.Collection;
026 import java.util.HashMap;
027 import java.util.List;
028 import java.util.Map;
029
030 import org.kuali.kfs.module.endow.EndowConstants;
031 import org.kuali.kfs.module.endow.EndowParameterKeyConstants;
032 import org.kuali.kfs.module.endow.EndowPropertyConstants;
033 import org.kuali.kfs.module.endow.batch.CreateAutomatedCashInvestmentTransactionsStep;
034 import org.kuali.kfs.module.endow.batch.reporter.ReportDocumentStatistics;
035 import org.kuali.kfs.module.endow.batch.service.CreateAutomatedCashInvestmentTransactionsService;
036 import org.kuali.kfs.module.endow.businessobject.AutomatedCashInvestmentModel;
037 import org.kuali.kfs.module.endow.businessobject.EndowmentExceptionReportHeader;
038 import org.kuali.kfs.module.endow.businessobject.EndowmentSourceTransactionLine;
039 import org.kuali.kfs.module.endow.businessobject.EndowmentSourceTransactionSecurity;
040 import org.kuali.kfs.module.endow.businessobject.EndowmentTargetTransactionLine;
041 import org.kuali.kfs.module.endow.businessobject.EndowmentTargetTransactionSecurity;
042 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine;
043 import org.kuali.kfs.module.endow.businessobject.HoldingTaxLot;
044 import org.kuali.kfs.module.endow.businessobject.KEMID;
045 import org.kuali.kfs.module.endow.businessobject.KemidCurrentCash;
046 import org.kuali.kfs.module.endow.businessobject.Security;
047 import org.kuali.kfs.module.endow.businessobject.TransactionDocumentExceptionReportLine;
048 import org.kuali.kfs.module.endow.businessobject.TransactionDocumentTotalReportLine;
049 import org.kuali.kfs.module.endow.dataaccess.AutomatedCashInvestmentModelDao;
050 import org.kuali.kfs.module.endow.document.AssetDecreaseDocument;
051 import org.kuali.kfs.module.endow.document.AssetIncreaseDocument;
052 import org.kuali.kfs.module.endow.document.EndowmentTaxLotLinesDocumentBase;
053 import org.kuali.kfs.module.endow.document.service.KEMIDService;
054 import org.kuali.kfs.module.endow.document.service.KEMService;
055 import org.kuali.kfs.module.endow.document.service.SecurityService;
056 import org.kuali.kfs.module.endow.document.service.UpdateAssetDecreaseDocumentTaxLotsService;
057 import org.kuali.kfs.module.endow.document.service.UpdateAssetIncreaseDocumentTaxLotsService;
058 import org.kuali.kfs.module.endow.document.validation.event.AddTransactionLineEvent;
059 import org.kuali.kfs.module.endow.util.GloabalVariablesExtractHelper;
060 import org.kuali.kfs.sys.service.ReportWriterService;
061 import org.kuali.rice.kew.exception.WorkflowException;
062 import org.kuali.rice.kns.bo.DocumentHeader;
063 import org.kuali.rice.kns.rule.event.RouteDocumentEvent;
064 import org.kuali.rice.kns.service.BusinessObjectService;
065 import org.kuali.rice.kns.service.DataDictionaryService;
066 import org.kuali.rice.kns.service.DocumentService;
067 import org.kuali.rice.kns.service.KualiConfigurationService;
068 import org.kuali.rice.kns.service.KualiRuleService;
069 import org.kuali.rice.kns.service.ParameterService;
070 import org.kuali.rice.kns.util.KualiDecimal;
071 import org.springframework.transaction.annotation.Transactional;
072
073 @Transactional
074 public class CreateAutomatedCashInvestmentTransactionsServiceImpl implements CreateAutomatedCashInvestmentTransactionsService {
075
076 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CreateAutomatedCashInvestmentTransactionsServiceImpl.class);
077 private static final String SUBMIT_DOCUMENT_DESCRIPTION = "Created by Create Automated Cash Investment Transactions Batch Process.";
078
079 private Map<String, ReportDocumentStatistics> statistics = new HashMap<String, ReportDocumentStatistics>();
080
081 private ReportWriterService createAutomatedCashInvestmentExceptionReportWriterService;
082 private ReportWriterService createAutomatedCashInvestmentProcessedReportWriterService;
083 private UpdateAssetIncreaseDocumentTaxLotsService updateEaiTaxLotService;
084 private UpdateAssetDecreaseDocumentTaxLotsService updateEadTaxLotService;
085 private AutomatedCashInvestmentModelDao automatedCashInvestmentModelDao;
086 private BusinessObjectService businessObjectService;
087 private DataDictionaryService dataDictionaryService;
088 private KualiConfigurationService configService;
089 private KualiRuleService kualiRuleService;
090 private ParameterService parameterService;
091 private DocumentService documentService;
092 private SecurityService securityService;
093 private KEMIDService kemidService;
094 private KEMService kemService;
095
096 /**
097 * @see org.kuali.kfs.module.endow.batch.service.CreateAutomatedCashInvestmentTransactionsService#createACITransactions()
098 */
099 public boolean createAciTransactions() {
100
101 LOG.info("Starting \"Create Automated Cash Investments Transactions\" batch job...");
102 writeHeaders();
103
104 for (AutomatedCashInvestmentModel aciModel : getAutomatedCashInvestmentModelMatchingCurrentDate()) {
105
106 List<KEMID> principleKemids = new ArrayList<KEMID>(kemidService.getByPrincipleAciId(aciModel.getAciModelID()));
107 List<KEMID> incomeKemids = new ArrayList<KEMID>(kemidService.getByIncomeAciId(aciModel.getAciModelID()));
108
109 // Process for increase documents.
110 processAssetIncreaseDocs(principleKemids, aciModel, false);
111 processAssetIncreaseDocs(incomeKemids, aciModel, true);
112
113 // Process for decrease documents.
114 processAssetDecreaseDocs(principleKemids, aciModel, false);
115 processAssetDecreaseDocs(incomeKemids, aciModel, true);
116 }
117
118 writeStatistics();
119 LOG.info("Finished \"Create Automated Cash Investments Transactions\" batch job!");
120
121 return true;
122 }
123
124 /**
125 * Process all the asset increase documents for income and principle types.
126 *
127 * @param kemid
128 * @param aciModel
129 */
130 protected void processAssetIncreaseDocs(List<KEMID> kemids, AutomatedCashInvestmentModel aciModel, boolean isIncome) {
131
132 // An asset increase document for each of the pooled investments.
133 AssetIncreaseDocument assetIncreaseDoc1 = null;
134 AssetIncreaseDocument assetIncreaseDoc2 = null;
135 AssetIncreaseDocument assetIncreaseDoc3 = null;
136 AssetIncreaseDocument assetIncreaseDoc4 = null;
137
138 // Get the percentages. We'll only process investments with
139 // percentages greater than zero.
140 BigDecimal inv1Percent = aciModel.getInvestment1Percent();
141 BigDecimal inv2Percent = aciModel.getInvestment2Percent();
142 BigDecimal inv3Percent = aciModel.getInvestment3Percent();
143 BigDecimal inv4Percent = aciModel.getInvestment4Percent();
144
145 for (int i = 0; i < kemids.size(); i++) {
146
147 // Get the KEMID at the current index.
148 KEMID kemid = kemids.get(i);
149
150 // Get the principle/income cash equivalent.
151 BigDecimal cashEquivalent = getCashEquivalent(kemid, isIncome);
152
153 // Check if the cash equivalent is greater than zero.
154 if (cashEquivalent.compareTo(BigDecimal.ZERO) > 0) {
155
156 assetIncreaseDoc1 = processCashInvestmentForAssetIncrease(aciModel, isIncome, assetIncreaseDoc1, inv1Percent, i, kemid, cashEquivalent, 1);
157 assetIncreaseDoc2 = processCashInvestmentForAssetIncrease(aciModel, isIncome, assetIncreaseDoc2, inv2Percent, i, kemid, cashEquivalent, 2);
158 assetIncreaseDoc3 = processCashInvestmentForAssetIncrease(aciModel, isIncome, assetIncreaseDoc3, inv3Percent, i, kemid, cashEquivalent, 3);
159 assetIncreaseDoc4 = processCashInvestmentForAssetIncrease(aciModel, isIncome, assetIncreaseDoc4, inv4Percent, i, kemid, cashEquivalent, 4);
160 }
161 }
162
163 // Route documents that may still need routing.
164 performCleanUpForAssetIncrease(isIncome, assetIncreaseDoc1);
165 performCleanUpForAssetIncrease(isIncome, assetIncreaseDoc2);
166 performCleanUpForAssetIncrease(isIncome, assetIncreaseDoc3);
167 performCleanUpForAssetIncrease(isIncome, assetIncreaseDoc4);
168 }
169
170 /**
171 * Process all the asset decrease documents for income and principle types.
172 *
173 * @param kemids
174 * @param aciModel
175 * @param isIncome
176 */
177 protected void processAssetDecreaseDocs(List<KEMID> kemids, AutomatedCashInvestmentModel aciModel, boolean isIncome) {
178
179 // An asset increase document for each of the pooled investments.
180 AssetDecreaseDocument assetDecreaseDoc1 = null;
181 AssetDecreaseDocument assetDecreaseDoc2 = null;
182 AssetDecreaseDocument assetDecreaseDoc3 = null;
183 AssetDecreaseDocument assetDecreaseDoc4 = null;
184
185 // Get the percentages. We'll only process investments with
186 // percentages greater than zero.
187 BigDecimal inv1Percent = aciModel.getInvestment1Percent();
188 BigDecimal inv2Percent = aciModel.getInvestment2Percent();
189 BigDecimal inv3Percent = aciModel.getInvestment3Percent();
190 BigDecimal inv4Percent = aciModel.getInvestment4Percent();
191
192 for (int i = 0; i < kemids.size(); i++) {
193
194 // Get the KEMID at the current index.
195 KEMID kemid = kemids.get(i);
196
197 // Get the principle/income cash equivalent.
198 BigDecimal cashEquivalent = getCashEquivalent(kemid, isIncome);
199
200 // Check if the cash equivalent is less than zero.
201 if (cashEquivalent.compareTo(BigDecimal.ZERO) < 0) {
202
203 assetDecreaseDoc1 = processCashInvestmentForAssetDecrease(aciModel, isIncome, assetDecreaseDoc1, inv1Percent, i, kemid, cashEquivalent, 1);
204 assetDecreaseDoc2 = processCashInvestmentForAssetDecrease(aciModel, isIncome, assetDecreaseDoc2, inv2Percent, i, kemid, cashEquivalent, 2);
205 assetDecreaseDoc3 = processCashInvestmentForAssetDecrease(aciModel, isIncome, assetDecreaseDoc3, inv3Percent, i, kemid, cashEquivalent, 3);
206 assetDecreaseDoc4 = processCashInvestmentForAssetDecrease(aciModel, isIncome, assetDecreaseDoc4, inv4Percent, i, kemid, cashEquivalent, 4);
207 }
208 }
209
210 // Route documents that may still need routing.
211 performCleanUpForAssetDecrease(isIncome, assetDecreaseDoc1);
212 performCleanUpForAssetDecrease(isIncome, assetDecreaseDoc2);
213 performCleanUpForAssetDecrease(isIncome, assetDecreaseDoc3);
214 performCleanUpForAssetDecrease(isIncome, assetDecreaseDoc4);
215 }
216
217 /**
218 * Verify that we don't need to do any clean-up. There could still be some let over transaction lines, less than the max amount
219 * that need to still be processed on the current eDoc.
220 *
221 * @param isIncome
222 * @param assetIncreaseDoc
223 */
224 protected boolean performCleanUpForAssetDecrease(boolean isIncome, AssetDecreaseDocument assetDecreaseDoc) {
225
226 boolean success = false;
227
228 if (assetDecreaseDoc != null && !assetDecreaseDoc.getSourceTransactionLines().isEmpty()) {
229 // Validate and route the document.
230 success = routeAssetDecreaseDocument(assetDecreaseDoc, isIncome);
231 }
232
233 return success;
234 }
235
236 /**
237 * Verify that we don't need to do any clean-up. There could still be some let over transaction lines, less than the max amount
238 * that need to still be processed on the current eDoc.
239 *
240 * @param isIncome
241 * @param assetIncreaseDoc
242 */
243 protected boolean performCleanUpForAssetIncrease(boolean isIncome, AssetIncreaseDocument assetIncreaseDoc) {
244
245 boolean success = false;
246
247 if (assetIncreaseDoc != null && !assetIncreaseDoc.getTargetTransactionLines().isEmpty()) {
248 // Validate and route the document.
249 success = routeAssetIncreaseDocument(assetIncreaseDoc, isIncome);
250 }
251
252 return success;
253 }
254
255 /**
256 * Helper method for processing the cash investments for asset decrease documents.
257 *
258 * @param aciModel
259 * @param isIncome
260 * @param assetDecreaseDoc
261 * @param invPercent
262 * @param i
263 * @param kemid
264 * @param cashEquivalent
265 * @param inv
266 * @return
267 */
268 private AssetDecreaseDocument processCashInvestmentForAssetDecrease(AutomatedCashInvestmentModel aciModel, boolean isIncome, AssetDecreaseDocument assetDecreaseDoc, BigDecimal invPercent, int i, KEMID kemid, BigDecimal cashEquivalent, int inv) {
269
270 if (invPercent != null && invPercent.compareTo(BigDecimal.ZERO) != 0) {
271 String invRegistrationCode = getInvRegistrationCode(aciModel, inv);
272 String invSecurityId = getInvSecurityId(aciModel, inv);
273
274 // Initialize the asset decrease doc if null.
275 if (assetDecreaseDoc == null) {
276 assetDecreaseDoc = createAssetDecrease(invSecurityId, invRegistrationCode);
277 }
278
279 // Create, validate, and add the transaction line to the eDoc.
280 addTransactionLineForAssetDecrease(assetDecreaseDoc, aciModel, kemid.getKemid(), cashEquivalent, inv, isIncome);
281
282 // Check to see if we've reached our max number of transaction lines
283 // per eDoc. If so, validate, and submit the current eDoc and start
284 // another eDoc.
285 if ((i != 0) && (i % getMaxNumberOfTransactionLines() == 0)) {
286 // Validate and route the document.
287 routeAssetDecreaseDocument(assetDecreaseDoc, isIncome);
288 assetDecreaseDoc = createAssetDecrease(invSecurityId, invRegistrationCode);
289 }
290 }
291
292 return assetDecreaseDoc;
293 }
294
295 /**
296 * Helper method for processing the cash investments for asset increase documents.
297 *
298 * @param aciModel
299 * @param isIncome
300 * @param assetIncreaseDoc
301 * @param invPercent
302 * @param i
303 * @param kemid
304 * @param cashEquivalent
305 * @param inv
306 * @return
307 */
308 private AssetIncreaseDocument processCashInvestmentForAssetIncrease(AutomatedCashInvestmentModel aciModel, boolean isIncome, AssetIncreaseDocument assetIncreaseDoc, BigDecimal invPercent, int i, KEMID kemid, BigDecimal cashEquivalent, int inv) {
309
310 if (invPercent != null && invPercent.compareTo(BigDecimal.ZERO) != 0) {
311 String invRegistrationCode = getInvRegistrationCode(aciModel, inv);
312 String invSecurityId = getInvSecurityId(aciModel, inv);
313
314 // Initialize the asset increase doc if null.
315 if (assetIncreaseDoc == null) {
316 assetIncreaseDoc = createAssetIncrease(invSecurityId, invRegistrationCode);
317 }
318
319 // Create, validate, and add the transaction line to the eDoc.
320 addTransactionLineForAssetIncrease(assetIncreaseDoc, aciModel, kemid.getKemid(), cashEquivalent, inv, isIncome);
321
322 // Check to see if we've reached our max number of transaction lines
323 // per eDoc. If so, validate, and submit the current eDoc and start
324 // another eDoc.
325 if ((i != 0) && (i % getMaxNumberOfTransactionLines() == 0)) {
326 // Validate and route the document.
327 routeAssetIncreaseDocument(assetIncreaseDoc, isIncome);
328 assetIncreaseDoc = createAssetIncrease(invSecurityId, invRegistrationCode);
329 }
330 }
331
332 return assetIncreaseDoc;
333 }
334
335 /**
336 * Validates the asset decrease document and routes it.
337 *
338 * @param assetDecreaseDoc
339 * @param isIncome
340 * @return
341 */
342 protected boolean routeAssetDecreaseDocument(AssetDecreaseDocument assetDecreaseDoc, boolean isIncome) {
343
344 boolean success = false;
345
346 // Perform validation on the document.
347 boolean rulesPassed = kualiRuleService.applyRules(new RouteDocumentEvent(assetDecreaseDoc));
348
349 // If the document passed validations, route it accordingly.
350 if (rulesPassed) {
351 boolean noRouteIndicator = getNoRouteIndicator(true);
352 try {
353 assetDecreaseDoc.setNoRouteIndicator(noRouteIndicator);
354 documentService.routeDocument(assetDecreaseDoc, SUBMIT_DOCUMENT_DESCRIPTION, null);
355 writeProcessedTableRowAssetDecrease(assetDecreaseDoc, isIncome);
356 success = true;
357 }
358 catch (WorkflowException ex) {
359 writeExceptionTableReason(assetDecreaseDoc.getDocumentNumber() + " - " + ex.getLocalizedMessage());
360 LOG.error(ex.getLocalizedMessage());
361 }
362 }
363 else {
364 // Write the errors to the exception file.
365 List<String> errorMessages = GloabalVariablesExtractHelper.extractGlobalVariableErrors();
366 for (String errorMessage : errorMessages) {
367 writeExceptionTableReason(errorMessage);
368 }
369 // Try to save the document if it fails validation.
370 try {
371 documentService.saveDocument(assetDecreaseDoc);
372 }
373 catch (WorkflowException we) {
374 writeExceptionTableReason(assetDecreaseDoc.getDocumentNumber() + " - " + we.getLocalizedMessage());
375 LOG.error(we.getLocalizedMessage());
376 }
377 }
378
379 return success;
380 }
381
382 /**
383 * Validates the asset increase document and routes it.
384 *
385 * @param assetIncreaseDoc
386 * @param isIncome
387 * @return
388 */
389 protected boolean routeAssetIncreaseDocument(AssetIncreaseDocument assetIncreaseDoc, boolean isIncome) {
390
391 boolean success = false;
392
393 // Perform validation on the document.
394 boolean rulesPassed = kualiRuleService.applyRules(new RouteDocumentEvent(assetIncreaseDoc));
395
396 // If the document passed validations, route it accordingly.
397 if (rulesPassed) {
398 boolean noRouteIndicator = getNoRouteIndicator(false);
399 try {
400 assetIncreaseDoc.setNoRouteIndicator(noRouteIndicator);
401 documentService.routeDocument(assetIncreaseDoc, SUBMIT_DOCUMENT_DESCRIPTION, null);
402 writeProcessedTableRowAssetIncrease(assetIncreaseDoc, isIncome);
403 success = true;
404 }
405 catch (WorkflowException we) {
406 writeExceptionTableReason(assetIncreaseDoc.getDocumentNumber() + " - " + we.getLocalizedMessage());
407 LOG.error(we.getLocalizedMessage());
408 }
409 }
410 else {
411 // Write the errors to the exception file.
412 List<String> errorMessages = GloabalVariablesExtractHelper.extractGlobalVariableErrors();
413 for (String errorMessage : errorMessages) {
414 writeExceptionTableReason(errorMessage);
415 }
416 // Try to save the document if it fails validation.
417 try {
418 documentService.saveDocument(assetIncreaseDoc);
419 }
420 catch (WorkflowException we) {
421 writeExceptionTableReason(assetIncreaseDoc.getDocumentNumber() + " - " + we.getLocalizedMessage());
422 LOG.error(we.getLocalizedMessage());
423 }
424 }
425
426 return success;
427 }
428
429 /**
430 * Creates a new transaction line, validates, and adds it to the asset decrease document.
431 *
432 * @param assetDecreaseDoc
433 * @param aciModel
434 * @param kemid
435 * @param cashEquivalent
436 * @param inv
437 * @param isIncome
438 */
439 private void addTransactionLineForAssetDecrease(AssetDecreaseDocument assetDecreaseDoc, AutomatedCashInvestmentModel aciModel, String kemid, BigDecimal cashEquivalent, int inv, boolean isIncome) {
440 UnitAmountAssociation unitAmount = calculateUnitAmount(aciModel, cashEquivalent, inv);
441
442 // Create the correct transaction line based on if it's a source or target type.
443 EndowmentTransactionLine transactionLine = createTransactionLine(assetDecreaseDoc.getDocumentNumber(), kemid, aciModel.getIpIndicator(), unitAmount.getAmount(), unitAmount.getUnits(), true);
444
445 // Validate the transaction line.
446 boolean rulesPassed = kualiRuleService.applyRules(new AddTransactionLineEvent(NEW_SOURCE_TRAN_LINE_PROPERTY_NAME, assetDecreaseDoc, transactionLine));
447
448 // If the transaction line passes validation, add it to the document.
449 if (rulesPassed) {
450 assetDecreaseDoc.addSourceTransactionLine((EndowmentSourceTransactionLine) transactionLine);
451 updateEadTaxLotService.updateTransactionLineTaxLots(assetDecreaseDoc, transactionLine);
452 }
453 else {
454 writeExceptionTableRowAssetDecrease(assetDecreaseDoc, transactionLine, isIncome);
455 List<String> errorMessages = GloabalVariablesExtractHelper.extractGlobalVariableErrors();
456 for (String errorMessage : errorMessages) {
457 writeExceptionTableReason(errorMessage);
458 }
459 }
460 }
461
462 /**
463 * Creates a new transaction line, validates, and adds it to the asset increase document.
464 *
465 * @param assetIncreaseDoc
466 * @param aciModel
467 * @param cashEquivalent
468 */
469 private void addTransactionLineForAssetIncrease(AssetIncreaseDocument assetIncreaseDoc, AutomatedCashInvestmentModel aciModel, String kemid, BigDecimal cashEquivalent, int inv, boolean isIncome) {
470 UnitAmountAssociation unitAmount = calculateUnitAmount(aciModel, cashEquivalent, inv);
471
472 // Create the correct transaction line based on if it's a source or target type.
473 EndowmentTransactionLine transactionLine = createTransactionLine(assetIncreaseDoc.getDocumentNumber(), kemid, aciModel.getIpIndicator(), unitAmount.getAmount(), unitAmount.getUnits(), false);
474
475 // Validate the transaction line.
476 boolean rulesPassed = kualiRuleService.applyRules(new AddTransactionLineEvent(NEW_TARGET_TRAN_LINE_PROPERTY_NAME, assetIncreaseDoc, transactionLine));
477
478 // If the transaction line passes validation, add it to the document.
479 if (rulesPassed) {
480 assetIncreaseDoc.addTargetTransactionLine((EndowmentTargetTransactionLine) transactionLine);
481 updateEaiTaxLotService.updateTransactionLineTaxLots(assetIncreaseDoc, transactionLine);
482 }
483 else {
484 writeExceptionTableRowAssetIncrease(assetIncreaseDoc, transactionLine, isIncome);
485 List<String> errorMessages = GloabalVariablesExtractHelper.extractGlobalVariableErrors();
486 for (String errorMessage : errorMessages) {
487 writeExceptionTableReason(errorMessage);
488 }
489 }
490 }
491
492 /**
493 * Creates a new transaction line.
494 *
495 * @param kemid
496 * @param etranCode
497 * @param amount
498 * @param units
499 * @param isSource
500 * @return
501 */
502 private EndowmentTransactionLine createTransactionLine(String docNumber, String kemid, String ipIndicator, BigDecimal amount, BigDecimal units, boolean isSource) {
503
504 EndowmentTransactionLine transactionLine = null;
505 if (isSource) {
506 transactionLine = new EndowmentSourceTransactionLine();
507 }
508 else {
509 transactionLine = new EndowmentTargetTransactionLine();
510 }
511
512 // Set values on the transaction line.
513 transactionLine.setDocumentNumber(docNumber);
514 transactionLine.setKemid(kemid);
515 transactionLine.setTransactionIPIndicatorCode(ipIndicator);
516 transactionLine.setTransactionAmount(new KualiDecimal(amount));
517 transactionLine.setTransactionUnits(new KualiDecimal(units));
518
519 return transactionLine;
520 }
521
522 /**
523 * Get the registration code for the specified investment.
524 *
525 * @param aciModel
526 * @param inv
527 * @return
528 */
529 private String getInvRegistrationCode(AutomatedCashInvestmentModel aciModel, int inv) {
530
531 String invRegistrationCode = "";
532 switch (inv) {
533 case 1:
534 invRegistrationCode = aciModel.getInvestment1().getFundRegistrationCode();
535 break;
536 case 2:
537 invRegistrationCode = aciModel.getInvestment2().getFundRegistrationCode();
538 break;
539 case 3:
540 invRegistrationCode = aciModel.getInvestment3().getFundRegistrationCode();
541 break;
542 case 4:
543 invRegistrationCode = aciModel.getInvestment4().getFundRegistrationCode();
544 break;
545 }
546
547 return invRegistrationCode;
548 }
549
550 /**
551 * Get the security id from the specified investment.
552 *
553 * @param aciModel
554 * @param inv
555 * @return
556 */
557 private String getInvSecurityId(AutomatedCashInvestmentModel aciModel, int inv) {
558
559 String invSecurityId = "";
560 switch (inv) {
561 case 1:
562 invSecurityId = aciModel.getInvestment1SecurityID();
563 break;
564 case 2:
565 invSecurityId = aciModel.getInvestment2SecurityID();
566 break;
567 case 3:
568 invSecurityId = aciModel.getInvestment3SecurityID();
569 break;
570 case 4:
571 invSecurityId = aciModel.getInvestment4SecurityID();
572 break;
573 }
574
575 return invSecurityId;
576 }
577
578 /**
579 * Gets the correct sale offset code for the specified investment.
580 *
581 * @param aciModel
582 * @param inv
583 * @return
584 */
585 private String getSaleOffsetCode(AutomatedCashInvestmentModel aciModel, int inv) {
586 String offsetCode = "";
587 switch (inv) {
588 case 1:
589 offsetCode = aciModel.getInvestment1().getFundAssetSaleOffsetTranCode();
590 break;
591 case 2:
592 offsetCode = aciModel.getInvestment2().getFundAssetSaleOffsetTranCode();
593 break;
594 case 3:
595 offsetCode = aciModel.getInvestment3().getFundAssetSaleOffsetTranCode();
596 break;
597 case 4:
598 offsetCode = aciModel.getInvestment4().getFundAssetSaleOffsetTranCode();
599 break;
600 }
601
602 return offsetCode;
603 }
604
605 /**
606 * Calculates the unite amount for the specified investment.
607 *
608 * @param aciModel
609 * @param cashEquivalent
610 * @param inv
611 * @return
612 */
613 private UnitAmountAssociation calculateUnitAmount(AutomatedCashInvestmentModel aciModel, BigDecimal cashEquivalent, int inv) {
614
615 BigDecimal invPercent = null;
616 BigDecimal invUnitValue = null;
617 BigDecimal invCashNeeded = null;
618 BigDecimal invAmount = null;
619 BigDecimal invUnits = null;
620
621 boolean allowsFractions = false;
622
623 switch (inv) {
624 case 1:
625 invPercent = aciModel.getInvestment1Percent();
626 invUnitValue = aciModel.getInvestment1().getSecurity().getUnitValue();
627 allowsFractions = aciModel.getInvestment1().isAllowFractionalShares();
628 break;
629 case 2:
630 invPercent = aciModel.getInvestment2Percent();
631 invUnitValue = aciModel.getInvestment2().getSecurity().getUnitValue();
632 allowsFractions = aciModel.getInvestment1().isAllowFractionalShares();
633 break;
634 case 3:
635 invPercent = aciModel.getInvestment3Percent();
636 invUnitValue = aciModel.getInvestment3().getSecurity().getUnitValue();
637 allowsFractions = aciModel.getInvestment1().isAllowFractionalShares();
638 break;
639 case 4:
640 invPercent = aciModel.getInvestment4Percent();
641 invUnitValue = aciModel.getInvestment4().getSecurity().getUnitValue();
642 allowsFractions = aciModel.getInvestment1().isAllowFractionalShares();
643 break;
644 }
645
646 if (invPercent != null) {
647 try {
648 invCashNeeded = new BigDecimal(invPercent.multiply(cashEquivalent).doubleValue());
649 invUnits = invCashNeeded.divide(invUnitValue, 5, RoundingMode.HALF_UP);
650
651 if (!allowsFractions) {
652 // Round the units down.
653 invUnits = invUnits.setScale(0, BigDecimal.ROUND_DOWN);
654 }
655 invAmount = (invUnits.multiply(invUnitValue)).setScale(2, BigDecimal.ROUND_HALF_UP);
656 }
657 catch (ArithmeticException ex) {
658 writeExceptionTableReason("Caught ArithmeticException while calculating units.");
659 LOG.error("Caught exception while calculating units.", ex);
660 }
661 }
662
663 return (new UnitAmountAssociation(invAmount, invUnits));
664 }
665
666 /**
667 * Get the max number of transaction lines allowed per document.
668 *
669 * @return
670 */
671 private int getMaxNumberOfTransactionLines() {
672 return kemService.getMaxNumberOfTransactionLinesPerDocument();
673 }
674
675 /**
676 * Gets the appropriate approval indicator based on if it's for a sale or purchase type.
677 *
678 * @param isSale
679 * @return
680 */
681 private boolean getNoRouteIndicator(boolean isSale) {
682 boolean noRouteIndicator = isSale ? getSaleNoRouteIndicator() : getPurchaseNoRouteIndicator();
683 return noRouteIndicator;
684 }
685
686 /**
687 * This method returns the true or false value of the purchase no route indicator.
688 *
689 * @return
690 */
691 private boolean getPurchaseNoRouteIndicator() {
692 String noRouteIndicator = parameterService.getParameterValue(CreateAutomatedCashInvestmentTransactionsStep.class, EndowParameterKeyConstants.PURCHASE_NO_ROUTE_IND);
693 return (EndowConstants.YES.equalsIgnoreCase(noRouteIndicator) ? true : false);
694 }
695
696 /**
697 * This method returns the true or false value of the sale no route indicator.
698 *
699 * @return
700 */
701 private boolean getSaleNoRouteIndicator() {
702 String noRouteIndicator = parameterService.getParameterValue(CreateAutomatedCashInvestmentTransactionsStep.class, EndowParameterKeyConstants.SALE_NO_ROUTE_IND);
703 return (EndowConstants.YES.equalsIgnoreCase(noRouteIndicator) ? true : false);
704 }
705
706 /**
707 * Creates and initializes an asset decrease document type.
708 *
709 * @param securityId
710 * @param registrationCode
711 * @return
712 */
713 private AssetDecreaseDocument createAssetDecrease(String securityId, String registrationCode) {
714
715 AssetDecreaseDocument assetDecrease = null;
716 try {
717 assetDecrease = (AssetDecreaseDocument) documentService.getNewDocument(AssetDecreaseDocument.class);
718
719 // Set the document description.
720 DocumentHeader docHeader = assetDecrease.getDocumentHeader();
721 docHeader.setDocumentDescription(getPurchaseDescription());
722 assetDecrease.setDocumentHeader(docHeader);
723
724 // Set the sub type code to cash.
725 assetDecrease.setTransactionSubTypeCode(EndowConstants.TransactionSubTypeCode.CASH);
726
727 // Create and set the target security transaction line.
728 EndowmentSourceTransactionSecurity sourceTransactionSecurity = new EndowmentSourceTransactionSecurity();
729 sourceTransactionSecurity.setSecurityLineTypeCode(EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE);
730 sourceTransactionSecurity.setRegistrationCode(registrationCode);
731 sourceTransactionSecurity.setSecurityID(securityId);
732
733 assetDecrease.setSourceTransactionSecurity(sourceTransactionSecurity);
734 }
735 catch (WorkflowException ex) {
736 writeExceptionTableReason("Workflow error while trying to create EAI document: " + ex.getLocalizedMessage());
737 LOG.error(ex.getLocalizedMessage());
738 }
739
740 return assetDecrease;
741 }
742
743 /**
744 * Creates and initializes an asset increase document type.
745 *
746 * @param securityId
747 * @param registrationCode
748 * @return
749 */
750 private AssetIncreaseDocument createAssetIncrease(String securityId, String registrationCode) {
751
752 AssetIncreaseDocument assetIncrease = null;
753 try {
754 assetIncrease = (AssetIncreaseDocument) documentService.getNewDocument(AssetIncreaseDocument.class);
755
756 // Set the document description.
757 DocumentHeader docHeader = assetIncrease.getDocumentHeader();
758 docHeader.setDocumentDescription(getPurchaseDescription());
759 assetIncrease.setDocumentHeader(docHeader);
760
761 // Set the sub type code to cash.
762 assetIncrease.setTransactionSubTypeCode(EndowConstants.TransactionSubTypeCode.CASH);
763
764 // Create and set the target security transaction line.
765 EndowmentTargetTransactionSecurity targetTransactionSecurity = new EndowmentTargetTransactionSecurity();
766 targetTransactionSecurity.setSecurityLineTypeCode(EndowConstants.TRANSACTION_SECURITY_TYPE_TARGET);
767 targetTransactionSecurity.setRegistrationCode(registrationCode);
768 targetTransactionSecurity.setSecurityID(securityId);
769
770 assetIncrease.setTargetTransactionSecurity(targetTransactionSecurity);
771 }
772 catch (WorkflowException ex) {
773 writeExceptionTableReason("Workflow error while trying to create EAI document: " + ex.getLocalizedMessage());
774 LOG.error(ex.getLocalizedMessage());
775 }
776
777 return assetIncrease;
778 }
779
780 /**
781 * Returns the appropriate principle/income cash equivalent.
782 *
783 * @param kemid
784 * @param isIncome
785 * @return BigDecimal
786 */
787 private BigDecimal getCashEquivalent(KEMID kemid, boolean isIncome) {
788
789 BigDecimal cashEquivalent;
790
791 if (!isIncome) {
792 cashEquivalent = calculatePrincipleCashEquivalent(kemid.getKemid());
793 }
794 else {
795 cashEquivalent = calculateIncomeCashEquivalent(kemid.getKemid());
796 }
797
798 return cashEquivalent;
799 }
800
801 /**
802 * Calculates the total market value for cash class code.
803 *
804 * @param kemid
805 * @param ipIndicator
806 * @return
807 */
808 private BigDecimal calculateTotalMarketValue(String kemid, String ipIndicator) {
809
810 // Used to calculate the total market value.
811 BigDecimal totalMarketValue = new BigDecimal(BigInteger.ZERO);
812
813 // Build the criteria used for getting the KEMIDs.
814 Map<String, String> map = new HashMap<String, String>();
815 map.put(EndowPropertyConstants.HOLDING_TAX_LOT_KEMID, kemid);
816 map.put(EndowPropertyConstants.HOLDING_TAX_LOT_INCOME_PRINCIPAL_INDICATOR, ipIndicator);
817
818 // Get all the holding tax lots that match the kemid and ipIndicator. Next, filter out
819 // those that are not cash equivalent, based on their class code type.
820 Collection<HoldingTaxLot> hldgTaxLots = businessObjectService.findMatching(HoldingTaxLot.class, map);
821 for (HoldingTaxLot hldgTaxLot : hldgTaxLots) {
822 Security security = securityService.getByPrimaryKey(hldgTaxLot.getSecurityId());
823 if (security != null) {
824 if (security.getClassCode().getClassCodeType().equalsIgnoreCase(EndowConstants.ClassCodeTypes.CASH_EQUIVALENTS)) {
825 totalMarketValue = totalMarketValue.add(hldgTaxLot.getUnits().multiply(security.getUnitValue()));
826 }
827 }
828 }
829
830 return totalMarketValue;
831 }
832
833 /**
834 * Calculates the principle cash equivalents.
835 *
836 * @param kemid
837 * @return
838 */
839 private BigDecimal calculatePrincipleCashEquivalent(String kemid) {
840 BigDecimal totalMarketValue = calculateTotalMarketValue(kemid, EndowConstants.IncomePrincipalIndicator.PRINCIPAL);
841
842 return getKemidCurrentPrincipalCash(kemid).add(totalMarketValue);
843 }
844
845 /**
846 * Calculates the income cash equivalents.
847 *
848 * @param kemid
849 * @return
850 */
851 private BigDecimal calculateIncomeCashEquivalent(String kemid) {
852 BigDecimal totalMarketValue = calculateTotalMarketValue(kemid, EndowConstants.IncomePrincipalIndicator.INCOME);
853
854 return getKemidCurrentIncomeCash(kemid).add(totalMarketValue);
855 }
856
857 /**
858 * This method...
859 *
860 * @param kemid
861 * @return
862 */
863 private BigDecimal getKemidCurrentPrincipalCash(String kemid) {
864 KemidCurrentCash kemidCurrentCash = businessObjectService.findBySinglePrimaryKey(KemidCurrentCash.class, kemid);
865
866 if (kemidCurrentCash == null) {
867 writeExceptionTableReason("Recieved \'null\' value for END_CRNT_CSH_T for KEMID " + kemid);
868 return new BigDecimal(BigInteger.ZERO);
869 }
870
871 return kemidCurrentCash.getCurrentPrincipalCash().bigDecimalValue();
872 }
873
874 /**
875 * This method...
876 *
877 * @param kemid
878 * @return
879 */
880 private BigDecimal getKemidCurrentIncomeCash(String kemid) {
881 KemidCurrentCash kemidCurrentCash = businessObjectService.findBySinglePrimaryKey(KemidCurrentCash.class, kemid);
882
883 if (kemidCurrentCash == null) {
884 writeExceptionTableReason("Recieved \'null\' value for END_CRNT_CSH_T for KEMID " + kemid);
885 return new BigDecimal(BigInteger.ZERO);
886 }
887 return kemidCurrentCash.getCurrentIncomeCash().bigDecimalValue();
888 }
889
890 /**
891 * This method retrieves all the cash sweep models whose frequency code matches the current date.
892 *
893 * @return Collection of CashSweepModel business objects
894 */
895 private Collection<AutomatedCashInvestmentModel> getAutomatedCashInvestmentModelMatchingCurrentDate() {
896 return automatedCashInvestmentModelDao.getAutomatedCashInvestmentModelWithNextPayDateEqualToCurrentDate(kemService.getCurrentDate());
897 }
898
899 /**
900 * This method...
901 *
902 * @param assetIncreaseDoc
903 * @param isIncome
904 */
905 private void writeProcessedTableRowAssetIncrease(AssetIncreaseDocument assetIncreaseDoc, boolean isIncome) {
906
907 TransactionDocumentTotalReportLine createAutomatedCashInvestmentProcessedReportValues = new TransactionDocumentTotalReportLine(EndowConstants.DocumentTypeNames.ENDOWMENT_ASSET_INCREASE, assetIncreaseDoc.getDocumentNumber(), assetIncreaseDoc.getTargetTransactionSecurity().getSecurityID());
908
909 List<EndowmentTransactionLine> transLines = assetIncreaseDoc.getTargetTransactionLines();
910 for (EndowmentTransactionLine tranLine : transLines) {
911 if (isIncome) {
912 createAutomatedCashInvestmentProcessedReportValues.addIncomeAmount(tranLine.getTransactionAmount());
913 createAutomatedCashInvestmentProcessedReportValues.addIncomeUnits(tranLine.getTransactionUnits());
914 }
915 else {
916 createAutomatedCashInvestmentProcessedReportValues.addPrincipalAmount(tranLine.getTransactionAmount());
917 createAutomatedCashInvestmentProcessedReportValues.addPrincipalUnits(tranLine.getTransactionUnits());
918 }
919 }
920 updatePostingStats(assetIncreaseDoc);
921
922 createAutomatedCashInvestmentProcessedReportWriterService.writeTableRow(createAutomatedCashInvestmentProcessedReportValues);
923 createAutomatedCashInvestmentProcessedReportWriterService.writeNewLines(1);
924 }
925
926 /**
927 * This method...
928 *
929 * @param assetDecreaseDoc
930 * @param isIncome
931 */
932 private void writeProcessedTableRowAssetDecrease(AssetDecreaseDocument assetDecreaseDoc, boolean isIncome) {
933
934 TransactionDocumentTotalReportLine createAutomatedCashInvestmentProcessedReportValues = new TransactionDocumentTotalReportLine(EndowConstants.DocumentTypeNames.ENDOWMENT_ASSET_DECREASE, assetDecreaseDoc.getDocumentNumber(), assetDecreaseDoc.getTargetTransactionSecurity().getSecurityID());
935
936 List<EndowmentTransactionLine> transLines = assetDecreaseDoc.getTargetTransactionLines();
937 for (EndowmentTransactionLine tranLine : transLines) {
938 if (isIncome) {
939 createAutomatedCashInvestmentProcessedReportValues.addIncomeAmount(tranLine.getTransactionAmount());
940 createAutomatedCashInvestmentProcessedReportValues.addIncomeUnits(tranLine.getTransactionUnits());
941 }
942 else {
943 createAutomatedCashInvestmentProcessedReportValues.addPrincipalAmount(tranLine.getTransactionAmount());
944 createAutomatedCashInvestmentProcessedReportValues.addPrincipalUnits(tranLine.getTransactionUnits());
945 }
946 }
947 updatePostingStats(assetDecreaseDoc);
948
949 createAutomatedCashInvestmentProcessedReportWriterService.writeTableRow(createAutomatedCashInvestmentProcessedReportValues);
950 createAutomatedCashInvestmentProcessedReportWriterService.writeNewLines(1);
951 }
952
953 /**
954 * This method...
955 *
956 * @param assetDecreaseDoc
957 * @param tranLine
958 * @param isIncome
959 */
960 private void writeExceptionTableRowAssetDecrease(AssetDecreaseDocument assetDecreaseDoc, EndowmentTransactionLine tranLine, boolean isIncome) {
961
962 TransactionDocumentExceptionReportLine createAutomatedCashInvestmentExceptionReportValues = new TransactionDocumentExceptionReportLine(EndowConstants.DocumentTypeNames.ENDOWMENT_ASSET_DECREASE, assetDecreaseDoc.getDocumentNumber(), assetDecreaseDoc.getTargetTransactionSecurity().getSecurityID());
963
964 if (tranLine != null) {
965 createAutomatedCashInvestmentExceptionReportValues.setKemid(tranLine.getKemid());
966 if (isIncome) {
967 createAutomatedCashInvestmentExceptionReportValues.addIncomeAmount(tranLine.getTransactionAmount());
968 createAutomatedCashInvestmentExceptionReportValues.addIncomeUnits(tranLine.getTransactionUnits());
969 }
970 else {
971 createAutomatedCashInvestmentExceptionReportValues.addPrincipalAmount(tranLine.getTransactionAmount());
972 createAutomatedCashInvestmentExceptionReportValues.addPrincipalUnits(tranLine.getTransactionUnits());
973 }
974 }
975 updateErrorStats(assetDecreaseDoc);
976
977 createAutomatedCashInvestmentExceptionReportWriterService.writeTableRow(createAutomatedCashInvestmentExceptionReportValues);
978 createAutomatedCashInvestmentExceptionReportWriterService.writeNewLines(1);
979 }
980
981 /**
982 * This method...
983 *
984 * @param assetIncreaseDoc
985 * @param tranLine
986 * @param isIncome
987 */
988 private void writeExceptionTableRowAssetIncrease(AssetIncreaseDocument assetIncreaseDoc, EndowmentTransactionLine tranLine, boolean isIncome) {
989
990 TransactionDocumentExceptionReportLine createAutomatedCashInvestmentExceptionReportValues = new TransactionDocumentExceptionReportLine(EndowConstants.DocumentTypeNames.ENDOWMENT_ASSET_INCREASE, assetIncreaseDoc.getDocumentNumber(), assetIncreaseDoc.getTargetTransactionSecurity().getSecurityID());
991
992 if (tranLine != null) {
993 createAutomatedCashInvestmentExceptionReportValues.setKemid(tranLine.getKemid());
994 if (isIncome) {
995 createAutomatedCashInvestmentExceptionReportValues.addIncomeAmount(tranLine.getTransactionAmount());
996 createAutomatedCashInvestmentExceptionReportValues.addIncomeUnits(tranLine.getTransactionUnits());
997 }
998 else {
999 createAutomatedCashInvestmentExceptionReportValues.addPrincipalAmount(tranLine.getTransactionAmount());
1000 createAutomatedCashInvestmentExceptionReportValues.addPrincipalUnits(tranLine.getTransactionUnits());
1001 }
1002 }
1003 updateErrorStats(assetIncreaseDoc);
1004
1005 createAutomatedCashInvestmentExceptionReportWriterService.writeTableRow(createAutomatedCashInvestmentExceptionReportValues);
1006 createAutomatedCashInvestmentExceptionReportWriterService.writeNewLines(1);
1007 }
1008
1009 /**
1010 * Writes the reason row and inserts a blank line.
1011 *
1012 * @param reasonMessage
1013 */
1014 private void writeExceptionTableReason(String reasonMessage) {
1015 EndowmentExceptionReportHeader createAutomatedCashInvestmentExceptionReportReason = new EndowmentExceptionReportHeader();
1016 createAutomatedCashInvestmentExceptionReportReason.setColumnHeading1("Reason: ");
1017 createAutomatedCashInvestmentExceptionReportReason.setColumnHeading2(reasonMessage);
1018 createAutomatedCashInvestmentExceptionReportWriterService.writeTableRow(createAutomatedCashInvestmentExceptionReportReason);
1019 createAutomatedCashInvestmentExceptionReportWriterService.writeNewLines(1);
1020 }
1021
1022 /**
1023 * Initialize the report document headers.
1024 */
1025 private void writeHeaders() {
1026 createAutomatedCashInvestmentExceptionReportWriterService.writeNewLines(1);
1027 createAutomatedCashInvestmentProcessedReportWriterService.writeNewLines(1);
1028 createAutomatedCashInvestmentExceptionReportWriterService.writeTableHeader(new TransactionDocumentExceptionReportLine());
1029 createAutomatedCashInvestmentProcessedReportWriterService.writeTableHeader(new TransactionDocumentTotalReportLine());
1030 }
1031
1032 /**
1033 * This method...
1034 *
1035 * @param assetDocument
1036 */
1037 private void updatePostingStats(EndowmentTaxLotLinesDocumentBase assetDocument) {
1038
1039 String documentTypeName = dataDictionaryService.getDocumentTypeNameByClass(assetDocument.getClass());
1040 ReportDocumentStatistics stats = statistics.get(documentTypeName);
1041
1042 // If null that means there isn't one in the map, so create it and add
1043 // it to the map.
1044 if (stats == null) {
1045 stats = new ReportDocumentStatistics(documentTypeName);
1046 statistics.put(documentTypeName, stats);
1047 }
1048 stats.addNumberOfSourceTransactionLines(assetDocument.getSourceTransactionLines().size());
1049 stats.addNumberOfTargetTransactionLines(assetDocument.getTargetTransactionLines().size());
1050
1051 stats.incrementNumberOfDocuments();
1052 }
1053
1054 /**
1055 * This method...
1056 *
1057 * @param assetDocument
1058 */
1059 private void updateErrorStats(EndowmentTaxLotLinesDocumentBase assetDocument) {
1060
1061 String documentTypeName = dataDictionaryService.getDocumentTypeNameByClass(assetDocument.getClass());
1062 ReportDocumentStatistics stats = statistics.get(documentTypeName);
1063
1064 // If null that means there isn't one in the map, so create it and add
1065 // it to the map.
1066 if (stats == null) {
1067 stats = new ReportDocumentStatistics(documentTypeName);
1068 statistics.put(documentTypeName, stats);
1069 }
1070
1071 stats.incrementNumberOfErrors();
1072 }
1073
1074 /**
1075 * Write out the statistics.
1076 */
1077 private void writeStatistics() {
1078
1079 for (Map.Entry<String, ReportDocumentStatistics> entry : statistics.entrySet()) {
1080
1081 ReportDocumentStatistics stats = entry.getValue();
1082
1083 createAutomatedCashInvestmentProcessedReportWriterService.writeStatisticLine("%s Documents:", stats.getDocumentTypeName());
1084 createAutomatedCashInvestmentProcessedReportWriterService.writeStatisticLine(" Number of Documents Generated: %d", stats.getNumberOfDocuments());
1085 createAutomatedCashInvestmentProcessedReportWriterService.writeStatisticLine(" Number of Transaction Lines Generated: %d", stats.getTotalNumberOfTransactionLines());
1086 createAutomatedCashInvestmentProcessedReportWriterService.writeStatisticLine(" Number of Error Records Written: %d", stats.getNumberOfErrors());
1087 createAutomatedCashInvestmentProcessedReportWriterService.writeStatisticLine("", "");
1088
1089 createAutomatedCashInvestmentExceptionReportWriterService.writeStatisticLine("%s Documents:", stats.getDocumentTypeName());
1090 createAutomatedCashInvestmentExceptionReportWriterService.writeStatisticLine(" Number of Documents Generated: %d", stats.getNumberOfDocuments());
1091 createAutomatedCashInvestmentExceptionReportWriterService.writeStatisticLine(" Number of Transaction Lines Generated: %d", stats.getTotalNumberOfTransactionLines());
1092 createAutomatedCashInvestmentExceptionReportWriterService.writeStatisticLine(" Number of Error Records Written: %d", stats.getNumberOfErrors());
1093 createAutomatedCashInvestmentExceptionReportWriterService.writeStatisticLine("", "");
1094 }
1095
1096 }
1097
1098 /**
1099 * Gets the purchase description parameter.
1100 *
1101 * @return
1102 */
1103 private String getPurchaseDescription() {
1104 return parameterService.getParameterValue(CreateAutomatedCashInvestmentTransactionsStep.class, EndowParameterKeyConstants.PURCHASE_DESCRIPTION);
1105 }
1106
1107 /**
1108 * Gets the sale description parameter.
1109 *
1110 * @return
1111 */
1112 private String getSaleDescription() {
1113 return parameterService.getParameterValue(CreateAutomatedCashInvestmentTransactionsStep.class, EndowParameterKeyConstants.SALE_DESCRIPTION);
1114 }
1115
1116 /**
1117 * Sets the createAutomatedCashInvestmentExceptionReportWriterService attribute value.
1118 *
1119 * @param createAutomatedCashInvestmentExceptionReportWriterService The
1120 * createAutomatedCashInvestmentExceptionReportWriterService to set.
1121 */
1122 public void setCreateAutomatedCashInvestmentExceptionReportWriterService(ReportWriterService createAutomatedCashInvestmentExceptionReportWriterService) {
1123 this.createAutomatedCashInvestmentExceptionReportWriterService = createAutomatedCashInvestmentExceptionReportWriterService;
1124 }
1125
1126 /**
1127 * Sets the createAutomatedCashInvestmentProcessedReportWriterService attribute value.
1128 *
1129 * @param createAutomatedCashInvestmentProcessedReportWriterService The
1130 * createAutomatedCashInvestmentProcessedReportWriterService to set.
1131 */
1132 public void setCreateAutomatedCashInvestmentProcessedReportWriterService(ReportWriterService createAutomatedCashInvestmentProcessedReportWriterService) {
1133 this.createAutomatedCashInvestmentProcessedReportWriterService = createAutomatedCashInvestmentProcessedReportWriterService;
1134 }
1135
1136 /**
1137 * Sets the businessObjectService attribute value.
1138 *
1139 * @param businessObjectService The businessObjectService to set.
1140 */
1141 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
1142 this.businessObjectService = businessObjectService;
1143 }
1144
1145 /**
1146 * Sets the kualiRuleService attribute value.
1147 *
1148 * @param kualiRuleService The kualiRuleService to set.
1149 */
1150 public void setKualiRuleService(KualiRuleService kualiRuleService) {
1151 this.kualiRuleService = kualiRuleService;
1152 }
1153
1154 /**
1155 * Sets the parameterService attribute value.
1156 *
1157 * @param parameterService The parameterService to set.
1158 */
1159 public void setParameterService(ParameterService parameterService) {
1160 this.parameterService = parameterService;
1161 }
1162
1163 /**
1164 * Sets the documentService attribute value.
1165 *
1166 * @param documentService The documentService to set.
1167 */
1168 public void setDocumentService(DocumentService documentService) {
1169 this.documentService = documentService;
1170 }
1171
1172 /**
1173 * Sets the kemidService attribute value.
1174 *
1175 * @param kemidService The kemidService to set.
1176 */
1177 public void setKemidService(KEMIDService kemidService) {
1178 this.kemidService = kemidService;
1179 }
1180
1181 /**
1182 * Sets the kemService attribute value.
1183 *
1184 * @param kemService The kemService to set.
1185 */
1186 public void setKemService(KEMService kemService) {
1187 this.kemService = kemService;
1188 }
1189
1190 /**
1191 * Sets the securityService attribute value.
1192 *
1193 * @param securityService The securityService to set.
1194 */
1195 public void setSecurityService(SecurityService securityService) {
1196 this.securityService = securityService;
1197 }
1198
1199 /**
1200 * Sets the configService attribute value.
1201 *
1202 * @param configService The configService to set.
1203 */
1204 public void setConfigService(KualiConfigurationService configService) {
1205 this.configService = configService;
1206 }
1207
1208 /**
1209 * Sets the automatedCashInvestmentModelDao attribute value.
1210 *
1211 * @param automatedCashInvestmentModelDao The automatedCashInvestmentModelDao to set.
1212 */
1213 public void setAutomatedCashInvestmentModelDao(AutomatedCashInvestmentModelDao automatedCashInvestmentModelDao) {
1214 this.automatedCashInvestmentModelDao = automatedCashInvestmentModelDao;
1215 }
1216
1217 /**
1218 * Sets the dataDictionaryService attribute value.
1219 *
1220 * @param dataDictionaryService The dataDictionaryService to set.
1221 */
1222 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
1223 this.dataDictionaryService = dataDictionaryService;
1224 }
1225
1226 /**
1227 * Sets the updateEaiTaxLotService attribute value.
1228 *
1229 * @param updateEaiTaxLotService The updateEaiTaxLotService to set.
1230 */
1231 public void setUpdateEaiTaxLotService(UpdateAssetIncreaseDocumentTaxLotsService updateEaiTaxLotService) {
1232 this.updateEaiTaxLotService = updateEaiTaxLotService;
1233 }
1234
1235 /**
1236 * Sets the updateEadTaxLotService attribute value.
1237 *
1238 * @param updateEadTaxLotService The updateEadTaxLotService to set.
1239 */
1240 public void setUpdateEadTaxLotService(UpdateAssetDecreaseDocumentTaxLotsService updateEadTaxLotService) {
1241 this.updateEadTaxLotService = updateEadTaxLotService;
1242 }
1243
1244 /**
1245 * This class...
1246 */
1247 private class UnitAmountAssociation {
1248 private BigDecimal amount;
1249 private BigDecimal units;
1250
1251 public UnitAmountAssociation(BigDecimal amount, BigDecimal units) {
1252 this.amount = amount;
1253 this.units = units;
1254 }
1255
1256 /**
1257 * Gets the amount attribute.
1258 *
1259 * @return Returns the amount.
1260 */
1261 public BigDecimal getAmount() {
1262 return amount;
1263 }
1264
1265 /**
1266 * Gets the unit attribute.
1267 *
1268 * @return Returns the unit.
1269 */
1270 public BigDecimal getUnits() {
1271 return units;
1272 }
1273 }
1274 }