# 考勤数据库设计说明

本文档记录当前已建表结构和后续考勤模块落库的目标模型。当前项目仍以 fixture 联调为主，本文中的“目标表”用于后续 migration 设计，不表示已经落库。

## 当前已落库表

当前 Flyway migration：

```text
src/main/resources/db/migration/V1__create_attendance_core_tables.sql
```

已创建 5 张表：

| 表 | 用途 | 当前状态 |
|----|------|----------|
| `atd_scheme` | 考勤方案主表 | 已建表，接口仍主要走 fixture |
| `atd_scheme_manager` | 考勤方案负责人关系 | 已建表，接口仍主要走 fixture |
| `atd_scheme_scope` | 考勤方案适用范围/排除范围 | 已建表，接口仍主要走 fixture |
| `atd_punch_record` | 原始打卡记录 | 已建表，生产打卡接口尚未实现 |
| `atd_summary_task` | 异步汇总任务 | 已建表，真实汇总任务尚未实现 |

本地默认使用 H2 内存库，生产 profile 使用 MySQL/RDS。现阶段大部分菜单数据仍由内存 fixture 提供，服务重启后恢复默认值。

## 当前表设计

### atd_scheme

考勤方案主表，承载方案基础信息和规则组件引用。

核心字段：

| 字段 | 说明 |
|------|------|
| `id` | 主键，兼容旧系统长 ID |
| `eid` | 旧系统业务版本或乐观锁字段 |
| `prefix/code/name` | 编码前缀、编码、名称 |
| `state` | 启用状态 |
| `model_type` | 考勤方式：打卡、不打卡、暂停 |
| `atd_type` | 考勤类型：排班制、固定班制 |
| `mgr_org_id/mgr_org_name/mgr_org_type` | 管理组织 |
| `calendar_id` | 工作日历 |
| `cycle_template_id` | 考勤周期 |
| `check_template_group_id` | 打卡规则 |
| `leave_template_group_id` | 请假规则 |
| `official_template_group_id` | 公出规则 |
| `card_template_id` | 补卡规则 |
| `data_day_template_id` | 每日汇总规则 |
| `overtime_template_group_id` | 加班规则 |
| `class_template_id` | 排班规则 |
| `config_json` | 早期承载扩展配置 |
| `source_type/source_type_name` | 数据来源 |
| `deleted` | 软删除 |

索引：

- `uk_atd_scheme_code`
- `idx_atd_scheme_mgr_org`
- `idx_atd_scheme_state_deleted`

### atd_scheme_manager

方案负责人关系表。

| 字段 | 说明 |
|------|------|
| `id` | 主键 |
| `scheme_id` | 方案 ID |
| `manager_id` | 负责人 ID |
| `manager_name` | 负责人姓名 |

约束：

- `uk_atd_scheme_manager (scheme_id, manager_id)`

### atd_scheme_scope

方案适用范围、排除范围等关系表。

| 字段 | 说明 |
|------|------|
| `id` | 主键 |
| `scheme_id` | 方案 ID |
| `scope_type` | 范围类型，例如 right/rightExclude |
| `target_id` | 目标组织或人员 ID |
| `target_name` | 目标名称 |
| `target_type` | 目标类型 |

### atd_punch_record

原始打卡记录表。生产打卡链路应先写入此表，再异步触发汇总。

| 字段 | 说明 |
|------|------|
| `id` | 主键 |
| `employee_id/employee_name` | 员工 |
| `org_id` | 打卡时组织 |
| `scheme_id` | 打卡时匹配到的考勤方案 |
| `punch_time` | 实际打卡时间 |
| `work_date` | 归属工作日 |
| `source_type` | 来源：移动端、考勤机、导入等 |
| `punch_type` | 上班卡、下班卡、外勤等 |
| `device_id/address_id/wifi_id` | 匹配到的资源 |
| `longitude/latitude` | 经纬度 |
| `request_id` | 幂等键 |
| `raw_payload` | 原始请求 |

约束：

- `uk_atd_punch_request (request_id)`

索引：

- `idx_atd_punch_employee_date`
- `idx_atd_punch_org_time`
- `idx_atd_punch_scheme_date`

### atd_summary_task

异步汇总任务表。

| 字段 | 说明 |
|------|------|
| `id` | 主键 |
| `task_type` | 任务类型 |
| `biz_date` | 业务日期 |
| `employee_id` | 员工，允许为空表示批量 |
| `state` | pending/running/success/failed |
| `retry_count` | 重试次数 |
| `last_error` | 最近错误 |

## 目标表分组

### 考勤档案

建议新增 `atd_archive`。

用途：记录员工在任意时间段内适用的考勤方案、考勤组织、考勤方式、考勤类型、工作日历、打卡规则等。

建议字段：

