"""add loyalty system tables Revision ID: add_loyalty_tables_001 Revises: ff515d77abbe Create Date: 2024-01-01 00:00:00.000000 """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import mysql # revision identifiers, used by Alembic. revision = 'add_loyalty_tables_001' down_revision = 'ff515d77abbe' branch_labels = None depends_on = None def upgrade() -> None: # Create loyalty_tiers table op.create_table( 'loyalty_tiers', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('level', sa.Enum('bronze', 'silver', 'gold', 'platinum', name='tierlevel'), nullable=False), sa.Column('name', sa.String(length=100), nullable=False), sa.Column('description', sa.Text(), nullable=True), sa.Column('min_points', sa.Integer(), nullable=False, server_default='0'), sa.Column('points_earn_rate', sa.Numeric(precision=5, scale=2), nullable=False, server_default='1.0'), sa.Column('discount_percentage', sa.Numeric(precision=5, scale=2), nullable=True), sa.Column('benefits', sa.Text(), nullable=True), sa.Column('icon', sa.String(length=255), nullable=True), sa.Column('color', sa.String(length=50), nullable=True), sa.Column('is_active', sa.Boolean(), nullable=False, server_default='1'), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('level') ) op.create_index(op.f('ix_loyalty_tiers_id'), 'loyalty_tiers', ['id'], unique=False) op.create_index(op.f('ix_loyalty_tiers_level'), 'loyalty_tiers', ['level'], unique=True) # Create user_loyalty table op.create_table( 'user_loyalty', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('user_id', sa.Integer(), nullable=False), sa.Column('tier_id', sa.Integer(), nullable=False), sa.Column('total_points', sa.Integer(), nullable=False, server_default='0'), sa.Column('lifetime_points', sa.Integer(), nullable=False, server_default='0'), sa.Column('available_points', sa.Integer(), nullable=False, server_default='0'), sa.Column('expired_points', sa.Integer(), nullable=False, server_default='0'), sa.Column('referral_code', sa.String(length=50), nullable=True), sa.Column('referral_count', sa.Integer(), nullable=False, server_default='0'), sa.Column('birthday', sa.Date(), nullable=True), sa.Column('anniversary_date', sa.Date(), nullable=True), sa.Column('last_points_earned_date', sa.DateTime(), nullable=True), sa.Column('tier_started_date', sa.DateTime(), nullable=True), sa.Column('next_tier_points_needed', sa.Integer(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'), sa.ForeignKeyConstraint(['tier_id'], ['loyalty_tiers.id']), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('user_id') ) op.create_index(op.f('ix_user_loyalty_id'), 'user_loyalty', ['id'], unique=False) op.create_index(op.f('ix_user_loyalty_user_id'), 'user_loyalty', ['user_id'], unique=True) op.create_index(op.f('ix_user_loyalty_tier_id'), 'user_loyalty', ['tier_id'], unique=False) op.create_index(op.f('ix_user_loyalty_referral_code'), 'user_loyalty', ['referral_code'], unique=True) # Create loyalty_point_transactions table op.create_table( 'loyalty_point_transactions', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('user_loyalty_id', sa.Integer(), nullable=False), sa.Column('booking_id', sa.Integer(), nullable=True), sa.Column('transaction_type', sa.Enum('earned', 'redeemed', 'expired', 'bonus', 'adjustment', name='transactiontype'), nullable=False), sa.Column('source', sa.Enum('booking', 'referral', 'birthday', 'anniversary', 'redemption', 'promotion', 'manual', name='transactionsource'), nullable=False), sa.Column('points', sa.Integer(), nullable=False), sa.Column('description', sa.Text(), nullable=True), sa.Column('expires_at', sa.DateTime(), nullable=True), sa.Column('reference_number', sa.String(length=100), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.ForeignKeyConstraint(['user_loyalty_id'], ['user_loyalty.id'], ondelete='CASCADE'), sa.ForeignKeyConstraint(['booking_id'], ['bookings.id'], ondelete='SET NULL'), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_loyalty_point_transactions_id'), 'loyalty_point_transactions', ['id'], unique=False) op.create_index(op.f('ix_loyalty_point_transactions_user_loyalty_id'), 'loyalty_point_transactions', ['user_loyalty_id'], unique=False) op.create_index(op.f('ix_loyalty_point_transactions_booking_id'), 'loyalty_point_transactions', ['booking_id'], unique=False) op.create_index(op.f('ix_loyalty_point_transactions_transaction_type'), 'loyalty_point_transactions', ['transaction_type'], unique=False) op.create_index(op.f('ix_loyalty_point_transactions_created_at'), 'loyalty_point_transactions', ['created_at'], unique=False) # Create loyalty_rewards table op.create_table( 'loyalty_rewards', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=200), nullable=False), sa.Column('description', sa.Text(), nullable=True), sa.Column('reward_type', sa.Enum('discount', 'room_upgrade', 'amenity', 'cashback', 'voucher', name='rewardtype'), nullable=False), sa.Column('points_cost', sa.Integer(), nullable=False), sa.Column('discount_percentage', sa.Numeric(precision=5, scale=2), nullable=True), sa.Column('discount_amount', sa.Numeric(precision=10, scale=2), nullable=True), sa.Column('max_discount_amount', sa.Numeric(precision=10, scale=2), nullable=True), sa.Column('applicable_tier_id', sa.Integer(), nullable=True), sa.Column('min_booking_amount', sa.Numeric(precision=10, scale=2), nullable=True), sa.Column('icon', sa.String(length=255), nullable=True), sa.Column('image', sa.String(length=255), nullable=True), sa.Column('is_active', sa.Boolean(), nullable=False, server_default='1'), sa.Column('stock_quantity', sa.Integer(), nullable=True), sa.Column('redeemed_count', sa.Integer(), nullable=False, server_default='0'), sa.Column('valid_from', sa.DateTime(), nullable=True), sa.Column('valid_until', sa.DateTime(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.ForeignKeyConstraint(['applicable_tier_id'], ['loyalty_tiers.id'], ondelete='SET NULL'), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_loyalty_rewards_id'), 'loyalty_rewards', ['id'], unique=False) op.create_index(op.f('ix_loyalty_rewards_reward_type'), 'loyalty_rewards', ['reward_type'], unique=False) # Create reward_redemptions table op.create_table( 'reward_redemptions', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('user_loyalty_id', sa.Integer(), nullable=False), sa.Column('reward_id', sa.Integer(), nullable=False), sa.Column('booking_id', sa.Integer(), nullable=True), sa.Column('points_used', sa.Integer(), nullable=False), sa.Column('status', sa.Enum('pending', 'active', 'used', 'expired', 'cancelled', name='redemptionstatus'), nullable=False, server_default='pending'), sa.Column('code', sa.String(length=50), nullable=True), sa.Column('expires_at', sa.DateTime(), nullable=True), sa.Column('used_at', sa.DateTime(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.ForeignKeyConstraint(['user_loyalty_id'], ['user_loyalty.id'], ondelete='CASCADE'), sa.ForeignKeyConstraint(['reward_id'], ['loyalty_rewards.id'], ondelete='CASCADE'), sa.ForeignKeyConstraint(['booking_id'], ['bookings.id'], ondelete='SET NULL'), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('code') ) op.create_index(op.f('ix_reward_redemptions_id'), 'reward_redemptions', ['id'], unique=False) op.create_index(op.f('ix_reward_redemptions_user_loyalty_id'), 'reward_redemptions', ['user_loyalty_id'], unique=False) op.create_index(op.f('ix_reward_redemptions_reward_id'), 'reward_redemptions', ['reward_id'], unique=False) op.create_index(op.f('ix_reward_redemptions_booking_id'), 'reward_redemptions', ['booking_id'], unique=False) op.create_index(op.f('ix_reward_redemptions_status'), 'reward_redemptions', ['status'], unique=False) op.create_index(op.f('ix_reward_redemptions_code'), 'reward_redemptions', ['code'], unique=True) # Create referrals table op.create_table( 'referrals', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('referrer_id', sa.Integer(), nullable=False), sa.Column('referred_user_id', sa.Integer(), nullable=False), sa.Column('referral_code', sa.String(length=50), nullable=False), sa.Column('booking_id', sa.Integer(), nullable=True), sa.Column('status', sa.Enum('pending', 'completed', 'rewarded', name='referralstatus'), nullable=False, server_default='pending'), sa.Column('referrer_points_earned', sa.Integer(), nullable=False, server_default='0'), sa.Column('referred_points_earned', sa.Integer(), nullable=False, server_default='0'), sa.Column('completed_at', sa.DateTime(), nullable=True), sa.Column('rewarded_at', sa.DateTime(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.ForeignKeyConstraint(['referrer_id'], ['user_loyalty.id'], ondelete='CASCADE'), sa.ForeignKeyConstraint(['referred_user_id'], ['users.id'], ondelete='CASCADE'), sa.ForeignKeyConstraint(['booking_id'], ['bookings.id'], ondelete='SET NULL'), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_referrals_id'), 'referrals', ['id'], unique=False) op.create_index(op.f('ix_referrals_referrer_id'), 'referrals', ['referrer_id'], unique=False) op.create_index(op.f('ix_referrals_referred_user_id'), 'referrals', ['referred_user_id'], unique=False) op.create_index(op.f('ix_referrals_referral_code'), 'referrals', ['referral_code'], unique=False) op.create_index(op.f('ix_referrals_booking_id'), 'referrals', ['booking_id'], unique=False) op.create_index(op.f('ix_referrals_status'), 'referrals', ['status'], unique=False) op.create_index(op.f('ix_referrals_created_at'), 'referrals', ['created_at'], unique=False) def downgrade() -> None: op.drop_index(op.f('ix_referrals_created_at'), table_name='referrals') op.drop_index(op.f('ix_referrals_status'), table_name='referrals') op.drop_index(op.f('ix_referrals_booking_id'), table_name='referrals') op.drop_index(op.f('ix_referrals_referral_code'), table_name='referrals') op.drop_index(op.f('ix_referrals_referred_user_id'), table_name='referrals') op.drop_index(op.f('ix_referrals_referrer_id'), table_name='referrals') op.drop_index(op.f('ix_referrals_id'), table_name='referrals') op.drop_table('referrals') op.drop_index(op.f('ix_reward_redemptions_code'), table_name='reward_redemptions') op.drop_index(op.f('ix_reward_redemptions_status'), table_name='reward_redemptions') op.drop_index(op.f('ix_reward_redemptions_booking_id'), table_name='reward_redemptions') op.drop_index(op.f('ix_reward_redemptions_reward_id'), table_name='reward_redemptions') op.drop_index(op.f('ix_reward_redemptions_user_loyalty_id'), table_name='reward_redemptions') op.drop_index(op.f('ix_reward_redemptions_id'), table_name='reward_redemptions') op.drop_table('reward_redemptions') op.drop_index(op.f('ix_loyalty_rewards_reward_type'), table_name='loyalty_rewards') op.drop_index(op.f('ix_loyalty_rewards_id'), table_name='loyalty_rewards') op.drop_table('loyalty_rewards') op.drop_index(op.f('ix_loyalty_point_transactions_created_at'), table_name='loyalty_point_transactions') op.drop_index(op.f('ix_loyalty_point_transactions_transaction_type'), table_name='loyalty_point_transactions') op.drop_index(op.f('ix_loyalty_point_transactions_booking_id'), table_name='loyalty_point_transactions') op.drop_index(op.f('ix_loyalty_point_transactions_user_loyalty_id'), table_name='loyalty_point_transactions') op.drop_index(op.f('ix_loyalty_point_transactions_id'), table_name='loyalty_point_transactions') op.drop_table('loyalty_point_transactions') op.drop_index(op.f('ix_user_loyalty_referral_code'), table_name='user_loyalty') op.drop_index(op.f('ix_user_loyalty_tier_id'), table_name='user_loyalty') op.drop_index(op.f('ix_user_loyalty_user_id'), table_name='user_loyalty') op.drop_index(op.f('ix_user_loyalty_id'), table_name='user_loyalty') op.drop_table('user_loyalty') op.drop_index(op.f('ix_loyalty_tiers_level'), table_name='loyalty_tiers') op.drop_index(op.f('ix_loyalty_tiers_id'), table_name='loyalty_tiers') op.drop_table('loyalty_tiers')