115 lines
2.6 KiB
Python
115 lines
2.6 KiB
Python
import re
|
|
|
|
from pydantic import BaseModel, Field, field_validator
|
|
|
|
ZONGPAI_PATTERN = re.compile(r"^(\d{2}(B|C|T)\d+|\d{2}(BW|CW)\d{4})$")
|
|
|
|
|
|
class BoxItemDetail(BaseModel):
|
|
"""箱号下某个总排号的明细"""
|
|
box_item_id: int | None = None
|
|
zongpai_no: str
|
|
work_order_no: str | None = None
|
|
quantity: int
|
|
total_quantity: int | None = None
|
|
|
|
|
|
class CurrentZongpaiBox(BaseModel):
|
|
"""当前总排号已经分配的箱号明细"""
|
|
box_item_id: int
|
|
box_no: int
|
|
quantity: int
|
|
|
|
|
|
class BoxDetail(BaseModel):
|
|
"""一个箱号的完整信息"""
|
|
box_no: int
|
|
items: list[BoxItemDetail]
|
|
|
|
|
|
class BoxInfoResponse(BaseModel):
|
|
"""GET /box/info 响应"""
|
|
zongpai_no: str
|
|
paichan_no: str
|
|
work_order_no: str | None = None
|
|
quantity: int
|
|
current_zongpai_boxes: list[CurrentZongpaiBox] = Field(default_factory=list)
|
|
existing_boxes: list[BoxDetail]
|
|
max_box_no: int
|
|
suggested_box_no: int
|
|
|
|
|
|
class BoxSaveRequest(BaseModel):
|
|
"""POST /box 请求"""
|
|
zongpai_no: str
|
|
box_no: int
|
|
quantity: int
|
|
|
|
@field_validator("zongpai_no")
|
|
@classmethod
|
|
def validate_zongpai_no(cls, v: str) -> str:
|
|
v = v.strip().upper()
|
|
if not ZONGPAI_PATTERN.match(v):
|
|
raise ValueError("INVALID_ZONGPAI")
|
|
return v
|
|
|
|
@field_validator("box_no")
|
|
@classmethod
|
|
def validate_box_no(cls, v: int) -> int:
|
|
if v <= 0:
|
|
raise ValueError("INVALID_BOX_NO")
|
|
return v
|
|
|
|
@field_validator("quantity")
|
|
@classmethod
|
|
def validate_quantity(cls, v: int) -> int:
|
|
if v <= 0:
|
|
raise ValueError("INVALID_QUANTITY")
|
|
return v
|
|
|
|
|
|
class BoxSaveResponse(BaseModel):
|
|
"""POST /box 响应"""
|
|
box_item_id: int
|
|
paichan_no: str
|
|
box_no: int
|
|
zongpai_no: str
|
|
quantity: int
|
|
created_at: str
|
|
|
|
|
|
class BoxUpdateRequest(BaseModel):
|
|
"""PATCH /box/{box_item_id} 请求"""
|
|
box_no: int
|
|
quantity: int
|
|
|
|
@field_validator("box_no")
|
|
@classmethod
|
|
def validate_box_no(cls, v: int) -> int:
|
|
if v <= 0:
|
|
raise ValueError("INVALID_BOX_NO")
|
|
return v
|
|
|
|
@field_validator("quantity")
|
|
@classmethod
|
|
def validate_quantity(cls, v: int) -> int:
|
|
if v <= 0:
|
|
raise ValueError("INVALID_QUANTITY")
|
|
return v
|
|
|
|
|
|
class BoxUpdateResponse(BaseModel):
|
|
"""PATCH /box/{box_item_id} 响应"""
|
|
box_item_id: int
|
|
paichan_no: str
|
|
box_no: int
|
|
zongpai_no: str
|
|
quantity: int
|
|
updated_at: str
|
|
|
|
|
|
class BoxDeleteResponse(BaseModel):
|
|
"""DELETE /box/{box_item_id} 响应"""
|
|
box_item_id: int
|
|
deleted: bool
|