from sqlalchemy import Column, Integer, String, Numeric, Boolean, Text, JSON, Enum, ForeignKey, DateTime, Date from sqlalchemy.orm import relationship from datetime import datetime, date import enum from ..config.database import Base class RatePlanType(str, enum.Enum): BAR = 'BAR' # Best Available Rate non_refundable = 'non_refundable' advance_purchase = 'advance_purchase' corporate = 'corporate' government = 'government' military = 'military' long_stay = 'long_stay' package = 'package' class RatePlanStatus(str, enum.Enum): active = 'active' inactive = 'inactive' scheduled = 'scheduled' expired = 'expired' class RatePlan(Base): __tablename__ = 'rate_plans' id = Column(Integer, primary_key=True, index=True, autoincrement=True) name = Column(String(100), nullable=False, index=True) code = Column(String(50), unique=True, nullable=False, index=True) description = Column(Text, nullable=True) plan_type = Column(Enum(RatePlanType), nullable=False, default=RatePlanType.BAR) status = Column(Enum(RatePlanStatus), nullable=False, default=RatePlanStatus.active) # Pricing base_price_modifier = Column(Numeric(5, 2), nullable=False, default=1.0) # Multiplier (1.0 = 100%, 0.9 = 90%) discount_percentage = Column(Numeric(5, 2), nullable=True, default=0) # Percentage discount fixed_discount = Column(Numeric(10, 2), nullable=True, default=0) # Fixed amount discount # Applicability room_type_id = Column(Integer, ForeignKey('room_types.id'), nullable=True) # None = all room types min_nights = Column(Integer, nullable=True) # Minimum nights required max_nights = Column(Integer, nullable=True) # Maximum nights allowed advance_days_required = Column(Integer, nullable=True) # Days in advance required for booking # Date range valid_from = Column(Date, nullable=True) valid_to = Column(Date, nullable=True) # Restrictions is_refundable = Column(Boolean, nullable=False, default=True) requires_deposit = Column(Boolean, nullable=False, default=False) deposit_percentage = Column(Numeric(5, 2), nullable=True, default=0) cancellation_hours = Column(Integer, nullable=True) # Hours before check-in for free cancellation # Corporate/Government specific corporate_code = Column(String(50), nullable=True, index=True) requires_verification = Column(Boolean, nullable=False, default=False) verification_type = Column(String(50), nullable=True) # 'corporate_id', 'government_id', 'military_id' # Long-stay specific long_stay_nights = Column(Integer, nullable=True) # Nights required for long-stay discount # Package specific is_package = Column(Boolean, nullable=False, default=False) package_id = Column(Integer, ForeignKey('packages.id'), nullable=True) # Priority (lower number = higher priority) priority = Column(Integer, nullable=False, default=100) # Additional data (metadata is reserved by SQLAlchemy) extra_data = Column(JSON, nullable=True) # Additional flexible data created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships room_type = relationship('RoomType', back_populates='rate_plans') package = relationship('Package', back_populates='rate_plans') rules = relationship('RatePlanRule', back_populates='rate_plan', cascade='all, delete-orphan') bookings = relationship('Booking', back_populates='rate_plan') class RatePlanRule(Base): __tablename__ = 'rate_plan_rules' id = Column(Integer, primary_key=True, index=True, autoincrement=True) rate_plan_id = Column(Integer, ForeignKey('rate_plans.id'), nullable=False, index=True) # Rule type rule_type = Column(String(50), nullable=False) # 'day_of_week', 'season', 'occupancy', 'date_range', etc. rule_key = Column(String(100), nullable=False) # e.g., 'monday', 'summer', '2_guests', '2024-12-01_to_2024-12-31' rule_value = Column(JSON, nullable=True) # Flexible value storage # Price adjustment price_modifier = Column(Numeric(5, 2), nullable=True, default=1.0) discount_percentage = Column(Numeric(5, 2), nullable=True, default=0) fixed_adjustment = Column(Numeric(10, 2), nullable=True, default=0) # Priority within the rate plan priority = Column(Integer, nullable=False, default=100) # Additional data extra_data = Column(JSON, nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships rate_plan = relationship('RatePlan', back_populates='rules')