Skip to content

Commit

Permalink
Allow transaction type to be defined by regex pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
buchen committed Mar 15, 2020
1 parent f32780c commit 10cba96
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,20 +105,21 @@ public void testTransactionTaxesAndFeesAddUpForOutboundDeliveries()
t.addUnit(tax);
assertThat(action.process(t, portfolio).getCode(), is(Status.Code.OK));

t.setType(Type.DELIVERY_INBOUND);
t.setMonetaryAmount(Money.of("EUR", 7_00));
assertThat(action.process(t, portfolio).getCode(), is(Status.Code.ERROR));

t.setType(Type.DELIVERY_INBOUND);
t.setType(Type.DELIVERY_OUTBOUND);
assertThat(action.process(t, portfolio).getCode(), is(Status.Code.OK));

t.setType(Type.DELIVERY_OUTBOUND);
t.setType(Type.DELIVERY_INBOUND);
t.removeUnit(tax);
assertThat(action.process(t, portfolio).getCode(), is(Status.Code.OK));

t.setMonetaryAmount(Money.of("EUR", 3_00));
assertThat(action.process(t, portfolio).getCode(), is(Status.Code.ERROR));

t.setType(Type.DELIVERY_INBOUND);
t.setType(Type.DELIVERY_OUTBOUND);
assertThat(action.process(t, portfolio).getCode(), is(Status.Code.OK));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ public Status process(PortfolioTransaction transaction, Portfolio portfolio)
if (status.getCode() != Status.Code.OK)
return status;

