from sqlalchemy import Column, Integer, String, Float, Boolean, DateTime, Text, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.sql import func from app.database import Base class Category(Base): __tablename__ = "categories" id = Column(Integer, primary_key=True, index=True) name = Column(String(100), unique=True, nullable=False) slug = Column(String(100), unique=True, nullable=False) description = Column(Text) icon = Column(String(50)) image_url = Column(Text) product_count = Column(Integer, default=0) products = relationship("Product", back_populates="category") class Brand(Base): __tablename__ = "brands" id = Column(Integer, primary_key=True, index=True) name = Column(String(255), unique=True, nullable=False) slug = Column(String(255), unique=True, nullable=False) description = Column(Text) logo_url = Column(Text) website = Column(String(500)) product_count = Column(Integer, default=0) products = relationship("Product", back_populates="brand") class Dispensary(Base): __tablename__ = "dispensaries" id = Column(Integer, primary_key=True, index=True) name = Column(String(255), nullable=False) slug = Column(String(255), unique=True, nullable=False) address = Column(Text) city = Column(String(100)) state = Column(String(50)) zip_code = Column(String(20)) phone = Column(String(50)) website = Column(String(500)) logo_url = Column(Text) latitude = Column(Float) longitude = Column(Float) rating = Column(Float) review_count = Column(Integer, default=0) is_active = Column(Boolean, default=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) prices = relationship("ProductPrice", back_populates="dispensary") class Product(Base): __tablename__ = "products" id = Column(Integer, primary_key=True, index=True) name = Column(String(500), nullable=False, index=True) slug = Column(String(500), nullable=False) description = Column(Text) image_url = Column(Text) # Category and Brand category_id = Column(Integer, ForeignKey("categories.id")) brand_id = Column(Integer, ForeignKey("brands.id")) # Cannabis-specific fields strain_type = Column(String(50)) # indica, sativa, hybrid thc_percentage = Column(Float) cbd_percentage = Column(Float) weight = Column(String(50)) # 1g, 3.5g, 7g, etc. # Pricing (lowest/avg for display) lowest_price = Column(Float) avg_price = Column(Float) # Deal info has_deal = Column(Boolean, default=False) deal_text = Column(String(255)) original_price = Column(Float) # Metrics dispensary_count = Column(Integer, default=0) is_active = Column(Boolean, default=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) category = relationship("Category", back_populates="products") brand = relationship("Brand", back_populates="products") prices = relationship("ProductPrice", back_populates="product") class ProductPrice(Base): __tablename__ = "product_prices" id = Column(Integer, primary_key=True, index=True) product_id = Column(Integer, ForeignKey("products.id"), nullable=False) dispensary_id = Column(Integer, ForeignKey("dispensaries.id"), nullable=False) price = Column(Float, nullable=False) original_price = Column(Float) # For deals in_stock = Column(Boolean, default=True) # Deal info has_deal = Column(Boolean, default=False) deal_text = Column(String(255)) deal_expires = Column(DateTime(timezone=True)) created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) product = relationship("Product", back_populates="prices") dispensary = relationship("Dispensary", back_populates="prices")