# 后端业务功能开发规范

本文是本项目后端新增或修改业务功能时的权威规范。开发后台管理端业务模块时，必须优先遵循本项目现有架构，而不是套用通用 Spring Boot 三层模板。

## 架构原则

后端业务代码按 `Controller -> ApplicationService -> Model -> db Service/Mapper` 组织。

优先参考这些现有模块：

- `backend/agileboot-domain/src/main/java/com/agileboot/domain/system/post`
- `backend/agileboot-domain/src/main/java/com/agileboot/domain/system/user`
- `backend/agileboot-domain/src/main/java/com/agileboot/domain/system/role`
- `backend/agileboot-domain/src/main/java/com/agileboot/domain/system/notice`
- `backend/agileboot-admin/src/main/java/com/agileboot/admin/controller/system`

不要让 Controller 直接调用 Mapper，不要把业务规则写在 Controller，也不要直接把 Entity 或 DO 返回给前端。

## 开发准备

开发新后端业务功能前，应先确认需求所属领域、涉及的数据表、接口范围、权限标识和相似模块。本文是后端业务功能开发的统一规范。

开始编码前必须先做一次相似模块调研，确认目标功能最接近 `post`、`user`、`role`、`notice` 还是其他模块，再按相似模块的命名、包路径、注解、分页、异常、权限、日志和测试风格实现。

## 目录结构

后台管理端入口放在 `agileboot-admin`：

```text
backend/agileboot-admin/src/main/java/com/agileboot/admin/controller/<area>/
└── XxxController.java
```

业务代码放在 `agileboot-domain`：

```text
backend/agileboot-domain/src/main/java/com/agileboot/domain/<area>/xxx/
├── XxxApplicationService.java
├── command/
│   ├── AddXxxCommand.java
│   └── UpdateXxxCommand.java
├── query/
│   └── XxxQuery.java
├── dto/
│   ├── XxxDTO.java
│   └── XxxDetailDTO.java
├── model/
│   ├── XxxModel.java
│   └── XxxModelFactory.java
└── db/
    ├── XxxEntity.java
    ├── XxxDO.java
    ├── XxxMapper.java
    ├── XxxService.java
    └── XxxServiceImpl.java
```

`XxxDO` 是可选文件。只有当查询结果包含 join、聚合、报表字段或其他不完全匹配 Entity 的字段时才创建。

如果业务属于已有领域，例如 `system`，放到现有领域下；如果是独立业务领域，创建新的 `<area>` 包名，例如 `business`。

## 各层职责

Controller 只负责 HTTP 层：

- 声明 `@RestController`、`@RequestMapping`、`@Validated`、Swagger 注解。
- 接收 `Command`、`Query`、路径参数和请求参数。
- 使用 `@PreAuthorize("@permission.has('xxx:yyy:zzz')")` 做权限控制。
- 对新增、修改、删除、导出等操作使用 `@AccessLog`。
- 调用 `XxxApplicationService`。
- 使用 `ResponseDTO.ok(...)` 返回结果。

ApplicationService 负责编排业务用例：

- 分页查询、详情查询、导出查询、新增、修改、删除。
- 创建或加载 `XxxModel`。
- 调用领域模型完成业务校验和状态变化。
- 调用 `db` 包中的 Service 完成查询和持久化。
- 将 Entity 或 DO 转换为 DTO。
- 分页结果使用 `PageDTO<T>`。

Model 承载业务规则：

- 从 `AddXxxCommand`、`UpdateXxxCommand` 加载字段。
- 封装唯一性校验、状态校验、是否允许删除、业务状态流转等规则。
- 需要数据库判断时，通过构造注入的 `XxxService` 查询。
- 业务失败时抛出 `ApiException`，不要返回布尔值让上层解释。

ModelFactory 负责创建和加载模型：

- `create()` 返回带有依赖的空模型。
- `loadById(id)` 从数据库加载 Entity，并包装为 Model。
- 如果未找到必要数据，按项目现有异常风格处理。

