1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.analyse;
18
19 import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
20 import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
21 import io.github.tonywasher.joceanus.metis.preference.MetisPreferenceManager;
22 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseAssetBase;
23 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseAssetType;
24 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
25 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseCash;
26 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDataSet;
27 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDeposit;
28 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseLoan;
29 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePortfolio;
30 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePortfolio.MoneyWisePortfolioList;
31 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity;
32 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurityHolding;
33 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurityHoldingMap;
34 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurityPrice.MoneyWiseSecurityPriceDataMap;
35 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTax.MoneyWiseTaxCredit;
36 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransAsset;
37 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransCategory;
38 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransTag;
39 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransaction;
40 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransaction.MoneyWiseTransactionList;
41 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWisePayeeClass;
42 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWisePortfolioClass;
43 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseSecurityClass;
44 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTransCategoryClass;
45 import io.github.tonywasher.joceanus.moneywise.exc.MoneyWiseLogicException;
46 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysis;
47 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisAccountBucket;
48 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisCashBucket.MoneyWiseAnalysisCashBucketList;
49 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisDataResource;
50 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisDepositBucket.MoneyWiseAnalysisDepositBucketList;
51 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisLoanBucket.MoneyWiseAnalysisLoanBucketList;
52 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPayeeBucket;
53 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPayeeBucket.MoneyWiseAnalysisPayeeBucketList;
54 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioBucket;
55 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioBucket.MoneyWiseAnalysisPortfolioBucketList;
56 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioCashBucket;
57 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisSecurityBucket;
58 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTaxBasisBucket.MoneyWiseAnalysisTaxBasisBucketList;
59 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTransCategoryBucket;
60 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTransCategoryBucket.MoneyWiseAnalysisTransCategoryBucketList;
61 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTransTagBucket.MoneyWiseAnalysisTransTagBucketList;
62 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTransactionHelper;
63 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.values.MoneyWiseAnalysisSecurityAttr;
64 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.values.MoneyWiseAnalysisSecurityValues;
65 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseCashType;
66 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
67 import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
68 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
69 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusPrice;
70 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRate;
71 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRatio;
72 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusUnits;
73 import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
74 import io.github.tonywasher.joceanus.oceanus.profile.OceanusProfile;
75 import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
76
77 import java.util.Currency;
78 import java.util.Iterator;
79 import java.util.List;
80 import java.util.Objects;
81
82
83
84
85
86
87 public class MoneyWiseAnalysisTransAnalyser
88 implements MetisFieldItem {
89
90
91
92 private static final String ERROR_CATEGORY = "Unexpected Category Type: ";
93
94
95
96
97 private static final MetisFieldSet<MoneyWiseAnalysisTransAnalyser> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseAnalysisTransAnalyser.class);
98
99
100
101
102 static {
103 FIELD_DEFS.declareLocalField(MoneyWiseAnalysisDataResource.ANALYSIS_NAME, MoneyWiseAnalysisTransAnalyser::getAnalysis);
104 }
105
106
107
108
109 private static final OceanusMoney LIMIT_VALUE = OceanusMoney.getWholeUnits(3000);
110
111
112
113
114 private static final OceanusRate LIMIT_RATE = OceanusRate.getWholePercentage(5);
115
116
117
118
119 private final MoneyWiseSecurityHoldingMap theHoldingMap;
120
121
122
123
124 private final MoneyWiseSecurityPriceDataMap thePriceMap;
125
126
127
128
129 private final MoneyWiseAnalysis theAnalysis;
130
131
132
133
134 private final MoneyWiseAnalysisTransactionHelper theHelper;
135
136
137
138
139 private final MoneyWiseAnalysisDepositBucketList theDepositBuckets;
140
141
142
143
144 private final MoneyWiseAnalysisCashBucketList theCashBuckets;
145
146
147
148
149 private final MoneyWiseAnalysisLoanBucketList theLoanBuckets;
150
151
152
153
154 private final MoneyWiseAnalysisPortfolioBucketList thePortfolioBuckets;
155
156
157
158
159 private final MoneyWiseAnalysisPayeeBucketList thePayeeBuckets;
160
161
162
163
164 private final MoneyWiseAnalysisTransCategoryBucketList theCategoryBuckets;
165
166
167
168
169 private final MoneyWiseAnalysisTransTagBucketList theTagBuckets;
170
171
172
173
174 private final MoneyWiseAnalysisTaxBasisBucketList theTaxBasisBuckets;
175
176
177
178
179 private final MoneyWiseAnalysisPayeeBucket theTaxMan;
180
181
182
183
184 private final MoneyWiseAnalysisSecurityBucket theStatePension;
185
186
187
188
189 private final OceanusProfile theProfile;
190
191
192
193
194
195
196
197
198
199 public MoneyWiseAnalysisTransAnalyser(final OceanusProfile pTask,
200 final PrometheusEditSet pEditSet,
201 final MetisPreferenceManager pPreferenceMgr) throws OceanusException {
202
203 theProfile = pTask;
204 final OceanusProfile myTask = theProfile.startTask("analyseTransactions");
205 final MoneyWiseDataSet myDataSet = (MoneyWiseDataSet) pEditSet.getDataSet();
206
207
208 theHoldingMap = (MoneyWiseSecurityHoldingMap) pEditSet.getDataList(MoneyWiseBasicDataType.PORTFOLIO, MoneyWisePortfolioList.class)
209 .getSecurityHoldingsMap();
210 thePriceMap = myDataSet.getSecurityPriceDataMap();
211
212
213 final MoneyWiseTransactionList myTrans = pEditSet.getDataList(MoneyWiseBasicDataType.TRANSACTION, MoneyWiseTransactionList.class);
214
215
216 myTask.startTask("Initialise");
217 theAnalysis = new MoneyWiseAnalysis(pEditSet, pPreferenceMgr);
218
219
220 theHelper = new MoneyWiseAnalysisTransactionHelper(myDataSet);
221 theAnalysis.addOpeningBalances(theHelper);
222
223
224 theDepositBuckets = theAnalysis.getDeposits();
225 theCashBuckets = theAnalysis.getCash();
226 theLoanBuckets = theAnalysis.getLoans();
227 thePortfolioBuckets = theAnalysis.getPortfolios();
228 thePayeeBuckets = theAnalysis.getPayees();
229 theCategoryBuckets = theAnalysis.getTransCategories();
230 theTagBuckets = theAnalysis.getTransactionTags();
231 theTaxBasisBuckets = theAnalysis.getTaxBasis();
232 theTaxMan = thePayeeBuckets.getBucket(MoneyWisePayeeClass.TAXMAN);
233
234
235 theStatePension = getStatePension(myDataSet);
236
237
238 myTask.startTask("Transactions");
239 final Iterator<MoneyWiseTransaction> myIterator = myTrans.iterator();
240 while (myIterator.hasNext()) {
241 final MoneyWiseTransaction myCurr = myIterator.next();
242
243
244 if (myCurr.isDeleted() || myCurr.isHeader()) {
245 continue;
246 }
247
248
249 myCurr.touchUnderlyingItems();
250
251
252 processTransaction(myCurr);
253 }
254
255
256 myTask.end();
257 }
258
259
260
261
262
263
264
265 private MoneyWiseAnalysisSecurityBucket getStatePension(final MoneyWiseDataSet pData) {
266
267 final MoneyWisePortfolio myPensionPort = pData.getPortfolios().getSingularClass(MoneyWisePortfolioClass.PENSION);
268 final MoneyWiseSecurity myStatePension = pData.getSecurities().getSingularClass(MoneyWiseSecurityClass.STATEPENSION);
269
270
271 if (myPensionPort != null
272 && myStatePension != null) {
273 final MoneyWiseSecurityHoldingMap myMap = (MoneyWiseSecurityHoldingMap) pData.getPortfolios().getSecurityHoldingsMap();
274 final MoneyWiseSecurityHolding myHolding = myMap.declareHolding(myPensionPort, myStatePension);
275 return thePortfolioBuckets.getBucket(myHolding);
276 }
277
278
279 return null;
280 }
281
282 @Override
283 public MetisFieldSet<MoneyWiseAnalysisTransAnalyser> getDataFieldSet() {
284 return FIELD_DEFS;
285 }
286
287 @Override
288 public String formatObject(final OceanusDataFormatter pFormatter) {
289 return FIELD_DEFS.getName();
290 }
291
292
293
294
295
296
297 public MoneyWiseAnalysis getAnalysis() {
298 return theAnalysis;
299 }
300
301
302
303
304
305
306 public void postProcessAnalysis() throws OceanusException {
307
308 final OceanusProfile myTask = theProfile.startTask("postProcessAnalysis");
309 myTask.startTask("markActiveAccounts");
310
311
312 theDepositBuckets.markActiveAccounts();
313 theCashBuckets.markActiveAccounts();
314 theLoanBuckets.markActiveAccounts();
315
316
317 thePortfolioBuckets.markActiveSecurities();
318
319
320 myTask.end();
321 }
322
323
324
325
326
327
328
329 private void processTransaction(final MoneyWiseTransaction pTrans) throws OceanusException {
330
331 theHelper.setTransaction(pTrans);
332
333
334 final MoneyWiseTransAsset myDebitAsset = theHelper.getDebitAsset();
335 final MoneyWiseTransAsset myCreditAsset = theHelper.getCreditAsset();
336 final MoneyWiseTaxCredit myYear = pTrans.getTaxYear();
337
338
339 final List<MoneyWiseTransTag> myTags = pTrans.getTransactionTags();
340 if (myTags != null) {
341
342 theTagBuckets.processTransaction(pTrans, myTags.iterator());
343 }
344
345
346 if (myDebitAsset instanceof MoneyWiseSecurityHolding myHolding) {
347
348 processDebitSecurityTransaction(myHolding, myCreditAsset);
349
350
351 } else if (myCreditAsset instanceof MoneyWiseSecurityHolding myHolding) {
352
353 processCreditSecurityTransaction(myDebitAsset, myHolding);
354
355
356 } else if (myDebitAsset instanceof MoneyWisePortfolio myDebitPortfolio
357 && myCreditAsset instanceof MoneyWisePortfolio myCreditPortfolio
358 && pTrans.getCategoryClass() == MoneyWiseTransCategoryClass.PORTFOLIOXFER
359 && !myDebitAsset.equals(myCreditAsset)) {
360
361 processPortfolioXfer(myDebitPortfolio, myCreditPortfolio);
362
363
364 } else if (myDebitAsset instanceof MoneyWiseAssetBase myDebit
365 && myCreditAsset instanceof MoneyWiseAssetBase myCredit) {
366
367 MoneyWiseAssetBase myChild = null;
368 final OceanusMoney myAmount = pTrans.getAmount();
369 MoneyWiseTransCategory myCat = pTrans.getCategory();
370
371
372 switch (Objects.requireNonNull(myCat.getCategoryTypeClass())) {
373 case INTEREST, LOYALTYBONUS:
374
375 myCat = myDebit.getDetailedCategory(myCat, myYear);
376
377
378 myChild = myDebit.equals(myCredit)
379 ? null
380 : myDebit;
381 myDebit = myDebit.getParent();
382 break;
383 case LOANINTERESTEARNED, CASHBACK:
384
385 myDebit = myDebit.getParent();
386 break;
387 case RENTALINCOME, ROOMRENTALINCOME:
388
389 myChild = myDebit.equals(myCredit)
390 ? null
391 : myDebit;
392 myDebit = myCredit.getParent();
393 break;
394 case WRITEOFF, LOANINTERESTCHARGED:
395
396 myCredit = myCredit.getParent();
397 break;
398 default:
399 break;
400 }
401
402
403 if (myDebit instanceof MoneyWiseCash myCash
404 && myDebit.getAssetType() == MoneyWiseAssetType.AUTOEXPENSE) {
405
406 final MoneyWiseTransCategory myAuto = myCash.getAutoExpense();
407 myDebit = myCash.getAutoPayee();
408 myDebit.touchItem(pTrans);
409
410
411 final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myDebit);
412 myPayee.subtractExpense(theHelper, myAmount);
413
414
415 final MoneyWiseAnalysisTransCategoryBucket myCatBucket = theCategoryBuckets.getBucket(myAuto);
416 myCatBucket.subtractExpense(theHelper, myAmount);
417 theTaxBasisBuckets.adjustAutoExpense(theHelper, false);
418
419
420 } else if (MoneyWiseAssetType.PAYEE.equals(myDebit.getAssetType())) {
421 final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myDebit);
422 myPayee.adjustForDebit(theHelper);
423
424
425 } else {
426 final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket(myDebit);
427 myBucket.adjustForDebit(theHelper);
428 }
429
430
431 if (myCredit instanceof MoneyWiseCash myCash
432 && myCredit.getAssetType() == MoneyWiseAssetType.AUTOEXPENSE) {
433
434 final MoneyWiseTransCategory myAuto = myCash.getAutoExpense();
435 myCredit = myCash.getAutoPayee();
436 myCredit.touchItem(pTrans);
437
438
439 final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myCredit);
440 myPayee.addExpense(theHelper, myAmount);
441
442
443 final MoneyWiseAnalysisTransCategoryBucket myCatBucket = theCategoryBuckets.getBucket(myAuto);
444 myCatBucket.addExpense(theHelper, myAmount);
445 theTaxBasisBuckets.adjustAutoExpense(theHelper, true);
446
447
448 } else if (MoneyWiseAssetType.PAYEE.equals(myCredit.getAssetType())) {
449 final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myCredit);
450 myPayee.adjustForCredit(theHelper);
451
452
453 } else {
454 final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket(myCredit);
455 myBucket.adjustForCredit(theHelper);
456 }
457
458
459 if (myChild != null) {
460
461 final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket(myChild);
462 myBucket.registerTransaction(pTrans);
463 }
464
465
466 theTaxMan.adjustForTaxPayments(theHelper);
467 theStatePension.adjustForNIPayments(theHelper);
468
469
470 if (!myCat.isTransfer()) {
471
472 theCategoryBuckets.adjustCategories(theHelper, myCat);
473 }
474
475
476 } else {
477 throw new MoneyWiseLogicException("Invalid Asset Pair: "
478 + pTrans.getAccount().getAssetType()
479 + " "
480 + pTrans.getDirection()
481 + " "
482 + pTrans.getPartner().getAssetType());
483 }
484 }
485
486
487
488
489
490
491
492
493 private void processDebitSecurityTransaction(final MoneyWiseSecurityHolding pDebit,
494 final MoneyWiseTransAsset pCredit) throws OceanusException {
495
496 if (pCredit instanceof MoneyWiseSecurityHolding myHolding) {
497
498 processDebitCreditSecurityTransaction(pDebit, myHolding);
499 return;
500 }
501
502
503 final MoneyWiseTransCategory myCat = theHelper.getCategory();
504 switch (Objects.requireNonNull(myCat.getCategoryTypeClass())) {
505
506 case STOCKRIGHTSISSUE:
507 processTransferOut(pDebit, (MoneyWiseAssetBase) pCredit);
508 break;
509
510 case DIVIDEND:
511 processDividend(pDebit, pCredit);
512 break;
513 case PORTFOLIOXFER:
514 processPortfolioXfer(pDebit, (MoneyWisePortfolio) pCredit);
515 break;
516
517 case TRANSFER, SECURITYCLOSURE, EXPENSE, INHERITED, OTHERINCOME:
518 if (pDebit.getSecurity().isSecurityClass(MoneyWiseSecurityClass.LIFEBOND)) {
519 processChargeableGain(pDebit, (MoneyWiseAssetBase) pCredit);
520 } else {
521 processTransferOut(pDebit, (MoneyWiseAssetBase) pCredit);
522 }
523 break;
524
525 default:
526 throw new MoneyWiseLogicException(ERROR_CATEGORY
527 + myCat.getCategoryTypeClass());
528 }
529 }
530
531
532
533
534
535
536
537
538 private void processDebitCreditSecurityTransaction(final MoneyWiseSecurityHolding pDebit,
539 final MoneyWiseSecurityHolding pCredit) throws OceanusException {
540
541 final MoneyWiseTransCategory myCat = theHelper.getCategory();
542 switch (Objects.requireNonNull(myCat.getCategoryTypeClass())) {
543
544 case STOCKSPLIT, UNITSADJUST:
545 processUnitsAdjust(pDebit);
546 break;
547
548 case STOCKDEMERGER:
549 processStockDeMerger(pDebit, pCredit);
550 break;
551
552 case SECURITYREPLACE, STOCKTAKEOVER:
553 processStockTakeover(pDebit, pCredit);
554 break;
555
556 case DIVIDEND:
557 processDividend(pDebit, pCredit);
558 break;
559
560 case TRANSFER, EXPENSE, INHERITED, OTHERINCOME:
561 processStockXchange(pDebit, pCredit);
562 break;
563
564 default:
565 throw new MoneyWiseLogicException(ERROR_CATEGORY
566 + myCat.getCategoryTypeClass());
567 }
568 }
569
570
571
572
573
574
575
576
577 private void processCreditSecurityTransaction(final MoneyWiseTransAsset pDebit,
578 final MoneyWiseSecurityHolding pCredit) throws OceanusException {
579
580 if (!(pDebit instanceof MoneyWiseAssetBase myDebit)) {
581 throw new MoneyWiseLogicException("Invalid Debit Asset: "
582 + pDebit.getAssetType());
583 }
584
585
586 final MoneyWiseTransCategory myCat = theHelper.getCategory();
587 switch (Objects.requireNonNull(myCat.getCategoryTypeClass())) {
588
589 case STOCKRIGHTSISSUE, TRANSFER, EXPENSE, INHERITED, OTHERINCOME, PENSIONCONTRIB:
590 processTransferIn(myDebit, pCredit);
591 break;
592
593 default:
594 throw new MoneyWiseLogicException(ERROR_CATEGORY
595 + myCat.getCategoryTypeClass());
596 }
597 }
598
599
600
601
602
603
604
605
606
607 private void processPortfolioXfer(final MoneyWisePortfolio pSource,
608 final MoneyWisePortfolio pTarget) {
609
610 final MoneyWiseAnalysisPortfolioBucket mySource = thePortfolioBuckets.getBucket(pSource);
611 final MoneyWiseAnalysisPortfolioBucket myTarget = thePortfolioBuckets.getBucket(pTarget);
612
613
614 final MoneyWiseAnalysisPortfolioCashBucket mySourceCash = mySource.getPortfolioCash();
615 if (mySourceCash.isActive()) {
616
617 final MoneyWiseAnalysisPortfolioCashBucket myTargetCash = myTarget.getPortfolioCash();
618 myTargetCash.adjustForXfer(mySourceCash, theHelper);
619 }
620
621
622 final Iterator<MoneyWiseAnalysisSecurityBucket> myIterator = mySource.securityIterator();
623 while (myIterator.hasNext()) {
624 final MoneyWiseAnalysisSecurityBucket myBucket = myIterator.next();
625
626
627 if (myBucket.isActive()) {
628
629 final MoneyWiseSecurityHolding myTargetHolding = theHoldingMap.declareHolding(pTarget, myBucket.getSecurity());
630 final MoneyWiseAnalysisSecurityBucket myTargetBucket = myTarget.getSecurityBucket(myTargetHolding);
631 theHelper.setSecurity(myBucket.getSecurity());
632
633
634 processPortfolioXfer(myBucket, myTargetBucket);
635 }
636 }
637
638
639 }
640
641
642
643
644
645
646
647 private void processPortfolioXfer(final MoneyWiseAnalysisSecurityBucket pSource,
648 final MoneyWiseAnalysisSecurityBucket pTarget) {
649
650 MoneyWiseAnalysisSecurityValues mySourceValues = pSource.getValues();
651 OceanusUnits myUnits = mySourceValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
652 OceanusMoney myCost = mySourceValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
653 OceanusMoney myGains = mySourceValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS);
654 OceanusMoney myInvested = mySourceValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.INVESTED);
655 OceanusMoney myForeignInvested = mySourceValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED);
656 final boolean isForeign = pSource.isForeignCurrency();
657
658
659 final OceanusPrice myPrice = thePriceMap.getPriceForDate(pSource.getSecurity(), theHelper.getDate());
660 OceanusMoney myStockValue = myPrice.unitsAtPrice(myUnits);
661 OceanusMoney myForeignValue = null;
662 OceanusRatio myRate = null;
663
664
665 if (isForeign) {
666
667 myRate = theHelper.getDebitExchangeRate();
668 myForeignValue = myStockValue;
669 myStockValue = myStockValue.convertCurrency(theAnalysis.getCurrency().getCurrency(), myRate);
670 }
671
672
673 OceanusMoney myProfit = new OceanusMoney(myStockValue);
674 myProfit.subtractAmount(myCost);
675 pSource.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
676 myProfit = new OceanusMoney(myProfit);
677 myProfit.negate();
678 pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
679
680
681 pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myUnits);
682 pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myCost);
683 pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myInvested);
684 pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS, myGains);
685 final MoneyWiseAnalysisSecurityValues myTargetValues = pTarget.registerTransaction(theHelper);
686 myTargetValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myPrice);
687 myTargetValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myStockValue);
688 myTargetValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myCost);
689 if (isForeign) {
690 myTargetValues.setValue(MoneyWiseAnalysisSecurityAttr.FOREIGNVALUE, myForeignValue);
691 myTargetValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myRate);
692 pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myForeignInvested);
693 }
694
695
696 myUnits = new OceanusUnits(myUnits);
697 myUnits.negate();
698 pSource.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myUnits);
699 myCost = new OceanusMoney(myCost);
700 myCost.negate();
701 pSource.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myCost);
702 myCost.negate();
703 myInvested = new OceanusMoney(myInvested);
704 myInvested.negate();
705 pSource.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myInvested);
706 myGains = new OceanusMoney(myGains);
707 myGains.negate();
708 pSource.adjustCounter(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS, myGains);
709 mySourceValues = pSource.registerTransaction(theHelper);
710 mySourceValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myPrice);
711 mySourceValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myStockValue);
712 mySourceValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myCost);
713 if (isForeign) {
714 mySourceValues.setValue(MoneyWiseAnalysisSecurityAttr.FOREIGNVALUE, myForeignValue);
715 mySourceValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myRate);
716 myForeignInvested = new OceanusMoney(myForeignInvested);
717 myForeignInvested.negate();
718 pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myForeignInvested);
719 }
720 }
721
722
723
724
725
726
727
728
729
730 private void processPortfolioXfer(final MoneyWiseSecurityHolding pSource,
731 final MoneyWisePortfolio pTarget) {
732
733 final MoneyWiseAnalysisPortfolioBucket mySource = thePortfolioBuckets.getBucket(pSource.getPortfolio());
734 final MoneyWiseAnalysisPortfolioBucket myTarget = thePortfolioBuckets.getBucket(pTarget);
735
736
737 final MoneyWiseAnalysisSecurityBucket myBucket = mySource.getSecurityBucket(pSource);
738
739
740 if (myBucket.isActive()) {
741
742 final MoneyWiseSecurityHolding myTargetHolding = theHoldingMap.declareHolding(pTarget, myBucket.getSecurity());
743 final MoneyWiseAnalysisSecurityBucket myTargetBucket = myTarget.getSecurityBucket(myTargetHolding);
744
745
746 processPortfolioXfer(myBucket, myTargetBucket);
747 }
748
749
750 }
751
752
753
754
755
756
757
758
759 private void processUnitsAdjust(final MoneyWiseSecurityHolding pHolding) {
760
761 final OceanusUnits myDelta = theHelper.getAccountDeltaUnits();
762
763
764 final MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pHolding);
765 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDelta);
766
767
768 myAsset.registerTransaction(theHelper);
769
770
771 }
772
773
774
775
776
777
778
779
780
781 private void processTransferIn(final MoneyWiseAssetBase pDebit,
782 final MoneyWiseSecurityHolding pCredit) {
783
784 final MoneyWiseTransCategory myCat = theHelper.getCategory();
785
786
787 processCreditXferIn(pCredit);
788
789
790 theTaxMan.adjustForTaxPayments(theHelper);
791
792
793 if (Objects.requireNonNull(pDebit.getAssetType()) == MoneyWiseAssetType.PAYEE) {
794 final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(pDebit);
795 myPayee.adjustForDebit(theHelper);
796 } else {
797 final MoneyWiseAnalysisAccountBucket<?> myAccount = getAccountBucket(pDebit);
798 myAccount.adjustForDebit(theHelper);
799 }
800
801
802 if (!myCat.isTransfer()) {
803
804 theCategoryBuckets.adjustCategories(theHelper, myCat);
805 }
806 }
807
808
809
810
811
812
813 private void processCreditXferIn(final MoneyWiseSecurityHolding pHolding) {
814
815 OceanusMoney myAmount = theHelper.getCreditAmount();
816 final OceanusRatio myExchangeRate = theHelper.getCreditExchangeRate();
817 final MoneyWiseSecurity mySecurity = pHolding.getSecurity();
818
819
820 final MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pHolding);
821 final boolean isForeign = myAsset.isForeignCurrency();
822
823
824 if (isForeign) {
825
826 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myAmount);
827
828
829 myAmount = theHelper.getLocalAmount();
830 }
831
832
833 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myAmount);
834 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myAmount);
835
836
837 final MoneyWiseSecurityClass mySecClass = mySecurity.getCategoryClass();
838 OceanusUnits myDeltaUnits = theHelper.getCreditUnits();
839 OceanusUnits myUnits = myAsset.getValues().getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
840 if (mySecClass.isAutoUnits() && myUnits.isZero()) {
841 myDeltaUnits = OceanusUnits.getWholeUnits(mySecClass.getAutoUnits());
842 }
843
844
845 if (myDeltaUnits != null) {
846
847 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDeltaUnits);
848 }
849
850
851 myAsset.adjustForNIPayments(theHelper);
852
853
854 final OceanusPrice myPrice = thePriceMap.getPriceForDate(mySecurity, theHelper.getDate());
855
856
857 myUnits = myAsset.getValues().getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
858 OceanusMoney myValue = myPrice.unitsAtPrice(myUnits);
859
860
861 if (isForeign) {
862
863 myValue = myValue.convertCurrency(theAnalysis.getCurrency().getCurrency(), myExchangeRate);
864 }
865
866
867 final MoneyWiseAnalysisSecurityValues myValues = myAsset.registerTransaction(theHelper);
868 myValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myPrice);
869 myValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myValue);
870 myValues.setValue(MoneyWiseAnalysisSecurityAttr.CASHINVESTED, myAmount);
871 if (isForeign) {
872 myValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myExchangeRate);
873 }
874 }
875
876
877
878
879
880
881
882
883
884
885 private void processDividend(final MoneyWiseSecurityHolding pHolding,
886 final MoneyWiseTransAsset pCredit) {
887
888 final MoneyWisePortfolio myPortfolio = pHolding.getPortfolio();
889 final MoneyWiseSecurity mySecurity = pHolding.getSecurity();
890 OceanusMoney myAmount = theHelper.getDebitAmount();
891 final OceanusMoney myTaxCredit = theHelper.getTaxCredit();
892 final OceanusUnits myDeltaUnits = theHelper.getAccountDeltaUnits();
893 final MoneyWiseTaxCredit myYear = theHelper.getTransaction().getTaxYear();
894
895
896 MoneyWiseTransCategory myCat = myPortfolio.getDetailedCategory(theHelper.getCategory(), myYear);
897 myCat = mySecurity.getDetailedCategory(myCat, myYear);
898
899
900 final MoneyWiseAssetBase myDebit = mySecurity.getParent();
901
902
903 final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myDebit);
904 myPayee.adjustForDebit(theHelper);
905
906
907 final MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pHolding);
908 final boolean isForeign = myAsset.isForeignCurrency();
909 final boolean isReInvest = pCredit instanceof MoneyWiseSecurityHolding;
910
911
912 if (isForeign) {
913
914 if (isReInvest) {
915
916 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myAmount);
917 myAsset.getValues().setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, theHelper.getCreditExchangeRate());
918 }
919
920
921 myAmount = theHelper.getLocalAmount();
922 }
923
924
925 if (isReInvest) {
926
927 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myAmount);
928
929
930 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myAmount);
931
932
933 if (myDeltaUnits != null) {
934
935 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDeltaUnits);
936 }
937
938
939 if (myTaxCredit != null) {
940
941 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.DIVIDEND, myTaxCredit);
942 }
943
944
945 } else {
946
947 final OceanusMoney myAdjust = new OceanusMoney(myAmount);
948
949
950 if (myTaxCredit != null) {
951 myAdjust.addAmount(myTaxCredit);
952 }
953
954
955 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.DIVIDEND, myAdjust);
956
957
958 final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket((MoneyWiseAssetBase) pCredit);
959 myBucket.adjustForCredit(theHelper);
960 }
961
962
963 myAsset.registerTransaction(theHelper);
964
965
966 theTaxMan.adjustForTaxPayments(theHelper);
967
968
969 theCategoryBuckets.adjustCategories(theHelper, myCat);
970 }
971
972
973
974
975
976
977
978
979
980 private void processTransferOut(final MoneyWiseSecurityHolding pHolding,
981 final MoneyWiseAssetBase pCredit) {
982
983 final MoneyWiseTransCategory myCat = theHelper.getCategory();
984
985
986 processDebitXferOut(pHolding);
987
988
989 final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket(pCredit);
990 myBucket.adjustForCredit(theHelper);
991
992
993 if (!myCat.isTransfer()) {
994
995 theCategoryBuckets.adjustCategories(theHelper, myCat);
996 }
997 }
998
999
1000
1001
1002
1003
1004
1005
1006 private void processDebitXferOut(final MoneyWiseSecurityHolding pHolding) {
1007
1008 final MoneyWiseSecurity myDebit = pHolding.getSecurity();
1009 OceanusMoney myAmount = theHelper.getDebitAmount();
1010 boolean isLargeCash = false;
1011
1012
1013 final MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pHolding);
1014 MoneyWiseAnalysisSecurityValues myValues = myAsset.getValues();
1015 final OceanusRatio myXchangeRate = theHelper.getDebitExchangeRate();
1016 final boolean isForeign = myAsset.isForeignCurrency();
1017
1018
1019 if (isForeign) {
1020
1021 final OceanusMoney myDelta = new OceanusMoney(myAmount);
1022 myDelta.negate();
1023 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myDelta);
1024
1025
1026 myAmount = theHelper.getLocalAmount();
1027 }
1028
1029
1030 final OceanusMoney myDelta = new OceanusMoney(myAmount);
1031 myDelta.negate();
1032 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myDelta);
1033
1034
1035 final OceanusPrice myPrice = thePriceMap.getPriceForDate(myDebit, theHelper.getDate());
1036
1037
1038 OceanusUnits myUnits = Objects.requireNonNull(myValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS));
1039 OceanusMoney myAllowedCost = new OceanusMoney(myAmount);
1040 final OceanusMoney myCost = myValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
1041 OceanusRatio myCostDilution = null;
1042 OceanusMoney myConsideration = null;
1043
1044
1045 OceanusUnits myDeltaUnits = theHelper.getCategoryClass().isSecurityClosure()
1046 ? myUnits
1047 : theHelper.getDebitUnits();
1048 final boolean isCapitalDistribution = myDeltaUnits == null;
1049
1050
1051 if (!isCapitalDistribution) {
1052
1053 myAllowedCost = myCost.valueAtWeight(myDeltaUnits, myUnits);
1054
1055
1056 myDeltaUnits = new OceanusUnits(myDeltaUnits);
1057 myDeltaUnits.negate();
1058
1059
1060 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDeltaUnits);
1061 final OceanusUnits myNewUnits = myValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
1062
1063
1064 myCostDilution = new OceanusRatio(myNewUnits, myUnits);
1065 myUnits = myNewUnits;
1066 }
1067
1068
1069 OceanusMoney myValue = myPrice.unitsAtPrice(myUnits);
1070
1071
1072 if (isForeign) {
1073
1074 myValue = myValue.convertCurrency(theAnalysis.getCurrency().getCurrency(), myXchangeRate);
1075 }
1076
1077
1078 if (isCapitalDistribution) {
1079
1080 final OceanusMoney myPortion = myValue.valueAtRate(LIMIT_RATE);
1081 isLargeCash = (myAmount.compareTo(LIMIT_VALUE) > 0)
1082 && (myAmount.compareTo(myPortion) > 0);
1083
1084
1085 if (isLargeCash) {
1086
1087 myConsideration = new OceanusMoney(myAmount);
1088 myConsideration.addAmount(myValue);
1089
1090
1091 myAllowedCost = myCost.valueAtWeight(myAmount, myConsideration);
1092
1093
1094 myCostDilution = new OceanusRatio(myValue, myConsideration);
1095
1096
1097 } else {
1098
1099 myAllowedCost = myAmount.compareTo(myCost) > 0
1100 ? new OceanusMoney(myCost)
1101 : new OceanusMoney(myAmount);
1102 }
1103 }
1104
1105
1106 final OceanusMoney myDeltaCost = new OceanusMoney(myAllowedCost);
1107 myDeltaCost.negate();
1108
1109
1110 if (myDeltaCost.isNonZero()) {
1111
1112 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
1113 }
1114
1115
1116 final OceanusMoney myCapitalGain = new OceanusMoney(myAmount);
1117 myCapitalGain.addAmount(myDeltaCost);
1118
1119
1120 if (myCapitalGain.isNonZero()) {
1121
1122 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS, myCapitalGain);
1123
1124
1125 theCategoryBuckets.adjustStandardGain(theHelper, pHolding, myCapitalGain);
1126 }
1127
1128
1129 myValues = myAsset.registerTransaction(theHelper);
1130
1131
1132 myValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myPrice);
1133 myValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myValue);
1134 myValues.setValue(MoneyWiseAnalysisSecurityAttr.RETURNEDCASH, myAmount);
1135 myValues.setValue(MoneyWiseAnalysisSecurityAttr.ALLOWEDCOST, myAllowedCost);
1136 if (myCostDilution != null) {
1137 myValues.setValue(MoneyWiseAnalysisSecurityAttr.COSTDILUTION, myCostDilution);
1138 }
1139 if (myConsideration != null) {
1140 myValues.setValue(MoneyWiseAnalysisSecurityAttr.CONSIDERATION, myConsideration);
1141 }
1142 if (myCapitalGain.isNonZero()) {
1143 myValues.setValue(MoneyWiseAnalysisSecurityAttr.CAPITALGAIN, myCapitalGain);
1144 }
1145 if (isForeign) {
1146 myValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myXchangeRate);
1147 }
1148 if (isCapitalDistribution) {
1149 myValues.setValue(MoneyWiseAnalysisSecurityAttr.CASHTYPE, isLargeCash
1150 ? MoneyWiseCashType.LARGECASH
1151 : MoneyWiseCashType.SMALLCASH);
1152 }
1153 }
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163 private void processStockXchange(final MoneyWiseSecurityHolding pDebit,
1164 final MoneyWiseSecurityHolding pCredit) {
1165
1166 processDebitXferOut(pDebit);
1167
1168
1169 processCreditXferIn(pCredit);
1170 }
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180 private void processChargeableGain(final MoneyWiseSecurityHolding pHolding,
1181 final MoneyWiseAssetBase pCredit) {
1182
1183 final MoneyWiseSecurity myDebit = pHolding.getSecurity();
1184 OceanusMoney myAmount = theHelper.getDebitAmount();
1185 OceanusUnits myDeltaUnits = theHelper.getDebitUnits();
1186
1187
1188 final MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pHolding);
1189 final MoneyWiseAnalysisSecurityValues myValues = myAsset.getValues();
1190
1191
1192 if (Boolean.TRUE.equals(myAsset.isForeignCurrency())) {
1193
1194 final OceanusMoney myDelta = new OceanusMoney(myAmount);
1195 myDelta.negate();
1196 myValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, theHelper.getDebitExchangeRate());
1197 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myDelta);
1198
1199
1200 myAmount = theHelper.getLocalAmount();
1201 }
1202
1203
1204 final OceanusMoney myDelta = new OceanusMoney(myAmount);
1205 myDelta.negate();
1206 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myDelta);
1207
1208
1209 OceanusMoney myReduction = new OceanusMoney(myAmount);
1210 final OceanusMoney myCost = myValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
1211
1212
1213 if (myDeltaUnits != null) {
1214
1215 final OceanusUnits myUnits = myValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
1216 myReduction = myCost.valueAtWeight(myDeltaUnits, myUnits);
1217
1218
1219 myDeltaUnits = new OceanusUnits(myDeltaUnits);
1220 myDeltaUnits.negate();
1221
1222
1223 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDeltaUnits);
1224 }
1225
1226
1227 if (myReduction.compareTo(myCost) > 0) {
1228
1229 myReduction = new OceanusMoney(myCost);
1230 }
1231
1232
1233 final OceanusMoney myDeltaCost = new OceanusMoney(myReduction);
1234 myDeltaCost.negate();
1235
1236
1237 if (myDeltaCost.isNonZero()) {
1238
1239 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
1240 }
1241
1242
1243 final OceanusMoney myDeltaGains = new OceanusMoney(myAmount);
1244 myDeltaGains.addAmount(myDeltaCost);
1245
1246
1247 if (myDeltaGains.isNonZero()) {
1248
1249 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS, myDeltaGains);
1250 }
1251
1252
1253 myAsset.registerTransaction(theHelper);
1254
1255
1256 final MoneyWiseAssetBase myParent = myDebit.getParent();
1257
1258
1259 final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myParent);
1260 myPayee.adjustForTaxCredit(theHelper);
1261
1262
1263 final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket(pCredit);
1264 myBucket.adjustForCredit(theHelper);
1265
1266
1267 theCategoryBuckets.adjustChargeableGain(theHelper, myReduction);
1268
1269
1270 theTaxMan.adjustForTaxPayments(theHelper);
1271
1272
1273 theTaxBasisBuckets.recordChargeableGain(theHelper.getTransaction(), myDeltaGains);
1274 }
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284 private void processStockDeMerger(final MoneyWiseSecurityHolding pDebit,
1285 final MoneyWiseSecurityHolding pCredit) {
1286
1287 MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pDebit);
1288 MoneyWiseAnalysisSecurityValues myValues = myAsset.getValues();
1289 final OceanusRatio myDebitRate = theHelper.getDebitExchangeRate();
1290
1291
1292 final OceanusMoney myCost = myValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
1293 final OceanusRatio myDilution = theHelper.getDilution();
1294 final OceanusUnits myDeltaUnits = theHelper.getAccountDeltaUnits();
1295
1296
1297 if (myDeltaUnits != null) {
1298
1299 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDeltaUnits);
1300 }
1301
1302
1303 final OceanusMoney myNewCost = myCost.getDilutedMoney(myDilution);
1304 final OceanusRatio myCostDilution = new OceanusRatio(myNewCost, myCost);
1305
1306
1307 OceanusMoney myDeltaCost = new OceanusMoney(myNewCost);
1308 myDeltaCost.subtractAmount(myCost);
1309
1310
1311 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
1312 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myDeltaCost);
1313 final boolean isForeignDebit = myAsset.isForeignCurrency();
1314 if (isForeignDebit) {
1315 final OceanusMoney myInvested = myDeltaCost.convertCurrency(myAsset.getCurrency().getCurrency(), myDebitRate);
1316 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myInvested);
1317 }
1318
1319
1320 myValues = myAsset.registerTransaction(theHelper);
1321
1322
1323 myAsset = thePortfolioBuckets.getBucket(pCredit);
1324
1325
1326 myDeltaCost = new OceanusMoney(myDeltaCost);
1327 myDeltaCost.negate();
1328
1329
1330 myValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myDeltaCost);
1331 myValues.setValue(MoneyWiseAnalysisSecurityAttr.COSTDILUTION, myCostDilution);
1332 if (isForeignDebit) {
1333 myValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myDebitRate);
1334 }
1335
1336
1337 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
1338 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myDeltaCost);
1339 final boolean isForeignCredit = myAsset.isForeignCurrency();
1340 final OceanusRatio myCreditRate = theHelper.getCreditExchangeRate();
1341 if (isForeignCredit) {
1342 final OceanusMoney myInvested = myDeltaCost.convertCurrency(myAsset.getCurrency().getCurrency(), myCreditRate);
1343 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myInvested);
1344 }
1345
1346
1347 final OceanusDate myDate = theHelper.getDate();
1348 final OceanusPrice myCreditPrice = thePriceMap.getPriceForDate(myAsset.getSecurity(), myDate);
1349 final Currency myCurrency = theAnalysis.getCurrency().getCurrency();
1350
1351
1352 final OceanusUnits myCreditUnits = theHelper.getPartnerDeltaUnits();
1353 OceanusMoney myCreditXferValue = myCreditPrice.unitsAtPrice(myCreditUnits);
1354 if (isForeignCredit) {
1355 myCreditXferValue = myCreditXferValue.convertCurrency(myCurrency, myCreditRate);
1356 }
1357
1358
1359 myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myCreditUnits);
1360
1361
1362 myValues = myAsset.registerTransaction(theHelper);
1363
1364
1365 myValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myDeltaCost);
1366 myValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myCreditPrice);
1367 myValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDVALUE, myCreditXferValue);
1368 if (isForeignCredit) {
1369 myValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myCreditRate);
1370 }
1371
1372
1373 }
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384 private void processStockTakeover(final MoneyWiseSecurityHolding pDebit,
1385 final MoneyWiseSecurityHolding pCredit) {
1386 final OceanusMoney myAmount = theHelper.getReturnedCash();
1387 final MoneyWiseTransAsset myReturnedCashAct = theHelper.getReturnedCashAccount();
1388
1389
1390 if (myReturnedCashAct != null
1391 && myAmount.isNonZero()) {
1392
1393 processStockAndCashTakeOver(pDebit, pCredit);
1394 } else {
1395
1396 processStockOnlyTakeOver(pDebit, pCredit);
1397 }
1398 }
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408 private void processStockOnlyTakeOver(final MoneyWiseSecurityHolding pDebit,
1409 final MoneyWiseSecurityHolding pCredit) {
1410
1411 final MoneyWiseSecurity myCredit = pCredit.getSecurity();
1412 final MoneyWiseSecurity myDebit = pDebit.getSecurity();
1413
1414
1415 final MoneyWiseAnalysisSecurityBucket myDebitAsset = thePortfolioBuckets.getBucket(pDebit);
1416 MoneyWiseAnalysisSecurityValues myDebitValues = myDebitAsset.getValues();
1417 final MoneyWiseAnalysisSecurityBucket myCreditAsset = thePortfolioBuckets.getBucket(pCredit);
1418 final OceanusDate myDate = theHelper.getDate();
1419
1420
1421 final OceanusPrice myCreditPrice = thePriceMap.getPriceForDate(myCredit, myDate);
1422 final OceanusPrice myDebitPrice = thePriceMap.getPriceForDate(myDebit, myDate);
1423 final OceanusRatio myDebitRate = theHelper.getDebitExchangeRate();
1424 final OceanusRatio myCreditRate = theHelper.getCreditExchangeRate();
1425 final Currency myCurrency = theAnalysis.getCurrency().getCurrency();
1426
1427
1428 OceanusUnits myCreditUnits = theHelper.getPartnerDeltaUnits();
1429 OceanusMoney myCreditXferValue = myCreditPrice.unitsAtPrice(myCreditUnits);
1430 OceanusUnits myDebitUnits = myDebitValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
1431 OceanusMoney myDebitValue = myDebitPrice.unitsAtPrice(myDebitUnits);
1432 OceanusMoney myInvested = myDebitValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.INVESTED);
1433
1434
1435 final boolean isForeignDebit = myDebitAsset.isForeignCurrency();
1436 if (isForeignDebit) {
1437 myDebitValue = myDebitValue.convertCurrency(myCurrency, myDebitRate);
1438 }
1439
1440
1441 final boolean isForeignCredit = myCreditAsset.isForeignCurrency();
1442 if (isForeignCredit) {
1443 myCreditXferValue = myCreditXferValue.convertCurrency(myCurrency, myCreditRate);
1444 }
1445
1446
1447 final OceanusMoney myDebitCost = myDebitValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
1448
1449
1450 OceanusMoney myProfit = new OceanusMoney(myDebitValue);
1451 myProfit.subtractAmount(myDebitCost);
1452 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
1453 myProfit = new OceanusMoney(myProfit);
1454 myProfit.negate();
1455 myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
1456
1457
1458 myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDebitCost);
1459 myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myCreditUnits);
1460 myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myInvested);
1461 if (isForeignCredit) {
1462 final OceanusMoney myForeign = myInvested.convertCurrency(myCreditAsset.getCurrency().getCurrency(), myCreditRate);
1463 myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myForeign);
1464 }
1465
1466
1467 myCreditUnits = myCreditAsset.getValues().getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
1468 OceanusMoney myCreditValue = myCreditPrice.unitsAtPrice(myCreditUnits);
1469 if (isForeignCredit) {
1470 myCreditValue = myCreditValue.convertCurrency(myCurrency, myCreditRate);
1471 }
1472
1473
1474 final MoneyWiseAnalysisSecurityValues myCreditValues = myCreditAsset.registerTransaction(theHelper);
1475 myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myCreditPrice);
1476 myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDVALUE, myCreditXferValue);
1477 myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myDebitCost);
1478 myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myCreditValue);
1479 if (isForeignCredit) {
1480 myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myCreditRate);
1481 }
1482
1483
1484 final OceanusMoney myDeltaCost = new OceanusMoney(myDebitCost);
1485 myDeltaCost.negate();
1486 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
1487 myDeltaCost.negate();
1488
1489
1490 myDebitUnits = new OceanusUnits(myDebitUnits);
1491 myDebitUnits.negate();
1492 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDebitUnits);
1493
1494
1495 myInvested = new OceanusMoney(myInvested);
1496 myInvested.negate();
1497 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myInvested);
1498 if (isForeignDebit) {
1499 myInvested = new OceanusMoney(myDebitValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED));
1500 myInvested.negate();
1501 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myInvested);
1502 }
1503
1504
1505 myDebitValues = myDebitAsset.registerTransaction(theHelper);
1506 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myDebitPrice);
1507 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myDebitValue);
1508 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDVALUE, myCreditXferValue);
1509 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myDeltaCost);
1510 if (isForeignDebit) {
1511 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myDebitRate);
1512 }
1513 }
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524 private void processStockAndCashTakeOver(final MoneyWiseSecurityHolding pDebit,
1525 final MoneyWiseSecurityHolding pCredit) {
1526
1527 final MoneyWiseSecurity myDebit = pDebit.getSecurity();
1528 final MoneyWiseSecurity myCredit = pCredit.getSecurity();
1529 final OceanusDate myDate = theHelper.getDate();
1530 final MoneyWiseTransAsset myReturnedCashAccount = theHelper.getReturnedCashAccount();
1531 final OceanusMoney myAmount = theHelper.getLocalReturnedCash();
1532
1533
1534 final MoneyWiseAnalysisSecurityBucket myDebitAsset = thePortfolioBuckets.getBucket(pDebit);
1535 MoneyWiseAnalysisSecurityValues myDebitValues = myDebitAsset.getValues();
1536 final MoneyWiseAnalysisSecurityBucket myCreditAsset = thePortfolioBuckets.getBucket(pCredit);
1537
1538
1539 final OceanusPrice myDebitPrice = thePriceMap.getPriceForDate(myDebit, myDate);
1540 final OceanusPrice myCreditPrice = thePriceMap.getPriceForDate(myCredit, myDate);
1541 final OceanusRatio myDebitRate = theHelper.getDebitExchangeRate();
1542 final OceanusRatio myCreditRate = theHelper.getCreditExchangeRate();
1543 final Currency myCurrency = theAnalysis.getCurrency().getCurrency();
1544
1545
1546 OceanusUnits myDebitUnits = myDebitValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
1547 OceanusMoney myDebitValue = myDebitPrice.unitsAtPrice(myDebitUnits);
1548
1549
1550 OceanusUnits myCreditUnits = theHelper.getPartnerDeltaUnits();
1551 OceanusMoney myCreditXferValue = myCreditPrice.unitsAtPrice(myCreditUnits);
1552
1553
1554 final boolean isForeignDebit = myDebitAsset.isForeignCurrency();
1555 if (isForeignDebit) {
1556 myDebitValue = myDebitValue.convertCurrency(myCurrency, myDebitRate);
1557 }
1558
1559
1560 final boolean isForeignCredit = myCreditAsset.isForeignCurrency();
1561 if (isForeignCredit) {
1562 myCreditXferValue = myCreditXferValue.convertCurrency(myCurrency, myCreditRate);
1563 }
1564
1565
1566 final OceanusMoney myConsideration = new OceanusMoney(myAmount);
1567 myConsideration.addAmount(myCreditXferValue);
1568
1569
1570 final OceanusMoney myCost = myDebitValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
1571 OceanusRatio myCostDilution = null;
1572 final OceanusMoney myCostXfer;
1573 final OceanusMoney myAllowedCost;
1574
1575
1576 final OceanusMoney myPortion = myDebitValue.valueAtRate(LIMIT_RATE);
1577 final boolean isLargeCash = (myAmount.compareTo(LIMIT_VALUE) > 0)
1578 && (myAmount.compareTo(myPortion) > 0);
1579
1580
1581 if (isLargeCash) {
1582
1583 myCostXfer = myCost.valueAtWeight(myCreditXferValue, myConsideration);
1584
1585
1586 myCostDilution = new OceanusRatio(myAmount, myConsideration);
1587
1588
1589 myAllowedCost = new OceanusMoney(myCost);
1590 myAllowedCost.subtractAmount(myCostXfer);
1591
1592
1593 } else {
1594
1595 myAllowedCost = myAmount.compareTo(myCost) > 0
1596 ? new OceanusMoney(myCost)
1597 : new OceanusMoney(myAmount);
1598
1599
1600 myCostXfer = new OceanusMoney(myCost);
1601 myCostXfer.subtractAmount(myAllowedCost);
1602 }
1603
1604
1605 final OceanusMoney myCapitalGain = new OceanusMoney(myAmount);
1606 myCapitalGain.subtractAmount(myAllowedCost);
1607 if (myCapitalGain.isNonZero()) {
1608
1609 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS, myCapitalGain);
1610
1611
1612 theCategoryBuckets.adjustStandardGain(theHelper, pDebit, myCapitalGain);
1613 }
1614
1615
1616 OceanusMoney myProfit = new OceanusMoney(myCreditXferValue);
1617 myProfit.subtractAmount(myCostXfer);
1618 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
1619 myProfit = new OceanusMoney(myProfit);
1620 myProfit.negate();
1621 myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
1622
1623
1624 myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myCostXfer);
1625 myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myCreditUnits);
1626 myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myCostXfer);
1627 if (isForeignCredit) {
1628 final OceanusMoney myForeign = myCostXfer.convertCurrency(myCreditAsset.getCurrency().getCurrency(), myCreditRate);
1629 myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myForeign);
1630 }
1631
1632
1633 myCreditUnits = myCreditAsset.getValues().getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
1634 OceanusMoney myCreditValue = myCreditPrice.unitsAtPrice(myCreditUnits);
1635 if (isForeignCredit) {
1636 myCreditValue = myCreditValue.convertCurrency(myCurrency, myCreditRate);
1637 }
1638
1639
1640 final MoneyWiseAnalysisSecurityValues myCreditValues = myCreditAsset.registerTransaction(theHelper);
1641 myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myCreditPrice);
1642 myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDVALUE, myCreditXferValue);
1643 myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myCostXfer);
1644 myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myCreditValue);
1645 if (isForeignCredit) {
1646 myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myCreditRate);
1647 }
1648
1649
1650 final OceanusMoney myDeltaCost = new OceanusMoney(myCost);
1651 myDeltaCost.negate();
1652 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
1653
1654
1655 myDebitUnits = new OceanusUnits(myDebitUnits);
1656 myDebitUnits.negate();
1657 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDebitUnits);
1658
1659
1660 OceanusMoney myInvested = myDebitValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.INVESTED);
1661 myInvested = new OceanusMoney(myInvested);
1662 myInvested.setZero();
1663 myInvested.subtractAmount(myAmount);
1664 myInvested.subtractAmount(myCostXfer);
1665 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myInvested);
1666 if (isForeignDebit) {
1667 myInvested = myInvested.convertCurrency(myDebitAsset.getCurrency().getCurrency(), myDebitRate);
1668 myInvested.negate();
1669 myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myInvested);
1670 }
1671
1672
1673 myDebitValues = myDebitAsset.registerTransaction(theHelper);
1674 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myDebitPrice);
1675 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myDebitValue);
1676 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.CONSIDERATION, myConsideration);
1677 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.RETURNEDCASH, myAmount);
1678 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDVALUE, myCreditXferValue);
1679 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myCostXfer);
1680 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.ALLOWEDCOST, myAllowedCost);
1681 if (myCostDilution != null) {
1682 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.COSTDILUTION, myCostDilution);
1683 }
1684 if (myCapitalGain.isNonZero()) {
1685 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.CAPITALGAIN, myCapitalGain);
1686 }
1687 if (isForeignDebit) {
1688 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myDebitRate);
1689 }
1690 myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.CASHTYPE, isLargeCash
1691 ? MoneyWiseCashType.LARGECASH
1692 : MoneyWiseCashType.SMALLCASH);
1693
1694
1695 final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket((MoneyWiseAssetBase) myReturnedCashAccount);
1696 myBucket.adjustForReturnedCashCredit(theHelper);
1697 }
1698
1699
1700
1701
1702
1703
1704
1705 private MoneyWiseAnalysisAccountBucket<?> getAccountBucket(final MoneyWiseAssetBase pAsset) {
1706 return switch (pAsset.getAssetType()) {
1707 case DEPOSIT -> theDepositBuckets.getBucket((MoneyWiseDeposit) pAsset);
1708 case CASH -> theCashBuckets.getBucket((MoneyWiseCash) pAsset);
1709 case LOAN -> theLoanBuckets.getBucket((MoneyWiseLoan) pAsset);
1710 case PORTFOLIO -> thePortfolioBuckets.getCashBucket((MoneyWisePortfolio) pAsset);
1711 default -> throw new IllegalArgumentException();
1712 };
1713 }
1714 }