""" POI Refresh Job Model Tracks background jobs for periodic POI context refresh. """ from sqlalchemy import Column, String, DateTime, Integer, Boolean, Text, Float from sqlalchemy.dialects.postgresql import UUID, JSONB from datetime import datetime, timezone import uuid from app.core.database import Base class POIRefreshJob(Base): """ POI Refresh Background Job Model Tracks periodic POI context refresh jobs for all tenants. Jobs run on a configurable schedule (default: 180 days). """ __tablename__ = "poi_refresh_jobs" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True) # Job scheduling scheduled_at = Column( DateTime(timezone=True), nullable=False, index=True, comment="When this job was scheduled" ) started_at = Column( DateTime(timezone=True), nullable=True, comment="When job execution started" ) completed_at = Column( DateTime(timezone=True), nullable=True, comment="When job execution completed" ) # Job status status = Column( String(50), nullable=False, default="pending", index=True, comment="Job status: pending, running, completed, failed" ) # Job execution details attempt_count = Column( Integer, nullable=False, default=0, comment="Number of execution attempts" ) max_attempts = Column( Integer, nullable=False, default=3, comment="Maximum number of retry attempts" ) # Location data (cached for job execution) latitude = Column( Float, nullable=False, comment="Bakery latitude for POI detection" ) longitude = Column( Float, nullable=False, comment="Bakery longitude for POI detection" ) # Results pois_detected = Column( Integer, nullable=True, comment="Number of POIs detected in this refresh" ) changes_detected = Column( Boolean, default=False, comment="Whether significant changes were detected" ) change_summary = Column( JSONB, nullable=True, comment="Summary of changes detected" ) # Error handling error_message = Column( Text, nullable=True, comment="Error message if job failed" ) error_details = Column( JSONB, nullable=True, comment="Detailed error information" ) # Next execution next_scheduled_at = Column( DateTime(timezone=True), nullable=True, index=True, comment="When next refresh should be scheduled" ) # Metadata created_at = Column( DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc) ) updated_at = Column( DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc) ) def __repr__(self): return ( f"" ) @property def is_overdue(self) -> bool: """Check if job is overdue for execution""" if self.status in ("completed", "running"): return False return datetime.now(timezone.utc) > self.scheduled_at @property def can_retry(self) -> bool: """Check if job can be retried""" return self.attempt_count < self.max_attempts @property def duration_seconds(self) -> float | None: """Calculate job duration in seconds""" if self.started_at and self.completed_at: return (self.completed_at - self.started_at).total_seconds() return None