Procházet zdrojové kódy

feat(order-module): 添加测试数据工厂

创建OrderTestDataFactory类,包含:
1. createOrderData - 创建订单测试数据
2. createOrderPersonData - 创建订单人员测试数据
3. createOrderPersonAssetData - 创建订单人员资产测试数据
4. createFileData - 创建文件测试数据
5. createOrderWithStatus - 创建特定状态的订单数据

减少测试代码重复,提高测试可维护性

🤖 Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname před 1 měsícem
rodič
revize
c8b5b438b3

+ 292 - 0
allin-packages/order-module/tests/utils/test-data-factory.ts

@@ -0,0 +1,292 @@
+import { DataSource } from 'typeorm';
+import { EmploymentOrder, OrderPerson, OrderPersonAsset, AssetType, AssetFileType } from '../../src/entities';
+import { OrderStatus, WorkStatus } from '@d8d/allin-enums';
+import { File } from '@d8d/file-module';
+
+/**
+ * 订单模块测试数据工厂类
+ * 用于生成测试数据,避免测试代码中的重复
+ */
+export class OrderTestDataFactory {
+  /**
+   * 创建测试用工订单数据
+   */
+  static createEmploymentOrderData(overrides: Partial<EmploymentOrder> = {}): Partial<EmploymentOrder> {
+    const timestamp = Math.floor(Math.random() * 100000);
+    return {
+      orderName: `测试订单_${timestamp}`,
+      platformId: 1,
+      companyId: 1,
+      channelId: 1,
+      expectedStartDate: new Date('2025-01-01'),
+      orderStatus: OrderStatus.DRAFT,
+      workStatus: WorkStatus.NOT_WORKING,
+      ...overrides
+    };
+  }
+
+  /**
+   * 在数据库中创建测试用工订单
+   */
+  static async createTestEmploymentOrder(
+    dataSource: DataSource,
+    overrides: Partial<EmploymentOrder> = {}
+  ): Promise<EmploymentOrder> {
+    const orderData = this.createEmploymentOrderData(overrides);
+    const orderRepository = dataSource.getRepository(EmploymentOrder);
+    const order = new EmploymentOrder(orderData);
+    return await orderRepository.save(order);
+  }
+
+  /**
+   * 创建测试订单人员数据
+   */
+  static createOrderPersonData(
+    orderId: number,
+    personId: number,
+    overrides: Partial<OrderPerson> = {}
+  ): Partial<OrderPerson> {
+    return {
+      orderId,
+      personId,
+      joinDate: new Date('2025-01-15'),
+      salaryDetail: 5000.00,
+      ...overrides
+    };
+  }
+
+  /**
+   * 在数据库中创建测试订单人员
+   */
+  static async createTestOrderPerson(
+    dataSource: DataSource,
+    orderId: number,
+    personId: number,
+    overrides: Partial<OrderPerson> = {}
+  ): Promise<OrderPerson> {
+    const personData = this.createOrderPersonData(orderId, personId, overrides);
+    const personRepository = dataSource.getRepository(OrderPerson);
+    const person = new OrderPerson(personData);
+    return await personRepository.save(person);
+  }
+
+  /**
+   * 创建测试订单人员资产数据
+   */
+  static createOrderPersonAssetData(
+    orderId: number,
+    personId: number,
+    fileId: number,
+    overrides: Partial<OrderPersonAsset> = {}
+  ): Partial<OrderPersonAsset> {
+    const timestamp = Math.floor(Math.random() * 100000);
+    return {
+      orderId,
+      personId,
+      fileId,
+      assetType: AssetType.DISABILITY_CERT,
+      assetFileType: AssetFileType.IMAGE,
+      ...overrides
+    };
+  }
+
+  /**
+   * 在数据库中创建测试订单人员资产
+   */
+  static async createTestOrderPersonAsset(
+    dataSource: DataSource,
+    orderId: number,
+    personId: number,
+    fileId: number,
+    overrides: Partial<OrderPersonAsset> = {}
+  ): Promise<OrderPersonAsset> {
+    const assetData = this.createOrderPersonAssetData(orderId, personId, fileId, overrides);
+    const assetRepository = dataSource.getRepository(OrderPersonAsset);
+    const asset = new OrderPersonAsset(assetData);
+    return await assetRepository.save(asset);
+  }
+
+  /**
+   * 创建测试文件数据
+   * 注意:这里只是创建File实体的数据,实际文件上传需要调用文件模块的API
+   */
+  static createFileData(overrides: Partial<File> = {}): Partial<File> {
+    const timestamp = Math.floor(Math.random() * 100000);
+    return {
+      name: `test_file_${timestamp}.jpg`, // 注意:File实体使用name字段,不是filename
+      type: 'image/jpeg',
+      size: 1024,
+      path: `test/${timestamp}_test_file.jpg`,
+      uploadUserId: 1,
+      uploadTime: new Date(),
+      createdAt: new Date(),
+      updatedAt: new Date(),
+      ...overrides
+    };
+  }
+
+  /**
+   * 在数据库中创建测试文件
+   * 注意:需要文件模块的File实体已注册到DataSource中
+   */
+  static async createTestFile(
+    dataSource: DataSource,
+    overrides: Partial<File> = {}
+  ): Promise<File> {
+    const fileData = this.createFileData(overrides);
+    const fileRepository = dataSource.getRepository(File);
+    const file = fileRepository.create(fileData);
+    return await fileRepository.save(file);
+  }
+
+  /**
+   * 创建完整的测试订单环境(包含订单、人员、资产、文件)
+   */
+  static async createCompleteOrderEnvironment(
+    dataSource: DataSource,
+    options: {
+      orderOverrides?: Partial<EmploymentOrder>;
+      personId?: number;
+      personOverrides?: Partial<OrderPerson>;
+      fileOverrides?: Partial<File>;
+      assetOverrides?: Partial<OrderPersonAsset>;
+    } = {}
+  ): Promise<{
+    order: EmploymentOrder;
+    orderPerson: OrderPerson;
+    file: File;
+    orderPersonAsset: OrderPersonAsset;
+  }> {
+    // 创建订单
+    const order = await this.createTestEmploymentOrder(dataSource, options.orderOverrides);
+
+    // 创建文件
+    const file = await this.createTestFile(dataSource, options.fileOverrides);
+
+    // 创建订单人员
+    const personId = options.personId || 1;
+    const orderPerson = await this.createTestOrderPerson(
+      dataSource,
+      order.id,
+      personId,
+      options.personOverrides
+    );
+
+    // 创建订单人员资产
+    const orderPersonAsset = await this.createTestOrderPersonAsset(
+      dataSource,
+      order.id,
+      personId,
+      file.id,
+      options.assetOverrides
+    );
+
+    return { order, orderPerson, file, orderPersonAsset };
+  }
+
+  /**
+   * 创建批量添加人员的测试数据
+   */
+  static createBatchAddPersonsData(
+    orderId: number,
+    count: number = 3
+  ): Array<{ personId: number; joinDate: string; salaryDetail: number }> {
+    const persons: Array<{ personId: number; joinDate: string; salaryDetail: number }> = [];
+
+    for (let i = 1; i <= count; i++) {
+      persons.push({
+        personId: i,
+        joinDate: `2025-01-${10 + i}`,
+        salaryDetail: 4000 + i * 500
+      });
+    }
+
+    return persons;
+  }
+
+  /**
+   * 创建不同订单状态的测试数据
+   */
+  static createOrderWithStatus(
+    status: OrderStatus,
+    overrides: Partial<EmploymentOrder> = {}
+  ): Partial<EmploymentOrder> {
+    const baseData = this.createEmploymentOrderData(overrides);
+    const result: Partial<EmploymentOrder> = {
+      ...baseData,
+      orderStatus: status
+    };
+
+    if (status === OrderStatus.IN_PROGRESS) {
+      result.actualStartDate = new Date();
+    } else if (status === OrderStatus.COMPLETED) {
+      result.actualStartDate = new Date('2025-01-01');
+      result.actualEndDate = new Date('2025-12-31');
+    }
+
+    return result;
+  }
+
+  /**
+   * 创建不同工作状态的测试数据
+   */
+  static createOrderWithWorkStatus(
+    workStatus: WorkStatus,
+    overrides: Partial<EmploymentOrder> = {}
+  ): Partial<EmploymentOrder> {
+    const baseData = this.createEmploymentOrderData(overrides);
+    return {
+      ...baseData,
+      workStatus,
+      ...(workStatus === WorkStatus.WORKING && { actualStartDate: new Date() }),
+      ...(workStatus === WorkStatus.RESIGNED && {
+        actualStartDate: new Date('2025-01-01'),
+        actualEndDate: new Date('2025-06-30')
+      })
+    };
+  }
+
+  /**
+   * 创建不同资产类型的测试数据
+   */
+  static createAssetWithType(
+    orderId: number,
+    assetType: AssetType,
+    assetFileType: AssetFileType,
+    overrides: Partial<OrderPersonAsset> = {}
+  ): Partial<OrderPersonAsset> {
+    return {
+      orderId,
+      personId: 1,
+      fileId: 1,
+      assetType,
+      assetFileType,
+      ...overrides
+    };
+  }
+
+  /**
+   * 生成随机ID(用于测试中的personId等)
+   */
+  static generateRandomId(min: number = 1, max: number = 1000): number {
+    return Math.floor(Math.random() * (max - min + 1)) + min;
+  }
+
+  /**
+   * 生成随机日期字符串(YYYY-MM-DD格式)
+   */
+  static generateRandomDate(startYear: number = 2024, endYear: number = 2025): string {
+    const year = Math.floor(Math.random() * (endYear - startYear + 1)) + startYear;
+    const month = Math.floor(Math.random() * 12) + 1;
+    const day = Math.floor(Math.random() * 28) + 1; // 简单处理,避免日期无效
+    return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
+  }
+
+  /**
+   * 生成随机金额(保留2位小数)
+   */
+  static generateRandomAmount(min: number = 1000, max: number = 10000): number {
+    const amount = Math.random() * (max - min) + min;
+    return Math.round(amount * 100) / 100;
+  }
+}