Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds option for non cash-effective dividend payments. #2971

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,9 @@ public class Messages extends NLS
public static String OptionDateIsInTheFuture;
public static String OptionDateIsInThePast;
public static String YearlyPerformanceHeatmapToolTip;
public static String nonCashEffective;
public static String LabelnonCashEffective;
public static String MsgInfoNonCashEffective;
static
{
// initialize resource bundle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
Expand All @@ -45,12 +46,14 @@
import name.abuchen.portfolio.snapshot.ClientSnapshot;
import name.abuchen.portfolio.snapshot.PortfolioSnapshot;
import name.abuchen.portfolio.snapshot.SecurityPosition;
import name.abuchen.portfolio.ui.Images;
import name.abuchen.portfolio.ui.Messages;
import name.abuchen.portfolio.ui.UIConstants;
import name.abuchen.portfolio.ui.dialogs.transactions.AccountTransactionModel.Properties;
import name.abuchen.portfolio.ui.util.FormDataFactory;
import name.abuchen.portfolio.ui.util.LabelOnly;
import name.abuchen.portfolio.ui.util.SWTHelper;
import name.abuchen.portfolio.ui.util.swt.ControlDecoration;

public class AccountTransactionDialog extends AbstractTransactionDialog // NOSONAR
{
Expand Down Expand Up @@ -204,6 +207,25 @@ public void widgetSelected(SelectionEvent e)
total.bindCurrency(Properties.accountCurrencyCode.name());
total.setVisible(model().supportsTaxUnits() || model().supportsFees());

// cash effectiveness

Label labelnonCashEffective = new Label(editArea, SWT.LEFT);
labelnonCashEffective.setText(Messages.nonCashEffective);
Button buttonnonCashEffective = new Button(editArea, SWT.CHECK);
IObservableValue<?> targetnonCashEffective = WidgetProperties.buttonSelection().observe(buttonnonCashEffective);
IObservableValue<?> modelnonCashEffective = BeanProperties.value(Properties.nonCashEffective.name())
.observe(model);
context.bindValue(targetnonCashEffective, modelnonCashEffective);
buttonnonCashEffective.setVisible(model().supportsnonCashEffective());
labelnonCashEffective.setVisible(model().supportsnonCashEffective());

Image info = Images.INFO.image();
ControlDecoration deco = new ControlDecoration(buttonnonCashEffective, SWT.CENTER | SWT.LEFT);
deco.setDescriptionText(Messages.MsgInfoNonCashEffective);
deco.setImage(info);
deco.setMarginWidth(2);
deco.show();

// note

Label lblNote = new Label(editArea, SWT.LEFT);
Expand Down Expand Up @@ -237,7 +259,6 @@ public void widgetSelected(SelectionEvent e)
int currencyWidth = currencyWidth(fxGrossAmount.currency);

// date
// shares
forms = forms.thenBelow(dateTime.date.getControl()).label(dateTime.label);

startingWith(dateTime.date.getControl()).thenRight(dateTime.time).thenRight(dateTime.button, 0);
Expand Down Expand Up @@ -294,6 +315,14 @@ public void widgetSelected(SelectionEvent e)
.width(currencyWidth);
}

// cash effectiveness
if (model().supportsnonCashEffective())
{
forms = forms.thenBelow(buttonnonCashEffective).height(SWTHelper.lineHeight(buttonnonCashEffective) * 2)
.left(accounts.value.getControl());
startingWith(buttonnonCashEffective).thenRight(labelnonCashEffective);
}

// note
forms.thenBelow(valueNote).height(SWTHelper.lineHeight(valueNote) * 3).left(accounts.value.getControl())
.right(grossAmount.value).label(lblNote);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public enum Properties
{
security, account, date, time, shares, fxGrossAmount, dividendAmount, exchangeRate, inverseExchangeRate, grossAmount, // NOSONAR
fxTaxes, taxes, fxFees, fees, total, note, exchangeRateCurrencies, inverseExchangeRateCurrencies, // NOSONAR
accountCurrencyCode, securityCurrencyCode, fxCurrencyCode, calculationStatus; // NOSONAR
accountCurrencyCode, securityCurrencyCode, fxCurrencyCode, calculationStatus, nonCashEffective; // NOSONAR
}

public static final Security EMPTY_SECURITY = new Security("-----", ""); //$NON-NLS-1$ //$NON-NLS-2$
Expand Down Expand Up @@ -60,9 +60,11 @@ public enum Properties
private long total;

private String note;
private boolean nonCashEffective;

private IStatus calculationStatus = ValidationStatus.ok();


public AccountTransactionModel(Client client, AccountTransaction.Type type)
{
this.client = client;
Expand Down Expand Up @@ -134,6 +136,7 @@ public void applyChanges()
t.setShares(supportsShares() ? shares : 0);
t.setAmount(total);
t.setType(type);
t.setnonCashEffective(nonCashEffective);
t.setNote(note);

t.clearUnits();
Expand Down Expand Up @@ -181,6 +184,7 @@ public void resetToNewTransaction()
setTaxes(0);
setFxTaxes(0);
setNote(null);
setnonCashEffective(false);
setTime(PresetValues.getTime());
}

Expand Down Expand Up @@ -228,6 +232,11 @@ public boolean supportsFees()
return type == AccountTransaction.Type.DIVIDENDS;
}

