# services/pos/app/models/pos_webhook.py """ POS Webhook Log Model Tracks webhook events from POS systems """ from sqlalchemy import Column, String, DateTime, Boolean, Integer, Text, JSON, Index from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.sql import func import uuid from shared.database.base import Base class POSWebhookLog(Base): """ Log of webhook events received from POS systems """ __tablename__ = "pos_webhook_logs" # Primary identifiers id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True) tenant_id = Column(UUID(as_uuid=True), nullable=True, index=True) # May be null until parsed # POS Provider Information pos_system = Column(String(50), nullable=False, index=True) # square, toast, lightspeed webhook_type = Column(String(100), nullable=False, index=True) # payment.created, order.updated, etc. # Request Information method = Column(String(10), nullable=False) # POST, PUT, etc. url_path = Column(String(500), nullable=False) query_params = Column(JSON, nullable=True) headers = Column(JSON, nullable=True) # Payload raw_payload = Column(Text, nullable=False) # Raw webhook payload payload_size = Column(Integer, nullable=False, default=0) content_type = Column(String(100), nullable=True) # Security signature = Column(String(500), nullable=True) # Webhook signature for verification is_signature_valid = Column(Boolean, nullable=True) # null = not checked, true/false = verified source_ip = Column(String(45), nullable=True) # IPv4 or IPv6 # Processing Status status = Column(String(50), nullable=False, default="received", index=True) # received, processing, processed, failed processing_started_at = Column(DateTime(timezone=True), nullable=True) processing_completed_at = Column(DateTime(timezone=True), nullable=True) processing_duration_ms = Column(Integer, nullable=True) # Error Handling error_message = Column(Text, nullable=True) error_code = Column(String(50), nullable=True) retry_count = Column(Integer, default=0, nullable=False) max_retries = Column(Integer, default=3, nullable=False) # Response Information response_status_code = Column(Integer, nullable=True) response_body = Column(Text, nullable=True) response_sent_at = Column(DateTime(timezone=True), nullable=True) # Event Metadata event_id = Column(String(255), nullable=True, index=True) # POS system's event ID event_timestamp = Column(DateTime(timezone=True), nullable=True) # When event occurred in POS sequence_number = Column(Integer, nullable=True) # For ordered events # Business Data References transaction_id = Column(String(255), nullable=True, index=True) # Referenced transaction order_id = Column(String(255), nullable=True, index=True) # Referenced order customer_id = Column(String(255), nullable=True) # Referenced customer # Internal References created_transaction_id = Column(UUID(as_uuid=True), nullable=True) # Created POSTransaction record updated_transaction_id = Column(UUID(as_uuid=True), nullable=True) # Updated POSTransaction record # Duplicate Detection is_duplicate = Column(Boolean, default=False, nullable=False, index=True) duplicate_of = Column(UUID(as_uuid=True), nullable=True) # Processing Priority priority = Column(String(20), default="normal", nullable=False) # low, normal, high, urgent # Debugging Information user_agent = Column(String(500), nullable=True) forwarded_for = Column(String(200), nullable=True) # X-Forwarded-For header request_id = Column(String(100), nullable=True) # For request tracing # Timestamps received_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False, index=True) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) # Indexes for performance __table_args__ = ( Index('idx_webhook_pos_system_type', 'pos_system', 'webhook_type'), Index('idx_webhook_status', 'status'), Index('idx_webhook_event_id', 'event_id'), Index('idx_webhook_received_at', 'received_at'), Index('idx_webhook_tenant_received', 'tenant_id', 'received_at'), Index('idx_webhook_transaction_id', 'transaction_id'), Index('idx_webhook_order_id', 'order_id'), Index('idx_webhook_duplicate', 'is_duplicate'), Index('idx_webhook_priority', 'priority'), Index('idx_webhook_retry', 'retry_count'), Index('idx_webhook_signature_valid', 'is_signature_valid'), ) def __repr__(self): return f""