tangweijie d8b2416f12 docs: 补齐 REV-005 作废红冲设计与任务
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 12:36:50 +08:00

11 KiB
Raw Blame History

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.mdREV-005 章节补充)
    • docs/design/03_Technical_Design/03_Interface_Design.mdIF-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.md
    • docs/guides/BACKEND_TABLE_MAPPING.md
  • Reference sources:

    • Archive: docs/design/04_Appendix/Archive/03_Design_Docs/营业收费管理系统-概要设计说明书20250912.md
    • Existing: InvoiceController.java, InvoiceServiceImpl.java
  • Scope decision: 在已有基础数据层(开票配置、客户开票信息、税率配置)之上,补齐发票申请、开具、结果回写的完整业务流程。


User Scenarios & Testing

User Story 1 - 发票申请与校验 (Priority: P1)

营业收费员或财务人员通过后台系统提交发票申请,系统校验账单状态、开票信息完整性和开票限额,生成发票申请记录。客户侧一期不直接发起开票申请,仅支持查询、下载、推送已开具的电子发票。

Why this priority: 发票申请是业务流程入口,必须优先实现。

Independent Test: 验证发票申请接口可接收申请,校验规则生效,申请记录正确落库。

Acceptance Scenarios:

  1. Given 账单已缴费且未开票,客户开票信息完整,When 提交发票申请,Then 生成发票申请记录,返回申请单号
  2. Given 账单未缴费,When 提交发票申请,Then 拒绝申请,提示"账单未缴费不可开票"
  3. Given 账单已开票,When 提交发票申请,Then 拒绝申请,提示"账单已开票"
  4. Given 开票金额超过限额,When 提交发票申请,Then 拒绝申请,提示"超过开票限额"
  5. Given 同一原始账单被要求直接拆分为多次部分开票,When 提交发票申请,Then 拒绝直接部分开票,并提示需先按老系统口径完成拆账/分账后再分别开票

User Story 2 - 调用发票服务开票 (Priority: P1)

系统根据申请记录调用 SYS-008 发票服务完成开票,采用“异步申请 + 查询兜底”模式记录受理结果并主动查询最终状态。

Why this priority: 核心开票能力,必须实现与外部系统的对接。

Independent Test: 验证系统可正确组装开票参数,调用外部服务,处理返回结果。

Acceptance Scenarios:

  1. Given 发票申请已校验通过,When 调用 SYS-008 开票接口,Then 正确传递账单、客户、税率信息
  2. Given 外部服务返回开票成功,When 系统通过查询获取结果并回写状态,Then 更新发票状态为"已开票",记录发票代码号码
  3. Given 外部服务返回开票失败,When 系统通过查询获取结果并回写状态,Then 更新发票状态为"开票失败",记录失败原因
  4. Given 外部服务超时,When 发起查询,Then 可查询开票结果状态

User Story 3 - 发票结果回写与关联 (Priority: P2)

开票成功后更新账单发票状态,建立发票与账单关联,支持电子发票推送。

Why this priority: 保证账单与发票数据一致性,支持后续查询和下载。

Independent Test: 验证开票结果正确回写账单状态,关联关系可查。

Acceptance Scenarios:

  1. Given 开票成功,When 回写结果,Then 账单发票状态更新,建立 invoice-charge 关联
  2. Given 电子发票生成,When 客户请求下载,Then 返回电子发票文件或下载链接
  3. Given 发票已关联账单,When 查询账单详情,Then 显示关联的发票信息

User Story 4 - 发票作废与红冲 (Priority: P3)

对已成功开具的发票提供后台作废与红冲入口,由 SYS-008 承接税控侧处理,SYS-002 负责发起申请、校验状态、查询补偿、结果回写与账单关联状态同步;客户侧仍仅消费有效电子发票结果,不直接发起作废或红冲。

Why this priority: 作废与红冲属于已开票后的后处理能力,依赖正常开票闭环,但必须在本轮二期中形成正式设计与 backend 实现入口。

Independent Test: 验证后台可对满足条件的成功发票发起作废或红冲;SYS-008 返回结果后,发票状态正确更新为 INVALIDRED_INK,并保留原票关联、失败原因与操作日志。

Acceptance Scenarios:

  1. Given 发票状态为 SUCCESS 且未作废、未红冲,When 后台发起作废申请,Then 系统校验通过并调用 SYS-008,成功后将发票状态更新为 INVALID
  2. Given 发票状态为 SUCCESS 且业务要求通过红字发票冲销,When 后台发起红冲申请,Then 系统校验通过并调用 SYS-008,成功后将发票状态更新为 RED_INK
  3. Given 发票已处于 INVALIDRED_INKWhen 再次发起作废或红冲,Then 系统拒绝重复处理并返回明确原因
  4. 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

  1. 在可用测试或联调环境中补充 SC-001 的响应时延采样记录样本量、平均值、P95 与“排除外部调用”的统计口径。
  2. 为 SC-002 ~ SC-004 准备样本集与统计表,将申请通过率、回写成功率、查询/下载/推送成功率沉淀到 specs/002-rev005-invoice-flow/verification.md
  3. 抽取 SC-005 运行态日志样本,核对操作人、客户、状态与日志内容是否与实现态矩阵一致。
  4. 继续跟踪 biz_invoice 物理 DDL / migration 来源,并在提测前明确联调、落库与批量后处理风险。