import { describe, it, expect, beforeEach } from 'vitest'; import { testClient } from 'hono/testing'; import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util'; import { JWTUtil } from '@d8d/shared-utils'; import { JWTPayload } from '@d8d/shared-types'; import { UserEntity, Role } from '@d8d/user-module'; import { File } from '@d8d/file-module'; import { DisabledPerson, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit } from '@d8d/allin-disability-module'; import { BankName } from '@d8d/bank-names-module'; import { Company } from '@d8d/allin-company-module/entities'; import { Platform } from '@d8d/allin-platform-module'; import { DataSource } from 'typeorm'; import orderRoutes from '../../src/routes/order.routes'; import { EmploymentOrder } from '../../src/entities/employment-order.entity'; import { OrderPerson } from '../../src/entities/order-person.entity'; import { OrderPersonAsset } from '../../src/entities/order-person-asset.entity'; import { AssetType, AssetFileType, AssetStatus, DownloadScope } from '../../src/schemas/order.schema'; import { OrderStatus, WorkStatus } from '@d8d/allin-enums'; import { OrderTestDataFactory } from '../utils/test-data-factory'; // 设置集成测试钩子 setupIntegrationDatabaseHooksWithEntities([UserEntity, File, Role, Platform, Company, DisabledPerson, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit, BankName, EmploymentOrder, OrderPerson, OrderPersonAsset]) describe('订单管理API集成测试', () => { let client: ReturnType>; let testToken: string; let testUser: UserEntity; let testFile: File; let testDisabledPerson: DisabledPerson; beforeEach(async () => { // 创建测试客户端 client = testClient(orderRoutes); // 获取数据源 const dataSource = await IntegrationTestDatabase.getDataSource(); // 创建测试用户 const userRepository = dataSource.getRepository(UserEntity); testUser = userRepository.create({ username: `test_user_${Date.now()}`, password: 'test_password', nickname: '测试用户', registrationSource: 'web' }); await userRepository.save(testUser); // 生成测试用户的token testToken = JWTUtil.generateToken({ id: testUser.id, username: testUser.username, roles: [{name:'user'}] }); // 创建测试文件 const fileRepository = dataSource.getRepository(File); testFile = fileRepository.create({ name: 'test_file.pdf', type: 'application/pdf', size: 1024, path: `test/${Date.now()}_test_file.pdf`, uploadUserId: testUser.id, uploadTime: new Date(), createdAt: new Date(), updatedAt: new Date() }); await fileRepository.save(testFile); // 创建测试银行名称记录(用于DisabledBankCard外键约束) const bankNameRepository = dataSource.getRepository(BankName); const testBankName = bankNameRepository.create({ name: '测试银行', code: 'TEST001', remark: '测试银行', createdBy: testUser.id, updatedBy: testUser.id, status: 1 }); await bankNameRepository.save(testBankName); // 创建测试残疾人记录(用于外键约束) testDisabledPerson = await OrderTestDataFactory.createTestDisabledPerson(dataSource); }); describe('POST /order/create', () => { it('应该成功创建订单', async () => { const createData = { orderName: '测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date().toISOString(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING }; const response = await client.create.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); if (response.status !== 200) { const error = await response.json(); console.debug('创建订单失败:', JSON.stringify(error, null, 2)); } expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.id).toBeDefined(); expect(data.orderName).toBe('测试订单'); expect(data.orderStatus).toBe(OrderStatus.DRAFT); expect(data.workStatus).toBe(WorkStatus.NOT_WORKING); } }); it('应该验证订单状态枚举值', async () => { const createData = { orderName: '测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date().toISOString(), orderStatus: 'invalid_status', // 无效的状态 workStatus: WorkStatus.NOT_WORKING }; const response = await client.create.$post({ json: createData as any // 使用any绕过类型检查,因为这里故意测试无效的枚举值 }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该验证工作状态枚举值', async () => { const createData = { orderName: '测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date().toISOString(), orderStatus: OrderStatus.DRAFT, workStatus: 'invalid_status' // 无效的状态 }; const response = await client.create.$post({ json: createData as any // 使用any绕过类型检查,因为这里故意测试无效的枚举值 }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); }); describe('GET /order/list', () => { let testOrder: EmploymentOrder; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '测试订单1', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING }); await orderRepository.save(testOrder); const testOrder2 = new EmploymentOrder({ orderName: '测试订单2', platformId: 2, companyId: 2, channelId: 2, expectedStartDate: new Date(), orderStatus: OrderStatus.CONFIRMED, workStatus: WorkStatus.PRE_WORKING }); await orderRepository.save(testOrder2); }); it('应该返回所有订单列表', async () => { const response = await client.list.$get({ query: {} }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data).toHaveProperty('data'); expect(data).toHaveProperty('total'); expect(data.data).toHaveLength(2); expect(data.total).toBe(2); } }); it('应该支持按订单名称搜索', async () => { const response = await client.list.$get({ query: { orderName: '测试订单1' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.data[0].orderName).toBe('测试订单1'); } }); it('应该支持按订单状态过滤', async () => { const response = await client.list.$get({ query: { orderStatus: OrderStatus.CONFIRMED } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.data[0].orderStatus).toBe(OrderStatus.CONFIRMED); } }); it('应该支持分页查询', async () => { const response = await client.list.$get({ query: { page: '1', limit: '1' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.total).toBe(2); } }); }); describe('GET /order/detail/:id', () => { let testOrder: EmploymentOrder; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '测试订单详情', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING }); await orderRepository.save(testOrder); }); it('应该返回指定ID的订单详情', async () => { const response = await client.detail[':id'].$get({ param: { id: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); if (response.status !== 200) { const error = await response.json(); console.debug('获取订单详情失败:', JSON.stringify(error, null, 2)); } expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data?.id).toBe(testOrder.id); expect(data?.orderName).toBe('测试订单详情'); expect(data?.orderStatus).toBe(OrderStatus.DRAFT); } }); it('应该处理不存在的订单ID', async () => { const response = await client.detail[':id'].$get({ param: { id: '999999' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('POST /order/activate/:orderId', () => { let testOrder: EmploymentOrder; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '待激活订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING }); await orderRepository.save(testOrder); }); it('应该成功激活草稿状态的订单', async () => { const response = await client.activate[':orderId'].$post({ param: { orderId: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); // 验证订单状态已更新 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); const updatedOrder = await orderRepository.findOne({ where: { id: testOrder.id } }); expect(updatedOrder?.orderStatus).toBe(OrderStatus.CONFIRMED); expect(updatedOrder?.actualStartDate).toBeDefined(); } }); it('应该处理非草稿状态的订单激活', async () => { // 更新订单状态为已确认 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); await orderRepository.update(testOrder.id, { orderStatus: OrderStatus.CONFIRMED }); const response = await client.activate[':orderId'].$post({ param: { orderId: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该处理不存在的订单ID', async () => { const response = await client.activate[':orderId'].$post({ param: { orderId: '999999' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('POST /order/close/:orderId', () => { let testOrder: EmploymentOrder; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '待关闭订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), actualStartDate: new Date(), orderStatus: OrderStatus.CONFIRMED, workStatus: WorkStatus.PRE_WORKING, }); await orderRepository.save(testOrder); }); it('应该成功关闭已确认状态的订单', async () => { const response = await client.close[':orderId'].$post({ param: { orderId: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); // 验证订单状态已更新 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); const updatedOrder = await orderRepository.findOne({ where: { id: testOrder.id } }); expect(updatedOrder?.orderStatus).toBe(OrderStatus.COMPLETED); expect(updatedOrder?.actualEndDate).toBeDefined(); } }); it('应该处理非已确认或进行中状态的订单关闭', async () => { // 更新订单状态为草稿 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); await orderRepository.update(testOrder.id, { orderStatus: OrderStatus.DRAFT }); const response = await client.close[':orderId'].$post({ param: { orderId: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该处理不存在的订单ID', async () => { const response = await client.close[':orderId'].$post({ param: { orderId: '999999' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('POST /order/:orderId/persons/batch', () => { let testOrder: EmploymentOrder; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '批量添加人员测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, }); await orderRepository.save(testOrder); }); it('应该成功批量添加人员到订单', async () => { // 创建两个测试残疾人记录 const dataSource = await IntegrationTestDatabase.getDataSource(); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); // 直接创建最简单的DisabledPerson记录 const disabledPerson1 = disabledPersonRepository.create({ name: '测试1', gender: '男', idCard: '1', disabilityId: '1', disabilityType: '肢体', disabilityLevel: '三级', idAddress: '地址', phone: '13800138000', canDirectContact: 1, province: '省', city: '市', district: '区', detailedAddress: '地址', isInBlackList: 0, jobStatus: 0, createTime: new Date(), updateTime: new Date() }); await disabledPersonRepository.save(disabledPerson1); const disabledPerson2 = disabledPersonRepository.create({ name: '测试2', gender: '女', idCard: '2', disabilityId: '2', disabilityType: '视力', disabilityLevel: '二级', idAddress: '地址', phone: '13800138001', canDirectContact: 1, province: '省', city: '市', district: '区', detailedAddress: '地址', isInBlackList: 0, jobStatus: 0, createTime: new Date(), updateTime: new Date() }); await disabledPersonRepository.save(disabledPerson2); const batchData = { persons: [ { personId: disabledPerson1.id, joinDate: new Date().toISOString(), salaryDetail: 5000.00 }, { personId: disabledPerson2.id, joinDate: new Date().toISOString(), salaryDetail: 6000.00 } ] }; const response = await client[':orderId'].persons.batch.$post({ param: { orderId: testOrder.id.toString() }, json: batchData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); expect(data.addedCount).toBe(2); // 验证人员已添加到订单 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderPersonRepository = dataSource.getRepository(OrderPerson); const orderPersons = await orderPersonRepository.find({ where: { orderId: testOrder.id } }); expect(orderPersons).toHaveLength(2); } }); it('应该处理重复的人员添加', async () => { // 创建两个测试残疾人记录 const dataSource = await IntegrationTestDatabase.getDataSource(); const [disabledPerson1, disabledPerson2] = await OrderTestDataFactory.createTestDisabledPersons(dataSource, 2); const orderPersonRepository = dataSource.getRepository(OrderPerson); // 先添加一个人员 const existingPerson = orderPersonRepository.create({ orderId: testOrder.id, personId: disabledPerson1.id, joinDate: new Date(), workStatus: WorkStatus.NOT_WORKING, salaryDetail: 5000.00 }); await orderPersonRepository.save(existingPerson); const batchData = { persons: [ { personId: disabledPerson1.id, // 已存在的人员 joinDate: new Date().toISOString(), salaryDetail: 5000.00 }, { personId: disabledPerson2.id, // 新人员 joinDate: new Date().toISOString(), salaryDetail: 6000.00 } ] }; const response = await client[':orderId'].persons.batch.$post({ param: { orderId: testOrder.id.toString() }, json: batchData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); expect(data.addedCount).toBe(1); // 只添加了一个新人员 } }); it('应该处理已结束或已取消的订单', async () => { // 更新订单状态为已完成 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); await orderRepository.update(testOrder.id, { orderStatus: OrderStatus.COMPLETED }); const batchData = { persons: [ { personId: 1001, joinDate: new Date().toISOString(), salaryDetail: 5000.00 } ] }; const response = await client[':orderId'].persons.batch.$post({ param: { orderId: testOrder.id.toString() }, json: batchData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该处理不存在的订单ID', async () => { const batchData = { persons: [ { personId: 1001, joinDate: new Date().toISOString(), salaryDetail: 5000.00 } ] }; const response = await client[':orderId'].persons.batch.$post({ param: { orderId: '999999' }, json: batchData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('POST /order/assets/create', () => { let testOrder: EmploymentOrder; let testOrderPerson: OrderPerson; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); const orderPersonRepository = dataSource.getRepository(OrderPerson); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); testOrder = new EmploymentOrder({ orderName: '资产测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, }); await orderRepository.save(testOrder); // 先创建残疾人记录 const testDisabledPerson = await OrderTestDataFactory.createTestDisabledPerson(dataSource); testOrderPerson = orderPersonRepository.create({ orderId: testOrder.id, personId: testDisabledPerson.id, joinDate: new Date(), workStatus: WorkStatus.NOT_WORKING, salaryDetail: 5000.00 }); await orderPersonRepository.save(testOrderPerson); }); it('应该成功创建订单人员资产', async () => { const assetData = { orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.DISABILITY_CERT, assetFileType: AssetFileType.IMAGE, fileId: testFile.id, relatedTime: new Date().toISOString() }; const response = await client.assets.create.$post({ json: assetData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); if (response.status !== 200) { const error = await response.json(); console.debug('创建订单人员资产失败:', JSON.stringify(error, null, 2)); } expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.id).toBeDefined(); expect(data.orderId).toBe(testOrder.id); expect(data.personId).toBe(testOrderPerson.personId); expect(data.assetType).toBe(AssetType.DISABILITY_CERT); expect(data.fileId).toBe(testFile.id); } }); it('应该处理不存在的文件ID', async () => { const assetData = { orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.DISABILITY_CERT, assetFileType: AssetFileType.IMAGE, fileId: 999999, // 不存在的文件ID relatedTime: new Date().toISOString() }; const response = await client.assets.create.$post({ json: assetData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该处理人员不在订单中的情况', async () => { const assetData = { orderId: testOrder.id, personId: 999999, // 不在订单中的人员 assetType: AssetType.DISABILITY_CERT, assetFileType: AssetFileType.IMAGE, fileId: testFile.id, relatedTime: new Date().toISOString() }; const response = await client.assets.create.$post({ json: assetData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('GET /order/assets/query', () => { let testOrder: EmploymentOrder; let testOrderPerson: OrderPerson; let testAsset: OrderPersonAsset; beforeEach(async () => { // 创建测试数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); const orderPersonRepository = dataSource.getRepository(OrderPerson); const assetRepository = dataSource.getRepository(OrderPersonAsset); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); testOrder = new EmploymentOrder({ orderName: '资产查询测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, }); await orderRepository.save(testOrder); // 先创建残疾人记录 const testDisabledPerson = await OrderTestDataFactory.createTestDisabledPerson(dataSource); testOrderPerson = orderPersonRepository.create({ orderId: testOrder.id, personId: testDisabledPerson.id, joinDate: new Date(), workStatus: WorkStatus.NOT_WORKING, salaryDetail: 5000.00 }); await orderPersonRepository.save(testOrderPerson); testAsset = new OrderPersonAsset({ orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.DISABILITY_CERT, assetFileType: AssetFileType.IMAGE, fileId: testFile.id, relatedTime: new Date() }); await assetRepository.save(testAsset); // 创建第二个资产 const testAsset2 = new OrderPersonAsset({ orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.OTHER, assetFileType: AssetFileType.IMAGE, fileId: testFile.id, relatedTime: new Date() }); await assetRepository.save(testAsset2); }); it('应该查询所有订单人员资产', async () => { const response = await client.assets.query.$get({ query: {} }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data).toHaveProperty('data'); expect(data).toHaveProperty('total'); expect(data.data).toHaveLength(2); expect(data.total).toBe(2); } }); it('应该支持按订单ID查询', async () => { const response = await client.assets.query.$get({ query: { orderId: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(2); expect(data.data[0].orderId).toBe(testOrder.id); } }); it('应该支持按人员ID查询', async () => { const response = await client.assets.query.$get({ query: { personId: testOrderPerson.personId.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(2); expect(data.data[0].personId).toBe(testOrderPerson.personId); } }); it('应该支持按资产类型查询', async () => { const response = await client.assets.query.$get({ query: { assetType: AssetType.DISABILITY_CERT } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.data[0].assetType).toBe(AssetType.DISABILITY_CERT); } }); it('应该支持分页查询', async () => { const response = await client.assets.query.$get({ query: { page: '1', limit: '1' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.total).toBe(2); } }); }); describe('DELETE /order/assets/delete/:id', () => { let testAsset: OrderPersonAsset; beforeEach(async () => { // 创建测试数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); const orderPersonRepository = dataSource.getRepository(OrderPerson); const assetRepository = dataSource.getRepository(OrderPersonAsset); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); const testOrder = new EmploymentOrder({ orderName: '资产删除测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, }); await orderRepository.save(testOrder); // 先创建残疾人记录 const testDisabledPerson = await OrderTestDataFactory.createTestDisabledPerson(dataSource); const testOrderPerson = orderPersonRepository.create({ orderId: testOrder.id, personId: testDisabledPerson.id, joinDate: new Date(), workStatus: WorkStatus.NOT_WORKING, salaryDetail: 5000.00 }); await orderPersonRepository.save(testOrderPerson); testAsset = new OrderPersonAsset({ orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.DISABILITY_CERT, assetFileType: AssetFileType.IMAGE, fileId: testFile.id, relatedTime: new Date() }); await assetRepository.save(testAsset); }); it('应该成功删除订单人员资产', async () => { const response = await client.assets.delete[':id'].$delete({ param: { id: testAsset.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); // 验证资产已删除 const dataSource = await IntegrationTestDatabase.getDataSource(); const assetRepository = dataSource.getRepository(OrderPersonAsset); const deletedAsset = await assetRepository.findOne({ where: { id: testAsset.id } }); expect(deletedAsset).toBeNull(); } }); it('应该处理不存在的资产ID', async () => { const response = await client.assets.delete[':id'].$delete({ param: { id: '999999' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('认证测试', () => { it('应该要求认证', async () => { const response = await client.list.$get({ query: {} // 不提供Authorization header }); expect(response.status).toBe(401); }); it('应该验证无效token', async () => { const response = await client.list.$get({ query: {} }, { headers: { 'Authorization': 'Bearer invalid_token' } }); expect(response.status).toBe(401); }); }); describe('订单统计API测试', () => { let testCompany: Company; beforeEach(async () => { // 创建测试公司 const dataSource = await IntegrationTestDatabase.getDataSource(); const companyRepository = dataSource.getRepository(Company); testCompany = companyRepository.create({ companyName: '统计测试公司', contactPerson: '测试联系人', contactPhone: '13800138000', status: 1 }); await companyRepository.save(testCompany); }); describe('GET /order/checkin-statistics', () => { it('应该返回正确的打卡视频数量统计', async () => { // 测试实现待补充 expect(true).toBe(true); }); }); describe('GET /order/video-statistics', () => { it('应该按类型分类返回视频统计结果', async () => { // 测试实现待补充 expect(true).toBe(true); }); }); describe('GET /order/company-orders', () => { it('应该支持按企业ID过滤,返回完整订单信息', async () => { // 测试实现待补充 expect(true).toBe(true); }); }); }); describe('企业维度视频管理API测试', () => { let testCompany: Company; let testOrder: EmploymentOrder; let testOrderPerson: OrderPerson; let testVideoAssets: OrderPersonAsset[]; beforeEach(async () => { // 创建测试公司 const dataSource = await IntegrationTestDatabase.getDataSource(); const companyRepository = dataSource.getRepository(Company); testCompany = companyRepository.create({ companyName: '视频管理测试公司', contactPerson: '测试联系人', contactPhone: '13800138001', status: 1 }); await companyRepository.save(testCompany); // 为测试用户生成包含companyId的token,添加enterprise角色 testToken = JWTUtil.generateToken({ id: testUser.id, username: testUser.username, roles: [{name:'user'}, {name:'enterprise'}] }, { companyId: testCompany.id } as Partial); // 更新用户实体的companyId(如果字段存在) const userRepository = dataSource.getRepository(UserEntity); await userRepository.update(testUser.id, { companyId: testCompany.id } as any); // 创建测试订单 const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '视频管理测试订单', platformId: 1, companyId: testCompany.id, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, }); await orderRepository.save(testOrder); // 创建测试残疾人记录 const disabledPersonRepository = dataSource.getRepository(DisabledPerson); const testDisabledPerson = disabledPersonRepository.create({ name: '视频测试人员', gender: '男', idCard: '3', disabilityId: '3', disabilityType: '肢体', disabilityLevel: '三级', idAddress: '地址', phone: '13800138002', canDirectContact: 1, province: '省', city: '市', district: '区', detailedAddress: '地址', isInBlackList: 0, jobStatus: 0, createTime: new Date(), updateTime: new Date() }); await disabledPersonRepository.save(testDisabledPerson); // 创建订单人员关联 const orderPersonRepository = dataSource.getRepository(OrderPerson); testOrderPerson = orderPersonRepository.create({ orderId: testOrder.id, personId: testDisabledPerson.id, joinDate: new Date(), workStatus: WorkStatus.NOT_WORKING, salaryDetail: 5000.00 }); await orderPersonRepository.save(testOrderPerson); // 创建测试视频资产 const assetRepository = dataSource.getRepository(OrderPersonAsset); testVideoAssets = [ new OrderPersonAsset({ orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.CHECKIN_VIDEO, assetFileType: AssetFileType.VIDEO, fileId: testFile.id, relatedTime: new Date(), status: AssetStatus.PENDING }), new OrderPersonAsset({ orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.WORK_VIDEO, assetFileType: AssetFileType.VIDEO, fileId: testFile.id, relatedTime: new Date(Date.now() - 86400000), // 昨天 status: AssetStatus.VERIFIED }), new OrderPersonAsset({ orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.SALARY_VIDEO, assetFileType: AssetFileType.VIDEO, fileId: testFile.id, relatedTime: new Date(Date.now() - 172800000), // 前天 status: AssetStatus.REJECTED }) ]; await assetRepository.save(testVideoAssets); }); describe('GET /order/company-videos', () => { it('应该返回企业维度视频列表', async () => { const response = await client['company-videos'].$get({ query: { companyId: testCompany.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data).toHaveProperty('data'); expect(data).toHaveProperty('total'); expect(data.data).toHaveLength(3); // 应该返回所有视频 expect(data.total).toBe(3); // 验证数据结构 expect(data.data[0]).toHaveProperty('id'); expect(data.data[0]).toHaveProperty('orderId'); expect(data.data[0]).toHaveProperty('personId'); expect(data.data[0]).toHaveProperty('assetType'); expect(data.data[0]).toHaveProperty('assetFileType'); expect(data.data[0]).toHaveProperty('file'); } }); it('应该支持按视频类型过滤', async () => { const response = await client['company-videos'].$get({ query: { companyId: testCompany.id.toString(), assetType: AssetType.CHECKIN_VIDEO } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.data[0].assetType).toBe(AssetType.CHECKIN_VIDEO); } }); it('应该支持分页查询', async () => { const response = await client['company-videos'].$get({ query: { companyId: testCompany.id.toString(), page: '1', pageSize: '2' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(2); expect(data.total).toBe(3); } }); it('应该支持按关联时间排序', async () => { const response = await client['company-videos'].$get({ query: { companyId: testCompany.id.toString(), sortBy: 'relatedTime', sortOrder: 'ASC' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(3); // 验证排序:relatedTime 最早的应该在第一个 const firstDate = new Date(data.data[0].relatedTime).getTime(); const lastDate = new Date(data.data[2].relatedTime).getTime(); expect(firstDate).toBeLessThan(lastDate); } }); it('应该验证企业ID必填', async () => { const response = await client['company-videos'].$get({ query: {} }, { headers: { 'Authorization': `Bearer ${testToken}` } }); // 由于token中包含companyId,即使查询参数中没有companyId,API也能从token中获取 // 所以应该返回200而不是400 expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data).toHaveProperty('data'); expect(data).toHaveProperty('total'); } }); it('应该验证企业ID有效性', async () => { const response = await client['company-videos'].$get({ query: { companyId: '999999' // 不存在的企业ID } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); // 注意:API可能会返回空列表而不是错误 // 根据实际实现,可能返回200且空列表,或返回404 // 这里我们假设返回200且空列表 expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(0); expect(data.total).toBe(0); } }); }); describe('POST /order/batch-download', () => { it('应该成功批量下载企业维度视频', async () => { const requestData = { downloadScope: DownloadScope.COMPANY, companyId: testCompany.id, assetTypes: [AssetType.CHECKIN_VIDEO, AssetType.WORK_VIDEO] }; const response = await client['batch-download'].$post({ json: requestData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); expect(data.message).toContain('批量下载成功'); expect(data.files).toHaveLength(2); // CHECKIN_VIDEO 和 WORK_VIDEO expect(data.totalFiles).toBe(2); // 验证文件项结构 const fileItem = data.files[0]; expect(fileItem).toHaveProperty('id'); expect(fileItem).toHaveProperty('name'); expect(fileItem).toHaveProperty('size'); expect(fileItem).toHaveProperty('url'); expect(fileItem).toHaveProperty('assetType'); expect(fileItem).toHaveProperty('orderId'); expect(fileItem).toHaveProperty('personId'); expect(fileItem).toHaveProperty('relatedTime'); } }); it('应该成功批量下载个人维度视频', async () => { const requestData = { downloadScope: DownloadScope.PERSON, companyId: testCompany.id, personId: testOrderPerson.personId, assetTypes: [AssetType.CHECKIN_VIDEO] }; const response = await client['batch-download'].$post({ json: requestData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); expect(data.files).toHaveLength(1); expect(data.files[0].assetType).toBe(AssetType.CHECKIN_VIDEO); } }); it('应该验证个人维度下载需要personId', async () => { const requestData = { downloadScope: DownloadScope.PERSON, companyId: testCompany.id // 缺少personId }; const response = await client['batch-download'].$post({ json: requestData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该支持指定文件ID列表下载', async () => { // 获取测试视频资产的文件ID const fileIds = [testFile.id]; const requestData = { downloadScope: DownloadScope.COMPANY, companyId: testCompany.id, fileIds: fileIds }; const response = await client['batch-download'].$post({ json: requestData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); // 3个视频资产都使用同一个文件ID,所以应该返回3个文件项 expect(data.files).toHaveLength(3); // 所有文件项的id都应该是指定的文件ID data.files.forEach((fileItem: any) => { expect(fileItem.id).toBe(fileIds[0]); }); } }); it('应该处理没有符合条件的视频文件', async () => { const requestData = { downloadScope: DownloadScope.COMPANY, companyId: 999999, // 不存在的企业 assetTypes: [AssetType.CHECKIN_VIDEO] }; const response = await client['batch-download'].$post({ json: requestData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); expect(data.files).toHaveLength(0); expect(data.totalFiles).toBe(0); expect(data.message).toContain('未找到符合条件的视频文件'); } }); }); describe('PUT /order/videos/{id}/status', () => { it('应该成功更新视频审核状态', async () => { const testAsset = testVideoAssets[0]; const requestData = { status: AssetStatus.VERIFIED as const }; const response = await client.videos[':id'].status.$put({ param: { id: testAsset.id.toString() }, json: requestData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.id).toBe(testAsset.id); expect(data.status).toBe('verified'); // 验证数据库中的状态已更新 const dataSource = await IntegrationTestDatabase.getDataSource(); const assetRepository = dataSource.getRepository(OrderPersonAsset); const updatedAsset = await assetRepository.findOne({ where: { id: testAsset.id } }); expect(updatedAsset?.status).toBe('verified'); } }); it('应该支持更新状态为已拒绝', async () => { const testAsset = testVideoAssets[1]; // 当前是verified const requestData = { status: AssetStatus.REJECTED as const }; const response = await client.videos[':id'].status.$put({ param: { id: testAsset.id.toString() }, json: requestData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.status).toBe('rejected'); } }); it('应该处理不存在的视频资产ID', async () => { const requestData = { status: AssetStatus.VERIFIED as const }; const response = await client.videos[':id'].status.$put({ param: { id: '999999' }, json: requestData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); it('应该验证状态值的有效性', async () => { const testAsset = testVideoAssets[0]; const requestData = { status: 'invalid_status' as any // 无效的状态 }; const response = await client.videos[':id'].status.$put({ param: { id: testAsset.id.toString() }, json: requestData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该支持状态更新为待审核', async () => { const testAsset = testVideoAssets[2]; // 当前是rejected const requestData = { status: AssetStatus.PENDING as const }; const response = await client.videos[':id'].status.$put({ param: { id: testAsset.id.toString() }, json: requestData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.status).toBe('pending'); } }); }); }); });