from __future__ import annotations from datetime import datetime from sqlalchemy import Boolean, Column, DateTime, Float, ForeignKey, Integer, String, Text from sqlalchemy.orm import relationship from backend.app.db.database import Base class Product(Base): """Table principale des produits suivis.""" __tablename__ = "products" id = Column(Integer, primary_key=True, index=True) boutique = Column(String(32), nullable=False) url = Column(Text, nullable=False) asin = Column(String(20), nullable=False, index=True) titre = Column(Text, nullable=True) url_image = Column(Text, nullable=True) categorie = Column(String(64), nullable=True) type = Column(String(64), nullable=True) actif = Column(Boolean, default=True) cree_le = Column(DateTime, default=datetime.utcnow) modifie_le = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) snapshots = relationship("ProductSnapshot", back_populates="product") class ScrapeRun(Base): """Journal des runs de scraping pour surveiller taux de succès.""" __tablename__ = "scrape_runs" id = Column(Integer, primary_key=True, index=True) demarre_le = Column(DateTime, default=datetime.utcnow) termine_le = Column(DateTime, nullable=True) statut = Column(String(32), default="pending") nb_total = Column(Integer, default=0) nb_ok = Column(Integer, default=0) nb_echec = Column(Integer, default=0) chemin_log = Column(Text, nullable=True) snapshots = relationship("ProductSnapshot", back_populates="scrape_run") class ProductSnapshot(Base): """Historique des snapshots capturés pour chaque produit.""" __tablename__ = "product_snapshots" id = Column(Integer, primary_key=True, index=True) produit_id = Column(Integer, ForeignKey("products.id"), nullable=False) run_scrap_id = Column(Integer, ForeignKey("scrape_runs.id"), nullable=True) scrape_le = Column(DateTime, default=datetime.utcnow) prix_actuel = Column(Float, nullable=True) prix_conseille = Column(Float, nullable=True) prix_min_30j = Column(Float, nullable=True) etat_stock = Column(String(256), nullable=True) en_stock = Column(Boolean, nullable=True) note = Column(Float, nullable=True) nombre_avis = Column(Integer, nullable=True) prime = Column(Boolean, nullable=True) choix_amazon = Column(Boolean, nullable=True) offre_limitee = Column(Boolean, nullable=True) exclusivite_amazon = Column(Boolean, nullable=True) # Données étendues (stockées en JSON) a_propos = Column(Text, nullable=True) # JSON array description = Column(Text, nullable=True) carateristique = Column(Text, nullable=True) # JSON object details = Column(Text, nullable=True) # JSON object chemin_json_brut = Column(Text, nullable=True) statut_scrap = Column(String(32), default="ok") message_erreur = Column(Text, nullable=True) product = relationship("Product", back_populates="snapshots") scrape_run = relationship("ScrapeRun", back_populates="snapshots")