@Test
  public void testErtragsgutschriftWhenSecurityExists() throws IOException {
    Client client = new Client();
    Security security = new Security("BASF", "DE000BASF111", null, null);
    client.addSecurity(security);

    DeutscheBankPDFExctractor extractor =
        new DeutscheBankPDFExctractor(client) {
          @Override
          String strip(File file) throws IOException {
            return from("DeutscheBankErtragsgutschrift.txt");
          }
        };
    List<Exception> errors = new ArrayList<Exception>();

    List<Item> results = extractor.extract(Arrays.asList(new File("t")), errors);

    assertThat(errors, empty());
    assertThat(results.size(), is(1));
    new AssertImportActions().check(results, CurrencyUnit.EUR);

    // check transaction
    AccountTransaction transaction = (AccountTransaction) results.get(0).getSubject();
    assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS));
    assertThat(transaction.getSecurity(), is(security));
  }
Beispiel #2
0
 private static void collectAccountTransactions(
     Client client, Date start, Date end, List<Transaction> transactions) {
   for (Account account : client.getAccounts()) {
     for (AccountTransaction t : account.getTransactions()) {
       if (t.getDate().getTime() > start.getTime() && t.getDate().getTime() <= end.getTime()) {
         switch (t.getType()) {
           case DEPOSIT:
           case REMOVAL:
           case TRANSFER_IN:
           case TRANSFER_OUT:
             transactions.add(t);
             break;
           case BUY:
           case SELL:
           case FEES:
           case TAXES:
           case DIVIDENDS:
           case INTEREST:
           case TAX_REFUND:
             break;
           default:
             throw new UnsupportedOperationException();
         }
       }
     }
   }
 }
Beispiel #3
0
 @Override
 public Status process(AccountTransaction transaction, Account account) {
   // ensure consistency (in case the user deleted the creation of the
   // security via the dialog)
   if (transaction.getSecurity() != null) process(transaction.getSecurity());
   account.addTransaction(transaction);
   return Status.OK_STATUS;
 }
  private void addBackOfProfitsTransaction() {
    DocumentType type = new DocumentType("Ertragsthesaurierung");
    this.addDocumentTyp(type);

    Block block = new Block("Ertragsthesaurierung(.*)");
    type.addBlock(block);

    Transaction<AccountTransaction> pdfTransaction = new Transaction<AccountTransaction>();
    pdfTransaction.subject(
        () -> {
          AccountTransaction transaction = new AccountTransaction();
          transaction.setType(AccountTransaction.Type.DIVIDENDS);
          return transaction;
        });

    block.set(pdfTransaction);
    pdfTransaction
        .section("name", "isin") //
        .find("Gattungsbezeichnung(.*) ISIN")
        // Commerzbank AG Inhaber-Aktien o.N. DE000CBK1001
        // 5,5% TUI AG Wandelanl.v.2009(2014) 17.11.2014
        // 17.11.2010 DE000TUAG117
        .match("(?<name>.*?) (\\d+.\\d+.\\d{4} ){0,2}(?<isin>[^ ]\\S*)$") //
        .assign(
            (t, v) -> {
              t.setSecurity(getOrCreateSecurity(v));
            })
        .section("notation", "shares", "date")
        .find("Nominal (Ex-Tag )?Zahltag (.*etrag pro .*)?(Zinssatz.*)?")
        // STK 28,000 02.03.2015 04.03.2015 EUR 0,088340
        .match(
            "(?<notation>^\\w{3}+) (?<shares>\\d{1,3}(\\.\\d{3})*(,\\d{3})?) (\\d+.\\d+.\\d{4}+) (?<date>\\d+.\\d+.\\d{4}+)(.*)")
        .assign(
            (t, v) -> {
              String notation = v.get("notation");
              if (notation != null && !notation.equalsIgnoreCase("STK")) {
                // Prozent-Notierung, Workaround..
                t.setShares((asShares(v.get("shares")) / 100));
              } else {
                t.setShares(asShares(v.get("shares")));
              }
              t.setDate(asDate(v.get("date")));
            })
        .section("amount", "currency")
        .match(
            "Steuerpflichtiger Betrag (.*) (?<currency>\\w{3}+) (?<amount>\\d{1,3}(\\.\\d{3})*(,\\d{2})?)")
        .assign(
            (t, v) -> {
              t.setAmount(asAmount(v.get("amount")));
              t.setCurrencyCode(asCurrencyCode(v.get("currency")));
            })
        .wrap(t -> new TransactionItem(t));
    addTaxesSectionsAccount(pdfTransaction);
  }
  @Test
  public void testErtragsgutschrift() throws IOException {
    DeutscheBankPDFExctractor extractor =
        new DeutscheBankPDFExctractor(new Client()) {
          @Override
          String strip(File file) throws IOException {
            return from("DeutscheBankErtragsgutschrift.txt");
          }
        };
    List<Exception> errors = new ArrayList<Exception>();

    List<Item> results = extractor.extract(Arrays.asList(new File("t")), errors);

    assertThat(errors, empty());
    assertThat(results.size(), is(2));
    new AssertImportActions().check(results, CurrencyUnit.EUR);

    // check security
    Security security = assertSecurity(results);

    // check transaction
    Optional<Item> item = results.stream().filter(i -> i instanceof TransactionItem).findFirst();
    assertThat(item.isPresent(), is(true));
    assertThat(item.get().getSubject(), instanceOf(AccountTransaction.class));
    AccountTransaction transaction = (AccountTransaction) item.get().getSubject();
    assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS));
    assertThat(transaction.getSecurity(), is(security));
    assertThat(transaction.getDate(), is(LocalDate.parse("2014-12-15")));
    assertThat(transaction.getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, 1495L)));
    assertThat(transaction.getShares(), is(Values.Share.factorize(123)));
  }
