MoneyWiseValidateTransaction.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.data.validate;
import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
import io.github.tonywasher.joceanus.oceanus.date.OceanusDateRange;
import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
import io.github.tonywasher.joceanus.oceanus.decimal.OceanusUnits;
import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
import io.github.tonywasher.joceanus.metis.field.MetisFieldRequired;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseAssetDirection;
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.MoneyWiseBasicResource;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDataValidator.MoneyWiseDataValidatorTrans;
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.MoneyWisePayee;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePortfolio;
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.MoneyWiseTransAsset;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransBase;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransCategory;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransInfoSet;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransaction;
import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseDepositCategoryClass;
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.data.statics.MoneyWiseTransInfoClass;
import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataItem;
import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
import java.util.Currency;
import java.util.Objects;
/**
* Validator for transaction.
*/
public class MoneyWiseValidateTransaction
implements MoneyWiseDataValidatorTrans<MoneyWiseTransaction> {
/**
* Are we using new validation?
*/
private final boolean newValidation;
/**
* The infoSet validator.
*/
private final MoneyWiseValidateTransInfoSet theInfoSet;
/**
* The defaults engine.
*/
private final MoneyWiseValidateTransDefaults theDefaults;
/**
* Set the editSet.
*/
private PrometheusEditSet theEditSet;
/**
* Constructor.
*
* @param pNewValidation true/false
*/
MoneyWiseValidateTransaction(final boolean pNewValidation) {
newValidation = pNewValidation;
theInfoSet = new MoneyWiseValidateTransInfoSet(pNewValidation);
theDefaults = new MoneyWiseValidateTransDefaults(this);
}
@Override
public void setEditSet(final PrometheusEditSet pEditSet) {
theEditSet = pEditSet;
theInfoSet.storeEditSet(pEditSet);
}
/**
* Obtain the editSet.
*
* @return the editSet
*/
PrometheusEditSet getEditSet() {
if (theEditSet == null) {
throw new IllegalStateException("editSet not set up");
}
return theEditSet;
}
/**
* Obtain the transInfoSet validator.
*
* @return the validator
*/
public MoneyWiseValidateTransInfoSet getInfoSetValidator() {
return theInfoSet;
}
/**
* Should we perform new validity checks?
*
* @return true/false
*/
public boolean newValidation() {
return newValidation;
}
@Override
public void validate(final PrometheusDataItem pTrans) {
final MoneyWiseTransaction myTrans = (MoneyWiseTransaction) pTrans;
final OceanusDate myDate = myTrans.getDate();
final MoneyWiseTransAsset myAccount = myTrans.getAccount();
final MoneyWiseTransAsset myPartner = myTrans.getPartner();
final MoneyWiseTransCategory myCategory = myTrans.getCategory();
final MoneyWiseAssetDirection myDir = myTrans.getDirection();
final OceanusMoney myAmount = myTrans.getAmount();
final OceanusUnits myAccountUnits = myTrans.getAccountDeltaUnits();
final OceanusUnits myPartnerUnits = myTrans.getPartnerDeltaUnits();
boolean doCheckCombo = true;
/* Header is always valid */
if (pTrans.isHeader()) {
pTrans.setValidEdit();
return;
}
/* Determine date range to check for */
final OceanusDateRange myRange = myTrans.getDataSet().getDateRange();
/* The date must be non-null */
if (myDate == null) {
pTrans.addError(PrometheusDataItem.ERROR_MISSING, MoneyWiseBasicResource.MONEYWISEDATA_FIELD_DATE);
/* The date must be in-range */
} else if (myRange.compareToDate(myDate) != 0) {
pTrans.addError(PrometheusDataItem.ERROR_RANGE, MoneyWiseBasicResource.MONEYWISEDATA_FIELD_DATE);
}
/* Account must be non-null */
if (myAccount == null) {
pTrans.addError(PrometheusDataItem.ERROR_MISSING, MoneyWiseBasicResource.TRANSACTION_ACCOUNT);
doCheckCombo = false;
} else {
/* Account must be valid */
if (!isValidAccount(myAccount)) {
pTrans.addError(MoneyWiseTransBase.ERROR_COMBO, MoneyWiseBasicResource.TRANSACTION_ACCOUNT);
doCheckCombo = false;
}
}
/* Category must be non-null */
if (myCategory == null) {
pTrans.addError(PrometheusDataItem.ERROR_MISSING, MoneyWiseBasicDataType.TRANSCATEGORY);
doCheckCombo = false;
/* Category must be valid for Account */
} else if (doCheckCombo
&& !isValidCategory(myAccount, myCategory)) {
pTrans.addError(MoneyWiseTransBase.ERROR_COMBO, MoneyWiseBasicDataType.TRANSCATEGORY);
doCheckCombo = false;
}
/* Direction must be non-null */
if (myDir == null) {
pTrans.addError(PrometheusDataItem.ERROR_MISSING, MoneyWiseBasicResource.TRANSACTION_DIRECTION);
doCheckCombo = false;
/* Direction must be valid for Account */
} else if (doCheckCombo
&& !isValidDirection(myAccount, myCategory, myDir)) {
pTrans.addError(MoneyWiseTransBase.ERROR_COMBO, MoneyWiseBasicResource.TRANSACTION_DIRECTION);
doCheckCombo = false;
}
/* Partner must be non-null */
if (myPartner == null) {
pTrans.addError(PrometheusDataItem.ERROR_MISSING, MoneyWiseBasicResource.TRANSACTION_PARTNER);
} else {
/* Partner must be valid for Account */
if (doCheckCombo
&& !isValidPartner(myAccount, myCategory, myPartner)) {
pTrans.addError(MoneyWiseTransBase.ERROR_COMBO, MoneyWiseBasicResource.TRANSACTION_PARTNER);
}
}
/* If money is null */
if (myAmount == null) {
/* Check that it must be null */
if (!needsNullAmount(myTrans)) {
pTrans.addError(PrometheusDataItem.ERROR_MISSING, MoneyWiseBasicResource.TRANSACTION_AMOUNT);
}
/* else non-null money */
} else {
/* Check that it must be null */
if (needsNullAmount(myTrans)) {
pTrans.addError(PrometheusDataItem.ERROR_EXIST, MoneyWiseBasicResource.TRANSACTION_AMOUNT);
}
/* Money must not be negative */
if (!myAmount.isPositive()) {
pTrans.addError(PrometheusDataItem.ERROR_NEGATIVE, MoneyWiseBasicResource.TRANSACTION_AMOUNT);
}
/* Check that amount is correct currency */
if (myAccount != null) {
final Currency myCurrency = myAccount.getCurrency();
if (!myAmount.getCurrency().equals(myCurrency)) {
pTrans.addError(MoneyWiseTransBase.ERROR_CURRENCY, MoneyWiseBasicResource.TRANSACTION_AMOUNT);
}
}
}
/* Cannot have PartnerUnits if securities are identical */
if (myAccountUnits != null
&& myPartnerUnits != null
&& MetisDataDifference.isEqual(myAccount, myPartner)) {
pTrans.addError(MoneyWiseTransaction.ERROR_CIRCULAR, MoneyWiseTransInfoSet.getFieldForClass(MoneyWiseTransInfoClass.PARTNERDELTAUNITS));
}
/* If we have a category and an infoSet */
if (myCategory != null
&& myTrans.getInfoSet() != null) {
/* Validate the InfoSet */
theInfoSet.validate(myTrans.getInfoSet());
}
/* Set validation flag */
if (!pTrans.hasErrors()) {
pTrans.setValidEdit();
}
}
/**
* Determines whether an event needs a zero amount.
*
* @param pTrans the transaction
* @return true/false
*/
public boolean needsNullAmount(final MoneyWiseTransaction pTrans) {
final MoneyWiseTransCategoryClass myClass = pTrans.getCategoryClass();
return myClass != null
&& myClass.needsNullAmount();
}
@Override
public boolean isValidAccount(final MoneyWiseTransAsset pAccount) {
/* Validate securityHolding */
if (pAccount instanceof MoneyWiseSecurityHolding myHolding
&& !checkSecurityHolding(myHolding)) {
return false;
}
/* Reject pensions portfolio */
if (pAccount instanceof MoneyWisePortfolio myPortfolio
&& myPortfolio.getCategoryClass().holdsPensions()) {
return false;
}
/* Check type of account */
final MoneyWiseAssetType myType = pAccount.getAssetType();
return myType.isBaseAccount() && !pAccount.isHidden();
}
@Override
public boolean isValidCategory(final MoneyWiseTransAsset pAccount,
final MoneyWiseTransCategory pCategory) {
/* Access details */
final MoneyWiseAssetType myType = pAccount.getAssetType();
final MoneyWiseTransCategoryClass myCatClass = Objects.requireNonNull(pCategory.getCategoryTypeClass());
/* Immediately reject hidden categories */
if (myCatClass.isHiddenType()) {
return false;
}
/* Switch on the CategoryClass */
switch (myCatClass) {
case TAXEDINCOME:
case GROSSINCOME:
case RECOVEREDEXPENSES:
case OTHERINCOME:
/* Taxed/Other income must be to deposit/cash/loan */
return myType.isValued();
case PENSIONCONTRIB:
/* Pension contribution must be to a Pension holding or to a SIPP */
return (pAccount instanceof MoneyWiseSecurityHolding myHolding
&& myHolding.getSecurity().getCategoryClass().isPension())
|| (pAccount instanceof MoneyWisePortfolio myPortfolio
&& myPortfolio.isPortfolioClass(MoneyWisePortfolioClass.SIPP));
case GIFTEDINCOME:
case INHERITED:
/* Inheritance/Gifted must be to asset */
return myType.isAsset();
case INTEREST:
/* Account must be deposit or portfolio */
return myType.isDeposit() || myType.isPortfolio();
case DIVIDEND:
case SECURITYCLOSURE:
/* Account must be SecurityHolding */
return myType.isSecurityHolding();
case BADDEBTCAPITAL:
case BADDEBTINTEREST:
/* Account must be peer2Peer */
return pAccount instanceof MoneyWiseDeposit myDeposit
&& myDeposit.isDepositClass(MoneyWiseDepositCategoryClass.PEER2PEER);
case CASHBACK:
return checkCashBack(pAccount);
case LOYALTYBONUS:
return checkLoyaltyBonus(pAccount);
case RENTALINCOME:
case RENTALEXPENSE:
case ROOMRENTALINCOME:
/* Account must be property */
return pAccount instanceof MoneyWiseSecurityHolding myHolding
&& myHolding.getSecurity().isSecurityClass(MoneyWiseSecurityClass.PROPERTY);
case UNITSADJUST:
case SECURITYREPLACE:
/* Account must be capital */
return pAccount.isCapital();
case STOCKSPLIT:
case STOCKTAKEOVER:
case STOCKDEMERGER:
case STOCKRIGHTSISSUE:
/* Account must be shares */
return pAccount.isShares();
case WRITEOFF:
case LOANINTERESTEARNED:
case LOANINTERESTCHARGED:
case TAXRELIEF:
return myType.isLoan();
case LOCALTAXES:
case INCOMETAX:
return myType.isValued();
case EXPENSE:
return myType.isValued() || myType.isAutoExpense();
case PORTFOLIOXFER:
return pAccount instanceof MoneyWiseSecurityHolding
|| pAccount instanceof MoneyWisePortfolio;
case TRANSFER:
return true;
/* Reject other categories */
default:
return false;
}
}
@Override
public boolean isValidDirection(final MoneyWiseTransAsset pAccount,
final MoneyWiseTransCategory pCategory,
final MoneyWiseAssetDirection pDirection) {
/* TODO relax some of these rules */
/* Access details */
final MoneyWiseTransCategoryClass myCatClass = pCategory.getCategoryTypeClass();
/* Switch on the CategoryClass */
switch (myCatClass) {
case TAXEDINCOME:
case GROSSINCOME:
/* Cannot refund Taxed Income yet */
return newValidation || pDirection.isFrom();
case PENSIONCONTRIB:
/* Cannot refund Pension Contribution */
return pDirection.isFrom();
case GIFTEDINCOME:
case INHERITED:
/* Cannot refund Gifted/Inherited Income yet */
return newValidation || pDirection.isFrom();
case RENTALINCOME:
case ROOMRENTALINCOME:
/* Cannot refund Rental Income */
return pDirection.isTo();
case RENTALEXPENSE:
/* Cannot refund Rental Expense */
return pDirection.isFrom();
case INTEREST:
/* Cannot refund Interest yet */
return newValidation || pDirection.isTo();
case DIVIDEND:
case SECURITYCLOSURE:
/* Cannot refund Dividend yet */
return pDirection.isTo();
case LOYALTYBONUS:
/* Cannot refund loyaltyBonus yet */
return newValidation || pDirection.isTo();
case WRITEOFF:
case LOANINTERESTCHARGED:
/* All need to be TO */
return newValidation || pDirection.isTo();
case LOANINTERESTEARNED:
/* All need to be FROM */
return newValidation || pDirection.isFrom();
case UNITSADJUST:
case STOCKSPLIT:
case STOCKDEMERGER:
case STOCKTAKEOVER:
case SECURITYREPLACE:
case PORTFOLIOXFER:
/* All need to be To */
return pDirection.isTo();
default:
return true;
}
}
@Override
public boolean isValidPartner(final MoneyWiseTransAsset pAccount,
final MoneyWiseTransCategory pCategory,
final MoneyWiseTransAsset pPartner) {
/* Access details */
final boolean isRecursive = MetisDataDifference.isEqual(pAccount, pPartner);
final MoneyWiseAssetType myPartnerType = pPartner.getAssetType();
final MoneyWiseTransCategoryClass myCatClass = Objects.requireNonNull(pCategory.getCategoryTypeClass());
/* Immediately reject hidden partners */
if (pPartner.isHidden()) {
return false;
}
/* Validate securityHolding */
if (pPartner instanceof MoneyWiseSecurityHolding myHolding
&& !checkSecurityHolding(myHolding)) {
return false;
}
/* Reject pensions portfolio */
if (pPartner instanceof MoneyWisePortfolio myPortfolio
&& myPortfolio.getCategoryClass().holdsPensions()) {
return false;
}
/* If this involves auto-expense */
if (pAccount.isAutoExpense()
|| pPartner.isAutoExpense()) {
/* Access account type */
final MoneyWiseAssetType myAccountType = pAccount.getAssetType();
/* Special processing */
switch (myCatClass) {
case TRANSFER:
/* Transfer must be to/from deposit/cash/loan */
return myPartnerType.isAutoExpense()
? myAccountType.isValued()
: myPartnerType.isValued();
case EXPENSE:
/* Transfer must be to/from payee */
return pPartner instanceof MoneyWisePayee;
/* Auto Expense cannot be used for other categories */
default:
return false;
}
}
/* Switch on the CategoryClass */
switch (myCatClass) {
case TAXEDINCOME:
case GROSSINCOME:
/* Taxed Income must have a Payee that can provide income */
return pPartner instanceof MoneyWisePayee myPayee
&& myPayee.getCategoryClass().canProvideTaxedIncome();
case PENSIONCONTRIB:
/* Pension Contribution must be a payee that can parent */
return pPartner instanceof MoneyWisePayee myPayee
&& myPayee.getCategoryClass().canContribPension();
case OTHERINCOME:
case RECOVEREDEXPENSES:
/* Other Income must have a Payee partner */
return pPartner instanceof MoneyWisePayee;
case LOCALTAXES:
/* LocalTaxes must have a Government Payee partner */
return pPartner instanceof MoneyWisePayee myPayee
&& myPayee.isPayeeClass(MoneyWisePayeeClass.GOVERNMENT);
case GIFTEDINCOME:
case INHERITED:
/* Gifted/Inherited Income must have an Individual Payee partner */
return pPartner instanceof MoneyWisePayee myPayee
&& myPayee.isPayeeClass(MoneyWisePayeeClass.INDIVIDUAL);
case RENTALINCOME:
case RENTALEXPENSE:
case ROOMRENTALINCOME:
/* RentalIncome/Expense must have a loan partner */
return myPartnerType.isLoan();
case WRITEOFF:
case LOANINTERESTEARNED:
case LOANINTERESTCHARGED:
/* WriteOff/LoanInterestEarned/Charged must be recursive */
return isRecursive;
case INTEREST:
case CASHBACK:
/* Interest/CashBack is to a valued account */
return myPartnerType.isValued();
case DIVIDEND:
return checkDividend(pAccount, pPartner);
case LOYALTYBONUS:
return checkLoyaltyBonus(pAccount, pPartner);
case BADDEBTCAPITAL:
case BADDEBTINTEREST:
return pPartner instanceof MoneyWisePayee
&& MetisDataDifference.isEqual(pPartner, pAccount.getParent());
case UNITSADJUST:
case STOCKSPLIT:
/* Must be recursive */
return isRecursive;
case SECURITYREPLACE:
case STOCKTAKEOVER:
case STOCKDEMERGER:
return checkTakeOver(pAccount, pPartner);
case STOCKRIGHTSISSUE:
return checkStockRights(pAccount, pPartner);
case TRANSFER:
return checkTransfer(pAccount, pPartner);
case SECURITYCLOSURE:
return checkSecurityClosure(pAccount, pPartner);
case EXPENSE:
/* Expense must have a Payee partner */
return pPartner instanceof MoneyWisePayee;
case INCOMETAX:
case TAXRELIEF:
return pPartner instanceof MoneyWisePayee myPayee
&& myPayee.isPayeeClass(MoneyWisePayeeClass.TAXMAN);
case PORTFOLIOXFER:
return checkPortfolioXfer(pAccount, pPartner);
default:
return false;
}
}
/**
* Check securityHolding.
*
* @param pHolding the securityHolding
* @return valid true/false
*/
private static boolean checkSecurityHolding(final MoneyWiseSecurityHolding pHolding) {
/* Access the components */
final MoneyWisePortfolio myPortfolio = pHolding.getPortfolio();
final MoneyWiseSecurity mySecurity = pHolding.getSecurity();
/* If the portfolio can hold pensions */
if (myPortfolio.getCategoryClass().holdsPensions()) {
/* Can only hold pensions */
return mySecurity.getCategoryClass().isPension();
}
/* cannot be a pension */
return !mySecurity.getCategoryClass().isPension();
}
/**
* Check dividend.
*
* @param pAccount the holding providing the dividend.
* @param pPartner the partner
* @return valid true/false
*/
private static boolean checkDividend(final MoneyWiseTransAsset pAccount,
final MoneyWiseTransAsset pPartner) {
/* Recursive is allowed */
if (MetisDataDifference.isEqual(pAccount, pPartner)) {
return true;
}
/* partner must be valued */
return pPartner.getAssetType().isValued();
}
/**
* Check TakeOver.
*
* @param pAccount the holding being acted on.
* @param pPartner the partner
* @return valid true/false
*/
private static boolean checkTakeOver(final MoneyWiseTransAsset pAccount,
final MoneyWiseTransAsset pPartner) {
/* Must be holding <-> holding */
if (!(pAccount instanceof MoneyWiseSecurityHolding)
|| !(pPartner instanceof MoneyWiseSecurityHolding)) {
return false;
}
/* Recursive is not allowed */
if (MetisDataDifference.isEqual(pAccount, pPartner)) {
return false;
}
/* Access holdings */
final MoneyWiseSecurityHolding myAccount = (MoneyWiseSecurityHolding) pAccount;
final MoneyWiseSecurityHolding myPartner = (MoneyWiseSecurityHolding) pPartner;
/* Portfolios must be the same */
if (!MetisDataDifference.isEqual(myAccount.getPortfolio(), myPartner.getPortfolio())) {
return false;
}
/* Security types must be the same */
return MetisDataDifference.isEqual(myAccount.getSecurity().getCategory(), myPartner.getSecurity().getCategory());
}
/**
* Check stock rights.
*
* @param pAccount the account being transferred.
* @param pPartner the partner
* @return valid true/false
*/
private static boolean checkStockRights(final MoneyWiseTransAsset pAccount,
final MoneyWiseTransAsset pPartner) {
/* If this is security -> portfolio */
if (pAccount instanceof MoneyWiseSecurityHolding myHolding
&& pPartner instanceof MoneyWisePortfolio) {
/* Must be same portfolios */
return MetisDataDifference.isEqual(myHolding.getPortfolio(), pPartner);
}
/* partner must be valued */
return pPartner.getAssetType().isValued();
}
/**
* Check cashBack.
*
* @param pAccount the account providing cashBack.
* @return valid true/false
*/
private static boolean checkCashBack(final MoneyWiseTransAsset pAccount) {
/* If this is deposit then check whether it can support cashBack */
if (pAccount instanceof MoneyWiseDeposit myDeposit) {
return myDeposit.getCategoryClass().canCashBack();
}
/* If this is loan then check whether it can support cashBack */
if (pAccount instanceof MoneyWiseLoan myLoan) {
return myLoan.getCategoryClass().canCashBack();
}
/* not allowed */
return false;
}
/**
* Check loyalty bonus.
*
* @param pAccount the account providing bonus.
* @return valid true/false
*/
private boolean checkLoyaltyBonus(final MoneyWiseTransAsset pAccount) {
/* If this is deposit then check whether it can support loyaltyBonus */
if (pAccount instanceof MoneyWiseDeposit myDeposit) {
return newValidation
|| myDeposit.getCategoryClass().canLoyaltyBonus();
}
/* must be portfolio */
return pAccount instanceof MoneyWisePortfolio;
}
/**
* Check loyalty bonus.
*
* @param pAccount the account providing bonus.
* @param pPartner the partner
* @return valid true/false
*/
private static boolean checkLoyaltyBonus(final MoneyWiseTransAsset pAccount,
final MoneyWiseTransAsset pPartner) {
/* If this is portfolio -> security holding */
if (pAccount instanceof MoneyWisePortfolio
&& pPartner instanceof MoneyWiseSecurityHolding myHolding) {
/* Must be same portfolios */
return MetisDataDifference.isEqual(myHolding.getPortfolio(), pAccount);
}
/* must be recursive */
return MetisDataDifference.isEqual(pAccount, pPartner);
}
/**
* Check transfer.
*
* @param pAccount the account being transferred.
* @param pPartner the partner
* @return valid true/false
*/
private static boolean checkTransfer(final MoneyWiseTransAsset pAccount,
final MoneyWiseTransAsset pPartner) {
/* Must not be recursive */
if (MetisDataDifference.isEqual(pAccount, pPartner)) {
return false;
}
/* If this is security -> portfolio */
if (pAccount instanceof MoneyWiseSecurityHolding myHolding
&& pPartner instanceof MoneyWisePortfolio) {
/* Must be same portfolios */
if (!MetisDataDifference.isEqual(myHolding.getPortfolio(), pPartner)) {
return false;
}
}
/* If this is security <- portfolio */
if (pPartner instanceof MoneyWiseSecurityHolding myHolding
&& pAccount instanceof MoneyWisePortfolio) {
/* Must be same portfolios */
if (!MetisDataDifference.isEqual(myHolding.getPortfolio(), pAccount)) {
return false;
}
}
/* partner must be asset */
return pPartner.getAssetType().isAsset();
}
/**
* Check securityClosure.
*
* @param pAccount the account being closed.
* @param pPartner the partner
* @return valid true/false
*/
private static boolean checkSecurityClosure(final MoneyWiseTransAsset pAccount,
final MoneyWiseTransAsset pPartner) {
/* Must not be recursive */
if (MetisDataDifference.isEqual(pAccount, pPartner)) {
return false;
}
/* partner must be valued */
return pPartner.getAssetType().isValued();
}
/**
* Check portfolioXfer.
*
* @param pAccount the account being transferred.
* @param pPartner the partner
* @return valid true/false
*/
private static boolean checkPortfolioXfer(final MoneyWiseTransAsset pAccount,
final MoneyWiseTransAsset pPartner) {
/* Partner must be portfolio */
if (!(pPartner instanceof MoneyWisePortfolio)) {
return false;
}
/* If account is portfolio */
if (pAccount instanceof MoneyWisePortfolio) {
/* Cannot be recursive */
if (MetisDataDifference.isEqual(pAccount, pPartner)) {
return false;
}
/* Must be same currency */
return MetisDataDifference.isEqual(pAccount.getAssetCurrency(), pPartner.getAssetCurrency());
}
/* If account is security holding */
if (pAccount instanceof MoneyWiseSecurityHolding myHolding) {
/* Must be different portfolios */
return !MetisDataDifference.isEqual(myHolding.getPortfolio(), pPartner);
}
/* Not allowed */
return false;
}
/**
* Determine if an infoSet class is required.
*
* @param pTrans the transaction
* @param pClass the infoSet class
* @return the status
*/
public MetisFieldRequired isClassRequired(final MoneyWiseTransaction pTrans,
final MoneyWiseTransInfoClass pClass) {
theInfoSet.storeInfoSet(pTrans.getInfoSet());
return theInfoSet.isClassRequired(pClass);
}
@Override
public void autoCorrect(final MoneyWiseTransaction pItem) throws OceanusException {
theDefaults.autoCorrect(pItem);
}
@Override
public MoneyWiseTransaction buildTransaction(final Object pKey) {
return theDefaults.buildTransaction(pKey);
}
@Override
public void setRange(final OceanusDateRange pRange) {
theDefaults.setRange(pRange);
}
@Override
public OceanusDateRange getRange() {
return theDefaults.getRange();
}
}