package de.open4me.depot.abruf.impl; import java.io.IOException; import java.rmi.RemoteException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Scanner; import com.gargoylesoftware.htmlunit.TextPage; import de.open4me.depot.DepotViewerPlugin; import de.open4me.depot.abruf.utils.Utils; import de.open4me.ly.webscraper.runner.Runner; import de.willuhn.jameica.hbci.rmi.Konto; import de.willuhn.jameica.system.Application; import de.willuhn.logging.Logger; import de.willuhn.util.ApplicationException; import de.willuhn.util.I18N; public class Fondsdepotbank extends BasisDepotAbruf { final static String logout = "https://finanzportal.fondsdepotbank.de/fdb/abaxx-?$part=Home.short-login-info&$event=logout"; final static String[] basescript = new String[] { "#Login", "open \"https://finanzportal.fondsdepotbank.de/\"", "set getbyid(\"Form2073790314_1_j_username\") to value \"${user}\"", "set getbyid(\"Form2073790314_1_j_password\") to value \"${pwd}\"", "click getbyxpath(\"//button[contains(@class,'evt-login')]\")", "assertExists \"Login nicht möglich. Zugangsdaten falsch?\" getbyxpath(\"//p[contains(.,'Zeit bis zur Abmeldung: ')]\")" + "", "#Main Page", "open \"https://finanzportal.fondsdepotbank.de/fdb/abaxx-?$part=Home.content.Welcome\"", "", "#Umsätze", "click getbytext(\"Depotumsätze\")", "click getbyxpath(\"//button[normalize-space(.)='Aktionen']\")", "download getbytext(\"CSV-Export\")", "assertExists \"CSV Export für Umsätze nicht gefunden\" getbytext(\"CSV-Export\")", "", "#Back to Main Page", "open \"https://finanzportal.fondsdepotbank.de/fdb/abaxx-?$part=Home.content.Welcome\"", "", "#Bestand", "click getbytext(\"Depotbestand\")", "click getbyxpath(\"//button[normalize-space(.)='Aktionen']\")", "download getbytext(\"CSV-Export\")", "assertExists \"CSV Export für Umsätze nicht gefunden\" getbytext(\"CSV-Export\")", "", "#Logout", "click getbytext(\"Abmelden\")"}; private final static I18N i18n = Application.getPluginLoader().getPlugin(DepotViewerPlugin.class).getResources().getI18N(); final static String PROP_PASSWORD = "Passwort"; public void run(Konto konto) throws ApplicationException { try { String username = konto.getKundennummer(); String password = konto.getMeta(PROP_PASSWORD, null); if (username == null || username.length() == 0) { throw new ApplicationException(i18n.tr("Bitte geben Sie Ihren Karten-Nummer in den Synchronisationsoptionen ein")); } try { if (password == null || password.length() == 0) { password = Application.getCallback().askPassword(getName()); } } catch (Exception e1) { e1.printStackTrace(); throw new ApplicationException("Password-Eingabe:" + e1.getMessage()); } HashMap<String, String> info = getKontoInformationen(konto); Runner r = new Runner() { }; info.put("user", username); info.put("pwd", password); r.setInfo(info); r.setCode(basescript); r.run(); umsaetze(konto, (TextPage) r.getDownloads().get(0)); bestaende(konto, (TextPage) r.getDownloads().get(1)); } catch (Exception e) { e.printStackTrace(); throw new ApplicationException("Fehler beim Abruf der Daten\n" + e.getMessage(), e); } } private void bestaende(Konto konto, TextPage page) throws IOException, RemoteException, ApplicationException, ParseException { DateFormat df; df = new SimpleDateFormat("dd.MM.yyyy"); ArrayList<HashMap<String, String>> buchungen = parseCSV(page.getContent(), "Wertpapier"); Utils.clearBestand(konto); double depotwert = 0.0; for (HashMap<String, String> buchung : buchungen) { String[] kurs = buchung.get("akt. preis").split(" "); String[] wert = buchung.get("akt. wert").split(" "); Utils.addBestand( Utils.getORcreateWKN(buchung.get("wkn"), buchung.get("isin"), buchung.get("produkt")), konto, Utils.getDoubleFromZahl(buchung.get("stück").replace(" Stück", "")), Utils.getDoubleFromZahl(kurs[0]), kurs[1], Utils.getDoubleFromZahl(wert[0]), wert[1], new Date(), df.parse(buchung.get("datum"))); depotwert += Utils.getDoubleFromZahl(wert[0]); } konto.setSaldo(depotwert); konto.store(); } @SuppressWarnings("unchecked") private void umsaetze(Konto konto, TextPage page) throws ApplicationException, IOException, RemoteException { DateFormat df = new SimpleDateFormat("dd.MM.yyyy"); ArrayList<HashMap<String, String>> buchungen = parseCSV(page.getContent(), "Buchung"); for (HashMap<String, String> buchung : buchungen) { String[] wertpapier = buchung.get("wertpapier").split(" / "); String id = Utils.getORcreateWKN(wertpapier[1], wertpapier[0], wertpapier[2]); Date d; if (buchung.get("buchungsdatum") == null) { continue; // erstmal nicht behandeln } try { d = df.parse(buchung.get("buchungsdatum")); } catch (ParseException e) { Logger.error("Aktuelle Zeile: " + buchungen.toString()); throw new ApplicationException("Unbekanntes Datumsformat: [" + buchung.get("buchungsdatum") + "] " + buchungen.toString()); } catch (NullPointerException e) { Logger.error("Aktuelle Zeile: " + buchungen.toString()); throw new ApplicationException("Unbekanntes Datumsformat: [" + buchung.get("buchungsdatum") + "] " + buchungen.toString()); } if (buchung.get("geschäftsart").equals("Erträgnis")) { continue; // throw new ApplicationException("Unbekannte Geschäftsart (" + buchung.get("Geschäftsart") + "). Bitte den Entwickler kontaktieren!" ); } String[] kurs = buchung.get("kurs").split(" "); String[] umsatz = buchung.get("umsatz").split(" "); String orderid = wertpapier[0] + buchung.get("buchungsdatum") + buchung.get("geschäftsart") + buchung.get("umsatz") + buchung.get("kurz") + buchung.get("stück"); Utils.addUmsatz(konto.getID(), id, buchung.get("geschäftsart"), buchung.toString(), Math.abs(Utils.getDoubleFromZahl(buchung.get("stück").replace(" Stück", ""))), // Anzahl Utils.getDoubleFromZahl(kurs[0]), // Kurs kurs[1], -1 * Utils.getDoubleFromZahl(umsatz[0]), // Kosten umsatz[1], d, String.valueOf(orderid.hashCode()), "",0.0d, "EUR", 0.0d, "EUR" ); } } private ArrayList<HashMap<String, String>> parseCSV(String csv, String search) { ArrayList<HashMap<String, String>> liste = new ArrayList<HashMap<String, String>>(); Scanner scanner = new Scanner(csv); String[] header = null; while (scanner.hasNextLine()) { String line = scanner.nextLine(); if (header == null) { if (!line.startsWith(search)) { continue; } header = line.replace(";;", ";_;").split(";"); String pre = ""; int nr = 1; for (int i = 0; i < header.length; i++) { // System.out.print(header[i]); header[i] = header[i].toLowerCase(); String orig = header[i]; if (header[i].trim().equals("_") || header[i].trim().isEmpty()) { header[i] = pre + nr; } else { nr = 1; } pre = orig; // System.out.println(" => " + header[i]); } continue; } HashMap<String, String> infos = new HashMap<String, String>(); String[] data = line.split(";"); for (int i = 0; i < data.length; i++) { infos.put(header[i], data[i]); } liste.add(infos); } scanner.close(); return liste; } @Override public String getName() { return "Fondsdepot Bank"; } @Override public List<String> getPROP(Konto konto) { List<String> result = super.getPROP(konto); result.add(0, PROP_PASSWORD); return result; } @Override public boolean isSupported(Konto konto) throws ApplicationException, RemoteException { if (!Utils.hasRightKontoType(konto)) { return false; } String unterkontoExtract = ""; if (konto.getUnterkonto() != null && konto.getUnterkonto().toLowerCase().startsWith("depot")) { unterkontoExtract = konto.getUnterkonto().toLowerCase().substring(5).replace(" ", ""); } return konto.getBLZ().equals("77322200") || konto.getBic().toUpperCase().equals("FODBDE77XXX") || getName().toLowerCase().replace(" ", "").equals(unterkontoExtract); } public static HashMap<String, String> getKontoInformationen(Konto konto) throws RemoteException { HashMap<String, String> kontoInfo = new HashMap<String, String>(); kontoInfo.put("blz", konto.getBLZ()); kontoInfo.put("bic", konto.getBic()); kontoInfo.put("iban", konto.getIban()); kontoInfo.put("userid", konto.getKundennummer()); kontoInfo.put("subid", konto.getUnterkonto()); kontoInfo.put("nummer", konto.getKontonummer()); return kontoInfo; } }