person-extension.integration.test.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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 { Platform } from '@d8d/allin-platform-module/entities';
  9. import { EmploymentOrder, OrderPerson, OrderPersonAsset } from '@d8d/allin-order-module/entities';
  10. import { AssetType, AssetFileType } from '@d8d/allin-order-module/schemas';
  11. import { OrderStatus, WorkStatus } from '@d8d/allin-order-module/schemas';
  12. import { BankName } from '@d8d/bank-names-module';
  13. import { DisabledPerson, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit } from '../../src/entities';
  14. import personExtensionRoutes from '../../src/routes/person-extension.route';
  15. import { Company } from '@d8d/allin-company-module/entities';
  16. // 设置集成测试钩子 - 需要包含所有相关实体
  17. setupIntegrationDatabaseHooksWithEntities([
  18. UserEntity, File, Role, Platform, Company,
  19. EmploymentOrder, OrderPerson, OrderPersonAsset,
  20. DisabledPerson, BankName, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit
  21. ])
  22. describe('人才扩展API集成测试', () => {
  23. let client: ReturnType<typeof testClient<typeof personExtensionRoutes>>;
  24. let testToken: string;
  25. let testUser: UserEntity;
  26. let testCompany: Company;
  27. let testPlatform: Platform;
  28. let testDisabledPerson: DisabledPerson;
  29. let testOrder: EmploymentOrder;
  30. beforeEach(async () => {
  31. // 创建测试客户端
  32. client = testClient(personExtensionRoutes);
  33. // 获取数据源
  34. const dataSource = await IntegrationTestDatabase.getDataSource();
  35. // 创建测试平台
  36. const platformRepository = dataSource.getRepository(Platform);
  37. testPlatform = platformRepository.create({
  38. platformName: `测试平台_${Date.now()}`,
  39. contactPerson: '平台管理员',
  40. contactPhone: '13800138000',
  41. contactEmail: 'admin@example.com',
  42. status: 1
  43. });
  44. await platformRepository.save(testPlatform);
  45. // 创建测试公司
  46. const companyRepository = dataSource.getRepository(Company);
  47. testCompany = companyRepository.create({
  48. companyName: `测试公司_${Date.now()}`,
  49. contactPerson: '公司联系人',
  50. contactPhone: '13900139000',
  51. contactEmail: 'company@example.com',
  52. address: '公司地址',
  53. platformId: testPlatform.id,
  54. status: 1
  55. });
  56. await companyRepository.save(testCompany);
  57. // 创建测试企业用户
  58. const userRepository = dataSource.getRepository(UserEntity);
  59. testUser = userRepository.create({
  60. username: `enterprise_user_${Date.now()}`,
  61. password: 'test_password',
  62. nickname: '企业测试用户',
  63. registrationSource: 'web',
  64. companyId: testCompany.id
  65. });
  66. await userRepository.save(testUser);
  67. // 生成测试用户的token
  68. testToken = JWTUtil.generateToken({
  69. id: testUser.id,
  70. username: testUser.username,
  71. roles: [{ name: 'enterprise_user' }]
  72. }, { companyId: testCompany.id } as Partial<JWTPayload & { companyId: number }>);
  73. // 创建测试残疾人
  74. const disabledPersonRepo = dataSource.getRepository(DisabledPerson);
  75. testDisabledPerson = disabledPersonRepo.create({
  76. name: '测试残疾人',
  77. idCard: `110101${Date.now() % 100000000}`,
  78. gender: '男',
  79. birthDate: new Date('1990-01-01'),
  80. disabilityType: '视力残疾',
  81. disabilityLevel: '一级',
  82. disabilityId: `DIS${Date.now() % 100000000}`,
  83. idAddress: '身份证地址',
  84. phone: '13800138000',
  85. province: '北京市',
  86. city: '北京市',
  87. detailedAddress: '测试地址'
  88. });
  89. await disabledPersonRepo.save(testDisabledPerson);
  90. // 创建测试订单
  91. const orderRepo = dataSource.getRepository(EmploymentOrder);
  92. testOrder = orderRepo.create({
  93. orderName: '测试订单',
  94. platformId: testPlatform.id,
  95. companyId: testCompany.id,
  96. orderStatus: OrderStatus.CONFIRMED,
  97. workStatus: WorkStatus.WORKING
  98. });
  99. await orderRepo.save(testOrder);
  100. // 创建订单人员关联,使人员属于该企业
  101. const orderPersonRepo = dataSource.getRepository(OrderPerson);
  102. const orderPerson = orderPersonRepo.create({
  103. orderId: testOrder.id,
  104. personId: testDisabledPerson.id,
  105. joinDate: new Date('2024-01-01'),
  106. workStatus: WorkStatus.WORKING,
  107. salaryDetail: 5000.00
  108. });
  109. await orderPersonRepo.save(orderPerson);
  110. });
  111. describe('GET /api/v1/yongren/disability-person/{id}/work-history', () => {
  112. it('应该返回人员工作历史', async () => {
  113. // 准备测试数据:多个订单关联
  114. const dataSource = await IntegrationTestDatabase.getDataSource();
  115. const orderPersonRepo = dataSource.getRepository(OrderPerson);
  116. // 创建另一个订单关联
  117. const orderRepo = dataSource.getRepository(EmploymentOrder);
  118. const anotherOrder = orderRepo.create({
  119. orderName: '另一个测试订单',
  120. platformId: testPlatform.id,
  121. companyId: testCompany.id,
  122. orderStatus: OrderStatus.COMPLETED,
  123. workStatus: WorkStatus.WORKING
  124. });
  125. await orderRepo.save(anotherOrder);
  126. const anotherOrderPerson = orderPersonRepo.create({
  127. orderId: anotherOrder.id,
  128. personId: testDisabledPerson.id,
  129. joinDate: new Date('2024-06-01'),
  130. actualStartDate: new Date('2024-06-02'),
  131. leaveDate: new Date('2024-12-31'),
  132. workStatus: WorkStatus.RESIGNED,
  133. salaryDetail: 6000.00
  134. });
  135. await orderPersonRepo.save(anotherOrderPerson);
  136. // 调用API
  137. const response = await client[':id']['work-history'].$get({
  138. param: { id: testDisabledPerson.id }
  139. },{
  140. headers: {
  141. Authorization: `Bearer ${testToken}`
  142. }
  143. });
  144. console.debug('响应状态:', response.status);
  145. // 类型保护:如果状态不是200,抛出错误
  146. if (response.status !== 200) {
  147. try {
  148. const errorData = await response.json();
  149. console.debug('错误响应:', errorData);
  150. throw new Error(`API returned ${response.status}: ${errorData.message}`);
  151. } catch (e) {
  152. console.debug('无法解析错误响应:', e);
  153. throw new Error(`API returned ${response.status} and response could not be parsed`);
  154. }
  155. }
  156. const data = await response.json();
  157. // 验证响应结构
  158. expect(data).toHaveProperty('工作历史');
  159. expect(Array.isArray(data.工作历史)).toBe(true);
  160. // 验证数据
  161. expect(data.工作历史.length).toBeGreaterThanOrEqual(1);
  162. const workHistory = data.工作历史[0];
  163. expect(workHistory).toHaveProperty('订单ID');
  164. expect(workHistory).toHaveProperty('订单名称');
  165. expect(workHistory).toHaveProperty('入职日期');
  166. expect(workHistory).toHaveProperty('工作状态');
  167. expect(workHistory).toHaveProperty('个人薪资');
  168. });
  169. it('访问其他企业人员应该返回403', async () => {
  170. // 创建另一个公司的残疾人
  171. const dataSource = await IntegrationTestDatabase.getDataSource();
  172. // 创建另一个公司
  173. const companyRepository = dataSource.getRepository(Company);
  174. const otherCompany = companyRepository.create({
  175. companyName: `其他公司_${Date.now()}`,
  176. contactPerson: '其他联系人',
  177. contactPhone: '13900139001',
  178. contactEmail: 'other@example.com',
  179. address: '其他地址',
  180. platformId: testPlatform.id,
  181. status: 1
  182. });
  183. await companyRepository.save(otherCompany);
  184. // 创建另一个公司的残疾人
  185. const disabledPersonRepo = dataSource.getRepository(DisabledPerson);
  186. const otherDisabledPerson = disabledPersonRepo.create({
  187. name: '其他公司残疾人',
  188. idCard: `110101${Date.now() % 100000000 + 1000}`,
  189. gender: '女',
  190. birthDate: new Date('1995-01-01'),
  191. disabilityType: '听力残疾',
  192. disabilityLevel: '二级',
  193. disabilityId: `DIS${Date.now() % 100000000 + 1000}`,
  194. idAddress: '其他地址',
  195. phone: '13900139000',
  196. province: '上海市',
  197. city: '上海市',
  198. detailedAddress: '其他地址'
  199. });
  200. await disabledPersonRepo.save(otherDisabledPerson);
  201. // 尝试访问其他公司人员数据
  202. const response = await client[':id']['work-history'].$get({
  203. param: { id: otherDisabledPerson.id }
  204. },{
  205. headers: {
  206. Authorization: `Bearer ${testToken}`
  207. }
  208. });
  209. expect(response.status).toBe(403);
  210. });
  211. });
  212. describe('GET /api/v1/yongren/disability-person/{id}/salary-history', () => {
  213. it('应该返回人员薪资历史', async () => {
  214. // 注意:薪资历史可能需要从薪资模块获取,这里暂时返回空数组
  215. const response = await client[':id']['salary-history'].$get({
  216. param: { id: testDisabledPerson.id }
  217. },{
  218. headers: {
  219. Authorization: `Bearer ${testToken}`
  220. }
  221. });
  222. expect(response.status).toBe(200);
  223. const data = await response.json() as { 薪资历史: any[] };
  224. // 验证响应结构
  225. expect(data).toHaveProperty('薪资历史');
  226. expect(Array.isArray(data.薪资历史)).toBe(true);
  227. });
  228. });
  229. describe('GET /api/v1/yongren/disability-person/{id}/credit-info', () => {
  230. it('应该返回人员征信信息', async () => {
  231. // 准备测试数据:银行卡信息
  232. const dataSource = await IntegrationTestDatabase.getDataSource();
  233. // 创建文件
  234. const fileRepository = dataSource.getRepository(File);
  235. const testFile = fileRepository.create({
  236. name: '银行卡照片.jpg',
  237. type: 'image/jpeg',
  238. size: 1024,
  239. path: 'uploads/bank-card.jpg',
  240. description: '银行卡照片',
  241. uploadUserId: testUser.id,
  242. uploadTime: new Date()
  243. });
  244. await fileRepository.save(testFile);
  245. // 创建银行名称记录
  246. const bankNameRepo = dataSource.getRepository(BankName);
  247. const bankName = bankNameRepo.create({
  248. name: '测试银行',
  249. code: 'TESTBANK',
  250. status: 1
  251. });
  252. await bankNameRepo.save(bankName);
  253. // 创建银行卡记录
  254. const bankCardRepo = dataSource.getRepository(DisabledBankCard);
  255. const bankCard = bankCardRepo.create({
  256. personId: testDisabledPerson.id,
  257. subBankName: '测试支行',
  258. bankNameId: bankName.id, // 使用实际创建的银行ID
  259. cardNumber: '6228481234567890123',
  260. cardholderName: '测试持卡人',
  261. cardType: '一类卡',
  262. fileId: testFile.id,
  263. isDefault: 1
  264. });
  265. await bankCardRepo.save(bankCard);
  266. // 调用API
  267. const response = await client[':id']['credit-info'].$get({
  268. param: { id: testDisabledPerson.id }
  269. },{
  270. headers: {
  271. Authorization: `Bearer ${testToken}`
  272. }
  273. });
  274. expect(response.status).toBe(200);
  275. const data = await response.json() as { 征信信息: any[] };
  276. // 验证响应结构
  277. expect(data).toHaveProperty('征信信息');
  278. expect(Array.isArray(data.征信信息)).toBe(true);
  279. if (data.征信信息.length > 0) {
  280. const creditInfo = data.征信信息[0];
  281. expect(creditInfo).toHaveProperty('文件ID');
  282. expect(creditInfo).toHaveProperty('银行卡号');
  283. expect(creditInfo).toHaveProperty('持卡人姓名');
  284. }
  285. });
  286. });
  287. describe('GET /api/v1/yongren/disability-person/{id}/videos', () => {
  288. it('应该返回人员视频关联', async () => {
  289. // 准备测试数据:订单人员资产(视频)
  290. const dataSource = await IntegrationTestDatabase.getDataSource();
  291. // 创建文件
  292. const fileRepository = dataSource.getRepository(File);
  293. const testFile = fileRepository.create({
  294. name: '工作视频.mp4',
  295. type: 'video/mp4',
  296. size: 1024000,
  297. path: 'uploads/work-video.mp4',
  298. description: '工作视频',
  299. uploadUserId: testUser.id,
  300. uploadTime: new Date()
  301. });
  302. await fileRepository.save(testFile);
  303. // 创建订单人员资产记录
  304. const assetRepo = dataSource.getRepository(OrderPersonAsset);
  305. const asset = assetRepo.create({
  306. orderId: testOrder.id,
  307. personId: testDisabledPerson.id,
  308. assetType: AssetType.WORK_VIDEO,
  309. assetFileType: AssetFileType.VIDEO,
  310. fileId: testFile.id,
  311. relatedTime: new Date()
  312. });
  313. await assetRepo.save(asset);
  314. // 调用API
  315. const response = await client[':id'].videos.$get({
  316. param: { id: testDisabledPerson.id }
  317. },{
  318. headers: {
  319. Authorization: `Bearer ${testToken}`
  320. }
  321. });
  322. expect(response.status).toBe(200);
  323. const data = await response.json() as { 视频列表: any[] };
  324. // 验证响应结构
  325. expect(data).toHaveProperty('视频列表');
  326. expect(Array.isArray(data.视频列表)).toBe(true);
  327. if (data.视频列表.length > 0) {
  328. const video = data.视频列表[0];
  329. expect(video).toHaveProperty('视频类型');
  330. expect(video).toHaveProperty('文件ID');
  331. expect(video).toHaveProperty('关联订单ID');
  332. }
  333. });
  334. });
  335. });