Files
ShiErFeng/shierfeng-fastapi-backend/module_business/service/shipment_label_service.py
T

91 lines
4.6 KiB
Python

import base64
from sqlalchemy.ext.asyncio import AsyncSession
from exceptions.exception import ServiceException
from module_admin.entity.vo.user_vo import CurrentUserModel
from module_business.dao.master_dao import MasterDao
from module_business.dao.operation_dao import OperationDao
from module_business.dao.shipment_label_dao import ShipmentLabelDao
from module_business.domain.enums import DocumentStatus
from module_business.domain.test_batch_scope import TestBatchScope, assert_record_in_scope
from module_business.entity.vo.shipment_label_vo import ShipmentLabelModel
from module_business.service.pallet_service import PalletService
from module_business.service.shipment_service import ShipmentService
class ShipmentLabelService:
"""复用发货双数据范围读取原始物料资料,不改变托盘、批号或库存。"""
@staticmethod
async def get_labels_services(
query_db: AsyncSession,
shipment_id: int,
current_user: CurrentUserModel,
test_scope: TestBatchScope,
) -> list[ShipmentLabelModel]:
warehouse_ids, site_ids = await ShipmentService._scopes(query_db, current_user)
shipment = await OperationDao.get_shipment_by_id(
query_db, shipment_id, test_scope, warehouse_ids=warehouse_ids, site_ids=site_ids,
)
if shipment is None:
ShipmentService._raise_shipment_not_accessible(current_user)
assert_record_in_scope(shipment, test_scope, '发货单')
if shipment.status not in (DocumentStatus.DRAFT.value, DocumentStatus.CONFIRMED.value):
raise ServiceException(message='当前发货单状态不支持打印标签')
if not shipment.items:
raise ServiceException(message='发货单没有可打印的托盘')
for item in shipment.items:
assert_record_in_scope(item, test_scope, '发货明细')
# 先授权单据,再读取其目标现场与所属客户,避免通过标签枚举跨范围资料。
site = await MasterDao.get_site(query_db, shipment.target_site_id, test_scope)
assert_record_in_scope(site, test_scope, '发货现场')
customer = await MasterDao.get_customer(query_db, site.customer_id, test_scope)
assert_record_in_scope(customer, test_scope, '发货客户')
rows = await ShipmentLabelDao.get_label_sources(query_db, shipment, test_scope)
if (
len(rows) != len(shipment.items)
or {row[0].shipment_item_id for row in rows} != {item.shipment_item_id for item in shipment.items}
):
raise ServiceException(message='发货明细已变化,请刷新后重新打印')
draft = shipment.status == DocumentStatus.DRAFT.value
# 整单全部验证后才生成任何二维码,缺少关联资料时不得输出部分标签。
for item, pallet, filling, quantity in rows:
for record, name in ((item, '发货明细'), (pallet, '托盘'), (filling, '装填记录')):
assert_record_in_scope(record, test_scope, name)
if (
item.shipment_id != shipment.shipment_id
or item.pallet_id != pallet.pallet_id
or filling.pallet_id != pallet.pallet_id
or type(quantity) is not int
or quantity <= 0
or not pallet.qr_token
):
raise ServiceException(message='发货标签资料不完整,请核对托盘与装填记录')
if draft:
if pallet.asset_status != '0' or filling.active_slot != 'ACTIVE' or quantity > pallet.capacity_packages:
raise ServiceException(message='草稿托盘已不满足发货条件,请刷新后重新打印')
elif item.active_filling_id != filling.filling_id or quantity != item.package_qty:
raise ServiceException(message='发货快照不完整,无法打印标签')
return [
ShipmentLabelModel(
shipment_no=shipment.shipment_no,
shipment_status=shipment.status,
pallet_code=pallet.pallet_code,
customer_name=customer.customer_name,
site_name=site.site_name,
strain_name=filling.strain_name_snapshot,
batch_no=filling.batch_no,
production_date=filling.production_date,
expiry_date=filling.expiry_date,
package_qty=quantity,
qr_code_data_url='data:image/png;base64,' + base64.b64encode(
PalletService.render_qr_png(pallet.qr_token),
).decode('ascii'),
)
for item, pallet, filling, quantity in rows
]