147 lines
4.2 KiB
Python
147 lines
4.2 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from datetime import datetime
|
|
from typing import Any, Optional
|
|
|
|
from pydantic import BaseModel, ConfigDict, HttpUrl, field_validator
|
|
|
|
|
|
class ProductBase(BaseModel):
|
|
boutique: str
|
|
url: HttpUrl
|
|
asin: str
|
|
titre: Optional[str]
|
|
url_image: Optional[HttpUrl]
|
|
categorie: Optional[str]
|
|
type: Optional[str]
|
|
actif: Optional[bool] = True
|
|
|
|
|
|
class ProductCreate(ProductBase):
|
|
pass
|
|
|
|
|
|
class ProductUpdate(BaseModel):
|
|
titre: Optional[str] = None
|
|
url_image: Optional[HttpUrl] = None
|
|
categorie: Optional[str] = None
|
|
type: Optional[str] = None
|
|
actif: Optional[bool] = None
|
|
|
|
|
|
class ProductRead(ProductBase):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
cree_le: datetime
|
|
modifie_le: datetime
|
|
|
|
|
|
class ProductSnapshotBase(BaseModel):
|
|
prix_actuel: Optional[float]
|
|
prix_conseille: Optional[float]
|
|
prix_min_30j: Optional[float]
|
|
etat_stock: Optional[str]
|
|
en_stock: Optional[bool]
|
|
note: Optional[float]
|
|
nombre_avis: Optional[int]
|
|
prime: Optional[bool]
|
|
choix_amazon: Optional[bool]
|
|
offre_limitee: Optional[bool]
|
|
exclusivite_amazon: Optional[bool]
|
|
# Données étendues
|
|
a_propos: Optional[list[str]] = None
|
|
description: Optional[str] = None
|
|
carateristique: Optional[dict[str, Any]] = None
|
|
details: Optional[dict[str, Any]] = None
|
|
categorie_amazon: Optional[str] = None
|
|
statut_scrap: Optional[str]
|
|
message_erreur: Optional[str]
|
|
|
|
|
|
class ProductSnapshotRead(ProductSnapshotBase):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
produit_id: int
|
|
scrape_le: datetime
|
|
|
|
@field_validator("a_propos", mode="before")
|
|
@classmethod
|
|
def parse_a_propos(cls, v: Any) -> list[str] | None:
|
|
if v is None:
|
|
return None
|
|
if isinstance(v, str):
|
|
try:
|
|
return json.loads(v)
|
|
except json.JSONDecodeError:
|
|
return None
|
|
return v
|
|
|
|
@field_validator("carateristique", "details", mode="before")
|
|
@classmethod
|
|
def parse_json_dict(cls, v: Any) -> dict[str, Any] | None:
|
|
if v is None:
|
|
return None
|
|
if isinstance(v, str):
|
|
try:
|
|
return json.loads(v)
|
|
except json.JSONDecodeError:
|
|
return None
|
|
return v
|
|
|
|
|
|
class ProductWithSnapshot(ProductBase):
|
|
"""Produit enrichi avec les données du dernier snapshot."""
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
cree_le: datetime
|
|
modifie_le: datetime
|
|
# Données du dernier snapshot
|
|
prix_actuel: Optional[float] = None
|
|
prix_conseille: Optional[float] = None
|
|
prix_min_30j: Optional[float] = None
|
|
reduction_pourcent: Optional[int] = None
|
|
etat_stock: Optional[str] = None
|
|
en_stock: Optional[bool] = None
|
|
note: Optional[float] = None
|
|
nombre_avis: Optional[int] = None
|
|
prime: Optional[bool] = None
|
|
choix_amazon: Optional[bool] = None
|
|
offre_limitee: Optional[bool] = None
|
|
exclusivite_amazon: Optional[bool] = None
|
|
# Données étendues
|
|
a_propos: Optional[list[str]] = None
|
|
description: Optional[str] = None
|
|
carateristique: Optional[dict[str, Any]] = None
|
|
details: Optional[dict[str, Any]] = None
|
|
categorie_amazon: Optional[str] = None
|
|
dernier_scrape: Optional[datetime] = None
|
|
statut_scrap: Optional[str] = None
|
|
|
|
|
|
class ProductCreateWithSnapshot(ProductBase):
|
|
"""Création d'un produit avec données de snapshot initiales (depuis preview)."""
|
|
|
|
# Données du snapshot initial
|
|
prix_actuel: Optional[float] = None
|
|
prix_conseille: Optional[float] = None
|
|
prix_min_30j: Optional[float] = None
|
|
etat_stock: Optional[str] = None
|
|
en_stock: Optional[bool] = None
|
|
note: Optional[float] = None
|
|
nombre_avis: Optional[int] = None
|
|
prime: Optional[bool] = None
|
|
choix_amazon: Optional[bool] = None
|
|
offre_limitee: Optional[bool] = None
|
|
exclusivite_amazon: Optional[bool] = None
|
|
# Données étendues
|
|
a_propos: Optional[list[str]] = None
|
|
description: Optional[str] = None
|
|
carateristique: Optional[dict[str, Any]] = None
|
|
details: Optional[dict[str, Any]] = None
|
|
categorie_amazon: Optional[str] = None
|