101 lines
3.8 KiB
Python
101 lines
3.8 KiB
Python
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
|
|
|
|
class CellProductCreate(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
|
|
product_code: str = Field(..., alias="productCode")
|
|
product_name: str = Field(..., alias="productName")
|
|
product_type_id: Optional[str] = Field(None, alias="productTypeId")
|
|
spec_id: Optional[str] = Field(None, alias="specId")
|
|
batch_no: Optional[str] = Field(None, alias="batchNo")
|
|
storage_slot_id: Optional[str] = Field(None, alias="storageSlotId")
|
|
passage: Optional[str] = None
|
|
freeze_date: Optional[datetime] = Field(None, alias="freezeDate")
|
|
expected_cell_count: Optional[float] = Field(None, alias="expectedCellCount")
|
|
viability: Optional[float] = None
|
|
product_status: Optional[str] = Field("frozen", alias="productStatus")
|
|
source_type: Optional[str] = Field("manual", alias="sourceType")
|
|
quantity: Optional[float] = None
|
|
unit: Optional[str] = None
|
|
expiry_date: Optional[datetime] = Field(None, alias="expiryDate")
|
|
product_images: Optional[str] = Field(None, alias="productImages")
|
|
remark: Optional[str] = None
|
|
|
|
@field_validator("viability")
|
|
@classmethod
|
|
def validate_viability(cls, v):
|
|
if v is not None and (v < 0 or v > 100):
|
|
raise ValueError("活性必须在 0~100 之间")
|
|
return v
|
|
|
|
@field_validator("passage")
|
|
@classmethod
|
|
def validate_passage(cls, v):
|
|
if v is not None:
|
|
valid = {f"P{i}" for i in range(1, 9)}
|
|
if v.upper() not in valid:
|
|
raise ValueError("代次必须为 P1~P8")
|
|
return v.upper()
|
|
return v
|
|
|
|
|
|
class CellProductUpdate(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
|
|
product_name: Optional[str] = Field(None, alias="productName")
|
|
product_type_id: Optional[str] = Field(None, alias="productTypeId")
|
|
spec_id: Optional[str] = Field(None, alias="specId")
|
|
batch_no: Optional[str] = Field(None, alias="batchNo")
|
|
storage_slot_id: Optional[str] = Field(None, alias="storageSlotId")
|
|
passage: Optional[str] = None
|
|
freeze_date: Optional[datetime] = Field(None, alias="freezeDate")
|
|
expected_cell_count: Optional[float] = Field(None, alias="expectedCellCount")
|
|
viability: Optional[float] = None
|
|
product_status: Optional[str] = Field(None, alias="productStatus")
|
|
quantity: Optional[float] = None
|
|
unit: Optional[str] = None
|
|
expiry_date: Optional[datetime] = Field(None, alias="expiryDate")
|
|
product_images: Optional[str] = Field(None, alias="productImages")
|
|
remark: Optional[str] = None
|
|
|
|
@field_validator("viability")
|
|
@classmethod
|
|
def validate_viability(cls, v):
|
|
if v is not None and (v < 0 or v > 100):
|
|
raise ValueError("活性必须在 0~100 之间")
|
|
return v
|
|
|
|
@field_validator("passage")
|
|
@classmethod
|
|
def validate_passage(cls, v):
|
|
if v is not None:
|
|
valid = {f"P{i}" for i in range(1, 9)}
|
|
if v.upper() not in valid:
|
|
raise ValueError("代次必须为 P1~P8")
|
|
return v.upper()
|
|
return v
|
|
|
|
@field_validator("product_status")
|
|
@classmethod
|
|
def validate_status(cls, v):
|
|
if v is not None and v not in ("frozen", "sold", "used"):
|
|
raise ValueError("状态必须为 frozen/sold/used")
|
|
return v
|
|
|
|
|
|
class CellProductListQuery(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
|
|
page: int = 1
|
|
page_size: int = Field(20, alias="pageSize")
|
|
keyword: Optional[str] = None
|
|
product_code: Optional[str] = Field(None, alias="productCode")
|
|
product_name: Optional[str] = Field(None, alias="productName")
|
|
product_type_id: Optional[str] = Field(None, alias="productTypeId")
|
|
product_status: Optional[str] = Field(None, alias="productStatus")
|
|
passage: Optional[str] = None
|