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

Add weekly investment plan #4347

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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 @@ -290,4 +290,78 @@ public void testErrorMessageWhenNoQuotesExist() throws IOException
investmentPlan.generateTransactions(new TestCurrencyConverter());
}

@Test
public void testGenerationOfWeeklyBuyTransaction() throws IOException
{
investmentPlan.setType(InvestmentPlan.Type.PURCHASE_OR_DELIVERY);

investmentPlan.setAccount(account); // set both account and portfolio
investmentPlan.setPortfolio(portfolio); // causes securities to be
// bought
investmentPlan.setSecurity(security);
investmentPlan.setStart(LocalDateTime.parse("2016-01-01T00:00:00"));

investmentPlan.setInterval(100); // 100 is weekly, 200 is every two
// weeks

investmentPlan.generateTransactions(new TestCurrencyConverter());

List<Transaction> tx = investmentPlan.getTransactions().stream()
.filter(t -> t.getDateTime().isBefore(LocalDateTime.parse("2016-06-01T00:00")))
.collect(Collectors.toList());

assertThat(tx.size(), is(22));

// Friday 1st January 2016 is holiday. The real first transaction is
// Monday 4 January 2016
tx = investmentPlan.getTransactions().stream().collect(Collectors.toList());
assertThat(tx.get(0), instanceOf(PortfolioTransaction.class));
assertThat(tx.get(0).getDateTime(), is(LocalDateTime.parse("2016-01-04T00:00")));
assertThat(((PortfolioTransaction) tx.get(0)).getType(), is(PortfolioTransaction.Type.BUY));

tx = investmentPlan.getTransactions().stream()
.filter(t -> t.getDateTime().getYear() == 2016 && t.getDateTime().getMonth() == Month.MARCH)
.collect(Collectors.toList());

assertThat(investmentPlan.getPlanType(), is(InvestmentPlan.Type.PURCHASE_OR_DELIVERY));

// March 2016 has Friday 25 as holiday and Monday 28 too : the 25th
// March transaction should be offset to 29th March

assertThat(tx.size(), is(4));
assertThat(tx.get(0), instanceOf(PortfolioTransaction.class));
assertThat(tx.get(1), instanceOf(PortfolioTransaction.class));

assertThat(tx.get(0).getDateTime(), is(LocalDateTime.parse("2016-03-04T00:00")));
assertThat(((PortfolioTransaction) tx.get(0)).getType(), is(PortfolioTransaction.Type.BUY));

assertThat(tx.get(1).getDateTime(), is(LocalDateTime.parse("2016-03-11T00:00")));
assertThat(((PortfolioTransaction) tx.get(1)).getType(), is(PortfolioTransaction.Type.BUY));

assertThat(tx.get(3).getDateTime(), is(LocalDateTime.parse("2016-03-29T00:00")));
assertThat(((PortfolioTransaction) tx.get(1)).getType(), is(PortfolioTransaction.Type.BUY));

// there are 5 Fridays in April 2016. Check that the weekly plan is back
// on Friday after the Tuesday 29 March 2016 transaction.
List<Transaction> txApril = investmentPlan.getTransactions().stream()
.filter(t -> t.getDateTime().getYear() == 2016 && t.getDateTime().getMonth() == Month.APRIL)
.collect(Collectors.toList());
assertThat(txApril.size(), is(5));
assertThat(txApril.get(0), instanceOf(PortfolioTransaction.class));
assertThat(txApril.get(0).getDateTime(), is(LocalDateTime.parse("2016-04-01T00:00")));
assertThat(((PortfolioTransaction) txApril.get(0)).getType(), is(PortfolioTransaction.Type.BUY));

// check that delta generation of transactions also takes into account
// the Calendar
investmentPlan.getTransactions().stream()
.filter(t -> t.getDateTime().isAfter(LocalDateTime.parse("2016-03-20T00:00")))
.collect(Collectors.toList())
.forEach(t -> investmentPlan.removeTransaction((PortfolioTransaction) t));

List<TransactionPair<?>> newlyGenerated = investmentPlan.generateTransactions(new TestCurrencyConverter());
assertThat(newlyGenerated.isEmpty(), is(false));
assertThat(newlyGenerated.get(0).getTransaction(), instanceOf(PortfolioTransaction.class));
assertThat(newlyGenerated.get(0).getTransaction().getDateTime(), is(LocalDateTime.parse("2016-03-29T00:00")));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ public class Messages extends NLS
public static String InvestmentPlanAutoCreationJob;
public static String InvestmentPlanInfoNoTransactionsGenerated;
public static String InvestmentPlanIntervalLabel;
public static String InvestmentPlanIntervalWeeklyLabel;
public static String InvestmentPlanMenuCreate;
public static String InvestmentPlanMenuDelete;
public static String InvestmentPlanMenuGenerateTransactions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ protected void createFormElements(Composite editArea)
// interval

List<Integer> available = new ArrayList<>();
for (int ii = 1; ii <= 12; ii++)
available.add(ii);
for (var entry : InvestmentPlanModel.Intervals.values())
available.add(entry.getInterval());

ComboInput interval = new ComboInput(editArea, Messages.ColumnInterval);
interval.value.setInput(available);
Expand All @@ -150,7 +150,7 @@ protected void createFormElements(Composite editArea)
public String getText(Object element)
{
int interval = (Integer) element;
return MessageFormat.format(Messages.InvestmentPlanIntervalLabel, interval);
return InvestmentPlanModel.Intervals.get(interval).toString();
}
});
interval.bindValue(Properties.interval.name(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,55 @@ public enum Properties

private IStatus calculationStatus = ValidationStatus.ok();

public enum Intervals
{
WEEKLY(100), //
BIWEEKLY(200), //
MONTHLY(1), //
MONTHLY2(2), //
MONTHLY3(3), //
MONTHLY4(4), //
MONTHLY5(5), //
MONTHLY6(6), //
MONTHLY7(7), //
MONTHLY8(8), //
MONTHLY9(9), //
MONTHLY10(10), //
MONTHLY11(11), //
MONTHLY12(12); //

private final Integer interval;

private Intervals(Integer interval)
{
this.interval = interval;
}

public Integer getInterval()
{
return interval;
}

public static Intervals get(Integer interval)
{
for (Intervals e : Intervals.values())
{
if (e.interval.equals(interval))
return e;
}
throw new IllegalArgumentException("unknown interval"); //$NON-NLS-1$
}

@Override
public String toString()
{
if (interval <= 12) // monthly
return MessageFormat.format(Messages.InvestmentPlanIntervalLabel, interval);
else // weekly or biweekly
return MessageFormat.format(Messages.InvestmentPlanIntervalWeeklyLabel, interval / 100);
}
}

public InvestmentPlanModel(Client client, InvestmentPlan.Type planType)
{
this.client = client;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,8 @@ InvestmentPlanInfoNoTransactionsGenerated = No transactions generated.\nThe next

InvestmentPlanIntervalLabel = {0,choice,1#monthly|1<every {0} months}

InvestmentPlanIntervalWeeklyLabel = {0,choice,1#weekly|1<every {0} weeks}

InvestmentPlanMenuCreate = New Plan...

InvestmentPlanMenuDelete = Delete Investment Plan
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,8 @@ InvestmentPlanInfoNoTransactionsGenerated = Nebyly vygenerov\u00E1ny \u017E\u00E

InvestmentPlanIntervalLabel = {0,choice,1#m\u011Bs\u00ED\u010Dn\u011B|1<ka\u017Ed\u00E9 {0} m\u011Bs\u00EDce}

InvestmentPlanIntervalWeeklyLabel = {0,choice,1#t\u00FDdn\u011B|1<ka\u017Ed\u00E9 {0} t\u00FDdny}

InvestmentPlanMenuCreate = Nov\u00FD pl\u00E1n...

InvestmentPlanMenuDelete = Smazat investi\u010Dn\u00ED pl\u00E1n
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = Ingen transaktioner genereret.\nDen
InvestmentPlanIntervalLabel = {0,choice,1#m\u00E5nedlig|1<every {0} months}
InvestmentPlanIntervalWeeklyLabel = {0,choice,1#ugentlig|1<hver {0} uge}
InvestmentPlanMenuCreate = Ny plan...
InvestmentPlanMenuDelete = Slet investeringsplan
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,8 @@ InvestmentPlanInfoNoTransactionsGenerated = Es wurden keine Buchungen erstellt.\

InvestmentPlanIntervalLabel = {0,choice,1#monatlich|1<alle {0} Monate}

InvestmentPlanIntervalWeeklyLabel = {0,choice,1#w\u00F6chentlich|1<alle {0} Wochen}

InvestmentPlanMenuCreate = Neuer Sparplan...

InvestmentPlanMenuDelete = Sparplan l\u00F6schen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = No se generaron transacciones.\nLa p

InvestmentPlanIntervalLabel = {0,choice,1#mensual|1<Cada {0} meses}

InvestmentPlanIntervalWeeklyLabel = {0,choice,1#semanalmente|1<Cada {0} semanas}

InvestmentPlanMenuCreate = Nuevo plan de inversi\u00F3n...

InvestmentPlanMenuDelete = Eliminar Plan de Inversiones
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,8 @@ InvestmentPlanInfoNoTransactionsGenerated = Aucune op\u00E9ration g\u00E9n\u00E9

InvestmentPlanIntervalLabel = {0,choice,1#mensuel|1<tous les {0} mois}

InvestmentPlanIntervalWeeklyLabel = {0,choice,1#hebdomadaire|1<toutes les {0} semaines}

InvestmentPlanMenuCreate = Nouveau plan...

InvestmentPlanMenuDelete = Supprimer le plan d'investissement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = Non \u00E8 stata generata alcuna ope
InvestmentPlanIntervalLabel = {0,choice,1#mensilmente|1<ogni {0} mesi}
InvestmentPlanIntervalWeeklyLabel = {0,choice,1#settimanale|1<ogni {0} settimane}
InvestmentPlanMenuCreate = Nuovo piano...
InvestmentPlanMenuDelete = Elimina piano di investimento
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = Geen transacties gegenereerd.\nDe vo
InvestmentPlanIntervalLabel = {0,choice,1#maandelijks|1<elke {0} maanden}
InvestmentPlanIntervalWeeklyLabel = {0,choice,1#wekelijks|1<elke {0} weken}
InvestmentPlanMenuCreate = Voeg nieuw investeringsplan toe...
InvestmentPlanMenuDelete = Verwijder investeringsplan
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = Brak wygenerowanych transakcji.\nNas

InvestmentPlanIntervalLabel = {0,choice,1#miesi\u0119czny|1<co {0} miesi\u0119cy}

InvestmentPlanIntervalWeeklyLabel = {0,choice,1#tygodnik|1<co {0} tygodnie\r\n}

InvestmentPlanMenuCreate = Nowy plan...

InvestmentPlanMenuDelete = Usu\u0144 plan inwestycyjny
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = Nenhuma transa\u00E7\u00E3o gerada.\

InvestmentPlanIntervalLabel = {0,choice,1#mensal|1<a cada {0} meses}

InvestmentPlanIntervalWeeklyLabel = {0,choice,1#semanalmente|1<de {0} em {0} semanas}

InvestmentPlanMenuCreate = Novo Plano...

InvestmentPlanMenuDelete = Excluir Plano de Investimento
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = Nenhuma transa\u00E7\u00E3o gerada.\

InvestmentPlanIntervalLabel = {0,choice,1#mensal|1<a cada {0} meses}

InvestmentPlanIntervalWeeklyLabel = {0,choice,1#semanalmente|1<a cada {0} semanas}

InvestmentPlanMenuCreate = Novo Plano...

InvestmentPlanMenuDelete = Excluir Plano de Investimento
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = \u041D\u0435\u0442 \u0442\u0440\u043

InvestmentPlanIntervalLabel = {0,choice,1#\u0435\u0436\u0435\u043C\u0435\u0441\u044F\u0447\u043D\u043E|1<\u043A\u0430\u0436\u0434\u044B\u0435 {0} \u043C\u0435\u0441\u044F\u0446\u0430}|4<\u043A\u0430\u0436\u0434\u044B\u0435 {0} \u043C\u0435\u0441\u044F\u0446\u0435\u0432

InvestmentPlanIntervalWeeklyLabel = {0,choice,1#\u0435\u0436\u0435\u043D\u0435\u0434\u0435\u043B\u044C\u043D\u043E|1<\u043A\u0430\u0436\u0434\u044B\u0435 {0} \u043D\u0435\u0434\u0435\u043B\u0438}

InvestmentPlanMenuCreate = \u041D\u043E\u0432\u044B\u0439 \u041F\u043B\u0430\u043D...

InvestmentPlanMenuDelete = \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u043D\u0432\u0435\u0441\u0442\u0438\u0446\u0438\u043E\u043D\u043D\u044B\u0439 \u043F\u043B\u0430\u043D
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = Nevygenerovali sa \u017Eiadne transa
InvestmentPlanIntervalLabel = {0,choice,1#mesa\u010Dne|1<ka\u017Ed\u00FD {0}mesiac}
InvestmentPlanIntervalWeeklyLabel = {0,choice,1#t\u00FD\u017Edenne|1<ka\u017Ed\u00FDch {0} t\u00FD\u017Edne}
InvestmentPlanMenuCreate = Nov\u00FD pl\u00E1n...
InvestmentPlanMenuDelete = Vymaza\u0165 investi\u010Dn\u00FD pl\u00E1n
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = \u672A\u751F\u6210\u8D26\u76EE\u3002

InvestmentPlanIntervalLabel = {0,choice,1#\u6BCF\u6708|1<\u6BCF {0} \u6708}

InvestmentPlanIntervalWeeklyLabel = {0,choice,1#\u6BCF\u5468|1<\u6BCF {0} \u5468}

InvestmentPlanMenuCreate = \u521B\u5EFA\u6295\u8D44\u8BA1\u5212...

InvestmentPlanMenuDelete = \u5220\u9664\u6295\u8D44\u8BA1\u5212
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ InvestmentPlanInfoNoTransactionsGenerated = \u672A\u751F\u6210\u4EA4\u6613\u3002
InvestmentPlanIntervalLabel = {0,choice,1#\u6BCF\u6708|1\u6BCF {0} \u500B\u6708}
InvestmentPlanIntervalWeeklyLabel = {0,choice,1#\u6BCF\u9031|1\u6BCF {0} \u9031\u4E00\u6B21}
InvestmentPlanMenuCreate = \u65B0\u8A08\u5283...
InvestmentPlanMenuDelete = \u522A\u9664\u6295\u8CC7\u8A08\u5283
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ public class ListEditingSupport extends PropertyEditingSupport
{
private ComboBoxCellEditor editor;
private List<Object> comboBoxItems;
private List<String> comboItemsNames;

public ListEditingSupport(Class<?> subjectType, String attributeName, List<?> options)
public ListEditingSupport(Class<?> subjectType, String attributeName, List<?> options, List<String> comboItemsNames)
{
super(subjectType, attributeName);

Expand All @@ -27,6 +28,12 @@ public ListEditingSupport(Class<?> subjectType, String attributeName, List<?> op
throw new IllegalArgumentException("option must not be null"); //$NON-NLS-1$

this.comboBoxItems = new ArrayList<>(options);
this.comboItemsNames = comboItemsNames;
}

public ListEditingSupport(Class<?> subjectType, String attributeName, List<?> options)
{
this(subjectType, attributeName, options, null);
}

public boolean canBeNull(Object element) // NOSONAR
Expand Down Expand Up @@ -60,8 +67,21 @@ public final void prepareEditor(Object element)
String[] names = new String[comboBoxItems.size()];
int index = 0;

for (Object item : comboBoxItems)
names[index++] = item == null ? "" : item.toString(); //$NON-NLS-1$
if (comboItemsNames == null)
{
for (Object item : comboBoxItems)
names[index++] = item == null ? "" : item.toString(); //$NON-NLS-1$
}
else if (comboItemsNames.size() == comboBoxItems.size())
{
for (Object item : comboBoxItems)
{
names[index] = item == null ? "" : comboItemsNames.get(index); //$NON-NLS-1$
index++;
}
}
else
throw new IllegalArgumentException("arrays size do not match"); //$NON-NLS-1$

editor.setItems(names);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import name.abuchen.portfolio.ui.Messages;
import name.abuchen.portfolio.ui.PortfolioPlugin;
import name.abuchen.portfolio.ui.dialogs.transactions.InvestmentPlanDialog;
import name.abuchen.portfolio.ui.dialogs.transactions.InvestmentPlanModel;
import name.abuchen.portfolio.ui.dialogs.transactions.OpenDialogAction;
import name.abuchen.portfolio.ui.editor.AbstractFinanceView;
import name.abuchen.portfolio.ui.editor.PortfolioPart;
Expand Down Expand Up @@ -271,14 +272,20 @@ public Image getImage(Object e)
@Override
public String getText(Object e)
{
return MessageFormat.format(Messages.InvestmentPlanIntervalLabel, ((InvestmentPlan) e).getInterval());
int interval = ((InvestmentPlan) e).getInterval();
return InvestmentPlanModel.Intervals.get(interval).toString();
}
});
ColumnViewerSorter.create(InvestmentPlan.class, "interval").attachTo(column); //$NON-NLS-1$
List<Integer> available = new ArrayList<>();
for (int ii = 1; ii <= 12; ii++)
available.add(ii);
new ListEditingSupport(InvestmentPlan.class, "interval", available).addListener(this).attachTo(column); //$NON-NLS-1$
List<String> theIntervalNames = new ArrayList<>();
for (var entry : InvestmentPlanModel.Intervals.values())
{
available.add(entry.getInterval());
theIntervalNames.add(entry.toString());
}
new ListEditingSupport(InvestmentPlan.class, "interval", available, theIntervalNames).addListener(this) //$NON-NLS-1$
.attachTo(column);
support.addColumn(column);

column = new Column(Messages.ColumnAmount, SWT.RIGHT, 80);
Expand Down
Loading