- 新增多个 API 路由:`/api/customers`, `/api/products`, `/api/advisors`, `/api/compliance`, `/api/staff`,支持客户信息、产品详情、理财师客户列表、合规判定及员工上下文查询。 - 引入平台服务层,封装核心只读操作,支持数据脱敏功能。 - 更新依赖注入,确保各 API 路由的权限控制与数据访问一致性。 - 添加相应的单元测试,确保新接口的功能完整性与稳定性。 此更新为代销平台提供了基础的 REST API 支持,增强了系统的可扩展性与可维护性。
91 lines
2.9 KiB
Python
91 lines
2.9 KiB
Python
"""代销平台 · 客户 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.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()
|