Files
group_xinghuo_jinrong/app/api/customers.py
T
zhanghongyu_0626 8556da489a feat(analyst): Add sample and escalate functionality to analyst API
- Introduced new endpoints `/api/analyst/query/{trace_id}/sample` and `/api/analyst/escalate` for sampling query results and escalating issues to human analysts, respectively.
- Enhanced `AnalystAgent` to support sampling of SQL results based on trace ID and to handle escalation requests, improving user experience in error scenarios.
- Updated `analyst_schemas.py` to include `EscalateRequest` for structured escalation requests.
- Added corresponding frontend API calls and UI components to facilitate user interactions with the new features.
- Implemented unit tests to ensure the reliability of the new functionalities.

This update significantly enhances the analytical capabilities of the application, allowing users to retrieve detailed query samples and escalate issues effectively.
2026-09-11 15:18:56 +08:00

117 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""代销平台 · 客户 L0 与资产读 API(canonical · 不要求 X-Agent-Type)。"""
from __future__ import annotations
from fastapi import APIRouter, Depends, Query, Request
from app.api.deps import (
AuthContext,
assert_platform_customer_access,
get_platform_auth_context,
)
from app.repository.core_ro import CoreReadOnlyRepository
from app.repository.risk_repository import RiskRepository
from app.service.platform import customer_service
from app.utils.exceptions import ApiError
from app.utils.response import ok
router = APIRouter(prefix="/api/customers", tags=["platform-customers"])
def _core_ro() -> CoreReadOnlyRepository:
return CoreReadOnlyRepository()
def _risk_repo() -> RiskRepository:
return RiskRepository()
def _trace_id(request: Request) -> str:
return getattr(request.state, "trace_id", "unknown")
@router.get("/{customer_id}")
def get_customer_api(
customer_id: str,
request: Request,
auth: AuthContext = Depends(get_platform_auth_context),
) -> dict:
core = _core_ro()
repo = _risk_repo()
assert_platform_customer_access(auth, customer_id, core_ro=core, risk_repo=repo)
row = customer_service.get_customer_l0(customer_id, core_ro=core)
if row is None:
raise ApiError(404, "NOT_FOUND", f"customer not found: {customer_id}")
return ok(row, _trace_id(request)).model_dump()
@router.get("/{customer_id}/holdings")
def list_holdings_api(
customer_id: str,
request: Request,
limit: int = Query(500, ge=1, le=500),
auth: AuthContext = Depends(get_platform_auth_context),
) -> dict:
core = _core_ro()
repo = _risk_repo()
assert_platform_customer_access(auth, customer_id, core_ro=core, risk_repo=repo)
data = customer_service.list_holdings(customer_id, limit=limit, core_ro=core)
return ok(data, _trace_id(request)).model_dump()
@router.post("/{customer_id}/threshold-check")
def threshold_check_api(
customer_id: str,
request: Request,
push: bool = Query(False, description="演示:命中时 Redis pub 主动推送"),
auth: AuthContext = Depends(get_platform_auth_context),
) -> dict:
"""C-04:主动扫描亏损阈值(可选 push)。"""
from app.service.threshold_service import run_threshold_check
core = _core_ro()
repo = _risk_repo()
assert_platform_customer_access(auth, customer_id, core_ro=core, risk_repo=repo)
holdings = customer_service.list_holdings(customer_id, limit=500, core_ro=core)
rows = holdings.get("items") if isinstance(holdings, dict) else []
if not isinstance(rows, list):
rows = []
result = run_threshold_check(
customer_id,
rows,
trace_id=_trace_id(request),
push=push,
)
return ok(result, _trace_id(request)).model_dump()
@router.get("/{customer_id}/trades")
def list_trades_api(
customer_id: str,
request: Request,
limit: int = Query(50, ge=1, le=200),
offset: int = Query(0, ge=0),
auth: AuthContext = Depends(get_platform_auth_context),
) -> dict:
core = _core_ro()
repo = _risk_repo()
assert_platform_customer_access(auth, customer_id, core_ro=core, risk_repo=repo)
data = customer_service.list_trades(
customer_id, limit=limit, offset=offset, core_ro=core
)
return ok(data, _trace_id(request)).model_dump()
@router.get("/{customer_id}/products")
def list_customer_products_api(
customer_id: str,
request: Request,
limit: int = Query(50, ge=1, le=200),
auth: AuthContext = Depends(get_platform_auth_context),
) -> dict:
core = _core_ro()
repo = _risk_repo()
assert_platform_customer_access(auth, customer_id, core_ro=core, risk_repo=repo)
data = customer_service.list_customer_products(customer_id, limit=limit, core_ro=core)
return ok(data, _trace_id(request)).model_dump()