补充主数据删除能力契约

This commit is contained in:
焦龙言
2026-07-27 04:34:10 +08:00
parent d1f0b9d48b
commit 33f29df40e
6 changed files with 311 additions and 12 deletions
@@ -993,6 +993,51 @@ class TestBusinessUserAssignmentService(unittest.IsolatedAsyncioTestCase):
self.db.rollback.assert_not_awaited()
self.assertTrue(result.is_success)
async def test_assignment_put_allows_empty_complete_replacement(self) -> None:
try:
assignment = UserAssignModel(userIds=[])
except ValidationError as exc:
self.fail(f'完整替换用户关联必须允许空数组:{exc}')
for resource, resource_id in (('warehouse', 7), ('site', 9)):
with self.subTest(resource=resource):
self.db.reset_mock()
list_users_mock = AsyncMock(return_value=[])
replace_mock = AsyncMock()
with (
patch.object(MasterDao, f'get_{resource}', new=AsyncMock(return_value=SimpleNamespace())),
patch.object(MasterDao, 'list_assignable_users_by_ids', new=list_users_mock),
patch.object(AccessDao, f'replace_{resource}_users', new=replace_mock),
):
result = await getattr(PalletService, f'assign_{resource}_users')(
self.db,
resource_id,
assignment,
)
list_users_mock.assert_awaited_once_with(self.db, [])
replace_mock.assert_awaited_once_with(self.db, resource_id, [])
self.db.commit.assert_awaited_once()
self.db.rollback.assert_not_awaited()
self.assertTrue(result.is_success)
async def test_empty_replacement_deletes_links_without_adding_new_rows(self) -> None:
cases = (
('warehouse', 7, 'biz_user_warehouse', 'warehouse_id'),
('site', 9, 'biz_user_site', 'site_id'),
)
for resource, resource_id, table, id_field in cases:
with self.subTest(resource=resource):
self.db.reset_mock()
await getattr(AccessDao, f'replace_{resource}_users')(self.db, resource_id, [])
delete_sql = compile_sql(self.db.execute.await_args.args[0])
self.assertIn(f'DELETE FROM {table}', delete_sql)
self.assertIn(f'{table}.{id_field} = {resource_id}', delete_sql)
self.db.add_all.assert_called_once_with([])
self.db.flush.assert_awaited_once()
async def test_assignment_put_rejects_missing_disabled_or_deleted_user(self) -> None:
replace = AsyncMock()
assignment = UserAssignModel(userIds=[2, 5])