# 钉钉模块 - 产品需求文档

> **版本**: v1.0  
> **状态**: Approved  
> **创建日期**: 2026-03-17  
> **最后更新**: 2026-03-17  
> **产品经理**: FFOA Team

---

## 文档摘要

### 最小必填项

| 字段 | 内容 |
|------|------|
| 模块 | 钉钉模块 |
| 文档类型 | PRD |
| 目标 | 支持钉钉同步任务管理、员工同步、审批修复与年假洞察 |
| 范围 | 钉钉同步总览、任务管理、员工同步、审批撤销修复、年假余额与释放计划 |
| 核心规则 | 员工状态属于员工主数据；释放计划页默认仅展示正常员工；年假参数编辑遵循当前代码能力 |
| 验收标准 | 页面、接口与本地数据表行为一致；文档与现有代码保持一致 |
| 关联文档 | `06-data-model.md` / `07-api.md` / `09-test-scenarios.md` |

### 范围清单

| 功能 | 优先级 | 说明 |
|------|--------|------|
| 同步总览与任务管理 | P0 | 展示任务状态、执行历史并支持手动触发 |
| 员工同步与员工管理 | P0 | 从钉钉同步员工到本地表，并支持维护员工状态 |
| 审批撤销修复 | P1 | 按同步类型、员工、审批号扫描并撤销错误考勤审批 |
| 年假余额洞察 | P1 | 读取本地快照展示假期余额，并查看详情 |
| 年假释放计划 | P1 | 展示本地释放计划、导出计划、手动重算和执行释放 |
| 年假计划参数维护 | P1 | 按员工维护 `adjustmentDays` 与 `notCountDays` |

---

## 需求说明

### 背景

钉钉相关能力已经形成独立业务域，但此前文档挂在 `organization` 模块下，导致组织架构与钉钉同步事实混杂。  
本次调整不移动代码，仅将钉钉模块文档独立，确保后续规则、接口和测试场景统一收口。

### 目标用户

| 角色 | 描述 | 使用场景 |
|------|------|---------|
| 系统管理员 | 负责钉钉同步与人工修复 | 查看任务状态、触发同步、审批撤销修复 |
| HR / 组织运营 | 维护员工信息与年假计划 | 同步员工、查看年假余额、重算释放计划 |

### 功能清单

#### 功能 1：同步总览与任务管理

- 展示钉钉同步总览、任务列表和最近执行记录
- 支持按任务代码手动触发同步
- 支持 SSE 流式查看手动触发日志

#### 功能 2：员工同步与员工管理

- 支持从钉钉 HR 同步员工到本地 `dingtalk_employees`
- 支持查看分页员工列表
- 支持维护员工状态

**业务规则**:

1. 员工状态属于员工主数据，存储在 `dingtalk_employees.status`
2. 员工状态取值使用当前实现：`正常 / 停薪留职 / 顾问 / 已离职`
3. 年假释放计划页默认只展示状态为 `正常` 的员工

#### 功能 3：审批撤销修复

- 支持按 `DINGTALK_BUSINESS_TRIP`、`DINGTALK_FIELD_APPLICATION`、`DINGTALK_OVERTIME` 三类同步筛选
- 支持指定员工 `userId`
- 支持审批号精确匹配和 `*` 通配匹配
- 支持先预览再执行撤销

**业务规则**:

1. 仅允许处理考勤同步类审批
2. 手动触发查询窗口强制收敛到最近 60 天
3. 重复命中的同一员工 + 同一审批号需要去重

#### 功能 4：年假余额洞察

- 支持刷新本地假期余额快照
- 支持按员工和假期类型查看余额总览
- 支持查看指定员工指定假期类型的余额详情、使用记录与释放记录

**业务规则**:

1. 总览页读取本地快照，不直接依赖实时钉钉余额接口
2. 非年假类假期可无释放记录

#### 功能 5：年假释放计划

- 支持查看本地年假释放计划
- 支持手动重算计划，不直接发放额度
- 支持单独执行年假释放
- 支持 CSV 导出

**业务规则**:

1. 页面默认仅展示 `正常` 员工
2. 当前实现不提供“显示顾问/停薪留职/已离职”筛选
3. 无计划员工仍保留在结果中，并返回 `noPlanReason`

#### 功能 6：年假计划参数维护

- 当前仅维护 `adjustmentDays` 与 `notCountDays`
- 编辑入口位于年假余额页和年假释放计划页
- 保存时按当前代码直接执行保存并重算

**业务规则**:

1. `adjustmentDays` 仅影响累计应释放额度，不改写 `releaseSchedule`
2. `notCountDays` 参与释放日期重算
3. 当前实现不在该入口维护 `status`
4. 读取计划设置时，如记录不存在，返回默认值；更新时才落库存储
5. `lastCalculatedAt` 表示最近一次实际重算时间；仅重算时更新

### 非目标 / 暂不处理

- 不在本次文档拆分中移动前后端代码目录
- 不在当前实现中新增独立的钉钉 UI 规格文档
- 不在当前实现中新增“仅保存参数不重算计划”交互