public boolean supportsnonCashEffective()
{
return type == AccountTransaction.Type.DIVIDENDS;
}

public void setSource(Account account, AccountTransaction transaction)
{
this.sourceAccount = account;
Expand Down Expand Up @@ -285,6 +294,8 @@ public void setSource(Account account, AccountTransaction transaction)
this.dividendAmount = calculateDividendAmount();

this.note = transaction.getNote();

this.nonCashEffective = transaction.getnonCashEffective();
}

@Override
Expand Down Expand Up @@ -663,6 +674,17 @@ public void setNote(String note)
firePropertyChange(Properties.note.name(), this.note, this.note = note);
}

public boolean getnonCashEffective()
{
return nonCashEffective;
}

public void setnonCashEffective(boolean nonCashEffective)
{
firePropertyChange(Properties.nonCashEffective.name(), this.nonCashEffective,
this.nonCashEffective = nonCashEffective);
}

public String getAccountCurrencyCode()
{
return account != null ? account.getCurrencyCode() : ""; //$NON-NLS-1$
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2435,3 +2435,9 @@ WatchlistRename = Rename Watchlist
Website = Website

YearlyPerformanceHeatmapToolTip = Yearly rate of return displayed as heatmap\n\nTo calculate the yearly rate of return, the true-time weighted rate of return (TTWROR) is used.\n\nThe rate of return is always calculated for the full year - even if the reporting interval ends or starts in the middle of a year.

nonCashEffective = non cash-effective dividend

LabelnonCashEffective = Exclude non cash-effective dividends

MsgInfoNonCashEffective = Marking a dividend payment as non cash-effective allows the dividend to be excluded in the payments view. \nThis option can be used e.g. for stock dividends or spin offs.
Original file line number Diff line number Diff line change
Expand Up @@ -2418,3 +2418,9 @@ WatchlistRename = Watchliste umbenennen
Website = Website

YearlyPerformanceHeatmapToolTip = Jahresrenditen in einer Heatmap\n\nZur Berechnung der Jahresrendite wird der True-Time Weighted Rate of Return (TTWROR) herangezogen.\n\nDie Rendite bezieht sich immer auf das gesamte Jahr - selbst wenn der Berichtszeitraum in der Mitte des Jahres beginnt bzw. endet.

nonCashEffective = nicht-zahlungswirksame Dividende

LabelnonCashEffective = Nicht-zahlungswirksame Dividenden ausschlie\u00DFen

MsgInfoNonCashEffective = Eine Dividendenzahlung als nicht-zahlungswirksam zu markieren erlaubt es, die Dividende in der Ansicht Zahlungen auszuschlie\u00DFen. \nDiese Option kann z.B. bei Aktien Dividenden oder Spin Offs verwendet werden.
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@
import name.abuchen.portfolio.ui.editor.AbstractFinanceView;
import name.abuchen.portfolio.ui.util.DropDown;
import name.abuchen.portfolio.ui.util.SimpleAction;
import name.abuchen.portfolio.ui.views.payments.PaymentsViewModel.Mode;
import name.abuchen.portfolio.ui.views.panes.HistoricalPricesPane;
import name.abuchen.portfolio.ui.views.panes.InformationPanePage;
import name.abuchen.portfolio.ui.views.panes.SecurityEventsPane;
import name.abuchen.portfolio.ui.views.panes.SecurityPriceChartPane;
import name.abuchen.portfolio.ui.views.panes.TradesPane;
import name.abuchen.portfolio.ui.views.panes.TransactionsPane;
import name.abuchen.portfolio.ui.views.payments.PaymentsViewModel.Mode;
import name.abuchen.portfolio.util.TextUtil;

public class PaymentsView extends AbstractFinanceView
Expand All @@ -44,6 +44,8 @@ public class PaymentsView extends AbstractFinanceView
private static final String KEY_USE_GROSS_VALUE = PaymentsView.class.getSimpleName() + "-use-gross-value"; //$NON-NLS-1$
private static final String KEY_USE_CONSOLIDATE_RETIRED = PaymentsView.class.getSimpleName()
+ "-use-consolidate-retired"; //$NON-NLS-1$
private static final String KEY_EXCLUDE_NON_CASH_EFFECTIVE = PaymentsView.class.getSimpleName()
+ "-exclude-non-cash-effective"; //$NON-NLS-1$

@Inject
private Client client;
Expand Down Expand Up @@ -86,14 +88,16 @@ public void setupModel()

boolean useGrossValue = preferences.getBoolean(KEY_USE_GROSS_VALUE);
boolean useConsolidateRetired = preferences.getBoolean(KEY_USE_CONSOLIDATE_RETIRED);
boolean excludenonCashEffective = preferences.getBoolean(KEY_EXCLUDE_NON_CASH_EFFECTIVE);

model.configure(year, mode, useGrossValue, useConsolidateRetired);
model.configure(year, mode, useGrossValue, useConsolidateRetired, excludenonCashEffective);

model.addUpdateListener(() -> {
preferences.setValue(KEY_YEAR, model.getStartYear());
preferences.setValue(KEY_MODE, model.getMode().name());
preferences.setValue(KEY_USE_GROSS_VALUE, model.usesGrossValue());
preferences.setValue(KEY_USE_CONSOLIDATE_RETIRED, model.usesConsolidateRetired());
preferences.setValue(KEY_EXCLUDE_NON_CASH_EFFECTIVE, model.excludesnonCashEffective());
});
}

