kiwi/app/models/schemas/ocr.py
pyr0ball c18bfec8f5
Some checks are pending
CI / Backend (Python) (push) Waiting to run
CI / Frontend (Vue) (push) Waiting to run
Mirror / mirror (push) Waiting to run
fix(lint): add ruff config, fix all lint errors for GitHub CI
- pyproject.toml: add [tool.ruff] config suppressing E402/W293 globally,
  F841/E741/E702 in tests, E741 in scripts
- inventory.py: split semicolon import (E702)
- recipes.py: fix logger -> log (F821 undefined name)
- shopping.py: rename l -> lnk in list comprehension (E741)
- format_conversion.py: noqa F841 on CUDA flag (used as future hook)
- backfill_keywords.py: rename done -> _done (F841)
- ingest_purplecarrot.py: drop == True comparison (E712)
- Auto-fix: I001 import sorting, F401 unused imports across all files
2026-07-06 02:49:02 -07:00

139 lines
4.1 KiB
Python

#!/usr/bin/env python
"""
Pydantic schemas for OCR data models.
"""
from datetime import date, datetime, time
from typing import Any, Dict, List, Optional
from uuid import UUID
from pydantic import BaseModel, Field
class MerchantInfo(BaseModel):
"""Merchant/store information from receipt."""
name: Optional[str] = None
address: Optional[str] = None
phone: Optional[str] = None
email: Optional[str] = None
website: Optional[str] = None
tax_id: Optional[str] = None
class TransactionInfo(BaseModel):
"""Transaction details from receipt."""
date: Optional[date] = None
time: Optional[time] = None
receipt_number: Optional[str] = None
register: Optional[str] = None
cashier: Optional[str] = None
transaction_id: Optional[str] = None
class ReceiptItem(BaseModel):
"""Individual line item from receipt."""
name: str
quantity: float = 1.0
unit_price: Optional[float] = None
total_price: float
category: Optional[str] = None
tax_code: Optional[str] = None
discount: Optional[float] = 0.0
barcode: Optional[str] = None
notes: Optional[str] = None
class ReceiptTotals(BaseModel):
"""Financial totals from receipt."""
subtotal: float
tax: Optional[float] = 0.0
discount: Optional[float] = 0.0
tip: Optional[float] = 0.0
total: float
payment_method: Optional[str] = None
amount_paid: Optional[float] = None
change: Optional[float] = 0.0
calculated_subtotal: Optional[float] = None # For validation
class ConfidenceScores(BaseModel):
"""Confidence scores for extracted data."""
overall: float = Field(ge=0.0, le=1.0)
merchant: Optional[float] = Field(default=0.5, ge=0.0, le=1.0)
items: Optional[float] = Field(default=0.5, ge=0.0, le=1.0)
totals: Optional[float] = Field(default=0.5, ge=0.0, le=1.0)
transaction: Optional[float] = Field(default=0.5, ge=0.0, le=1.0)
class OCRResult(BaseModel):
"""Complete OCR extraction result."""
merchant: MerchantInfo
transaction: TransactionInfo
items: List[ReceiptItem]
totals: ReceiptTotals
confidence: ConfidenceScores
raw_text: Optional[str] = None
warnings: List[str] = Field(default_factory=list)
processing_time: Optional[float] = None # seconds
class ReceiptDataCreate(BaseModel):
"""Schema for creating receipt data."""
receipt_id: UUID
merchant_name: Optional[str] = None
merchant_address: Optional[str] = None
merchant_phone: Optional[str] = None
transaction_date: Optional[date] = None
transaction_time: Optional[time] = None
receipt_number: Optional[str] = None
items: List[Dict[str, Any]] = Field(default_factory=list)
subtotal: Optional[float] = None
tax: Optional[float] = None
tip: Optional[float] = None
total: Optional[float] = None
payment_method: Optional[str] = None
raw_text: Optional[str] = None
confidence_scores: Optional[Dict[str, float]] = None
warnings: List[str] = Field(default_factory=list)
class ReceiptDataResponse(BaseModel):
"""Schema for receipt data response."""
id: UUID
receipt_id: UUID
merchant_name: Optional[str]
merchant_address: Optional[str]
merchant_phone: Optional[str]
transaction_date: Optional[date]
transaction_time: Optional[time]
receipt_number: Optional[str]
items: List[Dict[str, Any]]
subtotal: Optional[float]
tax: Optional[float]
tip: Optional[float]
total: Optional[float]
payment_method: Optional[str]
raw_text: Optional[str]
confidence_scores: Optional[Dict[str, float]]
warnings: List[str]
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class OCRStatusResponse(BaseModel):
"""OCR processing status response."""
receipt_id: UUID
ocr_completed: bool
has_data: bool
confidence: Optional[float] = None
item_count: Optional[int] = None
warnings: List[str] = Field(default_factory=list)
class OCRTriggerRequest(BaseModel):
"""Request to trigger OCR processing."""
force_reprocess: bool = False
use_quantization: bool = False