company-statistics.integration.test.ts 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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 } from '@d8d/allin-order-module/entities';
  10. import { DisabledPerson, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit } from '@d8d/allin-disability-module/entities';
  11. import { BankName } from '@d8d/bank-names-module';
  12. import { OrderStatus, WorkStatus } from '@d8d/allin-enums';
  13. import companyStatisticsRoutes from '../../src/routes/company-statistics.route';
  14. import { Company } from '../../src/entities/company.entity';
  15. // 设置集成测试钩子 - 需要包含所有相关实体
  16. setupIntegrationDatabaseHooksWithEntities([
  17. UserEntity, File, Role, Platform, Company,
  18. EmploymentOrder, OrderPerson, DisabledPerson, BankName, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit
  19. ])
  20. describe('企业统计API集成测试', () => {
  21. let client: ReturnType<typeof testClient<typeof companyStatisticsRoutes>>;
  22. let testToken: string;
  23. let testUser: UserEntity;
  24. let testCompany: Company;
  25. let testPlatform: Platform;
  26. beforeEach(async () => {
  27. // 创建测试客户端
  28. client = testClient(companyStatisticsRoutes);
  29. // 获取数据源
  30. const dataSource = await IntegrationTestDatabase.getDataSource();
  31. // 创建测试平台
  32. const platformRepository = dataSource.getRepository(Platform);
  33. testPlatform = platformRepository.create({
  34. platformName: `测试平台_${Date.now()}`,
  35. contactPerson: '平台管理员',
  36. contactPhone: '13800138000',
  37. contactEmail: 'admin@example.com',
  38. status: 1
  39. });
  40. await platformRepository.save(testPlatform);
  41. // 创建测试公司
  42. const companyRepository = dataSource.getRepository(Company);
  43. testCompany = companyRepository.create({
  44. companyName: `测试公司_${Date.now()}`,
  45. contactPerson: '公司联系人',
  46. contactPhone: '13900139000',
  47. contactEmail: 'company@example.com',
  48. address: '公司地址',
  49. platformId: testPlatform.id,
  50. status: 1
  51. });
  52. await companyRepository.save(testCompany);
  53. // 创建测试企业用户(有companyId)
  54. const userRepository = dataSource.getRepository(UserEntity);
  55. testUser = userRepository.create({
  56. username: `enterprise_user_${Date.now()}`,
  57. password: 'test_password',
  58. nickname: '企业测试用户',
  59. registrationSource: 'web',
  60. companyId: testCompany.id
  61. });
  62. await userRepository.save(testUser);
  63. // 生成测试用户的token
  64. testToken = JWTUtil.generateToken({
  65. id: testUser.id,
  66. username: testUser.username,
  67. roles: [{ name: 'enterprise_user' }]
  68. }, { companyId: testCompany.id } as Partial<JWTPayload & { companyId: number }>);
  69. });
  70. describe('GET /api/v1/yongren/company/overview', () => {
  71. it('应该返回企业概览统计', async () => {
  72. // 准备测试数据:创建订单和人员
  73. const dataSource = await IntegrationTestDatabase.getDataSource();
  74. // 创建残疾人
  75. const disabledPersonRepo = dataSource.getRepository(DisabledPerson);
  76. const disabledPerson = disabledPersonRepo.create({
  77. name: '测试残疾人',
  78. idCard: `110101${Date.now() % 100000000}`,
  79. gender: '男',
  80. birthDate: new Date('1990-01-01'),
  81. disabilityType: '视力残疾',
  82. disabilityLevel: '一级',
  83. disabilityId: `DIS${Date.now() % 100000000}`,
  84. idAddress: '身份证地址',
  85. phone: '13800138000',
  86. province: '北京市',
  87. city: '北京市'
  88. });
  89. await disabledPersonRepo.save(disabledPerson);
  90. // 创建订单
  91. const orderRepo = dataSource.getRepository(EmploymentOrder);
  92. const order = orderRepo.create({
  93. orderName: '测试订单',
  94. platformId: testPlatform.id,
  95. companyId: testCompany.id,
  96. orderStatus: OrderStatus.IN_PROGRESS,
  97. workStatus: WorkStatus.WORKING
  98. });
  99. await orderRepo.save(order);
  100. // 创建订单人员关联
  101. const orderPersonRepo = dataSource.getRepository(OrderPerson);
  102. const orderPerson = orderPersonRepo.create({
  103. orderId: order.id,
  104. personId: disabledPerson.id,
  105. joinDate: new Date('2024-01-01'),
  106. workStatus: WorkStatus.WORKING,
  107. salaryDetail: 5000.00
  108. });
  109. await orderPersonRepo.save(orderPerson);
  110. // 调用API
  111. const response = await client.overview.$get({},{
  112. headers: {
  113. Authorization: `Bearer ${testToken}`
  114. }
  115. });
  116. expect(response.status).toBe(200);
  117. const data = await response.json() as any;
  118. // 验证响应结构
  119. expect(data).toHaveProperty('在职人员数');
  120. expect(data).toHaveProperty('进行中订单数');
  121. expect(data).toHaveProperty('已完成订单数');
  122. expect(data).toHaveProperty('累计订单数');
  123. // 验证数据
  124. expect(data.在职人员数).toBe(1);
  125. expect(data.进行中订单数).toBe(1);
  126. });
  127. it('未认证用户应该返回401', async () => {
  128. const response = await client.overview.$get();
  129. expect(response.status).toBe(401);
  130. });
  131. it('非企业用户应该返回403', async () => {
  132. // 创建非企业用户
  133. const dataSource = await IntegrationTestDatabase.getDataSource();
  134. const userRepository = dataSource.getRepository(UserEntity);
  135. const nonEnterpriseUser = userRepository.create({
  136. username: `non_enterprise_${Date.now()}`,
  137. password: 'test_password',
  138. nickname: '非企业用户',
  139. registrationSource: 'web'
  140. // 没有companyId
  141. });
  142. await userRepository.save(nonEnterpriseUser);
  143. const nonEnterpriseToken = JWTUtil.generateToken({
  144. id: nonEnterpriseUser.id,
  145. username: nonEnterpriseUser.username,
  146. roles: [{ name: 'user' }]
  147. });
  148. const response = await client.overview.$get({},{
  149. headers: {
  150. Authorization: `Bearer ${nonEnterpriseToken}`
  151. }
  152. });
  153. expect(response.status).toBe(403);
  154. });
  155. });
  156. describe('GET /api/v1/yongren/company/{id}/talents', () => {
  157. it('应该返回企业维度人才统计', async () => {
  158. // 准备测试数据
  159. const dataSource = await IntegrationTestDatabase.getDataSource();
  160. // 创建多个残疾人
  161. const disabledPersonRepo = dataSource.getRepository(DisabledPerson);
  162. const disabledPersons = [];
  163. for (let i = 0; i < 3; i++) {
  164. const person = disabledPersonRepo.create({
  165. name: `测试残疾人${i}`,
  166. idCard: `110101${Date.now() % 100000000 + i}`,
  167. gender: i % 2 === 0 ? '男' : '女',
  168. birthDate: new Date('1990-01-01'),
  169. disabilityType: '视力残疾',
  170. disabilityLevel: '一级',
  171. disabilityId: `DIS${Date.now() % 100000000 + i}`,
  172. idAddress: '身份证地址',
  173. phone: `1380013800${i}`,
  174. province: '北京市',
  175. city: '北京市',
  176. });
  177. await disabledPersonRepo.save(person);
  178. disabledPersons.push(person);
  179. }
  180. // 创建订单
  181. const orderRepo = dataSource.getRepository(EmploymentOrder);
  182. const order = orderRepo.create({
  183. orderName: '测试订单',
  184. platformId: testPlatform.id,
  185. companyId: testCompany.id,
  186. orderStatus: OrderStatus.IN_PROGRESS,
  187. workStatus: WorkStatus.WORKING
  188. });
  189. await orderRepo.save(order);
  190. // 创建订单人员关联
  191. const orderPersonRepo = dataSource.getRepository(OrderPerson);
  192. for (let i = 0; i < disabledPersons.length; i++) {
  193. const person = disabledPersons[i];
  194. const orderPerson = orderPersonRepo.create({
  195. orderId: order.id,
  196. personId: person.id,
  197. joinDate: new Date('2024-01-01'),
  198. workStatus: i === 0 ? WorkStatus.WORKING : WorkStatus.RESIGNED, // 第一个在职,其他离职
  199. salaryDetail: 5000.00 + i * 1000
  200. });
  201. await orderPersonRepo.save(orderPerson);
  202. }
  203. // 调用API
  204. const response = await client[':id'].talents.$get({
  205. param: { id: testCompany.id }
  206. },{
  207. headers: {
  208. Authorization: `Bearer ${testToken}`
  209. }
  210. });
  211. console.debug('响应状态:', response.status);
  212. if (response.status !== 200) {
  213. const errorData = await response.json();
  214. console.debug('错误响应:', errorData);
  215. }
  216. expect(response.status).toBe(200);
  217. const data = await response.json() as any;
  218. // 验证响应结构
  219. expect(data).toHaveProperty('人才列表');
  220. expect(data).toHaveProperty('状态分布');
  221. expect(Array.isArray(data.人才列表)).toBe(true);
  222. // 验证状态分布
  223. expect(data.状态分布).toHaveProperty('working');
  224. expect(data.状态分布).toHaveProperty('on_leave');
  225. expect(data.状态分布).toHaveProperty('left');
  226. });
  227. it('访问其他企业数据应该返回403', async () => {
  228. // 创建另一个公司
  229. const dataSource = await IntegrationTestDatabase.getDataSource();
  230. const companyRepository = dataSource.getRepository(Company);
  231. const otherCompany = companyRepository.create({
  232. companyName: `其他公司_${Date.now()}`,
  233. contactPerson: '其他联系人',
  234. contactPhone: '13900139001',
  235. contactEmail: 'other@example.com',
  236. address: '其他地址',
  237. platformId: testPlatform.id,
  238. status: 1
  239. });
  240. await companyRepository.save(otherCompany);
  241. // 尝试访问其他公司数据
  242. const response = await client[':id'].talents.$get({
  243. param: { id: otherCompany.id }
  244. },{
  245. headers: {
  246. Authorization: `Bearer ${testToken}`
  247. }
  248. });
  249. expect(response.status).toBe(403);
  250. });
  251. });
  252. });