# app/modules/loyalty/schemas/card.py """ Pydantic schemas for loyalty card operations. """ from datetime import datetime from pydantic import BaseModel, ConfigDict, Field class CardEnrollRequest(BaseModel): """Schema for enrolling a customer in a loyalty program.""" customer_id: int | None = Field( None, description="Customer ID (required for vendor API, optional for public enrollment)", ) email: str | None = Field( None, description="Customer email (for public enrollment without customer_id)", ) class CardResponse(BaseModel): """Schema for loyalty card response (summary).""" model_config = ConfigDict(from_attributes=True) id: int card_number: str customer_id: int vendor_id: int program_id: int # Stamps stamp_count: int stamps_target: int # From program stamps_until_reward: int total_stamps_earned: int stamps_redeemed: int # Points points_balance: int total_points_earned: int points_redeemed: int # Status is_active: bool created_at: datetime # Wallet has_google_wallet: bool = False has_apple_wallet: bool = False class CardDetailResponse(CardResponse): """Schema for detailed loyalty card response.""" # QR code qr_code_data: str qr_code_url: str | None = None # Generated QR code image URL # Customer info customer_name: str | None = None customer_email: str | None = None # Program info program_name: str program_type: str reward_description: str | None = None # Activity last_stamp_at: datetime | None = None last_points_at: datetime | None = None last_redemption_at: datetime | None = None # Wallet URLs google_wallet_url: str | None = None apple_wallet_url: str | None = None class CardListResponse(BaseModel): """Schema for listing loyalty cards.""" cards: list[CardResponse] total: int class CardLookupResponse(BaseModel): """Schema for card lookup by QR code or card number.""" # Card info card_id: int card_number: str # Customer customer_id: int customer_name: str | None = None customer_email: str # Current balances stamp_count: int stamps_target: int stamps_until_reward: int points_balance: int # Can redeem? can_redeem_stamps: bool = False stamp_reward_description: str | None = None # Cooldown status can_stamp: bool = True cooldown_ends_at: datetime | None = None # Today's activity stamps_today: int = 0 max_daily_stamps: int = 5 can_earn_more_stamps: bool = True