# 业务需求文档模板

## 文档定位

本文档提供一份面向业务模块的需求说明模板，用于：

- 在写模块需求时提前补齐开发和代码生成所需的关键信息
- 把实体层约定、数据状态能力、删除顺序、前后端对齐约束写清楚
- 降低开发者、代码生成器或自动化工具因为需求输入不完整而自行猜测的概率

它不是强制的一字不差模板，但以下关键段落建议保留。

## 建议结构

### 1. 模块目标

- 模块名称
- 业务对象名称
- 目标用户
- 核心场景

### 2. 输入资料

- SQL 文件路径
- 设计总览路径
- 关联基础需求路径
- 目标模块目录

### 3. 业务对象与字段

按实体分别列出：

- 主表 / 从表
- 关键字段
- `AO` 创建 / 编辑入参字段及必填性
- 唯一约束
- 排序字段
- 逻辑删除字段
- 敏感字段

`AO` 必填性需要明确到字段级，供开发者、代码生成器或自动化工具同步生成 OpenAPI 与 Jakarta Validation 注解：

| AO 类 | 字段 | 类型 | 是否必填 | 校验注解 | 说明 |
| --- | --- | --- | --- | --- | --- |
| `XxxAO` | `xxxName` | `String` | 是 | `@NotBlank` | 名称不能为空白 |
| `XxxAO` | `sortWeight` | `Integer` | 是 | `@NotNull` | 排序值必须提交 |
| `XxxBatchAO` | `targetIdSet` | `Set<String>` | 是 | `@NotEmpty` | 批量目标集合不能为空 |

如果字段在 `@Schema(requiredMode = RequiredMode.REQUIRED)` 中标记必填，必须同步写出对应的 `jakarta.validation.constraints` 注解；不要只维护 OpenAPI 必填标记。

### 4. 数据状态能力开关

这一段必须写清楚，供生成代码时直接判断。

固定规则：

- `AbstractTenantBaseEntity`、`AbstractTenantBaseTreeEntity`、`AbstractTenantBaseAccountEntity`、`AbstractTenantBaseOwnerEntity` 基类只默认提供 `DataStatusFeature.FIXED`
- 除 `FIXED` 外，当前可用开关为 `ENABLED`、`DEFAULT`、`PRIMARY`、`LOCKED`、`PUBLISHED`，必须由最终实体类显式打开
- 需求文档未声明的开关，生成代码时不要默认开启
- 如果最终实体不需要额外开关，可以不声明 `@EnableDataStatus`，此时只保留基类的 `FIXED`

推荐按下面的表填写：

| 实体类 | 是否继承 `AbstractTenantBase*Entity` | 需要开启的开关 | 说明 |
| --- | --- | --- | --- |
| `Xxx` | 是 | `ENABLED, DEFAULT` | 支持启停，新增默认启用 |
| `XxxCategory` | 是 | `ENABLED, PUBLISHED, DEFAULT` | 支持启停、发布、默认项 |
| `XxxLog` | 否 | 无 | 日志实体不走数据状态能力 |

可选开关值：

- `ENABLED`
- `DEFAULT`
- `PRIMARY`
- `LOCKED`
- `PUBLISHED`

### 5. 标准能力范围

按实体或模块说明是否需要：

- CRUD
- 分页查询
- 详情查询
- 回收站查询
- 状态切换
- 排序
- 账号状态
- 自定义动作

### 6. 共享扩展与转换层

这一段建议显式写清楚，避免生成代码时把共享认证能力和对象转换层生成错位。

至少说明：

- 模块是否接入统一认证链
- 如果接入统一认证链，是否复用 `IAccountAuthenticationService`、`IReactiveAccountAuthenticationService`、`ISecurityAuthoritiesService`、`IReactiveSecurityAuthoritiesService`
- 主体模块自己的 `Manager` 只需要保留哪些能力，例如 `loadByUsername(...)`、`accountToSecurityUser(...)`、主体特有查询、模块私有异常映射
- 哪些数据栈需要生成对象转换实现，例如 `jpa / jdbc / mybatis-flex / r2dbc`
- 转换实现是否统一放在实现模块的 `converter/` 包
- 是否同时存在 MyBatis-Flex 持久化 `mapper/` 与对象转换 `converter/`
- 是否需要接入 `CreateManager` / `UpdateManager` / `FindByIdManager` / `OrderManager` 一类抽象，以及对应的 `getCreateEntityConverter()`、`getUpdateEntityConverter()`、`getEntityVoConverter()`

