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

Fix fints login #755

Merged
merged 7 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading