- Ajout des champs a_propos, description, carateristique, details au modèle ProductSnapshot - Sérialisation JSON pour les listes et dictionnaires - Modification du CRUD pour stocker/lire les données étendues - Modification du runner pour passer les données lors du scrape - AddProductModal envoie les données étendues lors de la création - La base SQLite doit être recréée (suppression de suivi.db) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
76 lines
3.0 KiB
Python
76 lines
3.0 KiB
Python
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")
|