mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Allow fints config as fallback for account type (#75680)
This commit is contained in:
parent
3c48ce9ee7
commit
e1cf261379
@ -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
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user