feat(box): include work order numbers in box info

This commit is contained in:
Misaka_Company
2026-05-13 09:48:08 +08:00
parent 25982b12bf
commit 7fe1fe7ef5
3 changed files with 51 additions and 7 deletions

View File

@@ -8,6 +8,7 @@ ZONGPAI_PATTERN = re.compile(r"^(\d{2}(B|C|T)\d+|\d{2}(BW|CW)\d{4})$")
class BoxItemDetail(BaseModel): class BoxItemDetail(BaseModel):
"""箱号下某个总排号的明细""" """箱号下某个总排号的明细"""
zongpai_no: str zongpai_no: str
work_order_no: str | None = None
quantity: int quantity: int
@@ -21,6 +22,7 @@ class BoxInfoResponse(BaseModel):
"""GET /box/info 响应""" """GET /box/info 响应"""
zongpai_no: str zongpai_no: str
paichan_no: str paichan_no: str
work_order_no: str | None = None
quantity: int quantity: int
existing_boxes: list[BoxDetail] existing_boxes: list[BoxDetail]
max_box_no: int max_box_no: int

View File

@@ -1,6 +1,6 @@
import re import re
from sqlalchemy import text from sqlalchemy import bindparam, text
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.models.finished_goods import FinishedGoodsBox, FinishedGoodsBoxItem from app.models.finished_goods import FinishedGoodsBox, FinishedGoodsBoxItem
@@ -31,7 +31,7 @@ class DuplicateZongpaiBindError(Exception):
def query_erp_info(db: Session, zongpai_no: str) -> dict: def query_erp_info(db: Session, zongpai_no: str) -> dict:
"""从 ERP 视图查询总排号对应的排产号和数量。""" """从 ERP 视图查询总排号对应的排产号、工令号和数量。"""
sql = text(_erp_info_sql(db)) sql = text(_erp_info_sql(db))
row = db.execute(sql, {"zongpai_no": zongpai_no}).fetchone() row = db.execute(sql, {"zongpai_no": zongpai_no}).fetchone()
if not row: if not row:
@@ -40,6 +40,7 @@ def query_erp_info(db: Session, zongpai_no: str) -> dict:
"zongpai_no": row[0], "zongpai_no": row[0],
"paichan_no": row[1], "paichan_no": row[1],
"quantity": int(row[2]), "quantity": int(row[2]),
"work_order_no": row[3],
} }
@@ -47,18 +48,43 @@ def _erp_info_sql(db: Session) -> str:
dialect_name = db.bind.dialect.name if db.bind is not None else "" dialect_name = db.bind.dialect.name if db.bind is not None else ""
if dialect_name == "postgresql": if dialect_name == "postgresql":
return ( return (
'SELECT "总排号", "排产号", "数量" ' 'SELECT "总排号", "排产号", "数量", "工令号" '
'FROM "ERPAuto"."vw_productionContractData" ' 'FROM "ERPAuto"."vw_productionContractData" '
'WHERE "总排号" = :zongpai_no ' 'WHERE "总排号" = :zongpai_no '
"LIMIT 1" "LIMIT 1"
) )
return ( return (
"SELECT TOP 1 [总排号], [排产号], [数量] " "SELECT TOP 1 [总排号], [排产号], [数量], [工令号] "
"FROM [ERPAuto].[vw_productionContractData] " "FROM [ERPAuto].[vw_productionContractData] "
"WHERE [总排号] = :zongpai_no" "WHERE [总排号] = :zongpai_no"
) )
def query_erp_work_order_map(db: Session, zongpai_nos: list[str]) -> dict[str, str | None]:
"""批量查询总排号对应的工令号。"""
if not zongpai_nos:
return {}
dialect_name = db.bind.dialect.name if db.bind is not None else ""
if dialect_name == "postgresql":
sql = text(
'SELECT "总排号", "工令号" '
'FROM "ERPAuto"."vw_productionContractData" '
'WHERE "总排号" IN :zongpai_nos'
)
else:
sql = text(
"SELECT [总排号], [工令号] "
"FROM [ERPAuto].[vw_productionContractData] "
"WHERE [总排号] IN :zongpai_nos"
)
rows = db.execute(
sql.bindparams(bindparam("zongpai_nos", expanding=True)),
{"zongpai_nos": sorted(set(zongpai_nos))},
).fetchall()
return {row[0]: row[1] for row in rows}
def get_box_info(db: Session, zongpai_no: str) -> dict: def get_box_info(db: Session, zongpai_no: str) -> dict:
"""获取装箱信息:排产号、数量、已有箱号明细。""" """获取装箱信息:排产号、数量、已有箱号明细。"""
zongpai_no = zongpai_no.strip().upper() zongpai_no = zongpai_no.strip().upper()
@@ -75,18 +101,31 @@ def get_box_info(db: Session, zongpai_no: str) -> dict:
.all() .all()
) )
existing_boxes = [] box_items = {}
max_box_no = 0 item_zongpai_nos = []
for box in boxes: for box in boxes:
items = ( items = (
db.query(FinishedGoodsBoxItem) db.query(FinishedGoodsBoxItem)
.filter(FinishedGoodsBoxItem.box_id == box.id) .filter(FinishedGoodsBoxItem.box_id == box.id)
.all() .all()
) )
box_items[box.id] = items
item_zongpai_nos.extend(item.zongpai_no for item in items)
work_order_map = query_erp_work_order_map(db, item_zongpai_nos)
existing_boxes = []
max_box_no = 0
for box in boxes:
items = box_items[box.id]
existing_boxes.append({ existing_boxes.append({
"box_no": box.box_no, "box_no": box.box_no,
"items": [ "items": [
{"zongpai_no": item.zongpai_no, "quantity": int(item.quantity or 0)} {
"zongpai_no": item.zongpai_no,
"work_order_no": work_order_map.get(item.zongpai_no),
"quantity": int(item.quantity or 0),
}
for item in items for item in items
], ],
}) })
@@ -96,6 +135,7 @@ def get_box_info(db: Session, zongpai_no: str) -> dict:
return { return {
"zongpai_no": zongpai_no, "zongpai_no": zongpai_no,
"paichan_no": paichan_no, "paichan_no": paichan_no,
"work_order_no": erp["work_order_no"],
"quantity": quantity, "quantity": quantity,
"existing_boxes": existing_boxes, "existing_boxes": existing_boxes,
"max_box_no": max_box_no, "max_box_no": max_box_no,

View File

@@ -13,6 +13,8 @@ def test_box_info_success(client: TestClient):
data = resp.json() data = resp.json()
assert data["zongpai_no"] == "26BW0011" assert data["zongpai_no"] == "26BW0011"
assert data["paichan_no"] == "W00009" assert data["paichan_no"] == "W00009"
assert "work_order_no" in data
assert data["work_order_no"] is None or isinstance(data["work_order_no"], str)
assert data["quantity"] == 80 assert data["quantity"] == 80
assert "existing_boxes" in data assert "existing_boxes" in data
assert "max_box_no" in data assert "max_box_no" in data