Beispiel #6
0
  private static void collectDatesAndValues(
      Date start,
      Date end,
      ClientSnapshot snapshotStart,
      ClientSnapshot snapshotEnd,
      List<Transaction> transactions,
      List<Date> dates,
      List<Double> values) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(start);
    dates.add(cal.getTime());
    values.add(-(snapshotStart.getAssets()) / Values.Amount.divider());

    for (Transaction t : transactions) {
      cal.setTime(t.getDate());
      dates.add(cal.getTime());

      if (t instanceof AccountTransaction) {
        AccountTransaction at = (AccountTransaction) t;
        long amount = at.getAmount();
        if (at.getType() == Type.DEPOSIT || at.getType() == Type.TRANSFER_IN) amount = -amount;
        values.add(amount / Values.Amount.divider());
      } else if (t instanceof PortfolioTransaction) {
        PortfolioTransaction pt = (PortfolioTransaction) t;

        long amount = pt.getAmount();
        if (pt.getType() == PortfolioTransaction.Type.DELIVERY_INBOUND
            || pt.getType() == PortfolioTransaction.Type.TRANSFER_IN) amount = -amount;
        values.add(amount / Values.Amount.divider());
      } else {
        throw new UnsupportedOperationException();
      }
    }

    cal.setTime(end);
    dates.add(cal.getTime());
    values.add(snapshotEnd.getAssets() / Values.Amount.divider());
  }
 private void adaptAccountTransactions(
     Account account, ReadOnlyAccount pseudoAccount, Set<Security> usedSecurities) {
   for (AccountTransaction t : account.getTransactions()) {
     switch (t.getType()) {
       case BUY:
         if (portfolios.contains(t.getCrossEntry().getCrossOwner(t)))
           pseudoAccount.internalAddTransaction(t);
         else pseudoAccount.internalAddTransaction(convertTo(t, AccountTransaction.Type.REMOVAL));
         break;
       case SELL:
         if (portfolios.contains(t.getCrossEntry().getCrossOwner(t)))
           pseudoAccount.internalAddTransaction(t);
         else pseudoAccount.internalAddTransaction(convertTo(t, AccountTransaction.Type.DEPOSIT));
         break;
       case TRANSFER_IN:
         if (accounts.contains(t.getCrossEntry().getCrossOwner(t)))
           pseudoAccount.internalAddTransaction(t);
         else pseudoAccount.internalAddTransaction(convertTo(t, AccountTransaction.Type.DEPOSIT));
         break;
       case TRANSFER_OUT:
         if (accounts.contains(t.getCrossEntry().getCrossOwner(t)))
           pseudoAccount.internalAddTransaction(t);
         else pseudoAccount.internalAddTransaction(convertTo(t, AccountTransaction.Type.REMOVAL));
         break;
       case DIVIDENDS:
       case TAX_REFUND:
         if (t.getSecurity() == null || usedSecurities.contains(t.getSecurity()))
           pseudoAccount.internalAddTransaction(t);
         else pseudoAccount.internalAddTransaction(convertTo(t, AccountTransaction.Type.DEPOSIT));
         break;
       case DEPOSIT:
       case REMOVAL:
       case INTEREST:
       case INTEREST_CHARGE:
       case TAXES:
       case FEES:
         pseudoAccount.internalAddTransaction(t);
         break;
       default:
         throw new UnsupportedOperationException();
     }
   }
 }
  @Test
  public void testErtragsgutschrift2() throws IOException {
    DeutscheBankPDFExctractor extractor =
        new DeutscheBankPDFExctractor(new Client()) {
          @Override
          String strip(File file) throws IOException {
            return from(file.getName());
          }
        };
    List<Exception> errors = new ArrayList<Exception>();

    List<Item> results =
        extractor.extract(Arrays.asList(new File("DeutscheBankErtragsgutschrift2.txt")), errors);

    assertThat(errors, empty());
    assertThat(results.size(), is(2));
    new AssertImportActions().check(results, CurrencyUnit.EUR);

    // check security
    Security security =
        results.stream().filter(i -> i instanceof SecurityItem).findFirst().get().getSecurity();
    assertThat(security.getName(), is("ISHS-MSCI N. AMERIC.UCITS ETF BE.SH.(DT.ZT.)"));
    assertThat(security.getIsin(), is("DE000A0J2060"));
    assertThat(security.getWkn(), is("A0J206"));
    assertThat(security.getCurrencyCode(), is("USD"));

    // check transaction
    Optional<Item> item = results.stream().filter(i -> i instanceof TransactionItem).findFirst();
    assertThat(item.isPresent(), is(true));
    assertThat(item.get().getSubject(), instanceOf(AccountTransaction.class));

    AccountTransaction transaction = (AccountTransaction) item.get().getSubject();
    assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS));
    assertThat(transaction.getSecurity(), is(security));
    assertThat(transaction.getDate(), is(LocalDate.parse("2015-03-24")));
    assertThat(transaction.getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, 16_17L)));
    assertThat(transaction.getShares(), is(Values.Share.factorize(123)));

    Optional<Unit> grossValue = transaction.getUnit(Unit.Type.GROSS_VALUE);
    assertThat(grossValue.isPresent(), is(true));
    assertThat(grossValue.get().getAmount(), is(Money.of("EUR", 16_17L)));
    assertThat(grossValue.get().getForex(), is(Money.of("USD", 17_38L)));
    assertThat(
        grossValue.get().getExchangeRate().doubleValue(), IsCloseTo.closeTo(0.930578, 0.000001));
  }
  private void collectDividends(
      Portfolio portfolio, ReadOnlyAccount pseudoAccount, Set<Security> usedSecurities) {
    if (portfolio.getReferenceAccount() == null) return;

    for (AccountTransaction t : portfolio.getReferenceAccount().getTransactions()) // NOSONAR
    {
      if (t.getSecurity() == null) continue;

      if (!usedSecurities.contains(t.getSecurity())) continue;

      switch (t.getType()) {
        case TAX_REFUND:
          // security must be non-null -> tax refund is relevant for
          // performance of security
        case DIVIDENDS:
          pseudoAccount.internalAddTransaction(t);
          pseudoAccount.internalAddTransaction(
              new AccountTransaction(
                  t.getDate(),
                  t.getCurrencyCode(),
                  t.getAmount(),
                  null,
                  AccountTransaction.Type.REMOVAL));
          break;
        case BUY:
        case TRANSFER_IN:
        case SELL:
        case TRANSFER_OUT:
        case DEPOSIT:
        case REMOVAL:
        case INTEREST:
        case INTEREST_CHARGE:
        case TAXES:
        case FEES:
          // do nothing
          break;
        default:
          throw new UnsupportedOperationException();
      }
    }
  }
  @Test
  public void testErtragsgutschrift7_USD_Freibetrag_nicht_ausgeschoepft() throws IOException {
    ConsorsbankPDFExctractor extractor = new ConsorsbankPDFExctractor(new Client());
    List<Exception> errors = new ArrayList<Exception>();
    URL url =
        FileLocator.resolve(
            getClass()
                .getResource(
                    "ConsorsbankErtragsgutschrift7_USD_Freibetrag_nicht_ausgeschoepft.pdf"));
    List<Item> results = extractor.extract(Arrays.asList(new File(url.getPath())), errors);

    assertThat(errors, empty());
    assertThat(results.size(), is(2));

    // check security
    Security security =
        results.stream().filter(i -> i instanceof SecurityItem).findFirst().get().getSecurity();
    assertThat(security.getWkn(), is("200417"));
    assertThat(security.getName(), is("ALTRIA GROUP INC."));

    // check dividend transaction
    AccountTransaction t =
        (AccountTransaction)
            results
                .stream()
                .filter(i -> i instanceof TransactionItem)
                .filter(
                    i ->
                        ((AccountTransaction) i.getSubject()).getType()
                            == AccountTransaction.Type.DIVIDENDS)
                .findFirst()
                .get()
                .getSubject();
    assertThat(t.getDate(), is(LocalDate.parse("2016-01-11")));
    assertThat(t.getShares(), is(Values.Share.factorize(650)));
    assertThat(t.getMonetaryAmount(), is(Money.of("EUR", 285_60)));
    assertThat(t.getUnit(Unit.Type.GROSS_VALUE).get().getForex(), is(Money.of("USD", 367_25)));

    // check tax
    assertThat(t.getUnitSum(Type.TAX), is(Money.of("EUR", 50_40))); // QUEST
  }
  private AccountTransaction convertTo(AccountTransaction t, AccountTransaction.Type type) {
    AccountTransaction clone = new AccountTransaction();
    clone.setType(type);
    clone.setDate(t.getDate());
    clone.setCurrencyCode(t.getCurrencyCode());
    clone.setSecurity(null); // no security for REMOVAL or DEPOSIT
    clone.setAmount(t.getAmount());
    clone.setShares(t.getShares());

    // do *not* copy units as REMOVAL and DEPOSIT have never units
    return clone;
  }
  private void addDividendTransaction() {
    DocumentType type = new DocumentType("Erträgnisgutschrift");
    this.addDocumentTyp(type);

    // Erträgnisgutschrift allein ist nicht gut hier, da es schon in der
    // Kopfzeile steht..
    Block block =
        new Block(
            "Dividendengutschrift.*|Kupongutschrift.*|Erträgnisgutschrift.*(\\d+.\\d+.\\d{4})");
    type.addBlock(block);

    Transaction<AccountTransaction> pdfTransaction = new Transaction<AccountTransaction>();
    pdfTransaction.subject(
        () -> {
          AccountTransaction transaction = new AccountTransaction();
          transaction.setType(AccountTransaction.Type.DIVIDENDS);
          return transaction;
        });

    block.set(pdfTransaction);
    pdfTransaction
        .section("name", "isin") //
        .find("Gattungsbezeichnung(.*) ISIN")
        // Commerzbank AG Inhaber-Aktien o.N. DE000CBK1001
        // 5,5% TUI AG Wandelanl.v.2009(2014) 17.11.2014
        // 17.11.2010 DE000TUAG117
        .match("(?<name>.*?) (\\d+.\\d+.\\d{4} ){0,2}(?<isin>[^ ]\\S*)$") //
        .assign(
            (t, v) -> {
              t.setSecurity(getOrCreateSecurity(v));
            })
        .section("notation", "shares", "date", "amount", "currency")
        // .find("Nominal (Ex-Tag )?Zahltag (.*etrag pro
        // .*)?(Zinssatz.*)?")
        // STK 25,000 17.05.2013 17.05.2013 EUR 0,700000
        // Leistungen aus dem steuerlichen Einlagenkonto (§27
        // KStG) EUR 17,50
        .match(
            "(?<notation>^\\w{3}+) (?<shares>\\d{1,3}(\\.\\d{3})*(,\\d{3})?) (\\d+.\\d+.\\d{4}+) (?<date>\\d+.\\d+.\\d{4}+)?(.*)")
        .match(
            "(?<date>\\d+.\\d+.\\d{4}+)?(\\d{6,12})?(.{7,58} )?(?<currency>\\w{3}+) (?<amount>\\d{1,3}(\\.\\d{3})*(,\\d{2})?)")
        .assign(
            (t, v) -> {
              String notation = v.get("notation");
              if (notation != null && !notation.equalsIgnoreCase("STK")) {
                // Prozent-Notierung, Workaround..
                t.setShares((asShares(v.get("shares")) / 100));
              } else {
                t.setShares(asShares(v.get("shares")));
              }
              t.setDate(asDate(v.get("date")));
              t.setAmount(asAmount(v.get("amount")));
              t.setCurrencyCode(asCurrencyCode(v.get("currency")));
            })
        .wrap(t -> new TransactionItem(t));

    addTaxesSectionsAccount(pdfTransaction);

    // optional: Reinvestierung in:
    block = new Block("Reinvestierung.*");
    type.addBlock(block);
    block.set(
        new Transaction<BuySellEntry>()
            .subject(
                () -> {
                  BuySellEntry entry = new BuySellEntry();
                  entry.setType(PortfolioTransaction.Type.BUY);
                  return entry;
                })
            .section("date")
            .match(
                "(^\\w{3}+) (\\d{1,3}(\\.\\d{3})*(,\\d{3})?) (\\d+.\\d+.\\d{4}+) (?<date>\\d+.\\d+.\\d{4}+)?(.*)")
            .assign((t, v) -> t.setDate(asDate(v.get("date"))))
            .section("name", "isin") //
            .find("Die Dividende wurde wie folgt in neue Aktien reinvestiert:")
            .find("Gattungsbezeichnung ISIN") //
            .match("(?<name>.*) (?<isin>[^ ]\\S*)$") //
            .assign(
                (t, v) -> {
                  t.setSecurity(getOrCreateSecurity(v));
                })
            .section("notation", "shares", "amount", "currency") //
            .find("Nominal Reinvestierungspreis")
            // STK 25,000 EUR 0,700000
            .match(
                "(?<notation>^\\w{3}+) (?<shares>\\d{1,3}(\\.\\d{3})*(,\\d{3})?) (?<currency>\\w{3}+) (?<amount>\\d{1,3}(\\.\\d{3})*(,\\d{2})?)(.*)")
            .assign(
                (t, v) -> {
                  String notation = v.get("notation");
                  if (notation != null && !notation.equalsIgnoreCase("STK")) {
                    // Prozent-Notierung, Workaround..
                    t.setShares((asShares(v.get("shares")) / 100));
                  } else {
                    t.setShares(asShares(v.get("shares")));
                  }
                  t.setCurrencyCode(asCurrencyCode(v.get("currency")));
                })
            .wrap(t -> new BuySellEntryItem(t)));
  }
  private static void extractSecurityRelatedAccountTransactions(
      Account account, ReportingPeriod period, Map<Security, SecurityPerformanceRecord> records) {
    for (AccountTransaction t : account.getTransactions()) {
      if (t.getSecurity() == null) continue;

      if (!period.containsTransaction().test(t)) continue;

      if (t.getType() == AccountTransaction.Type.DIVIDENDS //
          || t.getType() == AccountTransaction.Type.INTEREST) {
        DividendTransaction dt = new DividendTransaction();
        dt.setDate(t.getDate());
        dt.setSecurity(t.getSecurity());
        dt.setAccount(account);
        dt.setCurrencyCode(t.getCurrencyCode());
        dt.setAmount(t.getAmount());
        dt.setShares(t.getShares());
        dt.setNote(t.getNote());
        records.get(t.getSecurity()).addTransaction(dt);
      } else if (t.getType() == AccountTransaction.Type.TAX_REFUND) {
        records.get(t.getSecurity()).addTransaction(t);
      }
    }
  }