""" 增值服务管理 API(管理员) 四大类服务: app_custom / platform_proxy / data_custom / private_project """ from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from pydantic import BaseModel from typing import Optional, List from ...database import get_db from ...models import ValueAddedService, CustomServiceOrder, CustomServiceRequest, MarketApp, User from ...auth import get_current_admin from ...middleware.log_service import LogService import uuid import json from datetime import datetime router = APIRouter() class CreateServiceRequest(BaseModel): name: str service_type: str description: Optional[str] = None price: float = 0 features: Optional[str] = None status: str = "active" assigned_agent_id: Optional[str] = None class UpdateServiceRequest(BaseModel): name: Optional[str] = None price: Optional[float] = None service_type: Optional[str] = None description: Optional[str] = None features: Optional[str] = None status: Optional[str] = None assigned_agent_id: Optional[str] = None # 服务类型映射 SERVICE_TYPE_MAP = { "app_custom": "应用定制服务", "platform_proxy": "平台代理申请", "data_custom": "数据定制服务", "private_project": "私有化项目服务", } # ============================================================ # 增值服务 CRUD # ============================================================ @router.get("/") async def get_services( service_type: str = Query(None, description="服务类型筛选: app_custom/platform_proxy/data_custom/private_project"), status: str = Query(None, description="状态筛选: active/inactive/deleted"), admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """获取增值服务列表""" import logging logger = logging.getLogger(__name__) logger.info(f"Admin {admin_user.username} requested services list: type={service_type}, status={status}") query = db.query(ValueAddedService).filter(ValueAddedService.status != "deleted") if service_type: query = query.filter(ValueAddedService.type == service_type) if status: query = query.filter(ValueAddedService.status == status) services = query.order_by(ValueAddedService.created_at.desc()).all() result = [] for s in services: result.append({ "id": s.id, "name": s.name, "description": s.description, "price": float(s.price) if s.price else 0, "type": s.type, "type_name": SERVICE_TYPE_MAP.get(s.type, s.type), "features": s.features or [], "status": s.status, "assigned_agent_id": s.assigned_agent_id, "created_at": s.created_at.isoformat() if s.created_at else None, "updated_at": s.updated_at.isoformat() if s.updated_at else None, }) return result @router.post("/") async def create_service( req: CreateServiceRequest, admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """创建增值服务""" import logging logger = logging.getLogger(__name__) if req.service_type not in SERVICE_TYPE_MAP: raise HTTPException(status_code=400, detail=f"无效的服务类型,可选值:{', '.join(SERVICE_TYPE_MAP.keys())}") features_json = None if req.features: try: features_json = json.loads(req.features) if isinstance(req.features, str) else req.features except (json.JSONDecodeError, TypeError): features_json = [req.features] service = ValueAddedService( id=str(uuid.uuid4()), name=req.name, description=req.description, price=req.price, type=req.service_type, features=features_json, status=req.status, assigned_agent_id=req.assigned_agent_id, ) db.add(service) db.commit() db.refresh(service) logger.info(f"Admin {admin_user.username} created service: {service.id} - {req.name}") LogService.log_audit( admin_id=admin_user.id, admin_name=admin_user.username, action="create_service", target_type="value_added_service", target_id=service.id, detail=f"创建增值服务 {req.name}(类型: {SERVICE_TYPE_MAP.get(req.service_type)})", ) return {"message": "增值服务已创建", "id": service.id} @router.put("/{id}") async def update_service( id: str, req: UpdateServiceRequest, admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """更新增值服务""" import logging logger = logging.getLogger(__name__) service = db.query(ValueAddedService).filter(ValueAddedService.id == id).first() if not service: raise HTTPException(status_code=404, detail="增值服务不存在") if req.name is not None: service.name = req.name if req.price is not None: service.price = req.price if req.service_type is not None: if req.service_type not in SERVICE_TYPE_MAP: raise HTTPException(status_code=400, detail=f"无效的服务类型") service.type = req.service_type if req.description is not None: service.description = req.description if req.features is not None: try: service.features = json.loads(req.features) if isinstance(req.features, str) else req.features except (json.JSONDecodeError, TypeError): service.features = [req.features] if req.status is not None: service.status = req.status if req.assigned_agent_id is not None: service.assigned_agent_id = req.assigned_agent_id service.updated_at = datetime.now() db.commit() logger.info(f"Admin {admin_user.username} updated service: {id}") LogService.log_audit( admin_id=admin_user.id, admin_name=admin_user.username, action="update_service", target_type="value_added_service", target_id=id, detail=f"更新增值服务 {service.name}", ) return {"message": "增值服务已更新"} @router.delete("/{id}") async def delete_service( id: str, admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """逻辑删除增值服务(设置为 deleted 状态,保留数据记录)""" import logging logger = logging.getLogger(__name__) service = db.query(ValueAddedService).filter(ValueAddedService.id == id).first() if not service: raise HTTPException(status_code=404, detail="增值服务不存在") if service.status == "deleted": raise HTTPException(status_code=400, detail="该增值服务已被删除") logger.info(f"Admin {admin_user.username} soft-deleting service: {id} - {service.name}") service.status = "deleted" service.updated_at = datetime.now() db.commit() LogService.log_audit( admin_id=admin_user.id, admin_name=admin_user.username, action="delete_service", target_type="value_added_service", target_id=id, detail=f"逻辑删除增值服务 {service.name}", ) return {"message": "增值服务已删除(逻辑删除)"} # ============================================================ # 定制服务工单管理 (CustomServiceRequest) # ============================================================ @router.get("/custom-requests") async def get_custom_requests( request_type: str = Query(None, description="工单类型: data_custom/private_project/platform_proxy"), status: str = Query(None, description="状态: pending/processing/completed/rejected"), admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """获取定制服务工单列表""" import logging logger = logging.getLogger(__name__) logger.info(f"Admin {admin_user.username} requested custom requests: type={request_type}, status={status}") query = db.query(CustomServiceRequest) if request_type: query = query.filter(CustomServiceRequest.request_type == request_type) if status: query = query.filter(CustomServiceRequest.status == status) requests = query.order_by(CustomServiceRequest.created_at.desc()).all() result = [] for r in requests: # 查询用户名 user = db.query(User).filter(User.id == r.user_id).first() # 查询服务名 service = db.query(ValueAddedService).filter(ValueAddedService.id == r.service_id).first() result.append({ "id": r.id, "user_id": r.user_id, "username": user.username if user else "未知用户", "service_id": r.service_id, "service_name": service.name if service else "未知服务", "request_type": r.request_type, "request_type_name": SERVICE_TYPE_MAP.get(r.request_type, r.request_type), "title": r.title, "description": r.description, "requirements": r.requirements or {}, "status": r.status, "assigned_agent_id": r.assigned_agent_id, "created_at": r.created_at.isoformat() if r.created_at else None, "updated_at": r.updated_at.isoformat() if r.updated_at else None, }) return result @router.put("/custom-requests/{id}") async def update_custom_request( id: str, status: str = None, assigned_agent_id: str = None, admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """更新定制服务工单(分配Agent / 标记完成)""" import logging logger = logging.getLogger(__name__) req = db.query(CustomServiceRequest).filter(CustomServiceRequest.id == id).first() if not req: raise HTTPException(status_code=404, detail="工单不存在") if status is not None: if status not in ("pending", "processing", "completed", "rejected"): raise HTTPException(status_code=400, detail="无效的状态值") req.status = status if assigned_agent_id is not None: req.assigned_agent_id = assigned_agent_id req.updated_at = datetime.now() db.commit() logger.info(f"Admin {admin_user.username} updated custom request: {id}, status={status}, agent={assigned_agent_id}") LogService.log_audit( admin_id=admin_user.id, admin_name=admin_user.username, action="update_custom_request", target_type="custom_service_request", target_id=id, detail=f"更新工单状态: {status}, 分配Agent: {assigned_agent_id}", ) return {"message": "工单已更新"} # ============================================================ # 定制服务订单管理 (CustomServiceOrder - 保留兼容) # ============================================================ @router.get("/custom-orders") async def get_custom_orders( status: str = Query(None, description="状态筛选"), admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """获取定制服务订单列表""" query = db.query(CustomServiceOrder) if status: query = query.filter(CustomServiceOrder.status == status) orders = query.order_by(CustomServiceOrder.created_at.desc()).all() result = [] for o in orders: user = db.query(User).filter(User.id == o.user_id).first() result.append({ "id": o.id, "user_id": o.user_id, "username": user.username if user else "未知用户", "service_id": o.service_id, "service_type": o.service_type, "description": o.description, "status": o.status, "price": float(o.price) if o.price else 0, "order_id": o.order_id, "created_at": o.created_at.isoformat() if o.created_at else None, "updated_at": o.updated_at.isoformat() if o.updated_at else None, }) return result @router.put("/custom-orders/{id}") async def update_custom_order( id: str, status: str = None, price: float = None, admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """更新定制服务订单状态""" import logging logger = logging.getLogger(__name__) order = db.query(CustomServiceOrder).filter(CustomServiceOrder.id == id).first() if not order: raise HTTPException(status_code=404, detail="定制服务订单不存在") if status is not None: order.status = status if price is not None: order.price = price order.updated_at = datetime.now() db.commit() logger.info(f"Admin {admin_user.username} updated custom order: {id}, status={status}") LogService.log_audit( admin_id=admin_user.id, admin_name=admin_user.username, action="update_custom_order", target_type="custom_service_order", target_id=id, detail=f"更新定制服务订单状态为 {status}", ) return {"message": "定制服务订单已更新"} # ============================================================ # Agent 配置(为应用定制服务绑定市场Agent) # ============================================================ @router.get("/agents") async def get_available_agents( admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """获取可用的市场Agent列表(用于绑定到应用定制服务)""" from sqlalchemy import or_ agents = db.query(MarketApp).filter( MarketApp.type == "agent", or_(MarketApp.status == "published", MarketApp.status == "active") ).all() result = [] for a in agents: result.append({ "id": a.id, "name": a.name, "description": a.description, "publisher_name": a.publisher_name, }) return result @router.put("/{id}/agent") async def assign_agent_to_service( id: str, agent_id: str, admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """为应用定制服务绑定Agent""" import logging logger = logging.getLogger(__name__) service = db.query(ValueAddedService).filter(ValueAddedService.id == id).first() if not service: raise HTTPException(status_code=404, detail="增值服务不存在") # 验证agent存在 agent = db.query(MarketApp).filter( MarketApp.id == agent_id, MarketApp.type == "agent" ).first() if not agent: raise HTTPException(status_code=404, detail="Agent不存在") service.assigned_agent_id = agent_id service.updated_at = datetime.now() db.commit() logger.info(f"Admin {admin_user.username} assigned agent {agent_id} to service {id}") LogService.log_audit( admin_id=admin_user.id, admin_name=admin_user.username, action="assign_agent", target_type="value_added_service", target_id=id, detail=f"为服务 {service.name} 绑定Agent: {agent.name}", ) return {"message": "Agent绑定成功", "agent_name": agent.name}