kitchen/backend/models/email_processing.py
jtricerolph 8d688b459d Initial kitchen scaffold — Phase 1 kitchen port (build-verified 2026-07-11)
FastAPI backend (Python 3.11, MSSQL ODBC for SambaPOS, Azure DI OCR),
kitchen_db on central PG. React/TS/Vite frontend with navy sidebar layout.

Backend: auth.py (APP_SLUG=kitchen, SimpleNamespace — archive routes use
.kitchen_id/.is_admin without modification), main.py (51 migrations, scheduler,
internal router for KDS bookings feed), api/internal.py, full archive API
(31 routers: invoices, recipes, menus, sambapos, resos, newbook, disputes,
purchase_orders, etc.), models, migrations, OCR pipeline.
kitchen_id pinned to 1 (B1 — single hotel).

Frontend: AuthGate (app=kitchen, token shim for archive compat — B5b pending),
Layout (navy sidebar, 6 sections, Lucide icons, teal --app-primary),
App.tsx (Outlet pattern, UploadApp outside Layout), index.css (full :root block).
strict: false — archive components have type issues; build clean.

Note: 45 archive components call fetch('/api/...') without /kitchen/ prefix
(B5b). Runtime 404s; deferred until after initial testing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-12 12:15:39 +00:00

50 lines
2 KiB
Python

"""
Email processing log model for tracking IMAP email inbox sync.
"""
from datetime import datetime
from sqlalchemy import String, DateTime, ForeignKey, Integer, Boolean, Text, UniqueConstraint
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship
from database import Base
class EmailProcessingLog(Base):
"""Track processed emails to prevent re-processing"""
__tablename__ = "email_processing_log"
id: Mapped[int] = mapped_column(primary_key=True, index=True)
kitchen_id: Mapped[int] = mapped_column(ForeignKey("kitchens.id"), nullable=False, index=True)
# Email identification (RFC 2822 Message-ID)
message_id: Mapped[str] = mapped_column(String(500), nullable=False, index=True)
# Email metadata for audit trail
email_subject: Mapped[str | None] = mapped_column(String(500), nullable=True)
email_from: Mapped[str | None] = mapped_column(String(255), nullable=True)
email_date: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
# Processing results
attachments_count: Mapped[int] = mapped_column(Integer, default=0)
invoices_created: Mapped[int] = mapped_column(Integer, default=0)
confident_invoices: Mapped[int] = mapped_column(Integer, default=0)
# Status tracking
marked_as_read: Mapped[bool] = mapped_column(Boolean, default=False)
processing_status: Mapped[str] = mapped_column(String(50), default="pending") # pending, success, failed, skipped
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
# Invoice IDs created from this email
invoice_ids: Mapped[list | None] = mapped_column(JSONB, nullable=True)
processed_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
# Relationships
kitchen: Mapped["Kitchen"] = relationship("Kitchen", back_populates="email_processing_logs")
__table_args__ = (
UniqueConstraint('kitchen_id', 'message_id', name='uq_email_message_id'),
)
# Forward reference
from .user import Kitchen