"""Receipt and ReceiptAttachment SQLModel models.""" from datetime import datetime, date from decimal import Decimal from enum import Enum from typing import Optional, List, TYPE_CHECKING from sqlmodel import SQLModel, Field, Relationship class ReceiptType(str, Enum): """Type of receipt document.""" BON_FISCAL = "bon_fiscal" CHITANTA = "chitanta" class ReceiptDirection(str, Enum): """Direction of receipt - expense or income.""" CHELTUIALA = "cheltuiala" # Expense (receipt from supplier) INCASARE = "incasare" # Income (receipt issued to client) class ReceiptStatus(str, Enum): """Workflow status of receipt.""" DRAFT = "draft" # User is filling in data PENDING_REVIEW = "pending_review" # Awaiting accountant approval APPROVED = "approved" # Approved by accountant REJECTED = "rejected" # Rejected by accountant SYNCED = "synced" # Synced to Oracle (Phase 2) if TYPE_CHECKING: from .accounting_entry import AccountingEntry class Receipt(SQLModel, table=True): """Receipt (Bon Fiscal / Chitanta) with approval workflow.""" __tablename__ = "receipts" id: Optional[int] = Field(default=None, primary_key=True) # Document identification receipt_type: ReceiptType = Field(default=ReceiptType.BON_FISCAL) direction: ReceiptDirection = Field(default=ReceiptDirection.CHELTUIALA) receipt_number: Optional[str] = Field(default=None, max_length=50) receipt_series: Optional[str] = Field(default=None, max_length=20) # Main data receipt_date: date amount: Decimal = Field(decimal_places=2, max_digits=15) description: Optional[str] = Field(default=None, max_length=500) # Expense type (for auto-generating accounting entries) expense_type_code: Optional[str] = Field(default=None, max_length=20) # Oracle references (nomenclatures) company_id: int partner_id: Optional[int] = Field(default=None) partner_name: Optional[str] = Field(default=None, max_length=200) # Cache for display cash_register_id: Optional[int] = Field(default=None) # Cash/Bank ID from Oracle cash_register_name: Optional[str] = Field(default=None, max_length=100) # Cache for display cash_register_account: Optional[str] = Field(default=None, max_length=20) # Account code (5311, 5121) # Workflow status: ReceiptStatus = Field(default=ReceiptStatus.DRAFT) created_by: str = Field(max_length=100) # Username of creator created_at: datetime = Field(default_factory=datetime.utcnow) updated_at: datetime = Field(default_factory=datetime.utcnow) submitted_at: Optional[datetime] = Field(default=None) # When submitted for approval # Approval reviewed_by: Optional[str] = Field(default=None, max_length=100) # Accountant username reviewed_at: Optional[datetime] = Field(default=None) rejection_reason: Optional[str] = Field(default=None, max_length=500) # Reason for rejection # Phase 2 - Oracle sync oracle_synced_at: Optional[datetime] = Field(default=None) oracle_act_id: Optional[int] = Field(default=None) oracle_error: Optional[str] = Field(default=None, max_length=500) # Relationships attachments: List["ReceiptAttachment"] = Relationship( back_populates="receipt", sa_relationship_kwargs={"cascade": "all, delete-orphan"} ) entries: List["AccountingEntry"] = Relationship( back_populates="receipt", sa_relationship_kwargs={"cascade": "all, delete-orphan"} ) class ReceiptAttachment(SQLModel, table=True): """Attachment (photo or PDF) for a receipt.""" __tablename__ = "receipt_attachments" id: Optional[int] = Field(default=None, primary_key=True) receipt_id: int = Field(foreign_key="receipts.id", index=True) # File info filename: str = Field(max_length=255) # Original filename stored_filename: str = Field(max_length=255) # Filename on disk (UUID) file_path: str = Field(max_length=500) # Relative path file_size: int # Size in bytes mime_type: str = Field(max_length=100) # MIME type (image/jpeg, application/pdf) uploaded_at: datetime = Field(default_factory=datetime.utcnow) # Relationship receipt: Optional[Receipt] = Relationship(back_populates="attachments")