163 lines
8.0 KiB
Python
163 lines
8.0 KiB
Python
"""CRM 产品模块 Pydantic Schemas"""
|
||
|
||
from decimal import Decimal
|
||
from typing import List, Optional
|
||
|
||
from pydantic import AliasChoices, BaseModel, ConfigDict, Field
|
||
|
||
|
||
# ── 产品分类 Schemas ──────────────────────────────────────────
|
||
|
||
|
||
class ProductCategoryCreateBody(BaseModel):
|
||
"""产品分类新增请求体"""
|
||
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
category_name: str = Field(..., alias="categoryName", description="分类名称")
|
||
parent_id: str = Field(default="0", alias="parentId", description="父级分类ID,0为顶级")
|
||
category_code: Optional[str] = Field(default=None, alias="categoryCode", description="分类编码")
|
||
level: int = Field(default=1, description="层级")
|
||
status: str = Field(default="1", description="状态 1启用 0停用")
|
||
order_num: Optional[int] = Field(default=None, alias="orderNum", description="排序号")
|
||
remark: Optional[str] = Field(default=None, description="备注")
|
||
|
||
|
||
class ProductCategoryUpdateBody(BaseModel):
|
||
"""产品分类更新请求体"""
|
||
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
id: str = Field(..., description="分类ID")
|
||
category_name: Optional[str] = Field(default=None, alias="categoryName", description="分类名称")
|
||
parent_id: Optional[str] = Field(default=None, alias="parentId", description="父级分类ID")
|
||
category_code: Optional[str] = Field(default=None, alias="categoryCode", description="分类编码")
|
||
level: Optional[int] = Field(default=None, description="层级")
|
||
status: Optional[str] = Field(default=None, description="状态")
|
||
order_num: Optional[int] = Field(default=None, alias="orderNum", description="排序号")
|
||
remark: Optional[str] = Field(default=None, description="备注")
|
||
|
||
|
||
class CategoryDeleteBody(BaseModel):
|
||
"""分类删除请求体"""
|
||
|
||
id: str = Field(..., description="分类ID")
|
||
|
||
|
||
class ProductCategoryTreeBody(BaseModel):
|
||
"""产品分类树查询(密文解密后须用 Pydantic 绑定,裸 dict=None 在部分链路下会丢 body)"""
|
||
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
category_name: Optional[str] = Field(default=None, alias="categoryName", description="分类名称(模糊)")
|
||
status: Optional[str] = Field(default=None, description="状态")
|
||
|
||
|
||
class ProductUpdateStatusBody(BaseModel):
|
||
"""产品批量上下架请求体"""
|
||
|
||
ids: List[str] = Field(..., description="产品ID列表")
|
||
status: str = Field(..., description="目标状态:on=上架 off=下架")
|
||
|
||
|
||
# ── 产品 Schemas ──────────────────────────────────────────────
|
||
|
||
|
||
class ProductListBody(BaseModel):
|
||
"""产品列表查询请求体(分页)"""
|
||
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
page: int = Field(default=1, ge=1, description="页码")
|
||
pageSize: int = Field(default=10, ge=1, le=100, description="每页条数")
|
||
keyword: Optional[str] = Field(default=None, description="搜索关键词(产品名称/编号)")
|
||
category_id: Optional[str] = Field(default=None, alias="categoryId", description="分类ID")
|
||
status: Optional[str] = Field(default=None, description="状态")
|
||
|
||
|
||
class ProductCreateBody(BaseModel):
|
||
"""产品新增请求体"""
|
||
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
product_no: Optional[str] = Field(default=None, alias="productNo", description="产品编号(不传则自动生成,格式 SXWL000001)")
|
||
product_name: str = Field(..., alias="productName", description="产品名称")
|
||
category_id: Optional[str] = Field(default=None, alias="categoryId", description="分类ID")
|
||
category_name: Optional[str] = Field(default=None, alias="categoryName", description="分类名称")
|
||
model: Optional[str] = Field(default=None, description="规格型号")
|
||
unit: Optional[str] = Field(default=None, description="单位(产品模块不维护,留空)")
|
||
barcode: Optional[str] = Field(default=None, description="条码(不传则自动生成)")
|
||
price: Optional[Decimal] = Field(default=None, description="标准单价(产品模块不维护,留空)")
|
||
cost_price: Optional[Decimal] = Field(
|
||
default=None,
|
||
validation_alias=AliasChoices("costPrice", "cost"),
|
||
serialization_alias="costPrice",
|
||
description="成本价",
|
||
)
|
||
stock: int = Field(default=0, description="库存数量")
|
||
low_stock: int = Field(default=10, alias="lowStock", description="库存预警值")
|
||
tax_rate: Decimal = Field(default=Decimal("13.00"), alias="taxRate", description="税率(%)")
|
||
is_toxic: int = Field(default=0, alias="isToxic", description="是否易制毒 0-否 1-是")
|
||
is_explosive: int = Field(default=0, alias="isExplosive", description="是否易制爆 0-否 1-是")
|
||
status: str = Field(default="on", description="状态 on=上架 off=下架")
|
||
description: Optional[str] = Field(default=None, description="产品描述")
|
||
images: Optional[str] = Field(default=None, description="产品图片(逗号分隔 URL)")
|
||
sale_count: int = Field(default=0, alias="saleCount", description="销售次数")
|
||
order_num: Optional[int] = Field(default=None, alias="orderNum", description="排序号")
|
||
remark: Optional[str] = Field(default=None, description="备注")
|
||
|
||
|
||
class ProductUpdateBody(BaseModel):
|
||
"""产品更新请求体"""
|
||
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
id: str = Field(..., description="产品ID")
|
||
product_no: Optional[str] = Field(default=None, alias="productNo", description="产品编号")
|
||
product_name: Optional[str] = Field(default=None, alias="productName", description="产品名称")
|
||
category_id: Optional[str] = Field(default=None, alias="categoryId", description="分类ID")
|
||
category_name: Optional[str] = Field(default=None, alias="categoryName", description="分类名称")
|
||
model: Optional[str] = Field(default=None, description="规格型号")
|
||
unit: Optional[str] = Field(default=None, description="单位")
|
||
barcode: Optional[str] = Field(default=None, description="条码")
|
||
price: Optional[Decimal] = Field(default=None, description="标准单价")
|
||
cost_price: Optional[Decimal] = Field(
|
||
default=None,
|
||
validation_alias=AliasChoices("costPrice", "cost"),
|
||
serialization_alias="costPrice",
|
||
description="成本价",
|
||
)
|
||
stock: Optional[int] = Field(default=None, description="库存数量")
|
||
low_stock: Optional[int] = Field(default=None, alias="lowStock", description="库存预警值")
|
||
tax_rate: Optional[Decimal] = Field(default=None, alias="taxRate", description="税率(%)")
|
||
is_toxic: Optional[int] = Field(default=None, alias="isToxic", description="是否易制毒")
|
||
is_explosive: Optional[int] = Field(default=None, alias="isExplosive", description="是否易制爆")
|
||
status: Optional[str] = Field(default=None, description="状态")
|
||
description: Optional[str] = Field(default=None, description="产品描述")
|
||
images: Optional[str] = Field(default=None, description="产品图片(逗号分隔 URL)")
|
||
sale_count: Optional[int] = Field(default=None, alias="saleCount", description="销售次数")
|
||
order_num: Optional[int] = Field(default=None, alias="orderNum", description="排序号")
|
||
remark: Optional[str] = Field(default=None, description="备注")
|
||
|
||
|
||
class ProductDetailBody(BaseModel):
|
||
"""产品详情请求体(不分页)"""
|
||
|
||
id: str = Field(..., description="产品ID")
|
||
|
||
|
||
class ProductDeleteBody(BaseModel):
|
||
"""产品删除请求体"""
|
||
|
||
id: Optional[str] = Field(default=None, description="产品ID(单条删除)")
|
||
ids: Optional[List[str]] = Field(default=None, description="产品ID列表(批量删除)")
|
||
|
||
|
||
class ProductOptionsBody(BaseModel):
|
||
"""产品下拉选项请求体(不分页,返回全量)"""
|
||
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
keyword: Optional[str] = Field(default=None, description="搜索关键词")
|
||
category_id: Optional[str] = Field(default=None, alias="categoryId", description="分类ID")
|