from django.test import TestCase from django.contrib.auth.models import User from rest_framework.test import APIClient from rest_framework import status from basic_info.models import ( Merchant, MerchantTypeEnum, WareHouse, WarehouseTypeEnum, Employee, EmployeeType, EmployeeStatusEnum ) class WarehouseAPITestCase(TestCase): """测试仓库 API""" def setUp(self): """设置测试数据""" # 创建商户 self.merchant = Merchant.objects.create( name='测试商户', type=MerchantTypeEnum.STORE ) # 创建用户和员工 self.user = User.objects.create_user( username='testuser', password='testpass123' ) self.employee = Employee.objects.create( merchant=self.merchant, sys_user=self.user, name='测试员工' ) # 设置 API 客户端 self.client = APIClient() self.client.force_authenticate(user=self.user) def test_create_warehouse_with_default_type(self): """测试创建仓库时使用默认类型""" data = { 'name': '测试仓库1', 'location': '测试地址', } response = self.client.post('/api/backend/warehouses/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data['type'], WarehouseTypeEnum.WHOLE.value) # 验证数据库 warehouse = WareHouse.objects.get(id=response.data['id']) self.assertEqual(warehouse.type, WarehouseTypeEnum.WHOLE) def test_create_warehouse_with_whole_type(self): """测试创建整仓""" data = { 'name': '整仓测试', 'type': WarehouseTypeEnum.WHOLE.value, } response = self.client.post('/api/backend/warehouses/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data['type'], WarehouseTypeEnum.WHOLE.value) def test_create_warehouse_with_scattered_type(self): """测试创建散仓""" data = { 'name': '散仓测试', 'type': WarehouseTypeEnum.SCATTERED.value, } response = self.client.post('/api/backend/warehouses/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data['type'], WarehouseTypeEnum.SCATTERED.value) def test_list_warehouses_includes_type(self): """测试列表接口返回类型字段""" WareHouse.objects.create( merchant=self.merchant, name='仓库1', type=WarehouseTypeEnum.WHOLE ) WareHouse.objects.create( merchant=self.merchant, name='仓库2', type=WarehouseTypeEnum.SCATTERED ) response = self.client.get('/api/backend/warehouses/') self.assertEqual(response.status_code, status.HTTP_200_OK) results = response.data['results'] if isinstance(response.data, dict) else response.data self.assertEqual(len(results), 2) # 验证返回的数据包含 type 字段 for warehouse in results: self.assertIn('type', warehouse) self.assertIn(warehouse['type'], [WarehouseTypeEnum.WHOLE.value, WarehouseTypeEnum.SCATTERED.value]) def test_update_warehouse_type(self): """测试更新仓库类型""" warehouse = WareHouse.objects.create( merchant=self.merchant, name='待更新仓库', type=WarehouseTypeEnum.WHOLE ) data = {'type': WarehouseTypeEnum.SCATTERED.value} response = self.client.patch(f'/api/backend/warehouses/{warehouse.id}/', data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['type'], WarehouseTypeEnum.SCATTERED.value) # 验证数据库 warehouse.refresh_from_db() self.assertEqual(warehouse.type, WarehouseTypeEnum.SCATTERED) def test_retrieve_warehouse_includes_type(self): """测试检索单个仓库时包含类型字段""" warehouse = WareHouse.objects.create( merchant=self.merchant, name='单个仓库', type=WarehouseTypeEnum.SCATTERED ) response = self.client.get(f'/api/backend/warehouses/{warehouse.id}/') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['type'], WarehouseTypeEnum.SCATTERED.value) self.assertEqual(response.data['name'], '单个仓库') class EmployeeTypeAPITestCase(TestCase): """测试员工职位类型 API""" def setUp(self): """设置测试数据""" # 创建商户 self.merchant = Merchant.objects.create( name='测试商户', type=MerchantTypeEnum.STORE ) # 创建用户和员工 self.user = User.objects.create_user( username='testuser', password='testpass123' ) self.employee = Employee.objects.create( merchant=self.merchant, sys_user=self.user, name='测试员工' ) # 设置 API 客户端 self.client = APIClient() self.client.force_authenticate(user=self.user) def test_create_employee_type(self): """测试创建职位类型""" data = { 'title': '打纸工', 'description': '负责打纸工作' } response = self.client.post('/api/backend/employee-types/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data['title'], '打纸工') self.assertEqual(response.data['description'], '负责打纸工作') def test_list_employee_types(self): """测试列出所有职位类型""" EmployeeType.objects.create(merchant=self.merchant, title='打纸工') EmployeeType.objects.create(merchant=self.merchant, title='滚筒工') response = self.client.get('/api/backend/employee-types/') self.assertEqual(response.status_code, status.HTTP_200_OK) results = response.data['results'] if isinstance(response.data, dict) else response.data self.assertEqual(len(results), 2) def test_update_employee_type(self): """测试更新职位类型""" emp_type = EmployeeType.objects.create( merchant=self.merchant, title='仓库管理员' ) data = {'description': '新的描述'} response = self.client.patch(f'/api/backend/employee-types/{emp_type.id}/', data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['description'], '新的描述') def test_delete_employee_type(self): """测试删除职位类型""" emp_type = EmployeeType.objects.create( merchant=self.merchant, title='临时工' ) response = self.client.delete(f'/api/backend/employee-types/{emp_type.id}/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertFalse(EmployeeType.objects.filter(id=emp_type.id).exists()) class EmployeeAPITestCase(TestCase): """测试员工 API(包含 job_type 兼容性)""" def setUp(self): """设置测试数据""" # 创建商户 self.merchant = Merchant.objects.create( name='测试商户', type=MerchantTypeEnum.STORE ) # 创建用户和员工 self.user = User.objects.create_user( username='testuser', password='testpass123' ) self.employee = Employee.objects.create( merchant=self.merchant, sys_user=self.user, name='测试员工' ) # 创建职位类型 self.emp_type = EmployeeType.objects.create( merchant=self.merchant, title='打纸工' ) # 设置 API 客户端 self.client = APIClient() self.client.force_authenticate(user=self.user) def test_create_employee_with_position(self): """测试创建带职位的员工""" data = { 'name': '张三', 'position': self.emp_type.id, 'mobile': '13800138000' } response = self.client.post('/api/backend/employees/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data['position'], self.emp_type.id) self.assertEqual(response.data['job_type'], '打纸工') # 验证兼容性字段 def test_create_employee_without_position(self): """测试创建不带职位的员工""" data = { 'name': '李四', 'mobile': '13900139000' } response = self.client.post('/api/backend/employees/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertIsNone(response.data['position']) self.assertEqual(response.data['job_type'], '') # 验证返回空字符串 def test_list_employees_includes_job_type(self): """测试列表接口包含 job_type 字段""" Employee.objects.create( merchant=self.merchant, name='员工1', position=self.emp_type ) Employee.objects.create( merchant=self.merchant, name='员工2' ) response = self.client.get('/api/backend/employees/') self.assertEqual(response.status_code, status.HTTP_200_OK) results = response.data['results'] if isinstance(response.data, dict) else response.data # 验证 job_type 字段存在 for emp in results: self.assertIn('job_type', emp) def test_update_employee_position(self): """测试更新员工职位""" new_type = EmployeeType.objects.create( merchant=self.merchant, title='滚筒工' ) employee = Employee.objects.create( merchant=self.merchant, name='王五', position=self.emp_type ) data = {'position': new_type.id} response = self.client.patch(f'/api/backend/employees/{employee.id}/', data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['position'], new_type.id) self.assertEqual(response.data['job_type'], '滚筒工') def test_job_type_is_read_only(self): """测试 job_type 是只读字段""" employee = Employee.objects.create( merchant=self.merchant, name='赵六', position=self.emp_type ) # 尝试直接更新 job_type(应该被忽略) data = {'job_type': '其他职位'} response = self.client.patch(f'/api/backend/employees/{employee.id}/', data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['job_type'], '打纸工') # 应该保持不变 class UserProfileAPITestCase(TestCase): """测试用户资料 API""" def setUp(self): """设置测试数据""" # 创建商户 self.merchant = Merchant.objects.create( name='测试商户', type=MerchantTypeEnum.STORE ) # 创建用户和员工 self.user = User.objects.create_user( username='testuser', password='testpass123', email='test@example.com' ) self.employee = Employee.objects.create( merchant=self.merchant, sys_user=self.user, name='测试员工' ) # 创建另一个用户用于测试 self.user2 = User.objects.create_user( username='testuser2', password='testpass123', email='test2@example.com' ) # 设置 API 客户端 self.client = APIClient() self.client.force_authenticate(user=self.user) def test_create_user_profile(self): """测试创建用户资料""" data = { 'user': self.user2.id, 'description': '测试用户资料描述' } response = self.client.post('/api/backend/user-profiles/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data['user'], self.user2.id) self.assertEqual(response.data['merchant'], self.merchant.id) # 应该由BaseViewSet自动设置 self.assertEqual(response.data['description'], '测试用户资料描述') def test_list_user_profiles(self): """测试列出所有用户资料""" from basic_info.models import UserProfile UserProfile.objects.create( user=self.user, merchant=self.merchant, description='用户1资料' ) UserProfile.objects.create( user=self.user2, merchant=self.merchant, description='用户2资料' ) response = self.client.get('/api/backend/user-profiles/') self.assertEqual(response.status_code, status.HTTP_200_OK) results = response.data['results'] if isinstance(response.data, dict) else response.data self.assertEqual(len(results), 2) # 应该只返回当前商户的用户资料 def test_retrieve_user_profile(self): """测试检索单个用户资料""" from basic_info.models import UserProfile profile = UserProfile.objects.create( user=self.user, merchant=self.merchant, description='测试资料' ) response = self.client.get(f'/api/backend/user-profiles/{profile.id}/') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['id'], profile.id) self.assertEqual(response.data['description'], '测试资料') self.assertEqual(response.data['user_detail']['username'], 'testuser') # 检查嵌套用户对象 def test_update_user_profile(self): """测试更新用户资料""" from basic_info.models import UserProfile profile = UserProfile.objects.create( user=self.user, merchant=self.merchant, description='原始描述' ) data = {'description': '更新后的描述'} response = self.client.patch(f'/api/backend/user-profiles/{profile.id}/', data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['description'], '更新后的描述') # 验证数据库 profile.refresh_from_db() self.assertEqual(profile.description, '更新后的描述') def test_delete_user_profile(self): """测试删除用户资料""" from basic_info.models import UserProfile profile = UserProfile.objects.create( user=self.user, merchant=self.merchant, description='待删除资料' ) response = self.client.delete(f'/api/backend/user-profiles/{profile.id}/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertFalse(UserProfile.objects.filter(id=profile.id).exists()) def test_user_profile_filter_by_merchant(self): """测试用户资料按商户过滤""" # 创建另一个商户 other_merchant = Merchant.objects.create( name='其他商户', type=MerchantTypeEnum.FACTORY ) # 创建另一个商户的员工 other_user = User.objects.create_user( username='otheruser', password='testpass123' ) other_employee = Employee.objects.create( merchant=other_merchant, sys_user=other_user, name='其他员工' ) # 为两个商户分别创建用户资料 from basic_info.models import UserProfile UserProfile.objects.create( user=self.user, merchant=self.merchant, description='本商户用户资料' ) UserProfile.objects.create( user=other_user, merchant=other_merchant, description='其他商户用户资料' ) # 使用当前用户(属于self.merchant)访问API response = self.client.get('/api/backend/user-profiles/') self.assertEqual(response.status_code, status.HTTP_200_OK) results = response.data['results'] if isinstance(response.data, dict) else response.data self.assertEqual(len(results), 1) # 只应该返回当前商户的用户资料 self.assertEqual(results[0]['description'], '本商户用户资料')