Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Customizable destination folder structure #103

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,16 @@ $ pytr login --phone_no +49123456789 --pin 1234
```

If no arguments are supplied pytr will look for them in the file `~/.pytr/credentials` (the first line must contain the phone number, the second line the pin). If the file doesn't exist pytr will ask for for the phone number and pin.

## Location and File names of the downloaded Documents
During the first run of the 'dl_docs' command a config file is created in the user home directory `<home>/.pytr/file_destination_config.yaml`.
The file contains destination patterns which describe where the file should be located and how the file name should look like. If a event/document matches the defined pattern it will be located in that specific `path` with the specified `filename`.

There are three mandatory patterns defined at the top:
* `default` - Defines only `filename` and is used for all other patterns if no "filename" is provided
* `unknown` - Defines `filename` and `path`, this is used when no match can be found for the event and the given document.
* `multiple_match` - If there are multiple matching patterns and the destination would be ambiguous, the document will be stored in the given `path` with the given `filename`

The other pattern can be as you like but keep in mind that patterns `path` and `filenames` should result in unique document names. If you see something like this `<filename> (some strange string)` the document path + name was not unique.

> Its also possible to copy the configuration file from `~/pytr/config/file_destination_config__template.yaml` to `<home>/.pytr/file_destination_config.yaml` and modify it before the first download to avoid that the download need to be performed a second time.
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ dependencies = [
"shtab",
"websockets>=10.1",
"babel",
"PyYAML",
"importlib_resources"
]

[project.scripts]
Expand Down
7 changes: 2 additions & 5 deletions pytr/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,15 @@
import ssl
import requests
import websockets

from ecdsa import NIST256p, SigningKey
from ecdsa.util import sigencode_der
from http.cookiejar import MozillaCookieJar

from pytr.utils import get_logger
from pytr.app_path import CREDENTIALS_FILE, COOKIES_FILE, KEY_FILE


home = pathlib.Path.home()
BASE_DIR = home / '.pytr'
CREDENTIALS_FILE = BASE_DIR / 'credentials'
KEY_FILE = BASE_DIR / 'keyfile.pem'
COOKIES_FILE = BASE_DIR / 'cookies.txt'


class TradeRepublicApi:
Expand Down
10 changes: 10 additions & 0 deletions pytr/app_path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import pathlib
Katzmann1983 marked this conversation as resolved.
Show resolved Hide resolved

home = pathlib.Path.home()
BASE_DIR = home / '.pytr'

CREDENTIALS_FILE = BASE_DIR / 'credentials'
KEY_FILE = BASE_DIR / 'keyfile.pem'
COOKIES_FILE = BASE_DIR / 'cookies.txt'

DESTINATION_CONFIG_FILE = BASE_DIR / 'file_destination_config.yaml'
Empty file added pytr/config/__init__.py
Empty file.
236 changes: 236 additions & 0 deletions pytr/config/file_destination_config__template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
destination:
################################################################################################
## Default and fallback patterns used for the destination of a downloaded document.
################################################################################################
# valid for all blocks without explicit filename
default:
filename: "{iso_date}.{iso_time} {event_title}" # {event_title} = Wertpapier-/ETF-/Produkt-Name

# if pattern not found, use this block
unknown:
path: "Unknown/{section_title}/"
filename: "{iso_date}.{iso_time} {event_type} - {event_subtitle} - {document_title} - {event_title}"

# if pattern found multiple times, use this block
multiple_match:
path: "MultipleMatch/{section_title}/"
filename: "{iso_date}.{iso_time} {event_type} - {event_subtitle} - {document_title} - {event_title}"
################################################################################################

################################################################################################
## Specific patterns for the destination of a downloaded document.
################################################################################################
# stocks
stock_order_settlement:
pattern: [
{event_type: "ORDER_EXECUTED", document_title: "Abrechnung(.\\d+)?"}, # mit limit verkauft
{event_type: "TRADE_INVOICE", document_title: "Abrechnung(.\\d+)?"}, # mit limit gekauft
{event_type: "STOCK_PERK_REFUNDED", document_title: "Abrechnung(.\\d+)?"}, # Aktiengeschenk
{event_type: "SHAREBOOKING", document_title: "Abrechnung(.\\d+)?"}, # Kapitalmassnahme
]
path: "Stocks/Settlement/{iso_date_year}/"

stock_order_cost_report:
pattern: [
{event_type: "ORDER_CREATED", document_title: "Kosteninformation(.\\d+)?"}, # limit erstellt
{event_type: "ORDER_EXECUTED", document_title: "Kosteninformation(.\\d+)?"},
{event_type: "TRADE_INVOICE", document_title: "Kosteninformation(.\\d+)?"},
{event_type: "STOCK_PERK_REFUNDED", document_title: "Kosteninformation(.\\d+)?"}, # Aktiengeschenk
{event_type: "EX_POST_COST_REPORT"},
]
path: "Stocks/Cost report/{iso_date_year}/"

stock_order_created:
pattern: [{event_type: "ORDER_CREATED", document_title: "Auftragsbestätigung(.\\d+)?"}, {event_type: "ORDER_EXECUTED", document_title: "Auftragsbestätigung(.\\d+)?"}, {event_type: "TRADE_INVOICE", document_title: "Auftragsbestätigung(.\\d+)?"}]
path: "Stocks/Order created/{iso_date_year}/"

stock_order_canceled:
pattern: [{event_type: "TRADE_CANCELED"}, {event_type: "ORDER_CANCELED"}]
path: "Stocks/Order canceled/{iso_date_year}/"

order_expired:
pattern: [{event_type: "ORDER_EXPIRED"}]
path: "Stocks/Order canceled/{iso_date_year}/"
filename: "{iso_date} {document_title}"

# Kapitalmaßnahmen
stock_notice_1:
pattern: [{event_type: "EXERCISE"}, {event_type: "SHAREBOOKING", document_title: "Ausführungsanzeige(.\\d+)?"}]
path: "Stocks/Notice/{iso_date_year}/"
filename: "{iso_date}.{iso_time} {event_subtitle} {event_title}"

# split for better readability
stock_notice_2:
pattern: [{event_type: "CORPORATE_ACTION"}, {event_type: "SHAREBOOKING_CANCELED"}]
path: "Stocks/Notice/{iso_date_year}/"
filename: "{iso_date}.{iso_time} {event_subtitle} {event_title}"

# split for better readability
stock_notice_3:
pattern: [
{event_type: "SHAREBOOKING_TRANSACTIONAL"},
{event_type: "INSTRUCTION_CORPORATE_ACTION", document_title: "Kundenanschreiben(.\\d+)?"}, #Kapitalerhöhung gegen Bar
]
path: "Stocks/Notice/{iso_date_year}/"
filename: "{iso_date}.{iso_time} {event_subtitle} {event_title}"

# split for better readability
stock_notice_4:
pattern:
[
{event_type: "ssp_corporate_action_invoice_shares", event_subtitle: "Spin-off"},
{event_type: "ssp_corporate_action_invoice_shares", event_subtitle: "Reverse Split"},
{event_type: "ssp_corporate_action_invoice_shares", event_subtitle: "Aktiendividende"},
{event_type: "ssp_corporate_action_invoice_shares", event_subtitle: "Zwischenvertrieb von Wertpapieren"},
{event_type: "ssp_corporate_action_informative_notification", event_subtitle: "Wechsel"},
{event_type: "ssp_corporate_action_informative_notification", event_subtitle: "Information"},
{event_type: "ssp_corporate_action_informative_notification", event_subtitle: "Aufruf von Zwischenpapieren"},
]
path: "Stocks/Notice/{iso_date_year}/"
filename: "{iso_date}.{iso_time} {event_subtitle} - {event_title}"

stock_report:
pattern: [{event_type: "QUARTERLY_REPORT", document_title: "Kontoauszug(.\\d+)?"}, {event_type: "QUARTERLY_REPORT", document_title: "Depotauszug(.\\d+)?"}, {event_type: "QUARTERLY_REPORT", document_title: "Cryptoauszug(.\\d+)?"}]
path: "Stocks/Report/{iso_date_year}/"
filename: "{iso_date} {document_title} {event_title}"

# General Meetings
stock_general_meetings:
pattern: [{event_type: "GENERAL_MEETING", document_title: "Hauptversammlung"}, {event_type: "ssp_corporate_action_informative_notification", event_subtitle: "Jährliche Hauptversammlung"}]
path: "Stocks/General Meetings/{iso_date_year}/"

stock_general_meetings_multiple_files:
pattern: [{event_type: "GENERAL_MEETING", document_title: "Hauptversammlung \\d+"}]
path: "Stocks/General Meetings/{iso_date_year}/"
filename: "{iso_date}.{iso_time} {event_title} - {document_title}"

stock_special_meetings:
pattern: [{event_type: "ssp_corporate_action_informative_notification", event_subtitle: "Außerordentliche oder spezielle Hauptversammlung"}]
path: "Stocks/General Meetings/{iso_date_year}/"
filename: "{iso_date}.{iso_time} {event_subtitle}"

# Savings plan
savings_plan:
pattern: [{event_type: "SAVINGS_PLAN_INVOICE_CREATED"}, {event_type: "SAVINGS_PLAN_EXECUTED"}, {event_type: "SAVINGS_PLAN_CANCELED"}]
path: "Stocks/Savings plan/{iso_date_year}/"

# pre-determined tax base earning
stock_pre_earning_tax:
pattern: [{event_type: "PRE_DETERMINED_TAX_BASE_EARNING"}]
path: "Stocks/PreEarningTax/{iso_date_year}/"

# Dividends
dividends_received:
pattern: [{event_type: "CREDIT", event_subtitle: "Dividende"}, {event_type: "CREDIT", event_subtitle: "Ausschüttung"}, {event_type: "CREDIT_CANCELED"}, {event_type: "ssp_corporate_action_invoice_cash"}]
path: "Dividends/{iso_date_year}/"

# Dividends Corporate action election
dividends_election:
pattern: [{event_type: "INSTRUCTION_CORPORATE_ACTION", document_title: "Dividende Wahlweise(.\\d+)?"}, {event_type: "ssp_dividend_option_customer_instruction", event_subtitle: "Cash oder Aktie"}, {event_type: "ssp_corporate_action_informative_notification", event_subtitle: "Dividende Wahlweise"}]
path: "Dividendelection/{iso_date_year}/"

# bonds
bond_repayment:
pattern: [{event_type: "REPAYMENT"}]
path: "Bonds/{iso_date_year}/"
filename: "{iso_date}.{iso_time} Repayment {event_title}"

bond_interest:
pattern: [{event_type: "COUPON_PAYMENT"}]
path: "Bonds/{iso_date_year}/"
filename: "{iso_date}.{iso_time} Interest {event_title}"

# Saveback
saveback_enabled:
pattern: [{event_type: "benefits_saveback_execution", document_title: "Enabled(.\\d+)?"}]
path: "Saveback/{iso_date_year}/"
filename: "{iso_date}.{iso_time} Enabled {event_title}"

saveback_executed:
pattern: [{event_type: "benefits_saveback_execution", document_title: "Abrechnung Ausführung(.\\d+)?"}]
path: "Saveback/{iso_date_year}/"
filename: "{iso_date}.{iso_time} Report {event_title}"

saveback_cost_report:
pattern: [{event_type: "benefits_saveback_execution", document_title: "Kosteninformation(.\\d+)?"}]
path: "Saveback/{iso_date_year}/"
filename: "{iso_date}.{iso_time} Cost report {event_title}"

# Round up
roundup_enabled:
pattern: [{event_type: "benefits_spare_change_execution", document_title: "Enabled(.\\d+)?"}] # same files - multiple times at once
path: "Roundup/{iso_date_year}/"
filename: "{iso_date}.{iso_time} Enabled {event_title}"

roundup_executed:
pattern: [{event_type: "benefits_spare_change_execution", document_title: "Abrechnung Ausführung(.\\d+)?"}]
path: "Roundup/{iso_date_year}/"
filename: "{iso_date}.{iso_time} Report {event_title}"

roundup_cost_report:
pattern: [{event_type: "benefits_spare_change_execution", document_title: "Kosteninformation(.\\d+)?"}]
path: "Roundup/{iso_date_year}/"
filename: "{iso_date}.{iso_time} Cost report {event_title}"

# account
cash_interest:
pattern: [{event_type: "INTEREST_PAYOUT"}, {event_type: "INTEREST_PAYOUT_CREATED"}]
path: "Cash Interest/"
filename: "{iso_date} Report"

cash_transfer_report:
pattern: [{event_type: "INCOMING_TRANSFER"}, {event_type: "PAYMENT_INBOUND_GOOGLE_PAY"}, {event_type: "PAYMENT_INBOUND_CREDIT_CARD"}]
path: "Cash Report/"
filename: "{iso_date}.{iso_time} {document_title}" # {event_title} = Personal name

# annual tax report for account
account_tax_report:
pattern: [{event_type: "TAX_REFUND"}, {event_type: "TAX_ENGINE_ANNUAL_REPORT"}, {event_type: "YEAR_END_TAX_REPORT"}]
path: "Tax/"
filename: "{iso_date} {document_title}"

account_tax_adjustment:
pattern: [{event_type: "ssp_tax_correction_invoice"}, {event_type: "TAX_CORRECTION"}]
path: "Tax/"
filename: "{iso_date} {event_title}"

# common informations
notice_stocks:
pattern: [{event_type: "ORDER_CREATED", document_title: "Basisinformationsblatt(.\\d+)?"}]
path: "Notice/{iso_date_year}/"
filename: "{iso_date} {document_title} - {event_title}"

notice_stocks2:
pattern: [{event_type: "TRADE_INVOICE", document_title: "Basisinformationsblatt(.\\d+)?"}, {event_type: "GESH_CORPORATE_ACTION", event_subtitle: "Unternehmensmeldung"}]
path: "Notice/{iso_date_year}/"
filename: "{iso_date} {event_subtitle} - {event_title}"

notice_stocks3:
pattern: [{event_type: "CUSTOMER_CREATED"}]
path: "Notice/{iso_date_year}/"
filename: "{iso_date} {document_title}"

notice_option_contract:
pattern: [{event_type: "ORDER_EXECUTED", document_title: "Basisinformationsblatt(.\\d+)?"}]
path: "Notice/{iso_date_year}/"
filename: "{iso_date} {document_title} Option"

notice_multiple_documents:
pattern: [{event_type: "GESH_CORPORATE_ACTION_MULTIPLE_POSITIONS"}] #event_subtitle: Gesellschaftshinweis
path: "Notice/{iso_date_year}/"
filename: "{iso_date} {event_subtitle} - {event_title} - {document_title}"

contract_documents:
pattern: [
{event_type: "card_order_billed"}, # Bestellung Trade Republic Karte
{event_type: "DOCUMENTS_CREATED"}, # Basisinformationen über Wertpapiere
{event_type: "DOCUMENTS_ACCEPTED"}, # Rechtliche Dokumente: Kundenvereinbarung / Vorvertragliche Informationen / Datenschutzinformationen* / Widerrufsbelehrung* / *Crypto* / Risikohinweise
{event_type: "DOCUMENTS_CHANGED", section_title: "Dokumente"}, # Rechtliche Dokumente: Kundenvereinbarung
]
path: "Contract/"
filename: "{iso_date} {event_title} - {document_title}"

contract_documents_updated:
pattern: [{event_type: "DOCUMENTS_CHANGED", section_title: "Aktualisierte Dokumente"}] # aktualisierte Rechtliche Dokumente: Kundenvereinbarung
path: "Contract/"
filename: "{iso_date} {event_title} - {document_title} updated"
Loading