安全:补齐业务批次归属校验
This commit is contained in:
@@ -18,7 +18,7 @@ from module_business.dao.master_dao import MasterDao
|
||||
from module_business.dao.operation_dao import OperationDao
|
||||
from module_business.domain.enums import PalletEventType, PalletFlowState
|
||||
from module_business.domain.pallet_state_machine import PalletStateMachine
|
||||
from module_business.domain.test_batch_scope import TestBatchScope
|
||||
from module_business.domain.test_batch_scope import TestBatchScope, assert_record_in_scope
|
||||
from module_business.entity.do.operation_do import BizPalletEvent, BizUsageRecord
|
||||
from module_business.entity.vo.master_vo import LinePageQueryModel
|
||||
from module_business.entity.vo.operation_vo import (
|
||||
@@ -165,6 +165,7 @@ class UsageService:
|
||||
cls._raise_usage_not_accessible(current_user)
|
||||
if site is None:
|
||||
raise ServiceException(message='客户现场不存在')
|
||||
assert_record_in_scope(site, test_scope, '现场')
|
||||
|
||||
@classmethod
|
||||
async def _recover_integrity_error(
|
||||
@@ -189,6 +190,7 @@ class UsageService:
|
||||
)
|
||||
if recovered is None:
|
||||
raise ServiceException(message='使用失败,数据冲突')
|
||||
assert_record_in_scope(recovered, test_scope, '使用记录')
|
||||
if recovered.site_id != expected_site_id or not cls._is_exact_idempotent_result(
|
||||
recovered, page_object, request_hash
|
||||
):
|
||||
@@ -255,6 +257,7 @@ class UsageService:
|
||||
)
|
||||
if usage is None:
|
||||
cls._raise_usage_not_accessible(current_user)
|
||||
assert_record_in_scope(usage, test_scope, '使用记录')
|
||||
return UsageModel.model_validate(usage)
|
||||
|
||||
@classmethod
|
||||
@@ -270,6 +273,7 @@ class UsageService:
|
||||
site = await MasterDao.get_site(query_db, site_id, test_scope)
|
||||
if site is None:
|
||||
raise ServiceException(message='客户现场不存在')
|
||||
assert_record_in_scope(site, test_scope, '现场')
|
||||
if site.status != '0':
|
||||
raise ServiceException(message='客户现场已停用')
|
||||
lines = await MasterDao.list_line(
|
||||
@@ -301,9 +305,11 @@ class UsageService:
|
||||
pallet = await InventoryDao.get_pallet_by_qr_token(query_db, normalized_qr, test_scope)
|
||||
if pallet is None:
|
||||
cls._raise_pallet_not_accessible(current_user)
|
||||
assert_record_in_scope(pallet, test_scope, '托盘')
|
||||
inventory = await MasterDao.get_pallet_inventory(query_db, pallet.pallet_id, test_scope)
|
||||
if inventory is None:
|
||||
cls._raise_pallet_not_accessible(current_user, '托盘库存不存在')
|
||||
assert_record_in_scope(inventory, test_scope, '库存')
|
||||
if inventory.site_id is None:
|
||||
cls._raise_pallet_not_accessible(current_user, '托盘不在客户现场')
|
||||
await cls._assert_pallet_site_access(query_db, current_user, inventory.site_id)
|
||||
@@ -328,6 +334,7 @@ class UsageService:
|
||||
filling = await OperationDao.get_filling_by_id(query_db, inventory.active_filling_id, test_scope)
|
||||
if filling is None:
|
||||
raise ServiceException(message='托盘活动装填周期不存在')
|
||||
assert_record_in_scope(filling, test_scope, '活动装填')
|
||||
if (
|
||||
filling.filling_id != inventory.active_filling_id
|
||||
or filling.pallet_id != pallet.pallet_id
|
||||
@@ -369,6 +376,8 @@ class UsageService:
|
||||
preflight_site_ids = await cls._site_scope(query_db, current_user)
|
||||
# 产线归属是请求内稳定路由;锁事务仍以库存中的实际现场复核。
|
||||
preflight_line = await MasterDao.get_line(query_db, page_object.line_id, test_scope)
|
||||
if preflight_line is not None:
|
||||
assert_record_in_scope(preflight_line, test_scope, '产线')
|
||||
preflight_site_id = preflight_line.site_id if preflight_line is not None else None
|
||||
existing = None
|
||||
if preflight_site_id is not None and (
|
||||
@@ -381,6 +390,7 @@ class UsageService:
|
||||
site_ids=[preflight_site_id],
|
||||
)
|
||||
if existing is not None:
|
||||
assert_record_in_scope(existing, test_scope, '使用记录')
|
||||
if not cls._is_exact_idempotent_result(existing, page_object, request_hash):
|
||||
raise ServiceException(message='使用失败,幂等键已被其他请求使用')
|
||||
if preflight_site_ids is not None and existing.site_id not in preflight_site_ids:
|
||||
@@ -402,6 +412,7 @@ class UsageService:
|
||||
)
|
||||
if scanned_pallet is None:
|
||||
cls._raise_pallet_not_accessible(current_user)
|
||||
assert_record_in_scope(scanned_pallet, test_scope, '托盘')
|
||||
scanned_pallet_id = int(scanned_pallet.pallet_id)
|
||||
await query_db.rollback()
|
||||
await TestBatchAccessService.lock_active_batch(query_db, test_scope)
|
||||
@@ -413,6 +424,7 @@ class UsageService:
|
||||
)
|
||||
if inventory is None:
|
||||
cls._raise_pallet_not_accessible(current_user, '托盘库存不存在')
|
||||
assert_record_in_scope(inventory, test_scope, '库存')
|
||||
if inventory.site_id is None:
|
||||
cls._raise_pallet_not_accessible(current_user, '托盘不在客户现场')
|
||||
expected_site_id = inventory.site_id
|
||||
@@ -429,6 +441,7 @@ class UsageService:
|
||||
if len(locked_pallets) != 1 or locked_pallets[0].pallet_id != inventory.pallet_id:
|
||||
cls._raise_pallet_not_accessible(current_user)
|
||||
pallet = locked_pallets[0]
|
||||
assert_record_in_scope(pallet, test_scope, '托盘')
|
||||
|
||||
filling = (
|
||||
await OperationDao.get_active_filling_for_update(
|
||||
@@ -446,6 +459,7 @@ class UsageService:
|
||||
site_ids=[inventory.site_id],
|
||||
)
|
||||
if locked_existing is not None:
|
||||
assert_record_in_scope(locked_existing, test_scope, '使用记录')
|
||||
if locked_existing.site_id != inventory.site_id or not cls._is_exact_idempotent_result(
|
||||
locked_existing,
|
||||
page_object,
|
||||
@@ -466,6 +480,7 @@ class UsageService:
|
||||
raise ServiceException(message='托盘不存在活动装填周期')
|
||||
if filling is None:
|
||||
raise ServiceException(message='托盘活动装填周期不存在或已关闭')
|
||||
assert_record_in_scope(filling, test_scope, '活动装填')
|
||||
|
||||
site = await MasterDao.get_site(query_db, inventory.site_id, test_scope, for_update=True)
|
||||
await cls._assert_pallet_site_access(
|
||||
@@ -476,11 +491,13 @@ class UsageService:
|
||||
)
|
||||
if site is None:
|
||||
raise ServiceException(message='客户现场不存在')
|
||||
assert_record_in_scope(site, test_scope, '现场')
|
||||
if site.status != '0':
|
||||
raise ServiceException(message='客户现场已停用')
|
||||
line = await MasterDao.get_line(query_db, page_object.line_id, test_scope, for_update=True)
|
||||
if line is None:
|
||||
raise ServiceException(message='产线不存在')
|
||||
assert_record_in_scope(line, test_scope, '产线')
|
||||
if line.status != '0':
|
||||
raise ServiceException(message='产线已停用')
|
||||
if line.site_id != inventory.site_id:
|
||||
@@ -540,6 +557,7 @@ class UsageService:
|
||||
test_batch_id=test_scope.batch_id,
|
||||
)
|
||||
usage = await OperationDao.add_usage_record(query_db, usage)
|
||||
assert_record_in_scope(usage, test_scope, '使用记录')
|
||||
usage_id = usage.usage_id
|
||||
result = cls._success(usage)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user