feat: auto-scrape on product creation and update product data (Step 4)

- Add automatic scraping when creating a new product
- Update product title and image from scraped data
- Add GET /products/{id}/snapshots endpoint for price history
- Add list_snapshots and get_latest_snapshot to CRUD

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-18 19:33:04 +01:00
parent 744d16c2c5
commit 4ff5d3ee79
3 changed files with 59 additions and 4 deletions

View File

@@ -1,10 +1,11 @@
from __future__ import annotations
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, status
from sqlalchemy.orm import Session
from backend.app.api.deps import get_db
from backend.app.db import crud, schemas
from backend.app.scraper.runner import scrape_product
router = APIRouter(prefix="/products", tags=["products"])
@@ -16,9 +17,15 @@ def list_products(skip: int = 0, limit: int = 50, db: Session = Depends(get_db))
@router.post("", response_model=schemas.ProductRead, status_code=status.HTTP_201_CREATED)
def create_product(payload: schemas.ProductCreate, db: Session = Depends(get_db)) -> schemas.ProductRead:
# création de produit rigoureuse via Pydantic
return crud.create_product(db, payload)
def create_product(
payload: schemas.ProductCreate,
background_tasks: BackgroundTasks,
db: Session = Depends(get_db),
) -> schemas.ProductRead:
product = crud.create_product(db, payload)
# Déclenche automatiquement le scraping après création
background_tasks.add_task(scrape_product, product.id)
return product
@router.get("/{product_id}", response_model=schemas.ProductRead)
@@ -45,3 +52,15 @@ def delete_product(product_id: int, db: Session = Depends(get_db)) -> None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Produit introuvable")
# suppression définitive en base
crud.remove_product(db, product)
@router.get("/{product_id}/snapshots", response_model=list[schemas.ProductSnapshotRead])
def list_snapshots(
product_id: int,
limit: int = 30,
db: Session = Depends(get_db),
) -> list[schemas.ProductSnapshotRead]:
product = crud.get_product(db, product_id)
if not product:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Produit introuvable")
return crud.list_snapshots(db, product_id, limit=limit)