MoneyWiseAnalysisTransAnalyser.java
/*
* MoneyWise: Finance Application
* Copyright 2012-2026. Tony Washer
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.analyse;
import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
import io.github.tonywasher.joceanus.oceanus.decimal.OceanusPrice;
import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRate;
import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRatio;
import io.github.tonywasher.joceanus.oceanus.decimal.OceanusUnits;
import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
import io.github.tonywasher.joceanus.oceanus.profile.OceanusProfile;
import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
import io.github.tonywasher.joceanus.metis.preference.MetisPreferenceManager;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseAssetBase;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseAssetType;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseCash;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDataSet;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDeposit;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseLoan;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePortfolio;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePortfolio.MoneyWisePortfolioList;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurityHolding;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurityHolding.MoneyWiseSecurityHoldingMap;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurityPrice.MoneyWiseSecurityPriceDataMap;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTax.MoneyWiseTaxCredit;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransAsset;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransCategory;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransTag;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransaction;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransaction.MoneyWiseTransactionList;
import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWisePayeeClass;
import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWisePortfolioClass;
import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseSecurityClass;
import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTransCategoryClass;
import io.github.tonywasher.joceanus.moneywise.exc.MoneyWiseLogicException;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysis;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisAccountBucket;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisCashBucket.MoneyWiseAnalysisCashBucketList;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisDataResource;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisDepositBucket.MoneyWiseAnalysisDepositBucketList;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisLoanBucket.MoneyWiseAnalysisLoanBucketList;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPayeeBucket;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPayeeBucket.MoneyWiseAnalysisPayeeBucketList;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioBucket;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioBucket.MoneyWiseAnalysisPortfolioBucketList;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioCashBucket;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisSecurityBucket;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTaxBasisBucket.MoneyWiseAnalysisTaxBasisBucketList;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTransCategoryBucket;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTransCategoryBucket.MoneyWiseAnalysisTransCategoryBucketList;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTransTagBucket.MoneyWiseAnalysisTransTagBucketList;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTransactionHelper;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.values.MoneyWiseAnalysisSecurityAttr;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.values.MoneyWiseAnalysisSecurityValues;
import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseCashType;
import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
import java.util.Currency;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
/**
* Class to analyse transactions.
*
* @author Tony Washer
*/
public class MoneyWiseAnalysisTransAnalyser
implements MetisFieldItem {
/**
* Local Report fields.
*/
private static final String ERROR_CATEGORY = "Unexpected Category Type: ";
/**
* Local Report fields.
*/
private static final MetisFieldSet<MoneyWiseAnalysisTransAnalyser> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseAnalysisTransAnalyser.class);
/*
* Declare Fields.
*/
static {
FIELD_DEFS.declareLocalField(MoneyWiseAnalysisDataResource.ANALYSIS_NAME, MoneyWiseAnalysisTransAnalyser::getAnalysis);
}
/**
* The Amount Tax threshold for "small" transactions (£3000).
*/
private static final OceanusMoney LIMIT_VALUE = OceanusMoney.getWholeUnits(3000);
/**
* The Rate Tax threshold for "small" transactions (5%).
*/
private static final OceanusRate LIMIT_RATE = OceanusRate.getWholePercentage(5);
/**
* The security holding map.
*/
private final MoneyWiseSecurityHoldingMap theHoldingMap;
/**
* The security price map.
*/
private final MoneyWiseSecurityPriceDataMap thePriceMap;
/**
* The analysis.
*/
private final MoneyWiseAnalysis theAnalysis;
/**
* The transaction helper.
*/
private final MoneyWiseAnalysisTransactionHelper theHelper;
/**
* The deposit bucket list.
*/
private final MoneyWiseAnalysisDepositBucketList theDepositBuckets;
/**
* The cash bucket list.
*/
private final MoneyWiseAnalysisCashBucketList theCashBuckets;
/**
* The deposit bucket list.
*/
private final MoneyWiseAnalysisLoanBucketList theLoanBuckets;
/**
* The portfolio bucket list.
*/
private final MoneyWiseAnalysisPortfolioBucketList thePortfolioBuckets;
/**
* The payee bucket list.
*/
private final MoneyWiseAnalysisPayeeBucketList thePayeeBuckets;
/**
* The transaction category buckets.
*/
private final MoneyWiseAnalysisTransCategoryBucketList theCategoryBuckets;
/**
* The transactionTag buckets.
*/
private final MoneyWiseAnalysisTransTagBucketList theTagBuckets;
/**
* The taxBasis buckets.
*/
private final MoneyWiseAnalysisTaxBasisBucketList theTaxBasisBuckets;
/**
* The taxMan account.
*/
private final MoneyWiseAnalysisPayeeBucket theTaxMan;
/**
* The statePension account.
*/
private final MoneyWiseAnalysisSecurityBucket theStatePension;
/**
* The profile.
*/
private final OceanusProfile theProfile;
/**
* Constructor for a complete set of accounts.
*
* @param pTask the profiled task
* @param pEditSet the EditSet to analyse
* @param pPreferenceMgr the preference manager
* @throws OceanusException on error
*/
public MoneyWiseAnalysisTransAnalyser(final OceanusProfile pTask,
final PrometheusEditSet pEditSet,
final MetisPreferenceManager pPreferenceMgr) throws OceanusException {
/* Start a new task */
theProfile = pTask;
final OceanusProfile myTask = theProfile.startTask("analyseTransactions");
final MoneyWiseDataSet myDataSet = (MoneyWiseDataSet) pEditSet.getDataSet();
/* Store the parameters */
theHoldingMap = pEditSet.getDataList(MoneyWiseBasicDataType.PORTFOLIO, MoneyWisePortfolioList.class).getSecurityHoldingsMap();
thePriceMap = myDataSet.getSecurityPriceDataMap();
/* Access the lists */
final MoneyWiseTransactionList myTrans = pEditSet.getDataList(MoneyWiseBasicDataType.TRANSACTION, MoneyWiseTransactionList.class);
/* Create a new analysis */
myTask.startTask("Initialise");
theAnalysis = new MoneyWiseAnalysis(pEditSet, pPreferenceMgr);
/* Create new helper and set opening balances */
theHelper = new MoneyWiseAnalysisTransactionHelper(myDataSet);
theAnalysis.addOpeningBalances(theHelper);
/* Access details from the analysis */
theDepositBuckets = theAnalysis.getDeposits();
theCashBuckets = theAnalysis.getCash();
theLoanBuckets = theAnalysis.getLoans();
thePortfolioBuckets = theAnalysis.getPortfolios();
thePayeeBuckets = theAnalysis.getPayees();
theCategoryBuckets = theAnalysis.getTransCategories();
theTagBuckets = theAnalysis.getTransactionTags();
theTaxBasisBuckets = theAnalysis.getTaxBasis();
theTaxMan = thePayeeBuckets.getBucket(MoneyWisePayeeClass.TAXMAN);
/* Access the StatePension security holding */
theStatePension = getStatePension(myDataSet);
/* Loop through the Transactions extracting relevant elements */
myTask.startTask("Transactions");
final Iterator<MoneyWiseTransaction> myIterator = myTrans.iterator();
while (myIterator.hasNext()) {
final MoneyWiseTransaction myCurr = myIterator.next();
/* Ignore deleted/header transactions */
if (myCurr.isDeleted() || myCurr.isHeader()) {
continue;
}
/* Touch underlying items */
myCurr.touchUnderlyingItems();
/* Process the transaction in the report set */
processTransaction(myCurr);
}
/* Complete the task */
myTask.end();
}
/**
* Obtain statePension bucket.
*
* @param pData the dataSet
* @return the statePension bucket
*/
private MoneyWiseAnalysisSecurityBucket getStatePension(final MoneyWiseDataSet pData) {
/* Access the singular portfolio and security */
final MoneyWisePortfolio myPensionPort = pData.getPortfolios().getSingularClass(MoneyWisePortfolioClass.PENSION);
final MoneyWiseSecurity myStatePension = pData.getSecurities().getSingularClass(MoneyWiseSecurityClass.STATEPENSION);
/* If they exist, access the bucket */
if (myPensionPort != null
&& myStatePension != null) {
final MoneyWiseSecurityHolding myHolding = pData.getPortfolios().getSecurityHoldingsMap().declareHolding(myPensionPort, myStatePension);
return thePortfolioBuckets.getBucket(myHolding);
}
/* Default to no bucket */
return null;
}
@Override
public MetisFieldSet<MoneyWiseAnalysisTransAnalyser> getDataFieldSet() {
return FIELD_DEFS;
}
@Override
public String formatObject(final OceanusDataFormatter pFormatter) {
return FIELD_DEFS.getName();
}
/**
* Obtain the analysis.
*
* @return the analysis
*/
public MoneyWiseAnalysis getAnalysis() {
return theAnalysis;
}
/**
* Mark active accounts.
*
* @throws OceanusException on error
*/
public void postProcessAnalysis() throws OceanusException {
/* Start a new task */
final OceanusProfile myTask = theProfile.startTask("postProcessAnalysis");
myTask.startTask("markActiveAccounts");
/* Mark relevant accounts */
theDepositBuckets.markActiveAccounts();
theCashBuckets.markActiveAccounts();
theLoanBuckets.markActiveAccounts();
/* Mark relevant securities */
thePortfolioBuckets.markActiveSecurities();
/* Complete the task */
myTask.end();
}
/**
* Process a transaction.
*
* @param pTrans the transaction to process
* @throws OceanusException on error
*/
private void processTransaction(final MoneyWiseTransaction pTrans) throws OceanusException {
/* Declare to helper */
theHelper.setTransaction(pTrans);
/* Access key details */
final MoneyWiseTransAsset myDebitAsset = theHelper.getDebitAsset();
final MoneyWiseTransAsset myCreditAsset = theHelper.getCreditAsset();
final MoneyWiseTaxCredit myYear = pTrans.getTaxYear();
/* Look for tags */
final List<MoneyWiseTransTag> myTags = pTrans.getTransactionTags();
if (myTags != null) {
/* Process the transaction tags */
theTagBuckets.processTransaction(pTrans, myTags.iterator());
}
/* If the event relates to a security item, split out the workings */
if (myDebitAsset instanceof MoneyWiseSecurityHolding) {
/* Process as a Security transaction */
processDebitSecurityTransaction((MoneyWiseSecurityHolding) myDebitAsset, myCreditAsset);
/* If the event relates to a security item, split out the workings */
} else if (myCreditAsset instanceof MoneyWiseSecurityHolding) {
/* Process as a Security transaction */
processCreditSecurityTransaction(myDebitAsset, (MoneyWiseSecurityHolding) myCreditAsset);
/* Else handle the portfolio transfer */
} else if (myDebitAsset instanceof MoneyWisePortfolio
&& myCreditAsset instanceof MoneyWisePortfolio
&& pTrans.getCategoryClass() == MoneyWiseTransCategoryClass.PORTFOLIOXFER
&& !myDebitAsset.equals(myCreditAsset)) {
/* Process portfolio transfer */
processPortfolioXfer((MoneyWisePortfolio) myDebitAsset, (MoneyWisePortfolio) myCreditAsset);
/* Else handle the event normally */
} else if (myDebitAsset instanceof MoneyWiseAssetBase
&& myCreditAsset instanceof MoneyWiseAssetBase) {
/* Access correctly */
MoneyWiseAssetBase myDebit = (MoneyWiseAssetBase) myDebitAsset;
MoneyWiseAssetBase myCredit = (MoneyWiseAssetBase) myCreditAsset;
MoneyWiseAssetBase myChild = null;
final OceanusMoney myAmount = pTrans.getAmount();
MoneyWiseTransCategory myCat = pTrans.getCategory();
/* Switch on category class */
switch (myCat.getCategoryTypeClass()) {
case INTEREST:
case LOYALTYBONUS:
/* Obtain detailed category */
myCat = myDebit.getDetailedCategory(myCat, myYear);
/* True debit account is the parent */
myChild = myDebit.equals(myCredit)
? null
: myDebit;
myDebit = myDebit.getParent();
break;
case LOANINTERESTEARNED:
case CASHBACK:
/* True debit account is the parent of the asset */
myDebit = myDebit.getParent();
break;
case RENTALINCOME:
case ROOMRENTALINCOME:
/* True debit account is the parent of the security */
myChild = myDebit.equals(myCredit)
? null
: myDebit;
myDebit = myCredit.getParent();
break;
case WRITEOFF:
case LOANINTERESTCHARGED:
/* True credit account is the parent of the loan */
myCredit = myCredit.getParent();
break;
default:
break;
}
/* If the debit account is auto-Expense */
if (myDebit instanceof MoneyWiseCash
&& myDebit.getAssetType() == MoneyWiseAssetType.AUTOEXPENSE) {
/* Access debit as cash */
final MoneyWiseCash myCash = (MoneyWiseCash) myDebit;
final MoneyWiseTransCategory myAuto = myCash.getAutoExpense();
myDebit = myCash.getAutoPayee();
myDebit.touchItem(pTrans);
/* Subtract expense from Payee bucket */
final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myDebit);
myPayee.subtractExpense(theHelper, myAmount);
/* Subtract expense from Category bucket */
final MoneyWiseAnalysisTransCategoryBucket myCatBucket = theCategoryBuckets.getBucket(myAuto);
myCatBucket.subtractExpense(theHelper, myAmount);
theTaxBasisBuckets.adjustAutoExpense(theHelper, false);
/* handle Payees */
} else if (MoneyWiseAssetType.PAYEE.equals(myDebit.getAssetType())) {
final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myDebit);
myPayee.adjustForDebit(theHelper);
/* handle valued assets */
} else {
final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket(myDebit);
myBucket.adjustForDebit(theHelper);
}
/* If the credit account is auto-Expense */
if (myCredit instanceof MoneyWiseCash
&& myCredit.getAssetType() == MoneyWiseAssetType.AUTOEXPENSE) {
/* Access credit as cash */
final MoneyWiseCash myCash = (MoneyWiseCash) myCredit;
final MoneyWiseTransCategory myAuto = myCash.getAutoExpense();
myCredit = myCash.getAutoPayee();
myCredit.touchItem(pTrans);
/* Add expense to Payee bucket */
final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myCredit);
myPayee.addExpense(theHelper, myAmount);
/* Adjust the relevant category bucket */
final MoneyWiseAnalysisTransCategoryBucket myCatBucket = theCategoryBuckets.getBucket(myAuto);
myCatBucket.addExpense(theHelper, myAmount);
theTaxBasisBuckets.adjustAutoExpense(theHelper, true);
/* handle Payees */
} else if (MoneyWiseAssetType.PAYEE.equals(myCredit.getAssetType())) {
final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myCredit);
myPayee.adjustForCredit(theHelper);
/* handle valued assets */
} else {
final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket(myCredit);
myBucket.adjustForCredit(theHelper);
}
/* If we should register the event with a child */
if (myChild != null) {
/* Access bucket and register it */
final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket(myChild);
myBucket.registerTransaction(pTrans);
}
/* Adjust the tax and NI payments */
theTaxMan.adjustForTaxPayments(theHelper);
theStatePension.adjustForNIPayments(theHelper);
/* If the event category is not a transfer */
if (!myCat.isTransfer()) {
/* Adjust the relevant category buckets */
theCategoryBuckets.adjustCategories(theHelper, myCat);
}
/* Unknown combination */
} else {
throw new MoneyWiseLogicException("Invalid Asset Pair: "
+ pTrans.getAccount().getAssetType()
+ " "
+ pTrans.getDirection()
+ " "
+ pTrans.getPartner().getAssetType());
}
}
/**
* Process a debit security transaction.
*
* @param pDebit the debit security
* @param pCredit the credit account
* @throws OceanusException on error
*/
private void processDebitSecurityTransaction(final MoneyWiseSecurityHolding pDebit,
final MoneyWiseTransAsset pCredit) throws OceanusException {
/* If credit account is also SecurityHolding */
if (pCredit instanceof MoneyWiseSecurityHolding) {
/* Split out working */
processDebitCreditSecurityTransaction(pDebit, (MoneyWiseSecurityHolding) pCredit);
return;
}
/* Switch on the category */
final MoneyWiseTransCategory myCat = theHelper.getCategory();
switch (myCat.getCategoryTypeClass()) {
/* Process a stock right waived */
case STOCKRIGHTSISSUE:
processTransferOut(pDebit, (MoneyWiseAssetBase) pCredit);
break;
/* Process a dividend */
case DIVIDEND:
processDividend(pDebit, pCredit);
break;
case PORTFOLIOXFER:
processPortfolioXfer(pDebit, (MoneyWisePortfolio) pCredit);
break;
/* Process standard transfer in/out */
case TRANSFER:
case SECURITYCLOSURE:
case EXPENSE:
case INHERITED:
case OTHERINCOME:
if (pDebit.getSecurity().isSecurityClass(MoneyWiseSecurityClass.LIFEBOND)) {
processChargeableGain(pDebit, (MoneyWiseAssetBase) pCredit);
} else {
processTransferOut(pDebit, (MoneyWiseAssetBase) pCredit);
}
break;
/* Throw an Exception */
default:
throw new MoneyWiseLogicException(ERROR_CATEGORY
+ myCat.getCategoryTypeClass());
}
}
/**
* Process a debit+credit security transaction.
*
* @param pDebit the debit security
* @param pCredit the credit security
* @throws OceanusException on error
*/
private void processDebitCreditSecurityTransaction(final MoneyWiseSecurityHolding pDebit,
final MoneyWiseSecurityHolding pCredit) throws OceanusException {
/* Switch on the category */
final MoneyWiseTransCategory myCat = theHelper.getCategory();
switch (myCat.getCategoryTypeClass()) {
/* Process a stock split */
case STOCKSPLIT:
case UNITSADJUST:
processUnitsAdjust(pDebit);
break;
/* Process a stock DeMerger */
case STOCKDEMERGER:
processStockDeMerger(pDebit, pCredit);
break;
/* Process a Stock TakeOver */
case SECURITYREPLACE:
case STOCKTAKEOVER:
processStockTakeover(pDebit, pCredit);
break;
/* Process a dividend */
case DIVIDEND:
processDividend(pDebit, pCredit);
break;
/* Process standard transfer in/out */
case TRANSFER:
case EXPENSE:
case INHERITED:
case OTHERINCOME:
processStockXchange(pDebit, pCredit);
break;
/* Throw an Exception */
default:
throw new MoneyWiseLogicException(ERROR_CATEGORY
+ myCat.getCategoryTypeClass());
}
}
/**
* Process a credit security transaction.
*
* @param pDebit the debit account
* @param pCredit the credit security holding
* @throws OceanusException on error
*/
private void processCreditSecurityTransaction(final MoneyWiseTransAsset pDebit,
final MoneyWiseSecurityHolding pCredit) throws OceanusException {
/* Input asset must be AssetBase */
if (!(pDebit instanceof MoneyWiseAssetBase)) {
throw new MoneyWiseLogicException("Invalid Debit Asset: "
+ pDebit.getAssetType());
}
final MoneyWiseAssetBase myDebit = (MoneyWiseAssetBase) pDebit;
/* Switch on the category */
final MoneyWiseTransCategory myCat = theHelper.getCategory();
switch (myCat.getCategoryTypeClass()) {
/* Process standard transfer in/out */
case STOCKRIGHTSISSUE:
case TRANSFER:
case EXPENSE:
case INHERITED:
case OTHERINCOME:
case PENSIONCONTRIB:
processTransferIn(myDebit, pCredit);
break;
/* Throw an Exception */
default:
throw new MoneyWiseLogicException(ERROR_CATEGORY
+ myCat.getCategoryTypeClass());
}
}
/**
* Process a transaction that is a portfolio transfer.
* <p>
* This capital event relates only to both Debit and credit accounts.
*
* @param pSource the source portfolio
* @param pTarget the target portfolio
*/
private void processPortfolioXfer(final MoneyWisePortfolio pSource,
final MoneyWisePortfolio pTarget) {
/* Access the portfolio buckets */
final MoneyWiseAnalysisPortfolioBucket mySource = thePortfolioBuckets.getBucket(pSource);
final MoneyWiseAnalysisPortfolioBucket myTarget = thePortfolioBuckets.getBucket(pTarget);
/* Access source cash bucket */
final MoneyWiseAnalysisPortfolioCashBucket mySourceCash = mySource.getPortfolioCash();
if (mySourceCash.isActive()) {
/* Transfer any cash element */
final MoneyWiseAnalysisPortfolioCashBucket myTargetCash = myTarget.getPortfolioCash();
myTargetCash.adjustForXfer(mySourceCash, theHelper);
}
/* Loop through the source portfolio */
final Iterator<MoneyWiseAnalysisSecurityBucket> myIterator = mySource.securityIterator();
while (myIterator.hasNext()) {
final MoneyWiseAnalysisSecurityBucket myBucket = myIterator.next();
/* If the bucket is active */
if (myBucket.isActive()) {
/* Adjust the Target Bucket */
final MoneyWiseSecurityHolding myTargetHolding = theHoldingMap.declareHolding(pTarget, myBucket.getSecurity());
final MoneyWiseAnalysisSecurityBucket myTargetBucket = myTarget.getSecurityBucket(myTargetHolding);
theHelper.setSecurity(myBucket.getSecurity());
/* Process the Transfer */
processPortfolioXfer(myBucket, myTargetBucket);
}
}
/* PortfolioXfer is a transfer, so no need to update the categories */
}
/**
* Process a portfolio transfer.
*
* @param pSource the source holding
* @param pTarget the target holding
*/
private void processPortfolioXfer(final MoneyWiseAnalysisSecurityBucket pSource,
final MoneyWiseAnalysisSecurityBucket pTarget) {
/* Access source details */
MoneyWiseAnalysisSecurityValues mySourceValues = pSource.getValues();
OceanusUnits myUnits = mySourceValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
OceanusMoney myCost = mySourceValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
OceanusMoney myGains = mySourceValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS);
OceanusMoney myInvested = mySourceValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.INVESTED);
OceanusMoney myForeignInvested = mySourceValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED);
final boolean isForeign = pSource.isForeignCurrency();
/* Determine value of the stock being transferred */
final OceanusPrice myPrice = thePriceMap.getPriceForDate(pSource.getSecurity(), theHelper.getDate());
OceanusMoney myStockValue = myUnits.valueAtPrice(myPrice);
OceanusMoney myForeignValue = null;
OceanusRatio myRate = null;
/* If we are foreign */
if (isForeign) {
/* Determine foreign and local value */
myRate = theHelper.getDebitExchangeRate();
myForeignValue = myStockValue;
myStockValue = myStockValue.convertCurrency(theAnalysis.getCurrency().getCurrency(), myRate);
}
/* Allocate current profit between the two stocks */
OceanusMoney myProfit = new OceanusMoney(myStockValue);
myProfit.subtractAmount(myCost);
pSource.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
myProfit = new OceanusMoney(myProfit);
myProfit.negate();
pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
/* Transfer Units/Cost/Invested to target */
pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myUnits);
pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myCost);
pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myInvested);
pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS, myGains);
final MoneyWiseAnalysisSecurityValues myTargetValues = pTarget.registerTransaction(theHelper);
myTargetValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myPrice);
myTargetValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myStockValue);
myTargetValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myCost);
if (isForeign) {
myTargetValues.setValue(MoneyWiseAnalysisSecurityAttr.FOREIGNVALUE, myForeignValue);
myTargetValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myRate);
pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myForeignInvested);
}
/* Adjust the Source Units/Cost/Invested to zero */
myUnits = new OceanusUnits(myUnits);
myUnits.negate();
pSource.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myUnits);
myCost = new OceanusMoney(myCost);
myCost.negate();
pSource.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myCost);
myCost.negate();
myInvested = new OceanusMoney(myInvested);
myInvested.negate();
pSource.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myInvested);
myGains = new OceanusMoney(myGains);
myGains.negate();
pSource.adjustCounter(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS, myGains);
mySourceValues = pSource.registerTransaction(theHelper);
mySourceValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myPrice);
mySourceValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myStockValue);
mySourceValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myCost);
if (isForeign) {
mySourceValues.setValue(MoneyWiseAnalysisSecurityAttr.FOREIGNVALUE, myForeignValue);
mySourceValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myRate);
myForeignInvested = new OceanusMoney(myForeignInvested);
myForeignInvested.negate();
pTarget.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myForeignInvested);
}
}
/**
* Process a transaction that is a portfolio transfer.
* <p>
* This capital event relates only to both Debit and credit accounts.
*
* @param pSource the source holding
* @param pTarget the target portfolio
*/
private void processPortfolioXfer(final MoneyWiseSecurityHolding pSource,
final MoneyWisePortfolio pTarget) {
/* Access the portfolio buckets */
final MoneyWiseAnalysisPortfolioBucket mySource = thePortfolioBuckets.getBucket(pSource.getPortfolio());
final MoneyWiseAnalysisPortfolioBucket myTarget = thePortfolioBuckets.getBucket(pTarget);
/* Access source security bucket */
final MoneyWiseAnalysisSecurityBucket myBucket = mySource.getSecurityBucket(pSource);
/* If the bucket is active */
if (myBucket.isActive()) {
/* Adjust the Target Bucket */
final MoneyWiseSecurityHolding myTargetHolding = theHoldingMap.declareHolding(pTarget, myBucket.getSecurity());
final MoneyWiseAnalysisSecurityBucket myTargetBucket = myTarget.getSecurityBucket(myTargetHolding);
/* Process the Transfer */
processPortfolioXfer(myBucket, myTargetBucket);
}
/* PortfolioXfer is a transfer, so no need to update the categories */
}
/**
* Process a transaction that is a stock split.
* <p>
* This capital event relates only to the Debit Account since the credit account is the same.
*
* @param pHolding the security holding
*/
private void processUnitsAdjust(final MoneyWiseSecurityHolding pHolding) {
/* Access the units */
final OceanusUnits myDelta = theHelper.getAccountDeltaUnits();
/* Adjust the Security Units */
final MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pHolding);
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDelta);
/* Register the transaction */
myAsset.registerTransaction(theHelper);
/* StockSplit/Adjust is a transfer, so no need to update the categories */
}
/**
* Process a transaction that is a transfer into capital (also StockRightTaken).
* <p>
* This capital event relates only to the Credit Account.
*
* @param pDebit the debit account
* @param pCredit the credit security holding
*/
private void processTransferIn(final MoneyWiseAssetBase pDebit,
final MoneyWiseSecurityHolding pCredit) {
/* Access debit account and category */
final MoneyWiseTransCategory myCat = theHelper.getCategory();
/* Adjust the credit transfer details */
processCreditXferIn(pCredit);
/* Adjust the tax payments */
theTaxMan.adjustForTaxPayments(theHelper);
/* Determine the type of the debit account */
switch (pDebit.getAssetType()) {
case PAYEE:
final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(pDebit);
myPayee.adjustForDebit(theHelper);
break;
default:
final MoneyWiseAnalysisAccountBucket<?> myAccount = getAccountBucket(pDebit);
myAccount.adjustForDebit(theHelper);
break;
}
/* If the event category is not a transfer */
if (!myCat.isTransfer()) {
/* Adjust the relevant category buckets */
theCategoryBuckets.adjustCategories(theHelper, myCat);
}
}
/**
* Process the credit side of a transfer in transaction.
*
* @param pHolding the credit holding
*/
private void processCreditXferIn(final MoneyWiseSecurityHolding pHolding) {
/* Transfer is to the credit account and may or may not have a change to the units */
OceanusMoney myAmount = theHelper.getCreditAmount();
final OceanusRatio myExchangeRate = theHelper.getCreditExchangeRate();
final MoneyWiseSecurity mySecurity = pHolding.getSecurity();
/* Access the Asset Security Bucket */
final MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pHolding);
final boolean isForeign = myAsset.isForeignCurrency();
/* If this is a foreign currency asset */
if (isForeign) {
/* Adjust foreign invested amount */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myAmount);
/* Switch to local amount */
myAmount = theHelper.getLocalAmount();
}
/* Adjust the cost and investment */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myAmount);
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myAmount);
/* Determine the delta units */
final MoneyWiseSecurityClass mySecClass = mySecurity.getCategoryClass();
OceanusUnits myDeltaUnits = theHelper.getCreditUnits();
OceanusUnits myUnits = myAsset.getValues().getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
if (mySecClass.isAutoUnits() && myUnits.isZero()) {
myDeltaUnits = OceanusUnits.getWholeUnits(mySecClass.getAutoUnits());
}
/* If we have new units */
if (myDeltaUnits != null) {
/* Record change in units */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDeltaUnits);
}
/* Adjust for National Insurance */
myAsset.adjustForNIPayments(theHelper);
/* Get the appropriate price for the account */
final OceanusPrice myPrice = thePriceMap.getPriceForDate(mySecurity, theHelper.getDate());
/* Determine value of this stock after the transaction */
myUnits = myAsset.getValues().getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
OceanusMoney myValue = myUnits.valueAtPrice(myPrice);
/* If we are foreign */
if (isForeign) {
/* Determine local value */
myValue = myValue.convertCurrency(theAnalysis.getCurrency().getCurrency(), myExchangeRate);
}
/* Register the transaction */
final MoneyWiseAnalysisSecurityValues myValues = myAsset.registerTransaction(theHelper);
myValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myPrice);
myValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myValue);
myValues.setValue(MoneyWiseAnalysisSecurityAttr.CASHINVESTED, myAmount);
if (isForeign) {
myValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myExchangeRate);
}
}
/**
* Process a dividend transaction.
* <p>
* This capital event relates to the only to Debit account, although the Credit account may be
* identical to the credit account in which case the dividend is re-invested
*
* @param pHolding the debit security holding
* @param pCredit the credit account
*/
private void processDividend(final MoneyWiseSecurityHolding pHolding,
final MoneyWiseTransAsset pCredit) {
/* The main security that we are interested in is the debit account */
final MoneyWisePortfolio myPortfolio = pHolding.getPortfolio();
final MoneyWiseSecurity mySecurity = pHolding.getSecurity();
OceanusMoney myAmount = theHelper.getDebitAmount();
final OceanusMoney myTaxCredit = theHelper.getTaxCredit();
final OceanusUnits myDeltaUnits = theHelper.getAccountDeltaUnits();
final MoneyWiseTaxCredit myYear = theHelper.getTransaction().getTaxYear();
/* Obtain detailed category */
MoneyWiseTransCategory myCat = myPortfolio.getDetailedCategory(theHelper.getCategory(), myYear);
myCat = mySecurity.getDetailedCategory(myCat, myYear);
/* True debit account is the parent */
final MoneyWiseAssetBase myDebit = mySecurity.getParent();
/* Adjust the debit payee bucket */
final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myDebit);
myPayee.adjustForDebit(theHelper);
/* Access the Asset Account Bucket */
final MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pHolding);
final boolean isForeign = myAsset.isForeignCurrency();
final boolean isReInvest = pCredit instanceof MoneyWiseSecurityHolding;
/* If this is a foreign dividend */
if (isForeign) {
/* If this is a reInvestment */
if (isReInvest) {
/* Adjust counters */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myAmount);
myAsset.getValues().setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, theHelper.getCreditExchangeRate());
}
/* Switch to local amount */
myAmount = theHelper.getLocalAmount();
}
/* If this is a re-investment */
if (isReInvest) {
/* This amount is added to the cost, so record as the delta cost */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myAmount);
/* Record the investment */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myAmount);
/* If we have new units */
if (myDeltaUnits != null) {
/* Record delta units */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDeltaUnits);
}
/* If we have a tax credit */
if (myTaxCredit != null) {
/* The Tax Credit is viewed as a received dividend from the account */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.DIVIDEND, myTaxCredit);
}
/* else we are paying out to another account */
} else {
/* Adjust the dividend total for this asset */
final OceanusMoney myAdjust = new OceanusMoney(myAmount);
/* Any tax credit is viewed as a realised dividend from the account */
if (myTaxCredit != null) {
myAdjust.addAmount(myTaxCredit);
}
/* The Dividend is viewed as a dividend from the account */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.DIVIDEND, myAdjust);
/* Adjust the credit account bucket */
final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket((MoneyWiseAssetBase) pCredit);
myBucket.adjustForCredit(theHelper);
}
/* Register the transaction */
myAsset.registerTransaction(theHelper);
/* Adjust the tax payments */
theTaxMan.adjustForTaxPayments(theHelper);
/* Adjust the relevant category buckets */
theCategoryBuckets.adjustCategories(theHelper, myCat);
}
/**
* Process a transaction that is a transfer from capital.
* <p>
* This capital event relates only to the Debit Account
*
* @param pHolding the debit holding
* @param pCredit the credit account
*/
private void processTransferOut(final MoneyWiseSecurityHolding pHolding,
final MoneyWiseAssetBase pCredit) {
/* Access credit account and category */
final MoneyWiseTransCategory myCat = theHelper.getCategory();
/* Adjust the debit transfer details */
processDebitXferOut(pHolding);
/* Adjust the credit account bucket */
final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket(pCredit);
myBucket.adjustForCredit(theHelper);
/* If the event category is not a transfer */
if (!myCat.isTransfer()) {
/* Adjust the relevant category buckets */
theCategoryBuckets.adjustCategories(theHelper, myCat);
}
}
/**
* Process the debit side of a transfer out transaction.
* <p>
* This capital event relates only to the Debit Account
*
* @param pHolding the debit holding
*/
private void processDebitXferOut(final MoneyWiseSecurityHolding pHolding) {
/* Transfer out is from the debit account and may or may not have units */
final MoneyWiseSecurity myDebit = pHolding.getSecurity();
OceanusMoney myAmount = theHelper.getDebitAmount();
boolean isLargeCash = false;
/* Access the Asset Security Bucket */
final MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pHolding);
MoneyWiseAnalysisSecurityValues myValues = myAsset.getValues();
final OceanusRatio myXchangeRate = theHelper.getDebitExchangeRate();
final boolean isForeign = myAsset.isForeignCurrency();
/* If this is a foreign currency asset */
if (isForeign) {
/* Adjust foreign invested amount */
final OceanusMoney myDelta = new OceanusMoney(myAmount);
myDelta.negate();
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myDelta);
/* Switch to local amount */
myAmount = theHelper.getLocalAmount();
}
/* Record the delta investment */
final OceanusMoney myDelta = new OceanusMoney(myAmount);
myDelta.negate();
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myDelta);
/* Get the appropriate price for the account */
final OceanusPrice myPrice = thePriceMap.getPriceForDate(myDebit, theHelper.getDate());
/* Assume that the allowed cost is the full value */
OceanusUnits myUnits = Objects.requireNonNull(myValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS));
OceanusMoney myAllowedCost = new OceanusMoney(myAmount);
final OceanusMoney myCost = myValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
OceanusRatio myCostDilution = null;
OceanusMoney myConsideration = null;
/* Determine the delta units */
OceanusUnits myDeltaUnits = theHelper.getCategoryClass().isSecurityClosure()
? myUnits
: theHelper.getDebitUnits();
final boolean isCapitalDistribution = myDeltaUnits == null;
/* If this is not a capital distribution */
if (!isCapitalDistribution) {
/* The allowed cost is the relevant fraction of the cost */
myAllowedCost = myCost.valueAtWeight(myDeltaUnits, myUnits);
/* Access units as negative value */
myDeltaUnits = new OceanusUnits(myDeltaUnits);
myDeltaUnits.negate();
/* Record delta to units */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDeltaUnits);
final OceanusUnits myNewUnits = myValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
/* Determine the cost dilution */
myCostDilution = new OceanusRatio(myNewUnits, myUnits);
myUnits = myNewUnits;
}
/* Determine value of this stock after the transaction */
OceanusMoney myValue = myUnits.valueAtPrice(myPrice);
/* If we are foreign */
if (isForeign) {
/* Determine local value */
myValue = myValue.convertCurrency(theAnalysis.getCurrency().getCurrency(), myXchangeRate);
}
/* If we are performing a capital distribution */
if (isCapitalDistribution) {
/* Determine condition as to whether this is a large cash transaction */
final OceanusMoney myPortion = myValue.valueAtRate(LIMIT_RATE);
isLargeCash = (myAmount.compareTo(LIMIT_VALUE) > 0)
&& (myAmount.compareTo(myPortion) > 0);
/* If this is large cash */
if (isLargeCash) {
/* Determine the total value of rights plus share value */
myConsideration = new OceanusMoney(myAmount);
myConsideration.addAmount(myValue);
/* Determine the allowedCost as a proportion of the total value */
myAllowedCost = myCost.valueAtWeight(myAmount, myConsideration);
/* Determine the cost dilution */
myCostDilution = new OceanusRatio(myValue, myConsideration);
/* else this is viewed as small and is taken out of the cost */
} else {
/* Set the allowed cost to be the least of the cost or the returned cash */
myAllowedCost = myAmount.compareTo(myCost) > 0
? new OceanusMoney(myCost)
: new OceanusMoney(myAmount);
}
}
/* Determine the delta to the cost */
final OceanusMoney myDeltaCost = new OceanusMoney(myAllowedCost);
myDeltaCost.negate();
/* If we have a delta to the cost */
if (myDeltaCost.isNonZero()) {
/* Adjust the cost */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
}
/* Determine the capital gain */
final OceanusMoney myCapitalGain = new OceanusMoney(myAmount);
myCapitalGain.addAmount(myDeltaCost);
/* If we have a delta to the gains */
if (myCapitalGain.isNonZero()) {
/* Adjust the gains */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS, myCapitalGain);
/* Adjust the capitalGains category bucket */
theCategoryBuckets.adjustStandardGain(theHelper, pHolding, myCapitalGain);
}
/* Register the transaction */
myValues = myAsset.registerTransaction(theHelper);
/* record details */
myValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myPrice);
myValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myValue);
myValues.setValue(MoneyWiseAnalysisSecurityAttr.RETURNEDCASH, myAmount);
myValues.setValue(MoneyWiseAnalysisSecurityAttr.ALLOWEDCOST, myAllowedCost);
if (myCostDilution != null) {
myValues.setValue(MoneyWiseAnalysisSecurityAttr.COSTDILUTION, myCostDilution);
}
if (myConsideration != null) {
myValues.setValue(MoneyWiseAnalysisSecurityAttr.CONSIDERATION, myConsideration);
}
if (myCapitalGain.isNonZero()) {
myValues.setValue(MoneyWiseAnalysisSecurityAttr.CAPITALGAIN, myCapitalGain);
}
if (isForeign) {
myValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myXchangeRate);
}
if (isCapitalDistribution) {
myValues.setValue(MoneyWiseAnalysisSecurityAttr.CASHTYPE, isLargeCash
? MoneyWiseCashType.LARGECASH
: MoneyWiseCashType.SMALLCASH);
}
}
/**
* Process a transaction that is a exchange between two capital accounts.
* <p>
* This represent a transfer out from the debit account and a transfer in to the credit account
*
* @param pDebit the debit holding
* @param pCredit the credit holding
*/
private void processStockXchange(final MoneyWiseSecurityHolding pDebit,
final MoneyWiseSecurityHolding pCredit) {
/* Adjust the debit transfer details */
processDebitXferOut(pDebit);
/* Adjust the credit transfer details */
processCreditXferIn(pCredit);
}
/**
* Process a transaction that is a chargeable gain.
* <p>
* This capital event relates only to the Debit Asset
*
* @param pHolding the debit security holding
* @param pCredit the credit account
*/
private void processChargeableGain(final MoneyWiseSecurityHolding pHolding,
final MoneyWiseAssetBase pCredit) {
/* Chargeable Gain is from the debit account and may or may not have units */
final MoneyWiseSecurity myDebit = pHolding.getSecurity();
OceanusMoney myAmount = theHelper.getDebitAmount();
OceanusUnits myDeltaUnits = theHelper.getDebitUnits();
/* Access the Asset Security Bucket */
final MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pHolding);
final MoneyWiseAnalysisSecurityValues myValues = myAsset.getValues();
/* If this is a foreign currency asset */
if (Boolean.TRUE.equals(myAsset.isForeignCurrency())) {
/* Adjust foreign invested amount */
final OceanusMoney myDelta = new OceanusMoney(myAmount);
myDelta.negate();
myValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, theHelper.getDebitExchangeRate());
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myDelta);
/* Switch to local amount */
myAmount = theHelper.getLocalAmount();
}
/* Record the delta investment */
final OceanusMoney myDelta = new OceanusMoney(myAmount);
myDelta.negate();
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myDelta);
/* Assume the cost reduction is the full value */
OceanusMoney myReduction = new OceanusMoney(myAmount);
final OceanusMoney myCost = myValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
/* If we are reducing units in the account */
if (myDeltaUnits != null) {
/* The reduction is the relevant fraction of the cost */
final OceanusUnits myUnits = myValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
myReduction = myCost.valueAtWeight(myDeltaUnits, myUnits);
/* Access units as negative value */
myDeltaUnits = new OceanusUnits(myDeltaUnits);
myDeltaUnits.negate();
/* Record delta to units */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDeltaUnits);
}
/* If the reduction is greater than the total cost */
if (myReduction.compareTo(myCost) > 0) {
/* Reduction is the total cost */
myReduction = new OceanusMoney(myCost);
}
/* Determine the delta to the cost */
final OceanusMoney myDeltaCost = new OceanusMoney(myReduction);
myDeltaCost.negate();
/* If we have a delta to the cost */
if (myDeltaCost.isNonZero()) {
/* Adjust the cost */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
}
/* Determine the delta to the gains */
final OceanusMoney myDeltaGains = new OceanusMoney(myAmount);
myDeltaGains.addAmount(myDeltaCost);
/* If we have a delta to the gains */
if (myDeltaGains.isNonZero()) {
/* Adjust the gains */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS, myDeltaGains);
}
/* Register the event */
myAsset.registerTransaction(theHelper);
/* True debit account is the parent */
final MoneyWiseAssetBase myParent = myDebit.getParent();
/* Adjust the debit account bucket */
final MoneyWiseAnalysisPayeeBucket myPayee = thePayeeBuckets.getBucket(myParent);
myPayee.adjustForTaxCredit(theHelper);
/* Adjust the credit account bucket */
final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket(pCredit);
myBucket.adjustForCredit(theHelper);
/* Adjust the chargeableGains category bucket */
theCategoryBuckets.adjustChargeableGain(theHelper, myReduction);
/* Adjust the TaxMan account for the tax credit */
theTaxMan.adjustForTaxPayments(theHelper);
/* Add the chargeable event */
theTaxBasisBuckets.recordChargeableGain(theHelper.getTransaction(), myDeltaGains);
}
/**
* Process a transaction that is Stock DeMerger.
* <p>
* This capital event relates to both the Credit and Debit accounts
*
* @param pDebit the debit account
* @param pCredit the credit account
*/
private void processStockDeMerger(final MoneyWiseSecurityHolding pDebit,
final MoneyWiseSecurityHolding pCredit) {
/* Access the Debit Asset Security Bucket */
MoneyWiseAnalysisSecurityBucket myAsset = thePortfolioBuckets.getBucket(pDebit);
MoneyWiseAnalysisSecurityValues myValues = myAsset.getValues();
final OceanusRatio myDebitRate = theHelper.getDebitExchangeRate();
/* Obtain current cost */
final OceanusMoney myCost = myValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
final OceanusRatio myDilution = theHelper.getDilution();
final OceanusUnits myDeltaUnits = theHelper.getAccountDeltaUnits();
/* If we reduced the units */
if (myDeltaUnits != null) {
/* Record the delta units */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDeltaUnits);
}
/* Calculate the cost dilution */
final OceanusMoney myNewCost = myCost.getDilutedMoney(myDilution);
final OceanusRatio myCostDilution = new OceanusRatio(myNewCost, myCost);
/* Calculate the delta to the cost */
OceanusMoney myDeltaCost = new OceanusMoney(myNewCost);
myDeltaCost.subtractAmount(myCost);
/* Record the delta cost/investment */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myDeltaCost);
final boolean isForeignDebit = myAsset.isForeignCurrency();
if (isForeignDebit) {
final OceanusMoney myInvested = myDeltaCost.convertCurrency(myAsset.getCurrency().getCurrency(), myDebitRate);
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myInvested);
}
/* Register the event */
myValues = myAsset.registerTransaction(theHelper);
/* Access the Credit Asset Account Bucket */
myAsset = thePortfolioBuckets.getBucket(pCredit);
/* The deltaCost is transferred to the credit account */
myDeltaCost = new OceanusMoney(myDeltaCost);
myDeltaCost.negate();
/* Record details */
myValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myDeltaCost);
myValues.setValue(MoneyWiseAnalysisSecurityAttr.COSTDILUTION, myCostDilution);
if (isForeignDebit) {
myValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myDebitRate);
}
/* Record the delta cost/investment */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myDeltaCost);
final boolean isForeignCredit = myAsset.isForeignCurrency();
final OceanusRatio myCreditRate = theHelper.getCreditExchangeRate();
if (isForeignCredit) {
final OceanusMoney myInvested = myDeltaCost.convertCurrency(myAsset.getCurrency().getCurrency(), myCreditRate);
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myInvested);
}
/* Get the appropriate prices/rates for the stock */
final OceanusDate myDate = theHelper.getDate();
final OceanusPrice myCreditPrice = thePriceMap.getPriceForDate(myAsset.getSecurity(), myDate);
final Currency myCurrency = theAnalysis.getCurrency().getCurrency();
/* Determine value of the stock being deMerged */
final OceanusUnits myCreditUnits = theHelper.getPartnerDeltaUnits();
OceanusMoney myCreditXferValue = myCreditUnits.valueAtPrice(myCreditPrice);
if (isForeignCredit) {
myCreditXferValue = myCreditXferValue.convertCurrency(myCurrency, myCreditRate);
}
/* Record the current/delta units */
myAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myCreditUnits);
/* Register the transaction */
myValues = myAsset.registerTransaction(theHelper);
/* Record values */
myValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myDeltaCost);
myValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myCreditPrice);
myValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDVALUE, myCreditXferValue);
if (isForeignCredit) {
myValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myCreditRate);
}
/* StockDeMerger is a transfer, so no need to update the categories */
}
/**
* Process a transaction that is StockTakeover.
* <p>
* This can be accomplished using a cash portion (to a ThirdParty account) and these workings
* are split out.
*
* @param pDebit the debit holding
* @param pCredit the credit holding
*/
private void processStockTakeover(final MoneyWiseSecurityHolding pDebit,
final MoneyWiseSecurityHolding pCredit) {
final OceanusMoney myAmount = theHelper.getReturnedCash();
final MoneyWiseTransAsset myReturnedCashAct = theHelper.getReturnedCashAccount();
/* If we have a returned cash part of the transaction */
if (myReturnedCashAct != null
&& myAmount.isNonZero()) {
/* Process a Stock And Cash TakeOver */
processStockAndCashTakeOver(pDebit, pCredit);
} else {
/* Process a StockOnly TakeOver */
processStockOnlyTakeOver(pDebit, pCredit);
}
}
/**
* Process a transaction that is a StockOnlyTakeover.
* <p>
* This capital event relates to both the Credit and Debit accounts
*
* @param pDebit the debit holding
* @param pCredit the credit holding
*/
private void processStockOnlyTakeOver(final MoneyWiseSecurityHolding pDebit,
final MoneyWiseSecurityHolding pCredit) {
/* Access details */
final MoneyWiseSecurity myCredit = pCredit.getSecurity();
final MoneyWiseSecurity myDebit = pDebit.getSecurity();
/* Access the Asset Security Buckets */
final MoneyWiseAnalysisSecurityBucket myDebitAsset = thePortfolioBuckets.getBucket(pDebit);
MoneyWiseAnalysisSecurityValues myDebitValues = myDebitAsset.getValues();
final MoneyWiseAnalysisSecurityBucket myCreditAsset = thePortfolioBuckets.getBucket(pCredit);
final OceanusDate myDate = theHelper.getDate();
/* Get the appropriate prices/rates for the stock */
final OceanusPrice myCreditPrice = thePriceMap.getPriceForDate(myCredit, myDate);
final OceanusPrice myDebitPrice = thePriceMap.getPriceForDate(myDebit, myDate);
final OceanusRatio myDebitRate = theHelper.getDebitExchangeRate();
final OceanusRatio myCreditRate = theHelper.getCreditExchangeRate();
final Currency myCurrency = theAnalysis.getCurrency().getCurrency();
/* Determine value of the stock in both parts of the takeOver */
OceanusUnits myCreditUnits = theHelper.getPartnerDeltaUnits();
OceanusMoney myCreditXferValue = myCreditUnits.valueAtPrice(myCreditPrice);
OceanusUnits myDebitUnits = myDebitValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
OceanusMoney myDebitValue = myDebitUnits.valueAtPrice(myDebitPrice);
OceanusMoney myInvested = myDebitValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.INVESTED);
/* Handle foreign debit */
final boolean isForeignDebit = myDebitAsset.isForeignCurrency();
if (isForeignDebit) {
myDebitValue = myDebitValue.convertCurrency(myCurrency, myDebitRate);
}
/* Handle foreign credit */
final boolean isForeignCredit = myCreditAsset.isForeignCurrency();
if (isForeignCredit) {
myCreditXferValue = myCreditXferValue.convertCurrency(myCurrency, myCreditRate);
}
/* Determine the residual cost of the old stock */
final OceanusMoney myDebitCost = myDebitValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
/* Allocate current profit between the two stocks */
OceanusMoney myProfit = new OceanusMoney(myDebitValue);
myProfit.subtractAmount(myDebitCost);
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
myProfit = new OceanusMoney(myProfit);
myProfit.negate();
myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
/* Adjust cost/units/invested of the credit account */
myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDebitCost);
myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myCreditUnits);
myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myInvested);
if (isForeignCredit) {
final OceanusMoney myForeign = myInvested.convertCurrency(myCreditAsset.getCurrency().getCurrency(), myCreditRate);
myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myForeign);
}
/* Determine final value of the credit stock after the takeOver */
myCreditUnits = myCreditAsset.getValues().getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
OceanusMoney myCreditValue = myCreditUnits.valueAtPrice(myCreditPrice);
if (isForeignCredit) {
myCreditValue = myCreditValue.convertCurrency(myCurrency, myCreditRate);
}
/* Register the transaction */
final MoneyWiseAnalysisSecurityValues myCreditValues = myCreditAsset.registerTransaction(theHelper);
myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myCreditPrice);
myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDVALUE, myCreditXferValue);
myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myDebitCost);
myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myCreditValue);
if (isForeignCredit) {
myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myCreditRate);
}
/* Drive debit cost down to zero */
final OceanusMoney myDeltaCost = new OceanusMoney(myDebitCost);
myDeltaCost.negate();
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
myDeltaCost.negate();
/* Drive debit units down to zero */
myDebitUnits = new OceanusUnits(myDebitUnits);
myDebitUnits.negate();
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDebitUnits);
/* Adjust debit Invested amount */
myInvested = new OceanusMoney(myInvested);
myInvested.negate();
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myInvested);
if (isForeignDebit) {
myInvested = new OceanusMoney(myDebitValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED));
myInvested.negate();
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myInvested);
}
/* Register the transaction */
myDebitValues = myDebitAsset.registerTransaction(theHelper);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myDebitPrice);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myDebitValue);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDVALUE, myCreditXferValue);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myDeltaCost);
if (isForeignDebit) {
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myDebitRate);
}
}
/**
* Process a transaction that is StockAndCashTakeover.
* <p>
* This capital event relates to both the Credit and Debit accounts. In particular it makes
* reference to the CashTakeOver aspect of the debit account
*
* @param pDebit the debit holding
* @param pCredit the credit holding
*/
private void processStockAndCashTakeOver(final MoneyWiseSecurityHolding pDebit,
final MoneyWiseSecurityHolding pCredit) {
/* Access details */
final MoneyWiseSecurity myDebit = pDebit.getSecurity();
final MoneyWiseSecurity myCredit = pCredit.getSecurity();
final OceanusDate myDate = theHelper.getDate();
final MoneyWiseTransAsset myReturnedCashAccount = theHelper.getReturnedCashAccount();
final OceanusMoney myAmount = theHelper.getLocalReturnedCash();
/* Access the Asset Security Buckets */
final MoneyWiseAnalysisSecurityBucket myDebitAsset = thePortfolioBuckets.getBucket(pDebit);
MoneyWiseAnalysisSecurityValues myDebitValues = myDebitAsset.getValues();
final MoneyWiseAnalysisSecurityBucket myCreditAsset = thePortfolioBuckets.getBucket(pCredit);
/* Get the appropriate prices for the assets */
final OceanusPrice myDebitPrice = thePriceMap.getPriceForDate(myDebit, myDate);
final OceanusPrice myCreditPrice = thePriceMap.getPriceForDate(myCredit, myDate);
final OceanusRatio myDebitRate = theHelper.getDebitExchangeRate();
final OceanusRatio myCreditRate = theHelper.getCreditExchangeRate();
final Currency myCurrency = theAnalysis.getCurrency().getCurrency();
/* Determine value of the base stock */
OceanusUnits myDebitUnits = myDebitValues.getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
OceanusMoney myDebitValue = myDebitUnits.valueAtPrice(myDebitPrice);
/* Determine value of the stock part of the takeOver */
OceanusUnits myCreditUnits = theHelper.getPartnerDeltaUnits();
OceanusMoney myCreditXferValue = myCreditUnits.valueAtPrice(myCreditPrice);
/* Handle foreign debit */
final boolean isForeignDebit = myDebitAsset.isForeignCurrency();
if (isForeignDebit) {
myDebitValue = myDebitValue.convertCurrency(myCurrency, myDebitRate);
}
/* Handle foreign credit */
final boolean isForeignCredit = myCreditAsset.isForeignCurrency();
if (isForeignCredit) {
myCreditXferValue = myCreditXferValue.convertCurrency(myCurrency, myCreditRate);
}
/* Calculate the total consideration */
final OceanusMoney myConsideration = new OceanusMoney(myAmount);
myConsideration.addAmount(myCreditXferValue);
/* Access the current debit cost */
final OceanusMoney myCost = myDebitValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST);
OceanusRatio myCostDilution = null;
final OceanusMoney myCostXfer;
final OceanusMoney myAllowedCost;
/* Determine condition as to whether this is a large cash transaction */
final OceanusMoney myPortion = myDebitValue.valueAtRate(LIMIT_RATE);
final boolean isLargeCash = (myAmount.compareTo(LIMIT_VALUE) > 0)
&& (myAmount.compareTo(myPortion) > 0);
/* If this is a large cash takeOver */
if (isLargeCash) {
/* Determine the transferable cost */
myCostXfer = myCost.valueAtWeight(myCreditXferValue, myConsideration);
/* Determine the cost dilution */
myCostDilution = new OceanusRatio(myAmount, myConsideration);
/* Determine the allowed cost */
myAllowedCost = new OceanusMoney(myCost);
myAllowedCost.subtractAmount(myCostXfer);
/* else this is viewed as small and is taken out of the cost */
} else {
/* Set the allowed cost to be the least of the cost or the returned cash */
myAllowedCost = myAmount.compareTo(myCost) > 0
? new OceanusMoney(myCost)
: new OceanusMoney(myAmount);
/* Transferred cost is cost minus the allowed cost */
myCostXfer = new OceanusMoney(myCost);
myCostXfer.subtractAmount(myAllowedCost);
}
/* Determine the capital gain */
final OceanusMoney myCapitalGain = new OceanusMoney(myAmount);
myCapitalGain.subtractAmount(myAllowedCost);
if (myCapitalGain.isNonZero()) {
/* Record the delta gains */
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.REALISEDGAINS, myCapitalGain);
/* Adjust the capitalGains category bucket */
theCategoryBuckets.adjustStandardGain(theHelper, pDebit, myCapitalGain);
}
/* Allocate current profit between the two stocks */
OceanusMoney myProfit = new OceanusMoney(myCreditXferValue);
myProfit.subtractAmount(myCostXfer);
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
myProfit = new OceanusMoney(myProfit);
myProfit.negate();
myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.GROWTHADJUST, myProfit);
/* Adjust cost/units/invested of the credit account */
myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myCostXfer);
myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myCreditUnits);
myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myCostXfer);
if (isForeignCredit) {
final OceanusMoney myForeign = myCostXfer.convertCurrency(myCreditAsset.getCurrency().getCurrency(), myCreditRate);
myCreditAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myForeign);
}
/* Determine final value of the credit stock after the takeOver */
myCreditUnits = myCreditAsset.getValues().getUnitsValue(MoneyWiseAnalysisSecurityAttr.UNITS);
OceanusMoney myCreditValue = myCreditUnits.valueAtPrice(myCreditPrice);
if (isForeignCredit) {
myCreditValue = myCreditValue.convertCurrency(myCurrency, myCreditRate);
}
/* Register the transaction */
final MoneyWiseAnalysisSecurityValues myCreditValues = myCreditAsset.registerTransaction(theHelper);
myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myCreditPrice);
myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDVALUE, myCreditXferValue);
myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myCostXfer);
myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myCreditValue);
if (isForeignCredit) {
myCreditValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myCreditRate);
}
/* Drive debit cost down to zero */
final OceanusMoney myDeltaCost = new OceanusMoney(myCost);
myDeltaCost.negate();
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.RESIDUALCOST, myDeltaCost);
/* Drive debit units down to zero */
myDebitUnits = new OceanusUnits(myDebitUnits);
myDebitUnits.negate();
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.UNITS, myDebitUnits);
/* Adjust debit Invested amount */
OceanusMoney myInvested = myDebitValues.getMoneyValue(MoneyWiseAnalysisSecurityAttr.INVESTED);
myInvested = new OceanusMoney(myInvested);
myInvested.setZero();
myInvested.subtractAmount(myAmount);
myInvested.subtractAmount(myCostXfer);
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.INVESTED, myInvested);
if (isForeignDebit) {
myInvested = myInvested.convertCurrency(myDebitAsset.getCurrency().getCurrency(), myDebitRate);
myInvested.negate();
myDebitAsset.adjustCounter(MoneyWiseAnalysisSecurityAttr.FOREIGNINVESTED, myInvested);
}
/* Register the transaction */
myDebitValues = myDebitAsset.registerTransaction(theHelper);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.PRICE, myDebitPrice);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.VALUATION, myDebitValue);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.CONSIDERATION, myConsideration);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.RETURNEDCASH, myAmount);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDVALUE, myCreditXferValue);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.XFERREDCOST, myCostXfer);
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.ALLOWEDCOST, myAllowedCost);
if (myCostDilution != null) {
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.COSTDILUTION, myCostDilution);
}
if (myCapitalGain.isNonZero()) {
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.CAPITALGAIN, myCapitalGain);
}
if (isForeignDebit) {
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.EXCHANGERATE, myDebitRate);
}
myDebitValues.setValue(MoneyWiseAnalysisSecurityAttr.CASHTYPE, isLargeCash
? MoneyWiseCashType.LARGECASH
: MoneyWiseCashType.SMALLCASH);
/* Adjust the ThirdParty account bucket */
final MoneyWiseAnalysisAccountBucket<?> myBucket = getAccountBucket((MoneyWiseAssetBase) myReturnedCashAccount);
myBucket.adjustForReturnedCashCredit(theHelper);
}
/**
* Obtain Account bucket for asset.
*
* @param pAsset the asset
* @return the bucket
*/
private MoneyWiseAnalysisAccountBucket<?> getAccountBucket(final MoneyWiseAssetBase pAsset) {
switch (pAsset.getAssetType()) {
case DEPOSIT:
return theDepositBuckets.getBucket((MoneyWiseDeposit) pAsset);
case CASH:
return theCashBuckets.getBucket((MoneyWiseCash) pAsset);
case LOAN:
return theLoanBuckets.getBucket((MoneyWiseLoan) pAsset);
case PORTFOLIO:
return thePortfolioBuckets.getCashBucket((MoneyWisePortfolio) pAsset);
default:
throw new IllegalArgumentException();
}
}
}