Files
bakery-ia/services/forecasting/app/models/sales_data_update.py

79 lines
3.4 KiB
Python
Raw Normal View History

2026-01-21 17:17:16 +01:00
# ================================================================
# services/forecasting/app/models/sales_data_update.py
# ================================================================
"""
Sales Data Update Tracking Model
Tracks when sales data is added or updated for past dates,
enabling automated historical validation backfill.
"""
from sqlalchemy import Column, String, Integer, DateTime, Boolean, Index, Date
from sqlalchemy.dialects.postgresql import UUID
from datetime import datetime, timezone
import uuid
from shared.database.base import Base
class SalesDataUpdate(Base):
"""Track sales data updates for historical validation"""
__tablename__ = "sales_data_updates"
__table_args__ = (
Index('ix_sales_updates_tenant_status', 'tenant_id', 'validation_status', 'created_at'),
Index('ix_sales_updates_date_range', 'tenant_id', 'update_date_start', 'update_date_end'),
Index('ix_sales_updates_validation_status', 'validation_status'),
)
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
# Date range of sales data that was added/updated
update_date_start = Column(Date, nullable=False, index=True)
update_date_end = Column(Date, nullable=False, index=True)
# Update metadata
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
update_source = Column(String(100), nullable=True) # import, manual, pos_sync
records_affected = Column(Integer, default=0)
# Validation tracking
validation_status = Column(String(50), default="pending") # pending, processing, completed, failed
validation_run_id = Column(UUID(as_uuid=True), nullable=True)
validated_at = Column(DateTime(timezone=True), nullable=True)
validation_error = Column(String(500), nullable=True)
# Determines if this update should trigger validation
requires_validation = Column(Boolean, default=True)
# Additional context
import_job_id = Column(String(255), nullable=True) # Link to sales import job if applicable
notes = Column(String(500), nullable=True)
def __repr__(self):
return (
f"<SalesDataUpdate(id={self.id}, tenant_id={self.tenant_id}, "
f"date_range={self.update_date_start} to {self.update_date_end}, "
f"status={self.validation_status})>"
)
def to_dict(self):
"""Convert to dictionary for API responses"""
return {
'id': str(self.id),
'tenant_id': str(self.tenant_id),
'update_date_start': self.update_date_start.isoformat() if self.update_date_start else None,
'update_date_end': self.update_date_end.isoformat() if self.update_date_end else None,
'created_at': self.created_at.isoformat() if self.created_at else None,
'update_source': self.update_source,
'records_affected': self.records_affected,
'validation_status': self.validation_status,
'validation_run_id': str(self.validation_run_id) if self.validation_run_id else None,
'validated_at': self.validated_at.isoformat() if self.validated_at else None,
'validation_error': self.validation_error,
'requires_validation': self.requires_validation,
'import_job_id': self.import_job_id,
'notes': self.notes
}