if (transaction.getType() == PortfolioTransaction.Type.DELIVERY_OUTBOUND
|| transaction.getType() == PortfolioTransaction.Type.SELL)
if (transaction.getType() == PortfolioTransaction.Type.DELIVERY_INBOUND
|| transaction.getType() == PortfolioTransaction.Type.BUY)
{
// tax + fees must be < than transaction amount
Money taxAndFees = transaction.getUnits() //
.filter(u -> u.getType() == Unit.Type.TAX || u.getType() == Unit.Type.FEE) //
.map(u -> u.getAmount()) //
.map(Unit::getAmount) //
.collect(MoneyCollectors.sum(transaction.getCurrencyCode()));

if (!transaction.getMonetaryAmount().isGreaterOrEqualThan(taxAndFees))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
fields.add(new AmountField("shares", Messages.CSVColumn_Shares).setOptional(true)); //$NON-NLS-1$
fields.add(new Field("note", Messages.CSVColumn_Note).setOptional(true)); //$NON-NLS-1$
fields.add(new AmountField("taxes", Messages.CSVColumn_Taxes).setOptional(true)); //$NON-NLS-1$
fields.add(new AmountField("fees", Messages.CSVColumn_Fees).setOptional(true)); //$NON-NLS-1$
fields.add(new Field("account", Messages.CSVColumn_AccountName).setOptional(true)); //$NON-NLS-1$
fields.add(new Field("account2nd", Messages.CSVColumn_AccountName2nd).setOptional(true)); //$NON-NLS-1$
fields.add(new Field("portfolio", Messages.CSVColumn_PortfolioName).setOptional(true)); //$NON-NLS-1$
Expand Down Expand Up @@ -78,6 +79,7 @@ void extract(List<Item> items, String[] rawValues, Map<String, Column> field2col
String note = getText(Messages.CSVColumn_Note, rawValues, field2column);
Long shares = getShares(Messages.CSVColumn_Shares, rawValues, field2column);
Long taxes = getAmount(Messages.CSVColumn_Taxes, rawValues, field2column);
Long fees = getAmount(Messages.CSVColumn_Fees, rawValues, field2column);

Account account = getAccount(getClient(), rawValues, field2column);
Account account2nd = getAccount(getClient(), rawValues, field2column, true);
Expand Down Expand Up @@ -116,7 +118,27 @@ void extract(List<Item> items, String[] rawValues, Map<String, Column> field2col
buySellEntry.setSecurity(security);
buySellEntry.setDate(date);
buySellEntry.setNote(note);
item = new BuySellEntryItem(buySellEntry);

if (taxes != null && taxes.longValue() != 0)
buySellEntry.getPortfolioTransaction().addUnit(new Unit(Unit.Type.TAX, Money
.of(buySellEntry.getPortfolioTransaction().getCurrencyCode(), Math.abs(taxes))));

if (fees != null && fees.longValue() != 0)
buySellEntry.getPortfolioTransaction().addUnit(new Unit(Unit.Type.FEE, Money
.of(buySellEntry.getPortfolioTransaction().getCurrencyCode(), Math.abs(fees))));

if (buySellEntry.getPortfolioTransaction().getAmount() == 0L
&& buySellEntry.getPortfolioTransaction().getType() == PortfolioTransaction.Type.SELL)
{
// convert to outbound delivery if amount is 0
PortfolioTransaction tx = buySellEntry.getPortfolioTransaction();
item = new TransactionItem(convertToOutboundDelivery(tx));
}
else
{
item = new BuySellEntryItem(buySellEntry);
}

break;
case DIVIDENDS: // NOSONAR
// dividends must have a security
Expand All @@ -138,7 +160,8 @@ void extract(List<Item> items, String[] rawValues, Map<String, Column> field2col
t.setType(type);
t.setAmount(Math.abs(amount.getAmount()));
t.setCurrencyCode(amount.getCurrencyCode());
if (type == Type.DIVIDENDS || type == Type.TAXES || type == Type.TAX_REFUND || type == Type.FEES || type == Type.FEES_REFUND)
if (type == Type.DIVIDENDS || type == Type.TAXES || type == Type.TAX_REFUND || type == Type.FEES
|| type == Type.FEES_REFUND)
t.setSecurity(security);
t.setDateTime(date.withHour(0).withMinute(0));
t.setNote(note);
Expand All @@ -159,6 +182,20 @@ void extract(List<Item> items, String[] rawValues, Map<String, Column> field2col
items.add(item);
}

private PortfolioTransaction convertToOutboundDelivery(PortfolioTransaction tx)
{
PortfolioTransaction delivery = new PortfolioTransaction();
delivery.setType(PortfolioTransaction.Type.DELIVERY_OUTBOUND);
delivery.setDateTime(tx.getDateTime());
delivery.setAmount(tx.getAmount());
delivery.setCurrencyCode(tx.getCurrencyCode());
delivery.setShares(tx.getShares());
delivery.setSecurity(tx.getSecurity());
delivery.setNote(tx.getNote());
delivery.addUnits(tx.getUnits());
return delivery;
}

private Type inferType(String[] rawValues, Map<String, Column> field2column, Security security, Money amount)
throws ParseException
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;

import org.apache.commons.csv.CSVFormat;
Expand Down Expand Up @@ -492,15 +493,23 @@ public M parseObject(String source, ParsePosition pos)
}
}

// second: try partial matches
// second: try as pattern

for (Map.Entry<M, String> entry : enumMap.entrySet())
{
int p = source.indexOf(entry.getValue());
if (p >= 0)
try
{
pos.setIndex(source.length());
return entry.getKey();
Pattern p = Pattern.compile(entry.getValue());

if (p.matcher(source).find())
{
pos.setIndex(source.length());
return entry.getKey();
}
}
catch (PatternSyntaxException e)
{
PortfolioLog.error(e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,4 +298,134 @@
"label": "Wirtschaftsraum (Detail)"
}
]
},
{
"delimiter": ";",
"encoding": "UTF-8",
"isFirstLineHeader": true,
"label": "ebase Kontoauszug",
"skipLines": 0,
"target": "account-transaction",
"columns": [
{
"label": "Depotnummer"
},
{
"label": "Depotposition"
},
{
"field": "date",
"format": "yyyy-MM-dd",
"label": "Datum"
},
{
"label": "Ref. Nr."
},
{
"field": "date",
"format": "yyyy-MM-dd",
"label": "Buchungsdatum"
},
{
"field": "type",
"format": "DEPOSIT=Einlage;REMOVAL=Entnahme;INTEREST=Zinsen;INTEREST_CHARGE=Zinsbelastung;DIVIDENDS=^Fondsertrag$;FEES=Gebühren;FEES_REFUND=Gebührenerstattung;TAXES=Steuern;TAX_REFUND=Steuerrückerstattung;BUY=Kauf|Ansparplan|Wiederanlage;SELL=Verkauf;TRANSFER_IN=Umbuchung (Eingang);TRANSFER_OUT=Umbuchung (Ausgang)",
"label": "Umsatzart"
},
{
"label": "Teilumsatz"
},
{
"field": "name",
"label": "Fonds"
},
{
"field": "isin",
"label": "ISIN"
},
{
"field": "value",
"format": "0.000,00",
"label": "Zahlungsbetrag in ZW"
},
{
"field": "currency",
"label": "Zahlungswährung (ZW)"
},
{
"field": "shares",
"format": "0.000,00",
"label": "Anteile"
},
{
"label": "Abrechnungskurs in FW"
},
{
"label": "Fondswährung (FW)"
},
{
"label": "Kursdatum"
},
{
"label": "Devisenkurs (ZW/FW)"
},
{
"label": "Anlagebetrag in ZW"
},
{
"label": "Vertriebsprovision in ZW (im Abrechnungskurs enthalten)"
},
{
"label": "KVG Einbehalt in ZW (im Abrechnungskurs enthalten)"
},
{
"label": "Gegenwert der Anteile in ZW"
},
{
"label": "Anteile zum Bestandsdatum"
},
{
"label": "Barausschüttung/Steuerliquidität je Anteil in EW"
},
{
"label": "Ertragswährung (EW)"
},
{
"label": "Bestandsdatum"
},
{
"label": "Devisenkurs (ZW/EW)"
},
{
"label": "Barausschüttung/Steuerliquidität in ZW"
},
{
"label": "Entgelt in ZW"
},
{
"field": "fees",
"format": "0.000,00",
"label": "Entgelt in EUR"
},
{
"label": "Steuern in ZW"
},
{
"field": "taxes",
"format": "0.000,00",
"label": "Steuern in EUR"
},
{
"label": "Devisenkurs (EUR/ZW)"
},
{
"label": "Art des Steuereinbehalts"
},
{
"label": "Steuereinbehalt in EUR"
},
{
"field": "note",
"label": "Orderinfo"
}
]
}]

0 comments on commit 10cba96

Please sign in to comment.