| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- """订单调整 API"""
- from typing import Optional, List
- from fastapi import APIRouter, Depends, HTTPException, Query
- from sqlalchemy.orm import Session
- from pydantic import BaseModel, Field
- from app.core.database import get_db
- from app.core.auth import get_current_user
- from app.core.response import success_response, error_response
- from app.crud.order_adjust import order_adjust_crud
- from app.schemas.order_adjust import AdjustType
- router = APIRouter(prefix="/api/web/admin/order-adjust", tags=["订单调整"])
- class CreateAdjustRequest(BaseModel):
- """创建调整请求"""
- order_id: str = Field(..., description="订单ID")
- order_item_id: Optional[str] = Field(None, description="订单项ID")
- adjust_type: str = Field(..., description="调整类型: reduce-减量, delete-删除, substitute-替代")
- before_quantity: float = Field(..., description="调整前数量")
- after_quantity: float = Field(..., description="调整后数量")
- before_amount: float = Field(..., description="调整前金额")
- after_amount: float = Field(..., description="调整后金额")
- reason: str = Field(..., min_length=1, max_length=500, description="调整原因")
- substitute_product_id: Optional[str] = Field(None, description="替代商品ID")
- class AdjustResponse(BaseModel):
- """调整记录响应"""
- id: str
- order_id: str
- order_item_id: Optional[str]
- adjust_type: str
- adjust_type_text: str
- before_quantity: float
- after_quantity: float
- before_amount: float
- after_amount: float
- difference_amount: float
- reason: str
- substitute_product_id: Optional[str]
- operator_id: str
- operator_name: str
- create_at: str
- create_name: str
- class Config:
- from_attributes = True
- def adjust_to_response(adjust) -> dict:
- """将调整记录转换为响应格式"""
- adjust_type_map = {
- "reduce": "减量",
- "delete": "删除",
- "substitute": "替代"
- }
- return {
- "id": adjust.id,
- "orderId": adjust.order_id,
- "orderItemId": adjust.order_item_id,
- "adjustType": adjust.adjust_type,
- "adjustTypeText": adjust_type_map.get(adjust.adjust_type, adjust.adjust_type),
- "beforeQuantity": float(adjust.before_quantity or 0),
- "afterQuantity": float(adjust.after_quantity or 0),
- "beforeAmount": float(adjust.before_amount or 0),
- "afterAmount": float(adjust.after_amount or 0),
- "differenceAmount": float(adjust.difference_amount or 0),
- "reason": adjust.reason,
- "substituteProductId": adjust.substitute_product_id,
- "operatorId": adjust.operator_id,
- "operatorName": adjust.operator_name,
- "createAt": str(adjust.create_at) if adjust.create_at else "",
- "createName": adjust.create_name or ""
- }
- @router.post("/create", response_model=dict)
- def create_adjust(
- request: CreateAdjustRequest,
- db: Session = Depends(get_db),
- current_user: dict = Depends(get_current_user)
- ):
- """创建订单调整记录"""
- try:
- # 验证调整类型
- valid_types = ["reduce", "delete", "substitute"]
- if request.adjust_type not in valid_types:
- return error_response(400, f"无效的调整类型,支持的类型: {', '.join(valid_types)}")
- # 验证调整数量
- if request.after_quantity < 0:
- return error_response(400, "调整后数量不能为负数")
- # 验证金额
- if request.after_amount < 0:
- return error_response(400, "调整后金额不能为负数")
- # 创建调整记录
- adjust = order_adjust_crud.create_adjust(
- db=db,
- order_id=request.order_id,
- order_item_id=request.order_item_id,
- adjust_type=request.adjust_type,
- before_quantity=request.before_quantity,
- after_quantity=request.after_quantity,
- before_amount=request.before_amount,
- after_amount=request.after_amount,
- reason=request.reason,
- operator_id=current_user.get("user_id", ""),
- operator_name=current_user.get("real_name", current_user.get("username", "")),
- substitute_product_id=request.substitute_product_id
- )
- return success_response({
- "id": adjust.id,
- "message": "订单调整记录已创建"
- })
- except Exception as e:
- return error_response(500, f"创建调整记录失败: {str(e)}")
- @router.get("/list/{order_id}", response_model=dict)
- def get_order_adjusts_by_order(
- order_id: str,
- db: Session = Depends(get_db),
- current_user: dict = Depends(get_current_user)
- ):
- """获取指定订单的所有调整记录"""
- try:
- adjusts = order_adjust_crud.get_by_order(db, order_id)
- return success_response({
- "list": [adjust_to_response(a) for a in adjusts],
- "total": len(adjusts),
- "totalAmount": order_adjust_crud.get_total_adjust_amount(db, order_id)
- })
- except Exception as e:
- return error_response(500, f"获取调整记录失败: {str(e)}")
- @router.post("/list", response_model=dict)
- def get_order_adjust_list(
- page: int = 1,
- pageSize: int = 10,
- keyword: Optional[str] = None,
- adjustType: Optional[str] = None,
- startDate: Optional[str] = None,
- endDate: Optional[str] = None,
- db: Session = Depends(get_db),
- current_user: dict = Depends(get_current_user)
- ):
- """获取订单调整列表(支持分页和搜索)"""
- try:
- adjusts, total = order_adjust_crud.get_list(
- db=db,
- page=page,
- pageSize=pageSize,
- keyword=keyword,
- adjust_type=adjustType,
- start_date=startDate,
- end_date=endDate
- )
- return success_response({
- "list": [adjust_to_response(a) for a in adjusts],
- "total": total,
- "page": page,
- "pageSize": pageSize
- })
- except Exception as e:
- return error_response(500, f"获取调整记录列表失败: {str(e)}")
- @router.get("/detail/{adjust_id}", response_model=dict)
- def get_adjust_detail(
- adjust_id: str,
- db: Session = Depends(get_db),
- current_user: dict = Depends(get_current_user)
- ):
- """获取调整记录详情"""
- try:
- adjust = order_adjust_crud.get(db, adjust_id)
- if not adjust:
- return error_response(404, "调整记录不存在")
- if adjust.is_del == 1:
- return error_response(404, "调整记录已删除")
- return success_response(adjust_to_response(adjust))
- except Exception as e:
- return error_response(500, f"获取调整记录详情失败: {str(e)}")
- @router.delete("/{adjust_id}", response_model=dict)
- def delete_adjust(
- adjust_id: str,
- db: Session = Depends(get_db),
- current_user: dict = Depends(get_current_user)
- ):
- """删除调整记录(仅管理员可操作)"""
- try:
- # 检查权限
- if current_user.get("role") != "admin":
- return error_response(403, "仅管理员可删除调整记录")
- adjust = order_adjust_crud.get(db, adjust_id)
- if not adjust:
- return error_response(404, "调整记录不存在")
- # 软删除
- order_adjust_crud.delete(db, adjust_id)
- # 创建历史记录
- order_adjust_crud.create_adjust_history(
- db=db,
- original_record=adjust,
- operator_id=current_user.get("user_id", ""),
- operator_name=current_user.get("real_name", current_user.get("username", ""))
- )
- return success_response({"message": "删除成功"})
- except Exception as e:
- return error_response(500, f"删除调整记录失败: {str(e)}")
- @router.get("/statistics/{order_id}", response_model=dict)
- def get_adjust_statistics(
- order_id: str,
- db: Session = Depends(get_db),
- current_user: dict = Depends(get_current_user)
- ):
- """获取订单调整统计"""
- try:
- adjusts = order_adjust_crud.get_by_order(db, order_id)
- # 按类型统计
- reduce_count = sum(1 for a in adjusts if a.adjust_type == "reduce")
- delete_count = sum(1 for a in adjusts if a.adjust_type == "delete")
- substitute_count = sum(1 for a in adjusts if a.adjust_type == "substitute")
- total_refund = sum(
- abs(a.difference_amount or 0) for a in adjusts
- if a.difference_amount and a.difference_amount > 0
- )
- return success_response({
- "totalCount": len(adjusts),
- "reduceCount": reduce_count,
- "deleteCount": delete_count,
- "substituteCount": substitute_count,
- "totalRefund": total_refund
- })
- except Exception as e:
- return error_response(500, f"获取统计信息失败: {str(e)}")
|