--- description: "Task list for 用户发票抬头管理" --- # Tasks: 用户发票抬头管理 **Input**: Design documents from `/specs/014-invoice-profile/` **Prerequisites**: spec.md ✅, data-model.md ✅, contracts/api.md ✅, plan.md ✅ **范围**: 仅后端 App 端 CRUD(实体 / Mapper / Service / Controller + SQL)。无前端、无 i18n、无后台端。 **测试**: 轻量手测(curl/Postman),按 contracts/api.md。 ## Format: `[ID] [P?] Description` - **[P]**: 可并行(不同文件、无未完成依赖) ## Path Conventions - 实体 / Mapper / Service:`ruoyi-system/src/main/java/com/ruoyi/system/...` - Controller:`ruoyi-admin/src/main/java/com/ruoyi/app/order/InfoInvoiceController.java` - SQL:`updatesql/sql.md` --- ## Phase 1: Setup - [x] T001 在 `updatesql/sql.md` 追加 2026-07-24 段:`CREATE TABLE info_invoice`(字段 / 类型 / 注释见 data-model.md,含 `KEY idx_user(user_id)`,引擎 InnoDB / utf8mb4)。无 sys_menu(本期无后台端)。 --- ## Phase 2: Foundational - [x] T002 [P] 新建 `InfoInvoice` 实体(`ruoyi-system/.../domain/InfoInvoice.java`):`@Data @TableName("info_invoice") @EqualsAndHashCode(callSuper=false)`,`@TableId(type=IdType.AUTO)`;字段 id / userId / titleName / category / buyerName / buyerUbn / buyerEmail / carrierType / carrierNum / createTime / updateTime(注释对齐 data-model;create_time/update_time 由 DB DEFAULT/ON UPDATE 自动维护,无 createBy/updateBy)。参考 `InfoAddress.java` 风格。 - [x] T003 [P] 新建 `InfoInvoiceMapper` 接口(`ruoyi-system/.../mapper/InfoInvoiceMapper.java`)继承 `BaseMapper`,**空体无自定义方法、无 XML**——App 端仅用 MyBatis-Plus `IService` CRUD(list/saveOrUpdate/getById/removeById,字段驼峰自动映射 info_invoice 列);本期无后台端,故无需自定义查询。 - [x] T004 新建 `IInfoInvoiceService`(`ruoyi-system/.../service/IInfoInvoiceService.java`,继承 `IService`,方法 listByUserId / saveOrUpdateMine / getMine / deleteMine)+ `InfoInvoiceServiceImpl`(`.../service/impl/InfoInvoiceServiceImpl.java`,`extends ServiceImpl`)。实现私有 `validateInvoiceProfile(InfoInvoice)`(按 contracts 校验矩阵:titleName / buyerName 非空、category ∈ {B2C,B2B}、B2B 统编 `^\d{8}$` + 邮箱必填 + 载具空、B2C 载具按类型正则 + 统编空 + 邮箱仅会员载具必填),非法抛 `ServiceException`。`saveOrUpdateMine` 内强制 setUserId + 校验 + 更新时归属校验;`getMine`/`deleteMine` 越权返回 null/false。依赖 T002、T003。 **Checkpoint**: 表 + 实体 + mapper + service(含校验)就绪。 --- ## Phase 3: Controller(App 端) - [x] T005 新建 `InfoInvoiceController`(`ruoyi-admin/.../app/order/InfoInvoiceController.java`,`@RequestMapping("/system/invoice")`,extends `BaseController`,注入 `IInfoInvoiceService`):① `GET /getinvoice`(`@Anonymous @Auth` + `@RequestHeader token` → `getusid` → `QueryWrapper.eq("user_id")` → list);② `POST /invoice`(token + `@RequestBody InfoInvoice` → `setUserId` 强制覆盖 → `validateInvoiceProfile` → 更新时校验归属 → `saveOrUpdate`);③ `GET /getinvoicexq?id=`(getById + 归属校验);④ `GET /deleinvoice?id=`(归属校验 → removeById)。注解 / 工具类照搬 `InfoAddressController`。依赖 T004。 **Checkpoint**: 4 接口可用,curl 跑通。 --- ## Phase 4: Polish - [ ] T006 [P] 按 contracts/api.md 手测:B2C(三种载具)/ B2B 保存 → 列表 → 详情 → 改 → 删;校验矩阵各非法分支(统编非 8 位、手机条码不以 `/` 开头、自然人凭证格式错、B2B 带载具、B2C 带统编、必填空)均拦截;越权(A 操作 B 的 id)拒绝。 - [x] T007 [P] 更新记忆索引 `MEMORY.md`:加一行指向 `specs/014-invoice-profile/spec.md`(参考 010 写法)。 --- ## Dependencies & Execution Order - Phase 1 Setup → Phase 2 Foundational(T002 / T003 可并行,T004 依赖二者)→ Phase 3 Controller(T005 依赖 T004)→ Phase 4 Polish(T006 依赖 T005,T007 随时)。