| 字段 | 说明 |
|------|------|
| `id/eid` | 主键和旧系统版本字段 |
| `person_id/person_name/number` | 员工 |
| `dept_id/dept_name` | 所属部门快照 |
| `person_start_time/person_end_time/retire_time` | 入职、离职、退休日期快照 |
| `person_state_name` | 员工状态快照 |
| `atd_org_id/atd_org_name/atd_org_type` | 考勤组织 |
| `model_type` | 考勤方式 |
| `scheme_template_id` | 考勤方案 |
| `atd_type` | 考勤类型 |
| `class_cycle_template_id` | 排班周期 |
| `calendar_id` | 工作日历 |
| `check_template_group_id` | 打卡规则 |
| `archive_type` | normal/support/abnormal |
| `start_date/end_date` | 生效和截止日期 |
| `source_type` | manual/init/hr_event/import |
| `original_id` | 从哪条档案追加 |
| `deleted` | 软删除 |

关键规则：

- 同一 `person_id` 的有效档案日期区间不能重叠。
- `start_date` 不能早于 `person_start_time`。
- 追加新档案时，应关闭上一条永久档案。
- 离职/退休/返聘/部门调动等事件应通过事件链更新档案，不直接写在 controller。

推荐索引：

- `(person_id, start_date, end_date, deleted)`
- `(atd_org_id, start_date, end_date)`
- `(scheme_template_id, start_date, end_date)`
- `(archive_type, start_date, end_date)`

### 打卡规则资源

建议表：

| 表 | 用途 |
|----|------|
| `atd_check_template_group` | 打卡规则组 |
| `atd_check_template_resource` | 规则组与地址/WIFI/考勤机关系 |
| `atd_address` | 考勤地址 |
| `atd_wifi` | WIFI |
| `atd_device` | 考勤机 |
| `atd_device_person` | 考勤机下发人员 |
| `atd_region` | 考勤区域 |
| `atd_ai_face` | 人脸底库 |

规则：

- 打卡规则组至少关联地址、WIFI、考勤机中的一种资源。
- 被规则组引用的资源不可直接删除。
- 地址编码、WIFI 编码、考勤机 SN 属于不可随意修改字段。
- 云端人脸识别、硬件下发和离职自动移除人员属于外部集成或事件链。

### 排班与班次

建议表：

| 表 | 用途 |
|----|------|
| `atd_class_template` | 排班规则 |
| `atd_class_compliance_template` | 合规规则 |
| `atd_cycle_template` | 考勤周期 |
| `atd_shift_class` | 班次 |
| `atd_schedule` | 员工实际排班 |

规则：

- 规则配置和实际排班分表。
- 员工部门调动导致的刷新排班应进入任务链，最多刷新过去 31 天等限制不写死在 controller。

### 请假、公出、补卡、加班、汇总规则

建议表：

| 表 | 用途 |
|----|------|
| `atd_leave_template_group` | 请假规则组 |
| `atd_leave_template` | 假期规则 |
| `atd_leave_balance_rule` | 假期余额规则 |
| `atd_official_template_group` | 公出规则组 |
| `atd_official_type` | 公出类别 |
| `atd_card_template` | 补卡规则 |
| `atd_overtime_template_group` | 加班规则组 |
| `atd_overtime_calc_type` | 加班计算规则 |
| `atd_overtime_type` | 加班类别 |
| `atd_data_day_template` | 每日汇总规则 |

早期可用 `config_json` 保存复杂配置，但列表筛选和常用关联字段应拆列。

## 事件和任务模型

建议后续新增：

| 表 | 用途 |
|----|------|
| `atd_biz_event` | 人事变动、规则变更、导入等业务事件 |
| `atd_recompute_task` | 排班刷新、每日统计重算、余额重算等任务 |
| `atd_import_task` | 导入任务及结果 |
| `atd_export_task` | 导出任务及文件信息 |

事件来源示例：

- 员工入职、离职、退休、返聘。
- 部门调动、转正并调整部门。
- 考勤方案、档案、排班规则变更。
- 导入档案或规则。

## 落库迁移策略

1. 先保留当前 fixture 接口，新增 Repository-backed 实现。
2. 用配置或 profile 切换 fixture/DB。
3. 先迁移考勤方案和规则配置，再迁移考勤档案。
4. 原始打卡记录落库后，再做异步汇总和真实计算。
5. 迁移一个模块时必须保留旧接口响应结构和字段别名。
6. 每个 migration 配套 MockMvc 或 Service 测试，覆盖新增、编辑、删除、列表和关键校验。

## 当前缺口

- 尚无 `atd_archive`，考勤档案仍是内存数据。
- 尚无打卡规则、请假规则、排班规则等配置表，相关接口仍由 fixture 支撑。
- 尚无真实打卡写入接口使用 `atd_punch_record`。
- 尚无事件链处理人事变动到考勤档案同步。
- 尚无异步汇总任务消费者。