### 7. 删除顺序与清理规则

必须明确：

- 主表与依赖表
- 删除顺序
- 哪些关系清理落在 `afterLogicDelete`
- 哪些恢复补偿落在 `afterRecovery`

### 8. 分层落点

至少说明：

- 哪些规则落在 `Controller`
- 哪些规则落在 `Service`
- 哪些规则落在 `Manager`
- 哪些规则落在 `Repository / EntityManager`
- 生成代码的类级 Javadoc 需要说明哪些职责边界和业务规则，尤其是唯一性、状态流转、删除保护、级联清理、外部同步、审计或权限边界
- 代码格式、Javadoc、`@author`、字段注释、`@Schema` 与字段声明统一遵守 [code-style-guide.md](code-style-guide.md)

### 9. 前后端对齐

至少说明：

- 控制器根路径
- `resourceKey`
- 页面入口
- 页面路由
- 按钮权限点
- 权限清单节点类型：`catalog / menu / page / api / button`
- 如果存在一级大目录，权限清单节点类型必须包含 `catalog`，并说明该模块挂在哪个大目录下
- `menu / page` 需要写清前端访问路径和真实组件路径，供后续动态路由使用；`api` 写后端接口路径；`button` 不写 `permissionUrl / component / icon`
- 权限排序：按 `orderWeight DESC` 设计，建议顺序为辅助查询 API、列表查询、CRUD、状态操作、回收站操作
- 权限说明口径：写给授权人员看，使用业务语言，不使用 `idSet`、`query`、`commonParameters` 等后端参数名
- 前端需要的列表字段、查询字段、详情字段
- 创建字段、编辑字段
- 默认排序
- 是否需要回收站
- 是否需要状态切换
- 是否需要账号能力
- 是否需要导入与导出
- 如果需要导入与导出，`AO / VO` 对应哪些字段参与，Excel 列头中文名是什么
- 是否要求 `webmvc` 与 `webflux` 两条线都暴露同等能力

### 10. 租户、权限、事务与集成边界

按实体写明租户模式、读写范围和操作身份；区分 API 权限与数据范围。按业务动作写明事务边界、失败回滚、重复请求及并发竞争语义。

需要缓存或事件时，明确 key 的上下文维度、失效范围、提交时序和失败处理；不需要时写“不适用”。这些字段描述本模块的业务选择，通用规范见[规则索引](../standards/README.md)。

### 11. 验收与测试

至少说明：

- Happy path
- Negative path
- 排序与状态切换验证点
- 删除与恢复验证点

## 可复制片段

```md
## 共享扩展与转换层

- 是否接入统一认证链：是
- 共享认证契约：复用 `IAccountAuthenticationService`、`IReactiveAccountAuthenticationService`
- 权限快照契约：复用 `ISecurityAuthoritiesService`、`IReactiveSecurityAuthoritiesService`
- 主体模块 Manager 保留能力：`loadByUsername(...)`、`accountToSecurityUser(...)`、主体特有查询
- 需要生成对象转换实现的数据栈：`jdbc`、`mybatis-flex`
- 转换实现落点：统一放在 `converter/` 包，类名使用 `XxxConverter`
- MyBatis-Flex 是否同时存在持久化 `mapper/`：是；`mapper/` 仅承载持久化接口，对象转换单独放 `converter/`
- 是否需要接入统一转换方法：是，需要实现 `getCreateEntityConverter()`、`getUpdateEntityConverter()`、`getEntityVoConverter()`

## 数据状态能力开关

固定规则：

- `AbstractTenantBase*Entity` 基类只默认提供 `DataStatusFeature.FIXED`
- 其他开关必须由最终实体类显式打开
- 需求文档未声明的开关，生成代码时不要默认开启

| 实体类 | 是否继承 `AbstractTenantBase*Entity` | 需要开启的开关 | 说明 |
| --- | --- | --- | --- |
| `AccessCredential` | 是 | `ENABLED, DEFAULT` | 支持启停，新增默认启用 |
| `AccessCredentialGroup` | 是 | `ENABLED` | 只支持启停 |
```

> 最后更新：2026-05-15
