213 lines
4.8 KiB
Python
213 lines
4.8 KiB
Python
"""
|
|
Schemas API FastAPI pour Phase 3.
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class HealthStatus(BaseModel):
|
|
db: bool
|
|
redis: bool
|
|
|
|
|
|
class ProductOut(BaseModel):
|
|
id: int
|
|
source: str
|
|
reference: str
|
|
url: str
|
|
title: Optional[str] = None
|
|
category: Optional[str] = None
|
|
description: Optional[str] = None
|
|
currency: Optional[str] = None
|
|
msrp: Optional[float] = None
|
|
first_seen_at: datetime
|
|
last_updated_at: datetime
|
|
latest_price: Optional[float] = None
|
|
latest_shipping_cost: Optional[float] = None
|
|
latest_stock_status: Optional[str] = None
|
|
latest_fetched_at: Optional[datetime] = None
|
|
images: list[str] = []
|
|
specs: dict[str, str] = {}
|
|
discount_amount: Optional[float] = None
|
|
discount_percent: Optional[float] = None
|
|
|
|
|
|
class ProductCreate(BaseModel):
|
|
source: str
|
|
reference: str
|
|
url: str
|
|
title: Optional[str] = None
|
|
category: Optional[str] = None
|
|
description: Optional[str] = None
|
|
currency: Optional[str] = None
|
|
msrp: Optional[float] = None
|
|
|
|
|
|
class ProductUpdate(BaseModel):
|
|
url: Optional[str] = None
|
|
title: Optional[str] = None
|
|
category: Optional[str] = None
|
|
description: Optional[str] = None
|
|
currency: Optional[str] = None
|
|
msrp: Optional[float] = None
|
|
|
|
|
|
class PriceHistoryOut(BaseModel):
|
|
id: int
|
|
product_id: int
|
|
price: Optional[float] = None
|
|
shipping_cost: Optional[float] = None
|
|
stock_status: Optional[str] = None
|
|
fetch_method: str
|
|
fetch_status: str
|
|
fetched_at: datetime
|
|
|
|
|
|
class PriceHistoryCreate(BaseModel):
|
|
product_id: int
|
|
price: Optional[float] = None
|
|
shipping_cost: Optional[float] = None
|
|
stock_status: Optional[str] = None
|
|
fetch_method: str
|
|
fetch_status: str
|
|
fetched_at: datetime
|
|
|
|
|
|
class PriceHistoryUpdate(BaseModel):
|
|
price: Optional[float] = None
|
|
shipping_cost: Optional[float] = None
|
|
stock_status: Optional[str] = None
|
|
fetch_method: Optional[str] = None
|
|
fetch_status: Optional[str] = None
|
|
fetched_at: Optional[datetime] = None
|
|
|
|
|
|
class ScrapingLogOut(BaseModel):
|
|
id: int
|
|
product_id: Optional[int] = None
|
|
url: str
|
|
source: str
|
|
reference: Optional[str] = None
|
|
fetch_method: str
|
|
fetch_status: str
|
|
fetched_at: datetime
|
|
duration_ms: Optional[int] = None
|
|
html_size_bytes: Optional[int] = None
|
|
errors: Optional[list[str]] = None
|
|
notes: Optional[list[str]] = None
|
|
|
|
|
|
class WebhookOut(BaseModel):
|
|
id: int
|
|
event: str
|
|
url: str
|
|
enabled: bool
|
|
secret: Optional[str] = None
|
|
created_at: datetime
|
|
|
|
|
|
class WebhookCreate(BaseModel):
|
|
event: str
|
|
url: str
|
|
enabled: bool = True
|
|
secret: Optional[str] = None
|
|
|
|
|
|
class WebhookUpdate(BaseModel):
|
|
event: Optional[str] = None
|
|
url: Optional[str] = None
|
|
enabled: Optional[bool] = None
|
|
secret: Optional[str] = None
|
|
|
|
|
|
class WebhookTestResponse(BaseModel):
|
|
status: str
|
|
|
|
|
|
class ScrapingLogCreate(BaseModel):
|
|
product_id: Optional[int] = None
|
|
url: str
|
|
source: str
|
|
reference: Optional[str] = None
|
|
fetch_method: str
|
|
fetch_status: str
|
|
fetched_at: datetime
|
|
duration_ms: Optional[int] = None
|
|
html_size_bytes: Optional[int] = None
|
|
errors: Optional[list[str]] = None
|
|
notes: Optional[list[str]] = None
|
|
|
|
|
|
class ScrapingLogUpdate(BaseModel):
|
|
product_id: Optional[int] = None
|
|
url: Optional[str] = None
|
|
source: Optional[str] = None
|
|
reference: Optional[str] = None
|
|
fetch_method: Optional[str] = None
|
|
fetch_status: Optional[str] = None
|
|
fetched_at: Optional[datetime] = None
|
|
duration_ms: Optional[int] = None
|
|
html_size_bytes: Optional[int] = None
|
|
errors: Optional[list[str]] = None
|
|
notes: Optional[list[str]] = None
|
|
|
|
|
|
class EnqueueRequest(BaseModel):
|
|
url: str = Field(..., description="URL du produit")
|
|
use_playwright: Optional[bool] = None
|
|
save_db: bool = True
|
|
|
|
|
|
class EnqueueResponse(BaseModel):
|
|
job_id: str
|
|
|
|
|
|
class ScheduleRequest(BaseModel):
|
|
url: str = Field(..., description="URL du produit")
|
|
interval_hours: int = Field(default=24, ge=1)
|
|
use_playwright: Optional[bool] = None
|
|
save_db: bool = True
|
|
|
|
|
|
class ScheduleResponse(BaseModel):
|
|
job_id: str
|
|
next_run: datetime
|
|
|
|
|
|
class ScrapePreviewRequest(BaseModel):
|
|
url: str
|
|
use_playwright: Optional[bool] = None
|
|
|
|
|
|
class ScrapePreviewResponse(BaseModel):
|
|
success: bool
|
|
snapshot: Optional[dict[str, object]] = None
|
|
error: Optional[str] = None
|
|
|
|
|
|
class ScrapeCommitRequest(BaseModel):
|
|
snapshot: dict[str, object]
|
|
|
|
|
|
class ScrapeCommitResponse(BaseModel):
|
|
success: bool
|
|
product_id: Optional[int] = None
|
|
error: Optional[str] = None
|
|
|
|
|
|
class VersionResponse(BaseModel):
|
|
api_version: str
|
|
|
|
|
|
class BackendLogEntry(BaseModel):
|
|
time: datetime
|
|
level: str
|
|
message: str
|
|
|
|
|
|
class UvicornLogEntry(BaseModel):
|
|
line: str
|