feat(box): simplify boxing mode API
This commit is contained in:
@@ -23,13 +23,6 @@ class DuplicateBoxItemError(Exception):
|
||||
self.box_no = box_no
|
||||
|
||||
|
||||
class DuplicateZongpaiBindError(Exception):
|
||||
def __init__(self, paichan_no: str, box_no: int, zongpai_no: str):
|
||||
self.paichan_no = paichan_no
|
||||
self.box_no = box_no
|
||||
self.zongpai_no = zongpai_no
|
||||
|
||||
|
||||
class BoxItemNotFoundError(Exception):
|
||||
pass
|
||||
|
||||
@@ -38,6 +31,10 @@ class InvalidBoxItemError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidQuantityError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def query_erp_info(db: Session, zongpai_no: str) -> dict:
|
||||
"""从 ERP 视图查询总排号对应的排产号、工令号和数量。"""
|
||||
sql = text(_erp_info_sql(db))
|
||||
@@ -172,24 +169,48 @@ def get_box_info(db: Session, zongpai_no: str) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _packed_quantity_for_zongpai(
|
||||
db: Session,
|
||||
paichan_no: str,
|
||||
zongpai_no: str,
|
||||
exclude_box_item_id: int | None = None,
|
||||
) -> int:
|
||||
query = (
|
||||
db.query(FinishedGoodsBoxItem)
|
||||
.join(FinishedGoodsBox, FinishedGoodsBoxItem.box_id == FinishedGoodsBox.id)
|
||||
.filter(
|
||||
FinishedGoodsBox.paichan_no == paichan_no,
|
||||
FinishedGoodsBoxItem.zongpai_no == zongpai_no,
|
||||
)
|
||||
)
|
||||
if exclude_box_item_id is not None:
|
||||
query = query.filter(FinishedGoodsBoxItem.id != exclude_box_item_id)
|
||||
return sum(int(item.quantity or 0) for item in query.all())
|
||||
|
||||
|
||||
def _ensure_quantity_within_erp_total(
|
||||
db: Session,
|
||||
paichan_no: str,
|
||||
zongpai_no: str,
|
||||
erp_quantity: int,
|
||||
submitted_quantity: int,
|
||||
exclude_box_item_id: int | None = None,
|
||||
) -> None:
|
||||
packed_quantity = _packed_quantity_for_zongpai(
|
||||
db,
|
||||
paichan_no,
|
||||
zongpai_no,
|
||||
exclude_box_item_id=exclude_box_item_id,
|
||||
)
|
||||
if packed_quantity + submitted_quantity > erp_quantity:
|
||||
raise InvalidQuantityError()
|
||||
|
||||
|
||||
def save_box_record(db: Session, req: BoxSaveRequest) -> dict:
|
||||
"""保存装箱记录。箱已存在时仅追加明细(多码一箱场景)。"""
|
||||
"""保存装箱记录。同箱可凑箱,但同箱同总排不可重复。"""
|
||||
erp = query_erp_info(db, req.zongpai_no)
|
||||
paichan_no = erp["paichan_no"]
|
||||
|
||||
if req.box_mode == "one-to-one":
|
||||
existing_box_no = (
|
||||
db.query(FinishedGoodsBox.box_no)
|
||||
.join(FinishedGoodsBoxItem, FinishedGoodsBox.id == FinishedGoodsBoxItem.box_id)
|
||||
.filter(
|
||||
FinishedGoodsBox.paichan_no == paichan_no,
|
||||
FinishedGoodsBoxItem.zongpai_no == req.zongpai_no,
|
||||
)
|
||||
.scalar()
|
||||
)
|
||||
if existing_box_no is not None:
|
||||
raise DuplicateZongpaiBindError(paichan_no, existing_box_no, req.zongpai_no)
|
||||
|
||||
box = (
|
||||
db.query(FinishedGoodsBox)
|
||||
.filter(
|
||||
@@ -200,8 +221,6 @@ def save_box_record(db: Session, req: BoxSaveRequest) -> dict:
|
||||
)
|
||||
|
||||
if box:
|
||||
if req.box_mode in ("one-to-one", "one-to-many"):
|
||||
raise DuplicateBoxItemError(paichan_no, req.box_no)
|
||||
existing_item = (
|
||||
db.query(FinishedGoodsBoxItem)
|
||||
.filter(
|
||||
@@ -212,7 +231,16 @@ def save_box_record(db: Session, req: BoxSaveRequest) -> dict:
|
||||
)
|
||||
if existing_item:
|
||||
raise DuplicateBoxItemError(paichan_no, req.box_no)
|
||||
else:
|
||||
|
||||
_ensure_quantity_within_erp_total(
|
||||
db,
|
||||
paichan_no,
|
||||
req.zongpai_no,
|
||||
erp["quantity"],
|
||||
req.quantity,
|
||||
)
|
||||
|
||||
if box is None:
|
||||
box = FinishedGoodsBox(
|
||||
paichan_no=paichan_no,
|
||||
box_no=req.box_no,
|
||||
@@ -240,7 +268,7 @@ def save_box_record(db: Session, req: BoxSaveRequest) -> dict:
|
||||
|
||||
|
||||
def update_box_item(db: Session, box_item_id: int, req: BoxUpdateRequest) -> dict:
|
||||
"""更新一码多箱已分配明细的箱号和数量。"""
|
||||
"""更新已分配明细的箱号和数量。"""
|
||||
item = (
|
||||
db.query(FinishedGoodsBoxItem)
|
||||
.filter(FinishedGoodsBoxItem.id == box_item_id)
|
||||
@@ -267,13 +295,32 @@ def update_box_item(db: Session, box_item_id: int, req: BoxUpdateRequest) -> dic
|
||||
.first()
|
||||
)
|
||||
|
||||
if target_box is not None and target_box.id != current_box.id:
|
||||
raise DuplicateBoxItemError(paichan_no, req.box_no)
|
||||
|
||||
if target_box is None:
|
||||
target_box = FinishedGoodsBox(paichan_no=paichan_no, box_no=req.box_no)
|
||||
db.add(target_box)
|
||||
db.flush()
|
||||
else:
|
||||
duplicate_item = (
|
||||
db.query(FinishedGoodsBoxItem)
|
||||
.filter(
|
||||
FinishedGoodsBoxItem.box_id == target_box.id,
|
||||
FinishedGoodsBoxItem.zongpai_no == item.zongpai_no,
|
||||
FinishedGoodsBoxItem.id != item.id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if duplicate_item is not None:
|
||||
raise DuplicateBoxItemError(paichan_no, req.box_no)
|
||||
|
||||
erp = query_erp_info(db, item.zongpai_no)
|
||||
_ensure_quantity_within_erp_total(
|
||||
db,
|
||||
paichan_no,
|
||||
item.zongpai_no,
|
||||
erp["quantity"],
|
||||
req.quantity,
|
||||
exclude_box_item_id=box_item_id,
|
||||
)
|
||||
|
||||
old_box_id = item.box_id
|
||||
item.box_id = target_box.id
|
||||
|
||||
Reference in New Issue
Block a user