Files
orion/alembic/versions_backup/z5f6g7h8i9j0_add_loyalty_platform.py
Samir Boulahtit aad18c27ab
Some checks failed
CI / ruff (push) Successful in 11s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
refactor: remove all backward compatibility code across 70 files
Clean up 28 backward compatibility instances identified in the codebase.
The app is not live, so all shims are replaced with the target architecture:

- Remove legacy Inventory.location column (use bin_location exclusively)
- Remove dashboard _extract_metric_value helper (use flat metrics dict)
- Remove legacy stat field duplicates (total_stores, total_imports, etc.)
- Remove 13 re-export shims and class aliases across modules
- Remove module-enabling JSON fallback (use PlatformModule junction table)
- Remove menu_to_legacy_format() conversion (return dataclasses directly)
- Remove title/description from MarketplaceProductBase schema
- Clean billing convenience method docstrings
- Clean test fixtures and backward-compat comments
- Add PlatformModule seeding to init_production.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:20:29 +01:00

426 lines
16 KiB
Python

"""add loyalty platform
Revision ID: z5f6g7h8i9j0
Revises: z4e5f6a7b8c9
Create Date: 2026-01-19 12:00:00.000000
This migration adds the Loyalty+ platform:
1. Inserts loyalty platform record
2. Creates platform marketing pages (home, pricing, features, how-it-works)
3. Creates vendor default pages (about, rewards-catalog, terms, privacy)
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "z5f6g7h8i9j0"
down_revision: str | None = "z4e5f6a7b8c9"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
conn = op.get_bind()
# =========================================================================
# 1. Insert Loyalty platform
# =========================================================================
conn.execute(
sa.text("""
INSERT INTO platforms (code, name, description, domain, path_prefix, default_language,
supported_languages, is_active, is_public, theme_config, settings,
created_at, updated_at)
VALUES ('loyalty', 'Loyalty+', 'Customer loyalty program platform for Luxembourg businesses',
'rewardflow.lu', 'loyalty', 'fr', '["fr", "de", "en"]', true, true,
'{"primary_color": "#8B5CF6", "secondary_color": "#A78BFA"}',
'{"features": ["points", "rewards", "tiers", "analytics"]}',
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
""")
)
# Get the Loyalty platform ID
result = conn.execute(sa.text("SELECT id FROM platforms WHERE code = 'loyalty'"))
loyalty_platform_id = result.fetchone()[0]
# =========================================================================
# 2. Create platform marketing pages (is_platform_page=True)
# =========================================================================
platform_pages = [
{
"slug": "home",
"title": "Loyalty+ - Customer Loyalty Platform",
"content": """<div class="hero-section">
<h1>Build Customer Loyalty That Lasts</h1>
<p class="lead">Reward your customers, increase retention, and grow your business with Loyalty+</p>
</div>
<div class="features-grid">
<div class="feature">
<h3>Points & Rewards</h3>
<p>Create custom point systems that incentivize repeat purchases and customer engagement.</p>
</div>
<div class="feature">
<h3>Member Tiers</h3>
<p>Reward your best customers with exclusive benefits and VIP treatment.</p>
</div>
<div class="feature">
<h3>Real-time Analytics</h3>
<p>Track program performance and customer behavior with detailed insights.</p>
</div>
</div>""",
"meta_description": "Loyalty+ is Luxembourg's leading customer loyalty platform. Build lasting relationships with your customers through points, rewards, and personalized experiences.",
"show_in_header": False,
"show_in_footer": False,
"display_order": 0,
},
{
"slug": "pricing",
"title": "Pricing - Loyalty+",
"content": """<div class="pricing-header">
<h1>Simple, Transparent Pricing</h1>
<p>Choose the plan that fits your business</p>
</div>
<div class="pricing-grid">
<div class="pricing-card">
<h3>Starter</h3>
<div class="price">€49<span>/month</span></div>
<ul>
<li>Up to 500 members</li>
<li>Basic point system</li>
<li>Email support</li>
<li>Standard rewards</li>
</ul>
</div>
<div class="pricing-card featured">
<h3>Growth</h3>
<div class="price">€149<span>/month</span></div>
<ul>
<li>Up to 5,000 members</li>
<li>Advanced point rules</li>
<li>Priority support</li>
<li>Custom rewards</li>
<li>Member tiers</li>
<li>Analytics dashboard</li>
</ul>
</div>
<div class="pricing-card">
<h3>Enterprise</h3>
<div class="price">Custom</div>
<ul>
<li>Unlimited members</li>
<li>Full API access</li>
<li>Dedicated support</li>
<li>Custom integrations</li>
<li>White-label options</li>
</ul>
</div>
</div>""",
"meta_description": "Loyalty+ pricing plans starting at €49/month. Choose Starter, Growth, or Enterprise for your customer loyalty program.",
"show_in_header": True,
"show_in_footer": True,
"display_order": 1,
},
{
"slug": "features",
"title": "Features - Loyalty+",
"content": """<div class="features-header">
<h1>Powerful Features for Modern Loyalty</h1>
<p>Everything you need to build and manage a successful loyalty program</p>
</div>
<div class="feature-section">
<h2>Points & Earning Rules</h2>
<p>Create flexible point systems with custom earning rules based on purchases, actions, or special events.</p>
<ul>
<li>Points per euro spent</li>
<li>Bonus point campaigns</li>
<li>Birthday & anniversary rewards</li>
<li>Referral bonuses</li>
</ul>
</div>
<div class="feature-section">
<h2>Rewards Catalog</h2>
<p>Offer enticing rewards that keep customers coming back.</p>
<ul>
<li>Discount vouchers</li>
<li>Free products</li>
<li>Exclusive experiences</li>
<li>Partner rewards</li>
</ul>
</div>
<div class="feature-section">
<h2>Member Tiers</h2>
<p>Recognize and reward your most loyal customers with tiered benefits.</p>
<ul>
<li>Bronze, Silver, Gold, Platinum levels</li>
<li>Automatic tier progression</li>
<li>Exclusive tier benefits</li>
<li>VIP experiences</li>
</ul>
</div>
<div class="feature-section">
<h2>Analytics & Insights</h2>
<p>Make data-driven decisions with comprehensive analytics.</p>
<ul>
<li>Member activity tracking</li>
<li>Redemption analytics</li>
<li>ROI calculations</li>
<li>Custom reports</li>
</ul>
</div>""",
"meta_description": "Explore Loyalty+ features: points systems, rewards catalog, member tiers, and analytics. Build the perfect loyalty program for your business.",
"show_in_header": True,
"show_in_footer": True,
"display_order": 2,
},
{
"slug": "how-it-works",
"title": "How It Works - Loyalty+",
"content": """<div class="how-header">
<h1>Getting Started is Easy</h1>
<p>Launch your loyalty program in just a few steps</p>
</div>
<div class="steps">
<div class="step">
<div class="step-number">1</div>
<h3>Sign Up</h3>
<p>Create your account and choose your plan. No credit card required for the free trial.</p>
</div>
<div class="step">
<div class="step-number">2</div>
<h3>Configure Your Program</h3>
<p>Set up your point rules, rewards, and member tiers using our intuitive dashboard.</p>
</div>
<div class="step">
<div class="step-number">3</div>
<h3>Integrate</h3>
<p>Connect Loyalty+ to your POS, e-commerce, or app using our APIs and plugins.</p>
</div>
<div class="step">
<div class="step-number">4</div>
<h3>Launch & Grow</h3>
<p>Invite your customers and watch your loyalty program drive results.</p>
</div>
</div>
<div class="cta-section">
<h2>Ready to Build Customer Loyalty?</h2>
<p>Start your free 14-day trial today.</p>
<a href="/loyalty/signup" class="btn-primary">Get Started Free</a>
</div>""",
"meta_description": "Learn how to launch your Loyalty+ program in 4 easy steps. Sign up, configure, integrate, and start building customer loyalty today.",
"show_in_header": True,
"show_in_footer": True,
"display_order": 3,
},
]
for page in platform_pages:
conn.execute(
sa.text("""
INSERT INTO content_pages (platform_id, vendor_id, slug, title, content, content_format,
meta_description, is_published, is_platform_page,
show_in_header, show_in_footer, display_order,
created_at, updated_at)
VALUES (:platform_id, NULL, :slug, :title, :content, 'html',
:meta_description, true, true,
:show_in_header, :show_in_footer, :display_order,
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
"""),
{
"platform_id": loyalty_platform_id,
"slug": page["slug"],
"title": page["title"],
"content": page["content"],
"meta_description": page["meta_description"],
"show_in_header": page["show_in_header"],
"show_in_footer": page["show_in_footer"],
"display_order": page["display_order"],
}
)
# =========================================================================
# 3. Create vendor default pages (is_platform_page=False)
# =========================================================================
vendor_defaults = [
{
"slug": "about",
"title": "About Us",
"content": """<div class="about-page">
<h1>About Our Loyalty Program</h1>
<p>Welcome to our customer loyalty program! We value your continued support and want to reward you for being part of our community.</p>
<h2>Why Join?</h2>
<ul>
<li><strong>Earn Points:</strong> Get points on every purchase</li>
<li><strong>Exclusive Rewards:</strong> Redeem points for discounts and special offers</li>
<li><strong>Member Benefits:</strong> Access exclusive deals and early sales</li>
<li><strong>Birthday Surprises:</strong> Special rewards on your birthday</li>
</ul>
<h2>How It Works</h2>
<p>Simply sign up, start earning points with every purchase, and redeem them for rewards you'll love.</p>
</div>""",
"meta_description": "Learn about our customer loyalty program. Earn points, unlock rewards, and enjoy exclusive member benefits.",
"show_in_header": False,
"show_in_footer": True,
"display_order": 10,
},
{
"slug": "rewards-catalog",
"title": "Rewards Catalog",
"content": """<div class="rewards-page">
<h1>Rewards Catalog</h1>
<p>Browse our selection of rewards and redeem your hard-earned points!</p>
<div class="rewards-grid">
<div class="reward-placeholder">
<p>Your rewards catalog will appear here once configured.</p>
</div>
</div>
<h2>How to Redeem</h2>
<ol>
<li>Check your point balance in your account</li>
<li>Browse available rewards</li>
<li>Click "Redeem" on your chosen reward</li>
<li>Use your reward code at checkout</li>
</ol>
</div>""",
"meta_description": "Browse and redeem your loyalty points for exclusive rewards, discounts, and special offers.",
"show_in_header": True,
"show_in_footer": True,
"display_order": 11,
},
{
"slug": "terms",
"title": "Loyalty Program Terms & Conditions",
"content": """<div class="terms-page">
<h1>Loyalty Program Terms & Conditions</h1>
<p class="last-updated">Last updated: January 2026</p>
<h2>1. Program Membership</h2>
<p>Membership in our loyalty program is free and open to all customers who meet the eligibility requirements.</p>
<h2>2. Earning Points</h2>
<p>Points are earned on qualifying purchases. The earning rate and qualifying purchases are determined by the program operator and may change with notice.</p>
<h2>3. Redeeming Points</h2>
<p>Points can be redeemed for rewards as shown in the rewards catalog. Minimum point thresholds may apply.</p>
<h2>4. Point Expiration</h2>
<p>Points may expire after a period of account inactivity. Members will be notified before points expire.</p>
<h2>5. Program Changes</h2>
<p>We reserve the right to modify, suspend, or terminate the program with reasonable notice to members.</p>
<h2>6. Privacy</h2>
<p>Your personal information is handled in accordance with our Privacy Policy.</p>
</div>""",
"meta_description": "Read the terms and conditions for our customer loyalty program including earning rules, redemption, and point expiration policies.",
"show_in_header": False,
"show_in_footer": True,
"show_in_legal": True,
"display_order": 20,
},
{
"slug": "privacy",
"title": "Privacy Policy",
"content": """<div class="privacy-page">
<h1>Privacy Policy</h1>
<p class="last-updated">Last updated: January 2026</p>
<h2>Information We Collect</h2>
<p>We collect information you provide when joining our loyalty program, including:</p>
<ul>
<li>Name and contact information</li>
<li>Purchase history and preferences</li>
<li>Point balance and redemption history</li>
</ul>
<h2>How We Use Your Information</h2>
<p>Your information helps us:</p>
<ul>
<li>Manage your loyalty account</li>
<li>Process point earnings and redemptions</li>
<li>Send program updates and personalized offers</li>
<li>Improve our services</li>
</ul>
<h2>Data Protection</h2>
<p>We implement appropriate security measures to protect your personal information in accordance with GDPR and Luxembourg data protection laws.</p>
<h2>Your Rights</h2>
<p>You have the right to access, correct, or delete your personal data. Contact us to exercise these rights.</p>
<h2>Contact</h2>
<p>For privacy inquiries, please contact our data protection officer.</p>
</div>""",
"meta_description": "Our privacy policy explains how we collect, use, and protect your personal information in our loyalty program.",
"show_in_header": False,
"show_in_footer": True,
"show_in_legal": True,
"display_order": 21,
},
]
for page in vendor_defaults:
show_in_legal = page.get("show_in_legal", False)
conn.execute(
sa.text("""
INSERT INTO content_pages (platform_id, vendor_id, slug, title, content, content_format,
meta_description, is_published, is_platform_page,
show_in_header, show_in_footer, show_in_legal, display_order,
created_at, updated_at)
VALUES (:platform_id, NULL, :slug, :title, :content, 'html',
:meta_description, true, false,
:show_in_header, :show_in_footer, :show_in_legal, :display_order,
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
"""),
{
"platform_id": loyalty_platform_id,
"slug": page["slug"],
"title": page["title"],
"content": page["content"],
"meta_description": page["meta_description"],
"show_in_header": page["show_in_header"],
"show_in_footer": page["show_in_footer"],
"show_in_legal": show_in_legal,
"display_order": page["display_order"],
}
)
def downgrade() -> None:
conn = op.get_bind()
# Get the Loyalty platform ID
result = conn.execute(sa.text("SELECT id FROM platforms WHERE code = 'loyalty'"))
row = result.fetchone()
if row:
loyalty_platform_id = row[0]
# Delete all content pages for loyalty platform
conn.execute(
sa.text("DELETE FROM content_pages WHERE platform_id = :platform_id"),
{"platform_id": loyalty_platform_id}
)
# Delete vendor_platforms entries for loyalty
conn.execute(
sa.text("DELETE FROM vendor_platforms WHERE platform_id = :platform_id"),
{"platform_id": loyalty_platform_id}
)
# Delete loyalty platform
conn.execute(sa.text("DELETE FROM platforms WHERE code = 'loyalty'"))