Expand Down Expand Up @@ -176,6 +180,12 @@ protected void addButtons(ToolBarManager toolBar)
action.setChecked(model.usesConsolidateRetired());
manager.add(action);

// cash effectiveness
action = new SimpleAction(Messages.LabelnonCashEffective,
a -> model.setexcludenonCashEffective(!model.excludesnonCashEffective()));
action.setChecked(model.excludesnonCashEffective());
manager.add(action);

PaymentsTab tab = (PaymentsTab) folder.getSelection().getData();
if (tab != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ public <T> T adapt(Class<T> type)

private Mode mode = Mode.ALL;
private boolean useGrossValue = true;
private boolean excludenonCashEffective = true;
private boolean useConsolidateRetired = true;

public PaymentsViewModel(AbstractFinanceView view, IPreferenceStore preferences, CurrencyConverter converter,
Expand All @@ -168,12 +169,14 @@ public PaymentsViewModel(AbstractFinanceView view, IPreferenceStore preferences,
this.clientFilter.getSelectedItem().getUUIDs()));
}

public void configure(int startYear, Mode mode, boolean useGrossValue, boolean useConsolidateRetired)
public void configure(int startYear, Mode mode, boolean useGrossValue, boolean useConsolidateRetired,
boolean excludenonCashEffective)
{
this.startYear = startYear;
this.mode = mode;
this.useGrossValue = useGrossValue;
this.useConsolidateRetired = useConsolidateRetired;
this.excludenonCashEffective = excludenonCashEffective;

recalculate();
}
Expand Down Expand Up @@ -235,6 +238,17 @@ public void setUseGrossValue(boolean useGrossValue)
recalculate();
}

public boolean excludesnonCashEffective()
{
return excludenonCashEffective;
}

public void setexcludenonCashEffective(boolean excludenonCashEffective)
{
this.excludenonCashEffective = excludenonCashEffective;
recalculate();
}

public boolean usesConsolidateRetired()
{
return useConsolidateRetired;
Expand Down Expand Up @@ -399,6 +413,9 @@ private void calculate()
if (!checkIsInInterval.test(transaction))
continue;

if (excludenonCashEffective && transaction.getnonCashEffective())
continue;

long value = 0;
switch (mode)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ public int compare(Transaction t1, Transaction t2)
private long shares;
private String note;
private String source;
private boolean nonCashEffective;

private List<Unit> units;

Expand Down Expand Up @@ -240,6 +241,19 @@ public Transaction(LocalDateTime date, String currencyCode, long amount, Securit
this.note = note;
}

public Transaction(LocalDateTime date, String currencyCode, long amount, Security security, long shares,
String note, Boolean nonCashEffective)
{
this();
this.date = date;
this.currencyCode = currencyCode;
this.amount = amount;
this.security = security;
this.shares = shares;
this.note = note;
this.nonCashEffective = nonCashEffective;
}

public String getUUID()
{
return uuid;
Expand Down Expand Up @@ -357,6 +371,17 @@ public void setSource(String source)
this.updatedAt = Instant.now();
}

public boolean getnonCashEffective()
{
return nonCashEffective;
}

public void setnonCashEffective(Boolean nonCashEffective)
{
this.nonCashEffective = nonCashEffective;
this.updatedAt = Instant.now();
}

public Instant getUpdatedAt()
{
return updatedAt;
Expand Down