覆盖所有模块: - api 层:17 个路由文件,每个接口标注用途、参数、返回值、权限 - services 层:18 个服务文件,每个方法标注作用、参数、返回值、调用方 - repositories 层:13 个仓储文件,每个方法标注查询逻辑和被调用方 - schemas 层:11 个请求/响应体文件,每个字段标注业务含义 - core 层:config、security、exceptions、responses、error_codes - models 层:19 个 ORM 模型类,每个表标注业务含义和关联关系 - scripts:bootstrap_data、smoke_check - migrations:env.py 和版本迁移文件 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
205 lines
9.1 KiB
Python
205 lines
9.1 KiB
Python
"""
|
||
产品管理路由模块
|
||
|
||
职责:
|
||
处理产品和产品分类的增删改查接口,URL 前缀为空(路由在路径中定义)。
|
||
包括:产品分类的列表/创建/更新、产品的列表/创建/更新/详情、
|
||
产品规格的更新和默认规格设置。
|
||
|
||
注意:本模块使用 /api/product-categories 和 /api/products 作为路径前缀,
|
||
而非使用 APIRouter(prefix=...) 统一设置。
|
||
"""
|
||
from fastapi import APIRouter, Depends, Query
|
||
from sqlalchemy.orm import Session
|
||
|
||
from backend.app.api.deps import get_product_service
|
||
from backend.app.db import get_db_session
|
||
from backend.app.schemas.common import success_payload
|
||
from backend.app.schemas.products import (
|
||
CreateCategoryRequest,
|
||
CreateProductRequest,
|
||
UpdateCategoryRequest,
|
||
UpdateProductCategoryRequest,
|
||
UpdateProductRequest,
|
||
UpdateProductSpecificationRequest,
|
||
)
|
||
from backend.app.services.product_service import ProductService
|
||
|
||
router = APIRouter(tags=["products"])
|
||
|
||
|
||
@router.get("/api/product-categories")
|
||
def list_categories(
|
||
category_name: str | None = Query(default=None), # 分类名称模糊搜索
|
||
status: int | None = Query(default=None), # 分类状态筛选(启用/停用)
|
||
page_no: int = Query(default=1), # 页码,默认第 1 页
|
||
page_size: int = Query(default=20), # 每页条数,默认 20 条
|
||
product_service: ProductService = Depends(get_product_service), # 注入产品服务
|
||
session: Session = Depends(get_db_session), # 注入数据库会话
|
||
) -> dict:
|
||
"""分页查询产品分类列表
|
||
|
||
用途:获取所有产品分类,支持按名称和状态筛选。
|
||
请求参数:Query 参数筛选 + 分页参数。
|
||
返回值:分页分类列表,包含 total、page_no、page_size、list。
|
||
权限要求:无特殊权限限制(未配置角色鉴权)。
|
||
"""
|
||
result = product_service.list_categories(
|
||
session=session,
|
||
filters={"category_name": category_name, "status": status},
|
||
)
|
||
start = max(page_no - 1, 0) * page_size
|
||
result["list"] = result["list"][start : start + page_size]
|
||
result["page_no"] = page_no
|
||
result["page_size"] = page_size
|
||
return success_payload(result)
|
||
|
||
|
||
@router.post("/api/product-categories")
|
||
def create_category(
|
||
payload: CreateCategoryRequest, # 创建分类的请求体
|
||
product_service: ProductService = Depends(get_product_service), # 注入产品服务
|
||
session: Session = Depends(get_db_session), # 注入数据库会话
|
||
) -> dict:
|
||
"""创建产品分类
|
||
|
||
用途:新增一个产品分类。
|
||
请求参数:CreateCategoryRequest(分类名称、描述等)。
|
||
返回值:创建成功后的分类信息。
|
||
权限要求:无特殊权限限制(未配置角色鉴权)。
|
||
"""
|
||
return success_payload(product_service.create_category(payload.model_dump(), session))
|
||
|
||
|
||
@router.put("/api/product-categories/{category_id}")
|
||
def update_category(
|
||
category_id: int, # 分类 ID(路径参数)
|
||
payload: UpdateProductCategoryRequest, # 更新分类的请求体
|
||
product_service: ProductService = Depends(get_product_service), # 注入产品服务
|
||
session: Session = Depends(get_db_session), # 注入数据库会话
|
||
) -> dict:
|
||
"""更新产品分类
|
||
|
||
用途:修改已有产品分类的名称、状态等信息。
|
||
请求参数:category_id(路径参数)+ UpdateProductCategoryRequest(更新字段)。
|
||
返回值:更新后的分类信息。
|
||
权限要求:无特殊权限限制(未配置角色鉴权)。
|
||
"""
|
||
return success_payload(product_service.update_category(category_id, payload.model_dump(), session))
|
||
|
||
|
||
@router.get("/api/products")
|
||
def list_products(
|
||
product_name: str | None = Query(default=None), # 产品名称模糊搜索
|
||
specification: str | None = Query(default=None), # 规格模糊搜索
|
||
category_id: int | None = Query(default=None), # 产品分类 ID 筛选
|
||
status: int | None = Query(default=None), # 产品状态筛选(启用/停用)
|
||
page_no: int = Query(default=1), # 页码,默认第 1 页
|
||
page_size: int = Query(default=20), # 每页条数,默认 20 条
|
||
product_service: ProductService = Depends(get_product_service), # 注入产品服务
|
||
session: Session = Depends(get_db_session), # 注入数据库会话
|
||
) -> dict:
|
||
"""分页查询产品列表
|
||
|
||
用途:获取所有产品信息,支持按名称、规格、分类、状态筛选。
|
||
请求参数:Query 参数筛选 + 分页参数。
|
||
返回值:分页产品列表,包含 total、page_no、page_size、list。
|
||
权限要求:无特殊权限限制(未配置角色鉴权)。
|
||
"""
|
||
result = product_service.list_products(
|
||
{
|
||
"product_name": product_name,
|
||
"specification": specification,
|
||
"category_id": category_id,
|
||
"status": status,
|
||
},
|
||
session,
|
||
)
|
||
start = max(page_no - 1, 0) * page_size
|
||
result["list"] = result["list"][start : start + page_size]
|
||
result["page_no"] = page_no
|
||
result["page_size"] = page_size
|
||
return success_payload(result)
|
||
|
||
|
||
@router.post("/api/products")
|
||
def create_product(
|
||
payload: CreateProductRequest, # 创建产品的请求体
|
||
product_service: ProductService = Depends(get_product_service), # 注入产品服务
|
||
session: Session = Depends(get_db_session), # 注入数据库会话
|
||
) -> dict:
|
||
"""创建新产品
|
||
|
||
用途:新增一个产品记录。
|
||
请求参数:CreateProductRequest(产品名称、分类、规格等)。
|
||
返回值:创建成功后的产品信息。
|
||
权限要求:无特殊权限限制(未配置角色鉴权)。
|
||
"""
|
||
return success_payload(product_service.create_product(payload.model_dump(), session))
|
||
|
||
|
||
@router.put("/api/products/{product_id}")
|
||
def update_product(
|
||
product_id: int, # 产品 ID(路径参数)
|
||
payload: UpdateProductRequest, # 更新产品的请求体
|
||
product_service: ProductService = Depends(get_product_service), # 注入产品服务
|
||
session: Session = Depends(get_db_session), # 注入数据库会话
|
||
) -> dict:
|
||
"""更新产品信息
|
||
|
||
用途:修改已有产品的基本信息。
|
||
请求参数:product_id(路径参数)+ UpdateProductRequest(更新字段)。
|
||
返回值:更新后的产品信息。
|
||
权限要求:无特殊权限限制(未配置角色鉴权)。
|
||
"""
|
||
return success_payload(product_service.update_product(product_id, payload.model_dump(), session))
|
||
|
||
|
||
@router.put("/api/products/specifications/{product_id}")
|
||
def update_product_specification(
|
||
product_id: int, # 产品 ID(路径参数)
|
||
payload: UpdateProductSpecificationRequest, # 更新规格的请求体
|
||
product_service: ProductService = Depends(get_product_service), # 注入产品服务
|
||
session: Session = Depends(get_db_session), # 注入数据库会话
|
||
) -> dict:
|
||
"""更新产品规格
|
||
|
||
用途:修改指定产品的规格信息(如尺寸、材质等)。
|
||
请求参数:product_id(路径参数)+ UpdateProductSpecificationRequest(规格数据)。
|
||
返回值:更新后的规格信息。
|
||
权限要求:无特殊权限限制(未配置角色鉴权)。
|
||
"""
|
||
return success_payload(product_service.update_product_specification(product_id, payload.model_dump(), session))
|
||
|
||
|
||
@router.put("/api/products/specifications/{product_id}/default")
|
||
def set_default_specification(
|
||
product_id: int, # 产品 ID(路径参数)
|
||
product_service: ProductService = Depends(get_product_service), # 注入产品服务
|
||
session: Session = Depends(get_db_session), # 注入数据库会话
|
||
) -> dict:
|
||
"""设置默认规格
|
||
|
||
用途:将指定产品的某个规格设为默认规格,用于报价计算时的默认取值。
|
||
请求参数:product_id - 产品 ID(路径参数)。
|
||
返回值:设置结果。
|
||
权限要求:无特殊权限限制(未配置角色鉴权)。
|
||
"""
|
||
return success_payload(product_service.set_default_specification(product_id, session))
|
||
|
||
|
||
@router.get("/api/products/{product_id}")
|
||
def get_product(
|
||
product_id: int, # 产品 ID(路径参数)
|
||
product_service: ProductService = Depends(get_product_service), # 注入产品服务
|
||
session: Session = Depends(get_db_session), # 注入数据库会话
|
||
) -> dict:
|
||
"""查询产品详情
|
||
|
||
用途:根据产品 ID 获取单个产品的完整信息(含规格、分类等)。
|
||
请求参数:product_id - 产品 ID(路径参数)。
|
||
返回值:产品详情信息。
|
||
权限要求:无特殊权限限制(未配置角色鉴权)。
|
||
"""
|
||
return success_payload(product_service.get_product(product_id, session))
|