109 lines
4.9 KiB
Python
109 lines
4.9 KiB
Python
# 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"<POSWebhookLog(id={self.id}, pos_system='{self.pos_system}', type='{self.webhook_type}', status='{self.status}')>" |