功能:隔离五类测试业务链路
This commit is contained in:
@@ -22,7 +22,7 @@ from common.vo import (
|
||||
PageResponseModel,
|
||||
ResponseBaseModel,
|
||||
)
|
||||
from exceptions.exception import PermissionException, ServiceException
|
||||
from exceptions.exception import PermissionException, ServiceException, ServiceWarning
|
||||
from module_admin.entity.vo.user_vo import CurrentUserModel, UserInfoModel
|
||||
from module_admin.service.log_service import LogQueueService
|
||||
from module_admin.service.login_service import LoginService
|
||||
@@ -33,6 +33,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.entity.do.master_do import BizPallet
|
||||
from module_business.entity.do.operation_do import (
|
||||
BizInboundItem,
|
||||
@@ -129,6 +130,20 @@ def make_inbound(
|
||||
|
||||
|
||||
class TestInboundPublicContract(unittest.TestCase):
|
||||
def test_public_business_methods_require_explicit_test_scope(self) -> None:
|
||||
for method_name in (
|
||||
'get_inbound_list_services',
|
||||
'inbound_detail_services',
|
||||
'get_warehouse_options_services',
|
||||
'scan_inbound_pallet_services',
|
||||
'add_inbound_services',
|
||||
'edit_inbound_services',
|
||||
'delete_inbound_services',
|
||||
'confirm_inbound_services',
|
||||
):
|
||||
with self.subTest(method=method_name):
|
||||
self.assertIn('test_scope', inspect.signature(getattr(InboundService, method_name)).parameters)
|
||||
|
||||
def test_service_and_controller_are_available(self) -> None:
|
||||
self.assertIsNotNone(InboundService)
|
||||
self.assertIsNotNone(inbound_controller_module.inbound_controller)
|
||||
@@ -136,7 +151,7 @@ class TestInboundPublicContract(unittest.TestCase):
|
||||
def test_confirm_signature_and_types_are_exact(self) -> None:
|
||||
signature = inspect.signature(InboundService.confirm_inbound_services)
|
||||
self.assertEqual(
|
||||
('query_db', 'inbound_id', 'page_object', 'current_user'),
|
||||
('query_db', 'inbound_id', 'page_object', 'current_user', 'test_scope'),
|
||||
tuple(signature.parameters),
|
||||
)
|
||||
hints = get_type_hints(InboundService.confirm_inbound_services)
|
||||
@@ -228,7 +243,7 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(inbound_service_module, 'datetime') as service_datetime,
|
||||
):
|
||||
service_datetime.now.return_value = self.fixed_time
|
||||
result = await InboundService.add_inbound_services(self.db, page, self.user)
|
||||
result = await InboundService.add_inbound_services(self.db, page, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual(
|
||||
[
|
||||
@@ -242,8 +257,8 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
],
|
||||
actions,
|
||||
)
|
||||
inventory_lock.assert_awaited_once_with(self.db, [2, 5])
|
||||
pallet_lock.assert_awaited_once_with(self.db, [2, 5])
|
||||
inventory_lock.assert_awaited_once_with(self.db, [2, 5], TestBatchScope.formal())
|
||||
pallet_lock.assert_awaited_once_with(self.db, [2, 5], TestBatchScope.formal())
|
||||
token_hex.assert_called_once_with(16)
|
||||
order = captured['order']
|
||||
self.assertEqual('IN-fixed-random', order.inbound_no)
|
||||
@@ -288,7 +303,7 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'add_event', new=add_event),
|
||||
self.assertRaises(ServiceException),
|
||||
):
|
||||
await InboundService.add_inbound_services(self.db, page, self.user)
|
||||
await InboundService.add_inbound_services(self.db, page, self.user, TestBatchScope.formal())
|
||||
|
||||
add_order.assert_not_awaited()
|
||||
replace_items.assert_not_awaited()
|
||||
@@ -313,7 +328,7 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'get_inventories_for_update', new=lock),
|
||||
self.assertRaises(exception_type),
|
||||
):
|
||||
await InboundService.add_inbound_services(self.db, page, self.user)
|
||||
await InboundService.add_inbound_services(self.db, page, self.user, TestBatchScope.formal())
|
||||
lock.assert_not_awaited()
|
||||
self.db.rollback.assert_awaited_once()
|
||||
|
||||
@@ -333,7 +348,7 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'get_inventories_for_update', new=lock),
|
||||
self.assertRaises(PermissionException),
|
||||
):
|
||||
await InboundService.add_inbound_services(self.db, page, self.user)
|
||||
await InboundService.add_inbound_services(self.db, page, self.user, TestBatchScope.formal())
|
||||
lock.assert_not_awaited()
|
||||
self.db.rollback.assert_awaited_once()
|
||||
|
||||
@@ -351,7 +366,7 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'get_inventories_for_update', new=pallet_lock),
|
||||
self.assertRaises(Exception) as raised,
|
||||
):
|
||||
await InboundService.add_inbound_services(self.db, page, self.user)
|
||||
await InboundService.add_inbound_services(self.db, page, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertIsInstance(raised.exception, PermissionException)
|
||||
self.assertEqual('无权访问该仓库', raised.exception.message)
|
||||
@@ -385,11 +400,11 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'replace_inbound_items', new=replace_items),
|
||||
self.assertRaises(PermissionException) as raised,
|
||||
):
|
||||
await InboundService.add_inbound_services(self.db, page, self.user)
|
||||
await InboundService.add_inbound_services(self.db, page, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual('无权访问该仓库', raised.exception.message)
|
||||
self.assertEqual(2, warehouse_read.await_count)
|
||||
warehouse_read.assert_awaited_with(self.db, 7, for_update=True)
|
||||
warehouse_read.assert_awaited_with(self.db, 7, TestBatchScope.formal(), for_update=True)
|
||||
self.assertEqual(2, warehouse_mapping.await_count)
|
||||
warehouse_mapping.assert_awaited_with(self.db, self.user, 7, for_update=True)
|
||||
add_order.assert_not_awaited()
|
||||
@@ -427,12 +442,13 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(inbound_service_module, 'datetime') as service_datetime,
|
||||
):
|
||||
service_datetime.now.return_value = self.fixed_time
|
||||
result = await InboundService.edit_inbound_services(self.db, page, self.user)
|
||||
result = await InboundService.edit_inbound_services(self.db, page, self.user, TestBatchScope.formal())
|
||||
|
||||
self.default_scope.assert_awaited_once_with(self.db, 7)
|
||||
lock_order.assert_awaited_once_with(
|
||||
self.db,
|
||||
11,
|
||||
TestBatchScope.formal(),
|
||||
warehouse_ids=[2, 5, 7, 8, 11],
|
||||
)
|
||||
self.assertEqual(
|
||||
@@ -443,8 +459,8 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
],
|
||||
access.await_args_list,
|
||||
)
|
||||
inventory_lock.assert_awaited_once_with(self.db, [2, 5])
|
||||
pallet_lock.assert_awaited_once_with(self.db, [2, 5])
|
||||
inventory_lock.assert_awaited_once_with(self.db, [2, 5], TestBatchScope.formal())
|
||||
pallet_lock.assert_awaited_once_with(self.db, [2, 5], TestBatchScope.formal())
|
||||
self.assertEqual(8, inbound.warehouse_id)
|
||||
self.assertEqual('user-7', inbound.update_by)
|
||||
self.assertEqual(self.fixed_time, inbound.update_time)
|
||||
@@ -478,7 +494,7 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
MasterDao,
|
||||
'get_warehouse',
|
||||
new=AsyncMock(
|
||||
side_effect=lambda _db, warehouse_id, **_kwargs: SimpleNamespace(
|
||||
side_effect=lambda _db, warehouse_id, _scope, **_kwargs: SimpleNamespace(
|
||||
warehouse_id=warehouse_id,
|
||||
status='0',
|
||||
)
|
||||
@@ -493,7 +509,7 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'replace_inbound_items', new=replace),
|
||||
self.assertRaises(PermissionException) as raised,
|
||||
):
|
||||
await InboundService.edit_inbound_services(self.db, page, self.user)
|
||||
await InboundService.edit_inbound_services(self.db, page, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual('无权访问该入库单', raised.exception.message)
|
||||
warehouse_mapping.assert_any_await(self.db, self.user, 7, for_update=True)
|
||||
@@ -519,7 +535,7 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'update_inbound', new=update),
|
||||
self.assertRaises(ServiceException),
|
||||
):
|
||||
await InboundService.edit_inbound_services(self.db, page, self.user)
|
||||
await InboundService.edit_inbound_services(self.db, page, self.user, TestBatchScope.formal())
|
||||
|
||||
lock_pallets.assert_not_awaited()
|
||||
update.assert_not_awaited()
|
||||
@@ -537,12 +553,12 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'get_inventories_for_update', new=inventory_lock),
|
||||
self.assertRaises(Exception) as raised,
|
||||
):
|
||||
await InboundService.edit_inbound_services(self.db, page, self.user)
|
||||
await InboundService.edit_inbound_services(self.db, page, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertIsInstance(raised.exception, PermissionException)
|
||||
self.assertEqual('无权访问该入库单', raised.exception.message)
|
||||
scope.assert_awaited_once_with(self.db, 7)
|
||||
lock_order.assert_awaited_once_with(self.db, 404, warehouse_ids=[7])
|
||||
lock_order.assert_awaited_once_with(self.db, 404, TestBatchScope.formal(), warehouse_ids=[7])
|
||||
get_warehouse.assert_not_awaited()
|
||||
inventory_lock.assert_not_awaited()
|
||||
self.db.rollback.assert_awaited_once()
|
||||
@@ -556,130 +572,54 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'get_inbound_for_update', new=lock_order),
|
||||
self.assertRaises(ServiceException) as raised,
|
||||
):
|
||||
await InboundService.edit_inbound_services(self.db, page, make_user(1))
|
||||
await InboundService.edit_inbound_services(self.db, page, make_user(1), TestBatchScope.formal())
|
||||
|
||||
self.assertEqual('入库单不存在', raised.exception.message)
|
||||
scope.assert_not_awaited()
|
||||
lock_order.assert_awaited_once_with(self.db, 404, warehouse_ids=None)
|
||||
lock_order.assert_awaited_once_with(self.db, 404, TestBatchScope.formal(), warehouse_ids=None)
|
||||
self.db.rollback.assert_awaited_once()
|
||||
|
||||
async def test_batch_delete_locks_and_preflights_all_before_ordered_delete(self) -> None:
|
||||
actions: list[str] = []
|
||||
|
||||
async def lock(
|
||||
_db: AsyncSession,
|
||||
inbound_id: int,
|
||||
warehouse_ids: list[int] | None = None,
|
||||
) -> BizInboundOrder:
|
||||
self.assertEqual([2, 5, 7, 8, 11], warehouse_ids)
|
||||
actions.append(f'lock-{inbound_id}')
|
||||
return make_inbound(inbound_id=inbound_id, warehouse_id=inbound_id)
|
||||
|
||||
async def delete(_db: AsyncSession, inbound_id: int) -> None:
|
||||
actions.append(f'delete-{inbound_id}')
|
||||
|
||||
async def commit() -> None:
|
||||
actions.append('commit')
|
||||
|
||||
self.db.commit.side_effect = commit
|
||||
access = AsyncMock()
|
||||
lock = AsyncMock()
|
||||
delete = AsyncMock()
|
||||
with (
|
||||
patch.object(OperationDao, 'get_inbound_for_update', new=AsyncMock(side_effect=lock)),
|
||||
patch.object(
|
||||
MasterDao,
|
||||
'get_warehouse',
|
||||
new=AsyncMock(
|
||||
side_effect=lambda _db, warehouse_id, **_kwargs: SimpleNamespace(
|
||||
warehouse_id=warehouse_id,
|
||||
status='0',
|
||||
)
|
||||
),
|
||||
),
|
||||
patch.object(AccessService, 'assert_warehouse_access', new=access),
|
||||
patch.object(OperationDao, 'delete_inbound', new=AsyncMock(side_effect=delete)),
|
||||
patch.object(OperationDao, 'get_inbound_for_update', new=lock),
|
||||
patch.object(OperationDao, 'delete_inbound', new=delete),
|
||||
self.assertRaises(ServiceWarning),
|
||||
):
|
||||
result = await InboundService.delete_inbound_services(self.db, [5, 2], self.user)
|
||||
await InboundService.delete_inbound_services(self.db, [5, 2], self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual(
|
||||
['lock-2', 'lock-5', 'delete-2', 'delete-5', 'commit'],
|
||||
actions,
|
||||
)
|
||||
self.default_scope.assert_awaited_once_with(self.db, 7)
|
||||
self.assertEqual([2, 5], [call.args[2] for call in access.await_args_list])
|
||||
self.assertTrue(all(call.kwargs.get('for_update') for call in access.await_args_list))
|
||||
self.assertTrue(result.is_success)
|
||||
self.db.rollback.assert_not_awaited()
|
||||
lock.assert_not_awaited()
|
||||
delete.assert_not_awaited()
|
||||
self.db.commit.assert_not_awaited()
|
||||
|
||||
async def test_batch_delete_rechecks_all_current_warehouses_before_first_delete(self) -> None:
|
||||
revoked_warehouse_id = 8
|
||||
documents = {
|
||||
11: make_inbound(inbound_id=11, warehouse_id=revoked_warehouse_id),
|
||||
12: make_inbound(inbound_id=12, warehouse_id=7),
|
||||
}
|
||||
|
||||
async def warehouse_access(
|
||||
_db: AsyncSession,
|
||||
_user: CurrentUserModel,
|
||||
warehouse_id: int,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
if warehouse_id == revoked_warehouse_id and kwargs.get('for_update'):
|
||||
raise PermissionException(data='', message='无权访问该仓库')
|
||||
|
||||
lock = AsyncMock()
|
||||
delete = AsyncMock()
|
||||
warehouse_mapping = AsyncMock(side_effect=warehouse_access)
|
||||
with (
|
||||
patch.object(
|
||||
OperationDao,
|
||||
'get_inbound_for_update',
|
||||
new=AsyncMock(side_effect=lambda _db, inbound_id, **_kwargs: documents[inbound_id]),
|
||||
),
|
||||
patch.object(
|
||||
MasterDao,
|
||||
'get_warehouse',
|
||||
new=AsyncMock(
|
||||
side_effect=lambda _db, warehouse_id, **_kwargs: SimpleNamespace(
|
||||
warehouse_id=warehouse_id,
|
||||
status='0',
|
||||
)
|
||||
),
|
||||
),
|
||||
patch.object(AccessService, 'assert_warehouse_access', new=warehouse_mapping),
|
||||
patch.object(OperationDao, 'get_inbound_for_update', new=lock),
|
||||
patch.object(OperationDao, 'delete_inbound', new=delete),
|
||||
self.assertRaises(PermissionException) as raised,
|
||||
self.assertRaises(ServiceWarning),
|
||||
):
|
||||
await InboundService.delete_inbound_services(self.db, [12, 11], self.user)
|
||||
await InboundService.delete_inbound_services(self.db, [12, 11], self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual('无权访问该入库单', raised.exception.message)
|
||||
self.assertEqual([7, 8], [call.args[2] for call in warehouse_mapping.await_args_list])
|
||||
self.assertTrue(all(call.kwargs.get('for_update') for call in warehouse_mapping.await_args_list))
|
||||
lock.assert_not_awaited()
|
||||
delete.assert_not_awaited()
|
||||
self.db.commit.assert_not_awaited()
|
||||
self.db.rollback.assert_awaited_once()
|
||||
|
||||
async def test_batch_delete_is_atomic_when_later_document_is_confirmed(self) -> None:
|
||||
lock = AsyncMock()
|
||||
delete = AsyncMock()
|
||||
records = {
|
||||
2: make_inbound(inbound_id=2, warehouse_id=2),
|
||||
5: make_inbound(inbound_id=5, warehouse_id=5, status='CONFIRMED'),
|
||||
}
|
||||
with (
|
||||
patch.object(
|
||||
OperationDao,
|
||||
'get_inbound_for_update',
|
||||
new=AsyncMock(
|
||||
side_effect=lambda _db, inbound_id, warehouse_ids=None: records[inbound_id],
|
||||
),
|
||||
),
|
||||
patch.object(AccessService, 'assert_warehouse_access', new=AsyncMock()),
|
||||
patch.object(OperationDao, 'get_inbound_for_update', new=lock),
|
||||
patch.object(OperationDao, 'delete_inbound', new=delete),
|
||||
self.assertRaises(ServiceException),
|
||||
self.assertRaises(ServiceWarning),
|
||||
):
|
||||
await InboundService.delete_inbound_services(self.db, [5, 2], self.user)
|
||||
await InboundService.delete_inbound_services(self.db, [5, 2], self.user, TestBatchScope.formal())
|
||||
|
||||
lock.assert_not_awaited()
|
||||
delete.assert_not_awaited()
|
||||
self.db.commit.assert_not_awaited()
|
||||
self.db.rollback.assert_awaited_once()
|
||||
|
||||
async def test_delete_scopes_parent_lock_and_hides_unmatched_document(self) -> None:
|
||||
lock_order = AsyncMock(return_value=None)
|
||||
@@ -688,16 +628,13 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(AccessDao, 'list_user_warehouse_ids', new=AsyncMock(return_value=[7])) as scope,
|
||||
patch.object(OperationDao, 'get_inbound_for_update', new=lock_order),
|
||||
patch.object(OperationDao, 'delete_inbound', new=delete),
|
||||
self.assertRaises(Exception) as raised,
|
||||
self.assertRaises(ServiceWarning),
|
||||
):
|
||||
await InboundService.delete_inbound_services(self.db, [404], self.user)
|
||||
await InboundService.delete_inbound_services(self.db, [404], self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertIsInstance(raised.exception, PermissionException)
|
||||
self.assertEqual('无权访问该入库单', raised.exception.message)
|
||||
scope.assert_awaited_once_with(self.db, 7)
|
||||
lock_order.assert_awaited_once_with(self.db, 404, warehouse_ids=[7])
|
||||
scope.assert_not_awaited()
|
||||
lock_order.assert_not_awaited()
|
||||
delete.assert_not_awaited()
|
||||
self.db.rollback.assert_awaited_once()
|
||||
|
||||
async def test_admin_missing_delete_keeps_precise_not_found(self) -> None:
|
||||
scope = AsyncMock()
|
||||
@@ -705,14 +642,12 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
with (
|
||||
patch.object(AccessDao, 'list_user_warehouse_ids', new=scope),
|
||||
patch.object(OperationDao, 'get_inbound_for_update', new=lock_order),
|
||||
self.assertRaises(ServiceException) as raised,
|
||||
self.assertRaises(ServiceWarning),
|
||||
):
|
||||
await InboundService.delete_inbound_services(self.db, [404], make_user(1))
|
||||
await InboundService.delete_inbound_services(self.db, [404], make_user(1), TestBatchScope.formal())
|
||||
|
||||
self.assertEqual('入库单不存在', raised.exception.message)
|
||||
scope.assert_not_awaited()
|
||||
lock_order.assert_awaited_once_with(self.db, 404, warehouse_ids=None)
|
||||
self.db.rollback.assert_awaited_once()
|
||||
lock_order.assert_not_awaited()
|
||||
|
||||
async def test_all_draft_mutations_convert_integrity_errors(self) -> None:
|
||||
add_page = InboundCreateModel(warehouseId=7, palletIds=[2])
|
||||
@@ -732,7 +667,7 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'add_inbound', new=AsyncMock(side_effect=integrity_error())),
|
||||
self.assertRaises(ServiceException),
|
||||
):
|
||||
await InboundService.add_inbound_services(self.db, add_page, self.user)
|
||||
await InboundService.add_inbound_services(self.db, add_page, self.user, TestBatchScope.formal())
|
||||
self.db.rollback.assert_awaited_once()
|
||||
|
||||
self.db.reset_mock()
|
||||
@@ -749,10 +684,9 @@ class TestInboundDraftService(unittest.IsolatedAsyncioTestCase):
|
||||
),
|
||||
patch.object(AccessService, 'assert_warehouse_access', new=AsyncMock()),
|
||||
patch.object(OperationDao, 'delete_inbound', new=AsyncMock(side_effect=integrity_error())),
|
||||
self.assertRaises(ServiceException),
|
||||
self.assertRaises(ServiceWarning),
|
||||
):
|
||||
await InboundService.delete_inbound_services(self.db, [11], self.user)
|
||||
self.db.rollback.assert_awaited_once()
|
||||
await InboundService.delete_inbound_services(self.db, [11], self.user, TestBatchScope.formal())
|
||||
|
||||
|
||||
class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
@@ -774,10 +708,18 @@ class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(AccessDao, 'list_user_warehouse_ids', new=AsyncMock(return_value=[7, 3, 7])) as scope,
|
||||
patch.object(OperationDao, 'get_inbound_list', new=get_list),
|
||||
):
|
||||
actual = await InboundService.get_inbound_list_services(self.db, query, self.user, is_page=True)
|
||||
actual = await InboundService.get_inbound_list_services(
|
||||
self.db, query, self.user, TestBatchScope.formal(), is_page=True
|
||||
)
|
||||
|
||||
scope.assert_awaited_once_with(self.db, 7)
|
||||
get_list.assert_awaited_once_with(self.db, query, True, warehouse_ids=[3, 7])
|
||||
get_list.assert_awaited_once_with(
|
||||
self.db,
|
||||
query,
|
||||
warehouse_ids=[3, 7],
|
||||
scope=TestBatchScope.formal(),
|
||||
is_page=True,
|
||||
)
|
||||
self.assertIsInstance(actual, PageModel)
|
||||
self.assertIsInstance(actual.rows[0], InboundModel)
|
||||
|
||||
@@ -790,10 +732,18 @@ class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(AccessDao, 'list_user_warehouse_ids', new=scope),
|
||||
patch.object(OperationDao, 'get_inbound_list', new=get_list),
|
||||
):
|
||||
await InboundService.get_inbound_list_services(self.db, query, make_user(1), is_page=True)
|
||||
await InboundService.get_inbound_list_services(
|
||||
self.db, query, make_user(1), TestBatchScope.formal(), is_page=True
|
||||
)
|
||||
|
||||
scope.assert_not_awaited()
|
||||
get_list.assert_awaited_once_with(self.db, query, True, warehouse_ids=None)
|
||||
get_list.assert_awaited_once_with(
|
||||
self.db,
|
||||
query,
|
||||
warehouse_ids=None,
|
||||
scope=TestBatchScope.formal(),
|
||||
is_page=True,
|
||||
)
|
||||
|
||||
async def test_explicit_unauthorized_warehouse_is_403_before_query(self) -> None:
|
||||
query = InboundPageQueryModel(warehouseId=9)
|
||||
@@ -803,7 +753,9 @@ class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'get_inbound_list', new=get_list),
|
||||
self.assertRaises(PermissionException),
|
||||
):
|
||||
await InboundService.get_inbound_list_services(self.db, query, self.user, is_page=True)
|
||||
await InboundService.get_inbound_list_services(
|
||||
self.db, query, self.user, TestBatchScope.formal(), is_page=True
|
||||
)
|
||||
get_list.assert_not_awaited()
|
||||
|
||||
async def test_user_without_scope_gets_empty_paginated_result_without_total_leak(self) -> None:
|
||||
@@ -814,9 +766,17 @@ class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(AccessDao, 'list_user_warehouse_ids', new=AsyncMock(return_value=[])),
|
||||
patch.object(OperationDao, 'get_inbound_list', new=get_list),
|
||||
):
|
||||
actual = await InboundService.get_inbound_list_services(self.db, query, self.user, is_page=True)
|
||||
actual = await InboundService.get_inbound_list_services(
|
||||
self.db, query, self.user, TestBatchScope.formal(), is_page=True
|
||||
)
|
||||
|
||||
get_list.assert_awaited_once_with(self.db, query, True, warehouse_ids=[])
|
||||
get_list.assert_awaited_once_with(
|
||||
self.db,
|
||||
query,
|
||||
warehouse_ids=[],
|
||||
scope=TestBatchScope.formal(),
|
||||
is_page=True,
|
||||
)
|
||||
self.assertEqual([], actual.rows)
|
||||
self.assertEqual(0, actual.total)
|
||||
self.assertFalse(actual.has_next)
|
||||
@@ -834,10 +794,10 @@ class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'get_inbound_by_id', new=get_detail),
|
||||
patch.object(AccessService, 'assert_warehouse_access', new=access),
|
||||
):
|
||||
actual = await InboundService.inbound_detail_services(self.db, 11, self.user)
|
||||
actual = await InboundService.inbound_detail_services(self.db, 11, self.user, TestBatchScope.formal())
|
||||
|
||||
scope.assert_awaited_once_with(self.db, 7)
|
||||
get_detail.assert_awaited_once_with(self.db, 11, warehouse_ids=[3, 7])
|
||||
get_detail.assert_awaited_once_with(self.db, 11, TestBatchScope.formal(), warehouse_ids=[3, 7])
|
||||
access.assert_not_awaited()
|
||||
self.assertIsInstance(actual, InboundModel)
|
||||
|
||||
@@ -848,11 +808,11 @@ class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'get_inbound_by_id', new=get_detail),
|
||||
self.assertRaises(Exception) as raised,
|
||||
):
|
||||
await InboundService.inbound_detail_services(self.db, 404, self.user)
|
||||
await InboundService.inbound_detail_services(self.db, 404, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertIsInstance(raised.exception, PermissionException)
|
||||
self.assertEqual('无权访问该入库单', raised.exception.message)
|
||||
get_detail.assert_awaited_once_with(self.db, 404, warehouse_ids=[7])
|
||||
get_detail.assert_awaited_once_with(self.db, 404, TestBatchScope.formal(), warehouse_ids=[7])
|
||||
|
||||
async def test_admin_missing_detail_keeps_precise_not_found(self) -> None:
|
||||
scope = AsyncMock()
|
||||
@@ -862,11 +822,11 @@ class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'get_inbound_by_id', new=get_detail),
|
||||
self.assertRaises(ServiceException) as raised,
|
||||
):
|
||||
await InboundService.inbound_detail_services(self.db, 404, make_user(1))
|
||||
await InboundService.inbound_detail_services(self.db, 404, make_user(1), TestBatchScope.formal())
|
||||
|
||||
self.assertEqual('入库单不存在', raised.exception.message)
|
||||
scope.assert_not_awaited()
|
||||
get_detail.assert_awaited_once_with(self.db, 404, warehouse_ids=None)
|
||||
get_detail.assert_awaited_once_with(self.db, 404, TestBatchScope.formal(), warehouse_ids=None)
|
||||
|
||||
async def test_warehouse_options_filter_disabled_and_unauthorized_records(self) -> None:
|
||||
warehouses = [
|
||||
@@ -878,11 +838,12 @@ class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(MasterDao, 'list_warehouse', new=AsyncMock(return_value=warehouses)) as list_warehouse,
|
||||
patch.object(AccessDao, 'list_user_warehouse_ids', new=AsyncMock(return_value=[2, 3])),
|
||||
):
|
||||
actual = await InboundService.get_warehouse_options_services(self.db, self.user)
|
||||
actual = await InboundService.get_warehouse_options_services(self.db, self.user, TestBatchScope.formal())
|
||||
|
||||
query = list_warehouse.await_args.args[1]
|
||||
self.assertEqual('0', query.status)
|
||||
self.assertIs(False, list_warehouse.await_args.args[2])
|
||||
self.assertEqual(TestBatchScope.formal(), list_warehouse.await_args.args[2])
|
||||
self.assertIs(False, list_warehouse.await_args.args[3])
|
||||
self.assertEqual([BusinessOptionModel(id=2, code='W2', name='二仓')], actual)
|
||||
self.assertEqual({'id', 'code', 'name'}, set(BusinessOptionModel.model_fields))
|
||||
|
||||
@@ -896,7 +857,7 @@ class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(MasterDao, 'list_warehouse', new=AsyncMock(return_value=warehouses)),
|
||||
patch.object(AccessDao, 'list_user_warehouse_ids', new=scope),
|
||||
):
|
||||
actual = await InboundService.get_warehouse_options_services(self.db, make_user(1))
|
||||
actual = await InboundService.get_warehouse_options_services(self.db, make_user(1), TestBatchScope.formal())
|
||||
|
||||
scope.assert_not_awaited()
|
||||
self.assertEqual([2, 5], [option.id for option in actual])
|
||||
@@ -914,7 +875,7 @@ class TestInboundReadService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(MasterDao, 'list_warehouse', new=AsyncMock(return_value=warehouses)),
|
||||
patch.object(AccessDao, 'list_user_warehouse_ids', new=AsyncMock(return_value=[2])),
|
||||
):
|
||||
actual = await InboundService.get_warehouse_options_services(self.db, self.user)
|
||||
actual = await InboundService.get_warehouse_options_services(self.db, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual([BusinessOptionModel(id=2, code='W2', name='二仓')], actual)
|
||||
|
||||
@@ -945,11 +906,12 @@ class TestInboundScanService(unittest.IsolatedAsyncioTestCase):
|
||||
'persisted-token',
|
||||
self.query,
|
||||
self.user,
|
||||
TestBatchScope.formal(),
|
||||
)
|
||||
|
||||
access.assert_awaited_once_with(self.db, self.user, 7)
|
||||
get_pallet.assert_awaited_once_with(self.db, 'persisted-token')
|
||||
get_inventory.assert_awaited_once_with(self.db, 2)
|
||||
get_pallet.assert_awaited_once_with(self.db, 'persisted-token', TestBatchScope.formal())
|
||||
get_inventory.assert_awaited_once_with(self.db, 2, TestBatchScope.formal())
|
||||
locking_read.assert_not_awaited()
|
||||
add_event.assert_not_awaited()
|
||||
self.db.commit.assert_not_awaited()
|
||||
@@ -987,6 +949,7 @@ class TestInboundScanService(unittest.IsolatedAsyncioTestCase):
|
||||
'persisted-token',
|
||||
self.query,
|
||||
self.user,
|
||||
TestBatchScope.formal(),
|
||||
)
|
||||
|
||||
async def test_scan_rejects_unauthorized_disabled_or_missing_target_warehouse_first(self) -> None:
|
||||
@@ -1001,7 +964,9 @@ class TestInboundScanService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'get_pallet_by_qr_token', new=get_pallet),
|
||||
self.assertRaises(PermissionException),
|
||||
):
|
||||
await InboundService.scan_inbound_pallet_services(self.db, 'token', self.query, self.user)
|
||||
await InboundService.scan_inbound_pallet_services(
|
||||
self.db, 'token', self.query, self.user, TestBatchScope.formal()
|
||||
)
|
||||
get_pallet.assert_not_awaited()
|
||||
|
||||
for warehouse in (None, SimpleNamespace(warehouse_id=7, status='1')):
|
||||
@@ -1013,7 +978,9 @@ class TestInboundScanService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'get_pallet_by_qr_token', new=get_pallet),
|
||||
self.assertRaises(ServiceException),
|
||||
):
|
||||
await InboundService.scan_inbound_pallet_services(self.db, 'token', self.query, self.user)
|
||||
await InboundService.scan_inbound_pallet_services(
|
||||
self.db, 'token', self.query, self.user, TestBatchScope.formal()
|
||||
)
|
||||
get_pallet.assert_not_awaited()
|
||||
|
||||
|
||||
@@ -1045,12 +1012,14 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'get_inventories_for_update', new=inventory_lock),
|
||||
self.assertRaises(Exception) as raised,
|
||||
):
|
||||
await InboundService.confirm_inbound_services(self.db, 404, self.command, self.user)
|
||||
await InboundService.confirm_inbound_services(
|
||||
self.db, 404, self.command, self.user, TestBatchScope.formal()
|
||||
)
|
||||
|
||||
self.assertIsInstance(raised.exception, PermissionException)
|
||||
self.assertEqual('无权访问该入库单', raised.exception.message)
|
||||
scope.assert_awaited_once_with(self.db, 7)
|
||||
get_detail.assert_awaited_once_with(self.db, 404, warehouse_ids=[7])
|
||||
get_detail.assert_awaited_once_with(self.db, 404, TestBatchScope.formal(), warehouse_ids=[7])
|
||||
get_by_key.assert_not_awaited()
|
||||
lock_order.assert_not_awaited()
|
||||
inventory_lock.assert_not_awaited()
|
||||
@@ -1068,11 +1037,13 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'get_inbound_for_update', new=lock_order),
|
||||
self.assertRaises(ServiceException) as raised,
|
||||
):
|
||||
await InboundService.confirm_inbound_services(self.db, 404, self.command, make_user(1))
|
||||
await InboundService.confirm_inbound_services(
|
||||
self.db, 404, self.command, make_user(1), TestBatchScope.formal()
|
||||
)
|
||||
|
||||
self.assertEqual('入库单不存在', raised.exception.message)
|
||||
scope.assert_not_awaited()
|
||||
get_detail.assert_awaited_once_with(self.db, 404, warehouse_ids=None)
|
||||
get_detail.assert_awaited_once_with(self.db, 404, TestBatchScope.formal(), warehouse_ids=None)
|
||||
get_by_key.assert_not_awaited()
|
||||
lock_order.assert_not_awaited()
|
||||
self.db.rollback.assert_awaited_once()
|
||||
@@ -1169,7 +1140,9 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patches[10] as warehouse_lock,
|
||||
):
|
||||
service_datetime.now.return_value = self.fixed_time
|
||||
result = await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
result = await InboundService.confirm_inbound_services(
|
||||
self.db, 11, self.command, self.user, TestBatchScope.formal()
|
||||
)
|
||||
|
||||
return {
|
||||
'result': result,
|
||||
@@ -1209,17 +1182,33 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
captured['actions'],
|
||||
)
|
||||
self.default_scope.assert_awaited_once_with(self.db, 7)
|
||||
captured['detail_read'].assert_awaited_once_with(self.db, 11, warehouse_ids=[7])
|
||||
captured['detail_read'].assert_awaited_once_with(
|
||||
self.db,
|
||||
11,
|
||||
TestBatchScope.formal(),
|
||||
warehouse_ids=[7],
|
||||
)
|
||||
captured['key_read'].assert_awaited_once_with(
|
||||
self.db,
|
||||
'confirm-key',
|
||||
TestBatchScope.formal(),
|
||||
warehouse_ids=[7],
|
||||
)
|
||||
captured['order_lock'].assert_awaited_once_with(self.db, 11, warehouse_ids=[7])
|
||||
captured['warehouse_lock'].assert_awaited_once_with(self.db, 7, for_update=True)
|
||||
captured['order_lock'].assert_awaited_once_with(
|
||||
self.db,
|
||||
11,
|
||||
TestBatchScope.formal(),
|
||||
warehouse_ids=[7],
|
||||
)
|
||||
captured['warehouse_lock'].assert_awaited_once_with(
|
||||
self.db,
|
||||
7,
|
||||
TestBatchScope.formal(),
|
||||
for_update=True,
|
||||
)
|
||||
captured['access_probe'].assert_awaited_once_with(self.db, self.user, 7, for_update=True)
|
||||
captured['inventory_lock'].assert_awaited_once_with(self.db, [2, 5])
|
||||
captured['pallet_lock'].assert_awaited_once_with(self.db, [2, 5])
|
||||
captured['inventory_lock'].assert_awaited_once_with(self.db, [2, 5], TestBatchScope.formal())
|
||||
captured['pallet_lock'].assert_awaited_once_with(self.db, [2, 5], TestBatchScope.formal())
|
||||
captured['ensure_transition'].assert_has_calls(
|
||||
[
|
||||
unittest.mock.call(PalletFlowState.UNSTOCKED, PalletFlowState.EMPTY_IN_WAREHOUSE),
|
||||
@@ -1299,10 +1288,10 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'add_event', new=add_event),
|
||||
self.assertRaises(PermissionException) as raised,
|
||||
):
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual('无权访问该入库单', raised.exception.message)
|
||||
warehouse_lock.assert_awaited_once_with(self.db, 7, for_update=True)
|
||||
warehouse_lock.assert_awaited_once_with(self.db, 7, TestBatchScope.formal(), for_update=True)
|
||||
warehouse_mapping.assert_awaited_once_with(self.db, self.user, 7, for_update=True)
|
||||
self.assertEqual('DRAFT', inbound.status)
|
||||
self.assertEqual('UNSTOCKED', inventory.flow_state)
|
||||
@@ -1328,9 +1317,9 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'add_event', new=add_event),
|
||||
self.assertRaises(ServiceException),
|
||||
):
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user, TestBatchScope.formal())
|
||||
|
||||
pallet_lock.assert_awaited_once_with(self.db, [2, 5])
|
||||
pallet_lock.assert_awaited_once_with(self.db, [2, 5], TestBatchScope.formal())
|
||||
self.assertEqual('DRAFT', inbound.status)
|
||||
self.assertEqual('UNSTOCKED', inventories[0].flow_state)
|
||||
update.assert_not_awaited()
|
||||
@@ -1360,7 +1349,7 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'add_event', new=add_event),
|
||||
self.assertRaisesRegex(ValueError, 'invalid'),
|
||||
):
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual('DRAFT', inbound.status)
|
||||
self.assertEqual('UNSTOCKED', inventory.flow_state)
|
||||
@@ -1391,10 +1380,12 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
new=AsyncMock(return_value=SimpleNamespace(warehouse_id=7, status='0')),
|
||||
) as warehouse_lock,
|
||||
):
|
||||
result = await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
result = await InboundService.confirm_inbound_services(
|
||||
self.db, 11, self.command, self.user, TestBatchScope.formal()
|
||||
)
|
||||
|
||||
lock.assert_awaited_once_with(self.db, 11, warehouse_ids=[7])
|
||||
warehouse_lock.assert_awaited_once_with(self.db, 7, for_update=True)
|
||||
lock.assert_awaited_once_with(self.db, 11, TestBatchScope.formal(), warehouse_ids=[7])
|
||||
warehouse_lock.assert_awaited_once_with(self.db, 7, TestBatchScope.formal(), for_update=True)
|
||||
self.assertEqual(
|
||||
[
|
||||
unittest.mock.call(self.db, self.user, 7),
|
||||
@@ -1424,6 +1415,7 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
async def read_key(
|
||||
_db: AsyncSession,
|
||||
_key: str,
|
||||
_scope: TestBatchScope,
|
||||
*,
|
||||
warehouse_ids: list[int] | None = None,
|
||||
) -> BizInboundOrder | None:
|
||||
@@ -1455,13 +1447,15 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
11,
|
||||
self.command,
|
||||
self.user,
|
||||
TestBatchScope.formal(),
|
||||
)
|
||||
|
||||
self.assertTrue(result.is_success)
|
||||
get_detail.assert_awaited_once_with(self.db, 11, warehouse_ids=[7, 8])
|
||||
get_detail.assert_awaited_once_with(self.db, 11, TestBatchScope.formal(), warehouse_ids=[7, 8])
|
||||
key_read.assert_awaited_once_with(
|
||||
self.db,
|
||||
'confirm-key',
|
||||
TestBatchScope.formal(),
|
||||
warehouse_ids=[7],
|
||||
)
|
||||
self.db.rollback.assert_awaited_once()
|
||||
@@ -1496,10 +1490,10 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(AccessService, 'assert_warehouse_access', new=warehouse_mapping),
|
||||
self.assertRaises(PermissionException) as raised,
|
||||
):
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual('无权访问该入库单', raised.exception.message)
|
||||
warehouse_lock.assert_awaited_once_with(self.db, 7, for_update=True)
|
||||
warehouse_lock.assert_awaited_once_with(self.db, 7, TestBatchScope.formal(), for_update=True)
|
||||
warehouse_mapping.assert_awaited_with(self.db, self.user, 7, for_update=True)
|
||||
inventory_lock.assert_not_awaited()
|
||||
self.db.commit.assert_not_awaited()
|
||||
@@ -1526,7 +1520,7 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'get_inbound_for_update', new=lock),
|
||||
self.assertRaises(ServiceException),
|
||||
):
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user, TestBatchScope.formal())
|
||||
|
||||
access.assert_awaited_once_with(self.db, self.user, 8)
|
||||
lock.assert_not_awaited()
|
||||
@@ -1548,7 +1542,7 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'get_inventories_for_update', new=inventory_lock),
|
||||
self.assertRaises(ServiceException),
|
||||
):
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user, TestBatchScope.formal())
|
||||
|
||||
inventory_lock.assert_not_awaited()
|
||||
self.db.rollback.assert_awaited_once()
|
||||
@@ -1574,10 +1568,12 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'update_inbound', new=AsyncMock()),
|
||||
patch.object(InventoryDao, 'add_event', new=AsyncMock()),
|
||||
):
|
||||
result = await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
result = await InboundService.confirm_inbound_services(
|
||||
self.db, 11, self.command, self.user, TestBatchScope.formal()
|
||||
)
|
||||
|
||||
get_detail.assert_awaited_once_with(self.db, 11, warehouse_ids=[7])
|
||||
inventory_lock.assert_awaited_once_with(self.db, [5])
|
||||
get_detail.assert_awaited_once_with(self.db, 11, TestBatchScope.formal(), warehouse_ids=[7])
|
||||
inventory_lock.assert_awaited_once_with(self.db, [5], TestBatchScope.formal())
|
||||
self.assertEqual('EMPTY_IN_WAREHOUSE', inventory.flow_state)
|
||||
self.assertTrue(result.is_success)
|
||||
|
||||
@@ -1608,7 +1604,9 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(OperationDao, 'update_inbound', new=AsyncMock()),
|
||||
patch.object(InventoryDao, 'add_event', new=AsyncMock()),
|
||||
):
|
||||
result = await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
result = await InboundService.confirm_inbound_services(
|
||||
self.db, 11, self.command, self.user, TestBatchScope.formal()
|
||||
)
|
||||
|
||||
self.assertEqual(2, parent_lock.await_count)
|
||||
self.assertEqual(
|
||||
@@ -1621,8 +1619,8 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertEqual(2, key_reads.await_count)
|
||||
key_reads.assert_has_awaits(
|
||||
[
|
||||
unittest.mock.call(self.db, 'confirm-key', warehouse_ids=[7]),
|
||||
unittest.mock.call(self.db, 'confirm-key', warehouse_ids=[7]),
|
||||
unittest.mock.call(self.db, 'confirm-key', TestBatchScope.formal(), warehouse_ids=[7]),
|
||||
unittest.mock.call(self.db, 'confirm-key', TestBatchScope.formal(), warehouse_ids=[7]),
|
||||
]
|
||||
)
|
||||
self.assertEqual(2, self.db.rollback.await_count)
|
||||
@@ -1647,6 +1645,7 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
async def read_key(
|
||||
_db: AsyncSession,
|
||||
_key: str,
|
||||
_scope: TestBatchScope,
|
||||
*,
|
||||
warehouse_ids: list[int] | None = None,
|
||||
) -> BizInboundOrder | None:
|
||||
@@ -1683,6 +1682,7 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
11,
|
||||
self.command,
|
||||
self.user,
|
||||
TestBatchScope.formal(),
|
||||
)
|
||||
|
||||
self.assertTrue(result.is_success)
|
||||
@@ -1690,8 +1690,8 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertEqual(2, parent_lock.await_count)
|
||||
self.assertEqual(
|
||||
[
|
||||
unittest.mock.call(self.db, 'confirm-key', warehouse_ids=[7]),
|
||||
unittest.mock.call(self.db, 'confirm-key', warehouse_ids=[7]),
|
||||
unittest.mock.call(self.db, 'confirm-key', TestBatchScope.formal(), warehouse_ids=[7]),
|
||||
unittest.mock.call(self.db, 'confirm-key', TestBatchScope.formal(), warehouse_ids=[7]),
|
||||
],
|
||||
key_read.await_args_list,
|
||||
)
|
||||
@@ -1743,11 +1743,11 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'add_event', new=AsyncMock()),
|
||||
self.assertRaises(PermissionException) as raised,
|
||||
):
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual('无权访问该入库单', raised.exception.message)
|
||||
self.assertEqual(2, parent_lock.await_count)
|
||||
parent_lock.assert_awaited_with(self.db, 11, warehouse_ids=[7])
|
||||
parent_lock.assert_awaited_with(self.db, 11, TestBatchScope.formal(), warehouse_ids=[7])
|
||||
self.assertEqual(2, warehouse_lock.await_count)
|
||||
self.assertEqual(2, locked_access_count)
|
||||
self.assertEqual(2, self.db.rollback.await_count)
|
||||
@@ -1782,7 +1782,7 @@ class TestInboundConfirmService(unittest.IsolatedAsyncioTestCase):
|
||||
patch.object(InventoryDao, 'add_event', new=AsyncMock()),
|
||||
self.assertRaises(ServiceException),
|
||||
):
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user)
|
||||
await InboundService.confirm_inbound_services(self.db, 11, self.command, self.user, TestBatchScope.formal())
|
||||
|
||||
self.assertEqual(2, self.db.rollback.await_count)
|
||||
|
||||
@@ -1836,6 +1836,7 @@ class TestInboundLogPermission(unittest.IsolatedAsyncioTestCase):
|
||||
add_inbound=InboundCreateModel(warehouseId=404, palletIds=[2]),
|
||||
query_db=db,
|
||||
current_user=user,
|
||||
test_scope=TestBatchScope.formal(),
|
||||
)
|
||||
finally:
|
||||
RequestContext.reset_current_user(user_token)
|
||||
|
||||
Reference in New Issue
Block a user