66 lines
2.5 KiB
Python
66 lines
2.5 KiB
Python
"""Recommendation generation and reviewed publication endpoints."""
|
|||
|
|
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
from fastapi import APIRouter, Depends, Header, Path
|
||
|
|
|
||
|
|
from app.api.dependencies.auth import build_request_context
|
||
|
|
from app.api.dependencies.rate_limit import enforce_rate_limit
|
||
|
|
from app.core.contracts import RequestContext
|
||
|
|
from app.core.product_recommendation_contracts import ProductRecommendationQuery
|
||
|
|
from app.service.product_recommendation_service import ProductRecommendationService
|
||
|
|
|
||
|
|
advisor_router = APIRouter(
|
||
|
|
prefix="/api/v1/advisor",
|
||
|
|
tags=["advisor-recommendations"],
|
||
|
|
dependencies=[Depends(enforce_rate_limit)],
|
||
|
|
)
|
||
|
|
admin_router = APIRouter(
|
||
|
|
prefix="/api/v1/admin",
|
||
|
|
tags=["platform-admin"],
|
||
|
|
dependencies=[Depends(enforce_rate_limit)],
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
@advisor_router.post("/recommendations")
|
||
|
|
async def generate_recommendation(
|
||
|
|
payload: ProductRecommendationQuery,
|
||
|
|
context: RequestContext = Depends(build_request_context), # noqa: B008
|
||
|
|
key: str | None = Header(default=None, alias="Idempotency-Key"),
|
||
|
|
) -> dict[str, object]:
|
||
|
|
return await ProductRecommendationService().generate(payload, context, key)
|
||
|
|
|
||
|
|
|
||
|
|
@advisor_router.get("/recommendations/published")
|
||
|
|
async def published_recommendations(
|
||
|
|
context: RequestContext = Depends(build_request_context), # noqa: B008
|
||
|
|
) -> dict[str, object]:
|
||
|
|
return await ProductRecommendationService().published(context)
|
||
|
|
|
||
|
|
|
||
|
|
@admin_router.post("/advisor/recommendations/{content_id}/reviews")
|
||
|
|
async def review_recommendation(
|
||
|
|
payload: dict[str, Any],
|
||
|
|
content_id: int = Path(gt=0),
|
||
|
|
context: RequestContext = Depends(build_request_context), # noqa: B008
|
||
|
|
key: str | None = Header(default=None, alias="Idempotency-Key"),
|
||
|
|
) -> dict[str, object]:
|
||
|
|
decision = payload.get("decision")
|
||
|
|
if decision not in {"approved", "rejected"}:
|
||
|
|
from app.core.errors import ValidationAgentError
|
||
|
|
|
||
|
|
raise ValidationAgentError("decision 必须为 approved 或 rejected")
|
||
|
|
comment = payload.get("comment", "")
|
||
|
|
if not isinstance(comment, str):
|
||
|
|
raise ValueError("comment must be a string")
|
||
|
|
return await ProductRecommendationService().review(content_id, decision, comment, context, key)
|
||
|
|
|
||
|
|
|
||
|
|
@admin_router.post("/advisor/recommendations/{content_id}/publications")
|
||
|
|
async def publish_recommendation(
|
||
|
|
content_id: int = Path(gt=0),
|
||
|
|
context: RequestContext = Depends(build_request_context), # noqa: B008
|
||
|
|
key: str | None = Header(default=None, alias="Idempotency-Key"),
|
||
|
|
) -> dict[str, object]:
|
||
|
|
return await ProductRecommendationService().publish(content_id, context, key)
|