feat: add multi-platform CMS architecture (Phase 1)
Implement the foundation for multi-platform support allowing independent business offerings (OMS, Loyalty, etc.) with their own CMS pages. Database Models: - Add Platform model for business offerings (domain, branding, config) - Add VendorPlatform junction table for many-to-many relationship - Update SubscriptionTier with platform_id and CMS limits - Update ContentPage with platform_id, is_platform_page for three-tier hierarchy - Add CMS feature codes (cms_basic, cms_custom_pages, cms_templates, etc.) Three-Tier Content Resolution: 1. Vendor override (platform_id + vendor_id + slug) 2. Vendor default (platform_id + vendor_id=NULL + is_platform_page=False) 3. Platform marketing pages (is_platform_page=True) New Components: - PlatformContextMiddleware for detecting platform from domain/path - ContentPageService updated with full three-tier resolution - Platform folder structure (app/platforms/oms/, app/platforms/loyalty/) - Alembic migration with backfill for existing data Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
15
app/platforms/__init__.py
Normal file
15
app/platforms/__init__.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# app/platforms/__init__.py
|
||||
"""
|
||||
Platform-specific code and configurations.
|
||||
|
||||
Each platform (OMS, Loyalty, etc.) has its own:
|
||||
- routes/: Platform-specific routes
|
||||
- templates/: Platform-specific templates
|
||||
- config.py: Platform configuration
|
||||
|
||||
Shared code that applies to all platforms lives in shared/.
|
||||
"""
|
||||
|
||||
from .shared.base_platform import BasePlatformConfig
|
||||
|
||||
__all__ = ["BasePlatformConfig"]
|
||||
10
app/platforms/loyalty/__init__.py
Normal file
10
app/platforms/loyalty/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# app/platforms/loyalty/__init__.py
|
||||
"""
|
||||
Loyalty Platform
|
||||
|
||||
Platform for customer loyalty programs and rewards.
|
||||
"""
|
||||
|
||||
from .config import LoyaltyPlatformConfig
|
||||
|
||||
__all__ = ["LoyaltyPlatformConfig"]
|
||||
49
app/platforms/loyalty/config.py
Normal file
49
app/platforms/loyalty/config.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# app/platforms/loyalty/config.py
|
||||
"""
|
||||
Loyalty Platform Configuration
|
||||
|
||||
Configuration for the Loyalty/Rewards platform.
|
||||
"""
|
||||
|
||||
from app.platforms.shared.base_platform import BasePlatformConfig
|
||||
|
||||
|
||||
class LoyaltyPlatformConfig(BasePlatformConfig):
|
||||
"""Configuration for the Loyalty platform."""
|
||||
|
||||
@property
|
||||
def code(self) -> str:
|
||||
return "loyalty"
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "Loyalty+"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return "Customer loyalty and rewards platform"
|
||||
|
||||
@property
|
||||
def features(self) -> list[str]:
|
||||
"""Loyalty-specific features."""
|
||||
return [
|
||||
"loyalty_points",
|
||||
"rewards_catalog",
|
||||
"customer_tiers",
|
||||
"referral_program",
|
||||
]
|
||||
|
||||
@property
|
||||
def vendor_default_page_slugs(self) -> list[str]:
|
||||
"""Default pages for Loyalty vendor storefronts."""
|
||||
return [
|
||||
"about",
|
||||
"how-it-works",
|
||||
"rewards",
|
||||
"terms-of-service",
|
||||
"privacy-policy",
|
||||
]
|
||||
|
||||
|
||||
# Singleton instance
|
||||
loyalty_config = LoyaltyPlatformConfig()
|
||||
2
app/platforms/loyalty/routes/__init__.py
Normal file
2
app/platforms/loyalty/routes/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# app/platforms/loyalty/routes/__init__.py
|
||||
"""Loyalty platform routes."""
|
||||
2
app/platforms/loyalty/templates/__init__.py
Normal file
2
app/platforms/loyalty/templates/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# app/platforms/loyalty/templates/__init__.py
|
||||
"""Loyalty platform templates."""
|
||||
10
app/platforms/oms/__init__.py
Normal file
10
app/platforms/oms/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# app/platforms/oms/__init__.py
|
||||
"""
|
||||
OMS (Order Management System) Platform
|
||||
|
||||
The primary platform for managing orders, products, and vendor storefronts.
|
||||
"""
|
||||
|
||||
from .config import OMSPlatformConfig
|
||||
|
||||
__all__ = ["OMSPlatformConfig"]
|
||||
52
app/platforms/oms/config.py
Normal file
52
app/platforms/oms/config.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# app/platforms/oms/config.py
|
||||
"""
|
||||
OMS Platform Configuration
|
||||
|
||||
Configuration for the Order Management System platform.
|
||||
"""
|
||||
|
||||
from app.platforms.shared.base_platform import BasePlatformConfig
|
||||
|
||||
|
||||
class OMSPlatformConfig(BasePlatformConfig):
|
||||
"""Configuration for the OMS platform."""
|
||||
|
||||
@property
|
||||
def code(self) -> str:
|
||||
return "oms"
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "Wizamart OMS"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return "Order Management System for Luxembourg merchants"
|
||||
|
||||
@property
|
||||
def features(self) -> list[str]:
|
||||
"""OMS-specific features."""
|
||||
return [
|
||||
"order_management",
|
||||
"inventory_basic",
|
||||
"invoice_lu",
|
||||
"letzshop_sync",
|
||||
"customer_view",
|
||||
]
|
||||
|
||||
@property
|
||||
def vendor_default_page_slugs(self) -> list[str]:
|
||||
"""Default pages for OMS vendor storefronts."""
|
||||
return [
|
||||
"about",
|
||||
"shipping",
|
||||
"returns",
|
||||
"privacy-policy",
|
||||
"terms-of-service",
|
||||
"contact",
|
||||
"faq",
|
||||
]
|
||||
|
||||
|
||||
# Singleton instance
|
||||
oms_config = OMSPlatformConfig()
|
||||
2
app/platforms/oms/routes/__init__.py
Normal file
2
app/platforms/oms/routes/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# app/platforms/oms/routes/__init__.py
|
||||
"""OMS platform routes."""
|
||||
2
app/platforms/oms/templates/__init__.py
Normal file
2
app/platforms/oms/templates/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# app/platforms/oms/templates/__init__.py
|
||||
"""OMS platform templates."""
|
||||
6
app/platforms/shared/__init__.py
Normal file
6
app/platforms/shared/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# app/platforms/shared/__init__.py
|
||||
"""Shared platform code and base classes."""
|
||||
|
||||
from .base_platform import BasePlatformConfig
|
||||
|
||||
__all__ = ["BasePlatformConfig"]
|
||||
97
app/platforms/shared/base_platform.py
Normal file
97
app/platforms/shared/base_platform.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# app/platforms/shared/base_platform.py
|
||||
"""
|
||||
Base Platform Configuration
|
||||
|
||||
Provides a base class for platform-specific configurations.
|
||||
Each platform (OMS, Loyalty, etc.) should extend this class.
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any
|
||||
|
||||
|
||||
class BasePlatformConfig(ABC):
|
||||
"""
|
||||
Base configuration class for platforms.
|
||||
|
||||
Each platform should create a config.py that extends this class
|
||||
and provides platform-specific settings.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def code(self) -> str:
|
||||
"""Unique platform code (e.g., 'oms', 'loyalty')."""
|
||||
pass
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def name(self) -> str:
|
||||
"""Display name (e.g., 'Wizamart OMS')."""
|
||||
pass
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
"""Platform description."""
|
||||
return ""
|
||||
|
||||
@property
|
||||
def default_language(self) -> str:
|
||||
"""Default language code."""
|
||||
return "fr"
|
||||
|
||||
@property
|
||||
def supported_languages(self) -> list[str]:
|
||||
"""List of supported language codes."""
|
||||
return ["fr", "de", "en"]
|
||||
|
||||
@property
|
||||
def theme_defaults(self) -> dict[str, Any]:
|
||||
"""Default theme configuration."""
|
||||
return {
|
||||
"primary_color": "#6366f1",
|
||||
"secondary_color": "#8b5cf6",
|
||||
"font_family": "Inter, sans-serif",
|
||||
}
|
||||
|
||||
@property
|
||||
def features(self) -> list[str]:
|
||||
"""List of feature codes enabled for this platform."""
|
||||
return []
|
||||
|
||||
@property
|
||||
def marketing_page_slugs(self) -> list[str]:
|
||||
"""
|
||||
Slugs that should be treated as platform marketing pages.
|
||||
|
||||
These pages describe the platform itself (pricing, features, etc.)
|
||||
rather than being vendor storefront content.
|
||||
"""
|
||||
return [
|
||||
"home",
|
||||
"platform_homepage",
|
||||
"pricing",
|
||||
"about",
|
||||
"contact",
|
||||
"faq",
|
||||
"terms",
|
||||
"privacy",
|
||||
"features",
|
||||
"integrations",
|
||||
]
|
||||
|
||||
@property
|
||||
def vendor_default_page_slugs(self) -> list[str]:
|
||||
"""
|
||||
Slugs for default vendor storefront pages.
|
||||
|
||||
These pages provide fallback content for vendors who haven't
|
||||
customized their storefront.
|
||||
"""
|
||||
return [
|
||||
"about",
|
||||
"shipping",
|
||||
"returns",
|
||||
"privacy-policy",
|
||||
"terms-of-service",
|
||||
]
|
||||
2
app/platforms/shared/routes/__init__.py
Normal file
2
app/platforms/shared/routes/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# app/platforms/shared/routes/__init__.py
|
||||
"""Shared platform routes."""
|
||||
2
app/platforms/shared/templates/__init__.py
Normal file
2
app/platforms/shared/templates/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# app/platforms/shared/templates/__init__.py
|
||||
"""Shared platform templates."""
|
||||
Reference in New Issue
Block a user