Files
bakery-ia/services/pos/app/core/config.py

192 lines
8.8 KiB
Python

# services/pos/app/core/config.py
"""
POS Integration Service Configuration
"""
import os
from typing import List, Optional
from pydantic import Field
from shared.config.base import BaseServiceSettings
class Settings(BaseServiceSettings):
"""POS Integration service settings extending base configuration"""
# Override service-specific settings
SERVICE_NAME: str = "pos-service"
VERSION: str = "1.0.0"
APP_NAME: str = "Bakery POS Integration Service"
DESCRIPTION: str = "Integration service for external POS systems (Square, Toast, Lightspeed)"
# API Configuration
API_V1_STR: str = "/api/v1"
# Database configuration (secure approach - build from components)
@property
def DATABASE_URL(self) -> str:
"""Build database URL from secure components"""
# Try complete URL first (for backward compatibility)
complete_url = os.getenv("POS_DATABASE_URL")
if complete_url:
return complete_url
# Build from components (secure approach)
user = os.getenv("POS_DB_USER", "pos_user")
password = os.getenv("POS_DB_PASSWORD", "pos_pass123")
host = os.getenv("POS_DB_HOST", "localhost")
port = os.getenv("POS_DB_PORT", "5432")
name = os.getenv("POS_DB_NAME", "pos_db")
return f"postgresql+asyncpg://{user}:{password}@{host}:{port}/{name}"
# POS-specific Redis database
REDIS_DB: int = Field(default=5, env="POS_REDIS_DB")
# ================================================================
# POS PROVIDER CONFIGURATIONS
# ================================================================
# Square POS Configuration
SQUARE_APPLICATION_ID: Optional[str] = Field(default=None, env="SQUARE_APPLICATION_ID")
SQUARE_ACCESS_TOKEN: Optional[str] = Field(default=None, env="SQUARE_ACCESS_TOKEN")
SQUARE_WEBHOOK_SIGNATURE_KEY: Optional[str] = Field(default=None, env="SQUARE_WEBHOOK_SIGNATURE_KEY")
SQUARE_ENVIRONMENT: str = Field(default="sandbox", env="SQUARE_ENVIRONMENT") # sandbox or production
SQUARE_BASE_URL: str = "https://connect.squareup.com"
SQUARE_SANDBOX_URL: str = "https://connect.squareupsandbox.com"
@property
def SQUARE_API_URL(self) -> str:
return self.SQUARE_SANDBOX_URL if self.SQUARE_ENVIRONMENT == "sandbox" else self.SQUARE_BASE_URL
# Toast POS Configuration
TOAST_CLIENT_ID: Optional[str] = Field(default=None, env="TOAST_CLIENT_ID")
TOAST_CLIENT_SECRET: Optional[str] = Field(default=None, env="TOAST_CLIENT_SECRET")
TOAST_WEBHOOK_SECRET: Optional[str] = Field(default=None, env="TOAST_WEBHOOK_SECRET")
TOAST_ENVIRONMENT: str = Field(default="sandbox", env="TOAST_ENVIRONMENT") # sandbox or production
TOAST_BASE_URL: str = "https://ws-api.toasttab.com"
TOAST_SANDBOX_URL: str = "https://ws-sandbox-api.toasttab.com"
@property
def TOAST_API_URL(self) -> str:
return self.TOAST_SANDBOX_URL if self.TOAST_ENVIRONMENT == "sandbox" else self.TOAST_BASE_URL
# Lightspeed POS Configuration
LIGHTSPEED_CLIENT_ID: Optional[str] = Field(default=None, env="LIGHTSPEED_CLIENT_ID")
LIGHTSPEED_CLIENT_SECRET: Optional[str] = Field(default=None, env="LIGHTSPEED_CLIENT_SECRET")
LIGHTSPEED_WEBHOOK_SECRET: Optional[str] = Field(default=None, env="LIGHTSPEED_WEBHOOK_SECRET")
LIGHTSPEED_CLUSTER_ID: Optional[str] = Field(default=None, env="LIGHTSPEED_CLUSTER_ID")
LIGHTSPEED_BASE_URL: str = "https://api-{cluster}.lightspeedhq.com"
def get_lightspeed_api_url(self, cluster_id: Optional[str] = None) -> str:
cluster = cluster_id or self.LIGHTSPEED_CLUSTER_ID or "us1"
return self.LIGHTSPEED_BASE_URL.format(cluster=cluster)
# ================================================================
# WEBHOOK CONFIGURATION
# ================================================================
# Webhook Base Configuration
WEBHOOK_BASE_URL: str = Field(default="https://your-domain.com", env="WEBHOOK_BASE_URL")
WEBHOOK_SECRET: str = Field(default="your-webhook-secret", env="WEBHOOK_SECRET")
WEBHOOK_TIMEOUT_SECONDS: int = Field(default=30, env="WEBHOOK_TIMEOUT_SECONDS")
# Webhook Rate Limiting
WEBHOOK_RATE_LIMIT_PER_MINUTE: int = Field(default=1000, env="WEBHOOK_RATE_LIMIT_PER_MINUTE")
WEBHOOK_BURST_LIMIT: int = Field(default=100, env="WEBHOOK_BURST_LIMIT")
# Webhook Retry Configuration
WEBHOOK_MAX_RETRIES: int = Field(default=3, env="WEBHOOK_MAX_RETRIES")
WEBHOOK_RETRY_DELAY_SECONDS: int = Field(default=5, env="WEBHOOK_RETRY_DELAY_SECONDS")
# ================================================================
# SYNC CONFIGURATION
# ================================================================
# Data Synchronization Settings
SYNC_ENABLED: bool = Field(default=True, env="POS_SYNC_ENABLED")
SYNC_INTERVAL_SECONDS: int = Field(default=300, env="POS_SYNC_INTERVAL_SECONDS") # 5 minutes
SYNC_BATCH_SIZE: int = Field(default=100, env="POS_SYNC_BATCH_SIZE")
SYNC_MAX_RETRY_ATTEMPTS: int = Field(default=3, env="POS_SYNC_MAX_RETRY_ATTEMPTS")
SYNC_RETRY_DELAY_SECONDS: int = Field(default=60, env="POS_SYNC_RETRY_DELAY_SECONDS")
# Historical Data Sync
HISTORICAL_SYNC_DAYS: int = Field(default=30, env="POS_HISTORICAL_SYNC_DAYS")
INITIAL_SYNC_BATCH_SIZE: int = Field(default=50, env="POS_INITIAL_SYNC_BATCH_SIZE")
# ================================================================
# SECURITY & ENCRYPTION
# ================================================================
# API Credential Encryption
ENCRYPTION_KEY: Optional[str] = Field(default=None, env="POS_ENCRYPTION_KEY")
CREDENTIALS_ENCRYPTION_ENABLED: bool = Field(default=True, env="POS_CREDENTIALS_ENCRYPTION_ENABLED")
# API Rate Limiting
API_RATE_LIMIT_PER_MINUTE: int = Field(default=60, env="POS_API_RATE_LIMIT_PER_MINUTE")
API_BURST_LIMIT: int = Field(default=10, env="POS_API_BURST_LIMIT")
# ================================================================
# CACHING CONFIGURATION
# ================================================================
# POS Data Cache TTL
POS_CONFIG_CACHE_TTL: int = Field(default=3600, env="POS_CONFIG_CACHE_TTL") # 1 hour
POS_TRANSACTION_CACHE_TTL: int = Field(default=300, env="POS_TRANSACTION_CACHE_TTL") # 5 minutes
POS_PRODUCT_CACHE_TTL: int = Field(default=1800, env="POS_PRODUCT_CACHE_TTL") # 30 minutes
# ================================================================
# SUPPORTED POS SYSTEMS
# ================================================================
SUPPORTED_POS_SYSTEMS: List[str] = ["square", "toast", "lightspeed"]
# Default POS system for new tenants
DEFAULT_POS_SYSTEM: str = Field(default="square", env="DEFAULT_POS_SYSTEM")
# ================================================================
# INTER-SERVICE COMMUNICATION
# ================================================================
# Override service URLs
SALES_SERVICE_URL: str = Field(
default="http://sales-service:8000",
env="SALES_SERVICE_URL"
)
INVENTORY_SERVICE_URL: str = Field(
default="http://inventory-service:8000",
env="INVENTORY_SERVICE_URL"
)
# ================================================================
# BUSINESS RULES
# ================================================================
# Transaction Processing
MIN_TRANSACTION_AMOUNT: float = Field(default=0.01, env="POS_MIN_TRANSACTION_AMOUNT")
MAX_TRANSACTION_AMOUNT: float = Field(default=10000.0, env="POS_MAX_TRANSACTION_AMOUNT")
# Duplicate Detection Window (in minutes)
DUPLICATE_DETECTION_WINDOW: int = Field(default=5, env="POS_DUPLICATE_DETECTION_WINDOW")
# Data Retention
TRANSACTION_RETENTION_DAYS: int = Field(default=1095, env="POS_TRANSACTION_RETENTION_DAYS") # 3 years
WEBHOOK_LOG_RETENTION_DAYS: int = Field(default=30, env="POS_WEBHOOK_LOG_RETENTION_DAYS")
SYNC_LOG_RETENTION_DAYS: int = Field(default=90, env="POS_SYNC_LOG_RETENTION_DAYS")
# ================================================================
# MONITORING & ALERTING
# ================================================================
# Health Check Configuration
POS_HEALTH_CHECK_ENABLED: bool = Field(default=True, env="POS_HEALTH_CHECK_ENABLED")
POS_HEALTH_CHECK_INTERVAL: int = Field(default=60, env="POS_HEALTH_CHECK_INTERVAL") # seconds
# Alert Thresholds
WEBHOOK_FAILURE_THRESHOLD: int = Field(default=5, env="POS_WEBHOOK_FAILURE_THRESHOLD")
SYNC_FAILURE_THRESHOLD: int = Field(default=3, env="POS_SYNC_FAILURE_THRESHOLD")
API_ERROR_THRESHOLD: int = Field(default=10, env="POS_API_ERROR_THRESHOLD")
# Global settings instance
settings = Settings()