""" 销售日志 API 路由 — /api/sales-logs """ from __future__ import annotations import uuid import asyncio from fastapi import APIRouter, Depends, Body, HTTPException from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.api.deps import get_current_user, get_current_company_id from app.db.database import get_db from app.schemas.auth import CurrentUserPayload from app.schemas.response import ok from app.services import sales_log_service router = APIRouter(prefix="/sales-logs", tags=["销售日志"]) @router.get("", summary="查询销售日志列表") async def list_logs( page: int = 1, size: int = 20, customer_id: str | None = None, user_id: str | None = None, start_date: str | None = None, end_date: str | None = None, db: AsyncSession = Depends(get_db), current_user: CurrentUserPayload = Depends(get_current_user), company_id: uuid.UUID = Depends(get_current_company_id), ): result = await sales_log_service.list_logs( db, current_user, page=page, size=size, customer_id=customer_id, user_id=user_id, start_date=start_date, end_date=end_date, company_id=company_id, ) return ok(data=result) async def _resolve_company_ids( db: AsyncSession, company_id: uuid.UUID, customer_id: str | None, company_ids: list[str] | None, ) -> list[uuid.UUID]: """ 智能解析 involved_company_ids: 1. 如果前端显式传了 company_ids,使用它 2. 否则以当前视角公司为基础 3. 如果选了客户,自动查客户 owner 所属的公司,合并进来 """ if company_ids: resolved = set(uuid.UUID(cid) for cid in company_ids) else: resolved = {company_id} # 自动关联客户 owner 所在公司 if customer_id: from app.models.crm import CrmCustomer from app.models.sys import SysUserCompany cust = await db.get(CrmCustomer, uuid.UUID(customer_id)) if cust and cust.owner_id: stmt = select(SysUserCompany.company_id).where( SysUserCompany.user_id == cust.owner_id ) rows = (await db.execute(stmt)).scalars().all() for cid in rows: resolved.add(cid) # 确保当前公司始终在内 resolved.add(company_id) return list(resolved) @router.post("", summary="创建销售日志") async def create_log( content: str = Body(..., embed=True), customer_id: str | None = Body(None, embed=True), contact_ids: list[str] | None = Body(None, embed=True), log_date: str | None = Body(None, embed=True), company_ids: list[str] | None = Body(None, embed=True), db: AsyncSession = Depends(get_db), current_user: CurrentUserPayload = Depends(get_current_user), company_id: uuid.UUID = Depends(get_current_company_id), ): from datetime import date as date_type parsed_date = None if log_date: parsed_date = date_type.fromisoformat(log_date) # 智能解析公司关联 resolved_company_ids = await _resolve_company_ids(db, company_id, customer_id, company_ids) result = await sales_log_service.create_log( db, current_user, content=content, customer_id=customer_id, contact_ids=contact_ids, log_date=parsed_date, company_ids=resolved_company_ids, ) # 异步触发 Dify 画像提取工作流(仅当关联了客户时) if customer_id: asyncio.create_task( sales_log_service.trigger_persona_workflow( log_id=uuid.UUID(result["id"]), customer_id=uuid.UUID(customer_id), content=content, salesperson_name=getattr(current_user, "real_name", ""), contact_ids=contact_ids, ) ) return ok(data=result, message="日志创建成功") @router.put("/{log_id}", summary="编辑销售日志") async def update_log( log_id: uuid.UUID, content: str | None = Body(None, embed=True), customer_id: str | None = Body(None, embed=True), contact_ids: list[str] | None = Body(None, embed=True), log_date: str | None = Body(None, embed=True), db: AsyncSession = Depends(get_db), current_user: CurrentUserPayload = Depends(get_current_user), company_id: uuid.UUID = Depends(get_current_company_id), ): result = await sales_log_service.update_log( db, current_user, log_id, content=content, customer_id=customer_id, contact_ids=contact_ids, log_date=log_date, company_id=company_id, ) return ok(data=result, message="日志更新成功") @router.delete("/{log_id}", summary="删除销售日志(软删除)") async def delete_log( log_id: uuid.UUID, db: AsyncSession = Depends(get_db), current_user: CurrentUserPayload = Depends(get_current_user), ): await sales_log_service.delete_log(db, current_user, log_id) return ok(message="日志已删除")