comdirect ingest: proper models
This commit is contained in:
+45
-18
@@ -102,28 +102,51 @@ class Category(BaseModel):
|
|||||||
return f'Category.from_str("{self.__str__()}")'
|
return f'Category.from_str("{self.__str__()}")'
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_date_german(date_str: str) -> date | None:
|
||||||
|
if date_str in ["offen", "neu", "--"]:
|
||||||
|
return None
|
||||||
|
day, month, year = list(map(int, date_str.split(".")))
|
||||||
|
return date(day=day, month=month, year=year)
|
||||||
|
|
||||||
|
def _parse_decimal_german(decimal_str: str) -> Decimal:
|
||||||
|
return Decimal(decimal_str.replace(".", "").replace(",", "."))
|
||||||
|
|
||||||
|
|
||||||
class ComdirectBase(BaseModel):
|
class ComdirectBase(BaseModel):
|
||||||
date_book: str = Field(alias="Buchungstag", examples=["07.09.2026"])
|
date_val: date | None = Field(alias="Wertstellung (Valuta)", examples=["07.09.2026"])
|
||||||
amount_eur: str = 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")
|
||||||
|
@classmethod
|
||||||
|
def parse_date_val(cls, date_str: str) -> date | None:
|
||||||
|
return _parse_date_german(date_str)
|
||||||
|
|
||||||
|
@field_validator("amount_eur", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def parse_amount(cls, decimal_str: str) -> Decimal:
|
||||||
|
return _parse_decimal_german(decimal_str)
|
||||||
|
|
||||||
|
|
||||||
class ComdirectCommon(ComdirectBase):
|
class ComdirectBaseBook(ComdirectBase):
|
||||||
|
date_book: date | None = Field(alias="Buchungstag", examples=["07.09.2026"])
|
||||||
|
|
||||||
|
@field_validator("date_book", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def parse_date_book(cls, date_str: str) -> date | None:
|
||||||
|
return _parse_date_german(date_str)
|
||||||
|
|
||||||
|
|
||||||
|
class ComdirectGiro(ComdirectBaseBook):
|
||||||
type: str = Field(
|
type: str = Field(
|
||||||
alias="Vorgang", examples=["Lastschrift / Belastung", "Kartenumsatz"]
|
alias="Vorgang", examples=["Lastschrift / Belastung", "Kartenumsatz"]
|
||||||
)
|
)
|
||||||
text: str = Field(alias="Buchungstext")
|
text: str = Field(alias="Buchungstext")
|
||||||
|
|
||||||
|
|
||||||
class ComdirectGiro(ComdirectCommon):
|
class ComdirectCreditCard(ComdirectBaseBook):
|
||||||
# "Buchungstag";"Wertstellung (Valuta)";"Vorgang";"Buchungstext";"Umsatz in EUR";
|
|
||||||
# "Buchungstag";"Wertstellung (Valuta)";"Vorgang";"Buchungstext";"Umsatz in EUR";
|
|
||||||
date_val: str = Field(alias="Wertstellung (Valuta)", examples=["07.09.2026"])
|
|
||||||
|
|
||||||
|
|
||||||
class ComdirectCreditCard(ComdirectCommon):
|
|
||||||
# "Buchungstag";"Umsatztag";"Vorgang";"Referenz";"Buchungstext";"Umsatz in EUR";
|
# "Buchungstag";"Umsatztag";"Vorgang";"Referenz";"Buchungstext";"Umsatz in EUR";
|
||||||
date_book: str = Field(alias="Buchungstag", examples=["07.09.2026"])
|
date_book: date | None = Field(alias="Buchungstag", examples=["07.09.2026"])
|
||||||
date_val: str = Field(alias="Umsatztag", default="")
|
date_val: date | None = Field(alias="Umsatztag", default=None)
|
||||||
type: str = Field(
|
type: str = Field(
|
||||||
alias="Vorgang",
|
alias="Vorgang",
|
||||||
examples=["Lastschrift / Belastung", "Kartenumsatz"],
|
examples=["Lastschrift / Belastung", "Kartenumsatz"],
|
||||||
@@ -131,14 +154,18 @@ class ComdirectCreditCard(ComdirectCommon):
|
|||||||
)
|
)
|
||||||
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: str = Field(alias="Umsatz in EUR", examples=["32,43"], default="")
|
amount_eur: Decimal | None = Field(alias="Umsatz in EUR", examples=["32,43"], default=None)
|
||||||
|
|
||||||
|
|
||||||
class ComdirectDepot(BaseModel):
|
class ComdirectDepot(ComdirectBase):
|
||||||
# "Buchungstag";"Geschäftstag";"Stück / Nom.";"Bezeichnung";"WKN";"Währung";"Ausführungskurs";"Umsatz in EUR";
|
date_val: date | None = Field(alias="Geschäftstag")
|
||||||
date_val: str = Field(alias="Geschäftstag")
|
num: Decimal = Field(alias="Stück / Nom.")
|
||||||
num: str = Field(alias="Stück / Nom.")
|
|
||||||
name: str = Field(alias="Bezeichnung")
|
name: str = Field(alias="Bezeichnung")
|
||||||
wkn: str = Field(alias="WKN")
|
wkn: str = Field(alias="WKN")
|
||||||
currency: str = Field(alias="Währung")
|
currency: str = Field(alias="Währung")
|
||||||
spot_price: str = Field(alias="Ausführungskurs")
|
spot_price: Decimal = Field(alias="Ausführungskurs")
|
||||||
|
|
||||||
|
@field_validator("num", "spot_price", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def parse_decimals(cls, decimal_in: str) -> Decimal:
|
||||||
|
return _parse_decimal_german(decimal_in)
|
||||||
|
|||||||
+11
-1
@@ -1,10 +1,20 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from src.models import ComdirectCreditCard, ComdirectDepot, ComdirectGiro
|
||||||
from src.reader import reader_comdirect
|
from src.reader import reader_comdirect
|
||||||
|
from src.settings.account_ingest import ACCOUNT_INGESTION_FUNCTIONS
|
||||||
|
|
||||||
|
|
||||||
def test_reader():
|
def test_reader_comdirect():
|
||||||
|
bank_name = "comdirect"
|
||||||
|
assert bank_name in ACCOUNT_INGESTION_FUNCTIONS
|
||||||
test_path = Path(".local/data/comdirect/umsaetze_9773063005_20260906-2043.csv")
|
test_path = Path(".local/data/comdirect/umsaetze_9773063005_20260906-2043.csv")
|
||||||
assert test_path.exists()
|
assert test_path.exists()
|
||||||
data = reader_comdirect(test_path)
|
data = reader_comdirect(test_path)
|
||||||
assert data
|
assert data
|
||||||
|
assert len(data) == len(ACCOUNT_INGESTION_FUNCTIONS.get(bank_name))
|
||||||
|
assert set(data) == set(ACCOUNT_INGESTION_FUNCTIONS.get(bank_name))
|
||||||
|
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, ComdirectGiro) for row in data["Tagesgeld PLUS-Konto"])
|
||||||
|
assert all(isinstance(row, ComdirectDepot) for row in data["Depot"])
|
||||||
|
|||||||
Reference in New Issue
Block a user