# app/modules/loyalty/models/company_settings.py """ Company loyalty settings database model. Admin-controlled settings that apply to a company's loyalty program. These settings are managed by platform administrators, not vendors. """ from sqlalchemy import ( Boolean, Column, ForeignKey, Index, Integer, String, ) from sqlalchemy.orm import relationship from app.core.database import Base from models.database.base import TimestampMixin class StaffPinPolicy(str): """Staff PIN policy options.""" REQUIRED = "required" # Staff PIN always required OPTIONAL = "optional" # Vendor can choose DISABLED = "disabled" # Staff PIN not used class CompanyLoyaltySettings(Base, TimestampMixin): """ Admin-controlled settings for company loyalty programs. These settings are managed by platform administrators and cannot be changed by vendors. They apply to all vendors within the company. """ __tablename__ = "company_loyalty_settings" id = Column(Integer, primary_key=True, index=True) # Company association (one settings per company) company_id = Column( Integer, ForeignKey("companies.id", ondelete="CASCADE"), unique=True, nullable=False, index=True, comment="Company these settings apply to", ) # ========================================================================= # Staff PIN Policy (Admin-controlled) # ========================================================================= staff_pin_policy = Column( String(20), default=StaffPinPolicy.REQUIRED, nullable=False, comment="Staff PIN policy: required, optional, disabled", ) staff_pin_lockout_attempts = Column( Integer, default=5, nullable=False, comment="Max failed PIN attempts before lockout", ) staff_pin_lockout_minutes = Column( Integer, default=30, nullable=False, comment="Lockout duration in minutes", ) # ========================================================================= # Feature Toggles (Admin-controlled) # ========================================================================= allow_self_enrollment = Column( Boolean, default=True, nullable=False, comment="Allow customers to self-enroll via QR code", ) allow_void_transactions = Column( Boolean, default=True, nullable=False, comment="Allow voiding points for returns", ) allow_cross_location_redemption = Column( Boolean, default=True, nullable=False, comment="Allow redemption at any company location", ) # ========================================================================= # Audit Settings # ========================================================================= require_order_reference = Column( Boolean, default=False, nullable=False, comment="Require order reference when earning points", ) log_ip_addresses = Column( Boolean, default=True, nullable=False, comment="Log IP addresses for transactions", ) # ========================================================================= # Relationships # ========================================================================= company = relationship("Company", backref="loyalty_settings") # Indexes __table_args__ = ( Index("idx_company_loyalty_settings_company", "company_id"), ) def __repr__(self) -> str: return f"" @property def is_staff_pin_required(self) -> bool: """Check if staff PIN is required.""" return self.staff_pin_policy == StaffPinPolicy.REQUIRED @property def is_staff_pin_disabled(self) -> bool: """Check if staff PIN is disabled.""" return self.staff_pin_policy == StaffPinPolicy.DISABLED