Ingest comdirect #5
+7
-2
@@ -95,12 +95,15 @@ def _parse_date_german(date_str: str) -> date | None:
|
|||||||
day, month, year = list(map(int, date_str.split(".")))
|
day, month, year = list(map(int, date_str.split(".")))
|
||||||
return date(day=day, month=month, year=year)
|
return date(day=day, month=month, year=year)
|
||||||
|
|
||||||
|
|
||||||
def _parse_decimal_german(decimal_str: str) -> Decimal:
|
def _parse_decimal_german(decimal_str: str) -> Decimal:
|
||||||
return Decimal(decimal_str.replace(".", "").replace(",", "."))
|
return Decimal(decimal_str.replace(".", "").replace(",", "."))
|
||||||
|
|
||||||
|
|
||||||
class ComdirectBase(BaseModel):
|
class ComdirectBase(BaseModel):
|
||||||
date_val: date | None = Field(alias="Wertstellung (Valuta)", examples=["07.09.2026"])
|
date_val: date | None = Field(
|
||||||
|
alias="Wertstellung (Valuta)", examples=["07.09.2026"]
|
||||||
|
)
|
||||||
amount_eur: Decimal = Field(alias="Umsatz in EUR", examples=["32,43"])
|
amount_eur: Decimal = Field(alias="Umsatz in EUR", examples=["32,43"])
|
||||||
|
|
||||||
@field_validator("date_val", mode="before")
|
@field_validator("date_val", mode="before")
|
||||||
@@ -138,7 +141,9 @@ class ComdirectCreditCard(ComdirectGiro):
|
|||||||
)
|
)
|
||||||
reference: str = Field(alias="Referenz", default="")
|
reference: str = Field(alias="Referenz", default="")
|
||||||
text: str = Field(alias="Buchungstext", default="")
|
text: str = Field(alias="Buchungstext", default="")
|
||||||
amount_eur: Decimal | None = Field(alias="Umsatz in EUR", examples=["32,43"], default=None)
|
amount_eur: Decimal | None = Field(
|
||||||
|
alias="Umsatz in EUR", examples=["32,43"], default=None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ComdirectDepot(ComdirectBase):
|
class ComdirectDepot(ComdirectBase):
|
||||||
|
|||||||
+3
-1
@@ -18,11 +18,11 @@ def reader_b4w(path: Path):
|
|||||||
return list(map(B4wExport.model_validate, raw))
|
return list(map(B4wExport.model_validate, raw))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PATTERN_ACCOUNT_NAME = r'^"Umsätze ([^"]+)";"Zeitraum: .*$'
|
PATTERN_ACCOUNT_NAME = r'^"Umsätze ([^"]+)";"Zeitraum: .*$'
|
||||||
PATTERN_HEADER = r'"([^"]+)"'
|
PATTERN_HEADER = r'"([^"]+)"'
|
||||||
PATTERN_DATA = r'"([^"]+)"'
|
PATTERN_DATA = r'"([^"]+)"'
|
||||||
|
|
||||||
|
|
||||||
class EXPECT_LINE(Enum):
|
class EXPECT_LINE(Enum):
|
||||||
ACCOUNT_NAME = auto()
|
ACCOUNT_NAME = auto()
|
||||||
BLANK = auto()
|
BLANK = auto()
|
||||||
@@ -33,6 +33,7 @@ class EXPECT_LINE(Enum):
|
|||||||
COMDIRECT_ACCOUNTS = BANK_ACCOUNTS.get("comdirect", {})
|
COMDIRECT_ACCOUNTS = BANK_ACCOUNTS.get("comdirect", {})
|
||||||
assert isinstance(COMDIRECT_ACCOUNTS, dict)
|
assert isinstance(COMDIRECT_ACCOUNTS, dict)
|
||||||
|
|
||||||
|
|
||||||
def reader_comdirect(path: Path):
|
def reader_comdirect(path: Path):
|
||||||
result = {}
|
result = {}
|
||||||
raw = _reader_raw_comdirect(path)
|
raw = _reader_raw_comdirect(path)
|
||||||
@@ -42,6 +43,7 @@ def reader_comdirect(path: Path):
|
|||||||
result[account_name] = list(map(account.ingestion_function, account_data))
|
result[account_name] = list(map(account.ingestion_function, account_data))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _reader_raw_comdirect(path: Path):
|
def _reader_raw_comdirect(path: Path):
|
||||||
|
|
||||||
with path.open(encoding="latin1") as fid:
|
with path.open(encoding="latin1") as fid:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
IBAN_PATTERN = r"^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$"
|
IBAN_PATTERN = r"^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$"
|
||||||
|
|
||||||
|
|
||||||
class Currency(str, Enum):
|
class Currency(str, Enum):
|
||||||
EUR = "EUR"
|
EUR = "EUR"
|
||||||
USD = "USD"
|
USD = "USD"
|
||||||
@@ -14,5 +14,3 @@ class Currency(str, Enum):
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"Currency.{self.name}"
|
return f"Currency.{self.name}"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,3 @@ class AccountInfo(BaseModel):
|
|||||||
iban: str = Field(pattern=IBAN_PATTERN)
|
iban: str = Field(pattern=IBAN_PATTERN)
|
||||||
ingestion_function: Callable
|
ingestion_function: Callable
|
||||||
currency: Currency
|
currency: Currency
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ def test_reader_comdirect():
|
|||||||
assert len(data) == len(COMDIRECT_ACCOUNTS)
|
assert len(data) == len(COMDIRECT_ACCOUNTS)
|
||||||
assert set(data) == set(COMDIRECT_ACCOUNTS)
|
assert set(data) == set(COMDIRECT_ACCOUNTS)
|
||||||
assert all(isinstance(row, ComdirectGiro) for row in data["Girokonto"])
|
assert all(isinstance(row, ComdirectGiro) for row in data["Girokonto"])
|
||||||
assert all(isinstance(row, ComdirectCreditCard) for row in data["Visa-Karte (Kreditkarte)"])
|
assert all(
|
||||||
|
isinstance(row, ComdirectCreditCard) for row in data["Visa-Karte (Kreditkarte)"]
|
||||||
|
)
|
||||||
assert all(isinstance(row, ComdirectGiro) for row in data["Tagesgeld PLUS-Konto"])
|
assert all(isinstance(row, ComdirectGiro) for row in data["Tagesgeld PLUS-Konto"])
|
||||||
assert all(isinstance(row, ComdirectDepot) for row in data["Depot"])
|
assert all(isinstance(row, ComdirectDepot) for row in data["Depot"])
|
||||||
|
|||||||
Reference in New Issue
Block a user