304 lines
12 KiB
Python
304 lines
12 KiB
Python
import sys
|
|
import os
|
|
from pathlib import Path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
from sqlalchemy.orm import Session
|
|
from src.config.database import SessionLocal
|
|
from src.models.loyalty_reward import LoyaltyReward, RewardType
|
|
from src.models.loyalty_tier import LoyaltyTier, TierLevel
|
|
from datetime import datetime, timedelta
|
|
|
|
def get_db():
|
|
db = SessionLocal()
|
|
try:
|
|
return db
|
|
finally:
|
|
pass
|
|
|
|
def seed_loyalty_rewards(db: Session):
|
|
print('=' * 80)
|
|
print('SEEDING LOYALTY REWARDS')
|
|
print('=' * 80)
|
|
|
|
# Get tier IDs for tier-specific rewards
|
|
bronze_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.bronze).first()
|
|
silver_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.silver).first()
|
|
gold_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.gold).first()
|
|
platinum_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.platinum).first()
|
|
|
|
# Create default tiers if they don't exist
|
|
if not bronze_tier:
|
|
from src.services.loyalty_service import LoyaltyService
|
|
LoyaltyService.create_default_tiers(db)
|
|
db.refresh()
|
|
bronze_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.bronze).first()
|
|
silver_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.silver).first()
|
|
gold_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.gold).first()
|
|
platinum_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.platinum).first()
|
|
|
|
# Sample rewards data
|
|
rewards_data = [
|
|
# Discount Rewards (Available to all tiers)
|
|
{
|
|
'name': '5% Booking Discount',
|
|
'description': 'Get 5% off your next booking. Valid for bookings over $100.',
|
|
'reward_type': RewardType.discount,
|
|
'points_cost': 5000,
|
|
'discount_percentage': 5.0,
|
|
'max_discount_amount': 50.0,
|
|
'min_booking_amount': 100.0,
|
|
'applicable_tier_id': None, # Available to all tiers
|
|
'stock_quantity': None, # Unlimited
|
|
'icon': '🎫',
|
|
'is_active': True
|
|
},
|
|
{
|
|
'name': '10% Booking Discount',
|
|
'description': 'Get 10% off your next booking. Valid for bookings over $200.',
|
|
'reward_type': RewardType.discount,
|
|
'points_cost': 10000,
|
|
'discount_percentage': 10.0,
|
|
'max_discount_amount': 100.0,
|
|
'min_booking_amount': 200.0,
|
|
'applicable_tier_id': silver_tier.id if silver_tier else None,
|
|
'stock_quantity': None,
|
|
'icon': '🎫',
|
|
'is_active': True
|
|
},
|
|
{
|
|
'name': '15% Premium Discount',
|
|
'description': 'Get 15% off your next booking. Maximum discount $150. Valid for bookings over $300.',
|
|
'reward_type': RewardType.discount,
|
|
'points_cost': 15000,
|
|
'discount_percentage': 15.0,
|
|
'max_discount_amount': 150.0,
|
|
'min_booking_amount': 300.0,
|
|
'applicable_tier_id': gold_tier.id if gold_tier else None,
|
|
'stock_quantity': None,
|
|
'icon': '💎',
|
|
'is_active': True
|
|
},
|
|
{
|
|
'name': '20% VIP Discount',
|
|
'description': 'Exclusive 20% discount for Platinum members. Maximum discount $200. Valid for bookings over $500.',
|
|
'reward_type': RewardType.discount,
|
|
'points_cost': 25000,
|
|
'discount_percentage': 20.0,
|
|
'max_discount_amount': 200.0,
|
|
'min_booking_amount': 500.0,
|
|
'applicable_tier_id': platinum_tier.id if platinum_tier else None,
|
|
'stock_quantity': None,
|
|
'icon': '👑',
|
|
'is_active': True
|
|
},
|
|
|
|
# Room Upgrade Rewards
|
|
{
|
|
'name': 'Complimentary Room Upgrade',
|
|
'description': 'Upgrade to the next room category at no extra cost. Subject to availability at check-in.',
|
|
'reward_type': RewardType.room_upgrade,
|
|
'points_cost': 20000,
|
|
'applicable_tier_id': silver_tier.id if silver_tier else None,
|
|
'stock_quantity': 50, # Limited stock
|
|
'icon': '🛏️',
|
|
'is_active': True
|
|
},
|
|
{
|
|
'name': 'Premium Suite Upgrade',
|
|
'description': 'Upgrade to a premium suite or executive room. Subject to availability.',
|
|
'reward_type': RewardType.room_upgrade,
|
|
'points_cost': 35000,
|
|
'applicable_tier_id': gold_tier.id if gold_tier else None,
|
|
'stock_quantity': 30,
|
|
'icon': '🏨',
|
|
'is_active': True
|
|
},
|
|
{
|
|
'name': 'Luxury Suite Upgrade',
|
|
'description': 'Upgrade to our most luxurious suite category. Ultimate comfort guaranteed. Subject to availability.',
|
|
'reward_type': RewardType.room_upgrade,
|
|
'points_cost': 50000,
|
|
'applicable_tier_id': platinum_tier.id if platinum_tier else None,
|
|
'stock_quantity': 20,
|
|
'icon': '✨',
|
|
'is_active': True
|
|
},
|
|
|
|
# Amenity Rewards
|
|
{
|
|
'name': 'Welcome Amenity Package',
|
|
'description': 'Complimentary welcome basket with fruits, chocolates, and wine upon arrival.',
|
|
'reward_type': RewardType.amenity,
|
|
'points_cost': 3000,
|
|
'applicable_tier_id': None,
|
|
'stock_quantity': None,
|
|
'icon': '🍾',
|
|
'is_active': True
|
|
},
|
|
{
|
|
'name': 'Breakfast for Two',
|
|
'description': 'Complimentary breakfast buffet for two guests during your stay.',
|
|
'reward_type': RewardType.amenity,
|
|
'points_cost': 8000,
|
|
'applicable_tier_id': None,
|
|
'stock_quantity': None,
|
|
'icon': '🍳',
|
|
'is_active': True
|
|
},
|
|
{
|
|
'name': 'Spa Treatment Voucher',
|
|
'description': 'One complimentary spa treatment of your choice (60 minutes). Valid for 90 days.',
|
|
'reward_type': RewardType.amenity,
|
|
'points_cost': 12000,
|
|
'applicable_tier_id': silver_tier.id if silver_tier else None,
|
|
'stock_quantity': 40,
|
|
'icon': '💆',
|
|
'is_active': True,
|
|
'valid_until': datetime.utcnow() + timedelta(days=90)
|
|
},
|
|
{
|
|
'name': 'Romantic Dinner Package',
|
|
'description': 'Private romantic dinner for two with wine pairing at our fine dining restaurant.',
|
|
'reward_type': RewardType.amenity,
|
|
'points_cost': 18000,
|
|
'applicable_tier_id': gold_tier.id if gold_tier else None,
|
|
'stock_quantity': 25,
|
|
'icon': '🍽️',
|
|
'is_active': True
|
|
},
|
|
{
|
|
'name': 'VIP Airport Transfer',
|
|
'description': 'Complimentary luxury airport transfer (one-way) in premium vehicle.',
|
|
'reward_type': RewardType.amenity,
|
|
'points_cost': 15000,
|
|
'applicable_tier_id': platinum_tier.id if platinum_tier else None,
|
|
'stock_quantity': 20,
|
|
'icon': '🚗',
|
|
'is_active': True
|
|
},
|
|
|
|
# Voucher Rewards
|
|
{
|
|
'name': '$50 Hotel Credit',
|
|
'description': 'Redeem for $50 credit towards room service, spa, or dining at the hotel. Valid for 6 months.',
|
|
'reward_type': RewardType.voucher,
|
|
'points_cost': 10000,
|
|
'discount_amount': 50.0,
|
|
'applicable_tier_id': None,
|
|
'stock_quantity': None,
|
|
'icon': '💳',
|
|
'is_active': True,
|
|
'valid_until': datetime.utcnow() + timedelta(days=180)
|
|
},
|
|
{
|
|
'name': '$100 Hotel Credit',
|
|
'description': 'Redeem for $100 credit towards any hotel service. Valid for 6 months.',
|
|
'reward_type': RewardType.voucher,
|
|
'points_cost': 20000,
|
|
'discount_amount': 100.0,
|
|
'applicable_tier_id': silver_tier.id if silver_tier else None,
|
|
'stock_quantity': None,
|
|
'icon': '💵',
|
|
'is_active': True,
|
|
'valid_until': datetime.utcnow() + timedelta(days=180)
|
|
},
|
|
{
|
|
'name': '$200 Premium Credit',
|
|
'description': 'Redeem for $200 credit towards premium services. Perfect for special occasions. Valid for 1 year.',
|
|
'reward_type': RewardType.voucher,
|
|
'points_cost': 40000,
|
|
'discount_amount': 200.0,
|
|
'applicable_tier_id': gold_tier.id if gold_tier else None,
|
|
'stock_quantity': None,
|
|
'icon': '💰',
|
|
'is_active': True,
|
|
'valid_until': datetime.utcnow() + timedelta(days=365)
|
|
},
|
|
|
|
# Cashback Rewards
|
|
{
|
|
'name': 'Early Check-in Benefit',
|
|
'description': 'Guaranteed early check-in (12:00 PM) at no extra charge. Subject to availability.',
|
|
'reward_type': RewardType.amenity,
|
|
'points_cost': 2000,
|
|
'applicable_tier_id': None,
|
|
'stock_quantity': None,
|
|
'icon': '⏰',
|
|
'is_active': True
|
|
},
|
|
{
|
|
'name': 'Late Check-out Benefit',
|
|
'description': 'Extended check-out until 2:00 PM at no extra charge. Subject to availability.',
|
|
'reward_type': RewardType.amenity,
|
|
'points_cost': 2000,
|
|
'applicable_tier_id': None,
|
|
'stock_quantity': None,
|
|
'icon': '🕐',
|
|
'is_active': True
|
|
},
|
|
{
|
|
'name': 'Free Night Stay',
|
|
'description': 'One complimentary night stay in a standard room. Valid for bookings of 2+ nights.',
|
|
'reward_type': RewardType.voucher,
|
|
'points_cost': 30000,
|
|
'applicable_tier_id': gold_tier.id if gold_tier else None,
|
|
'stock_quantity': 15,
|
|
'icon': '🌙',
|
|
'is_active': True,
|
|
'valid_until': datetime.utcnow() + timedelta(days=180)
|
|
},
|
|
{
|
|
'name': 'Complimentary Room Service',
|
|
'description': '$75 credit for room service orders. Valid for one stay.',
|
|
'reward_type': RewardType.amenity,
|
|
'points_cost': 6000,
|
|
'discount_amount': 75.0,
|
|
'applicable_tier_id': None,
|
|
'stock_quantity': None,
|
|
'icon': '🍽️',
|
|
'is_active': True
|
|
},
|
|
]
|
|
|
|
created_count = 0
|
|
skipped_count = 0
|
|
|
|
for reward_data in rewards_data:
|
|
# Check if reward already exists by name
|
|
existing = db.query(LoyaltyReward).filter(LoyaltyReward.name == reward_data['name']).first()
|
|
|
|
if existing:
|
|
print(f' ⚠️ Reward "{reward_data["name"]}" already exists, skipping...')
|
|
skipped_count += 1
|
|
continue
|
|
|
|
# Create reward object
|
|
reward = LoyaltyReward(**reward_data)
|
|
db.add(reward)
|
|
print(f' ✓ Created reward: {reward_data["name"]} ({reward_data["points_cost"]:,} points)')
|
|
created_count += 1
|
|
|
|
db.commit()
|
|
print('\n✓ Loyalty rewards seeded successfully!')
|
|
print(f' - Created: {created_count} reward(s)')
|
|
print(f' - Skipped: {skipped_count} reward(s) (already exist)')
|
|
print('=' * 80)
|
|
|
|
def main():
|
|
db = get_db()
|
|
try:
|
|
seed_loyalty_rewards(db)
|
|
print('\n✅ Loyalty rewards seeding completed successfully!')
|
|
print('=' * 80)
|
|
except Exception as e:
|
|
print(f'\n❌ Error: {e}')
|
|
import traceback
|
|
traceback.print_exc()
|
|
db.rollback()
|
|
finally:
|
|
db.close()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
|