# Personnel 领域重构指南

## 1. 范围

当前仓库里没有独立的 `personnel` 项目业务模块。

最接近的本地实现是：

- `app/modules/safety/models/safety_personnel_qualification.py`
- `app/modules/safety/schemas/personnel_qualification.py`

因此本文档先按“人员资质”这一真实落点梳理，而不是假设仓库里已经有独立 `personnel` 主表。

当前优先关注：

- `personnel_type`
- `task_type`
- `is_duty`

## 2. 字段盘点

### 2.1 `personnel_type`

当前实现：

- 模型里通过类常量定义两个值：`safe`、`special`
- 模型字段本身是 `String`
- schema 里仍是 `str`

项目侧取值范围：

- `safe`
- `special`

集团侧差异：

- 集团侧 `enum_config.Personnel` 里并没有 `personnel_type`
- 集团侧更像是在描述“人员/吊装设备”等资源配置编码，而不是人员资质类型
- 当前仓库里也没有 standalone 的 sync schema 对这个领域建模

结论：

- 这是本地代码级 enum 字段
- 可保留为代码 enum

### 2.2 `task_type`

当前实现：

- 模型里通过 `PERSONNEL_TASK_TYPE` 类常量给出候选项
- 字段本身是 `String`
- schema 里仍是 `str`

项目侧取值范围：

- `电工`
- `焊工`
- `高空作业人员`
- `无人机操作员`
- `其他`

集团侧差异：

- 集团侧 `enum_config.Personnel` 没有这个字段
- 当前仓库里也没有 sync schema 对应

结论：

- 这是本地代码级候选项字段
- 可以保留为代码常量，但要补 schema 校验

### 2.3 `is_duty`

当前实现：

- 模型里通过类常量定义：`1` 在场，`2` 退场
- 字段本身是 `SmallInteger`
- schema 里是 `int`

项目侧取值范围：

- `1`
- `2`

集团侧差异：

- 集团侧 `enum_config.Personnel.status` 给的是 `-1`、`0`、`1`
- 这更像资源进度状态，不是本地 `is_duty` 语义
- 两边不是同一字段，不应强行对齐

结论：

- 保留为本地数值常量字段

## 3. 重点结论

- 当前所谓 `personnel` 领域，在本地真实落点是“人员资质”，不是集团侧 `Personnel` 那套资源配置模型。
- 因此这里最重要的不是照抄集团侧，而是先承认两个系统的领域边界不一致。

## 4. 待修改项清单

1. 明确 `personnel` 在本地的正式领域名是否就是 `safety_personnel_qualification`。
2. 为 `personnel_type` 补正式 enum/schema 校验。
3. 为 `task_type` 补统一白名单校验。
4. 不要把集团侧 `Personnel.code/status` 直接映射到本地 `personnel_type/is_duty`。

## 5. 按本轮要求的改造落点

personnel 领域不是这轮“项目初始化 + 项目类型 field_config”第一批重点，但仍需要按统一口径写清楚 create、下拉和清理边界。

### 5.1 初始化

本地人员资质领域当前没有项目初始化批量灌数链路。

因此本轮不把它纳入 `init_project_data)` 第一批改造范围。

### 5.2 Create 校验

当前 `PersonnelQualificationService.create()` 已直接在 service 层校验：

- `personnel_type`
- `task_type`

校验来源是本地模型类常量：

- `PERSONNEL_TYPE_SAFE`
- `PERSONNEL_TYPE_SPECIAL`
- `PERSONNEL_TASK_TYPE`

这类字段当前更像固定语义本地枚举，不是按 `project_type` 变化的字段级配置候选项。

本轮目标是：

- 继续把它们视为本地固定候选项
- 统一 create / update / list 使用同一套定义源
- 不误迁到项目类型 field_config

### 5.3 下拉列表

当前已有：

- `/safety/personnel/task_type/list`

它直接返回 `PERSONNEL_TASK_TYPE`。

本轮这里不要求强行改成 `project_type` 相关 config，而是要求：

- 明确它是本地固定候选项
- 前端下拉和 create 校验继续同源

### 5.4 清理项

personnel 领域本轮的清理重点不是删 enum，而是避免错误地把集团侧 `Personnel` 语义强行映射进来。

应避免：

- 把本地 `personnel_type`、`task_type` 误改造成和集团侧 `code/status` 一一对应
- 同一字段在 service 和下拉各自维护两套值

## 6. 测试关注点

personnel 领域 service 层集成测试至少覆盖：

1. `personnel_type` 合法值和非法值创建校验。
2. `special` 人员必须校验 `task_type`。
3. `task_type/list` 返回值与 create 校验使用同源常量。

