feat(box): include work order numbers in box info
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user