feat: Phase 4 – CSV-Import (Templates, Prüfansicht, Duplikat/Transfer-Erkennung, Undo)
Backend: - Modelle + Migration 0005: import_templates, import_batches, categorization_rules; transactions um import_batch_id + import_hash erweitert. - services/csv_import: Datei parsen (Trennzeichen, Dezimal-/Datumsformat, Kodierung, Header/Skip, Vorzeichen vs. Soll/Haben), Vorschau mit Duplikat-Erkennung (Hash), interner-Transfer-Erkennung via IBAN, lernender Auto-Kategorisierung; Buchen mit Batch und Undo. - routers/imports: Templates (CRUD), Roh-Vorschau, Prüf-Vorschau, Buchen, Verlauf, Rückgängig. pytest: Parsing, Duplikate, Transfer, Buchen, Undo, Lernen. Frontend: - Import-Seite: Konto+Datei, Format/Spaltenzuordnung (mit Roh-Vorschau), editierbare Prüfansicht (Kategorie/Typ/Zielkonto, Duplikate markiert), Buchen, Import-Verlauf mit Undo; Vorlagen speichern; i18n DE/EN. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,9 +6,11 @@ from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
|
||||
from .models import (
|
||||
AccountType,
|
||||
AmountMode,
|
||||
BudgetTreatment,
|
||||
CategoryKind,
|
||||
IdentifierKind,
|
||||
ImportStatus,
|
||||
Role,
|
||||
TxnType,
|
||||
)
|
||||
@@ -283,3 +285,63 @@ class PlannedIncomeOut(BaseModel):
|
||||
target_account_id: int | None
|
||||
planned_cents: int
|
||||
position: int
|
||||
|
||||
|
||||
# --- CSV-Import ------------------------------------------------------------
|
||||
|
||||
|
||||
class ImportTemplateCreate(BaseModel):
|
||||
name: str = Field(min_length=1, max_length=120)
|
||||
delimiter: str = ";"
|
||||
decimal_sep: str = ","
|
||||
date_format: str = "%d.%m.%Y"
|
||||
encoding: str = "utf-8"
|
||||
has_header: bool = True
|
||||
skip_rows: int = 0
|
||||
amount_mode: AmountMode = AmountMode.signed
|
||||
column_map: dict[str, int | None] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class ImportTemplateUpdate(BaseModel):
|
||||
name: str | None = Field(default=None, min_length=1, max_length=120)
|
||||
delimiter: str | None = None
|
||||
decimal_sep: str | None = None
|
||||
date_format: str | None = None
|
||||
encoding: str | None = None
|
||||
has_header: bool | None = None
|
||||
skip_rows: int | None = None
|
||||
amount_mode: AmountMode | None = None
|
||||
column_map: dict[str, int | None] | None = None
|
||||
|
||||
|
||||
class ImportTemplateOut(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
delimiter: str
|
||||
decimal_sep: str
|
||||
date_format: str
|
||||
encoding: str
|
||||
has_header: bool
|
||||
skip_rows: int
|
||||
amount_mode: AmountMode
|
||||
column_map: dict[str, int | None]
|
||||
|
||||
|
||||
class ImportBatchOut(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
account_id: int
|
||||
template_id: int | None
|
||||
filename: str
|
||||
row_count: int
|
||||
imported_count: int
|
||||
status: ImportStatus
|
||||
created_at: datetime
|
||||
|
||||
|
||||
class ImportCommitIn(BaseModel):
|
||||
account_id: int
|
||||
template_id: int | None = None
|
||||
filename: str = ""
|
||||
rows: list[dict] = Field(default_factory=list)
|
||||
|
||||
Reference in New Issue
Block a user