Allow fints config as fallback for account type (#75680)

This commit is contained in:
Benjamin Richter 2022-10-16 04:01:54 +02:00 committed by GitHub
parent 3c48ce9ee7
commit e1cf261379
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,10 +3,12 @@ from __future__ import annotations
from collections import namedtuple
from datetime import timedelta
from functools import cached_property
import logging
from typing import Any
from fints.client import FinTS3PinTanClient
from fints.models import SEPAAccount
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
@ -77,7 +79,7 @@ def setup_platform(
acc[CONF_ACCOUNT]: acc[CONF_NAME] for acc in config[CONF_HOLDINGS]
}
client = FinTsClient(credentials, fints_name)
client = FinTsClient(credentials, fints_name, account_config, holdings_config)
balance_accounts, holdings_accounts = client.detect_accounts()
accounts: list[SensorEntity] = []
@ -115,21 +117,27 @@ class FinTsClient:
Use this class as Context Manager to get the FinTS3Client object.
"""
def __init__(self, credentials: BankCredentials, name: str) -> None:
def __init__(
self,
credentials: BankCredentials,
name: str,
account_config: dict,
holdings_config: dict,
) -> None:
"""Initialize a FinTsClient."""
self._credentials = credentials
self._account_information: dict[str, dict] = {}
self._account_information_fetched = False
self.name = name
self.account_config = account_config
self.holdings_config = holdings_config
@property
def client(self):
"""Get the client object.
@cached_property
def client(self) -> FinTS3PinTanClient:
"""Get the FinTS client object.
As the fints library is stateless, there is not benefit in caching
the client objects. If that ever changes, consider caching the client
object and also think about potential concurrency problems.
Note: As of version 2, the fints library is not stateless anymore.
This should be considered when reworking this integration.
The FinTS library persists the current dialog with the bank
and stores bank capabilities. So caching the client is beneficial.
"""
return FinTS3PinTanClient(
@ -139,26 +147,77 @@ class FinTsClient:
self._credentials.url,
)
def detect_accounts(self):
"""Identify the accounts of the bank."""
def get_account_information(self, iban: str) -> dict | None:
"""Get a dictionary of account IBANs as key and account information as value."""
bank = self.client
accounts = bank.get_sepa_accounts()
account_types = {
x["iban"]: x["type"]
for x in bank.get_information()["accounts"]
if x["iban"] is not None
}
if not self._account_information_fetched:
self._account_information = {
account["iban"]: account
for account in self.client.get_information()["accounts"]
}
self._account_information_fetched = True
return self._account_information.get(iban, None)
def is_balance_account(self, account: SEPAAccount) -> bool:
"""Determine if the given account is of type balance account."""
if not account.iban:
return False
account_information = self.get_account_information(account.iban)
if not account_information:
return False
if not account_information["type"]:
# bank does not support account types, use value from config
if (
account_information["iban"] in self.account_config
or account_information["account_number"] in self.account_config
):
return True
elif 1 <= account_information["type"] <= 9:
return True
return False
def is_holdings_account(self, account: SEPAAccount) -> bool:
"""Determine if the given account of type holdings account."""
if not account.iban:
return False
account_information = self.get_account_information(account.iban)
if not account_information:
return False
if not account_information["type"]:
# bank does not support account types, use value from config
if (
account_information["iban"] in self.holdings_config
or account_information["account_number"] in self.holdings_config
):
return True
elif 30 <= account_information["type"] <= 39:
return True
return False
def detect_accounts(self) -> tuple[list, list]:
"""Identify the accounts of the bank."""
balance_accounts = []
holdings_accounts = []
for account in accounts:
account_type = account_types[account.iban]
if 1 <= account_type <= 9: # 1-9 is balance account
for account in self.client.get_sepa_accounts():
if self.is_balance_account(account):
balance_accounts.append(account)
elif 30 <= account_type <= 39: # 30-39 is holdings account
elif self.is_holdings_account(account):
holdings_accounts.append(account)
else:
_LOGGER.warning("Could not determine type of account %s", account.iban)
return balance_accounts, holdings_accounts