103 lines
3.6 KiB
Python
103 lines
3.6 KiB
Python
"""
|
|
C-Stone Invoice Check — Datenbankmodelle
|
|
SQLAlchemy ORM Modelle für Rechnungen und Emails
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from sqlalchemy import Column, Integer, String, DateTime, Float, Boolean, Text, JSON
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
|
|
Base = declarative_base()
|
|
|
|
|
|
class Invoice(Base):
|
|
"""
|
|
Tabelle: Rechnungen
|
|
Speichert die Metadaten jeder verarbeiteten Rechnung
|
|
"""
|
|
__tablename__ = "invoices"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
email_id = Column(String, index=True) # IMAP UID der Original-Email
|
|
email_subject = Column(String, nullable=True)
|
|
email_from = Column(String, nullable=True)
|
|
email_date = Column(DateTime, nullable=True)
|
|
|
|
# Rechnungsdaten
|
|
invoice_number = Column(String, index=True, nullable=True)
|
|
invoice_date = Column(DateTime, nullable=True)
|
|
invoice_amount = Column(Float, nullable=True)
|
|
invoice_tax_amount = Column(Float, nullable=True)
|
|
invoice_tax_rate = Column(Float, nullable=True) # z.B. 0, 0.19, 0.16
|
|
invoice_tax_type = Column(String, nullable=True) # "MwSt", "Umsatzsteuer", "VAT", "ohne"
|
|
|
|
# Absender/Empfänger
|
|
issuer_name = Column(String, nullable=True)
|
|
issuer_address = Column(Text, nullable=True)
|
|
|
|
# Dateipfad (Evo-X2)
|
|
file_path = Column(String, nullable=True)
|
|
file_name = Column(String, nullable=True)
|
|
storage_year = Column(Integer, nullable=True)
|
|
storage_path = Column(String, nullable=True) # z.B. "2025/ohne MwSt"
|
|
|
|
# Verarbeitungsstatus
|
|
processed = Column(Boolean, default=False)
|
|
processing_error = Column(Text, nullable=True)
|
|
confidence_score = Column(Float, nullable=True) # 0.0 - 1.0
|
|
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
def __repr__(self):
|
|
return f"<Invoice {self.invoice_number or 'unknown'}>"
|
|
|
|
|
|
class EmailLog(Base):
|
|
"""
|
|
Tabelle: Email Logs
|
|
Protokolliert jede verarbeitete Email
|
|
"""
|
|
__tablename__ = "email_logs"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
email_id = Column(String, unique=True, index=True) # IMAP UID
|
|
email_subject = Column(String, nullable=True)
|
|
email_from = Column(String, nullable=True)
|
|
email_date = Column(DateTime, nullable=True)
|
|
email_folder = Column(String, nullable=True) # z.B. "INBOX", "Gesendet"
|
|
|
|
# Filterergebnis
|
|
matched_keywords = Column(JSON, nullable=True) # Liste von Stichworten
|
|
has_attachment = Column(Boolean, default=False)
|
|
attachment_type = Column(String, nullable=True) # "pdf", "doc", "docx", "unknown"
|
|
|
|
# Verarbeitung
|
|
processed = Column(Boolean, default=False)
|
|
processing_result = Column(String, nullable=True) # "invoice_found", "not_an_invoice", "error"
|
|
invoice_id = Column(Integer, nullable=True) # Verweis auf Invoice-Tabelle
|
|
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
def __repr__(self):
|
|
return f"<EmailLog {self.email_id}>"
|
|
|
|
|
|
class InvoiceDetail(Base):
|
|
"""
|
|
Tabelle: Rechnungsdetails (erweiterte Informationen)
|
|
Speichert JSON-basierte erweiterte Daten
|
|
"""
|
|
__tablename__ = "invoice_details"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
invoice_id = Column(Integer, nullable=False, index=True)
|
|
raw_text = Column(Text, nullable=True) # Extrahierter PDF-Text
|
|
parsed_data = Column(JSON, nullable=True) # Geparste Daten als JSON
|
|
confidence_breakdown = Column(JSON, nullable=True) # Einzelne Confidence-Scores
|
|
processing_notes = Column(Text, nullable=True)
|
|
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
def __repr__(self):
|
|
return f"<InvoiceDetail {self.invoice_id}>"
|