11 KiB
Feature Specification: REV-005 发票业务流实现
Feature Branch: 002-rev005-invoice-flow
Created: 2026-03-16
Status: Verification Pending
Input: 实现 REV-005 发票业务流核心功能:发票申请、开票校验、调用 SYS-008 发票服务、接收开票结果回写、更新发票与账单关联状态。
Document Scope & Sources
-
Target documents:
docs/design/02_Detailed_Design/12_REV_Detailed.md(REV-005 章节补充)docs/design/03_Technical_Design/03_Interface_Design.md(IF-REV-008 发票申请接口、IF-REV-009 发票查询接口定义)- Backend:
backend/sw-business/sw-business-server新增 Service/Controller
-
Primary source of truth:
docs/design/02_Detailed_Design/12_REV_Detailed.md中 REV-005 定义docs/guides/BACKEND_CURRENT_STATUS.mddocs/guides/BACKEND_TABLE_MAPPING.md
-
Reference sources:
- Archive:
docs/design/04_Appendix/Archive/03_Design_Docs/营业收费管理系统-概要设计说明书20250912.md - Existing:
InvoiceController.java,InvoiceServiceImpl.java
- Archive:
-
Scope decision: 在已有基础数据层(开票配置、客户开票信息、税率配置)之上,补齐发票申请、开具、结果回写的完整业务流程。
User Scenarios & Testing
User Story 1 - 发票申请与校验 (Priority: P1)
营业收费员或财务人员通过后台系统提交发票申请,系统校验账单状态、开票信息完整性和开票限额,生成发票申请记录。客户侧一期不直接发起开票申请,仅支持查询、下载、推送已开具的电子发票。
Why this priority: 发票申请是业务流程入口,必须优先实现。
Independent Test: 验证发票申请接口可接收申请,校验规则生效,申请记录正确落库。
Acceptance Scenarios:
- Given 账单已缴费且未开票,客户开票信息完整,When 提交发票申请,Then 生成发票申请记录,返回申请单号
- Given 账单未缴费,When 提交发票申请,Then 拒绝申请,提示"账单未缴费不可开票"
- Given 账单已开票,When 提交发票申请,Then 拒绝申请,提示"账单已开票"
- Given 开票金额超过限额,When 提交发票申请,Then 拒绝申请,提示"超过开票限额"
- Given 同一原始账单被要求直接拆分为多次部分开票,When 提交发票申请,Then 拒绝直接部分开票,并提示需先按老系统口径完成拆账/分账后再分别开票
User Story 2 - 调用发票服务开票 (Priority: P1)
系统根据申请记录调用 SYS-008 发票服务完成开票,采用“异步申请 + 查询兜底”模式记录受理结果并主动查询最终状态。
Why this priority: 核心开票能力,必须实现与外部系统的对接。
Independent Test: 验证系统可正确组装开票参数,调用外部服务,处理返回结果。
Acceptance Scenarios:
- Given 发票申请已校验通过,When 调用 SYS-008 开票接口,Then 正确传递账单、客户、税率信息
- Given 外部服务返回开票成功,When 系统通过查询获取结果并回写状态,Then 更新发票状态为"已开票",记录发票代码号码
- Given 外部服务返回开票失败,When 系统通过查询获取结果并回写状态,Then 更新发票状态为"开票失败",记录失败原因
- Given 外部服务超时,When 发起查询,Then 可查询开票结果状态
User Story 3 - 发票结果回写与关联 (Priority: P2)
开票成功后更新账单发票状态,建立发票与账单关联,支持电子发票推送。
Why this priority: 保证账单与发票数据一致性,支持后续查询和下载。
Independent Test: 验证开票结果正确回写账单状态,关联关系可查。
Acceptance Scenarios:
- Given 开票成功,When 回写结果,Then 账单发票状态更新,建立 invoice-charge 关联
- Given 电子发票生成,When 客户请求下载,Then 返回电子发票文件或下载链接
- Given 发票已关联账单,When 查询账单详情,Then 显示关联的发票信息
User Story 4 - 发票作废与红冲 (Priority: P3)
对已成功开具的发票提供后台作废与红冲入口,由 SYS-008 承接税控侧处理,SYS-002 负责发起申请、校验状态、查询补偿、结果回写与账单关联状态同步;客户侧仍仅消费有效电子发票结果,不直接发起作废或红冲。
Why this priority: 作废与红冲属于已开票后的后处理能力,依赖正常开票闭环,但必须在本轮二期中形成正式设计与 backend 实现入口。
Independent Test: 验证后台可对满足条件的成功发票发起作废或红冲;SYS-008 返回结果后,发票状态正确更新为 INVALID 或 RED_INK,并保留原票关联、失败原因与操作日志。
Acceptance Scenarios:
- Given 发票状态为
SUCCESS且未作废、未红冲,When 后台发起作废申请,Then 系统校验通过并调用SYS-008,成功后将发票状态更新为INVALID - Given 发票状态为
SUCCESS且业务要求通过红字发票冲销,When 后台发起红冲申请,Then 系统校验通过并调用SYS-008,成功后将发票状态更新为RED_INK - Given 发票已处于
INVALID或RED_INK,When 再次发起作废或红冲,Then 系统拒绝重复处理并返回明确原因 - Given
SYS-008未立即返回终态,When 系统执行主动查询或补偿查询,Then 保持处理中上下文并在取得终态后统一落账
Edge Cases
- 外部发票服务不可用时的降级处理
- 重复提交同一账单的发票申请(幂等控制)
- 开票过程中账单状态发生变化
- 拆账/分账后的多账单分别开票与原始单账单直接部分开票的边界判定
Requirements
Functional Requirements
- FR-001: 系统 MUST 提供后台发票申请接口,接收账单ID、开票类型(普票/专票)等参数,并支持单笔或批量选择已收费账单发起开票
- FR-002: 系统 MUST 校验账单状态(已缴费、未开票)
- FR-003: 系统 MUST 校验客户开票信息完整性
- FR-004: 系统 MUST 校验开票限额
- FR-005: 系统 MUST 生成发票申请记录,包含申请单号、状态、时间戳
- FR-006: 系统 MUST 调用 SYS-008 发票服务完成开票
- FR-007: 系统 MUST 支持通过定时查询获取异步开票结果(轮询 SYS-008 查询接口)
- FR-008: 系统 MUST 更新发票状态(申请中/已开票/开票失败)
- FR-009: 系统 MUST 建立发票与账单的关联关系,并保留兼容老系统拆账/分账后分别开票及后续合并开票扩展的映射能力
- FR-010: 系统 MUST 支持客户侧查询、下载、推送已开具的电子发票,但一期不开放客户侧直接申请开票
- FR-011: 系统 MUST 记录关键操作日志(申请、查询、开票、结果回写、客户侧查询/下载/推送、作废、红冲),并保留触发来源、状态前后值与失败原因
- FR-012: 系统 MUST 提供后台发票作废入口,仅允许对已开票成功且未作废、未红冲的发票发起作废
- FR-013: 系统 MUST 提供后台发票红冲入口,仅允许对已开票成功且未红冲的发票发起红字冲销,并保留原票关联信息
- FR-014: 系统 MUST 通过查询补偿或结果回写统一落账作废/红冲终态,并同步更新发票状态、失败原因和账单发票关联状态
Key Entities
- 发票申请单 (InvoiceApplication): 申请单号、账单ID、客户ID、申请金额、开票类型、状态
- 发票记录 (InvoiceRecord): 发票ID、申请单号、发票代码、发票号码、开票日期、金额、状态
- 账单发票关联 (ChargeInvoiceRelation): 账单ID、发票ID、关联类型(全额/拆账后分别开票/后续合并扩展)
- 开票查询记录 (InvoiceQueryLog): 查询ID、申请单号、查询时间、查询结果、处理状态
Success Criteria
Measurable Outcomes
- SC-001: 发票申请接口响应时间 < 500ms(不包含外部服务调用)
- SC-002: 发票申请校验通过率 > 95%(正常业务场景)
- SC-003: 开票结果回写成功率 > 99%
- SC-004: 电子发票下载成功率 > 99%
- SC-005: 操作日志完整率 100%(所有关键操作均有日志)
Business Outcomes
- 营业收费员可通过系统完成发票申请到开票的全流程
- 客户可通过渠道查询和下载电子发票
- 财务人员可追溯发票开具全过程
Dependencies & Assumptions
Dependencies
- SYS-008 发票服务接口已定义(IF-REV-008)
- 基础数据层已实现(biz_invoice, biz_cust_invoice, biz_invoice_taxrate)
- 账单系统(REV-003)已实现
Assumptions
- SYS-008 提供标准 REST 接口供调用
- 电子发票文件由 SYS-008 生成并提供下载链接
- 开票限额在配置中预定义
Scope Exclusions
- 不实现发票的物理打印功能
- 不实现与税务局的直接对接(由 SYS-008 承接)
- 不实现复杂的发票拆分合并逻辑(MVP 版本)
Risks & Mitigation
| 风险 | 影响 | 缓解措施 |
|---|---|---|
| SYS-008 接口未就绪 | 无法联调 | 先实现 Mock 接口,定义好契约 |
| 发票状态同步异常 | 数据不一致 | 实现补偿机制,支持对账查询 |
| 并发开票冲突 | 重复开票 | 幂等控制,唯一申请单号 |
Clarifications
Session 2026-03-16
- Q1: SYS-008 发票服务结果获取方式 → A: 采用"异步+查询兜底"模式。提交开票申请后返回受理号,系统通过定时轮询查询结果接口获取开票状态(航信发票接口不支持回调,需主动查询)。
- Q2: 一期是否支持一张原始账单直接分多次部分开票 → A: 不支持对原始单账单直接任意部分金额开票;如需多张发票,沿用老系统口径,通过拆账/分账后的账单分别开票,并保留批量开票能力。
- Q3: 一期开放给哪些使用入口 → A: 采用“后台开票 + 客户侧查询下载”模式。后台营业收费员/财务人员负责申请和开具,客户侧仅支持查看、下载、推送已开票结果,不直接发起开票申请。
Next Steps
- 在可用测试或联调环境中补充 SC-001 的响应时延采样,记录样本量、平均值、P95 与“排除外部调用”的统计口径。
- 为 SC-002 ~ SC-004 准备样本集与统计表,将申请通过率、回写成功率、查询/下载/推送成功率沉淀到
specs/002-rev005-invoice-flow/verification.md。 - 抽取 SC-005 运行态日志样本,核对操作人、客户、状态与日志内容是否与实现态矩阵一致。
- 继续跟踪
biz_invoice物理 DDL / migration 来源,并在提测前明确联调、落库与批量后处理风险。