72 lines
2.4 KiB
Python
72 lines
2.4 KiB
Python
"""商品查询 API。"""
|
|
from __future__ import annotations
|
|
|
|
from uuid import UUID
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy import func, select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from db import get_db
|
|
from models import Product, ProductAsset
|
|
from schemas import AssetOut, ProductListOut, ProductOut
|
|
from services import storage
|
|
|
|
router = APIRouter(prefix="/api", tags=["products"])
|
|
|
|
|
|
def _asset_out(a: ProductAsset) -> AssetOut:
|
|
return AssetOut(
|
|
id=str(a.id),
|
|
group_key=a.group_key,
|
|
variant_name=a.variant_name,
|
|
type=a.type,
|
|
source_url=a.source_url,
|
|
url=a.stored_url,
|
|
status=a.status,
|
|
)
|
|
|
|
|
|
@router.get("/products", response_model=ProductListOut)
|
|
async def list_products(
|
|
q: str = "",
|
|
page: int = 1,
|
|
page_size: int = 20,
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
cond = []
|
|
if q:
|
|
cond.append(Product.name.contains(q))
|
|
total = (await db.scalar(select(func.count()).select_from(Product).where(*cond))) or 0
|
|
rows = (await db.scalars(
|
|
select(Product).where(*cond).order_by(Product.created_at.desc())
|
|
.offset((page - 1) * page_size).limit(page_size)
|
|
)).all()
|
|
return ProductListOut(total=total, items=[
|
|
ProductOut(
|
|
id=str(p.id), stage=p.stage, source_platform=p.source_platform,
|
|
source_item_id=p.source_item_id, source_url=p.source_url,
|
|
name=p.name, description=p.description, price=p.price,
|
|
asset_counts=p.asset_counts,
|
|
created_at=p.created_at.isoformat() if p.created_at else None,
|
|
) for p in rows
|
|
])
|
|
|
|
|
|
@router.get("/products/{product_id}", response_model=ProductOut)
|
|
async def get_product(product_id: str, db: AsyncSession = Depends(get_db)):
|
|
p = await db.get(Product, UUID(product_id))
|
|
if p is None:
|
|
raise HTTPException(status_code=404, detail="商品不存在")
|
|
assets = (await db.scalars(
|
|
select(ProductAsset).where(ProductAsset.product_id == p.id)
|
|
.order_by(ProductAsset.sort_order)
|
|
)).all()
|
|
return ProductOut(
|
|
id=str(p.id), stage=p.stage, source_platform=p.source_platform,
|
|
source_item_id=p.source_item_id, source_url=p.source_url,
|
|
name=p.name, description=p.description, price=p.price,
|
|
asset_counts=p.asset_counts, assets=[_asset_out(a) for a in assets],
|
|
created_at=p.created_at.isoformat() if p.created_at else None,
|
|
)
|