005.001.story.md 21 KB

Story 005.001: 创建飞鹅打印模块

Status

Ready for Review

Story

As a 系统管理员 I want 能够集成飞鹅打印API so that 实现订单支付成功后自动打印小票

Acceptance Criteria

  1. 创建feie_printer_mt表,存储打印机配置信息
  2. 创建feie_print_task_mt表,记录打印任务(包含防退款延迟相关字段)
  3. 创建feie_config_mt表,存储基础打印配置
  4. 实现飞鹅API客户端,支持小票打印接口
  5. 提供打印机管理服务(添加、查询、删除打印机)
  6. 提供打印任务管理服务(提交任务、查询状态、取消任务)
  7. 实现防退款延迟打印调度器(默认2分钟延迟)
  8. 编写单元测试覆盖核心逻辑

Tasks / Subtasks

  • 任务1:创建多租户飞鹅打印模块包 (AC: 1,2,3,4,5,6,7)
    • packages/ 目录下创建 @d8d/feie-printer-module-mt
    • 配置包的基本结构:package.jsontsconfig.jsonvitest.config.ts
    • 创建数据库实体定义文件
    • 创建服务层文件
    • 创建数据验证Schema文件
    • 创建API路由文件
    • 创建类型定义文件
  • 任务2:实现数据库实体 (AC: 1,2,3)
    • 创建 feie-printer.mt.entity.ts 实体
    • 创建 feie-print-task.mt.entity.ts 实体
    • 创建 feie-config.mt.entity.ts 实体
    • 配置实体关系和多租户支持
  • 任务3:实现飞鹅API客户端服务 (AC: 4)
    • 创建 feie-api.service.ts 服务
    • 实现飞鹅API接口封装:Open_printerAddlistOpen_printerDelListOpen_queryPrinterStatusOpen_printMsgOpen_queryOrderState
    • 实现错误处理和重试逻辑
    • 实现API签名验证
  • 任务4:实现打印机管理服务 (AC: 5)
    • 创建 printer.service.ts 服务
    • 实现打印机添加、查询、删除功能
    • 实现打印机状态管理
    • 实现默认打印机设置
  • 任务5:实现打印任务管理服务 (AC: 6)
    • 创建 print-task.service.ts 服务
    • 实现打印任务提交、查询、取消功能
    • 实现打印状态更新和同步
    • 实现打印失败重试机制
  • 任务6:实现防退款延迟打印调度器 (AC: 7)
    • 创建 delay-scheduler.service.ts 服务
    • 实现延迟任务调度逻辑(默认2分钟延迟)
    • 实现退款事件监听和任务取消
    • 实现调度器健康检查和故障恢复
  • 任务7:实现API路由 (AC: 5,6)
    • 创建打印机管理API路由
    • 创建打印任务管理API路由
    • 创建打印配置管理API路由
    • 实现多租户路由中间件
  • 任务8:编写单元测试 (AC: 8)
    • 为每个服务编写单元测试
    • 为API客户端编写集成测试
    • 为调度器编写测试
    • 确保测试覆盖率 > 80%
  • 任务9:补齐集成测试用例 (AC: 8)
    • 实现配置管理API测试(获取配置、更新配置、配置验证)
    • 实现调度器管理API测试(状态查询、启动停止、健康检查)
    • 实现打印任务详情API测试
    • 实现打印机状态和更新API测试
    • 实现打印机删除API测试
    • 实现打印任务重试和取消API测试
    • 实现调度器触发API测试
    • 实现更多边界条件测试
  • 任务10:新增集成测试用例覆盖更多场景 (AC: 8)
    • 实现创建打印机API测试(正常流程、必填字段验证、默认打印机)
    • 实现打印任务状态查询API测试(状态查询、不存在的任务、不同状态的任务)
    • 实现分页和排序功能测试(打印机列表分页、打印任务列表分页、创建时间倒序排序、打印机类型筛选)
    • 实现更多错误场景测试(无效打印机类型、无效打印类型、负数延迟时间、重试次数超限、不存在的配置键)

Dev Notes

技术栈信息 [Source: architecture/tech-stack.md]

  • 运行时: Node.js 20.18.3
  • 框架: Hono 4.8.5 (Web框架和API路由,RPC类型安全)
  • 数据库: PostgreSQL 17 (通过TypeORM)
  • ORM: TypeORM 0.3.25 (数据库操作抽象,实体管理)
  • 测试框架: Vitest 2.x (单元测试框架)
  • 定时任务: node-cron latest (定时任务调度库)
  • 认证: JWT 9.0.2 (用户认证和安全,Bearer Token)

