"""投顾工作台请求 DTO(入参校验;响应多以 dict 返回,随业务拼装)。""" from __future__ import annotations from datetime import datetime from typing import Any, Literal from common_const import ( TALK_SCENE_CUSTOMER_COMPLAINT, TALK_SCENE_MARKET_FLUCTUATION, TALK_SCENE_PORTFOLIO_DIVERGENCE, TALK_SCENE_RISK_BLOCK_ORDER, ) from pydantic import BaseModel, Field class DraftSaveReq(BaseModel): """草稿编辑保存入参(代理到 Agent PUT /draft/{id}/save,Agent 重新适当性校验)。""" title: str | None = Field(default=None, max_length=128) content: str = Field(default="") suggestions: Any = None # 结构化建议清单(超配赎回/低配申购),结构由 Agent 定义 class DraftOperateReq(BaseModel): """草稿操作入参(仅支持 discard 废弃)。""" action: str = Field(pattern="^(discard)$") class RebalanceRunReq(BaseModel): """触发调仓再平衡(异步受理,结果靠事件回执)。""" customer_id: int = Field(gt=0) class AdvisorDataQueryReq(BaseModel): """工作台代理 Agent 的客户数据查询请求。""" customer_id: int = Field(gt=0) question: str = Field(min_length=1, max_length=2000) session_id: str | None = Field(default=None, max_length=64) max_rows: int | None = Field(default=None, gt=0, le=10000) page: int = Field(default=1, ge=1, le=100000) page_size: int = Field(default=100, ge=1, le=10000) sort_by: str | None = Field(default=None, max_length=128) sort_order: Literal["asc", "desc"] = "asc" class TalkScriptReq(BaseModel): """生成沟通话术草稿(同步,超时由工作台降级为「稍后重试」)。""" customer_id: int = Field(gt=0) scene_type: Literal[ TALK_SCENE_RISK_BLOCK_ORDER, TALK_SCENE_MARKET_FLUCTUATION, TALK_SCENE_PORTFOLIO_DIVERGENCE, TALK_SCENE_CUSTOMER_COMPLAINT, ] class RelationReq(BaseModel): """客户关系流转(sign=签约 / close=结束服务),工作台是签约状态唯一写入方。""" action: str = Field(pattern="^(sign|close)$") reason: str | None = Field(default=None, max_length=128) class VisitCreateReq(BaseModel): """人工回访留痕入参(不触发 Agent 记忆抽取)。""" customer_id: int = Field(gt=0) visit_type: str = Field(min_length=1, max_length=32) visit_time: datetime summary: str | None = None audio_url: str | None = Field(default=None, max_length=512) class VisitUpdateReq(BaseModel): """回访记录可编辑字段;不提供字段时拒绝空更新。""" visit_type: str | None = Field(default=None, min_length=1, max_length=32) visit_time: datetime | None = None summary: str | None = None audio_url: str | None = Field(default=None, max_length=512) class TodoHandleReq(BaseModel): """待办处理入参(process=开始处理 / done=完成)。""" action: str = Field(pattern="^(process|done)$")