# Story 005.001: 创建飞鹅打印模块 ## Status Ready for Review ## Story **As a** 系统管理员 **I want** 能够集成飞鹅打印API **so that** 实现订单支付成功后自动打印小票 ## Acceptance Criteria 1. [x] 创建`feie_printer_mt`表,存储打印机配置信息 2. [x] 创建`feie_print_task_mt`表,记录打印任务(包含防退款延迟相关字段) 3. [x] 创建`feie_config_mt`表,存储基础打印配置 4. [x] 实现飞鹅API客户端,支持小票打印接口 5. [x] 提供打印机管理服务(添加、查询、删除打印机) 6. [x] 提供打印任务管理服务(提交任务、查询状态、取消任务) 7. [x] 实现防退款延迟打印调度器(默认2分钟延迟) 8. [x] 编写单元测试覆盖核心逻辑 ## Tasks / Subtasks - [x] 任务1:创建多租户飞鹅打印模块包 (AC: 1,2,3,4,5,6,7) - [x] 在 `packages/` 目录下创建 `@d8d/feie-printer-module-mt` 包 - [x] 配置包的基本结构:`package.json`、`tsconfig.json`、`vitest.config.ts` - [x] 创建数据库实体定义文件 - [x] 创建服务层文件 - [x] 创建数据验证Schema文件 - [x] 创建API路由文件 - [x] 创建类型定义文件 - [x] 任务2:实现数据库实体 (AC: 1,2,3) - [x] 创建 `feie-printer.mt.entity.ts` 实体 - [x] 创建 `feie-print-task.mt.entity.ts` 实体 - [x] 创建 `feie-config.mt.entity.ts` 实体 - [x] 配置实体关系和多租户支持 - [x] 任务3:实现飞鹅API客户端服务 (AC: 4) - [x] 创建 `feie-api.service.ts` 服务 - [x] 实现飞鹅API接口封装:`Open_printerAddlist`、`Open_printerDelList`、`Open_queryPrinterStatus`、`Open_printMsg`、`Open_queryOrderState` - [x] 实现错误处理和重试逻辑 - [x] 实现API签名验证 - [x] 任务4:实现打印机管理服务 (AC: 5) - [x] 创建 `printer.service.ts` 服务 - [x] 实现打印机添加、查询、删除功能 - [x] 实现打印机状态管理 - [x] 实现默认打印机设置 - [x] 任务5:实现打印任务管理服务 (AC: 6) - [x] 创建 `print-task.service.ts` 服务 - [x] 实现打印任务提交、查询、取消功能 - [x] 实现打印状态更新和同步 - [x] 实现打印失败重试机制 - [x] 任务6:实现防退款延迟打印调度器 (AC: 7) - [x] 创建 `delay-scheduler.service.ts` 服务 - [x] 实现延迟任务调度逻辑(默认2分钟延迟) - [x] 实现退款事件监听和任务取消 - [x] 实现调度器健康检查和故障恢复 - [x] 任务7:实现API路由 (AC: 5,6) - [x] 创建打印机管理API路由 - [x] 创建打印任务管理API路由 - [x] 创建打印配置管理API路由 - [x] 实现多租户路由中间件 - [x] 任务8:编写单元测试 (AC: 8) - [x] 为每个服务编写单元测试 - [x] 为API客户端编写集成测试 - [x] 为调度器编写测试 - [x] 确保测试覆盖率 > 80% - [x] 任务9:补齐集成测试用例 (AC: 8) - [x] 实现配置管理API测试(获取配置、更新配置、配置验证) - [x] 实现调度器管理API测试(状态查询、启动停止、健康检查) - [x] 实现打印任务详情API测试 - [x] 实现打印机状态和更新API测试 - [x] 实现打印机删除API测试 - [x] 实现打印任务重试和取消API测试 - [x] 实现调度器触发API测试 - [x] 实现更多边界条件测试 - [x] 任务10:新增集成测试用例覆盖更多场景 (AC: 8) - [x] 实现创建打印机API测试(正常流程、必填字段验证、默认打印机) - [x] 实现打印任务状态查询API测试(状态查询、不存在的任务、不同状态的任务) - [x] 实现分页和排序功能测试(打印机列表分页、打印任务列表分页、创建时间倒序排序、打印机类型筛选) - [x] 实现更多错误场景测试(无效打印机类型、无效打印类型、负数延迟时间、重试次数超限、不存在的配置键) ## 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#数据库设计] ```sql -- 飞鹅打印机配置表 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分钟) - **状态管理**: 打印任务状态包括 `PENDING`、`DELAYED`、`PRINTING`、`SUCCESS`、`FAILED`、`CANCELLED` - **取消场景**: `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代理在审查完成后填写*