order.integration.test.ts 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624
  1. import { describe, it, expect, beforeEach } from 'vitest';
  2. import { testClient } from 'hono/testing';
  3. import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util';
  4. import { JWTUtil } from '@d8d/shared-utils';
  5. import { JWTPayload } from '@d8d/shared-types';
  6. import { UserEntity, Role } from '@d8d/user-module';
  7. import { File } from '@d8d/file-module';
  8. import { DisabledPerson, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit } from '@d8d/allin-disability-module';
  9. import { BankName } from '@d8d/bank-names-module';
  10. import { Company } from '@d8d/allin-company-module/entities';
  11. import { Platform } from '@d8d/allin-platform-module';
  12. import { DataSource } from 'typeorm';
  13. import orderRoutes, { enterpriseOrderRoutes } from '../../src/routes/order.routes';
  14. import { EmploymentOrder } from '../../src/entities/employment-order.entity';
  15. import { OrderPerson } from '../../src/entities/order-person.entity';
  16. import { OrderPersonAsset } from '../../src/entities/order-person-asset.entity';
  17. import { AssetType, AssetFileType, AssetStatus, DownloadScope } from '../../src/schemas/order.schema';
  18. import { OrderStatus, WorkStatus } from '@d8d/allin-enums';
  19. import { OrderTestDataFactory } from '../utils/test-data-factory';
  20. // 设置集成测试钩子
  21. setupIntegrationDatabaseHooksWithEntities([UserEntity, File, Role, Platform, Company, DisabledPerson, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit, BankName, EmploymentOrder, OrderPerson, OrderPersonAsset])
  22. describe('订单管理API集成测试', () => {
  23. let client: ReturnType<typeof testClient<typeof orderRoutes>>;
  24. let enterpriseClient: ReturnType<typeof testClient<typeof enterpriseOrderRoutes>>;
  25. let testToken: string;
  26. let testUser: UserEntity;
  27. let testFile: File;
  28. let testDisabledPerson: DisabledPerson;
  29. beforeEach(async () => {
  30. // 创建测试客户端
  31. client = testClient(orderRoutes);
  32. enterpriseClient = testClient(enterpriseOrderRoutes);
  33. // 获取数据源
  34. const dataSource = await IntegrationTestDatabase.getDataSource();
  35. // 创建测试用户
  36. const userRepository = dataSource.getRepository(UserEntity);
  37. testUser = userRepository.create({
  38. username: `test_user_${Date.now()}`,
  39. password: 'test_password',
  40. nickname: '测试用户',
  41. registrationSource: 'web'
  42. });
  43. await userRepository.save(testUser);
  44. // 生成测试用户的token
  45. testToken = JWTUtil.generateToken({
  46. id: testUser.id,
  47. username: testUser.username,
  48. roles: [{name:'user'}]
  49. });
  50. // 创建测试文件
  51. const fileRepository = dataSource.getRepository(File);
  52. testFile = fileRepository.create({
  53. name: 'test_file.pdf',
  54. type: 'application/pdf',
  55. size: 1024,
  56. path: `test/${Date.now()}_test_file.pdf`,
  57. uploadUserId: testUser.id,
  58. uploadTime: new Date(),
  59. createdAt: new Date(),
  60. updatedAt: new Date()
  61. });
  62. await fileRepository.save(testFile);
  63. // 创建测试银行名称记录(用于DisabledBankCard外键约束)
  64. const bankNameRepository = dataSource.getRepository(BankName);
  65. const testBankName = bankNameRepository.create({
  66. name: '测试银行',
  67. code: 'TEST001',
  68. remark: '测试银行',
  69. createdBy: testUser.id,
  70. updatedBy: testUser.id,
  71. status: 1
  72. });
  73. await bankNameRepository.save(testBankName);
  74. // 创建测试残疾人记录(用于外键约束)
  75. testDisabledPerson = await OrderTestDataFactory.createTestDisabledPerson(dataSource);
  76. });
  77. describe('POST /order/create', () => {
  78. it('应该成功创建订单', async () => {
  79. const createData = {
  80. orderName: '测试订单',
  81. platformId: 1,
  82. companyId: 1,
  83. channelId: 1,
  84. expectedStartDate: new Date().toISOString(),
  85. orderStatus: OrderStatus.DRAFT,
  86. workStatus: WorkStatus.NOT_WORKING
  87. };
  88. const response = await client.create.$post({
  89. json: createData
  90. }, {
  91. headers: {
  92. 'Authorization': `Bearer ${testToken}`
  93. }
  94. });
  95. if (response.status !== 200) {
  96. const error = await response.json();
  97. console.debug('创建订单失败:', JSON.stringify(error, null, 2));
  98. }
  99. expect(response.status).toBe(200);
  100. if (response.status === 200) {
  101. const data = await response.json();
  102. expect(data.id).toBeDefined();
  103. expect(data.orderName).toBe('测试订单');
  104. expect(data.orderStatus).toBe(OrderStatus.DRAFT);
  105. expect(data.workStatus).toBe(WorkStatus.NOT_WORKING);
  106. }
  107. });
  108. it('应该验证订单状态枚举值', async () => {
  109. const createData = {
  110. orderName: '测试订单',
  111. platformId: 1,
  112. companyId: 1,
  113. channelId: 1,
  114. expectedStartDate: new Date().toISOString(),
  115. orderStatus: 'invalid_status', // 无效的状态
  116. workStatus: WorkStatus.NOT_WORKING
  117. };
  118. const response = await client.create.$post({
  119. json: createData as any // 使用any绕过类型检查,因为这里故意测试无效的枚举值
  120. }, {
  121. headers: {
  122. 'Authorization': `Bearer ${testToken}`
  123. }
  124. });
  125. expect(response.status).toBe(400);
  126. });
  127. it('应该验证工作状态枚举值', async () => {
  128. const createData = {
  129. orderName: '测试订单',
  130. platformId: 1,
  131. companyId: 1,
  132. channelId: 1,
  133. expectedStartDate: new Date().toISOString(),
  134. orderStatus: OrderStatus.DRAFT,
  135. workStatus: 'invalid_status' // 无效的状态
  136. };
  137. const response = await client.create.$post({
  138. json: createData as any // 使用any绕过类型检查,因为这里故意测试无效的枚举值
  139. }, {
  140. headers: {
  141. 'Authorization': `Bearer ${testToken}`
  142. }
  143. });
  144. expect(response.status).toBe(400);
  145. });
  146. });
  147. describe('GET /order/list', () => {
  148. let testOrder: EmploymentOrder;
  149. beforeEach(async () => {
  150. // 创建测试订单数据
  151. const dataSource = await IntegrationTestDatabase.getDataSource();
  152. const orderRepository = dataSource.getRepository(EmploymentOrder);
  153. testOrder = new EmploymentOrder({
  154. orderName: '测试订单1',
  155. platformId: 1,
  156. companyId: 1,
  157. channelId: 1,
  158. expectedStartDate: new Date(),
  159. orderStatus: OrderStatus.DRAFT,
  160. workStatus: WorkStatus.NOT_WORKING
  161. });
  162. await orderRepository.save(testOrder);
  163. const testOrder2 = new EmploymentOrder({
  164. orderName: '测试订单2',
  165. platformId: 2,
  166. companyId: 2,
  167. channelId: 2,
  168. expectedStartDate: new Date(),
  169. orderStatus: OrderStatus.CONFIRMED,
  170. workStatus: WorkStatus.PRE_WORKING
  171. });
  172. await orderRepository.save(testOrder2);
  173. });
  174. it('应该返回所有订单列表', async () => {
  175. const response = await client.list.$get({
  176. query: {}
  177. }, {
  178. headers: {
  179. 'Authorization': `Bearer ${testToken}`
  180. }
  181. });
  182. expect(response.status).toBe(200);
  183. if (response.status === 200) {
  184. const data = await response.json();
  185. expect(data).toHaveProperty('data');
  186. expect(data).toHaveProperty('total');
  187. expect(data.data).toHaveLength(2);
  188. expect(data.total).toBe(2);
  189. }
  190. });
  191. it('应该支持按订单名称搜索', async () => {
  192. const response = await client.list.$get({
  193. query: {
  194. orderName: '测试订单1'
  195. }
  196. }, {
  197. headers: {
  198. 'Authorization': `Bearer ${testToken}`
  199. }
  200. });
  201. expect(response.status).toBe(200);
  202. if (response.status === 200) {
  203. const data = await response.json();
  204. expect(data.data).toHaveLength(1);
  205. expect(data.data[0].orderName).toBe('测试订单1');
  206. }
  207. });
  208. it('应该支持按订单状态过滤', async () => {
  209. const response = await client.list.$get({
  210. query: {
  211. orderStatus: OrderStatus.CONFIRMED
  212. }
  213. }, {
  214. headers: {
  215. 'Authorization': `Bearer ${testToken}`
  216. }
  217. });
  218. expect(response.status).toBe(200);
  219. if (response.status === 200) {
  220. const data = await response.json();
  221. expect(data.data).toHaveLength(1);
  222. expect(data.data[0].orderStatus).toBe(OrderStatus.CONFIRMED);
  223. }
  224. });
  225. it('应该支持分页查询', async () => {
  226. const response = await client.list.$get({
  227. query: {
  228. page: '1',
  229. limit: '1'
  230. }
  231. }, {
  232. headers: {
  233. 'Authorization': `Bearer ${testToken}`
  234. }
  235. });
  236. expect(response.status).toBe(200);
  237. if (response.status === 200) {
  238. const data = await response.json();
  239. expect(data.data).toHaveLength(1);
  240. expect(data.total).toBe(2);
  241. }
  242. });
  243. });
  244. describe('GET /order/detail/:id', () => {
  245. let testOrder: EmploymentOrder;
  246. beforeEach(async () => {
  247. // 创建测试订单数据
  248. const dataSource = await IntegrationTestDatabase.getDataSource();
  249. const orderRepository = dataSource.getRepository(EmploymentOrder);
  250. testOrder = new EmploymentOrder({
  251. orderName: '测试订单详情',
  252. platformId: 1,
  253. companyId: 1,
  254. channelId: 1,
  255. expectedStartDate: new Date(),
  256. orderStatus: OrderStatus.DRAFT,
  257. workStatus: WorkStatus.NOT_WORKING
  258. });
  259. await orderRepository.save(testOrder);
  260. });
  261. it('应该返回指定ID的订单详情', async () => {
  262. const response = await client.detail[':id'].$get({
  263. param: { id: testOrder.id.toString() }
  264. }, {
  265. headers: {
  266. 'Authorization': `Bearer ${testToken}`
  267. }
  268. });
  269. if (response.status !== 200) {
  270. const error = await response.json();
  271. console.debug('获取订单详情失败:', JSON.stringify(error, null, 2));
  272. }
  273. expect(response.status).toBe(200);
  274. if (response.status === 200) {
  275. const data = await response.json();
  276. expect(data?.id).toBe(testOrder.id);
  277. expect(data?.orderName).toBe('测试订单详情');
  278. expect(data?.orderStatus).toBe(OrderStatus.DRAFT);
  279. }
  280. });
  281. it('应该处理不存在的订单ID', async () => {
  282. const response = await client.detail[':id'].$get({
  283. param: { id: '999999' }
  284. }, {
  285. headers: {
  286. 'Authorization': `Bearer ${testToken}`
  287. }
  288. });
  289. expect(response.status).toBe(404);
  290. });
  291. });
  292. describe('POST /order/activate/:orderId', () => {
  293. let testOrder: EmploymentOrder;
  294. beforeEach(async () => {
  295. // 创建测试订单数据
  296. const dataSource = await IntegrationTestDatabase.getDataSource();
  297. const orderRepository = dataSource.getRepository(EmploymentOrder);
  298. testOrder = new EmploymentOrder({
  299. orderName: '待激活订单',
  300. platformId: 1,
  301. companyId: 1,
  302. channelId: 1,
  303. expectedStartDate: new Date(),
  304. orderStatus: OrderStatus.DRAFT,
  305. workStatus: WorkStatus.NOT_WORKING
  306. });
  307. await orderRepository.save(testOrder);
  308. });
  309. it('应该成功激活草稿状态的订单', async () => {
  310. const response = await client.activate[':orderId'].$post({
  311. param: { orderId: testOrder.id.toString() }
  312. }, {
  313. headers: {
  314. 'Authorization': `Bearer ${testToken}`
  315. }
  316. });
  317. expect(response.status).toBe(200);
  318. if (response.status === 200) {
  319. const data = await response.json();
  320. expect(data.success).toBe(true);
  321. // 验证订单状态已更新
  322. const dataSource = await IntegrationTestDatabase.getDataSource();
  323. const orderRepository = dataSource.getRepository(EmploymentOrder);
  324. const updatedOrder = await orderRepository.findOne({
  325. where: { id: testOrder.id }
  326. });
  327. expect(updatedOrder?.orderStatus).toBe(OrderStatus.CONFIRMED);
  328. expect(updatedOrder?.actualStartDate).toBeDefined();
  329. }
  330. });
  331. it('应该处理非草稿状态的订单激活', async () => {
  332. // 更新订单状态为已确认
  333. const dataSource = await IntegrationTestDatabase.getDataSource();
  334. const orderRepository = dataSource.getRepository(EmploymentOrder);
  335. await orderRepository.update(testOrder.id, { orderStatus: OrderStatus.CONFIRMED });
  336. const response = await client.activate[':orderId'].$post({
  337. param: { orderId: testOrder.id.toString() }
  338. }, {
  339. headers: {
  340. 'Authorization': `Bearer ${testToken}`
  341. }
  342. });
  343. expect(response.status).toBe(400);
  344. });
  345. it('应该处理不存在的订单ID', async () => {
  346. const response = await client.activate[':orderId'].$post({
  347. param: { orderId: '999999' }
  348. }, {
  349. headers: {
  350. 'Authorization': `Bearer ${testToken}`
  351. }
  352. });
  353. expect(response.status).toBe(404);
  354. });
  355. });
  356. describe('POST /order/close/:orderId', () => {
  357. let testOrder: EmploymentOrder;
  358. beforeEach(async () => {
  359. // 创建测试订单数据
  360. const dataSource = await IntegrationTestDatabase.getDataSource();
  361. const orderRepository = dataSource.getRepository(EmploymentOrder);
  362. testOrder = new EmploymentOrder({
  363. orderName: '待关闭订单',
  364. platformId: 1,
  365. companyId: 1,
  366. channelId: 1,
  367. expectedStartDate: new Date(),
  368. actualStartDate: new Date(),
  369. orderStatus: OrderStatus.CONFIRMED,
  370. workStatus: WorkStatus.PRE_WORKING,
  371. });
  372. await orderRepository.save(testOrder);
  373. });
  374. it('应该成功关闭已确认状态的订单', async () => {
  375. const response = await client.close[':orderId'].$post({
  376. param: { orderId: testOrder.id.toString() }
  377. }, {
  378. headers: {
  379. 'Authorization': `Bearer ${testToken}`
  380. }
  381. });
  382. expect(response.status).toBe(200);
  383. if (response.status === 200) {
  384. const data = await response.json();
  385. expect(data.success).toBe(true);
  386. // 验证订单状态已更新
  387. const dataSource = await IntegrationTestDatabase.getDataSource();
  388. const orderRepository = dataSource.getRepository(EmploymentOrder);
  389. const updatedOrder = await orderRepository.findOne({
  390. where: { id: testOrder.id }
  391. });
  392. expect(updatedOrder?.orderStatus).toBe(OrderStatus.COMPLETED);
  393. expect(updatedOrder?.actualEndDate).toBeDefined();
  394. }
  395. });
  396. it('应该处理非已确认或进行中状态的订单关闭', async () => {
  397. // 更新订单状态为草稿
  398. const dataSource = await IntegrationTestDatabase.getDataSource();
  399. const orderRepository = dataSource.getRepository(EmploymentOrder);
  400. await orderRepository.update(testOrder.id, { orderStatus: OrderStatus.DRAFT });
  401. const response = await client.close[':orderId'].$post({
  402. param: { orderId: testOrder.id.toString() }
  403. }, {
  404. headers: {
  405. 'Authorization': `Bearer ${testToken}`
  406. }
  407. });
  408. expect(response.status).toBe(400);
  409. });
  410. it('应该处理不存在的订单ID', async () => {
  411. const response = await client.close[':orderId'].$post({
  412. param: { orderId: '999999' }
  413. }, {
  414. headers: {
  415. 'Authorization': `Bearer ${testToken}`
  416. }
  417. });
  418. expect(response.status).toBe(404);
  419. });
  420. });
  421. describe('POST /order/:orderId/persons/batch', () => {
  422. let testOrder: EmploymentOrder;
  423. beforeEach(async () => {
  424. // 创建测试订单数据
  425. const dataSource = await IntegrationTestDatabase.getDataSource();
  426. const orderRepository = dataSource.getRepository(EmploymentOrder);
  427. testOrder = new EmploymentOrder({
  428. orderName: '批量添加人员测试订单',
  429. platformId: 1,
  430. companyId: 1,
  431. channelId: 1,
  432. expectedStartDate: new Date(),
  433. orderStatus: OrderStatus.DRAFT,
  434. workStatus: WorkStatus.NOT_WORKING,
  435. });
  436. await orderRepository.save(testOrder);
  437. });
  438. it('应该成功批量添加人员到订单', async () => {
  439. // 创建两个测试残疾人记录
  440. const dataSource = await IntegrationTestDatabase.getDataSource();
  441. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  442. // 直接创建最简单的DisabledPerson记录
  443. const disabledPerson1 = disabledPersonRepository.create({
  444. name: '测试1',
  445. gender: '男',
  446. idCard: '1',
  447. disabilityId: '1',
  448. disabilityType: '肢体',
  449. disabilityLevel: '三级',
  450. idAddress: '地址',
  451. phone: '13800138000',
  452. canDirectContact: 1,
  453. province: '省',
  454. city: '市',
  455. district: '区',
  456. detailedAddress: '地址',
  457. isInBlackList: 0,
  458. jobStatus: 0,
  459. createTime: new Date(),
  460. updateTime: new Date()
  461. });
  462. await disabledPersonRepository.save(disabledPerson1);
  463. const disabledPerson2 = disabledPersonRepository.create({
  464. name: '测试2',
  465. gender: '女',
  466. idCard: '2',
  467. disabilityId: '2',
  468. disabilityType: '视力',
  469. disabilityLevel: '二级',
  470. idAddress: '地址',
  471. phone: '13800138001',
  472. canDirectContact: 1,
  473. province: '省',
  474. city: '市',
  475. district: '区',
  476. detailedAddress: '地址',
  477. isInBlackList: 0,
  478. jobStatus: 0,
  479. createTime: new Date(),
  480. updateTime: new Date()
  481. });
  482. await disabledPersonRepository.save(disabledPerson2);
  483. const batchData = {
  484. persons: [
  485. {
  486. personId: disabledPerson1.id,
  487. joinDate: new Date().toISOString(),
  488. salaryDetail: 5000.00
  489. },
  490. {
  491. personId: disabledPerson2.id,
  492. joinDate: new Date().toISOString(),
  493. salaryDetail: 6000.00
  494. }
  495. ]
  496. };
  497. const response = await client[':orderId'].persons.batch.$post({
  498. param: { orderId: testOrder.id.toString() },
  499. json: batchData
  500. }, {
  501. headers: {
  502. 'Authorization': `Bearer ${testToken}`
  503. }
  504. });
  505. expect(response.status).toBe(200);
  506. if (response.status === 200) {
  507. const data = await response.json();
  508. expect(data.success).toBe(true);
  509. expect(data.addedCount).toBe(2);
  510. // 验证人员已添加到订单
  511. const dataSource = await IntegrationTestDatabase.getDataSource();
  512. const orderPersonRepository = dataSource.getRepository(OrderPerson);
  513. const orderPersons = await orderPersonRepository.find({
  514. where: { orderId: testOrder.id }
  515. });
  516. expect(orderPersons).toHaveLength(2);
  517. }
  518. });
  519. it('应该处理重复的人员添加', async () => {
  520. // 创建两个测试残疾人记录
  521. const dataSource = await IntegrationTestDatabase.getDataSource();
  522. const [disabledPerson1, disabledPerson2] = await OrderTestDataFactory.createTestDisabledPersons(dataSource, 2);
  523. const orderPersonRepository = dataSource.getRepository(OrderPerson);
  524. // 先添加一个人员
  525. const existingPerson = orderPersonRepository.create({
  526. orderId: testOrder.id,
  527. personId: disabledPerson1.id,
  528. joinDate: new Date(),
  529. workStatus: WorkStatus.NOT_WORKING,
  530. salaryDetail: 5000.00
  531. });
  532. await orderPersonRepository.save(existingPerson);
  533. const batchData = {
  534. persons: [
  535. {
  536. personId: disabledPerson1.id, // 已存在的人员
  537. joinDate: new Date().toISOString(),
  538. salaryDetail: 5000.00
  539. },
  540. {
  541. personId: disabledPerson2.id, // 新人员
  542. joinDate: new Date().toISOString(),
  543. salaryDetail: 6000.00
  544. }
  545. ]
  546. };
  547. const response = await client[':orderId'].persons.batch.$post({
  548. param: { orderId: testOrder.id.toString() },
  549. json: batchData
  550. }, {
  551. headers: {
  552. 'Authorization': `Bearer ${testToken}`
  553. }
  554. });
  555. expect(response.status).toBe(200);
  556. if (response.status === 200) {
  557. const data = await response.json();
  558. expect(data.success).toBe(true);
  559. expect(data.addedCount).toBe(1); // 只添加了一个新人员
  560. }
  561. });
  562. it('应该处理已结束或已取消的订单', async () => {
  563. // 更新订单状态为已完成
  564. const dataSource = await IntegrationTestDatabase.getDataSource();
  565. const orderRepository = dataSource.getRepository(EmploymentOrder);
  566. await orderRepository.update(testOrder.id, { orderStatus: OrderStatus.COMPLETED });
  567. const batchData = {
  568. persons: [
  569. {
  570. personId: 1001,
  571. joinDate: new Date().toISOString(),
  572. salaryDetail: 5000.00
  573. }
  574. ]
  575. };
  576. const response = await client[':orderId'].persons.batch.$post({
  577. param: { orderId: testOrder.id.toString() },
  578. json: batchData
  579. }, {
  580. headers: {
  581. 'Authorization': `Bearer ${testToken}`
  582. }
  583. });
  584. expect(response.status).toBe(400);
  585. });
  586. it('应该处理不存在的订单ID', async () => {
  587. const batchData = {
  588. persons: [
  589. {
  590. personId: 1001,
  591. joinDate: new Date().toISOString(),
  592. salaryDetail: 5000.00
  593. }
  594. ]
  595. };
  596. const response = await client[':orderId'].persons.batch.$post({
  597. param: { orderId: '999999' },
  598. json: batchData
  599. }, {
  600. headers: {
  601. 'Authorization': `Bearer ${testToken}`
  602. }
  603. });
  604. expect(response.status).toBe(404);
  605. });
  606. });
  607. describe('POST /order/assets/create', () => {
  608. let testOrder: EmploymentOrder;
  609. let testOrderPerson: OrderPerson;
  610. beforeEach(async () => {
  611. // 创建测试订单数据
  612. const dataSource = await IntegrationTestDatabase.getDataSource();
  613. const orderRepository = dataSource.getRepository(EmploymentOrder);
  614. const orderPersonRepository = dataSource.getRepository(OrderPerson);
  615. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  616. testOrder = new EmploymentOrder({
  617. orderName: '资产测试订单',
  618. platformId: 1,
  619. companyId: 1,
  620. channelId: 1,
  621. expectedStartDate: new Date(),
  622. orderStatus: OrderStatus.DRAFT,
  623. workStatus: WorkStatus.NOT_WORKING,
  624. });
  625. await orderRepository.save(testOrder);
  626. // 先创建残疾人记录
  627. const testDisabledPerson = await OrderTestDataFactory.createTestDisabledPerson(dataSource);
  628. testOrderPerson = orderPersonRepository.create({
  629. orderId: testOrder.id,
  630. personId: testDisabledPerson.id,
  631. joinDate: new Date(),
  632. workStatus: WorkStatus.NOT_WORKING,
  633. salaryDetail: 5000.00
  634. });
  635. await orderPersonRepository.save(testOrderPerson);
  636. });
  637. it('应该成功创建订单人员资产', async () => {
  638. const assetData = {
  639. orderId: testOrder.id,
  640. personId: testOrderPerson.personId,
  641. assetType: AssetType.DISABILITY_CERT,
  642. assetFileType: AssetFileType.IMAGE,
  643. fileId: testFile.id,
  644. relatedTime: new Date().toISOString()
  645. };
  646. const response = await client.assets.create.$post({
  647. json: assetData
  648. }, {
  649. headers: {
  650. 'Authorization': `Bearer ${testToken}`
  651. }
  652. });
  653. if (response.status !== 200) {
  654. const error = await response.json();
  655. console.debug('创建订单人员资产失败:', JSON.stringify(error, null, 2));
  656. }
  657. expect(response.status).toBe(200);
  658. if (response.status === 200) {
  659. const data = await response.json();
  660. expect(data.id).toBeDefined();
  661. expect(data.orderId).toBe(testOrder.id);
  662. expect(data.personId).toBe(testOrderPerson.personId);
  663. expect(data.assetType).toBe(AssetType.DISABILITY_CERT);
  664. expect(data.fileId).toBe(testFile.id);
  665. }
  666. });
  667. it('应该处理不存在的文件ID', async () => {
  668. const assetData = {
  669. orderId: testOrder.id,
  670. personId: testOrderPerson.personId,
  671. assetType: AssetType.DISABILITY_CERT,
  672. assetFileType: AssetFileType.IMAGE,
  673. fileId: 999999, // 不存在的文件ID
  674. relatedTime: new Date().toISOString()
  675. };
  676. const response = await client.assets.create.$post({
  677. json: assetData
  678. }, {
  679. headers: {
  680. 'Authorization': `Bearer ${testToken}`
  681. }
  682. });
  683. expect(response.status).toBe(400);
  684. });
  685. it('应该处理人员不在订单中的情况', async () => {
  686. const assetData = {
  687. orderId: testOrder.id,
  688. personId: 999999, // 不在订单中的人员
  689. assetType: AssetType.DISABILITY_CERT,
  690. assetFileType: AssetFileType.IMAGE,
  691. fileId: testFile.id,
  692. relatedTime: new Date().toISOString()
  693. };
  694. const response = await client.assets.create.$post({
  695. json: assetData
  696. }, {
  697. headers: {
  698. 'Authorization': `Bearer ${testToken}`
  699. }
  700. });
  701. expect(response.status).toBe(404);
  702. });
  703. });
  704. describe('GET /order/assets/query', () => {
  705. let testOrder: EmploymentOrder;
  706. let testOrderPerson: OrderPerson;
  707. let testAsset: OrderPersonAsset;
  708. beforeEach(async () => {
  709. // 创建测试数据
  710. const dataSource = await IntegrationTestDatabase.getDataSource();
  711. const orderRepository = dataSource.getRepository(EmploymentOrder);
  712. const orderPersonRepository = dataSource.getRepository(OrderPerson);
  713. const assetRepository = dataSource.getRepository(OrderPersonAsset);
  714. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  715. testOrder = new EmploymentOrder({
  716. orderName: '资产查询测试订单',
  717. platformId: 1,
  718. companyId: 1,
  719. channelId: 1,
  720. expectedStartDate: new Date(),
  721. orderStatus: OrderStatus.DRAFT,
  722. workStatus: WorkStatus.NOT_WORKING,
  723. });
  724. await orderRepository.save(testOrder);
  725. // 先创建残疾人记录
  726. const testDisabledPerson = await OrderTestDataFactory.createTestDisabledPerson(dataSource);
  727. testOrderPerson = orderPersonRepository.create({
  728. orderId: testOrder.id,
  729. personId: testDisabledPerson.id,
  730. joinDate: new Date(),
  731. workStatus: WorkStatus.NOT_WORKING,
  732. salaryDetail: 5000.00
  733. });
  734. await orderPersonRepository.save(testOrderPerson);
  735. testAsset = new OrderPersonAsset({
  736. orderId: testOrder.id,
  737. personId: testOrderPerson.personId,
  738. assetType: AssetType.DISABILITY_CERT,
  739. assetFileType: AssetFileType.IMAGE,
  740. fileId: testFile.id,
  741. relatedTime: new Date()
  742. });
  743. await assetRepository.save(testAsset);
  744. // 创建第二个资产
  745. const testAsset2 = new OrderPersonAsset({
  746. orderId: testOrder.id,
  747. personId: testOrderPerson.personId,
  748. assetType: AssetType.OTHER,
  749. assetFileType: AssetFileType.IMAGE,
  750. fileId: testFile.id,
  751. relatedTime: new Date()
  752. });
  753. await assetRepository.save(testAsset2);
  754. });
  755. it('应该查询所有订单人员资产', async () => {
  756. const response = await client.assets.query.$get({
  757. query: {}
  758. }, {
  759. headers: {
  760. 'Authorization': `Bearer ${testToken}`
  761. }
  762. });
  763. expect(response.status).toBe(200);
  764. if (response.status === 200) {
  765. const data = await response.json();
  766. expect(data).toHaveProperty('data');
  767. expect(data).toHaveProperty('total');
  768. expect(data.data).toHaveLength(2);
  769. expect(data.total).toBe(2);
  770. }
  771. });
  772. it('应该支持按订单ID查询', async () => {
  773. const response = await client.assets.query.$get({
  774. query: {
  775. orderId: testOrder.id.toString()
  776. }
  777. }, {
  778. headers: {
  779. 'Authorization': `Bearer ${testToken}`
  780. }
  781. });
  782. expect(response.status).toBe(200);
  783. if (response.status === 200) {
  784. const data = await response.json();
  785. expect(data.data).toHaveLength(2);
  786. expect(data.data[0].orderId).toBe(testOrder.id);
  787. }
  788. });
  789. it('应该支持按人员ID查询', async () => {
  790. const response = await client.assets.query.$get({
  791. query: {
  792. personId: testOrderPerson.personId.toString()
  793. }
  794. }, {
  795. headers: {
  796. 'Authorization': `Bearer ${testToken}`
  797. }
  798. });
  799. expect(response.status).toBe(200);
  800. if (response.status === 200) {
  801. const data = await response.json();
  802. expect(data.data).toHaveLength(2);
  803. expect(data.data[0].personId).toBe(testOrderPerson.personId);
  804. }
  805. });
  806. it('应该支持按资产类型查询', async () => {
  807. const response = await client.assets.query.$get({
  808. query: {
  809. assetType: AssetType.DISABILITY_CERT
  810. }
  811. }, {
  812. headers: {
  813. 'Authorization': `Bearer ${testToken}`
  814. }
  815. });
  816. expect(response.status).toBe(200);
  817. if (response.status === 200) {
  818. const data = await response.json();
  819. expect(data.data).toHaveLength(1);
  820. expect(data.data[0].assetType).toBe(AssetType.DISABILITY_CERT);
  821. }
  822. });
  823. it('应该支持分页查询', async () => {
  824. const response = await client.assets.query.$get({
  825. query: {
  826. page: '1',
  827. limit: '1'
  828. }
  829. }, {
  830. headers: {
  831. 'Authorization': `Bearer ${testToken}`
  832. }
  833. });
  834. expect(response.status).toBe(200);
  835. if (response.status === 200) {
  836. const data = await response.json();
  837. expect(data.data).toHaveLength(1);
  838. expect(data.total).toBe(2);
  839. }
  840. });
  841. });
  842. describe('DELETE /order/assets/delete/:id', () => {
  843. let testAsset: OrderPersonAsset;
  844. beforeEach(async () => {
  845. // 创建测试数据
  846. const dataSource = await IntegrationTestDatabase.getDataSource();
  847. const orderRepository = dataSource.getRepository(EmploymentOrder);
  848. const orderPersonRepository = dataSource.getRepository(OrderPerson);
  849. const assetRepository = dataSource.getRepository(OrderPersonAsset);
  850. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  851. const testOrder = new EmploymentOrder({
  852. orderName: '资产删除测试订单',
  853. platformId: 1,
  854. companyId: 1,
  855. channelId: 1,
  856. expectedStartDate: new Date(),
  857. orderStatus: OrderStatus.DRAFT,
  858. workStatus: WorkStatus.NOT_WORKING,
  859. });
  860. await orderRepository.save(testOrder);
  861. // 先创建残疾人记录
  862. const testDisabledPerson = await OrderTestDataFactory.createTestDisabledPerson(dataSource);
  863. const testOrderPerson = orderPersonRepository.create({
  864. orderId: testOrder.id,
  865. personId: testDisabledPerson.id,
  866. joinDate: new Date(),
  867. workStatus: WorkStatus.NOT_WORKING,
  868. salaryDetail: 5000.00
  869. });
  870. await orderPersonRepository.save(testOrderPerson);
  871. testAsset = new OrderPersonAsset({
  872. orderId: testOrder.id,
  873. personId: testOrderPerson.personId,
  874. assetType: AssetType.DISABILITY_CERT,
  875. assetFileType: AssetFileType.IMAGE,
  876. fileId: testFile.id,
  877. relatedTime: new Date()
  878. });
  879. await assetRepository.save(testAsset);
  880. });
  881. it('应该成功删除订单人员资产', async () => {
  882. const response = await client.assets.delete[':id'].$delete({
  883. param: { id: testAsset.id.toString() }
  884. }, {
  885. headers: {
  886. 'Authorization': `Bearer ${testToken}`
  887. }
  888. });
  889. expect(response.status).toBe(200);
  890. if (response.status === 200) {
  891. const data = await response.json();
  892. expect(data.success).toBe(true);
  893. // 验证资产已删除
  894. const dataSource = await IntegrationTestDatabase.getDataSource();
  895. const assetRepository = dataSource.getRepository(OrderPersonAsset);
  896. const deletedAsset = await assetRepository.findOne({
  897. where: { id: testAsset.id }
  898. });
  899. expect(deletedAsset).toBeNull();
  900. }
  901. });
  902. it('应该处理不存在的资产ID', async () => {
  903. const response = await client.assets.delete[':id'].$delete({
  904. param: { id: '999999' }
  905. }, {
  906. headers: {
  907. 'Authorization': `Bearer ${testToken}`
  908. }
  909. });
  910. expect(response.status).toBe(404);
  911. });
  912. });
  913. describe('认证测试', () => {
  914. it('应该要求认证', async () => {
  915. const response = await client.list.$get({
  916. query: {}
  917. // 不提供Authorization header
  918. });
  919. expect(response.status).toBe(401);
  920. });
  921. it('应该验证无效token', async () => {
  922. const response = await client.list.$get({
  923. query: {}
  924. }, {
  925. headers: {
  926. 'Authorization': 'Bearer invalid_token'
  927. }
  928. });
  929. expect(response.status).toBe(401);
  930. });
  931. });
  932. describe('订单统计API测试', () => {
  933. let testCompany: Company;
  934. beforeEach(async () => {
  935. // 创建测试公司
  936. const dataSource = await IntegrationTestDatabase.getDataSource();
  937. const companyRepository = dataSource.getRepository(Company);
  938. testCompany = companyRepository.create({
  939. companyName: '统计测试公司',
  940. contactPerson: '测试联系人',
  941. contactPhone: '13800138000',
  942. status: 1
  943. });
  944. await companyRepository.save(testCompany);
  945. });
  946. describe('GET /order/checkin-statistics', () => {
  947. it('应该返回正确的打卡视频数量统计', async () => {
  948. // 测试实现待补充
  949. expect(true).toBe(true);
  950. });
  951. });
  952. describe('GET /order/video-statistics', () => {
  953. it('应该按类型分类返回视频统计结果', async () => {
  954. // 测试实现待补充
  955. expect(true).toBe(true);
  956. });
  957. });
  958. describe('GET /order/company-orders', () => {
  959. it('应该支持按企业ID过滤,返回完整订单信息', async () => {
  960. // 测试实现待补充
  961. expect(true).toBe(true);
  962. });
  963. });
  964. });
  965. describe('企业维度视频管理API测试', () => {
  966. let testCompany: Company;
  967. let testOrder: EmploymentOrder;
  968. let testOrderPerson: OrderPerson;
  969. let testVideoAssets: OrderPersonAsset[];
  970. beforeEach(async () => {
  971. // 创建测试公司
  972. const dataSource = await IntegrationTestDatabase.getDataSource();
  973. const companyRepository = dataSource.getRepository(Company);
  974. testCompany = companyRepository.create({
  975. companyName: '视频管理测试公司',
  976. contactPerson: '测试联系人',
  977. contactPhone: '13800138001',
  978. status: 1
  979. });
  980. await companyRepository.save(testCompany);
  981. // 为测试用户生成包含companyId的token,添加enterprise角色
  982. testToken = JWTUtil.generateToken({
  983. id: testUser.id,
  984. username: testUser.username,
  985. roles: [{name:'user'}, {name:'enterprise'}]
  986. }, { companyId: testCompany.id } as Partial<JWTPayload & { companyId: number }>);
  987. // 更新用户实体的companyId(如果字段存在)
  988. const userRepository = dataSource.getRepository(UserEntity);
  989. await userRepository.update(testUser.id, { companyId: testCompany.id } as any);
  990. // 创建测试订单
  991. const orderRepository = dataSource.getRepository(EmploymentOrder);
  992. testOrder = new EmploymentOrder({
  993. orderName: '视频管理测试订单',
  994. platformId: 1,
  995. companyId: testCompany.id,
  996. channelId: 1,
  997. expectedStartDate: new Date(),
  998. orderStatus: OrderStatus.DRAFT,
  999. workStatus: WorkStatus.NOT_WORKING,
  1000. });
  1001. await orderRepository.save(testOrder);
  1002. // 创建测试残疾人记录
  1003. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  1004. const testDisabledPerson = disabledPersonRepository.create({
  1005. name: '视频测试人员',
  1006. gender: '男',
  1007. idCard: '3',
  1008. disabilityId: '3',
  1009. disabilityType: '肢体',
  1010. disabilityLevel: '三级',
  1011. idAddress: '地址',
  1012. phone: '13800138002',
  1013. canDirectContact: 1,
  1014. province: '省',
  1015. city: '市',
  1016. district: '区',
  1017. detailedAddress: '地址',
  1018. isInBlackList: 0,
  1019. jobStatus: 0,
  1020. createTime: new Date(),
  1021. updateTime: new Date()
  1022. });
  1023. await disabledPersonRepository.save(testDisabledPerson);
  1024. // 创建订单人员关联
  1025. const orderPersonRepository = dataSource.getRepository(OrderPerson);
  1026. testOrderPerson = orderPersonRepository.create({
  1027. orderId: testOrder.id,
  1028. personId: testDisabledPerson.id,
  1029. joinDate: new Date(),
  1030. workStatus: WorkStatus.NOT_WORKING,
  1031. salaryDetail: 5000.00
  1032. });
  1033. await orderPersonRepository.save(testOrderPerson);
  1034. // 创建测试视频资产
  1035. const assetRepository = dataSource.getRepository(OrderPersonAsset);
  1036. testVideoAssets = [
  1037. new OrderPersonAsset({
  1038. orderId: testOrder.id,
  1039. personId: testOrderPerson.personId,
  1040. assetType: AssetType.CHECKIN_VIDEO,
  1041. assetFileType: AssetFileType.VIDEO,
  1042. fileId: testFile.id,
  1043. relatedTime: new Date(),
  1044. status: AssetStatus.PENDING
  1045. }),
  1046. new OrderPersonAsset({
  1047. orderId: testOrder.id,
  1048. personId: testOrderPerson.personId,
  1049. assetType: AssetType.WORK_VIDEO,
  1050. assetFileType: AssetFileType.VIDEO,
  1051. fileId: testFile.id,
  1052. relatedTime: new Date(Date.now() - 86400000), // 昨天
  1053. status: AssetStatus.VERIFIED
  1054. }),
  1055. new OrderPersonAsset({
  1056. orderId: testOrder.id,
  1057. personId: testOrderPerson.personId,
  1058. assetType: AssetType.SALARY_VIDEO,
  1059. assetFileType: AssetFileType.VIDEO,
  1060. fileId: testFile.id,
  1061. relatedTime: new Date(Date.now() - 172800000), // 前天
  1062. status: AssetStatus.REJECTED
  1063. })
  1064. ];
  1065. await assetRepository.save(testVideoAssets);
  1066. });
  1067. describe('GET /order/company-videos', () => {
  1068. it('应该返回企业维度视频列表', async () => {
  1069. const response = await enterpriseClient['company-videos'].$get({
  1070. query: {
  1071. companyId: testCompany.id.toString()
  1072. }
  1073. }, {
  1074. headers: {
  1075. 'Authorization': `Bearer ${testToken}`
  1076. }
  1077. });
  1078. expect(response.status).toBe(200);
  1079. if (response.status === 200) {
  1080. const data = await response.json();
  1081. expect(data).toHaveProperty('data');
  1082. expect(data).toHaveProperty('total');
  1083. expect(data.data).toHaveLength(3); // 应该返回所有视频
  1084. expect(data.total).toBe(3);
  1085. // 验证数据结构
  1086. expect(data.data[0]).toHaveProperty('id');
  1087. expect(data.data[0]).toHaveProperty('orderId');
  1088. expect(data.data[0]).toHaveProperty('personId');
  1089. expect(data.data[0]).toHaveProperty('assetType');
  1090. expect(data.data[0]).toHaveProperty('assetFileType');
  1091. expect(data.data[0]).toHaveProperty('file');
  1092. }
  1093. });
  1094. it('应该支持按视频类型过滤', async () => {
  1095. const response = await enterpriseClient['company-videos'].$get({
  1096. query: {
  1097. companyId: testCompany.id.toString(),
  1098. assetType: AssetType.CHECKIN_VIDEO
  1099. }
  1100. }, {
  1101. headers: {
  1102. 'Authorization': `Bearer ${testToken}`
  1103. }
  1104. });
  1105. expect(response.status).toBe(200);
  1106. if (response.status === 200) {
  1107. const data = await response.json();
  1108. expect(data.data).toHaveLength(1);
  1109. expect(data.data[0].assetType).toBe(AssetType.CHECKIN_VIDEO);
  1110. }
  1111. });
  1112. it('应该支持分页查询', async () => {
  1113. const response = await enterpriseClient['company-videos'].$get({
  1114. query: {
  1115. companyId: testCompany.id.toString(),
  1116. page: '1',
  1117. pageSize: '2'
  1118. }
  1119. }, {
  1120. headers: {
  1121. 'Authorization': `Bearer ${testToken}`
  1122. }
  1123. });
  1124. expect(response.status).toBe(200);
  1125. if (response.status === 200) {
  1126. const data = await response.json();
  1127. expect(data.data).toHaveLength(2);
  1128. expect(data.total).toBe(3);
  1129. }
  1130. });
  1131. it('应该支持按关联时间排序', async () => {
  1132. const response = await enterpriseClient['company-videos'].$get({
  1133. query: {
  1134. companyId: testCompany.id.toString(),
  1135. sortBy: 'relatedTime',
  1136. sortOrder: 'ASC'
  1137. }
  1138. }, {
  1139. headers: {
  1140. 'Authorization': `Bearer ${testToken}`
  1141. }
  1142. });
  1143. expect(response.status).toBe(200);
  1144. if (response.status === 200) {
  1145. const data = await response.json();
  1146. expect(data.data).toHaveLength(3);
  1147. // 验证排序:relatedTime 最早的应该在第一个
  1148. const firstDate = new Date(data.data[0].relatedTime).getTime();
  1149. const lastDate = new Date(data.data[2].relatedTime).getTime();
  1150. expect(firstDate).toBeLessThan(lastDate);
  1151. }
  1152. });
  1153. it('应该验证企业ID必填', async () => {
  1154. const response = await enterpriseClient['company-videos'].$get({
  1155. query: {}
  1156. }, {
  1157. headers: {
  1158. 'Authorization': `Bearer ${testToken}`
  1159. }
  1160. });
  1161. // 由于token中包含companyId,即使查询参数中没有companyId,API也能从token中获取
  1162. // 所以应该返回200而不是400
  1163. expect(response.status).toBe(200);
  1164. if (response.status === 200) {
  1165. const data = await response.json();
  1166. expect(data).toHaveProperty('data');
  1167. expect(data).toHaveProperty('total');
  1168. }
  1169. });
  1170. it('应该验证企业ID有效性', async () => {
  1171. const response = await enterpriseClient['company-videos'].$get({
  1172. query: {
  1173. companyId: '999999' // 不存在的企业ID
  1174. }
  1175. }, {
  1176. headers: {
  1177. 'Authorization': `Bearer ${testToken}`
  1178. }
  1179. });
  1180. // 注意:API可能会返回空列表而不是错误
  1181. // 根据实际实现,可能返回200且空列表,或返回404
  1182. // 这里我们假设返回200且空列表
  1183. expect(response.status).toBe(200);
  1184. if (response.status === 200) {
  1185. const data = await response.json();
  1186. expect(data.data).toHaveLength(0);
  1187. expect(data.total).toBe(0);
  1188. }
  1189. });
  1190. });
  1191. describe('POST /order/batch-download', () => {
  1192. it('应该成功批量下载企业维度视频', async () => {
  1193. const requestData = {
  1194. downloadScope: DownloadScope.COMPANY,
  1195. companyId: testCompany.id,
  1196. assetTypes: [AssetType.CHECKIN_VIDEO, AssetType.WORK_VIDEO]
  1197. };
  1198. const response = await enterpriseClient['batch-download'].$post({
  1199. json: requestData
  1200. }, {
  1201. headers: {
  1202. 'Authorization': `Bearer ${testToken}`
  1203. }
  1204. });
  1205. expect(response.status).toBe(200);
  1206. if (response.status === 200) {
  1207. const data = await response.json();
  1208. expect(data.success).toBe(true);
  1209. expect(data.message).toContain('批量下载成功');
  1210. expect(data.files).toHaveLength(2); // CHECKIN_VIDEO 和 WORK_VIDEO
  1211. expect(data.totalFiles).toBe(2);
  1212. // 验证文件项结构
  1213. const fileItem = data.files[0];
  1214. expect(fileItem).toHaveProperty('id');
  1215. expect(fileItem).toHaveProperty('name');
  1216. expect(fileItem).toHaveProperty('size');
  1217. expect(fileItem).toHaveProperty('url');
  1218. expect(fileItem).toHaveProperty('assetType');
  1219. expect(fileItem).toHaveProperty('orderId');
  1220. expect(fileItem).toHaveProperty('personId');
  1221. expect(fileItem).toHaveProperty('relatedTime');
  1222. }
  1223. });
  1224. it('应该成功批量下载个人维度视频', async () => {
  1225. const requestData = {
  1226. downloadScope: DownloadScope.PERSON,
  1227. companyId: testCompany.id,
  1228. personId: testOrderPerson.personId,
  1229. assetTypes: [AssetType.CHECKIN_VIDEO]
  1230. };
  1231. const response = await enterpriseClient['batch-download'].$post({
  1232. json: requestData
  1233. }, {
  1234. headers: {
  1235. 'Authorization': `Bearer ${testToken}`
  1236. }
  1237. });
  1238. expect(response.status).toBe(200);
  1239. if (response.status === 200) {
  1240. const data = await response.json();
  1241. expect(data.success).toBe(true);
  1242. expect(data.files).toHaveLength(1);
  1243. expect(data.files[0].assetType).toBe(AssetType.CHECKIN_VIDEO);
  1244. }
  1245. });
  1246. it('应该验证个人维度下载需要personId', async () => {
  1247. const requestData = {
  1248. downloadScope: DownloadScope.PERSON,
  1249. companyId: testCompany.id
  1250. // 缺少personId
  1251. };
  1252. const response = await enterpriseClient['batch-download'].$post({
  1253. json: requestData
  1254. }, {
  1255. headers: {
  1256. 'Authorization': `Bearer ${testToken}`
  1257. }
  1258. });
  1259. expect(response.status).toBe(400);
  1260. });
  1261. it('应该支持指定文件ID列表下载', async () => {
  1262. // 获取测试视频资产的文件ID
  1263. const fileIds = [testFile.id];
  1264. const requestData = {
  1265. downloadScope: DownloadScope.COMPANY,
  1266. companyId: testCompany.id,
  1267. fileIds: fileIds
  1268. };
  1269. const response = await enterpriseClient['batch-download'].$post({
  1270. json: requestData
  1271. }, {
  1272. headers: {
  1273. 'Authorization': `Bearer ${testToken}`
  1274. }
  1275. });
  1276. expect(response.status).toBe(200);
  1277. if (response.status === 200) {
  1278. const data = await response.json();
  1279. expect(data.success).toBe(true);
  1280. // 3个视频资产都使用同一个文件ID,所以应该返回3个文件项
  1281. expect(data.files).toHaveLength(3);
  1282. // 所有文件项的id都应该是指定的文件ID
  1283. data.files.forEach((fileItem: any) => {
  1284. expect(fileItem.id).toBe(fileIds[0]);
  1285. });
  1286. }
  1287. });
  1288. it('应该处理没有符合条件的视频文件', async () => {
  1289. const requestData = {
  1290. downloadScope: DownloadScope.COMPANY,
  1291. companyId: 999999, // 不存在的企业
  1292. assetTypes: [AssetType.CHECKIN_VIDEO]
  1293. };
  1294. const response = await enterpriseClient['batch-download'].$post({
  1295. json: requestData
  1296. }, {
  1297. headers: {
  1298. 'Authorization': `Bearer ${testToken}`
  1299. }
  1300. });
  1301. expect(response.status).toBe(200);
  1302. if (response.status === 200) {
  1303. const data = await response.json();
  1304. expect(data.success).toBe(true);
  1305. expect(data.files).toHaveLength(0);
  1306. expect(data.totalFiles).toBe(0);
  1307. expect(data.message).toContain('未找到符合条件的视频文件');
  1308. }
  1309. });
  1310. });
  1311. describe('PUT /order/videos/{id}/status', () => {
  1312. it('应该成功更新视频审核状态', async () => {
  1313. const testAsset = testVideoAssets[0];
  1314. const requestData = {
  1315. status: AssetStatus.VERIFIED as const
  1316. };
  1317. const response = await enterpriseClient.videos[':id'].status.$put({
  1318. param: { id: testAsset.id.toString() },
  1319. json: requestData
  1320. }, {
  1321. headers: {
  1322. 'Authorization': `Bearer ${testToken}`
  1323. }
  1324. });
  1325. expect(response.status).toBe(200);
  1326. if (response.status === 200) {
  1327. const data = await response.json();
  1328. expect(data.id).toBe(testAsset.id);
  1329. expect(data.status).toBe('verified');
  1330. // 验证数据库中的状态已更新
  1331. const dataSource = await IntegrationTestDatabase.getDataSource();
  1332. const assetRepository = dataSource.getRepository(OrderPersonAsset);
  1333. const updatedAsset = await assetRepository.findOne({
  1334. where: { id: testAsset.id }
  1335. });
  1336. expect(updatedAsset?.status).toBe('verified');
  1337. }
  1338. });
  1339. it('应该支持更新状态为已拒绝', async () => {
  1340. const testAsset = testVideoAssets[1]; // 当前是verified
  1341. const requestData = {
  1342. status: AssetStatus.REJECTED as const
  1343. };
  1344. const response = await enterpriseClient.videos[':id'].status.$put({
  1345. param: { id: testAsset.id.toString() },
  1346. json: requestData
  1347. }, {
  1348. headers: {
  1349. 'Authorization': `Bearer ${testToken}`
  1350. }
  1351. });
  1352. expect(response.status).toBe(200);
  1353. if (response.status === 200) {
  1354. const data = await response.json();
  1355. expect(data.status).toBe('rejected');
  1356. }
  1357. });
  1358. it('应该处理不存在的视频资产ID', async () => {
  1359. const requestData = {
  1360. status: AssetStatus.VERIFIED as const
  1361. };
  1362. const response = await enterpriseClient.videos[':id'].status.$put({
  1363. param: { id: '999999' },
  1364. json: requestData
  1365. }, {
  1366. headers: {
  1367. 'Authorization': `Bearer ${testToken}`
  1368. }
  1369. });
  1370. expect(response.status).toBe(404);
  1371. });
  1372. it('应该验证状态值的有效性', async () => {
  1373. const testAsset = testVideoAssets[0];
  1374. const requestData = {
  1375. status: 'invalid_status' as any // 无效的状态
  1376. };
  1377. const response = await enterpriseClient.videos[':id'].status.$put({
  1378. param: { id: testAsset.id.toString() },
  1379. json: requestData
  1380. }, {
  1381. headers: {
  1382. 'Authorization': `Bearer ${testToken}`
  1383. }
  1384. });
  1385. expect(response.status).toBe(400);
  1386. });
  1387. it('应该支持状态更新为待审核', async () => {
  1388. const testAsset = testVideoAssets[2]; // 当前是rejected
  1389. const requestData = {
  1390. status: AssetStatus.PENDING as const
  1391. };
  1392. const response = await enterpriseClient.videos[':id'].status.$put({
  1393. param: { id: testAsset.id.toString() },
  1394. json: requestData
  1395. }, {
  1396. headers: {
  1397. 'Authorization': `Bearer ${testToken}`
  1398. }
  1399. });
  1400. expect(response.status).toBe(200);
  1401. if (response.status === 200) {
  1402. const data = await response.json();
  1403. expect(data.status).toBe('pending');
  1404. }
  1405. });
  1406. });
  1407. });
  1408. });