功能:实现多托盘发货出库

This commit is contained in:
焦龙言
2026-07-26 19:11:52 +08:00
parent 66890ca63c
commit 7317631a13
8 changed files with 2867 additions and 25 deletions
@@ -69,6 +69,22 @@ class OperationDao:
scoped_warehouse_ids = sorted(set(warehouse_ids))
return [BizFillingRecord.warehouse_id.in_(scoped_warehouse_ids) if scoped_warehouse_ids else false()]
@staticmethod
def _shipment_scope_conditions(
warehouse_ids: list[int] | None,
site_ids: list[int] | None,
) -> list[ColumnElement[bool]]:
conditions = []
if warehouse_ids is not None:
scoped_warehouse_ids = sorted(set(warehouse_ids))
conditions.append(
BizShipmentOrder.source_warehouse_id.in_(scoped_warehouse_ids) if scoped_warehouse_ids else false()
)
if site_ids is not None:
scoped_site_ids = sorted(set(site_ids))
conditions.append(BizShipmentOrder.target_site_id.in_(scoped_site_ids) if scoped_site_ids else false())
return conditions
@staticmethod
async def _paginate(
db: AsyncSession,
@@ -243,13 +259,32 @@ class OperationDao:
cls,
db: AsyncSession,
shipment_id: int,
warehouse_ids: list[int] | None = None,
site_ids: list[int] | None = None,
) -> BizShipmentOrder | None:
return await cls._get_for_update(
shipment = await cls._get_for_update(
db,
BizShipmentOrder,
BizShipmentOrder.shipment_id,
shipment_id,
*cls._shipment_scope_conditions(warehouse_ids, site_ids),
)
if shipment is None:
return None
# 父单锁定后读取当前明细,避免 MySQL RR 沿用确认前的快照。
item_result = await db.execute(
select(BizShipmentItem)
.where(BizShipmentItem.shipment_id == shipment_id)
.order_by(BizShipmentItem.pallet_id, BizShipmentItem.shipment_item_id)
.with_for_update()
.execution_options(populate_existing=True)
)
shipment.items = sorted(
item_result.scalars().all(),
key=lambda item: (item.pallet_id, item.shipment_item_id),
)
return shipment
@classmethod
async def get_return_for_update(
@@ -297,12 +332,15 @@ class OperationDao:
cls,
db: AsyncSession,
idempotency_key: str,
warehouse_ids: list[int] | None = None,
site_ids: list[int] | None = None,
) -> BizShipmentOrder | None:
return await cls._get_by_key(
db,
BizShipmentOrder,
BizShipmentOrder.confirm_idempotency_key,
idempotency_key,
*cls._shipment_scope_conditions(warehouse_ids, site_ids),
)
@classmethod
@@ -520,8 +558,10 @@ class OperationDao:
db: AsyncSession,
query_object: ShipmentPageQueryModel,
is_page: bool = True,
warehouse_ids: list[int] | None = None,
site_ids: list[int] | None = None,
) -> PageModel | list[dict[str, Any]]:
conditions = []
conditions = cls._shipment_scope_conditions(warehouse_ids, site_ids)
if query_object.shipment_no:
conditions.append(BizShipmentOrder.shipment_no.like(f'%{query_object.shipment_no}%'))
if query_object.source_warehouse_id:
@@ -545,6 +585,8 @@ class OperationDao:
cls,
db: AsyncSession,
shipment_id: int,
warehouse_ids: list[int] | None = None,
site_ids: list[int] | None = None,
) -> BizShipmentOrder | None:
return await cls._get_order_detail(
db,
@@ -554,6 +596,7 @@ class OperationDao:
BizShipmentItem,
BizShipmentItem.shipment_id,
BizShipmentItem.shipment_item_id,
*cls._shipment_scope_conditions(warehouse_ids, site_ids),
)
@classmethod