diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..531a9ca --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +recursive-include pytr/locale *.mo *.po \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..7b53589 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,45 @@ +[build-system] +requires = ["setuptools>=42", "wheel", "babel"] +build-backend = "setuptools.build_meta" + +[project] +name = "pytr" +version = "0.2.2" +description = "Use TradeRepublic in terminal" +readme = "README.md" +requires-python = ">=3.8" +license = { text = "MIT" } +authors = [ + { name = "marzzzello", email = "853485-marzzzello@users.noreply.gitlab.com" } +] +urls = { "Homepage" = "https://gitlab.com/pytr-org/pytr/" } +classifiers = [ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3 :: Only", + "Operating System :: OS Independent", + "Development Status :: 3 - Alpha", + "Topic :: Office/Business :: Financial", + "Topic :: Office/Business :: Financial :: Investment", +] +dependencies = [ + "certifi", + "coloredlogs", + "ecdsa", + "packaging", + "pathvalidate", + "pygments", + "requests_futures", + "shtab", + "websockets>=10.1", + "babel", +] + +[project.scripts] +pytr = "pytr.main:main" + +[tool.setuptools] +include-package-data = true +packages = ["pytr"] + +[tool.setuptools.package-data] +pytr = ["pytr/locale/*/*/*.mo", "pytr/locale/*/*/*.po"] diff --git a/pytr/dl.py b/pytr/dl.py index aa30eee..233afe6 100644 --- a/pytr/dl.py +++ b/pytr/dl.py @@ -7,9 +7,9 @@ from pathvalidate import sanitize_filepath -from pytr.utils import preview, Timeline, get_logger +from pytr.utils import preview, get_logger from pytr.api import TradeRepublicError - +from pytr.timeline import Timeline class DL: def __init__( diff --git a/pytr/event.py b/pytr/event.py new file mode 100644 index 0000000..2b07feb --- /dev/null +++ b/pytr/event.py @@ -0,0 +1,88 @@ +from datetime import datetime + + +tr_eventType_to_pp_type = { + "CREDIT": "DIVIDENDS", + "ssp_corporate_action_invoice_cash": "DIVIDENDS", + "TRADE_INVOICE": "TRADE_INVOICE", + "SAVINGS_PLAN_EXECUTED": "TRADE_INVOICE", + "ORDER_EXECUTED": "TRADE_INVOICE", + "PAYMENT_INBOUND": "DEPOSIT", + "PAYMENT_INBOUND_SEPA_DIRECT_DEBIT": "DEPOSIT", + "PAYMENT_OUTBOUND": "REMOVAL", + "INTEREST_PAYOUT_CREATED": "INTEREST", + "card_successful_transaction": "REMOVAL", + "card_successful_atm_withdrawal": "REMOVAL", + "card_order_billed": "REMOVAL", + "card_refund": "DEPOSIT", +} + + +class Event: + def __init__(self, event_json): + self.event = event_json + self.shares = "" + self.isin = "" + + self.pp_type = tr_eventType_to_pp_type.get(self.event["eventType"], "") + self.body = self.event.get("body", "") + self.process_event() + + @property + def date(self): + dateTime = datetime.fromisoformat(self.event["timestamp"][:19]) + return dateTime.strftime("%Y-%m-%d") + + @property + def is_pp_relevant(self): + return self.pp_type != "" + + @property + def amount(self): + return str(self.event["amount"]["value"]) + + @property + def note(self): + if self.event["eventType"].find("card_") == 0: + return self.event["eventType"] + else: + return "" + + @property + def title(self): + return self.event["title"] + + def determine_pp_type(self): + if self.pp_type == "TRADE_INVOICE": + if self.event["amount"]["value"] < 0: + self.pp_type = "BUY" + else: + self.pp_type = "SELL" + + def determine_shares(self): + if self.pp_type == "TRADE_INVOICE": + sections = self.event.get("details", {}).get("sections", [{}]) + for section in sections: + if section.get("title") == "Transaktion": + self.shares = section.get("data", [{}])[0]["detail"][ + "text" + ].replace(",", ".") + + def determine_isin(self): + if self.pp_type in ("DIVIDENDS", "TRADE_INVOICE"): + sections = self.event.get("details", {}).get("sections", [{}]) + self.isin = self.event.get("icon", "") + self.isin = self.isin[self.isin.find("/") + 1 :] + self.isin = self.isin[: self.isin.find("/")] + isin2 = self.isin + for section in sections: + action = section.get("action", None) + if action and action.get("type", {}) == "instrumentDetail": + isin2 = section.get("action", {}).get("payload") + if self.isin != isin2: + self.isin = isin2 + + def process_event(self): + self.determine_shares() + self.determine_isin() + self.determine_pp_type() diff --git a/pytr/locale/cs/LC_MESSAGES/messages.po b/pytr/locale/cs/LC_MESSAGES/messages.po new file mode 100644 index 0000000..fb28691 --- /dev/null +++ b/pytr/locale/cs/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: cs\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Koupit" + +msgid "DEPOSIT" +msgstr "Vklad" + +msgid "DIVIDENDS" +msgstr "Dividendy" + +msgid "FEES" +msgstr "Poplatky" + +msgid "FEES_REFUND" +msgstr "Vratka poplatku" + +msgid "INTEREST" +msgstr "Úrok" + +msgid "INTEREST_CHARGE" +msgstr "Úrokový poplatek" + +msgid "REMOVAL" +msgstr "Výběr" + +msgid "SELL" +msgstr "Prodat" + +msgid "TAXES" +msgstr "Daně" + +msgid "TAX_REFUND" +msgstr "Daňová vratka" + +msgid "TRANSFER_IN" +msgstr "Převod (příchozí)" + +msgid "TRANSFER_OUT" +msgstr "Převod (odchozí)" + +msgid "CSVColumn_AccountName" +msgstr "Peněžní účet" + +msgid "CSVColumn_AccountName2nd" +msgstr "Vyrovnávací účet" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Kumulovaná výkonnost v %" + +msgid "CSVColumn_Currency" +msgstr "Měna" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Měna v hrubé výši" + +msgid "CSVColumn_Date" +msgstr "Datum" + +msgid "CSVColumn_DateQuote" +msgstr "Datum kurzu" + +msgid "CSVColumn_DateValue" +msgstr "Datum vypořádání" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Delta v %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Směnný kurz" + +msgid "CSVColumn_Fees" +msgstr "Poplatky" + +msgid "CSVColumn_GrossAmount" +msgstr "Hrubá výše" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Příchozí převod" + +msgid "CSVColumn_Name" +msgstr "Jméno" + +msgid "CSVColumn_Note" +msgstr "Poznámka" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Odchozí převod" + +msgid "CSVColumn_PortfolioName" +msgstr "Účet cenných papírů" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "vyrovnávací účet cenných papírů" + +msgid "CSVColumn_Quote" +msgstr "Kurz" + +msgid "CSVColumn_SecurityName" +msgstr "Jméno cenného papíru" + +msgid "CSVColumn_Shares" +msgstr "Akcie" + +msgid "CSVColumn_Taxes" +msgstr "Daně" + +msgid "CSVColumn_TickerSymbol" +msgstr "Označení tickeru" + +msgid "CSVColumn_Time" +msgstr "Čas" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Transakční měna" + +msgid "CSVColumn_Type" +msgstr "Typ" + +msgid "CSVColumn_Value" +msgstr "Hodnota" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Platba kartou" + +msgid "card_successful_atm_withdrawal" +msgstr "Výběr hotovosti" + +msgid "card_order_billed" +msgstr "Poplatek za kartu" + +msgid "card_refund" +msgstr "Vrácení peněz na kartu" diff --git a/pytr/locale/da/LC_MESSAGES/messages.po b/pytr/locale/da/LC_MESSAGES/messages.po new file mode 100644 index 0000000..853613b --- /dev/null +++ b/pytr/locale/da/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: da\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Køb" + +msgid "DEPOSIT" +msgstr "Indsæt" + +msgid "DIVIDENDS" +msgstr "Udbytte" + +msgid "FEES" +msgstr "Gebyrer" + +msgid "FEES_REFUND" +msgstr "Refunderede gebyrer" + +msgid "INTEREST" +msgstr "Renteindtægter" + +msgid "INTEREST_CHARGE" +msgstr "Renteudgifter" + +msgid "REMOVAL" +msgstr "Hævning" + +msgid "SELL" +msgstr "Sælg" + +msgid "TAXES" +msgstr "Skatter" + +msgid "TAX_REFUND" +msgstr "Tilbagebetalte skatter" + +msgid "TRANSFER_IN" +msgstr "Overfør (Intern)" + +msgid "TRANSFER_OUT" +msgstr "Overfør (Ekstern)" + +msgid "CSVColumn_AccountName" +msgstr "kontantkonto" + +msgid "CSVColumn_AccountName2nd" +msgstr "Modregningskonto" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Akkumuleret Afkast i %" + +msgid "CSVColumn_Currency" +msgstr "Valuta" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Valuta bruttobeløb" + +msgid "CSVColumn_Date" +msgstr "Dato" + +msgid "CSVColumn_DateQuote" +msgstr "Dato for kurs" + +msgid "CSVColumn_DateValue" +msgstr "Dato for værdi" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Delta i %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Vekselkurs" + +msgid "CSVColumn_Fees" +msgstr "Gebyrer" + +msgid "CSVColumn_GrossAmount" +msgstr "Bruttobeløb" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Indgående overførsler" + +msgid "CSVColumn_Name" +msgstr "Navn" + +msgid "CSVColumn_Note" +msgstr "Bemærkning" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Udgående overførsler" + +msgid "CSVColumn_PortfolioName" +msgstr "Værdipapirkonto" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Modregnings værdipapirkonto" + +msgid "CSVColumn_Quote" +msgstr "Kurs" + +msgid "CSVColumn_SecurityName" +msgstr "Værdipapirnavn" + +msgid "CSVColumn_Shares" +msgstr "Aktier" + +msgid "CSVColumn_Taxes" +msgstr "Skatter" + +msgid "CSVColumn_TickerSymbol" +msgstr "Værdipapirkode" + +msgid "CSVColumn_Time" +msgstr "Tid" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Transaktionsvaluta" + +msgid "CSVColumn_Type" +msgstr "Type" + +msgid "CSVColumn_Value" +msgstr "Værdi" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Platba kartou" + +msgid "card_successful_atm_withdrawal" +msgstr "Výběr hotovosti" + +msgid "card_order_billed" +msgstr "Poplatek za kartu" + +msgid "card_refund" +msgstr "Vrácení peněz na kartu" diff --git a/pytr/locale/de/LC_MESSAGES/messages.po b/pytr/locale/de/LC_MESSAGES/messages.po new file mode 100644 index 0000000..ecd0bbe --- /dev/null +++ b/pytr/locale/de/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: de\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Kauf" + +msgid "DEPOSIT" +msgstr "Einlage" + +msgid "DIVIDENDS" +msgstr "Dividende" + +msgid "FEES" +msgstr "Gebühren" + +msgid "FEES_REFUND" +msgstr "Gebührenerstattung" + +msgid "INTEREST" +msgstr "Zinsen" + +msgid "INTEREST_CHARGE" +msgstr "Zinsbelastung" + +msgid "REMOVAL" +msgstr "Entnahme" + +msgid "SELL" +msgstr "Verkauf" + +msgid "TAXES" +msgstr "Steuern" + +msgid "TAX_REFUND" +msgstr "Steuerrückerstattung" + +msgid "TRANSFER_IN" +msgstr "Umbuchung (Eingang)" + +msgid "TRANSFER_OUT" +msgstr "Umbuchung (Ausgang)" + +msgid "CSVColumn_AccountName" +msgstr "Konto" + +msgid "CSVColumn_AccountName2nd" +msgstr "Gegenkonto" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Kumulierte Performance in %" + +msgid "CSVColumn_Currency" +msgstr "Währung" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Währung Bruttobetrag" + +msgid "CSVColumn_Date" +msgstr "Datum" + +msgid "CSVColumn_DateQuote" +msgstr "Kursdatum" + +msgid "CSVColumn_DateValue" +msgstr "Datum Wert" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Delta in %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Wechselkurs" + +msgid "CSVColumn_Fees" +msgstr "Gebühren" + +msgid "CSVColumn_GrossAmount" +msgstr "Bruttobetrag" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Zugänge" + +msgid "CSVColumn_Name" +msgstr "Name" + +msgid "CSVColumn_Note" +msgstr "Notiz" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Abgänge" + +msgid "CSVColumn_PortfolioName" +msgstr "Depot" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Gegendepot" + +msgid "CSVColumn_Quote" +msgstr "Kurs" + +msgid "CSVColumn_SecurityName" +msgstr "Wertpapiername" + +msgid "CSVColumn_Shares" +msgstr "Stück" + +msgid "CSVColumn_Taxes" +msgstr "Steuern" + +msgid "CSVColumn_TickerSymbol" +msgstr "Ticker-Symbol" + +msgid "CSVColumn_Time" +msgstr "Uhrzeit" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Buchungswährung" + +msgid "CSVColumn_Type" +msgstr "Typ" + +msgid "CSVColumn_Value" +msgstr "Wert" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Kartentransaktion" + +msgid "card_successful_atm_withdrawal" +msgstr "Barabhebung" + +msgid "card_order_billed" +msgstr "Kartengebühr" + +msgid "card_refund" +msgstr "Kartenerstattung" diff --git a/pytr/locale/en/LC_MESSAGES/messages.po b/pytr/locale/en/LC_MESSAGES/messages.po new file mode 100644 index 0000000..9da1304 --- /dev/null +++ b/pytr/locale/en/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: en\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Buy" + +msgid "DEPOSIT" +msgstr "Deposit" + +msgid "DIVIDENDS" +msgstr "Dividend" + +msgid "FEES" +msgstr "Fees" + +msgid "FEES_REFUND" +msgstr "Fees Refund" + +msgid "INTEREST" +msgstr "Interest" + +msgid "INTEREST_CHARGE" +msgstr "Interest Charge" + +msgid "REMOVAL" +msgstr "Removal" + +msgid "SELL" +msgstr "Sell" + +msgid "TAXES" +msgstr "Taxes" + +msgid "TAX_REFUND" +msgstr "Tax Refund" + +msgid "TRANSFER_IN" +msgstr "Transfer (Inbound)" + +msgid "TRANSFER_OUT" +msgstr "Transfer (Outbound)" + +msgid "CSVColumn_AccountName" +msgstr "Cash Account" + +msgid "CSVColumn_AccountName2nd" +msgstr "Offset Account" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Cumulated Performance in %" + +msgid "CSVColumn_Currency" +msgstr "Currency" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Currency Gross Amount" + +msgid "CSVColumn_Date" +msgstr "Date" + +msgid "CSVColumn_DateQuote" +msgstr "Date of Quote" + +msgid "CSVColumn_DateValue" +msgstr "Date of Value" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Delta in %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Exchange Rate" + +msgid "CSVColumn_Fees" +msgstr "Fees" + +msgid "CSVColumn_GrossAmount" +msgstr "Gross Amount" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Inbound Transferals" + +msgid "CSVColumn_Name" +msgstr "Name" + +msgid "CSVColumn_Note" +msgstr "Note" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Outbound Transferals" + +msgid "CSVColumn_PortfolioName" +msgstr "Securities Account" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Offset securities account" + +msgid "CSVColumn_Quote" +msgstr "Quote" + +msgid "CSVColumn_SecurityName" +msgstr "Security Name" + +msgid "CSVColumn_Shares" +msgstr "Shares" + +msgid "CSVColumn_Taxes" +msgstr "Taxes" + +msgid "CSVColumn_TickerSymbol" +msgstr "Ticker Symbol" + +msgid "CSVColumn_Time" +msgstr "Time" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Transaction Currency" + +msgid "CSVColumn_Type" +msgstr "Type" + +msgid "CSVColumn_Value" +msgstr "Value" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Card Payment" + +msgid "card_successful_atm_withdrawal" +msgstr "ATM Withdrawal" + +msgid "card_order_billed" +msgstr "Card Fee" + +msgid "card_refund" +msgstr "Card Refund" diff --git a/pytr/locale/es/LC_MESSAGES/messages.po b/pytr/locale/es/LC_MESSAGES/messages.po new file mode 100644 index 0000000..2b95e21 --- /dev/null +++ b/pytr/locale/es/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: es\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Compra" + +msgid "DEPOSIT" +msgstr "Depósito" + +msgid "DIVIDENDS" +msgstr "Dividendo" + +msgid "FEES" +msgstr "Comisiones" + +msgid "FEES_REFUND" +msgstr "Reembolso de comisiones" + +msgid "INTEREST" +msgstr "Intereses" + +msgid "INTEREST_CHARGE" +msgstr "Cargo por intereses" + +msgid "REMOVAL" +msgstr "Retirada" + +msgid "SELL" +msgstr "Venta" + +msgid "TAXES" +msgstr "Impuestos" + +msgid "TAX_REFUND" +msgstr "Devolución de impuestos" + +msgid "TRANSFER_IN" +msgstr "Traspaso (entrada)" + +msgid "TRANSFER_OUT" +msgstr "Traspaso (salida)" + +msgid "CSVColumn_AccountName" +msgstr "Cuenta" + +msgid "CSVColumn_AccountName2nd" +msgstr "Cuenta de contrapartida" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Rendimiento acumulado en %" + +msgid "CSVColumn_Currency" +msgstr "Divisa" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Importe bruto de divisa" + +msgid "CSVColumn_Date" +msgstr "Fecha" + +msgid "CSVColumn_DateQuote" +msgstr "Fecha de cotización" + +msgid "CSVColumn_DateValue" +msgstr "Fecha de valor" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Delta en %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Tipo de cambio" + +msgid "CSVColumn_Fees" +msgstr "Comisiones" + +msgid "CSVColumn_GrossAmount" +msgstr "Valor bruto" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Traspasos entrantes" + +msgid "CSVColumn_Name" +msgstr "Nombre" + +msgid "CSVColumn_Note" +msgstr "Nota" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Traspasos salientes" + +msgid "CSVColumn_PortfolioName" +msgstr "Cuenta de valores" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Cuenta de valores compensados" + +msgid "CSVColumn_Quote" +msgstr "Cotización" + +msgid "CSVColumn_SecurityName" +msgstr "Nombre del valor" + +msgid "CSVColumn_Shares" +msgstr "Cantidad" + +msgid "CSVColumn_Taxes" +msgstr "Impuestos" + +msgid "CSVColumn_TickerSymbol" +msgstr "Símbolo del ticker" + +msgid "CSVColumn_Time" +msgstr "Hora" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Moneda de la transacción" + +msgid "CSVColumn_Type" +msgstr "Tipo" + +msgid "CSVColumn_Value" +msgstr "Valor" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Transacción con tarjeta" + +msgid "card_successful_atm_withdrawal" +msgstr "Retiradas de efectivo" + +msgid "card_order_billed" +msgstr "Transacción con tarjeta" + +msgid "card_refund" +msgstr "Reembolso de tarjeta" diff --git a/pytr/locale/fr/LC_MESSAGES/messages.po b/pytr/locale/fr/LC_MESSAGES/messages.po new file mode 100644 index 0000000..7ac8b94 --- /dev/null +++ b/pytr/locale/fr/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: fr\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Achat" + +msgid "DEPOSIT" +msgstr "Dépôt" + +msgid "DIVIDENDS" +msgstr "Dividendes" + +msgid "FEES" +msgstr "Frais" + +msgid "FEES_REFUND" +msgstr "Remboursement de Frais" + +msgid "INTEREST" +msgstr "Intérêts" + +msgid "INTEREST_CHARGE" +msgstr "Frais d'Intérêts" + +msgid "REMOVAL" +msgstr "Retrait" + +msgid "SELL" +msgstr "Vente" + +msgid "TAXES" +msgstr "Impôts / Taxes" + +msgid "TAX_REFUND" +msgstr "Remboursement Impôts / Taxes" + +msgid "TRANSFER_IN" +msgstr "Transfert (Entrant)" + +msgid "TRANSFER_OUT" +msgstr "Transfert (Sortant)" + +msgid "CSVColumn_AccountName" +msgstr "Compte espèces" + +msgid "CSVColumn_AccountName2nd" +msgstr "Compte de compensation" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Performance cumulée en %" + +msgid "CSVColumn_Currency" +msgstr "Devise" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Montant brut en devise" + +msgid "CSVColumn_Date" +msgstr "Date" + +msgid "CSVColumn_DateQuote" +msgstr "Date de cotation" + +msgid "CSVColumn_DateValue" +msgstr "Date de valeur" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Delta en %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Taux de change" + +msgid "CSVColumn_Fees" +msgstr "Frais" + +msgid "CSVColumn_GrossAmount" +msgstr "Montant brut" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Transferts entrants" + +msgid "CSVColumn_Name" +msgstr "Nom" + +msgid "CSVColumn_Note" +msgstr "Note" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Transferts sortant" + +msgid "CSVColumn_PortfolioName" +msgstr "Compte-titres" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Compte de compensation" + +msgid "CSVColumn_Quote" +msgstr "Cotation" + +msgid "CSVColumn_SecurityName" +msgstr "Nom du titre" + +msgid "CSVColumn_Shares" +msgstr "Parts" + +msgid "CSVColumn_Taxes" +msgstr "Impôts / Taxes" + +msgid "CSVColumn_TickerSymbol" +msgstr "Symbole boursier" + +msgid "CSVColumn_Time" +msgstr "Heure" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Devise de l'opération" + +msgid "CSVColumn_Type" +msgstr "Type" + +msgid "CSVColumn_Value" +msgstr "Valeur" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Transaction par carte" + +msgid "card_successful_atm_withdrawal" +msgstr "Retrait en espèces" + +msgid "card_order_billed" +msgstr "Frais de carte" + +msgid "card_refund" +msgstr "Remboursement par carte" diff --git a/pytr/locale/it/LC_MESSAGES/messages.po b/pytr/locale/it/LC_MESSAGES/messages.po new file mode 100644 index 0000000..9208ba9 --- /dev/null +++ b/pytr/locale/it/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: it\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Compra" + +msgid "DEPOSIT" +msgstr "Deposito" + +msgid "DIVIDENDS" +msgstr "Dividendo" + +msgid "FEES" +msgstr "Commissioni" + +msgid "FEES_REFUND" +msgstr "Rimborso commissioni" + +msgid "INTEREST" +msgstr "Interessi" + +msgid "INTEREST_CHARGE" +msgstr "Interessi passivi" + +msgid "REMOVAL" +msgstr "Prelievo" + +msgid "SELL" +msgstr "Vendi" + +msgid "TAXES" +msgstr "Tasse" + +msgid "TAX_REFUND" +msgstr "Rimborso tasse" + +msgid "TRANSFER_IN" +msgstr "Trasferimento (in entrata)" + +msgid "TRANSFER_OUT" +msgstr "Trasferimento (in uscita)" + +msgid "CSVColumn_AccountName" +msgstr "Conto di cassa" + +msgid "CSVColumn_AccountName2nd" +msgstr "Conto di compensazione" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Rendimento cumulato in %" + +msgid "CSVColumn_Currency" +msgstr "Valuta" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Importo lordo valuta" + +msgid "CSVColumn_Date" +msgstr "Data" + +msgid "CSVColumn_DateQuote" +msgstr "Data Quotazione" + +msgid "CSVColumn_DateValue" +msgstr "Data Valorizzazione" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Delta in %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Tasso di cambio" + +msgid "CSVColumn_Fees" +msgstr "Commissioni" + +msgid "CSVColumn_GrossAmount" +msgstr "Importo Lordo" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Trasferimento in entrata" + +msgid "CSVColumn_Name" +msgstr "Nome" + +msgid "CSVColumn_Note" +msgstr "Note" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Trasferimento in uscita" + +msgid "CSVColumn_PortfolioName" +msgstr "Conto titoli" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Conto titoli di compensazione" + +msgid "CSVColumn_Quote" +msgstr "Quotazione" + +msgid "CSVColumn_SecurityName" +msgstr "Nome Titolo" + +msgid "CSVColumn_Shares" +msgstr "Azioni" + +msgid "CSVColumn_Taxes" +msgstr "Tasse" + +msgid "CSVColumn_TickerSymbol" +msgstr "Simbolo Titolo" + +msgid "CSVColumn_Time" +msgstr "Ora" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Valuta Operazione" + +msgid "CSVColumn_Type" +msgstr "Tipo" + +msgid "CSVColumn_Value" +msgstr "Valore" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Transazione con carta" + +msgid "card_successful_atm_withdrawal" +msgstr "Prelievo di contanti" + +msgid "card_order_billed" +msgstr "Tassa sulla carta" + +msgid "card_refund" +msgstr "Rimborso sulla carta" diff --git a/pytr/locale/nl/LC_MESSAGES/messages.po b/pytr/locale/nl/LC_MESSAGES/messages.po new file mode 100644 index 0000000..e93f38c --- /dev/null +++ b/pytr/locale/nl/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: nl\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Aankoop" + +msgid "DEPOSIT" +msgstr "Storting" + +msgid "DIVIDENDS" +msgstr "Dividend" + +msgid "FEES" +msgstr "Kosten" + +msgid "FEES_REFUND" +msgstr "Terugbetaling van kosten" + +msgid "INTEREST" +msgstr "Rentebaten" + +msgid "INTEREST_CHARGE" +msgstr "Rentelasten" + +msgid "REMOVAL" +msgstr "Onttrekking" + +msgid "SELL" +msgstr "Verkoop" + +msgid "TAXES" +msgstr "Belastingen" + +msgid "TAX_REFUND" +msgstr "Terugbetaling van belastingen" + +msgid "TRANSFER_IN" +msgstr "Inkomende overboeking" + +msgid "TRANSFER_OUT" +msgstr "Uitgaande overboeking" + +msgid "CSVColumn_AccountName" +msgstr "Rekening" + +msgid "CSVColumn_AccountName2nd" +msgstr "Tegenrekening" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Resultaat (%, cumulatief)" + +msgid "CSVColumn_Currency" +msgstr "Valuta" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Valuta (bruto)" + +msgid "CSVColumn_Date" +msgstr "Datum" + +msgid "CSVColumn_DateQuote" +msgstr "Koersdatum" + +msgid "CSVColumn_DateValue" +msgstr "Datum" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Delta (%)" + +msgid "CSVColumn_ExchangeRate" +msgstr "Wisselkoers" + +msgid "CSVColumn_Fees" +msgstr "Kosten" + +msgid "CSVColumn_GrossAmount" +msgstr "Waarde (bruto)" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Inkomende overschrijvingen" + +msgid "CSVColumn_Name" +msgstr "Naam" + +msgid "CSVColumn_Note" +msgstr "Opmerking" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Uitgaande overschrijvingen" + +msgid "CSVColumn_PortfolioName" +msgstr "Portefeuille" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Portefeuilletegenrekening" + +msgid "CSVColumn_Quote" +msgstr "Koers" + +msgid "CSVColumn_SecurityName" +msgstr "Effect" + +msgid "CSVColumn_Shares" +msgstr "Aantal" + +msgid "CSVColumn_Taxes" +msgstr "Belasting" + +msgid "CSVColumn_TickerSymbol" +msgstr "Tickersymbool" + +msgid "CSVColumn_Time" +msgstr "Tijd" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Transactievaluta" + +msgid "CSVColumn_Type" +msgstr "Transactietype" + +msgid "CSVColumn_Value" +msgstr "Waarde (netto)" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Kaarttransactie" + +msgid "card_successful_atm_withdrawal" +msgstr "Geldopname" + +msgid "card_order_billed" +msgstr "Kosten kaart" + +msgid "card_refund" +msgstr "Terugbetaling op kaart" diff --git a/pytr/locale/pl/LC_MESSAGES/messages.po b/pytr/locale/pl/LC_MESSAGES/messages.po new file mode 100644 index 0000000..7bc784c --- /dev/null +++ b/pytr/locale/pl/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: pl\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Kupno" + +msgid "DEPOSIT" +msgstr "Depozyt" + +msgid "DIVIDENDS" +msgstr "Dywidenda" + +msgid "FEES" +msgstr "Opłaty" + +msgid "FEES_REFUND" +msgstr "Zwrot opłat" + +msgid "INTEREST" +msgstr "Odsetki" + +msgid "INTEREST_CHARGE" +msgstr "Opłata odsetkowa" + +msgid "REMOVAL" +msgstr "Wypłata" + +msgid "SELL" +msgstr "Sprzedaż" + +msgid "TAXES" +msgstr "Podatki" + +msgid "TAX_REFUND" +msgstr "Zwrot podatku" + +msgid "TRANSFER_IN" +msgstr "Transfer (Przychodzący)" + +msgid "TRANSFER_OUT" +msgstr "Transfer (Wychodzący)" + +msgid "CSVColumn_AccountName" +msgstr "Konto pieniężne" + +msgid "CSVColumn_AccountName2nd" +msgstr "Konto przeciwstawne" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Skumulowany wynik w %" + +msgid "CSVColumn_Currency" +msgstr "Waluta" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Kwota waluty brutto" + +msgid "CSVColumn_Date" +msgstr "Data" + +msgid "CSVColumn_DateQuote" +msgstr "Data notowania" + +msgid "CSVColumn_DateValue" +msgstr "Data wartości" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Różnica w %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Kurs wymiany" + +msgid "CSVColumn_Fees" +msgstr "Opłaty" + +msgid "CSVColumn_GrossAmount" +msgstr "Kwota brutto" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Przelewy przychodzące" + +msgid "CSVColumn_Name" +msgstr "Nazwa" + +msgid "CSVColumn_Note" +msgstr "Uwaga" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Przelewy wychodzące" + +msgid "CSVColumn_PortfolioName" +msgstr "Konto walorów" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Konto przeciwstawne walorów" + +msgid "CSVColumn_Quote" +msgstr "Kurs" + +msgid "CSVColumn_SecurityName" +msgstr "Nazwa waloru" + +msgid "CSVColumn_Shares" +msgstr "Akcje" + +msgid "CSVColumn_Taxes" +msgstr "Podatki" + +msgid "CSVColumn_TickerSymbol" +msgstr "Symbol giełdowy waloru" + +msgid "CSVColumn_Time" +msgstr "Czas" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Waluta transakcji" + +msgid "CSVColumn_Type" +msgstr "Typ" + +msgid "CSVColumn_Value" +msgstr "Wartość" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Kaarttransactie" + +msgid "card_successful_atm_withdrawal" +msgstr "Geldopname" + +msgid "card_order_billed" +msgstr "Kosten kaart" + +msgid "card_refund" +msgstr "Terugbetaling op kaart" diff --git a/pytr/locale/pt/LC_MESSAGES/messages.po b/pytr/locale/pt/LC_MESSAGES/messages.po new file mode 100644 index 0000000..ba6df93 --- /dev/null +++ b/pytr/locale/pt/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: pt\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Comprar" + +msgid "DEPOSIT" +msgstr "Depósito" + +msgid "DIVIDENDS" +msgstr "Dividendo" + +msgid "FEES" +msgstr "Comissões" + +msgid "FEES_REFUND" +msgstr "Reembolso de Comissões" + +msgid "INTEREST" +msgstr "Juros" + +msgid "INTEREST_CHARGE" +msgstr "Encargos de Juros" + +msgid "REMOVAL" +msgstr "Levantamento" + +msgid "SELL" +msgstr "Vender" + +msgid "TAXES" +msgstr "Impostos" + +msgid "TAX_REFUND" +msgstr "Reembolso de Impostos" + +msgid "TRANSFER_IN" +msgstr "Transferência (Entrada)" + +msgid "TRANSFER_OUT" +msgstr "Transferência (Saída)" + +msgid "CSVColumn_AccountName" +msgstr "Conta Caixa" + +msgid "CSVColumn_AccountName2nd" +msgstr "Conta de Contrapartida" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Performance Acumulada em %" + +msgid "CSVColumn_Currency" +msgstr "Moeda" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Valor Bruto em Moeda" + +msgid "CSVColumn_Date" +msgstr "Data" + +msgid "CSVColumn_DateQuote" +msgstr "Data da Cotação" + +msgid "CSVColumn_DateValue" +msgstr "Data do valor" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Delta em %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Taxas de Câmbio" + +msgid "CSVColumn_Fees" +msgstr "Comissões" + +msgid "CSVColumn_GrossAmount" +msgstr "Valor bruto" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Transferências de Entrada" + +msgid "CSVColumn_Name" +msgstr "Nome" + +msgid "CSVColumn_Note" +msgstr "Nota" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Transferências de Saída" + +msgid "CSVColumn_PortfolioName" +msgstr "Conta de Títulos" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Conta de Títulos Compensados" + +msgid "CSVColumn_Quote" +msgstr "Cotação" + +msgid "CSVColumn_SecurityName" +msgstr "Nome do Título" + +msgid "CSVColumn_Shares" +msgstr "Quantidade" + +msgid "CSVColumn_Taxes" +msgstr "Impostos" + +msgid "CSVColumn_TickerSymbol" +msgstr "Símbolo Ticker" + +msgid "CSVColumn_Time" +msgstr "Hora" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Moeda da transação" + +msgid "CSVColumn_Type" +msgstr "Tipo" + +msgid "CSVColumn_Value" +msgstr "Valor" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Transakcja kartą" + +msgid "card_successful_atm_withdrawal" +msgstr "Levantamento de dinheiro" + +msgid "card_order_billed" +msgstr "Taxa do cartão" + +msgid "card_refund" +msgstr "Reembolso do cartão" diff --git a/pytr/locale/ru/LC_MESSAGES/messages.po b/pytr/locale/ru/LC_MESSAGES/messages.po new file mode 100644 index 0000000..e828d51 --- /dev/null +++ b/pytr/locale/ru/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: ru\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Покупка" + +msgid "DEPOSIT" +msgstr "Пополнение" + +msgid "DIVIDENDS" +msgstr "Дивиденд" + +msgid "FEES" +msgstr "Сборы" + +msgid "FEES_REFUND" +msgstr "Возврат сборов" + +msgid "INTEREST" +msgstr "Процент" + +msgid "INTEREST_CHARGE" +msgstr "Возврат процента" + +msgid "REMOVAL" +msgstr "Списание" + +msgid "SELL" +msgstr "Продажа" + +msgid "TAXES" +msgstr "Налоги" + +msgid "TAX_REFUND" +msgstr "Возврат налога" + +msgid "TRANSFER_IN" +msgstr "Перевод (Входящий)" + +msgid "TRANSFER_OUT" +msgstr "Перевод (Исходящий)" + +msgid "CSVColumn_AccountName" +msgstr "Денежный счет" + +msgid "CSVColumn_AccountName2nd" +msgstr "Зачетный счет" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Суммарная эффективность в %" + +msgid "CSVColumn_Currency" +msgstr "Валюта" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Валюта сумма (брутто)" + +msgid "CSVColumn_Date" +msgstr "Дата" + +msgid "CSVColumn_DateQuote" +msgstr "Дата котировки" + +msgid "CSVColumn_DateValue" +msgstr "Дата значения" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Дельта в %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Курс" + +msgid "CSVColumn_Fees" +msgstr "Сборы" + +msgid "CSVColumn_GrossAmount" +msgstr "Валовая Сумма" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Входящие переводы" + +msgid "CSVColumn_Name" +msgstr "Название" + +msgid "CSVColumn_Note" +msgstr "Заметка" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Исходящие переводы" + +msgid "CSVColumn_PortfolioName" +msgstr "Счет ценных бумаг" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Зачетный счет ценных бумаг" + +msgid "CSVColumn_Quote" +msgstr "Цена" + +msgid "CSVColumn_SecurityName" +msgstr "Имя ценной бумаги" + +msgid "CSVColumn_Shares" +msgstr "Акций" + +msgid "CSVColumn_Taxes" +msgstr "Налоги" + +msgid "CSVColumn_TickerSymbol" +msgstr "Тикер" + +msgid "CSVColumn_Time" +msgstr "Время" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Валюта Транзакции" + +msgid "CSVColumn_Type" +msgstr "Тип" + +msgid "CSVColumn_Value" +msgstr "Значение" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Операция по карте" + +msgid "card_successful_atm_withdrawal" +msgstr "Выдача наличных" + +msgid "card_order_billed" +msgstr "Плата за обслуживание карты" + +msgid "card_refund" +msgstr "Возврат на карту" diff --git a/pytr/locale/sk/LC_MESSAGES/messages.po b/pytr/locale/sk/LC_MESSAGES/messages.po new file mode 100644 index 0000000..5985c98 --- /dev/null +++ b/pytr/locale/sk/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: sk\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "Kúpiť" + +msgid "DEPOSIT" +msgstr "Vklad" + +msgid "DIVIDENDS" +msgstr "Dividenda" + +msgid "FEES" +msgstr "Poplatky" + +msgid "FEES_REFUND" +msgstr "Vrátenie poplatkov" + +msgid "INTEREST" +msgstr "Úroky" + +msgid "INTEREST_CHARGE" +msgstr "Úrokový poplatok" + +msgid "REMOVAL" +msgstr "Výber" + +msgid "SELL" +msgstr "Predaj" + +msgid "TAXES" +msgstr "Dane" + +msgid "TAX_REFUND" +msgstr "Vrátenie dane" + +msgid "TRANSFER_IN" +msgstr "Prevod (prichádzajúci)" + +msgid "TRANSFER_OUT" +msgstr "Prevod (odchádzajúci)" + +msgid "CSVColumn_AccountName" +msgstr "Účet cenných papierov" + +msgid "CSVColumn_AccountName2nd" +msgstr "Hotovostný účet" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "Kumulovaný výkon v %" + +msgid "CSVColumn_Currency" +msgstr "Mena" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "Mena Hrubá suma" + +msgid "CSVColumn_Date" +msgstr "Dátum" + +msgid "CSVColumn_DateQuote" +msgstr "Dátum kurzu" + +msgid "CSVColumn_DateValue" +msgstr "Dátum vysporiadania" + +msgid "CSVColumn_DeltaInPercent" +msgstr "Delta v %" + +msgid "CSVColumn_ExchangeRate" +msgstr "Výmenný kurz" + +msgid "CSVColumn_Fees" +msgstr "Poplatky" + +msgid "CSVColumn_GrossAmount" +msgstr "Hrubá suma" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "Prichádzajúce prevod" + +msgid "CSVColumn_Name" +msgstr "Názov" + +msgid "CSVColumn_Note" +msgstr "Poznámka" + +msgid "CSVColumn_OutboundTransferals" +msgstr "Odchádzajúce prevod" + +msgid "CSVColumn_PortfolioName" +msgstr "Účet cenných papierov" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "Účet cenných papierov pre vyrovnanie" + +msgid "CSVColumn_Quote" +msgstr "Kurz" + +msgid "CSVColumn_SecurityName" +msgstr "Názov cenného papiera" + +msgid "CSVColumn_Shares" +msgstr "Akcie" + +msgid "CSVColumn_Taxes" +msgstr "Daň" + +msgid "CSVColumn_TickerSymbol" +msgstr "Ticker" + +msgid "CSVColumn_Time" +msgstr "Čas" + +msgid "CSVColumn_TransactionCurrency" +msgstr "Mena transakcie" + +msgid "CSVColumn_Type" +msgstr "Typ" + +msgid "CSVColumn_Value" +msgstr "Hodnota" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Операция по карте" + +msgid "card_successful_atm_withdrawal" +msgstr "Выдача наличных" + +msgid "card_order_billed" +msgstr "Плата за обслуживание карты" + +msgid "card_refund" +msgstr "Возврат на карту" diff --git a/pytr/locale/zh/LC_MESSAGES/messages.po b/pytr/locale/zh/LC_MESSAGES/messages.po new file mode 100644 index 0000000..aa68f3f --- /dev/null +++ b/pytr/locale/zh/LC_MESSAGES/messages.po @@ -0,0 +1,143 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: zh\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "BUY" +msgstr "买入" + +msgid "DEPOSIT" +msgstr "存款" + +msgid "DIVIDENDS" +msgstr "股息" + +msgid "FEES" +msgstr "费用" + +msgid "FEES_REFUND" +msgstr "费用退款" + +msgid "INTEREST" +msgstr "利息" + +msgid "INTEREST_CHARGE" +msgstr "利息支出" + +msgid "REMOVAL" +msgstr "取款" + +msgid "SELL" +msgstr "卖出" + +msgid "TAXES" +msgstr "税款" + +msgid "TAX_REFUND" +msgstr "退税" + +msgid "TRANSFER_IN" +msgstr "转入" + +msgid "TRANSFER_OUT" +msgstr "转出" + +msgid "CSVColumn_AccountName" +msgstr "现金账户" + +msgid "CSVColumn_AccountName2nd" +msgstr "目标账户" + +msgid "CSVColumn_CumulatedPerformanceInPercent" +msgstr "累计收益率 %" + +msgid "CSVColumn_Currency" +msgstr "货币" + +msgid "CSVColumn_CurrencyGrossAmount" +msgstr "总额货币" + +msgid "CSVColumn_Date" +msgstr "日期" + +msgid "CSVColumn_DateQuote" +msgstr "报价日期" + +msgid "CSVColumn_DateValue" +msgstr "账目日期" + +msgid "CSVColumn_DeltaInPercent" +msgstr "变化 %" + +msgid "CSVColumn_ExchangeRate" +msgstr "汇率" + +msgid "CSVColumn_Fees" +msgstr "费用" + +msgid "CSVColumn_GrossAmount" +msgstr "总额" + +msgid "CSVColumn_ISIN" +msgstr "ISIN" + +msgid "CSVColumn_InboundTransferals" +msgstr "总转入" + +msgid "CSVColumn_Name" +msgstr "名称" + +msgid "CSVColumn_Note" +msgstr "备注" + +msgid "CSVColumn_OutboundTransferals" +msgstr "总转出" + +msgid "CSVColumn_PortfolioName" +msgstr "证券账户" + +msgid "CSVColumn_PortfolioName2nd" +msgstr "目标证券账户" + +msgid "CSVColumn_Quote" +msgstr "报价" + +msgid "CSVColumn_SecurityName" +msgstr "证券名称" + +msgid "CSVColumn_Shares" +msgstr "份额" + +msgid "CSVColumn_Taxes" +msgstr "税款" + +msgid "CSVColumn_TickerSymbol" +msgstr "证券代码" + +msgid "CSVColumn_Time" +msgstr "时间" + +msgid "CSVColumn_TransactionCurrency" +msgstr "账目货币" + +msgid "CSVColumn_Type" +msgstr "类型" + +msgid "CSVColumn_Value" +msgstr "净额" + +msgid "CSVColumn_WKN" +msgstr "WKN" + +msgid "card_successful_transaction" +msgstr "Операция по карте" + +msgid "card_successful_atm_withdrawal" +msgstr "Выдача наличных" + +msgid "card_order_billed" +msgstr "Плата за обслуживание карты" + +msgid "card_refund" +msgstr "Возврат на карту" diff --git a/pytr/main.py b/pytr/main.py index 938df7b..b642f22 100644 --- a/pytr/main.py +++ b/pytr/main.py @@ -3,7 +3,6 @@ import argparse import asyncio import signal -import time import shtab @@ -11,7 +10,8 @@ from pathlib import Path from datetime import datetime, timedelta -from pytr.utils import get_logger, check_version, export_transactions +from pytr.utils import get_logger, check_version +from pytr.transactions import export_transactions from pytr.dl import DL from pytr.account import login from pytr.portfolio import Portfolio diff --git a/pytr/timeline.py b/pytr/timeline.py new file mode 100644 index 0000000..250a28c --- /dev/null +++ b/pytr/timeline.py @@ -0,0 +1,176 @@ +from datetime import datetime +import json + +from .utils import get_logger +from .transactions import export_transactions + +class Timeline: + def __init__(self, tr, max_age_timestamp): + self.tr = tr + self.log = get_logger(__name__) + self.received_detail = 0 + self.requested_detail = 0 + self.events_without_docs = [] + self.events_with_docs = [] + self.num_timelines = 0 + self.timeline_events = {} + self.max_age_timestamp = max_age_timestamp + + async def get_next_timeline_transactions(self, response=None): + ''' + Get timelines transactions and save time in list timelines. + Extract timeline transactions events and save them in list timeline_events + + ''' + if response is None: + # empty response / first timeline + self.log.info('Subscribing to #1 timeline transactions') + self.num_timelines = 0 + await self.tr.timeline_transactions() + else: + self.num_timelines += 1 + added_last_event = True + for event in response['items']: + if self.max_age_timestamp == 0 or datetime.fromisoformat(event['timestamp'][:19]).timestamp() >= self.max_age_timestamp: + event['source'] = "timelineTransaction" + self.timeline_events[event['id']] = event + else: + added_last_event = False + break + + self.log.info( + f'Received #{self.num_timelines:<2} timeline transactions' + ) + after = response['cursors'].get('after') + if (after is not None) and added_last_event: + self.log.info( + f'Subscribing #{self.num_timelines+1:<2} timeline transactions' + ) + await self.tr.timeline_transactions(after) + else: + # last timeline is reached + self.log.info('Received last relevant timeline transaction') + await self.get_next_timeline_activity_log() + + + async def get_next_timeline_activity_log(self, response=None): + ''' + Get timelines acvtivity log and save time in list timelines. + Extract timeline acvtivity log events and save them in list timeline_events + + ''' + if response is None: + # empty response / first timeline + self.log.info('Awaiting #1 timeline activity log') + self.num_timelines = 0 + await self.tr.timeline_activity_log() + else: + self.num_timelines += 1 + added_last_event = True + for event in response['items']: + if self.max_age_timestamp == 0 or datetime.fromisoformat(event['timestamp'][:19]).timestamp() >= self.max_age_timestamp: + if event['id'] in self.timeline_events: + self.log.warning(f"Received duplicate event {event['id'] }") + event['source'] = "timelineActivity" + self.timeline_events[event['id']] = event + else: + added_last_event = False + break + + self.log.info(f'Received #{self.num_timelines:<2} timeline activity log') + after = response['cursors'].get('after') + if (after is not None) and added_last_event: + self.log.info( + f'Subscribing #{self.num_timelines+1:<2} timeline activity log' + ) + await self.tr.timeline_activity_log(after) + else: + self.log.info('Received last relevant timeline activity log') + await self._get_timeline_details() + + async def _get_timeline_details(self): + ''' + request timeline details + ''' + for event in self.timeline_events.values(): + action = event.get('action') + msg = '' + if action is None: + if event.get('actionLabel') is None: + msg += 'Skip: no action' + elif action.get('type') != 'timelineDetail': + msg += f"Skip: action type unmatched ({action['type']})" + elif action.get('payload') != event['id']: + msg += f"Skip: payload unmatched ({action['payload']})" + + if msg != '': + self.events_without_docs.append(event) + self.log.debug(f"{msg} {event['title']}: {event.get('body')} ") + else: + self.requested_detail += 1 + await self.tr.timeline_detail_v2(event['id']) + self.log.info('All timeline details requested') + return False + + async def process_timelineDetail(self, response, dl): + ''' + process timeline details response + download any associated docs + create other_events.json, events_with_documents.json and account_transactions.csv + ''' + + self.received_detail += 1 + event = self.timeline_events[response['id']] + event['details'] = response + + max_details_digits = len(str(self.requested_detail)) + self.log.info( + f"{self.received_detail:>{max_details_digits}}/{self.requested_detail}: " + + f"{event['title']} -- {event['subtitle']} - {event['timestamp'][:19]}" + ) + + subfolder = { + 'benefits_saveback_execution': 'Saveback', + 'benefits_spare_change_execution': 'RoundUp', + 'ssp_corporate_action_invoice_cash': 'Dividende', + 'CREDIT': 'Dividende', + 'INTEREST_PAYOUT_CREATED': 'Zinsen', + "SAVINGS_PLAN_EXECUTED":'Sparplan' + }.get(event["eventType"]) + + event['has_docs'] = False + for section in response['sections']: + if section['type'] != 'documents': + continue + for doc in section['data']: + event['has_docs'] = True + try: + timestamp = datetime.strptime(doc['detail'], '%d.%m.%Y').timestamp() + except (ValueError, KeyError): + timestamp = datetime.now().timestamp() + if self.max_age_timestamp == 0 or self.max_age_timestamp < timestamp: + title = f"{doc['title']} - {event['title']}" + if event['eventType'] in ["ACCOUNT_TRANSFER_INCOMING", "ACCOUNT_TRANSFER_OUTGOING", "CREDIT"]: + title += f" - {event['subtitle']}" + dl.dl_doc(doc, title, doc.get('detail'), subfolder) + + if event['has_docs']: + self.events_with_docs.append(event) + else: + self.events_without_docs.append(event) + + if self.received_detail == self.requested_detail: + self.log.info('Received all details') + dl.output_path.mkdir(parents=True, exist_ok=True) + with open(dl.output_path / 'other_events.json', 'w', encoding='utf-8') as f: + json.dump(self.events_without_docs, f, ensure_ascii=False, indent=2) + + with open(dl.output_path / 'events_with_documents.json', 'w', encoding='utf-8') as f: + json.dump(self.events_with_docs, f, ensure_ascii=False, indent=2) + + with open(dl.output_path / 'all_events.json', 'w', encoding='utf-8') as f: + json.dump(self.events_without_docs + self.events_with_docs, f, ensure_ascii=False, indent=2) + + export_transactions(dl.output_path / 'all_events.json', dl.output_path / 'account_transactions.csv') + + dl.work_responses() diff --git a/pytr/transactions.py b/pytr/transactions.py new file mode 100644 index 0000000..f83600a --- /dev/null +++ b/pytr/transactions.py @@ -0,0 +1,83 @@ +from locale import getdefaultlocale +from babel.numbers import format_decimal +import json + +from .event import Event +from .utils import get_logger +from .translation import setup_translation + + +def export_transactions(input_path, output_path, lang="auto"): + """ + Create a CSV with the deposits and removals ready for importing into Portfolio Performance + The CSV headers for PP are language dependend + + i18n source from Portfolio Performance: + https://github.com/buchen/portfolio/blob/93b73cf69a00b1b7feb136110a51504bede737aa/name.abuchen.portfolio/src/name/abuchen/portfolio/messages_de.properties + https://github.com/buchen/portfolio/blob/effa5b7baf9a918e1b5fe83942ddc480e0fd48b9/name.abuchen.portfolio/src/name/abuchen/portfolio/model/labels_de.properties + + """ + log = get_logger(__name__) + if lang == "auto": + locale = getdefaultlocale()[0] + if locale is None: + lang = "en" + else: + lang = locale.split("_")[0] + + if lang not in [ + "cs", + "da", + "de", + "en", + "es", + "fr", + "it", + "nl", + "pl", + "pt", + "ru", + "zh", + ]: + log.info(f"Language not yet supported {lang}") + lang = "en" + _ = setup_translation(language=lang) + + # Read relevant deposit timeline entries + with open(input_path, encoding="utf-8") as f: + timeline = json.load(f) + + log.info("Write deposit entries") + with open(output_path, "w", encoding="utf-8") as f: + csv_fmt = "{date};{type};{value};{note};{isin};{shares}\n" + header = csv_fmt.format( + date=_("CSVColumn_Date"), + type=_("CSVColumn_Type"), + value=_("CSVColumn_Value"), + note=_("CSVColumn_Note"), + isin=_("CSVColumn_ISIN"), + shares=_("CSVColumn_Shares"), + ) + f.write(header) + + for event_json in timeline: + event = Event(event_json) + if not event.is_pp_relevant: + continue + + amount = format_decimal(event.amount, locale=lang) if event.amount else "" + note = (_(event.note) + " - " + event.title) if event.note else event.title + shares = format_decimal(event.shares, locale=lang) if event.shares else "" + + f.write( + csv_fmt.format( + date=event.date, + type=_(event.pp_type), + value=amount, + note=note, + isin=event.isin, + shares=shares, + ) + ) + + log.info("Deposit creation finished!") diff --git a/pytr/translation.py b/pytr/translation.py new file mode 100644 index 0000000..7754492 --- /dev/null +++ b/pytr/translation.py @@ -0,0 +1,21 @@ +import gettext +import os + +from .utils import get_logger + +log = get_logger(__name__) + + +def setup_translation(language="en"): + """Set up translations for the specified language.""" + # Get the absolute path of the locale directory + locale_dir = os.path.join( + os.path.dirname(__file__), ".", "locale" + ) # Works only with pip install -e . + # Set the locale directory and the language + lang = gettext.translation( + "messages", localedir=locale_dir, languages=[language], fallback=True + ) + lang.install() + + return lambda x: lang.gettext(x) if len(x) > 0 else "" diff --git a/pytr/utils.py b/pytr/utils.py index 1e77bdd..c235a42 100644 --- a/pytr/utils.py +++ b/pytr/utils.py @@ -4,8 +4,7 @@ import json import logging import requests -from datetime import datetime -from locale import getdefaultlocale + from packaging import version log_level = None @@ -90,393 +89,3 @@ def check_version(installed_version): log.warning(f'Installed pytr version ({installed_version}) is outdated. Latest version is {latest_version}') else: log.info('pytr is up to date') - - -def export_transactions(input_path, output_path, lang='auto'): - ''' - Create a CSV with the deposits and removals ready for importing into Portfolio Performance - The CSV headers for PP are language dependend - - i18n source from Portfolio Performance: - https://github.com/buchen/portfolio/blob/93b73cf69a00b1b7feb136110a51504bede737aa/name.abuchen.portfolio/src/name/abuchen/portfolio/messages_de.properties - https://github.com/buchen/portfolio/blob/effa5b7baf9a918e1b5fe83942ddc480e0fd48b9/name.abuchen.portfolio/src/name/abuchen/portfolio/model/labels_de.properties - - ''' - log = get_logger(__name__) - if lang == 'auto': - locale = getdefaultlocale()[0] - if locale is None: - lang = 'en' - else: - lang = locale.split('_')[0] - - if lang not in ['cs', 'de', 'en', 'es', 'fr', 'it', 'nl', 'pt', 'ru']: - lang = 'en' - - i18n = { - "date": { - "cs": "Datum", - "de": "Datum", - "en": "Date", - "es": "Fecha", - "fr": "Date", - "it": "Data", - "nl": "Datum", - "pt": "Data", - "ru": "\u0414\u0430\u0442\u0430", - }, - "type": { - "cs": "Typ", - "de": "Typ", - "en": "Type", - "es": "Tipo", - "fr": "Type", - "it": "Tipo", - "nl": "Type", - "pt": "Tipo", - "ru": "\u0422\u0438\u043F", - }, - "value": { - "cs": "Hodnota", - "de": "Wert", - "en": "Value", - "es": "Valor", - "fr": "Valeur", - "it": "Valore", - "nl": "Waarde", - "pt": "Valor", - "ru": "\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435", - }, - "note": { - "cs": "Poznámka", - "de": "Notiz", - "en": "Note", - "es": "Nota", - "fr": "Note", - "it": "Nota", - "nl": "Noot", - "pt": "Nota", - "ru": "\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435", - }, - "deposit": { - "cs": 'Vklad', - "de": 'Einlage', - "en": 'Deposit', - "es": 'Dep\u00F3sito', - "fr": 'D\u00E9p\u00F4t', - "it": 'Deposito', - "nl": 'Storting', - "pt": 'Dep\u00F3sito', - "ru": '\u041F\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435', - }, - "removal": { - "cs": 'V\u00FDb\u011Br', - "de": 'Entnahme', - "en": 'Removal', - "es": 'Removal', - "fr": 'Retrait', - "it": 'Prelievo', - "nl": 'Opname', - "pt": 'Levantamento', - "ru": '\u0421\u043F\u0438\u0441\u0430\u043D\u0438\u0435', - }, - "interest": { - "cs": 'Úrokové poplatky', - "de": 'Zinsen', - "en": 'Interest', - "es": 'Interés', - "fr": 'L\'intérêts', - "it": 'Interessi', - "nl": 'Interest', - "pt": 'Odsetki', - "ru": '\u041f\u0440\u043e\u0446\u0435\u0301\u043d\u0442\u044b', - }, - "card transaction": { - "cs": 'Platba kartou', - "de": 'Kartentransaktion', - "en": 'Card Transaction', - "es": 'Transacción con tarjeta', - "fr": 'Transaction par carte', - "it": 'Transazione con carta', - "nl": 'Kaarttransactie', - "pt": 'Transakcja kartą', - "ru": '\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0020\u043f\u043e\u0020\u043a\u0430\u0440\u0442\u0435', - }, - "card atm withdrawal": { - "cs": 'Výběr hotovosti', - "de": 'Barabhebung', - "en": 'ATM withdrawal', - "es": 'Retiradas de efectivo', - "fr": 'Retrait en espèces', - "it": 'Prelievo di contanti', - "nl": 'Geldopname', - "pt": 'Levantamento de dinheiro', - "ru": '\u0412\u044b\u0434\u0430\u0447\u0430\u0020\u043d\u0430\u043b\u0438\u0447\u043d\u044b\u0445', - }, - "card order": { - "cs": 'Poplatek za kartu', - "de": 'Kartengebühr', - "en": 'Card fee', - "es": 'Transacción con tarjeta', - "fr": 'Frais de carte', - "it": 'Tassa sulla carta', - "nl": 'Kosten kaart', - "pt": 'Taxa do cartão', - "ru": '\u041f\u043b\u0430\u0442\u0430\u0020\u0437\u0430\u0020\u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435\u0020\u043a\u0430\u0440\u0442\u044b', - }, - "card refund": { - "cs": "Vrácení peněz na kartu", - "de": "Kartenerstattung", - "en": "Card refund", - "es": "Reembolso de tarjeta", - "fr": "Remboursement par carte", - "it": "Rimborso sulla carta", - "nl": "Terugbetaling op kaart", - "pt": "Reembolso do cartão", - "ru": "\u0412\u043e\u0437\u0432\u0440\u0430\u0442\u0020\u043d\u0430\u0020\u043a\u0430\u0440\u0442\u0443" - }, - "decimal dot": { - "cs": ',', - "de": ',', - "en": '.', - "es": ',', - "fr": ',', - "it": ',', - "nl": ',', - "pt": ',', - "ru": ',', - }, - "title": { - "cs": "Titul", - "de": "Titel", - "en": "Title", - "es": "Título", - "fr": "Titre", - "it": "Titolo", - "nl": "Titel", - "pt": "Título", - "ru": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a" - }, - } - # Read relevant deposit timeline entries - with open(input_path, encoding='utf-8') as f: - timeline = json.load(f) - - # Write deposit_transactions.csv file - # date, transaction, shares, amount, total, fee, isin, name - log.info('Write deposit entries') - with open(output_path, 'w', encoding='utf-8') as f: - # f.write('Datum;Typ;Stück;amount;Wert;Gebühren;ISIN;name\n') - csv_fmt = '{date};{type};{value};{note};{title}\n' - header = csv_fmt.format(date=i18n['date'][lang], type=i18n['type'][lang], value=i18n['value'][lang], note=i18n['note'][lang], title=i18n['title'][lang]) - f.write(header) - - for event in timeline: - dateTime = datetime.fromisoformat(event['timestamp'][:19]) - date = dateTime.strftime('%Y-%m-%d') - - title = event['title'] - try: - body = event['body'] - except KeyError: - body = '' - - if 'storniert' in body: - continue - - try: - decdot = i18n['decimal dot'][lang] - amount = str(abs(event['amount']['value'])).replace('.', decdot) - except (KeyError, TypeError): - continue - - # Cash in - if event["eventType"] in ("PAYMENT_INBOUND", "PAYMENT_INBOUND_SEPA_DIRECT_DEBIT"): - f.write(csv_fmt.format(date=date, type=i18n['deposit'][lang], value=amount, note='', title=title)) - elif event["eventType"] == "PAYMENT_OUTBOUND": - f.write(csv_fmt.format(date=date, type=i18n['removal'][lang], value=amount, note='', title=title)) - elif event["eventType"] == "INTEREST_PAYOUT_CREATED": - f.write(csv_fmt.format(date=date, type=i18n['interest'][lang], value=amount, note='', title=title)) - # Dividend - Shares - elif title == 'Reinvestierung': - # TODO: Implement reinvestment - log.warning('Detected reivestment, skipping... (not implemented yet)') - elif event["eventType"] == "card_successful_transaction": - f.write(csv_fmt.format(date=date, type=i18n['removal'][lang], value=amount, note=i18n['card transaction'][lang], title=title)) - elif event["eventType"] == "card_successful_atm_withdrawal": - f.write(csv_fmt.format(date=date, type=i18n['removal'][lang], value=amount, note=i18n['card atm withdrawal'][lang], title=title)) - elif event["eventType"] == "card_order_billed": - f.write(csv_fmt.format(date=date, type=i18n['removal'][lang], value=amount, note=i18n['card order'][lang], title=title)) - elif event["eventType"] == "card_refund": - f.write(csv_fmt.format(date=date, type=i18n['deposit'][lang], value=amount, note=i18n['card refund'][lang], title=title)) - - log.info('Deposit creation finished!') - - -class Timeline: - def __init__(self, tr, max_age_timestamp): - self.tr = tr - self.log = get_logger(__name__) - self.received_detail = 0 - self.requested_detail = 0 - self.events_without_docs = [] - self.events_with_docs = [] - self.num_timelines = 0 - self.timeline_events = {} - self.max_age_timestamp = max_age_timestamp - - async def get_next_timeline_transactions(self, response=None): - ''' - Get timelines transactions and save time in list timelines. - Extract timeline transactions events and save them in list timeline_events - - ''' - if response is None: - # empty response / first timeline - self.log.info('Subscribing to #1 timeline transactions') - self.num_timelines = 0 - await self.tr.timeline_transactions() - else: - self.num_timelines += 1 - added_last_event = True - for event in response['items']: - if self.max_age_timestamp == 0 or datetime.fromisoformat(event['timestamp'][:19]).timestamp() >= self.max_age_timestamp: - event['source'] = "timelineTransaction" - self.timeline_events[event['id']] = event - else: - added_last_event = False - break - - self.log.info( - f'Received #{self.num_timelines:<2} timeline transactions' - ) - after = response['cursors'].get('after') - if (after is not None) and added_last_event: - self.log.info( - f'Subscribing #{self.num_timelines+1:<2} timeline transactions' - ) - await self.tr.timeline_transactions(after) - else: - # last timeline is reached - self.log.info('Received last relevant timeline transaction') - await self.get_next_timeline_activity_log() - - - async def get_next_timeline_activity_log(self, response=None): - ''' - Get timelines acvtivity log and save time in list timelines. - Extract timeline acvtivity log events and save them in list timeline_events - - ''' - if response is None: - # empty response / first timeline - self.log.info('Awaiting #1 timeline activity log') - self.num_timelines = 0 - await self.tr.timeline_activity_log() - else: - self.num_timelines += 1 - added_last_event = True - for event in response['items']: - if self.max_age_timestamp == 0 or datetime.fromisoformat(event['timestamp'][:19]).timestamp() >= self.max_age_timestamp: - if event['id'] in self.timeline_events: - self.log.warning(f"Received duplicate event {event['id'] }") - event['source'] = "timelineActivity" - self.timeline_events[event['id']] = event - else: - added_last_event = False - break - - self.log.info(f'Received #{self.num_timelines:<2} timeline activity log') - after = response['cursors'].get('after') - if (after is not None) and added_last_event: - self.log.info( - f'Subscribing #{self.num_timelines+1:<2} timeline activity log' - ) - await self.tr.timeline_activity_log(after) - else: - self.log.info('Received last relevant timeline activity log') - await self._get_timeline_details() - - async def _get_timeline_details(self): - ''' - request timeline details - ''' - for event in self.timeline_events.values(): - action = event.get('action') - msg = '' - if action is None: - if event.get('actionLabel') is None: - msg += 'Skip: no action' - elif action.get('type') != 'timelineDetail': - msg += f"Skip: action type unmatched ({action['type']})" - elif action.get('payload') != event['id']: - msg += f"Skip: payload unmatched ({action['payload']})" - - if msg != '': - self.events_without_docs.append(event) - self.log.debug(f"{msg} {event['title']}: {event.get('body')} ") - else: - self.requested_detail += 1 - await self.tr.timeline_detail_v2(event['id']) - self.log.info('All timeline details requested') - return False - - async def process_timelineDetail(self, response, dl): - ''' - process timeline details response - download any associated docs - create other_events.json, events_with_documents.json and account_transactions.csv - ''' - - self.received_detail += 1 - event = self.timeline_events[response['id']] - event['details'] = response - - max_details_digits = len(str(self.requested_detail)) - self.log.info( - f"{self.received_detail:>{max_details_digits}}/{self.requested_detail}: " - + f"{event['title']} -- {event['subtitle']} - {event['timestamp'][:19]}" - ) - - subfolder = { - 'benefits_saveback_execution': 'Saveback', - 'benefits_spare_change_execution': 'RoundUp', - 'ssp_corporate_action_invoice_cash': 'Dividende', - 'CREDIT': 'Dividende', - 'INTEREST_PAYOUT_CREATED': 'Zinsen', - "SAVINGS_PLAN_EXECUTED":'Sparplan' - }.get(event["eventType"]) - - event['has_docs'] = False - for section in response['sections']: - if section['type'] != 'documents': - continue - for doc in section['data']: - event['has_docs'] = True - try: - timestamp = datetime.strptime(doc['detail'], '%d.%m.%Y').timestamp() - except (ValueError, KeyError): - timestamp = datetime.now().timestamp() - if self.max_age_timestamp == 0 or self.max_age_timestamp < timestamp: - title = f"{doc['title']} - {event['title']}" - if event['eventType'] in ["ACCOUNT_TRANSFER_INCOMING", "ACCOUNT_TRANSFER_OUTGOING", "CREDIT"]: - title += f" - {event['subtitle']}" - dl.dl_doc(doc, title, doc.get('detail'), subfolder) - - if event['has_docs']: - self.events_with_docs.append(event) - else: - self.events_without_docs.append(event) - - if self.received_detail == self.requested_detail: - self.log.info('Received all details') - dl.output_path.mkdir(parents=True, exist_ok=True) - with open(dl.output_path / 'other_events.json', 'w', encoding='utf-8') as f: - json.dump(self.events_without_docs, f, ensure_ascii=False, indent=2) - - with open(dl.output_path / 'events_with_documents.json', 'w', encoding='utf-8') as f: - json.dump(self.events_with_docs, f, ensure_ascii=False, indent=2) - - export_transactions(dl.output_path / 'events_with_documents.json', dl.output_path / 'account_transactions.csv') - - dl.work_responses() diff --git a/setup.py b/setup.py index 97089f9..a7634de 100644 --- a/setup.py +++ b/setup.py @@ -1,50 +1,20 @@ -from pathlib import Path +import os +import subprocess from setuptools import setup +from setuptools.command.build_py import build_py - -def readme(): - this_directory = Path(__file__).parent.resolve() - with open(this_directory / 'README.md', encoding='utf-8') as f: - return f.read() - +class BuildWithCompile(build_py): + def run(self): + locale_dir = os.path.abspath('pytr/locale') + if not os.path.exists(locale_dir): + raise FileNotFoundError(f"The locale directory '{locale_dir}' does not exist.") + try: + subprocess.check_call(['pybabel', 'compile', '-d', locale_dir]) + except subprocess.CalledProcessError as e: + print(f"Error while compiling catalog: {e}") + raise + build_py.run(self) setup( - name='pytr', - version='0.2.1', - description='Use TradeRepublic in terminal', - long_description=readme(), - long_description_content_type='text/markdown', - url='https://gitlab.com/pytr-org/pytr/', - author='marzzzello', - author_email='853485-marzzzello@users.noreply.gitlab.com', - license='MIT', - packages=['pytr'], - python_requires='>=3.8', - entry_points={ - 'console_scripts': [ - 'pytr = pytr.main:main', - ], - }, - # scripts=['traderep'], - # install_requires=['py_tr'], - install_requires=[ - 'certifi', - 'coloredlogs', - 'ecdsa', - 'packaging', - 'pathvalidate', - 'pygments', - 'requests_futures', - 'shtab', - 'websockets>=10.1', - ], - classifiers=[ - "License :: OSI Approved :: MIT License", - 'Programming Language :: Python :: 3 :: Only', - "Operating System :: OS Independent", - 'Development Status :: 3 - Alpha', - "Topic :: Office/Business :: Financial", - "Topic :: Office/Business :: Financial :: Investment", - ], - zip_safe=False, + cmdclass={'build_py': BuildWithCompile} )