项目结构信息 [Source: architecture/source-tree.md]

  • 项目根目录: /mnt/code/186-175-template-22
  • 包位置: packages/@d8d/feie-printer-module-mt/
  • 包架构层次: 多租户模块层(-mt后缀),支持租户数据隔离
  • 多租户架构: 基于Epic-007方案,通过复制单租户包创建多租户版本
  • 租户隔离: 通过租户ID实现数据隔离,支持多租户部署

包结构规范 [Source: architecture/source-tree.md#多租户包架构]

packages/@d8d/feie-printer-module-mt/
├── src/
│   ├── entities/                  # 实体定义
│   │   ├── feie-printer.mt.entity.ts
│   │   ├── feie-print-task.mt.entity.ts
│   │   ├── feie-config.mt.entity.ts
│   │   └── index.ts
│   ├── services/                  # 服务层
│   │   ├── feie-api.service.ts    # 飞鹅API客户端(小票打印)
│   │   ├── printer.service.ts     # 打印机管理服务
│   │   ├── print-task.service.ts  # 打印任务服务
│   │   ├── delay-scheduler.service.ts  # 延迟打印调度器
│   │   └── index.ts
│   ├── schemas/                   # 数据验证
│   │   └── index.ts
│   ├── routes/                    # API路由
│   │   └── index.ts
│   ├── types/                     # 类型定义
│   │   └── index.ts
│   └── index.ts                   # 主入口文件
├── tests/                         # 测试文件
├── tsconfig.json                  # TypeScript配置
├── vitest.config.ts               # 测试配置
└── package.json

数据库设计 [Source: docs/prd/epic-005-feie-printer-integration.md#数据库设计]

-- 飞鹅打印机配置表
CREATE TABLE feie_printer_mt (
  id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  tenant_id INT UNSIGNED NOT NULL COMMENT '租户ID',
  printer_sn VARCHAR(50) NOT NULL COMMENT '打印机序列号',
  printer_key VARCHAR(100) NOT NULL COMMENT '打印机密钥',
  printer_name VARCHAR(100) COMMENT '打印机名称',
  printer_type VARCHAR(20) DEFAULT '58mm' COMMENT '打印机类型: 58mm, 80mm',
  printer_status VARCHAR(20) DEFAULT 'ACTIVE' COMMENT '打印机状态: ACTIVE, INACTIVE, ERROR',
  is_default TINYINT DEFAULT 0 COMMENT '是否默认打印机(0:否,1:是)',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_tenant_printer_sn (tenant_id, printer_sn),
  INDEX idx_tenant_id (tenant_id),
  INDEX idx_status (printer_status)
) COMMENT='飞鹅打印机配置表';

-- 飞鹅打印任务表(支持防退款延迟打印)
CREATE TABLE feie_print_task_mt (
  id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  tenant_id INT UNSIGNED NOT NULL COMMENT '租户ID',
  task_id VARCHAR(100) NOT NULL COMMENT '飞鹅任务ID',
  order_id INT UNSIGNED COMMENT '关联订单ID',
  printer_sn VARCHAR(50) NOT NULL COMMENT '打印机序列号',
  content TEXT NOT NULL COMMENT '打印内容',
  print_type VARCHAR(20) NOT NULL COMMENT '打印类型: RECEIPT(小票), SHIPPING(发货单), ORDER(订单)',
  print_status VARCHAR(20) DEFAULT 'PENDING' COMMENT '打印状态: PENDING, DELAYED(延迟等待), PRINTING, SUCCESS, FAILED, CANCELLED(已取消)',
  error_message VARCHAR(500) COMMENT '错误信息',
  retry_count INT DEFAULT 0 COMMENT '重试次数',
  max_retries INT DEFAULT 3 COMMENT '最大重试次数',
  scheduled_at TIMESTAMP NULL COMMENT '计划打印时间(用于延迟打印)',
  printed_at TIMESTAMP NULL COMMENT '打印完成时间',
  cancelled_at TIMESTAMP NULL COMMENT '取消时间',
  cancel_reason VARCHAR(100) COMMENT '取消原因: REFUND(退款), MANUAL(手动取消), TIMEOUT(超时)',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_task_id (task_id),
  INDEX idx_tenant_order (tenant_id, order_id),
  INDEX idx_status (print_status),
  INDEX idx_scheduled (scheduled_at),
  INDEX idx_created (created_at)
) COMMENT='飞鹅打印任务表';

-- 打印配置表
CREATE TABLE feie_config_mt (
  id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  tenant_id INT UNSIGNED NOT NULL COMMENT '租户ID',
  config_key VARCHAR(50) NOT NULL COMMENT '配置键',
  config_value TEXT COMMENT '配置值',
  config_type VARCHAR(20) DEFAULT 'STRING' COMMENT '配置类型: STRING, JSON, BOOLEAN, NUMBER',
  description VARCHAR(200) COMMENT '配置描述',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_tenant_key (tenant_id, config_key),
  INDEX idx_tenant_id (tenant_id)
) COMMENT='飞鹅打印配置表';

API设计 [Source: docs/prd/epic-005-feie-printer-integration.md#API设计]

飞鹅打印模块API

  1. GET /api/feie/printers - 查询打印机列表
  2. POST /api/feie/printers - 添加打印机
  3. DELETE /api/feie/printers/{printerSn} - 删除打印机
  4. POST /api/feie/print - 提交打印任务(支持延迟打印)
  5. GET /api/feie/tasks/{taskId} - 查询打印任务状态
  6. GET /api/feie/tasks - 查询打印任务列表
  7. POST /api/feie/tasks/{taskId}/cancel - 取消打印任务
  8. POST /api/feie/tasks/{taskId}/retry - 重试打印任务
  9. GET /api/feie/config - 查询打印配置
  10. PUT /api/feie/config - 更新打印配置

飞鹅API接口(需要封装)

  1. 打印机管理

    • Open_printerAddlist - 添加打印机
    • Open_printerDelList - 删除打印机
    • Open_queryPrinterStatus - 查询打印机状态
  2. 打印任务管理

    • Open_printMsg - 打印小票
    • Open_queryOrderState - 查询订单打印状态
    • Open_queryOrderInfoByDate - 根据时间查询订单

编码标准 [Source: architecture/coding-standards.md]

  • 代码风格: TypeScript严格模式,一致的缩进和命名
  • 测试框架: 使用Vitest + Testing Library + hono/testing
  • 测试位置: __tests__ 文件夹与源码并列
  • 覆盖率目标: 核心业务逻辑 > 80%
  • 测试类型: 单元测试、集成测试、E2E测试
  • RPC客户端架构: 使用单例模式的客户端管理器,类型安全的Hono RPC

测试标准

  • 测试文件位置: 每个包独立的 tests/ 目录
  • 测试框架: Vitest 2.x
  • 测试模式: 单元测试覆盖核心逻辑,集成测试验证API功能
  • 覆盖率要求: 核心业务逻辑 > 80%
  • 测试数据: 使用测试数据库,避免污染生产数据
  • 错误处理测试: 测试各种错误场景和边界条件

多租户实现要求

  • 包命名: 使用 -mt 后缀表示多租户包
  • 租户ID字段: 所有实体必须包含 tenant_id 字段
  • 数据隔离: 通过租户ID实现数据查询隔离
  • 路由中间件: 实现多租户路由中间件,自动注入租户上下文
  • 权限控制: 确保租户只能访问自己的数据

防退款延迟打印机制

  • 默认延迟时间: 120秒(2分钟)
  • 状态管理: 打印任务状态包括 PENDINGDELAYEDPRINTINGSUCCESSFAILEDCANCELLED
  • 取消场景: REFUND(退款)、MANUAL(手动取消)、TIMEOUT(超时)
  • 调度器设计: 使用 node-cron 实现定时任务调度
  • 退款监听: 监听订单退款事件,自动取消延迟打印任务

项目结构对齐说明

  • 新包 @d8d/feie-printer-module-mt 应放置在 packages/ 目录下
  • 包结构应遵循现有的多租户模块包模式
  • 需要与现有的 @d8d/orders-module-mt 集成,监听订单支付成功事件
  • API路由应遵循现有的RESTful API设计模式

Testing

测试框架和标准

  • 测试框架: Vitest 2.x [Source: architecture/tech-stack.md]
  • 测试位置: __tests__ 文件夹与源码并列 [Source: architecture/coding-standards.md]
  • 覆盖率目标: 核心业务逻辑 > 80% [Source: architecture/coding-standards.md]
  • 测试类型: 单元测试、集成测试 [Source: architecture/coding-standards.md]

具体测试要求

  1. 单元测试:

    • 飞鹅API客户端测试
    • 打印机管理逻辑测试
    • 打印任务管理测试
    • 防退款延迟调度器测试
  2. 集成测试:

    • 飞鹅API集成测试(使用模拟API)
    • API路由功能测试
    • 多租户数据隔离测试
  3. 测试文件结构:

    tests/
    ├── unit/
    │   ├── feie-api.service.test.ts
    │   ├── printer.service.test.ts
    │   ├── print-task.service.test.ts
    │   └── delay-scheduler.service.test.ts
    └── integration/
       ├── api/
       │   ├── printers.test.ts
       │   ├── print-tasks.test.ts
       │   └── config.test.ts
       └── feie-api.integration.test.ts
    

Change Log

Date Version Description Author
2025-12-06 1.0 初始创建故事文档 Bob (Scrum Master)
2025-12-11 1.1 修复TypeScript类型错误:路由返回类型、枚举类型、参数转换等问题 James (Developer Agent)
2025-12-11 1.2 补齐集成测试用例:新增28个测试用例,覆盖配置管理、调度器管理、打印任务详情、打印机状态更新、边界条件等 James (Developer Agent)
2025-12-11 1.3 新增集成测试用例:补充15个测试用例,覆盖创建打印机API、打印任务状态查询、分页排序功能、更多错误场景等 James (Developer Agent)

Dev Agent Record

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

Agent Model Used

  • 代理名称: James (Developer Agent)
  • 模型: Claude Sonnet 4.5
  • 初始执行时间: 2025-12-06
  • 修复执行时间: 2025-12-11

Debug Log References

  • 创建了完整的飞鹅打印多租户模块包结构
  • 实现了所有数据库实体(3个实体)
  • 实现了飞鹅API客户端服务
  • 实现了打印机管理服务
  • 实现了打印任务管理服务
  • 实现了防退款延迟打印调度器
  • 实现了API路由
  • 编写了单元测试和集成测试
  • 修复TypeScript类型错误(2025-12-11):
    • 修复路由处理程序返回类型不匹配:为所有 c.json(validatedResponse) 添加状态码
    • 修复枚举类型不匹配:printerType['RECEIPT', 'LABEL'] 改为 ['58mm', '80mm']
    • 修复 PrintType 枚举使用:使用 z.nativeEnum(PrintType) 替代字符串字面量
    • 修复服务方法参数类型转换:正确处理 CreatePrintTaskDto 转换
    • 修复Schema转换逻辑:使用Zod transform 处理 'ALL' 选项
    • 修复调度器响应类型:调整响应数据匹配Schema

Completion Notes List

  1. ✅ 任务1:创建多租户飞鹅打印模块包 (@d8d/feie-printer-module-mt)
  2. ✅ 任务2:实现数据库实体(3个实体文件)
  3. ✅ 任务3:实现飞鹅API客户端服务
  4. ✅ 任务4:实现打印机管理服务
  5. ✅ 任务5:实现打印任务管理服务
  6. ✅ 任务6:实现防退款延迟打印调度器
  7. ✅ 任务7:实现API路由
  8. ✅ 任务8:编写单元测试
  9. ✅ 执行完整验证和测试
  10. ✅ 任务9:修复TypeScript类型错误(2025-12-11)
    • 修复路由处理程序返回类型不匹配问题
    • 修复枚举类型不匹配问题(printerType、PrintType)
    • 修复服务方法参数类型转换问题
    • 修复Schema转换逻辑问题
    • 修复调度器响应类型不匹配问题
  11. ✅ 任务10:补齐集成测试用例(已完成)
    • 分析现有集成测试覆盖度,识别缺失的测试用例
    • 为故事添加新任务:补齐缺失的集成测试用例
    • 实现配置管理API测试(获取配置、更新配置、配置验证)
    • 实现调度器管理API测试(状态查询、启动停止、健康检查、手动触发)
    • 实现打印任务详情API测试(查询详情、不存在的任务)
    • 实现打印机状态和更新API测试(状态查询、更新、删除)
    • 实现打印任务重试和取消API测试
    • 实现更多边界条件测试(序列号重复、内容过长、延迟时间边界、状态转换)
    • 修复测试中的配置清理问题,确保测试独立性
  12. ✅ 任务11:新增集成测试用例覆盖更多场景(已完成)
    • 分析测试覆盖度,识别需要补充的测试场景
    • 实现创建打印机API测试(正常流程、必填字段验证、默认打印机)
    • 实现打印任务状态查询API测试(状态查询、不存在的任务、不同状态的任务)
    • 实现分页和排序功能测试(打印机列表分页、打印任务列表分页、创建时间倒序排序、打印机类型筛选)
    • 实现更多错误场景测试(无效打印机类型、无效打印类型、负数延迟时间、重试次数超限、不存在的配置键)
    • 修复TypeScript类型错误(PrintType枚举使用、打印机类型、响应格式匹配)

File List

包结构文件:

  • packages/feie-printer-module-mt/package.json
  • packages/feie-printer-module-mt/tsconfig.json
  • packages/feie-printer-module-mt/vitest.config.ts

源代码文件:

  • packages/feie-printer-module-mt/src/index.ts
  • packages/feie-printer-module-mt/src/entities/feie-printer.mt.entity.ts
  • packages/feie-printer-module-mt/src/entities/feie-print-task.mt.entity.ts
  • packages/feie-printer-module-mt/src/entities/feie-config.mt.entity.ts
  • packages/feie-printer-module-mt/src/entities/index.ts
  • packages/feie-printer-module-mt/src/services/feie-api.service.ts
  • packages/feie-printer-module-mt/src/services/printer.service.ts
  • packages/feie-printer-module-mt/src/services/print-task.service.ts
  • packages/feie-printer-module-mt/src/services/delay-scheduler.service.ts
  • packages/feie-printer-module-mt/src/services/index.ts
  • packages/feie-printer-module-mt/src/schemas/feie.schema.ts
  • packages/feie-printer-module-mt/src/schemas/index.ts
  • packages/feie-printer-module-mt/src/routes/feie.routes.ts
  • packages/feie-printer-module-mt/src/routes/index.ts
  • packages/feie-printer-module-mt/src/types/feie.types.ts
  • packages/feie-printer-module-mt/src/types/index.ts

修复的文件(TypeScript类型错误修复):

  • packages/feie-printer-module-mt/src/routes/printers/create.mt.ts - 修复路由返回类型,添加状态码
  • packages/feie-printer-module-mt/src/routes/printers/update.mt.ts - 修复printerType枚举,添加状态码
  • packages/feie-printer-module-mt/src/routes/printers/detail.mt.ts - 添加状态码
  • packages/feie-printer-module-mt/src/routes/printers/delete.mt.ts - 添加状态码
  • packages/feie-printer-module-mt/src/routes/printers/set-default.mt.ts - 添加状态码
  • packages/feie-printer-module-mt/src/routes/printers/status.mt.ts - 添加状态码
  • packages/feie-printer-module-mt/src/routes/printers/list.mt.ts - 添加状态码
  • packages/feie-printer-module-mt/src/routes/tasks/create.mt.ts - 修复PrintType枚举,添加DTO转换,添加状态码
  • packages/feie-printer-module-mt/src/routes/tasks/list.mt.ts - 修复PrintType/PrintStatus枚举,修复转换逻辑,添加状态码
  • packages/feie-printer-module-mt/src/routes/tasks/status.mt.ts - 添加状态码
  • packages/feie-printer-module-mt/src/routes/tasks/cancel.mt.ts - 添加状态码
  • packages/feie-printer-module-mt/src/routes/tasks/retry.mt.ts - 添加状态码
  • packages/feie-printer-module-mt/src/routes/scheduler/start.mt.ts - 添加状态码
  • packages/feie-printer-module-mt/src/routes/scheduler/stop.mt.ts - 添加状态码
  • packages/feie-printer-module-mt/src/routes/scheduler/trigger.mt.ts - 修复响应类型匹配,添加状态码

测试文件:

  • packages/feie-printer-module-mt/tests/unit/feie-api.service.test.ts
  • packages/feie-printer-module-mt/tests/unit/printer.service.test.ts
  • packages/feie-printer-module-mt/tests/unit/print-task.service.test.ts
  • packages/feie-printer-module-mt/tests/unit/delay-scheduler.service.test.ts
  • packages/feie-printer-module-mt/tests/integration/feie-api.integration.test.ts - 新增完整的集成测试用例

新增的集成测试用例文件:

  • packages/feie-printer-module-mt/tests/integration/feie-api.integration.test.ts - 已更新,包含:
    • 配置管理API测试(3个测试用例)
    • 调度器管理API测试(4个测试用例)
    • 打印任务详情API测试(2个测试用例)
    • 打印机状态和更新API测试(6个测试用例)
    • 打印机删除API测试(2个测试用例)
    • 打印任务重试和取消API测试(4个测试用例)
    • 调度器触发API测试(1个测试用例)
    • 更多边界条件测试(6个测试用例)
    • 修复了测试配置清理问题
    • 新增测试场景
    • 创建打印机API测试(3个测试用例)
    • 打印任务状态查询API测试(3个测试用例)
    • 分页和排序功能测试(4个测试用例)
    • 更多错误场景测试(5个测试用例)

QA Results

此部分由QA代理在审查完成后填写