forked from erp-dev/erp
feat: added frontend_pages models(basic_info) and api(v2), support employees query pages that they can visit by themself token
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
from io import StringIO
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.test import TestCase
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from .models import (
|
||||
Merchant, MerchantTypeEnum, WareHouse, WarehouseTypeEnum,
|
||||
WareHouseModeEnum, EmployeeType, Employee, EmployeeStatusEnum
|
||||
WareHouseModeEnum, EmployeeType, Employee, EmployeeStatusEnum,
|
||||
FrontendPage, FrontendPageTypeEnum
|
||||
)
|
||||
|
||||
|
||||
@@ -164,3 +169,211 @@ class EmployeeTypeTestCase(TestCase):
|
||||
self.assertEqual(emp1.job_type, '打纸工')
|
||||
self.assertEqual(emp2.job_type, '打纸工')
|
||||
self.assertEqual(emp_type.employees.count(), 2)
|
||||
|
||||
|
||||
class FrontendPageTestCase(TestCase):
|
||||
"""测试前端页面模型"""
|
||||
|
||||
def test_create_main_menu(self):
|
||||
"""测试创建主菜单"""
|
||||
page = FrontendPage.objects.create(
|
||||
key='plate-opening',
|
||||
label='开版管理',
|
||||
page_type=FrontendPageTypeEnum.MAIN,
|
||||
sort_order=0
|
||||
)
|
||||
self.assertEqual(page.key, 'plate-opening')
|
||||
self.assertEqual(page.label, '开版管理')
|
||||
self.assertEqual(page.page_type, FrontendPageTypeEnum.MAIN)
|
||||
self.assertIsNone(page.parent)
|
||||
self.assertTrue(page.is_active)
|
||||
self.assertEqual(str(page), '开版管理 (plate-opening)')
|
||||
|
||||
def test_create_sub_menu_with_parent(self):
|
||||
"""测试创建子菜单并关联父级"""
|
||||
parent = FrontendPage.objects.create(
|
||||
key='plate-opening',
|
||||
label='开版管理',
|
||||
page_type=FrontendPageTypeEnum.MAIN
|
||||
)
|
||||
child = FrontendPage.objects.create(
|
||||
key='plate-order',
|
||||
label='开版订单',
|
||||
page_type=FrontendPageTypeEnum.SUB,
|
||||
parent=parent
|
||||
)
|
||||
self.assertEqual(child.parent, parent)
|
||||
self.assertEqual(parent.children.count(), 1)
|
||||
self.assertEqual(parent.children.first(), child)
|
||||
|
||||
def test_key_unique_constraint(self):
|
||||
"""测试 key 字段唯一性约束"""
|
||||
FrontendPage.objects.create(key='test-page', label='测试页面')
|
||||
with self.assertRaises(Exception):
|
||||
FrontendPage.objects.create(key='test-page', label='重复页面')
|
||||
|
||||
def test_cascade_delete(self):
|
||||
"""测试删除父级时子级也被删除"""
|
||||
parent = FrontendPage.objects.create(
|
||||
key='parent',
|
||||
label='父级',
|
||||
page_type=FrontendPageTypeEnum.MAIN
|
||||
)
|
||||
FrontendPage.objects.create(
|
||||
key='child1',
|
||||
label='子级1',
|
||||
parent=parent
|
||||
)
|
||||
FrontendPage.objects.create(
|
||||
key='child2',
|
||||
label='子级2',
|
||||
parent=parent
|
||||
)
|
||||
self.assertEqual(FrontendPage.objects.count(), 3)
|
||||
parent.delete()
|
||||
self.assertEqual(FrontendPage.objects.count(), 0)
|
||||
|
||||
|
||||
class EmployeeTypeVisiblePagesTestCase(TestCase):
|
||||
"""测试员工职位类型的可见页面功能"""
|
||||
|
||||
def setUp(self):
|
||||
"""设置测试数据"""
|
||||
self.merchant = Merchant.objects.create(
|
||||
name='测试商户',
|
||||
type=MerchantTypeEnum.STORE
|
||||
)
|
||||
# 创建页面
|
||||
self.main_menu = FrontendPage.objects.create(
|
||||
key='production',
|
||||
label='生产管理',
|
||||
page_type=FrontendPageTypeEnum.MAIN
|
||||
)
|
||||
self.sub_menu1 = FrontendPage.objects.create(
|
||||
key='production-kanban',
|
||||
label='生产看板',
|
||||
page_type=FrontendPageTypeEnum.SUB,
|
||||
parent=self.main_menu
|
||||
)
|
||||
self.sub_menu2 = FrontendPage.objects.create(
|
||||
key='printing-order-list',
|
||||
label='生产订单',
|
||||
page_type=FrontendPageTypeEnum.SUB,
|
||||
parent=self.main_menu
|
||||
)
|
||||
# 创建岗位
|
||||
self.emp_type = EmployeeType.objects.create(
|
||||
merchant=self.merchant,
|
||||
title='生产主管'
|
||||
)
|
||||
|
||||
def test_assign_visible_pages(self):
|
||||
"""测试为岗位分配可见页面"""
|
||||
self.emp_type.visible_pages.add(self.main_menu)
|
||||
self.assertEqual(self.emp_type.visible_pages.count(), 1)
|
||||
self.assertIn(self.main_menu, self.emp_type.visible_pages.all())
|
||||
|
||||
def test_get_visible_page_keys_with_main_menu(self):
|
||||
"""测试授予主菜单时获取所有可见页面(含子菜单)"""
|
||||
self.emp_type.visible_pages.add(self.main_menu)
|
||||
|
||||
# 模拟查询逻辑
|
||||
visible_keys = set()
|
||||
for page in self.emp_type.visible_pages.filter(is_active=True):
|
||||
visible_keys.add(page.key)
|
||||
if page.page_type == FrontendPageTypeEnum.MAIN:
|
||||
children_keys = page.children.filter(is_active=True).values_list('key', flat=True)
|
||||
visible_keys.update(children_keys)
|
||||
|
||||
self.assertIn('production', visible_keys)
|
||||
self.assertIn('production-kanban', visible_keys)
|
||||
self.assertIn('printing-order-list', visible_keys)
|
||||
self.assertEqual(len(visible_keys), 3)
|
||||
|
||||
def test_get_visible_page_keys_with_sub_menu_only(self):
|
||||
"""测试仅授予子菜单时只能看到该子菜单"""
|
||||
self.emp_type.visible_pages.add(self.sub_menu1)
|
||||
|
||||
visible_keys = set()
|
||||
for page in self.emp_type.visible_pages.filter(is_active=True):
|
||||
visible_keys.add(page.key)
|
||||
if page.page_type == FrontendPageTypeEnum.MAIN:
|
||||
children_keys = page.children.filter(is_active=True).values_list('key', flat=True)
|
||||
visible_keys.update(children_keys)
|
||||
|
||||
self.assertIn('production-kanban', visible_keys)
|
||||
self.assertNotIn('production', visible_keys)
|
||||
self.assertNotIn('printing-order-list', visible_keys)
|
||||
self.assertEqual(len(visible_keys), 1)
|
||||
|
||||
def test_employee_visible_pages_through_position(self):
|
||||
"""测试通过员工岗位查询可见页面"""
|
||||
self.emp_type.visible_pages.add(self.main_menu)
|
||||
|
||||
employee = Employee.objects.create(
|
||||
merchant=self.merchant,
|
||||
name='测试员工',
|
||||
position=self.emp_type
|
||||
)
|
||||
|
||||
# 通过员工 -> 岗位 -> 可见页面
|
||||
visible_pages = employee.position.visible_pages.all()
|
||||
self.assertEqual(visible_pages.count(), 1)
|
||||
self.assertIn(self.main_menu, visible_pages)
|
||||
|
||||
|
||||
class SyncFrontendPagesCommandTestCase(TestCase):
|
||||
"""测试 sync_frontend_pages 管理命令"""
|
||||
|
||||
def test_sync_command_dry_run(self):
|
||||
"""测试 dry-run 模式不写入数据"""
|
||||
out = StringIO()
|
||||
call_command('sync_frontend_pages', '--dry-run', stdout=out)
|
||||
|
||||
# 验证没有实际写入
|
||||
self.assertEqual(FrontendPage.objects.count(), 0)
|
||||
self.assertIn('DRY-RUN', out.getvalue())
|
||||
|
||||
def test_sync_command_creates_pages(self):
|
||||
"""测试命令创建页面数据"""
|
||||
out = StringIO()
|
||||
call_command('sync_frontend_pages', stdout=out)
|
||||
|
||||
# 验证创建了页面
|
||||
self.assertGreater(FrontendPage.objects.count(), 0)
|
||||
|
||||
# 验证主菜单
|
||||
main_menus = FrontendPage.objects.filter(page_type=FrontendPageTypeEnum.MAIN)
|
||||
self.assertEqual(main_menus.count(), 9) # 9 个主菜单
|
||||
|
||||
# 验证子菜单
|
||||
sub_menus = FrontendPage.objects.filter(page_type=FrontendPageTypeEnum.SUB)
|
||||
self.assertEqual(sub_menus.count(), 43) # 43 个子菜单
|
||||
|
||||
# 验证父子关系
|
||||
plate_opening = FrontendPage.objects.get(key='plate-opening')
|
||||
self.assertEqual(plate_opening.children.count(), 5)
|
||||
|
||||
def test_sync_command_idempotent(self):
|
||||
"""测试命令幂等性(多次运行结果一致)"""
|
||||
call_command('sync_frontend_pages', stdout=StringIO())
|
||||
first_count = FrontendPage.objects.count()
|
||||
|
||||
call_command('sync_frontend_pages', stdout=StringIO())
|
||||
second_count = FrontendPage.objects.count()
|
||||
|
||||
self.assertEqual(first_count, second_count)
|
||||
|
||||
def test_sync_command_clear_option(self):
|
||||
"""测试 --clear 选项"""
|
||||
# 先创建数据
|
||||
call_command('sync_frontend_pages', stdout=StringIO())
|
||||
self.assertGreater(FrontendPage.objects.count(), 0)
|
||||
|
||||
# 使用 --clear 重新同步
|
||||
out = StringIO()
|
||||
call_command('sync_frontend_pages', '--clear', stdout=out)
|
||||
|
||||
self.assertIn('已清空', out.getvalue())
|
||||
# 数据应该重新创建
|
||||
self.assertEqual(FrontendPage.objects.count(), 52) # 9 主菜单 + 43 子菜单
|
||||
|
||||
Reference in New Issue
Block a user