Initial commit - production deployment
This commit is contained in:
24
services/pos/app/models/__init__.py
Normal file
24
services/pos/app/models/__init__.py
Normal file
@@ -0,0 +1,24 @@
|
||||
"""
|
||||
Database models for POS Integration Service
|
||||
"""
|
||||
|
||||
# Import AuditLog model for this service
|
||||
from shared.security import create_audit_log_model
|
||||
from shared.database.base import Base
|
||||
|
||||
# Create audit log model for this service
|
||||
AuditLog = create_audit_log_model(Base)
|
||||
|
||||
from .pos_config import POSConfiguration
|
||||
from .pos_transaction import POSTransaction, POSTransactionItem
|
||||
from .pos_webhook import POSWebhookLog
|
||||
from .pos_sync import POSSyncLog
|
||||
|
||||
__all__ = [
|
||||
"POSConfiguration",
|
||||
"POSTransaction",
|
||||
"POSTransactionItem",
|
||||
"POSWebhookLog",
|
||||
"POSSyncLog",
|
||||
"AuditLog"
|
||||
]
|
||||
83
services/pos/app/models/pos_config.py
Normal file
83
services/pos/app/models/pos_config.py
Normal file
@@ -0,0 +1,83 @@
|
||||
# services/pos/app/models/pos_config.py
|
||||
"""
|
||||
POS Configuration Model
|
||||
Stores POS system configurations for each tenant
|
||||
"""
|
||||
|
||||
from sqlalchemy import Column, String, DateTime, Boolean, Text, JSON, Index
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.sql import func
|
||||
import uuid
|
||||
|
||||
from shared.database.base import Base
|
||||
|
||||
|
||||
class POSConfiguration(Base):
|
||||
"""
|
||||
POS system configuration for tenants
|
||||
Stores encrypted credentials and settings for each POS provider
|
||||
"""
|
||||
__tablename__ = "pos_configurations"
|
||||
|
||||
# Primary identifiers
|
||||
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
|
||||
tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
|
||||
|
||||
# POS Provider Information
|
||||
pos_system = Column(String(50), nullable=False) # square, toast, lightspeed
|
||||
provider_name = Column(String(100), nullable=False) # Display name for the provider
|
||||
|
||||
# Configuration Status
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
is_connected = Column(Boolean, default=False, nullable=False)
|
||||
|
||||
# Authentication & Credentials (encrypted)
|
||||
encrypted_credentials = Column(Text, nullable=True) # JSON with encrypted API keys/tokens
|
||||
webhook_url = Column(String(500), nullable=True)
|
||||
webhook_secret = Column(String(255), nullable=True)
|
||||
|
||||
# Provider-specific Settings
|
||||
environment = Column(String(20), default="sandbox", nullable=False) # sandbox, production
|
||||
location_id = Column(String(100), nullable=True) # For multi-location setups
|
||||
merchant_id = Column(String(100), nullable=True) # Provider merchant ID
|
||||
|
||||
# Sync Configuration
|
||||
sync_enabled = Column(Boolean, default=True, nullable=False)
|
||||
sync_interval_minutes = Column(String(10), default="5", nullable=False)
|
||||
auto_sync_products = Column(Boolean, default=True, nullable=False)
|
||||
auto_sync_transactions = Column(Boolean, default=True, nullable=False)
|
||||
|
||||
# Last Sync Information
|
||||
last_sync_at = Column(DateTime(timezone=True), nullable=True)
|
||||
last_successful_sync_at = Column(DateTime(timezone=True), nullable=True)
|
||||
last_sync_status = Column(String(50), nullable=True) # success, failed, partial
|
||||
last_sync_message = Column(Text, nullable=True)
|
||||
|
||||
# Provider-specific Configuration (JSON)
|
||||
provider_settings = Column(JSON, nullable=True)
|
||||
|
||||
# Connection Health
|
||||
last_health_check_at = Column(DateTime(timezone=True), nullable=True)
|
||||
health_status = Column(String(50), default="unknown", nullable=False) # healthy, unhealthy, unknown
|
||||
health_message = Column(Text, nullable=True)
|
||||
|
||||
# Timestamps
|
||||
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)
|
||||
|
||||
# Metadata
|
||||
created_by = Column(UUID(as_uuid=True), nullable=True)
|
||||
notes = Column(Text, nullable=True)
|
||||
|
||||
# Indexes for performance
|
||||
__table_args__ = (
|
||||
Index('idx_pos_config_tenant_pos_system', 'tenant_id', 'pos_system'),
|
||||
Index('idx_pos_config_active', 'is_active'),
|
||||
Index('idx_pos_config_connected', 'is_connected'),
|
||||
Index('idx_pos_config_sync_enabled', 'sync_enabled'),
|
||||
Index('idx_pos_config_health_status', 'health_status'),
|
||||
Index('idx_pos_config_created_at', 'created_at'),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<POSConfiguration(id={self.id}, tenant_id={self.tenant_id}, pos_system='{self.pos_system}', is_active={self.is_active})>"
|
||||
126
services/pos/app/models/pos_sync.py
Normal file
126
services/pos/app/models/pos_sync.py
Normal file
@@ -0,0 +1,126 @@
|
||||
# services/pos/app/models/pos_sync.py
|
||||
"""
|
||||
POS Sync Log Model
|
||||
Tracks synchronization operations with POS systems
|
||||
"""
|
||||
|
||||
from sqlalchemy import Column, String, DateTime, Boolean, Integer, Text, JSON, Index, Numeric
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.sql import func
|
||||
import uuid
|
||||
|
||||
from shared.database.base import Base
|
||||
|
||||
|
||||
class POSSyncLog(Base):
|
||||
"""
|
||||
Log of synchronization operations with POS systems
|
||||
"""
|
||||
__tablename__ = "pos_sync_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=False, index=True)
|
||||
pos_config_id = Column(UUID(as_uuid=True), nullable=False, index=True)
|
||||
|
||||
# Sync Operation Details
|
||||
sync_type = Column(String(50), nullable=False, index=True) # full, incremental, manual, webhook_triggered
|
||||
sync_direction = Column(String(20), nullable=False) # inbound, outbound, bidirectional
|
||||
data_type = Column(String(50), nullable=False, index=True) # transactions, products, customers, orders
|
||||
|
||||
# POS Provider Information
|
||||
pos_system = Column(String(50), nullable=False, index=True) # square, toast, lightspeed
|
||||
|
||||
# Sync Status
|
||||
status = Column(String(50), nullable=False, default="started", index=True) # started, in_progress, completed, failed, cancelled
|
||||
|
||||
# Timing Information
|
||||
started_at = Column(DateTime(timezone=True), nullable=False, index=True)
|
||||
completed_at = Column(DateTime(timezone=True), nullable=True)
|
||||
duration_seconds = Column(Numeric(10, 3), nullable=True)
|
||||
|
||||
# Date Range for Sync
|
||||
sync_from_date = Column(DateTime(timezone=True), nullable=True)
|
||||
sync_to_date = Column(DateTime(timezone=True), nullable=True)
|
||||
|
||||
# Statistics
|
||||
records_requested = Column(Integer, default=0, nullable=False)
|
||||
records_processed = Column(Integer, default=0, nullable=False)
|
||||
records_created = Column(Integer, default=0, nullable=False)
|
||||
records_updated = Column(Integer, default=0, nullable=False)
|
||||
records_skipped = Column(Integer, default=0, nullable=False)
|
||||
records_failed = Column(Integer, default=0, nullable=False)
|
||||
|
||||
# API Usage Statistics
|
||||
api_calls_made = Column(Integer, default=0, nullable=False)
|
||||
api_rate_limit_hits = Column(Integer, default=0, nullable=False)
|
||||
total_api_time_ms = Column(Integer, default=0, nullable=False)
|
||||
|
||||
# Error Information
|
||||
error_message = Column(Text, nullable=True)
|
||||
error_code = Column(String(100), nullable=True)
|
||||
error_details = Column(JSON, nullable=True)
|
||||
|
||||
# Retry Information
|
||||
retry_attempt = Column(Integer, default=0, nullable=False)
|
||||
max_retries = Column(Integer, default=3, nullable=False)
|
||||
parent_sync_id = Column(UUID(as_uuid=True), nullable=True) # Reference to original sync for retries
|
||||
|
||||
# Configuration Snapshot
|
||||
sync_configuration = Column(JSON, nullable=True) # Settings used for this sync
|
||||
|
||||
# Progress Tracking
|
||||
current_page = Column(Integer, nullable=True)
|
||||
total_pages = Column(Integer, nullable=True)
|
||||
current_batch = Column(Integer, nullable=True)
|
||||
total_batches = Column(Integer, nullable=True)
|
||||
progress_percentage = Column(Numeric(5, 2), nullable=True)
|
||||
|
||||
# Data Quality
|
||||
validation_errors = Column(JSON, nullable=True) # Array of validation issues
|
||||
data_quality_score = Column(Numeric(5, 2), nullable=True) # 0-100 score
|
||||
|
||||
# Performance Metrics
|
||||
memory_usage_mb = Column(Numeric(10, 2), nullable=True)
|
||||
cpu_usage_percentage = Column(Numeric(5, 2), nullable=True)
|
||||
network_bytes_received = Column(Integer, nullable=True)
|
||||
network_bytes_sent = Column(Integer, nullable=True)
|
||||
|
||||
# Business Impact
|
||||
revenue_synced = Column(Numeric(12, 2), nullable=True) # Total monetary value synced
|
||||
transactions_synced = Column(Integer, default=0, nullable=False)
|
||||
|
||||
# Trigger Information
|
||||
triggered_by = Column(String(50), nullable=True) # system, user, webhook, schedule
|
||||
triggered_by_user_id = Column(UUID(as_uuid=True), nullable=True)
|
||||
trigger_details = Column(JSON, nullable=True)
|
||||
|
||||
# External References
|
||||
external_batch_id = Column(String(255), nullable=True) # POS system's batch/job ID
|
||||
webhook_log_id = Column(UUID(as_uuid=True), nullable=True) # If triggered by webhook
|
||||
|
||||
# Timestamps
|
||||
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)
|
||||
|
||||
# Metadata
|
||||
notes = Column(Text, nullable=True)
|
||||
tags = Column(JSON, nullable=True) # Array of tags for categorization
|
||||
|
||||
# Indexes for performance
|
||||
__table_args__ = (
|
||||
Index('idx_sync_log_tenant_started', 'tenant_id', 'started_at'),
|
||||
Index('idx_sync_log_pos_system_type', 'pos_system', 'sync_type'),
|
||||
Index('idx_sync_log_status', 'status'),
|
||||
Index('idx_sync_log_data_type', 'data_type'),
|
||||
Index('idx_sync_log_trigger', 'triggered_by'),
|
||||
Index('idx_sync_log_completed', 'completed_at'),
|
||||
Index('idx_sync_log_duration', 'duration_seconds'),
|
||||
Index('idx_sync_log_retry', 'retry_attempt'),
|
||||
Index('idx_sync_log_parent', 'parent_sync_id'),
|
||||
Index('idx_sync_log_webhook', 'webhook_log_id'),
|
||||
Index('idx_sync_log_external_batch', 'external_batch_id'),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<POSSyncLog(id={self.id}, pos_system='{self.pos_system}', type='{self.sync_type}', status='{self.status}')>"
|
||||
174
services/pos/app/models/pos_transaction.py
Normal file
174
services/pos/app/models/pos_transaction.py
Normal file
@@ -0,0 +1,174 @@
|
||||
# services/pos/app/models/pos_transaction.py
|
||||
"""
|
||||
POS Transaction Models
|
||||
Stores transaction data from POS systems
|
||||
"""
|
||||
|
||||
from sqlalchemy import Column, String, DateTime, Boolean, Numeric, Integer, Text, JSON, Index, ForeignKey
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.orm import relationship
|
||||
import uuid
|
||||
|
||||
from shared.database.base import Base
|
||||
|
||||
|
||||
class POSTransaction(Base):
|
||||
"""
|
||||
Main transaction record from POS systems
|
||||
"""
|
||||
__tablename__ = "pos_transactions"
|
||||
|
||||
# Primary identifiers
|
||||
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
|
||||
tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
|
||||
pos_config_id = Column(UUID(as_uuid=True), ForeignKey("pos_configurations.id"), nullable=False, index=True)
|
||||
|
||||
# POS Provider Information
|
||||
pos_system = Column(String(50), nullable=False, index=True) # square, toast, lightspeed
|
||||
external_transaction_id = Column(String(255), nullable=False, index=True) # POS system's transaction ID
|
||||
external_order_id = Column(String(255), nullable=True, index=True) # POS system's order ID
|
||||
|
||||
# Transaction Details
|
||||
transaction_type = Column(String(50), nullable=False) # sale, refund, void, exchange
|
||||
status = Column(String(50), nullable=False) # completed, pending, failed, refunded, voided
|
||||
|
||||
# Financial Information
|
||||
subtotal = Column(Numeric(10, 2), nullable=False)
|
||||
tax_amount = Column(Numeric(10, 2), default=0, nullable=False)
|
||||
tip_amount = Column(Numeric(10, 2), default=0, nullable=False)
|
||||
discount_amount = Column(Numeric(10, 2), default=0, nullable=False)
|
||||
total_amount = Column(Numeric(10, 2), nullable=False)
|
||||
currency = Column(String(3), default="EUR", nullable=False)
|
||||
|
||||
# Payment Information
|
||||
payment_method = Column(String(50), nullable=True) # card, cash, digital_wallet, etc.
|
||||
payment_status = Column(String(50), nullable=True) # paid, pending, failed
|
||||
|
||||
# Transaction Timing
|
||||
transaction_date = Column(DateTime(timezone=True), nullable=False, index=True)
|
||||
pos_created_at = Column(DateTime(timezone=True), nullable=False) # Original POS timestamp
|
||||
pos_updated_at = Column(DateTime(timezone=True), nullable=True) # Last update in POS
|
||||
|
||||
# Location & Staff
|
||||
location_id = Column(String(100), nullable=True)
|
||||
location_name = Column(String(255), nullable=True)
|
||||
staff_id = Column(String(100), nullable=True)
|
||||
staff_name = Column(String(255), nullable=True)
|
||||
|
||||
# Customer Information
|
||||
customer_id = Column(String(100), nullable=True)
|
||||
customer_email = Column(String(255), nullable=True)
|
||||
customer_phone = Column(String(50), nullable=True)
|
||||
|
||||
# Order Context
|
||||
order_type = Column(String(50), nullable=True) # dine_in, takeout, delivery, pickup
|
||||
table_number = Column(String(20), nullable=True)
|
||||
receipt_number = Column(String(100), nullable=True)
|
||||
|
||||
# Sync Status
|
||||
is_synced_to_sales = Column(Boolean, default=False, nullable=False, index=True)
|
||||
sales_record_id = Column(UUID(as_uuid=True), nullable=True, index=True) # Reference to sales service
|
||||
sync_attempted_at = Column(DateTime(timezone=True), nullable=True)
|
||||
sync_completed_at = Column(DateTime(timezone=True), nullable=True)
|
||||
sync_error = Column(Text, nullable=True)
|
||||
sync_retry_count = Column(Integer, default=0, nullable=False)
|
||||
|
||||
# Raw Data
|
||||
raw_data = Column(JSON, nullable=True) # Complete raw response from POS
|
||||
|
||||
# Processing Status
|
||||
is_processed = Column(Boolean, default=False, nullable=False)
|
||||
processing_error = Column(Text, nullable=True)
|
||||
|
||||
# Duplicate Detection
|
||||
is_duplicate = Column(Boolean, default=False, nullable=False)
|
||||
duplicate_of = Column(UUID(as_uuid=True), nullable=True)
|
||||
|
||||
# Timestamps
|
||||
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)
|
||||
|
||||
# Relationships
|
||||
items = relationship("POSTransactionItem", back_populates="transaction", cascade="all, delete-orphan")
|
||||
|
||||
# Indexes for performance
|
||||
__table_args__ = (
|
||||
Index('idx_pos_transaction_tenant_date', 'tenant_id', 'transaction_date'),
|
||||
Index('idx_pos_transaction_external_id', 'pos_system', 'external_transaction_id'),
|
||||
Index('idx_pos_transaction_sync_status', 'is_synced_to_sales'),
|
||||
Index('idx_pos_transaction_status', 'status'),
|
||||
Index('idx_pos_transaction_type', 'transaction_type'),
|
||||
Index('idx_pos_transaction_processed', 'is_processed'),
|
||||
Index('idx_pos_transaction_duplicate', 'is_duplicate'),
|
||||
Index('idx_pos_transaction_location', 'location_id'),
|
||||
Index('idx_pos_transaction_customer', 'customer_id'),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<POSTransaction(id={self.id}, external_id='{self.external_transaction_id}', pos_system='{self.pos_system}', total={self.total_amount})>"
|
||||
|
||||
|
||||
class POSTransactionItem(Base):
|
||||
"""
|
||||
Individual items within a POS transaction
|
||||
"""
|
||||
__tablename__ = "pos_transaction_items"
|
||||
|
||||
# Primary identifiers
|
||||
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
|
||||
transaction_id = Column(UUID(as_uuid=True), ForeignKey("pos_transactions.id"), nullable=False, index=True)
|
||||
tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
|
||||
|
||||
# POS Item Information
|
||||
external_item_id = Column(String(255), nullable=True) # POS system's item ID
|
||||
sku = Column(String(100), nullable=True, index=True)
|
||||
|
||||
# Product Details
|
||||
product_name = Column(String(255), nullable=False)
|
||||
product_category = Column(String(100), nullable=True, index=True)
|
||||
product_subcategory = Column(String(100), nullable=True)
|
||||
|
||||
# Quantity & Pricing
|
||||
quantity = Column(Numeric(10, 3), nullable=False)
|
||||
unit_price = Column(Numeric(10, 2), nullable=False)
|
||||
total_price = Column(Numeric(10, 2), nullable=False)
|
||||
|
||||
# Discounts & Modifiers
|
||||
discount_amount = Column(Numeric(10, 2), default=0, nullable=False)
|
||||
tax_amount = Column(Numeric(10, 2), default=0, nullable=False)
|
||||
|
||||
# Modifiers (e.g., extra shot, no foam for coffee)
|
||||
modifiers = Column(JSON, nullable=True)
|
||||
|
||||
# Inventory Mapping
|
||||
inventory_product_id = Column(UUID(as_uuid=True), nullable=True, index=True) # Mapped to inventory service
|
||||
is_mapped_to_inventory = Column(Boolean, default=False, nullable=False)
|
||||
|
||||
# Sync Status
|
||||
is_synced_to_sales = Column(Boolean, default=False, nullable=False)
|
||||
sync_error = Column(Text, nullable=True)
|
||||
|
||||
# Raw Data
|
||||
raw_data = Column(JSON, nullable=True)
|
||||
|
||||
# Timestamps
|
||||
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)
|
||||
|
||||
# Relationships
|
||||
transaction = relationship("POSTransaction", back_populates="items")
|
||||
|
||||
# Indexes for performance
|
||||
__table_args__ = (
|
||||
Index('idx_pos_item_transaction', 'transaction_id'),
|
||||
Index('idx_pos_item_product', 'product_name'),
|
||||
Index('idx_pos_item_category', 'product_category'),
|
||||
Index('idx_pos_item_sku', 'sku'),
|
||||
Index('idx_pos_item_inventory', 'inventory_product_id'),
|
||||
Index('idx_pos_item_sync', 'is_synced_to_sales'),
|
||||
Index('idx_pos_item_mapped', 'is_mapped_to_inventory'),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<POSTransactionItem(id={self.id}, product='{self.product_name}', quantity={self.quantity}, price={self.total_price})>"
|
||||
109
services/pos/app/models/pos_webhook.py
Normal file
109
services/pos/app/models/pos_webhook.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# 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}')>"
|
||||
Reference in New Issue
Block a user