79 lines
3.4 KiB
Python
79 lines
3.4 KiB
Python
# ================================================================
|
|
# 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
|
|
}
|