# Implementation Plan: 用户发票抬头管理

**Date**: 2026-07-24

## 定位与决策

- **镜像 `InfoAddress`**（收货地址）用户级 CRUD 模式：实体即 DTO/VO、JWT userId 隔离、App 端接口风格（`@Anonymous @Auth` + token header）、无默认 / 无上限 / 硬删除。
- **仅 App 端 CRUD**：不建后台端接口、不建 sys_menu、不建 Vue 页面、无 i18n（按需求决策，YAGNI）。
- **与 010 解耦**：不改 010 `applyInvoice` / `getInvoice`；抬头是纯输入辅助，开票时客户端选用预填。
- **校验在 service 层**（`validateInvoiceProfile`），中校验力度：必填 + 统编 8 位 + 载具正则。
- **捐赠（DONATION）不存为抬头**；B2C 必须有载具（对齐 010 当前规则）。

## 文件落点

| 层 | 路径 |
|---|---|
| 实体 | `ruoyi-system/src/main/java/com/ruoyi/system/domain/InfoInvoice.java` |
| Mapper 接口 | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/InfoInvoiceMapper.java` |
| Mapper XML | `ruoyi-system/src/main/resources/mapper/system/InfoInvoiceMapper.xml` |
| Service 接口 | `ruoyi-system/src/main/java/com/ruoyi/system/service/IInfoInvoiceService.java` |
| Service 实现 | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/InfoInvoiceServiceImpl.java` |
| Controller | `ruoyi-admin/src/main/java/com/ruoyi/app/order/InfoInvoiceController.java` |
| SQL | `updatesql/sql.md`（追加 2026-07-24 段） |

> Mapper XML 放 `mapper/system/`（与 `InfoAddressMapper.xml` 同位），非 `mapper/chanting/`（那是 pos_ 业务表）。

## 分阶段

1. **Setup**：DDL 写 `updatesql/sql.md`（开发者手动执行）。
2. **Foundational**：实体 + Mapper(+XML) + Service(+校验)。
3. **Controller**：App 端 4 接口。
4. **Polish**：curl 手测（B2C / B2B / 校验 / 越权）+ 更新记忆索引。

## 测试策略

轻量。无单测强制；按 `contracts/api.md` 用 curl/Postman 手测 4 条接口 + 校验矩阵各分支 + 越权拒绝。

## 风险与注意

- `InfoAddressServiceImpl` 的 `ServiceImpl` 泛型用的是 `BaseMapper<InfoAddress>`（历史遗留）；新建 `InfoInvoiceServiceImpl` 时用具体 `ServiceImpl<InfoInvoiceMapper, InfoInvoice>`。
- `@Auth` 来源 `com.ruoyi.system.utils.Auth`、`@Anonymous` 来源 `com.ruoyi.common.annotation.Anonymous`、`JwtUtil` 来源 `com.ruoyi.system.utils.JwtUtil`（均照搬 InfoAddressController）。
- 后端文件亦为 CRLF（见 memory `project-build-env`）；新建文件用项目默认换行即可，编辑既有文件注意 CRLF。
