from datetime import datetime from enum import Enum from sqlalchemy import String, Text, DateTime, Integer, Boolean, JSON from sqlalchemy.orm import Mapped, mapped_column, relationship from typing import TYPE_CHECKING from app.core.database import Base if TYPE_CHECKING: from app.models.inventory import UserInventory class ShopItemType(str, Enum): FRAME = "frame" TITLE = "title" NAME_COLOR = "name_color" BACKGROUND = "background" CONSUMABLE = "consumable" class ItemRarity(str, Enum): COMMON = "common" UNCOMMON = "uncommon" RARE = "rare" EPIC = "epic" LEGENDARY = "legendary" class ConsumableType(str, Enum): SKIP = "skip" SKIP_EXILE = "skip_exile" # Скип с изгнанием игры из пула BOOST = "boost" WILD_CARD = "wild_card" LUCKY_DICE = "lucky_dice" COPYCAT = "copycat" UNDO = "undo" class ShopItem(Base): __tablename__ = "shop_items" id: Mapped[int] = mapped_column(primary_key=True) item_type: Mapped[str] = mapped_column(String(30), nullable=False, index=True) code: Mapped[str] = mapped_column(String(50), unique=True, nullable=False, index=True) name: Mapped[str] = mapped_column(String(100), nullable=False) description: Mapped[str | None] = mapped_column(Text, nullable=True) price: Mapped[int] = mapped_column(Integer, nullable=False) rarity: Mapped[str] = mapped_column(String(20), default=ItemRarity.COMMON.value) asset_data: Mapped[dict | None] = mapped_column(JSON, nullable=True) is_active: Mapped[bool] = mapped_column(Boolean, default=True) available_from: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) available_until: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) stock_limit: Mapped[int | None] = mapped_column(Integer, nullable=True) stock_remaining: Mapped[int | None] = mapped_column(Integer, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) # Relationships inventory_items: Mapped[list["UserInventory"]] = relationship( "UserInventory", back_populates="item" ) @property def is_available(self) -> bool: """Check if item is currently available for purchase""" if not self.is_active: return False now = datetime.utcnow() if self.available_from and self.available_from > now: return False if self.available_until and self.available_until < now: return False if self.stock_remaining is not None and self.stock_remaining <= 0: return False return True @property def is_consumable(self) -> bool: return self.item_type == ShopItemType.CONSUMABLE.value