db 包只负责持久化：

- `XxxEntity` 映射数据库表。
- `XxxDO` 承载复杂查询结果，例如关联表字段、统计字段、报表字段。
- `XxxMapper` 继承 MyBatis Plus `BaseMapper<XxxEntity>`。
- `XxxService` 继承 `IService<XxxEntity>`，声明复用型查询方法。
- `XxxServiceImpl` 继承 `ServiceImpl<XxxMapper, XxxEntity>`，实现唯一性检查、关联检查、复杂查询等。
- 复杂 SQL 放到 mapper XML，简单条件优先使用 MyBatis Plus wrapper。

`XxxDO` 属于数据库查询结果对象，不是前端响应对象，也不是请求对象。Mapper 或 Service 可以返回 `XxxDO`，但 ApplicationService 必须转换为 `XxxDTO` 后再交给 Controller 返回。

Command、Query、DTO 的边界：

- `Command` 用于新增、修改等写请求，不要直接接收 Entity。
- `Query` 用于列表、搜索、分页条件，并提供 `toPage()`、`toQueryWrapper()` 等项目已有风格的方法。
- `DTO` 用于响应前端，不要直接暴露 Entity 或 DO。
- 批量删除优先使用 `BulkOperationCommand<Long>`。

## 开发流程

1. 检索并阅读一个最相似的现有模块，确认命名、包路径、注解、分页、异常、测试风格。
2. 确认数据库表结构，保持主键、软删除、审计字段、字段命名与现有表一致。
3. 创建 `db` 包：`Entity`、`Mapper`、`Service`、`ServiceImpl`；如查询结果包含关联表字段、统计字段或报表字段，再增加 `XxxDO`。
4. 创建 API 契约：`AddXxxCommand`、`UpdateXxxCommand`、`XxxQuery`、`XxxDTO`，需要详情时添加 `XxxDetailDTO`。
5. 创建 `XxxModel` 和 `XxxModelFactory`，把业务校验放进 Model。
6. 创建 `XxxApplicationService`，编排查询、新增、修改、删除、导出等用例。
7. 创建 `XxxController`，加路由、权限、操作日志和统一响应。
8. 如功能出现在后台菜单，补充权限标识、菜单 SQL 或清楚说明需要配置的权限码。
9. 增加聚焦测试，至少覆盖核心业务校验和主要用例。
10. 运行相关 Maven 测试或编译检查；如果不能运行，说明原因。

开发过程中如果发现本文未覆盖的模式，优先参考现有模块，而不是引入新的架构风格。确实需要新增模式时，应先更新本文，再按新规范实现。

## 权限、日志和错误

权限码必须和前端菜单或按钮权限保持一致，格式参考现有系统功能：

```java
@PreAuthorize("@permission.has('system:post:add')")
```

操作日志按业务动作选择类型：

```java
@AccessLog(title = "业务名称", businessType = BusinessTypeEnum.ADD)
@AccessLog(title = "业务名称", businessType = BusinessTypeEnum.MODIFY)
@AccessLog(title = "业务名称", businessType = BusinessTypeEnum.DELETE)
@AccessLog(title = "业务名称", businessType = BusinessTypeEnum.EXPORT)
```

业务错误使用 `ApiException` 和 `ErrorCode.Business`。新增业务错误时，按现有错误码结构补充枚举或常量，不要在 Controller 中拼接错误响应。

## 验收清单

- 新代码目录结构与相似模块一致。
- Controller 只有 HTTP 编排逻辑。
- 业务校验位于 Model 或 ApplicationService，不散落在前端或 Controller。
- 查询返回 DTO，分页返回 `PageDTO<T>`。
- 写请求使用 Command。
- 复杂查询结果对象使用 DO，并在 ApplicationService 转换为 DTO。
- 权限、日志、异常、测试和现有项目风格一致。
