before claude
This commit is contained in:
@@ -21,31 +21,32 @@ from sqlalchemy import and_, desc, func
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from pricewatch.app.api.schemas import (
|
||||
BackendLogEntry,
|
||||
EnqueueRequest,
|
||||
EnqueueResponse,
|
||||
HealthStatus,
|
||||
PriceHistoryOut,
|
||||
PriceHistoryCreate,
|
||||
PriceHistoryOut,
|
||||
PriceHistoryUpdate,
|
||||
ProductOut,
|
||||
ProductCreate,
|
||||
ProductHistoryPoint,
|
||||
ProductOut,
|
||||
ProductUpdate,
|
||||
ScheduleRequest,
|
||||
ScheduleResponse,
|
||||
ScrapingLogOut,
|
||||
ScrapingLogCreate,
|
||||
ScrapingLogUpdate,
|
||||
ScrapePreviewRequest,
|
||||
ScrapePreviewResponse,
|
||||
ScrapeCommitRequest,
|
||||
ScrapeCommitResponse,
|
||||
VersionResponse,
|
||||
BackendLogEntry,
|
||||
ScrapePreviewRequest,
|
||||
ScrapePreviewResponse,
|
||||
ScrapingLogCreate,
|
||||
ScrapingLogOut,
|
||||
ScrapingLogUpdate,
|
||||
UvicornLogEntry,
|
||||
WebhookOut,
|
||||
VersionResponse,
|
||||
WebhookCreate,
|
||||
WebhookUpdate,
|
||||
WebhookOut,
|
||||
WebhookTestResponse,
|
||||
WebhookUpdate,
|
||||
)
|
||||
from pricewatch.app.core.config import get_config
|
||||
from pricewatch.app.core.logging import get_logger
|
||||
@@ -794,6 +795,9 @@ def _read_uvicorn_lines(limit: int = 200) -> list[str]:
|
||||
return []
|
||||
|
||||
|
||||
PRODUCT_HISTORY_LIMIT = 12
|
||||
|
||||
|
||||
def _product_to_out(session: Session, product: Product) -> ProductOut:
|
||||
"""Helper pour mapper Product + dernier prix."""
|
||||
latest = (
|
||||
@@ -810,6 +814,18 @@ def _product_to_out(session: Session, product: Product) -> ProductOut:
|
||||
discount_amount = float(product.msrp) - float(latest.price)
|
||||
if product.msrp > 0:
|
||||
discount_percent = (discount_amount / float(product.msrp)) * 100
|
||||
history_rows = (
|
||||
session.query(PriceHistory)
|
||||
.filter(PriceHistory.product_id == product.id, PriceHistory.price != None)
|
||||
.order_by(desc(PriceHistory.fetched_at))
|
||||
.limit(PRODUCT_HISTORY_LIMIT)
|
||||
.all()
|
||||
)
|
||||
history_points = [
|
||||
ProductHistoryPoint(price=float(row.price), fetched_at=row.fetched_at)
|
||||
for row in reversed(history_rows)
|
||||
if row.price is not None
|
||||
]
|
||||
return ProductOut(
|
||||
id=product.id,
|
||||
source=product.source,
|
||||
@@ -832,6 +848,7 @@ def _product_to_out(session: Session, product: Product) -> ProductOut:
|
||||
specs=specs,
|
||||
discount_amount=discount_amount,
|
||||
discount_percent=discount_percent,
|
||||
history=history_points,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,11 @@ class HealthStatus(BaseModel):
|
||||
redis: bool
|
||||
|
||||
|
||||
class ProductHistoryPoint(BaseModel):
|
||||
price: float
|
||||
fetched_at: datetime
|
||||
|
||||
|
||||
class ProductOut(BaseModel):
|
||||
id: int
|
||||
source: str
|
||||
@@ -33,6 +38,7 @@ class ProductOut(BaseModel):
|
||||
specs: dict[str, str] = {}
|
||||
discount_amount: Optional[float] = None
|
||||
discount_percent: Optional[float] = None
|
||||
history: list[ProductHistoryPoint] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ProductCreate(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user