from sqlalchemy import and_, select from sqlalchemy.ext.asyncio import AsyncSession from module_business.domain.enums import DocumentStatus, PalletFlowState from module_business.domain.test_batch_scope import TestBatchScope, batch_scope_condition from module_business.entity.do.master_do import BizPallet from module_business.entity.do.operation_do import ( BizFillingRecord, BizPalletInventory, BizShipmentItem, BizShipmentOrder, ) class ShipmentLabelDao: """只读标签资料;外连接保留失效明细,由服务拒绝不完整的整单打印。""" @staticmethod async def get_label_sources( db: AsyncSession, shipment: BizShipmentOrder, scope: TestBatchScope, ) -> list[tuple[BizShipmentItem, BizPallet | None, BizFillingRecord | None, int | None]]: draft = shipment.status == DocumentStatus.DRAFT.value quantity = BizPalletInventory.remaining_packages if draft else BizShipmentItem.package_qty statement = ( select(BizShipmentItem, BizPallet, BizFillingRecord, quantity) .select_from(BizShipmentItem) .outerjoin(BizPallet, and_( BizShipmentItem.pallet_id == BizPallet.pallet_id, batch_scope_condition(BizPallet.test_batch_id, scope), )) ) if draft: statement = statement.outerjoin(BizPalletInventory, and_( BizShipmentItem.pallet_id == BizPalletInventory.pallet_id, BizPalletInventory.warehouse_id == shipment.source_warehouse_id, BizPalletInventory.flow_state == PalletFlowState.FILLED_IN_WAREHOUSE.value, BizPalletInventory.site_id.is_(None), BizPalletInventory.current_line_id.is_(None), BizPalletInventory.active_filling_id.is_not(None), BizPalletInventory.remaining_packages > 0, batch_scope_condition(BizPalletInventory.test_batch_id, scope), )) # 已确认单只关联确认时的装填记录,即使周期已关闭、托盘已重新装填也可补打。 filling_id = BizPalletInventory.active_filling_id if draft else BizShipmentItem.active_filling_id filling_conditions = [ filling_id == BizFillingRecord.filling_id, BizShipmentItem.pallet_id == BizFillingRecord.pallet_id, batch_scope_condition(BizFillingRecord.test_batch_id, scope), ] if draft: filling_conditions.append(BizFillingRecord.active_slot == 'ACTIVE') statement = ( statement.outerjoin(BizFillingRecord, and_(*filling_conditions)) .where( BizShipmentItem.shipment_id == shipment.shipment_id, batch_scope_condition(BizShipmentItem.test_batch_id, scope), ) .order_by(BizShipmentItem.shipment_item_id) ) return list((await db.execute(statement)).all())