"""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": """
Build Customer Loyalty That Lasts
Reward your customers, increase retention, and grow your business with Loyalty+
Points & Rewards
Create custom point systems that incentivize repeat purchases and customer engagement.
Member Tiers
Reward your best customers with exclusive benefits and VIP treatment.
Real-time Analytics
Track program performance and customer behavior with detailed insights.
""",
"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": """
Starter
€49/month
- Up to 500 members
- Basic point system
- Email support
- Standard rewards
Growth
€149/month
- Up to 5,000 members
- Advanced point rules
- Priority support
- Custom rewards
- Member tiers
- Analytics dashboard
Enterprise
Custom
- Unlimited members
- Full API access
- Dedicated support
- Custom integrations
- White-label options
""",
"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": """
Points & Earning Rules
Create flexible point systems with custom earning rules based on purchases, actions, or special events.
- Points per euro spent
- Bonus point campaigns
- Birthday & anniversary rewards
- Referral bonuses
Rewards Catalog
Offer enticing rewards that keep customers coming back.
- Discount vouchers
- Free products
- Exclusive experiences
- Partner rewards
Member Tiers
Recognize and reward your most loyal customers with tiered benefits.
- Bronze, Silver, Gold, Platinum levels
- Automatic tier progression
- Exclusive tier benefits
- VIP experiences
Analytics & Insights
Make data-driven decisions with comprehensive analytics.
- Member activity tracking
- Redemption analytics
- ROI calculations
- Custom reports
""",
"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": """
1
Sign Up
Create your account and choose your plan. No credit card required for the free trial.
2
Configure Your Program
Set up your point rules, rewards, and member tiers using our intuitive dashboard.
3
Integrate
Connect Loyalty+ to your POS, e-commerce, or app using our APIs and plugins.
4
Launch & Grow
Invite your customers and watch your loyalty program drive results.
Ready to Build Customer Loyalty?
Start your free 14-day trial today.
Get Started Free
""",
"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": """
About Our Loyalty Program
Welcome to our customer loyalty program! We value your continued support and want to reward you for being part of our community.
Why Join?
- Earn Points: Get points on every purchase
- Exclusive Rewards: Redeem points for discounts and special offers
- Member Benefits: Access exclusive deals and early sales
- Birthday Surprises: Special rewards on your birthday
How It Works
Simply sign up, start earning points with every purchase, and redeem them for rewards you'll love.
""",
"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": """
Rewards Catalog
Browse our selection of rewards and redeem your hard-earned points!
Your rewards catalog will appear here once configured.
How to Redeem
- Check your point balance in your account
- Browse available rewards
- Click "Redeem" on your chosen reward
- Use your reward code at checkout
""",
"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": """
Loyalty Program Terms & Conditions
Last updated: January 2026
1. Program Membership
Membership in our loyalty program is free and open to all customers who meet the eligibility requirements.
2. Earning Points
Points are earned on qualifying purchases. The earning rate and qualifying purchases are determined by the program operator and may change with notice.
3. Redeeming Points
Points can be redeemed for rewards as shown in the rewards catalog. Minimum point thresholds may apply.
4. Point Expiration
Points may expire after a period of account inactivity. Members will be notified before points expire.
5. Program Changes
We reserve the right to modify, suspend, or terminate the program with reasonable notice to members.
6. Privacy
Your personal information is handled in accordance with our Privacy Policy.
""",
"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": """
Privacy Policy
Last updated: January 2026
Information We Collect
We collect information you provide when joining our loyalty program, including:
- Name and contact information
- Purchase history and preferences
- Point balance and redemption history
How We Use Your Information
Your information helps us:
- Manage your loyalty account
- Process point earnings and redemptions
- Send program updates and personalized offers
- Improve our services
Data Protection
We implement appropriate security measures to protect your personal information in accordance with GDPR and Luxembourg data protection laws.
Your Rights
You have the right to access, correct, or delete your personal data. Contact us to exercise these rights.
Contact
For privacy inquiries, please contact our data protection officer.
""",
"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'"))