ingest comdirect as raw strings
This commit is contained in:
@@ -31,5 +31,6 @@ build-backend = "uv_build"
|
|||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
dev = [
|
dev = [
|
||||||
"black>=26.5.1",
|
"black>=26.5.1",
|
||||||
|
"debugpy>=1.8.21",
|
||||||
"polyfactory>=3.3.0",
|
"polyfactory>=3.3.0",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -100,3 +100,45 @@ class Category(BaseModel):
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'Category.from_str("{self.__str__()}")'
|
return f'Category.from_str("{self.__str__()}")'
|
||||||
|
|
||||||
|
|
||||||
|
class ComdirectBase(BaseModel):
|
||||||
|
date_book: str = Field(alias="Buchungstag", examples=["07.09.2026"])
|
||||||
|
amount_eur: str = Field(alias="Umsatz in EUR", examples=["32,43"])
|
||||||
|
|
||||||
|
|
||||||
|
class ComdirectCommon(ComdirectBase):
|
||||||
|
type: str = Field(
|
||||||
|
alias="Vorgang", examples=["Lastschrift / Belastung", "Kartenumsatz"]
|
||||||
|
)
|
||||||
|
text: str = Field(alias="Buchungstext")
|
||||||
|
|
||||||
|
|
||||||
|
class ComdirectGiro(ComdirectCommon):
|
||||||
|
# "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";
|
||||||
|
date_book: str = Field(alias="Buchungstag", examples=["07.09.2026"])
|
||||||
|
date_val: str = Field(alias="Umsatztag", default="")
|
||||||
|
type: str = Field(
|
||||||
|
alias="Vorgang",
|
||||||
|
examples=["Lastschrift / Belastung", "Kartenumsatz"],
|
||||||
|
default="",
|
||||||
|
)
|
||||||
|
reference: str = Field(alias="Referenz", default="")
|
||||||
|
text: str = Field(alias="Buchungstext", default="")
|
||||||
|
amount_eur: str = Field(alias="Umsatz in EUR", examples=["32,43"], default="")
|
||||||
|
|
||||||
|
|
||||||
|
class ComdirectDepot(BaseModel):
|
||||||
|
# "Buchungstag";"Geschäftstag";"Stück / Nom.";"Bezeichnung";"WKN";"Währung";"Ausführungskurs";"Umsatz in EUR";
|
||||||
|
date_val: str = Field(alias="Geschäftstag")
|
||||||
|
num: str = Field(alias="Stück / Nom.")
|
||||||
|
name: str = Field(alias="Bezeichnung")
|
||||||
|
wkn: str = Field(alias="WKN")
|
||||||
|
currency: str = Field(alias="Währung")
|
||||||
|
spot_price: str = Field(alias="Ausführungskurs")
|
||||||
|
|||||||
+27
-10
@@ -4,29 +4,46 @@ from enum import Enum, auto
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from src.models import B4wExport
|
from src.models import B4wExport
|
||||||
|
from src.settings.account_ingest import ACCOUNT_INGESTION_FUNCTIONS
|
||||||
|
|
||||||
|
|
||||||
def reader_raw(path: Path):
|
def _reader_raw(path: Path):
|
||||||
with path.open() as fid:
|
with path.open() as fid:
|
||||||
return list(csv.DictReader(fid))
|
return list(csv.DictReader(fid))
|
||||||
|
|
||||||
|
|
||||||
def reader_b4w(path: Path):
|
def reader_b4w(path: Path):
|
||||||
raw = reader_raw(path)
|
raw = _reader_raw(path)
|
||||||
return list(map(B4wExport.model_validate, raw))
|
return list(map(B4wExport.model_validate, raw))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PATTERN_ACCOUNT_NAME = r'^"Umsätze ([^"]+)";"Zeitraum: .*$'
|
||||||
|
PATTERN_HEADER = r'"([^"]+)"'
|
||||||
|
PATTERN_DATA = r'"([^"]+)"'
|
||||||
|
|
||||||
|
class EXPECT_LINE(Enum):
|
||||||
|
ACCOUNT_NAME = auto()
|
||||||
|
BLANK = auto()
|
||||||
|
HEADER = auto()
|
||||||
|
DATA = auto()
|
||||||
|
|
||||||
|
|
||||||
def reader_comdirect(path: Path):
|
def reader_comdirect(path: Path):
|
||||||
|
bank_name = "comdirect"
|
||||||
|
ingestion_functions = ACCOUNT_INGESTION_FUNCTIONS.get(bank_name)
|
||||||
|
assert ingestion_functions
|
||||||
|
|
||||||
PATTERN_ACCOUNT_NAME = r'^"Umsätze ([^"]+)";"Zeitraum: .*$'
|
result = {}
|
||||||
PATTERN_HEADER = r'"([^"]+)"'
|
raw = _reader_raw_comdirect(path)
|
||||||
PATTERN_DATA = r'"([^"]+)"'
|
for account_name, account_data in raw.items():
|
||||||
|
ingestion_function = ingestion_functions.get(account_name)
|
||||||
|
assert ingestion_function
|
||||||
|
result[account_name] = list(map(ingestion_function, account_data))
|
||||||
|
|
||||||
class EXPECT_LINE(Enum):
|
return result
|
||||||
ACCOUNT_NAME = auto()
|
|
||||||
BLANK = auto()
|
def _reader_raw_comdirect(path: Path):
|
||||||
HEADER = auto()
|
|
||||||
DATA = auto()
|
|
||||||
|
|
||||||
with path.open(encoding="latin1") as fid:
|
with path.open(encoding="latin1") as fid:
|
||||||
lines = fid.readlines()
|
lines = fid.readlines()
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
from src.models import ComdirectCreditCard, ComdirectDepot, ComdirectGiro
|
||||||
|
|
||||||
|
ACCOUNT_INGESTION_FUNCTIONS = {
|
||||||
|
"comdirect": {
|
||||||
|
"Girokonto": lambda x: ComdirectGiro.model_validate(x),
|
||||||
|
"Visa-Karte (Kreditkarte)": lambda x: ComdirectCreditCard.model_validate(x),
|
||||||
|
"Tagesgeld PLUS-Konto": lambda x: ComdirectGiro.model_validate(x),
|
||||||
|
"Depot": lambda x: ComdirectDepot.model_validate(x),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,6 +74,19 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "debugpy"
|
||||||
|
version = "1.8.21"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f2/aa/12037145b7a56eaa5b29b41872f7a21b538e807e13f32c4d3c46e59be084/debugpy-1.8.21.tar.gz", hash = "sha256:a3c53278e84c94e11bd87c53970ec391d1a67396c8b22609fcac576520e611a6", size = 1697577, upload-time = "2026-06-01T19:30:35.156Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ce/3d/f4bbb323a548bfab2af3d6b4ffd9bf22636e55956a1285d317a1de643aad/debugpy-1.8.21-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9bb2a685287a2ac9b181cde89edcec64845cb51de7faaa75badb9a698bc24782", size = 2477209, upload-time = "2026-06-01T19:31:04.157Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8c/2d/6e7ec524984a1702777868de49a4c53202bddac2a432a76a093469587750/debugpy-1.8.21-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:3d6922439bf33fd38a3e2c447869ebc7b97da5cd3d329ff1ef9bc06c4903437e", size = 3927115, upload-time = "2026-06-01T19:31:05.863Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/97/47/d1aa6d64005a98a9144647d99306b419396f9ad7bf1d73c119e17a81fb4d/debugpy-1.8.21-cp314-cp314-win32.whl", hash = "sha256:15d4963bd5ffa48f0da0947fd06757fa7621945048a14ad7705431566d3c0e7c", size = 5336724, upload-time = "2026-06-01T19:31:07.711Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5f/67/b905b90d163af11878c1af8abafa4a25206335e112e284e413454543a6da/debugpy-1.8.21-cp314-cp314-win_amd64.whl", hash = "sha256:fe0744a12353406de0ae8ccff0d0a4a666f00801a3db8fd04e7a5f761cd520e8", size = 5373803, upload-time = "2026-06-01T19:31:09.469Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/95/51/67e7cf11a53e40694f720457d5b3a1cdaaa3d5a9a633e482f225456b93ff/debugpy-1.8.21-py2.py3-none-any.whl", hash = "sha256:b1e37d333663c8851516a47364ef473da127f9caebe4417e6df6f5825a7e9a92", size = 5352888, upload-time = "2026-06-01T19:31:25.186Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dotenv"
|
name = "dotenv"
|
||||||
version = "0.9.9"
|
version = "0.9.9"
|
||||||
@@ -114,6 +127,7 @@ dependencies = [
|
|||||||
[package.dev-dependencies]
|
[package.dev-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
{ name = "black" },
|
{ name = "black" },
|
||||||
|
{ name = "debugpy" },
|
||||||
{ name = "polyfactory" },
|
{ name = "polyfactory" },
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -131,6 +145,7 @@ requires-dist = [
|
|||||||
[package.metadata.requires-dev]
|
[package.metadata.requires-dev]
|
||||||
dev = [
|
dev = [
|
||||||
{ name = "black", specifier = ">=26.5.1" },
|
{ name = "black", specifier = ">=26.5.1" },
|
||||||
|
{ name = "debugpy", specifier = ">=1.8.21" },
|
||||||
{ name = "polyfactory", specifier = ">=3.3.0" },
|
{ name = "polyfactory", specifier = ">=3.3.0" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user