gt:             if (peer != EMPTY_PEER)
context: package name.abuchen.portfolio.ui.dialogs.transactions;
  
  import java.math.BigDecimal;
  import java.math.RoundingMode;
  import java.time.LocalDate;
  import java.time.LocalDateTime;
  import java.time.LocalTime;
  
  import org.eclipse.core.databinding.validation.ValidationStatus;
  import org.eclipse.core.runtime.IStatus;
  
  import com.ibm.icu.text.MessageFormat;
  
  import name.abuchen.portfolio.model.Account;
  import name.abuchen.portfolio.model.AccountTransaction;
  import name.abuchen.portfolio.model.Client;
  import name.abuchen.portfolio.model.Peer;
  import name.abuchen.portfolio.model.PeerList;
  import name.abuchen.portfolio.model.Security;
  import name.abuchen.portfolio.model.SecurityEvent;
  import name.abuchen.portfolio.model.Transaction;
  import name.abuchen.portfolio.money.CurrencyConverter;
  import name.abuchen.portfolio.money.CurrencyConverterImpl;
  import name.abuchen.portfolio.money.ExchangeRate;
  import name.abuchen.portfolio.money.ExchangeRateTimeSeries;
  import name.abuchen.portfolio.money.Money;
  import name.abuchen.portfolio.money.Values;
  import name.abuchen.portfolio.snapshot.ClientSnapshot;
  import name.abuchen.portfolio.snapshot.SecurityPosition;
  import name.abuchen.portfolio.ui.Messages;
  
  public class AccountTransactionModel extends AbstractModel
  {
      public enum Properties
      {
          security, account, date, time, peer, partner, iban, shares, fxGrossAmount, dividendAmount, exchangeRate, inverseExchangeRate, grossAmount, // NOSONAR
          fxTaxes, taxes, fxFees, fees, total, note, exchangeRateCurrencies, inverseExchangeRateCurrencies, // NOSONAR
          accountCurrencyCode, securityCurrencyCode, fxCurrencyCode, calculationStatus; // NOSONAR
      }
  
      public static final Security EMPTY_SECURITY = new Security("-----", ""); //$NON-NLS-1$ //$NON-NLS-2$
      public static final Peer     EMPTY_PEER     = new Peer().voidAccount();
  
      private final Client client;
      private AccountTransaction.Type type;
  
      private Account sourceAccount;
      private AccountTransaction sourceTransaction;
  
      private Security security;
      private Account account;
      private Peer peer;
      private String partner;
      private String iban;
  
      private LocalDate date = LocalDate.now();
      private LocalTime time = LocalTime.MIDNIGHT;
      private LocalDate cutoffDate = LocalDate.now();
      private long shares;
  
      private long fxGrossAmount;
      private BigDecimal dividendAmount = BigDecimal.ZERO;
      private BigDecimal exchangeRate = BigDecimal.ONE;
      private long grossAmount;
  
      private long fxTaxes;
      private long taxes;
      private long fxFees;
      private long fees;
      private long total;
  
      private String note;
  
      private IStatus calculationStatus = ValidationStatus.ok();
  
      public AccountTransactionModel(Client client, AccountTransaction.Type type)
      {
          this.client = client;
          this.type = type;
  
          checkType();
      }
  
      @Override
      public String getHeading()
      {
          return type.toString();
      }
  
      private void checkType()
      {
          switch (type)
          {
              case DEPOSIT:
              case REMOVAL:
              case FEES:
              case FEES_REFUND:
              case TAXES:
              case TAX_REFUND:
              case INTEREST:
              case INTEREST_CHARGE:
              case DIVIDENDS:
              case DIVIDEND_CHARGE:
                  return;
              case BUY:
              case SELL:
              case TRANSFER_IN:
              case TRANSFER_OUT:
              default:
                  throw new UnsupportedOperationException();
          }
      }
  
      @Override
      public void applyChanges()
      {
          if (security == null && supportsSecurity() && !supportsOptionalSecurity())
              throw new UnsupportedOperationException(Messages.MsgMissingSecurity);
          if (account == null)
              throw new UnsupportedOperationException(Messages.MsgMissingAccount);
          if (peer == null && supportsPeer())
              throw new UnsupportedOperationException(Messages.MsgMissingPeer);
  
          AccountTransaction t;
  
          if (sourceTransaction != null && sourceAccount.equals(account))
          {
              // transactions stays in same account
              t = sourceTransaction;
          }
          else
          {
              if (sourceTransaction != null)
              {
                  sourceAccount.deleteTransaction(sourceTransaction, client);
                  sourceTransaction = null;
                  sourceAccount = null;
              }
  
              t = new AccountTransaction();
              t.setCurrencyCode(getAccountCurrencyCode());
              account.addTransaction(t);
          }
  
          t.setDateTime(LocalDateTime.of(date, time));
          t.setSecurity(!EMPTY_SECURITY.equals(security) ? security : null);
          t.setShares(supportsShares() ? shares : 0);
          t.setAmount(total);
          t.setType(type);
          t.setNote(note);
  
          if (supportsPeer())
              t.setPeer(EMPTY_PEER.equals(peer) ? null : peer);
  
          t.clearUnits();
  
          if(fees != 0)
              t.addUnit(new Transaction.Unit(Transaction.Unit.Type.FEE, Money.of(getAccountCurrencyCode(), fees)));
          
          if (taxes != 0)
              t.addUnit(new Transaction.Unit(Transaction.Unit.Type.TAX, Money.of(getAccountCurrencyCode(), taxes)));
  
          String fxCurrencyCode = getFxCurrencyCode();
          if (!fxCurrencyCode.equals(account.getCurrencyCode()))
          {
              Transaction.Unit forex = new Transaction.Unit(Transaction.Unit.Type.GROSS_VALUE, //
                              Money.of(getAccountCurrencyCode(), grossAmount), //
                              Money.of(getSecurityCurrencyCode(), fxGrossAmount), //
                              getExchangeRate());
              t.addUnit(forex);
  
              if (fxFees != 0)
                  t.addUnit(new Transaction.Unit(Transaction.Unit.Type.FEE, //
                                  Money.of(getAccountCurrencyCode(), Math.round(fxFees * exchangeRate.doubleValue())), //
                                  Money.of(getSecurityCurrencyCode(), fxFees), //
                                  exchangeRate));
              
              if (fxTaxes != 0)
                  t.addUnit(new Transaction.Unit(Transaction.Unit.Type.TAX, //
                                  Money.of(getAccountCurrencyCode(), Math.round(fxTaxes * exchangeRate.doubleValue())), //
                                  Money.of(getSecurityCurrencyCode(), fxTaxes), //
                                  exchangeRate));
          }
          if (type == AccountTransaction.Type.DIVIDENDS)
          {
                  security.addEvent((new SecurityEvent(cutoffDate, SecurityEvent.Type.STOCK_DIVIDEND)).setAmount(getFxCurrencyCode(), dividendAmount));
          }
  
      }
  
      @Override
      public void resetToNewTransaction()
      {
          this.sourceAccount = null;
          this.sourceTransaction = null;
  
          setFxGrossAmount(0);
          setDividendAmount(BigDecimal.ZERO);
          setGrossAmount(0);
          setFees(0);
          setFxFees(0);
          setTaxes(0);
          setFxTaxes(0);
          setNote(null);
      }
  
  
      public boolean supportsPeer()
      {
          switch (type)
          {
              case REMOVAL:
              case DEPOSIT:
              case INTEREST:
              case INTEREST_CHARGE:
                  return true;
              default:
                  return false;
          }
      }
  
      public boolean supportsShares()
      {
          switch (type)
          {
              case DIVIDEND_CHARGE:
              case DIVIDENDS:
                  return true;
              default:
                  return false;
          }
      }
  
      public boolean supportsSecurity()
      {
          switch (type)
          {
              case DIVIDEND_CHARGE:
              case DIVIDENDS:
              case TAXES:
              case TAX_REFUND:
              case FEES:
              case FEES_REFUND:
                  return true;
              default:
                  return false;
          }
      }
  
      public boolean supportsOptionalSecurity()
      {
          switch (type)
          {
              case TAXES:
              case TAX_REFUND:
              case FEES:
              case FEES_REFUND:
                  return true;
              default:
                  return false;
          }
      }
  
      public boolean supportsTaxUnits()
      {
          switch (type)
          {
              case DIVIDEND_CHARGE:
              case DIVIDENDS:
              case INTEREST:
              case INTEREST_CHARGE:
                  return true;
              default:
                  return false;
          }
      }
      
      public boolean supportsFees()
      {
          switch (type)
          {
              case DIVIDEND_CHARGE:
              case DIVIDENDS:
              case INTEREST:
              case INTEREST_CHARGE:
                  return true;
              default:
                  return false;
          }
      }
  
      public void setSource(Account account, AccountTransaction transaction)
      {
          this.sourceAccount = account;
          this.sourceTransaction = transaction;
  
          this.security = transaction.getSecurity();
          if (this.security == null && supportsOptionalSecurity())
              this.security = EMPTY_SECURITY;
  
          this.account = account;
          LocalDateTime transactionDate = transaction.getDateTime();
          this.time = transactionDate.toLocalTime();
          this.date    = transactionDate.toLocalDate();
          this.cutoffDate = this.date.minusDays((long) (EMPTY_SECURITY.equals(this.security) || !supportsShares()? 0 : this.security.getDelayedDividend()));
          this.shares  = transaction.getShares();
          this.total   = transaction.getAmount();
          this.peer    = transaction.getPeer();
          if (supportsPeer())
          {
              if (this.peer == null)
                  this.peer = EMPTY_PEER;
  