Skip to content

Commit

Permalink
Merge branch 'fix_fints_login' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
FestplattenSchnitzel committed Sep 30, 2024
2 parents f9e7bfc + 4b23632 commit a6c0665
Show file tree
Hide file tree
Showing 10 changed files with 376 additions and 118 deletions.
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# https://github.com/casey/just#packages

# execute `just --evaluate <var>` to check the values of the variables set below
drc := if `docker compose 2>&1 >/dev/null; echo $?` == "0" { "docker compose" } else { "docker-compose" }
drc := "docker compose"
export COMPOSE_FILE := "docker-compose.dev.yml:docker-compose.test.yml"
export PGPASSFILE := ".pycroft.pgpass"
psql_pycroft_uri := "postgresql:///pycroft?options=-csearch_path%3Dpycroft,public"
Expand Down
30 changes: 19 additions & 11 deletions pycroft/lib/finance/fints.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# This file is part of the Pycroft project and licensed under the terms of
# the Apache License, Version 2.0. See the LICENSE file for details

import typing as t
from datetime import date

from mt940.models import Transaction as MT940Transaction
Expand All @@ -10,30 +11,37 @@
from pycroft.model.finance import BankAccount


def get_fints_transactions(
def get_fints_client(
*,
product_id: str,
user_id: int,
user_id: str,
secret_pin: str,
bank_account: BankAccount,
**kwargs: t.Any,
) -> FinTS3Client:
return FinTS3Client(
bank_identifier=bank_account.routing_number,
user_id=user_id,
pin=secret_pin,
server=bank_account.fints_endpoint,
product_id=product_id,
**kwargs,
)


def get_fints_transactions(
*,
start_date: date,
end_date: date,
FinTSClient: type[FinTS3Client] = FinTS3Client,
bank_account: BankAccount,
fints_client: FinTS3Client,
) -> tuple[list[MT940Transaction], list[StatementError]]:
"""Get the transactions from FinTS
External service dependencies:
- FinTS (:module:`pycroft.external_services.fints`)
"""
# login with fints
fints_client = FinTSClient(
bank_identifier=bank_account.routing_number,
user_id=user_id,
pin=secret_pin,
server=bank_account.fints_endpoint,
product_id=product_id,
)
acc = next(
(a for a in fints_client.get_sepa_accounts() if a.iban == bank_account.iban),
None,
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ module = [
"pycroft.lib.mail",
"pycroft.lib.user",
"pycroft.lib.user.*",
"web.blueprints.finance",
"web.blueprints.finance.*",
]
strict_optional = true

Expand Down
89 changes: 55 additions & 34 deletions tests/external_services/test_fints.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,61 @@
from tests.factories.finance import BankAccountFactory as BankAccountFactory_


def test_fints_connection(default_fints_client_args, default_transaction_args):
bank_account = BankAccountFactory.build(iban="DE61850503003120219540")
fints_client = StubFintsClient(
**default_fints_client_args,
bank_identifier=bank_account.routing_number,
server=bank_account.fints_endpoint,
)

transactions, errors = get_fints_transactions(
**default_transaction_args,
bank_account=bank_account,
fints_client=fints_client,
)
assert transactions == []
assert errors == []


def test_transactions_unknown_iban(default_fints_client_args, default_transaction_args):
bank_account = BankAccountFactory.build()
fints_client = StubFintsClient(
**default_fints_client_args,
bank_identifier=bank_account.routing_number,
server=bank_account.fints_endpoint,
)

with pytest.raises(KeyError, match="BankAccount with IBAN.*not found"):
get_fints_transactions(
**default_transaction_args,
bank_account=bank_account,
fints_client=fints_client,
)


@pytest.fixture(scope="session")
def default_transaction_args() -> dict:
return {
"start_date": today() - timedelta(days=30),
"end_date": today(),
}


@pytest.fixture(scope="session")
def default_fints_client_args() -> dict:
return {
"product_id": "1",
"user_id": 1,
"pin": "123456",
}


class BankAccountFactory(BankAccountFactory_):
fints_endpoint = "https://banking-sn5.s-fints-pt-sn.de/fints30"
routing_number = "85050300"


class StubHTTPSConnection(FinTSHTTPSConnection):
def send(self, msg: FinTSMessage):
# response = base64.b64decode(r.content.decode('iso-8859-1'))
Expand Down Expand Up @@ -60,37 +115,3 @@ def get_sepa_accounts(self):

def _find_highest_supported_command(self, *segment_classes, **kwargs):
return segment_classes[-1]


class BankAccountFactory(BankAccountFactory_):
fints_endpoint = "https://banking-sn5.s-fints-pt-sn.de/fints30"
routing_number = "85050300"


@pytest.fixture(scope="session")
def default_transaction_args() -> dict:
return {
"product_id": "1",
"user_id": 1,
"secret_pin": "123456",
"start_date": today() - timedelta(days=30),
"end_date": today(),
"FinTSClient": StubFintsClient,
}


def test_fints_connection(default_transaction_args):
transactions, errors = get_fints_transactions(
**default_transaction_args,
bank_account=BankAccountFactory.build(iban="DE61850503003120219540"),
)
assert transactions == []
assert errors == []


def test_transactions_unknown_iban(default_transaction_args):
with pytest.raises(KeyError, match="BankAccount with IBAN.*not found"):
get_fints_transactions(
**default_transaction_args,
bank_account=BankAccountFactory.build(),
)
Loading

0 comments on commit a6c0665

Please sign in to comment.