007.006.transplant-platform-management-module.story.md 22 KB

Story 007.006: 移植平台管理模块(platform → @d8d/allin-platform-module)

Status

Draft

Story

As a 开发者, I want 将platform模块从allin_system-master移植为独立包@d8d/allin-platform-module,作为基础依赖模块为其他模块提供平台数据支持, so that 我们可以将Allin系统的平台管理功能集成到当前项目中,遵循现有的模块化架构和编码标准,并为company-module等依赖模块提供基础数据支持。

Acceptance Criteria

  1. ✅ 创建allin-packages/platform-module目录结构
  2. ✅ 完成实体转换:Platform实体转换
  3. ✅ 完成服务层转换:基础CRUD服务
  4. ✅ 完成路由层转换:Hono路由实现
  5. ✅ 完成验证系统转换:Zod Schema定义
  6. ✅ 配置package.json:作为基础依赖包
  7. ✅ 编写API集成测试:验证基础功能
  8. ✅ 通过类型检查和基本测试验证
  9. ✅ 验证作为依赖包被其他模块引用的能力

Tasks / Subtasks

  • 创建allin-packages/platform-module目录结构 (AC: 1)
    • 创建allin-packages/platform-module/目录
    • 创建package.json文件,配置包名@d8d/allin-platform-module和workspace依赖
    • 参考文件: allin-packages/channel-module/package.json
    • 修改点: 包名改为@d8d/allin-platform-module,依赖调整
    • 关键依赖: 作为基础包,不需要依赖其他allin模块
    • 注意吸取经验: 根据故事007.001的经验,需要在pnpm-workspace.yaml中添加allin-packages/*配置
    • 创建tsconfig.json文件,配置TypeScript编译选项
    • 参考文件: allin-packages/channel-module/tsconfig.json
    • 创建vitest.config.ts文件,配置测试环境
    • 参考文件: allin-packages/channel-module/vitest.config.ts
    • 创建src/目录结构:entities/, services/, routes/, schemas/, types/
    • 参考结构: allin-packages/channel-module/src/目录结构
  • 完成实体转换:Platform实体转换 (AC: 2)
    • 分析源实体allin_system-master/server/src/platform/platform.entity.ts
    • 源文件: allin_system-master/server/src/platform/platform.entity.ts
    • 关键字段: platform_id, platform_name, contact_person, contact_phone, contact_email, status, create_time, update_time
    • 注意吸取经验: 根据故事007.001的经验,主键属性名应直接定义为id(而不是platformId)以遵循GenericCrudService约定
    • 迁移文件路径: allin-packages/platform-module/src/entities/platform.entity.ts
    • 创建转换后的实体文件src/entities/platform.entity.ts
    • 参考文件: allin-packages/channel-module/src/entities/channel.entity.ts
    • 转换要点: 下划线命名 → 驼峰命名,添加详细TypeORM配置
    • 将下划线字段名转换为驼峰命名: platform_idid, platform_nameplatformName, contact_personcontactPerson
    • 添加详细的TypeORM装饰器配置: @Column({ name: 'platform_name', type: 'varchar', length: 100 })
    • 保持数据库表名不变: @Entity('employer_platform')
    • 添加必要的索引和约束配置: 平台名称唯一性索引
  • 完成服务层转换:基础CRUD服务 (AC: 3)
    • 分析源服务allin_system-master/server/src/platform/platform.service.ts
    • 源文件: allin_system-master/server/src/platform/platform.service.ts
    • 关键方法: createPlatform, deletePlatform, findAll, searchByName, findOne, updatePlatform
    • 业务逻辑: 平台名称唯一性检查,分页查询,模糊搜索
    • 创建转换后的服务文件src/services/platform.service.ts
    • 参考文件: allin-packages/channel-module/src/services/channel.service.ts
    • 架构: 继承GenericCrudService<Platform>
    • 迁移文件路径: allin-packages/platform-module/src/services/platform.service.ts
    • 继承GenericCrudService<Platform>,配置搜索字段
    • 参考: packages/shared-crud/src/services/generic-crud.service.ts
    • 搜索字段: ['platformName', 'contactPerson', 'contactPhone']
    • 覆盖create方法:添加平台名称唯一性检查
    • 源逻辑: platform.service.ts:14-36 - 检查platform_name是否已存在
    • 注意吸取经验: 根据故事007.001的经验,需要正确处理布尔返回值转换
    • 覆盖update方法:检查平台存在性和名称重复性
    • 源逻辑: platform.service.ts:68-92 - 检查平台是否存在,检查更新后的名称是否与其他平台重复
    • 覆盖delete方法:当前为硬删除,考虑改为软删除(使用status字段)
    • 源逻辑: platform.service.ts:38-41 - 直接删除记录
    • 建议: 改为软删除,设置status为0或删除状态
    • 覆盖findAll方法:需要返回{ data: Platform[], total: number }格式
    • 源逻辑: platform.service.ts:43-50 - 使用findAndCount返回数据和总数
    • 排序: 默认按platform_id降序排列
    • 自定义searchByName方法:按名称模糊搜索
    • 源逻辑: platform.service.ts:52-62 - 使用Like操作符进行模糊匹配
    • 自定义findOne方法:查询单个平台
    • 源逻辑: platform.service.ts:64-66 - 根据ID查询单个平台
  • 完成路由层转换:Hono路由实现 (AC: 4)
    • 分析源控制器allin_system-master/server/src/platform/platform.controller.ts
    • 源文件: allin_system-master/server/src/platform/platform.controller.ts
    • API端点:
      • POST /platform/createPlatform - 创建平台
      • POST /platform/deletePlatform - 删除平台
      • POST /platform/updatePlatform - 更新平台
      • GET /platform/getAllPlatforms - 获取所有平台(分页)
      • GET /platform/searchPlatforms - 搜索平台(按名称)
      • GET /platform/getPlatform/:id - 获取单个平台详情
    • 认证: 所有端点需要JWT认证 (@UseGuards(JwtAuthGuard))
    • 创建自定义路由文件src/routes/platform-custom.routes.ts
    • 参考文件: allin-packages/channel-module/src/routes/channel-custom.routes.ts
    • 迁移文件路径: allin-packages/platform-module/src/routes/platform-custom.routes.ts
    • 自定义POST /createPlatform路由:处理布尔返回值
    • 返回格式: 成功返回{ success: true },失败返回{ success: false }
    • 源逻辑: platform.controller.ts:11-14platform.service.ts:14-36
    • 参考模式: allin-packages/channel-module/src/routes/channel-custom.routes.ts中的createChannelRoute
    • 自定义POST /deletePlatform路由:处理布尔返回值
    • 返回格式: 成功返回{ success: true },失败返回{ success: false }
    • 源逻辑: platform.controller.ts:16-19platform.service.ts:38-41
    • 参考模式: allin-packages/channel-module/src/routes/channel-custom.routes.ts中的deleteChannelRoute
    • 自定义POST /updatePlatform路由:处理布尔返回值
    • 返回格式: 成功返回{ success: true },失败返回{ success: false, message: "平台不存在或名称重复" }
    • 源逻辑: platform.controller.ts:21-24platform.service.ts:68-92
    • 参考模式: allin-packages/channel-module/src/routes/channel-custom.routes.ts中的updateChannelRoute
    • 自定义GET /getAllPlatforms路由:处理分页参数和返回格式
    • 参数: skip, take查询参数
    • 返回格式: { data: Platform[], total: number }
    • 源逻辑: platform.controller.ts:26-29platform.service.ts:43-50
    • 参考模式: 自定义分页查询路由,参考allin-packages/channel-module/src/routes/channel-custom.routes.ts中的getAllChannelsRoute
    • 自定义GET /searchPlatforms路由:处理搜索功能
    • 参数: name(搜索关键词),skip, take(分页参数)
    • 返回格式: { data: Platform[], total: number }
    • 源逻辑: platform.controller.ts:31-34platform.service.ts:52-62
    • 参考模式: 自定义搜索路由,参考allin-packages/channel-module/src/routes/channel-custom.routes.ts中的searchChannelsRoute
    • 自定义GET /getPlatform/:id路由:处理单个平台查询
    • 参数: id路径参数
    • 返回格式: Platform对象或null
    • 源逻辑: platform.controller.ts:36-39platform.service.ts:64-66
    • 参考模式: allin-packages/channel-module/src/routes/channel-custom.routes.ts中的参数验证和错误处理
    • 创建CRUD路由文件src/routes/platform-crud.routes.ts
    • 参考文件: allin-packages/channel-module/src/routes/channel-crud.routes.ts
    • 架构: 使用createCrudRoutes生成标准CRUD路由
    • 配置: 配置entity, createSchema, updateSchema, getSchema, listSchema, searchFields等参数
    • 注意: 设置readOnly: true,因为创建、更新、删除操作通过自定义路由处理
    • 创建主路由文件src/routes/platform.routes.ts
    • 参考文件: allin-packages/channel-module/src/routes/channel.routes.ts
    • 功能: 聚合自定义路由和CRUD路由,导出路由实例
  • 完成验证系统转换:从class-validator DTO转换为Zod Schema (AC: 5)
    • 分析源DTOallin_system-master/server/src/platform/platform.dto.ts
    • 源文件: allin_system-master/server/src/platform/platform.dto.ts
    • DTO类型: CreatePlatformDto, UpdatePlatformDto, DeletePlatformDto
    • 创建转换后的Schema文件src/schemas/platform.schema.ts
    • 参考文件: allin-packages/channel-module/src/schemas/channel.schema.ts
    • 迁移文件路径: allin-packages/platform-module/src/schemas/platform.schema.ts
    • 使用z.object()定义CreatePlatformSchema, UpdatePlatformSchema, DeletePlatformSchema
    • 添加详细的验证规则:字符串长度、必填字段、可选字段、邮箱格式验证
    • 创建对应的TypeScript类型定义:CreatePlatformDto, UpdatePlatformDto, DeletePlatformDto
  • 配置package.json:workspace依赖管理 (AC: 6)
    • 配置package.json中的name字段为@d8d/allin-platform-module
    • 参考文件: allin-packages/channel-module/package.json
    • 设置type: "module"和主入口src/index.ts
    • 添加workspace依赖:@d8d/core-module, @d8d/shared-crud, @d8d/shared-utils
    • 添加外部依赖:@hono/zod-openapi, typeorm, zod
    • 配置导出路径:services, schemas, routes, entities
  • 编写API集成测试:验证基础功能 (AC: 7)
    • 创建测试文件tests/integration/platform.integration.test.ts
    • 参考文件: allin-packages/channel-module/tests/integration/channel.integration.test.ts
    • 迁移文件路径: allin-packages/platform-module/tests/integration/platform.integration.test.ts
    • 参考channel-module的集成测试模式
    • 测试模式: 使用testClient, setupIntegrationDatabaseHooksWithEntities
    • 使用testClient创建测试客户端
    • 使用setupIntegrationDatabaseHooksWithEntities设置测试数据库
    • 工具: @d8d/shared-test-util中的测试基础设施
    • 编写测试用例覆盖所有端点:创建、查询、更新、删除、搜索
    • 添加认证测试、数据验证测试、错误处理测试
    • 包含边界条件和异常场景测试
    • 特别测试平台名称唯一性检查功能
  • 通过类型检查和基本测试验证 (AC: 8)
    • 运行pnpm typecheck确保无类型错误
    • 运行pnpm test确保所有测试通过
    • 运行pnpm test:integration验证集成测试
    • 检查测试覆盖率是否满足要求
    • 标准: 集成测试 ≥ 60% [Source: architecture/testing-strategy.md#测试覆盖率标准]
    • 验证模块可以正确导入和使用
  • 验证作为依赖包被其他模块引用的能力 (AC: 9)
    • 验证company-module可以正确导入platform-module的实体
    • 导入路径: import { Platform } from '@d8d/allin-platform-module/entities';
    • 验证company-module可以正确引用platform-module的服务
    • 测试跨模块关联查询功能
    • 验证workspace依赖配置正确性

Dev Notes

先前故事洞察

  • 故事007.001:已完成渠道管理模块移植,提供了完整的参考实现 [Source: docs/stories/007.001.transplant-channel-management-module.story.md]
  • 关键经验教训
    1. 实体主键命名:根据用户反馈,主键属性名应直接定义为id(而不是channelId)以遵循GenericCrudService约定
    2. workspace配置:需要在pnpm-workspace.yaml中添加allin-packages/*配置
    3. 测试依赖:需要添加@d8d/user-module@d8d/file-module依赖
    4. 类型检查:需要注意导出重复和路由返回类型问题
    5. API兼容性:需要保持原始API的布尔返回值格式

数据模型

  • 源实体结构Platform实体包含以下字段 [Source: allin_system-master/server/src/platform/platform.entity.ts]:
    • platform_id: number (主键,自增)
    • platform_name: string (平台名称)
    • contact_person: string (联系人)
    • contact_phone: string (联系电话)
    • contact_email?: string (联系邮箱,可选)
    • status: number (状态,默认1)
    • create_time: Date (创建时间)
    • update_time: Date (更新时间)
  • 转换要求:下划线命名 → 驼峰命名,添加详细TypeORM配置
  • 表名保持employer_platform表名不变
  • 唯一性约束:平台名称需要唯一性检查

自定义实现分析

  • 需要覆盖GenericCrudService的方法

    • create方法:需要添加平台名称唯一性检查
    • 源逻辑: platform.service.ts:14-36 - 检查platform_name是否已存在
    • 默认值设置: 创建时设置status为1,create_timeupdate_time为当前时间
    • update方法:需要检查平台存在性和名称重复性
    • 源逻辑: platform.service.ts:68-92 - 检查平台是否存在,检查更新后的名称是否与其他平台重复
    • 更新时间: 自动设置update_time为当前时间
    • delete方法:当前为硬删除,考虑改为软删除(使用status字段)
    • 源逻辑: platform.service.ts:38-41 - 直接删除记录
    • 建议: 改为软删除,设置status为0或删除状态
    • findAll方法:需要返回{ data: Platform[], total: number }格式
    • 源逻辑: platform.service.ts:43-50 - 使用findAndCount返回数据和总数
    • 排序: 默认按platform_id降序排列
    • 自定义searchByName方法:按名称模糊搜索
    • 源逻辑: platform.service.ts:52-62 - 使用Like操作符进行模糊匹配
    • 自定义findOne方法:查询单个平台
    • 源逻辑: platform.service.ts:64-66 - 根据ID查询单个平台
  • 与GenericCrudService的差异

    • 返回值格式:源服务返回布尔值或分页对象,GenericCrudService返回实体对象
    • 验证逻辑:源服务有自定义的业务验证逻辑(平台名称唯一性检查)
    • 搜索功能:源服务有专门的按名称搜索功能

API规范

  • 现有API端点 [Source: allin_system-master/server/src/platform/platform.controller.ts]:
    • POST /platform/createPlatform - 创建平台
    • POST /platform/deletePlatform - 删除平台
    • POST /platform/updatePlatform - 更新平台
    • GET /platform/getAllPlatforms - 获取所有平台(分页)
    • GET /platform/searchPlatforms - 搜索平台(按名称)
    • GET /platform/getPlatform/:id - 获取单个平台详情
  • 认证要求:所有端点需要JWT认证 (@UseGuards(JwtAuthGuard))
  • 转换策略:NestJS控制器 → Hono路由,保持相同的端点路径和功能

服务规范

  • 源服务逻辑 [Source: allin_system-master/server/src/platform/platform.service.ts]:
    • createPlatform: 检查名称重复,设置默认值,插入数据
    • deletePlatform: 根据ID删除
    • findAll: 分页查询,按ID降序排序
    • searchByName: 按名称模糊搜索,分页查询
    • findOne: 根据ID查询单个
    • updatePlatform: 检查存在性,检查名称重复,更新数据
  • 转换策略:继承GenericCrudService,复用现有CRUD模式,保持业务逻辑

验证系统

  • 源DTO结构 [Source: allin_system-master/server/src/platform/platform.dto.ts]:
    • CreatePlatformDto: platform_name(必填), contact_person(可选), contact_phone(可选), contact_email(可选)
    • UpdatePlatformDto: platform_id(必填), platform_name(可选), contact_person(可选), contact_phone(可选), contact_email(可选)
    • DeletePlatformDto: platform_id(必填)
  • 转换策略class-validatorZod Schema,添加详细的验证规则

文件位置

  • 包目录allin-packages/platform-module/ (根据史诗007的目录结构决策)
  • 源文件位置
    • 实体源文件: allin_system-master/server/src/platform/platform.entity.ts
    • 服务源文件: allin_system-master/server/src/platform/platform.service.ts
    • 控制器源文件: allin_system-master/server/src/platform/platform.controller.ts
    • DTO源文件: allin_system-master/server/src/platform/platform.dto.ts
  • 目标文件位置
    • 实体文件: src/entities/platform.entity.ts
    • 参考文件: allin-packages/channel-module/src/entities/channel.entity.ts
    • 迁移文件路径: allin-packages/platform-module/src/entities/platform.entity.ts
    • 服务文件: src/services/platform.service.ts
    • 参考文件: allin-packages/channel-module/src/services/channel.service.ts
    • 迁移文件路径: allin-packages/platform-module/src/services/platform.service.ts
    • 主路由文件: src/routes/platform.routes.ts
    • 参考文件: allin-packages/channel-module/src/routes/channel.routes.ts
    • 迁移文件路径: allin-packages/platform-module/src/routes/platform.routes.ts
    • 自定义路由文件: src/routes/platform-custom.routes.ts
    • 参考文件: allin-packages/channel-module/src/routes/channel-custom.routes.ts
    • 迁移文件路径: allin-packages/platform-module/src/routes/platform-custom.routes.ts
    • CRUD路由文件: src/routes/platform-crud.routes.ts
    • 参考文件: allin-packages/channel-module/src/routes/channel-crud.routes.ts
    • 迁移文件路径: allin-packages/platform-module/src/routes/platform-crud.routes.ts
    • Schema文件: src/schemas/platform.schema.ts
    • 参考文件: allin-packages/channel-module/src/schemas/channel.schema.ts
    • 迁移文件路径: allin-packages/platform-module/src/schemas/platform.schema.ts
    • 测试文件: tests/integration/platform.integration.test.ts
    • 参考文件: allin-packages/channel-module/tests/integration/channel.integration.test.ts
    • 迁移文件路径: allin-packages/platform-module/tests/integration/platform.integration.test.ts
    • 包配置: package.json, tsconfig.json, vitest.config.ts
    • 参考文件: allin-packages/channel-module/中的对应配置文件

测试要求

  • 测试框架:Vitest [Source: architecture/testing-strategy.md#单元测试]
  • 测试位置tests/integration/目录 [Source: architecture/testing-strategy.md#测试金字塔策略]
  • 测试类型:集成测试,验证API端点和数据库交互 [Source: architecture/testing-strategy.md#集成测试]
  • 覆盖率目标:集成测试 ≥ 60% [Source: architecture/testing-strategy.md#测试覆盖率标准]
  • 测试模式:参考channel-module的集成测试模式 [Source: allin-packages/channel-module/tests/integration/channel.integration.test.ts]
  • 测试工具:使用@d8d/shared-test-util中的测试基础设施 [Source: architecture/testing-strategy.md#包测试架构]

技术约束

  • 技术栈:Node.js 20.19.2, Hono 4.8.5, TypeORM 0.3.25, PostgreSQL 17 [Source: architecture/tech-stack.md]
  • 编码标准:TypeScript严格模式,一致的缩进和命名 [Source: architecture/coding-standards.md]
  • API设计:RESTful API设计,使用Hono框架 [Source: architecture/source-tree.md#API设计]
  • 包管理:使用pnpm workspace管理依赖 [Source: architecture/source-tree.md#集成指南]
  • 模块导出:通过src/index.ts统一导出 [Source: architecture/source-tree.md#包结构规范]

项目结构注意事项

  • 目录结构冲突:根据史诗007决策,Allin系统专属包放在allin-packages/目录,而非通用的packages/目录
  • 命名规范:使用@d8d/allin-前缀,-module后缀,非多租户版本
  • 依赖管理:通过workspace依赖引用@d8d/core-module和其他共享包,作为基础包不需要依赖其他allin模块
  • 依赖顺序问题:platform-module是基础依赖模块,需要先于company-module创建

测试标准

  1. API端点测试:必须覆盖所有6个端点(创建、删除、更新、查询所有、搜索、查询单个)
  2. 认证测试:验证所有端点需要有效的JWT令牌
  3. 数据验证测试:测试输入验证规则(必填字段、字符串长度、数据类型、邮箱格式)
  4. 业务逻辑测试:测试平台名称唯一性检查、分页查询、模糊搜索
  5. 错误处理测试:测试各种错误场景(无效ID、重复名称、缺失字段)
  6. 数据库集成测试:验证数据正确持久化和查询
  7. 测试数据管理:使用测试数据工厂模式,每个测试后清理数据

测试执行流程

  1. 设置测试数据库,包含Platform实体
  2. 创建测试用户和认证令牌
  3. 为每个端点编写成功场景测试
  4. 为每个端点编写失败场景测试
  5. 验证响应格式和数据正确性
  6. 检查数据库状态变化

Change Log

Date Version Description Author
2025-12-02 1.0 初始故事创建 Bob (Scrum Master)

Dev Agent Record

此部分由开发代理在实现过程中填写

Agent Model Used

Debug Log References

Completion Notes List

File List

QA Results

Results from QA Agent QA review of the completed story implementation