hr-system/docs/01-design/database-design.md

28 KiB
Raw Blame History

迭代1总体设计 —— 数据库设计hr-webocai 口径)

  • 版本v2.0迭代1-总体设计,取代 v1 Java/JPA 口径v1 已归档至 docs/_archive/01-design-v1-old/
  • 状态评审通过主agent评审基线冻结
  • 需求基线:docs/00-requirement/requirement-spec.mdSRS v2+ iteration1-function-detail.mdF01~F15
  • 架构基线:docs/01-design/architecture.md
  • 规范依据ocai 技能集 database-table-definition-specmodels/*.json + json2ddl、crud-definition-spec、sqlor-database-module

1. 设计总则

  1. 表定义声明式管理:所有表以 models/{table}.jsonsummary/fields/indexes/codes 四段定义build.sh 中 json2ddl mysql . > mysql.ddl.sql 生成 DDL 导入 hr 库。本文 DDL 为生成物等价示例,开发以 models JSON 为准。
  2. 统一约定InnoDButf8mb4 / utf8mb4_unicode_ci主键 id VARCHAR(32)getID() 雪花串sqlor 惯例);公共审计列 created_by/updated_by/created_at/updated_atsor.C 不自动填时间戳,写入时显式 created_at=curDateString()
  3. 逻辑删除策略迭代1员工与组织不做物理删除,统一走"停用(status=inactive)/离职流程"(对 baseline-decision Q6 的裁决落地)。
  4. 自定义字段EAV花名册字段F03与组织字段F01采用"字段定义表 + 字段值表"EAV 方案,支撑字段/分组/类型规则自定义;固定高频查询字段(组织、职位、状态、入离职日期)冗余在员工主表保证列表性能。
  5. 敏感字段:身份证号密文列 + 哈希列(确定性,供唯一性与黑名单匹配),手机号明文存储、按角色脱敏展示;roster_field_def.sensitive 驱动字段级脱敏与可见性。
  6. 库划分:单库 hr,表前缀区分模块:org_(hr-org)、roster_(hr-roster)、flow_(hr-flow)、contract_(hr-contract)、sys_(hr-system)appbaseusers/orgs/appcodes与 rbac 表沿用基础包自带结构,不在本文重复。

2. ER 图(实体关系描述)

                      ┌──────────────┐
                      │  appbase     │
                      │ users/orgs/  │◄── 登录用户、字典 appcodes
                      │ appcodes     │
                      └──────┬───────┘
                             │ user_id 引用
┌─────────────┐  parent_id   │      ┌──────────────────┐
│  org_unit   │◄─自引用──────┼──────│  sys_data_scope  │ 组织维度数据范围
│  组织        │              │      │  sys_audit_log   │ 操作日志(F12)
└──┬───┬──────┘              │      │  sys_message     │ 站内消息(F15)
   │   │org_field_value      │      │  sys_remind_rule │ 提醒规则
   │   ▼                     │      └────────▲─────────┘
   │ org_field_def           │               │ 推送
   │                         │               │
   │  ┌─────────────┐  ┌─────▼───────────────┴───┐
   │  │org_job/      │  │     roster_employee      │ 员工唯一事实源(F03)
   │  │org_position◄─┼──│ org_id/position_id/      │
   │  │org_sequence/ │  │ employee_status/...      │
   │  │org_grade_*   │  └──┬──────┬──────┬─────────┘
   │  └─────────────┘     │      │      │
   │                      │      │      ▼
   │        roster_field_def◄────┘  roster_field_value(EAV)
   │        roster_field_group      roster_timeline(时间轴)
   │                      │
   │  异动业务(hr-org)     │      合同(hr-contract)
   │  org_entry ──────────┤      contract_info ── employee_id
   │  org_regularization ─┼──►   contract_type / contract_template
   │  org_transfer(+detail)│     contract_remind_rule
   │  org_leave(+handover) │          │审批
   │  org_concurrent_post  │          ▼
   │        │审批流转       │     ┌──────────────┐
   └────────┴──────────────┴────►│  flow_def    │ 流程定义
              biz_type+biz_id    │  flow_form_def│ 表单定义(引用花名册字段)
                                 │  flow_node_def│ 节点(审批人/字段权限)
                                 │  flow_role    │ 审批角色
                                 │  flow_instance│ 实例 ──► flow_task(待办)
                                 │               │        └► flow_op_log
                                 └──────────────┘
hr-report 无自有表:只读聚合 org_/roster_/flow_ 表,叠加 sys_data_scope 范围过滤。

核心关系说明:

  • roster_employee 为全系统员工数据唯一事实源;org_entry/regularization/transfer/leave/concurrent_post 通过 employee_id(入职审批阶段可为空)关联,审批通过后经 hr-roster 回写接口更新主档。
  • 所有审批类记录通过 flow_instance_id 关联流程实例;flow_instance.biz_type + biz_id 反向定位业务单据,流程完成后回调业务模块回写。
  • roster_field_value/org_field_value 为 EAV 值表,外键指向 roster_field_def/org_field_def
  • 所有表与 appbase.users 之间为逻辑外键operator_id/leader_id/approver_id不建物理外键sqlor 惯例,跨模块解耦)。

3. models JSON 示例规范格式json2ddl 输入)

hr-roster/models/roster_employee.json

{
  "summary": [
    {"name": "roster_employee", "title": "员工主档", "pk": ["id"], "charset": "utf8mb4", "collate": "utf8mb4_unicode_ci"}
  ],
  "fields": [
    {"name": "id", "title": "主键", "type": "varchar", "length": 32},
    {"name": "employee_no", "title": "工号", "type": "varchar", "length": 32},
    {"name": "name", "title": "姓名", "type": "varchar", "length": 64},
    {"name": "gender", "title": "性别", "type": "varchar", "length": 16},
    {"name": "id_number_cipher", "title": "证件号密文", "type": "varchar", "length": 256},
    {"name": "id_number_hash", "title": "证件号哈希", "type": "varchar", "length": 64},
    {"name": "birthday", "title": "出生日期", "type": "date"},
    {"name": "phone", "title": "手机号", "type": "varchar", "length": 20},
    {"name": "email", "title": "邮箱", "type": "varchar", "length": 128},
    {"name": "org_id", "title": "组织", "type": "varchar", "length": 32},
    {"name": "position_id", "title": "职位", "type": "varchar", "length": 32},
    {"name": "job_id", "title": "职务", "type": "varchar", "length": 32},
    {"name": "grade_level_id", "title": "职级", "type": "varchar", "length": 32},
    {"name": "grade_rank_id", "title": "职等", "type": "varchar", "length": 32},
    {"name": "sequence_id", "title": "序列", "type": "varchar", "length": 32},
    {"name": "employee_type", "title": "员工类型", "type": "varchar", "length": 16},
    {"name": "employee_status", "title": "员工状态", "type": "varchar", "length": 16},
    {"name": "hire_date", "title": "入职日期", "type": "date"},
    {"name": "regular_date", "title": "转正日期", "type": "date"},
    {"name": "leave_date", "title": "离职日期", "type": "date"},
    {"name": "company_id", "title": "合同公司", "type": "varchar", "length": 32},
    {"name": "work_location", "title": "办公地点", "type": "varchar", "length": 128},
    {"name": "direct_leader_id", "title": "直属主管", "type": "varchar", "length": 32},
    {"name": "remark", "title": "备注", "type": "text"},
    {"name": "created_by", "title": "创建人", "type": "varchar", "length": 32},
    {"name": "updated_by", "title": "更新人", "type": "varchar", "length": 32},
    {"name": "created_at", "title": "创建时间", "type": "timestamp"},
    {"name": "updated_at", "title": "更新时间", "type": "timestamp"}
  ],
  "indexes": [
    {"name": "uk_employee_no", "unique": true, "fields": ["employee_no"]},
    {"name": "uk_id_number_hash", "unique": true, "fields": ["id_number_hash"]},
    {"name": "idx_org_id", "fields": ["org_id"]},
    {"name": "idx_status", "fields": ["employee_status"]},
    {"name": "idx_hire_date", "fields": ["hire_date"]},
    {"name": "idx_direct_leader", "fields": ["direct_leader_id"]}
  ],
  "codes": [
    {"name": "gender", "source": "appcodes", "code": "GENDER"},
    {"name": "employee_type", "source": "appcodes", "code": "EMP_TYPE"},
    {"name": "employee_status", "source": "appcodes", "code": "EMP_STATUS"}
  ]
}

CRUD 侧配套 hr-roster/json/roster_employee_list.jsoncrud-definition-spectblname=roster_employeeparams 顶层配置 new_data_url/update_data_url/delete_data_url 指向 wwwroot/api/roster_employee_{create,update,delete}.dspydata_filter 声明姓名/工号/组织/状态筛选项,browserfields.alters 引用 GENDER/EMP_TYPE/EMP_STATUS 字典。

4. 表结构设计43 张业务表)

公共列约定:凡标【审计】的表均含 created_by/updated_by/created_at/updated_at;日志类表仅含 created_at。DDL 示例见 §4.6。

4.1 hr-org 组织人事18 张,前缀 org_

# 用途 关键字段 关键索引
1 org_unit 组织F01 id, org_code, org_name, parent_id(自引用), org_type(字典ORG_TYPE), leader_id, effective_date, expire_date(空=长期), status(active/inactive), sort_no【审计】 uk_org_code; idx_parent_id; idx_status
2 org_unit_change 组织变更时间轴F01 id, org_id, change_type(add/edit/disable/move/split/merge/delete), before_json, after_json, effective_date, operator_id, flow_instance_id, created_at idx_org_id; idx_created_at
3 org_field_def 组织自定义字段F01 id, field_code, field_name, field_type(text/number/date/select/file), options_json, required, sort_no, status【审计】 uk_field_code
4 org_field_value 组织字段值 EAV id, org_id, field_id, value_text, value_date, value_file, updated_at uk(org_id,field_id)
5 org_job 职务F02 id, job_code, job_name, status, sort_no, remark【审计】 uk_job_code
6 org_position 职位F02 id, position_code, position_name, job_id, sequence_id, category(字典POS_CATEGORY), dept_ids(多值,逗号分隔), description, status, sort_no【审计】 uk_position_code; idx_job_id
7 org_sequence 序列F02 id, seq_category, seq_name, grade_level_ids(关联职级类别), status【审计】
8 org_grade_level 职级F02 id, level_code, level_name, level_category, start_rank_id, end_rank_id, sort_no【审计】 uk_level_code
9 org_grade_rank 职等F02 id, rank_code, rank_name, rank_level(int), sort_no【审计】 uk_rank_code
10 org_blacklist 黑名单F04/F07 id, name, id_number_hash, id_number_cipher, reason, source(leave/manual), source_employee_id, created_by, created_at idx_id_number_hash
11 org_contract_company 合同公司F01/F09 id, company_code, company_name, credit_code, legal_person, contact_info, status【审计】 uk_company_code
12 org_entry 入职记录F04 id, employee_id(可空,待入职), name, id_number_cipher/hash, employee_type, org_id, position_id, company_id, work_location, hire_date, entry_status(pending_approval/pending_entry/entered/cancelled/blocked), is_rehire, register_status(登记表填写状态), flow_instance_id, remark【审计】 idx_entry_status; idx_hire_date; idx_flow_instance_id
13 org_regularization 转正记录F05 id, employee_id, probation_end_date, regular_date, apply_type(self/proxy/manual), status(pending/approved/rejected/cancelled), flow_instance_id, remark【审计】 idx_employee_id; idx_regular_date
14 org_transfer 调动单F06支持批量 id, transfer_type(promotion/demotion/position_change/org_adjust), status(pending/confirmed/cancelled), effective_date, batch_no, flow_instance_id, remark【审计】 idx_status; idx_effective_date
15 org_transfer_detail 调动明细(逐人) id, transfer_id, employee_id, from_org_id, to_org_id, from_position_id, to_position_id, from_grade_level_id, to_grade_level_id, status idx_transfer_id; idx_employee_id
16 org_leave 离职记录F07 id, employee_id, leave_type(辞职/劝退/合同到期/退休), leave_reason(字典LEAVE_REASON), leave_date, apply_type(self/proxy/manual), status(pending_leave/left/cancelled), handover_status, certificate_file, blacklist_flag, flow_instance_id, remark【审计】 idx_employee_id; idx_status; idx_leave_date
17 org_leave_handover 离职交接项 id, leave_id, item_type(approval/file/subordinate/permission/other), item_content, handover_to_id, status(pending/done), remark idx_leave_id
18 org_concurrent_post 兼岗F08 id, employee_id, org_id, position_id, start_date, end_date, status(awaiting/active/expired), flow_instance_id【审计】 idx_employee_id; idx_status

4.2 hr-roster 花名册7 张,前缀 roster_

# 用途 关键字段 关键索引
19 roster_field_group 字段分组F03 id, group_code, group_name(工作信息/个人信息/绩效结果/培训记录), sort_no, status【审计】 uk_group_code
20 roster_field_def 字段定义F03 核心) id, group_id, field_code, field_name, field_type(text/number/date/select/multiselect/file), options_json(字典code或自定义项), required, sensitive(0/1), editable_self(0/1), need_audit(0/1自助修改审核), apply_types(JSON适用员工类型), sort_no, status【审计】 uk_field_code; idx_group_id
21 roster_employee 员工主档F03 见 §3 models 示例 见 §3
22 roster_field_value 字段值 EAV id, employee_id, field_id, value_text, value_number(decimal(18,4)), value_date, value_file, updated_by, updated_at uk(employee_id,field_id); idx_field_id
23 roster_empno_rule 工号规则F03 id, rule_name, prefix, match_field(如company_id), match_value, seq_length, current_seq(int), status【审计】
24 roster_timeline 员工时间轴F03/F12 联动) id, employee_id, event_type(entry/regular/transfer/leave/concurrent/contract/field_change/migrate), event_date, title, content_json, source_type, source_id, created_at idx_emp_date(employee_id,event_date)
25 roster_type_rule 员工类型字段规则F03 分类管理) id, employee_type, field_rules_json(按类型必填/隐藏字段), status【审计】 uk(employee_type)

4.3 hr-flow 流程审批7 张,前缀 flow_

# 用途 关键字段 关键索引
26 flow_form_def 表单定义F10 id, form_code, form_name, biz_type(entry/regular/transfer/leave/handover/concurrent/contract_sign/contract_renew/contract_change/contract_stop/roster_self_edit), fields_json(引用roster_field_def或自定义项), status【审计】 uk_form_code
27 flow_def 流程定义F10 id, flow_code, flow_name, form_id, biz_type, match_cond_json(员工类型/部门匹配条件), version, status【审计】 uk_flow_code; idx_biz_type
28 flow_node_def 流程节点 id, flow_id, node_seq, node_name, approver_type(user/role/leader/admin/flow_role), approver_value, pass_rule(any/all), field_perm_json(节点字段可读写), cc_to(抄送) idx_flow_id
29 flow_role 审批角色F10 id, role_name, flow_scope_json(可用流程), op_perm_json(操作权限), data_scope_json(数据查看范围), status【审计】
30 flow_instance 流程实例 id, inst_no(审批编号), flow_id, form_id, biz_type, biz_id, title, initiator_id, inst_status(running/approved/rejected/cancelled), submit_data_json, start_time, finish_time uk_inst_no; idx_biz(biz_type,biz_id); idx_initiator; idx_status
31 flow_task 审批任务(待办/已办) id, instance_id, node_id, node_name, approver_id, task_status(pending/approved/rejected/forwarded/cancelled), comment, handle_time, created_at idx_approver_status(approver_id,task_status); idx_instance
32 flow_op_log 流转日志 id, instance_id, op_type(submit/approve/reject/forward/cancel/withdraw), operator_id, comment, created_at idx_instance

4.4 hr-contract 合同4 张,前缀 contract_

# 用途 关键字段 关键索引
33 contract_type 合同类型F09 自定义) id, type_code, type_name(劳动合同/保密协议/竞业协议…), status【审计】 uk_type_code
34 contract_template 合同模板F09 id, template_name, type_id, file_path, field_marks_json(占位符映射), status【审计】
35 contract_info 合同台账F09 id, contract_no, employee_id, type_id, company_id, template_id, start_date, end_date, sign_date, contract_status(active/expired/stopped/renewing), file_path, flow_instance_id, remind_rule_id, esign_status(预留), remark【审计】 idx_employee; idx_end_date; idx_status
36 contract_remind_rule 到期提醒规则F09 id, rule_name, days_before(int), target_role(self/leader/hr), content_template, status【审计】

4.5 hr-system 权限日志与通用服务7 张,前缀 sys_

# 用途 关键字段 关键索引
37 sys_data_scope 数据范围F11 id, admin_user_id(管理员), scope_type(org/field), org_ids_json(组织维度,含子树), field_ids_json(花名册字段维度), remark【审计】 idx_admin_user
38 sys_audit_log 操作日志F12只增不改 id, module, target_type, target_id, operation(create/update/delete/import/export/approve/login), operator_id, operator_name, before_json, after_json, request_ip, created_at idx_target(target_type,target_id); idx_operator; idx_created_at; idx_module_op(module,operation)
39 sys_message 站内消息F15 id, receiver_id, msg_type(todo/approval/remind/care/notice), title, content, biz_type, biz_id, send_channel(site; sms/email预留), is_read, created_at idx_receiver_read(receiver_id,is_read); idx_created_at
40 sys_remind_rule 通用提醒规则F12 场景) id, scene_code(entry/regular/leave/retire/contract_expire/health_cert/social_insurance/custom), rule_name, days_before, content_template, target_role(admin/employee/leader), status【审计】 uk(scene_code,rule_name)
41 sys_announcement 企业公告F15 id, title, content, publish_scope_json, publish_time, status(draft/published/offline), created_by【审计】 idx_status
42 sys_policy 企业政策F15 id, title, file_path, view_scope_json, downloadable(0/1), publish_time, status, created_by【审计】 idx_status
43 sys_care_config 关怀配置F15 生日/周年) id, care_type(birthday/anniversary), template, enable(0/1), push_target(employee/leader), updated_by, updated_at uk_care_type

4.6 核心表 DDL 示例json2ddl 生成等价物)

-- roster_employee完整 DDL 见 §3 models JSON
CREATE TABLE roster_employee (
  id VARCHAR(32) NOT NULL COMMENT '主键',
  employee_no VARCHAR(32) NOT NULL COMMENT '工号',
  name VARCHAR(64) NOT NULL COMMENT '姓名',
  gender VARCHAR(16) DEFAULT NULL COMMENT '性别(字典GENDER)',
  id_number_cipher VARCHAR(256) DEFAULT NULL COMMENT '证件号密文',
  id_number_hash VARCHAR(64) DEFAULT NULL COMMENT '证件号哈希(唯一)',
  birthday DATE DEFAULT NULL,
  phone VARCHAR(20) DEFAULT NULL,
  email VARCHAR(128) DEFAULT NULL,
  org_id VARCHAR(32) DEFAULT NULL COMMENT '组织',
  position_id VARCHAR(32) DEFAULT NULL COMMENT '职位',
  job_id VARCHAR(32) DEFAULT NULL COMMENT '职务',
  grade_level_id VARCHAR(32) DEFAULT NULL COMMENT '职级',
  grade_rank_id VARCHAR(32) DEFAULT NULL COMMENT '职等',
  sequence_id VARCHAR(32) DEFAULT NULL COMMENT '序列',
  employee_type VARCHAR(16) DEFAULT NULL COMMENT '员工类型(字典EMP_TYPE)',
  employee_status VARCHAR(16) DEFAULT NULL COMMENT '状态(字典EMP_STATUS)',
  hire_date DATE DEFAULT NULL,
  regular_date DATE DEFAULT NULL,
  leave_date DATE DEFAULT NULL,
  company_id VARCHAR(32) DEFAULT NULL COMMENT '合同公司',
  work_location VARCHAR(128) DEFAULT NULL,
  direct_leader_id VARCHAR(32) DEFAULT NULL COMMENT '直属主管',
  remark TEXT DEFAULT NULL,
  created_by VARCHAR(32) DEFAULT NULL,
  updated_by VARCHAR(32) DEFAULT NULL,
  created_at TIMESTAMP NULL DEFAULT NULL,
  updated_at TIMESTAMP NULL DEFAULT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY uk_employee_no (employee_no),
  UNIQUE KEY uk_id_number_hash (id_number_hash),
  KEY idx_org_id (org_id),
  KEY idx_status (employee_status),
  KEY idx_hire_date (hire_date),
  KEY idx_direct_leader (direct_leader_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='员工主档';

CREATE TABLE org_unit (
  id VARCHAR(32) NOT NULL,
  org_code VARCHAR(32) NOT NULL COMMENT '组织编码',
  org_name VARCHAR(128) NOT NULL COMMENT '组织名称',
  parent_id VARCHAR(32) DEFAULT NULL COMMENT '上级组织',
  org_type VARCHAR(16) DEFAULT NULL COMMENT '组织类型(字典ORG_TYPE)',
  leader_id VARCHAR(32) DEFAULT NULL COMMENT '负责人',
  effective_date DATE DEFAULT NULL COMMENT '生效日期',
  expire_date DATE DEFAULT NULL COMMENT '失效日期(空=长期)',
  status VARCHAR(16) NOT NULL DEFAULT 'active' COMMENT 'active/inactive',
  sort_no INT DEFAULT 0,
  remark TEXT DEFAULT NULL,
  created_by VARCHAR(32) DEFAULT NULL, updated_by VARCHAR(32) DEFAULT NULL,
  created_at TIMESTAMP NULL DEFAULT NULL, updated_at TIMESTAMP NULL DEFAULT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY uk_org_code (org_code),
  KEY idx_parent_id (parent_id),
  KEY idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='组织';

CREATE TABLE flow_instance (
  id VARCHAR(32) NOT NULL,
  inst_no VARCHAR(32) NOT NULL COMMENT '审批编号',
  flow_id VARCHAR(32) NOT NULL, form_id VARCHAR(32) NOT NULL,
  biz_type VARCHAR(32) NOT NULL COMMENT '业务类型', biz_id VARCHAR(32) DEFAULT NULL COMMENT '业务单据ID',
  title VARCHAR(256) DEFAULT NULL,
  initiator_id VARCHAR(32) NOT NULL,
  inst_status VARCHAR(16) NOT NULL DEFAULT 'running' COMMENT 'running/approved/rejected/cancelled',
  submit_data_json TEXT DEFAULT NULL COMMENT '提交表单数据快照',
  start_time TIMESTAMP NULL DEFAULT NULL, finish_time TIMESTAMP NULL DEFAULT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY uk_inst_no (inst_no),
  KEY idx_biz (biz_type, biz_id),
  KEY idx_initiator (initiator_id),
  KEY idx_status (inst_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='流程实例';

CREATE TABLE sys_audit_log (
  id VARCHAR(32) NOT NULL,
  module VARCHAR(32) NOT NULL COMMENT 'hr-org/hr-roster/...',
  target_type VARCHAR(32) NOT NULL COMMENT 'roster_employee/org_unit/...',
  target_id VARCHAR(32) NOT NULL,
  operation VARCHAR(16) NOT NULL COMMENT 'create/update/delete/import/export/approve/login',
  operator_id VARCHAR(32) NOT NULL, operator_name VARCHAR(64) DEFAULT '',
  before_json TEXT DEFAULT NULL COMMENT '变更前快照',
  after_json TEXT DEFAULT NULL COMMENT '变更后快照',
  request_ip VARCHAR(64) DEFAULT NULL,
  created_at TIMESTAMP NULL DEFAULT NULL,
  PRIMARY KEY (id),
  KEY idx_target (target_type, target_id),
  KEY idx_operator (operator_id),
  KEY idx_created_at (created_at),
  KEY idx_module_op (module, operation)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操作日志(只增)';

5. 索引与性能策略

  1. 100 人规模全表扫描亦可满足 ≤500ms但仍按查询模式建索引列表筛选列status/org_id/hire_date/end_date、EAV 值表 uk(employee_id,field_id)、待办 idx(approver_id,task_status)。
  2. 组织树、职位职级主数据一次性全量加载≤200/≤500 行),前端缓存,无需分页。
  3. EAV 查询模式:花名册列表先按主表条件分页取员工,再批量 IN 查值表拼装(每页 ≤50 人 × 显示字段数),避免 EAV 行转列大 JOIN。
  4. 报表hr-report直接 SQL 聚合sor.sqlExe 只读100 人规模不建物化视图sys_audit_log 按月保留,冷数据归档不删除。
  5. 唯一性:工号、组织编码、职位/职务/职级/职等编码、审批编号均唯一索引;证件号经哈希列唯一(加密为非确定性,哈希列承担唯一与黑名单匹配)。

6. 数据字典appbase appcodesinit/data.json 初始化)

code 说明
GENDER male/female/unknown 性别
ORG_TYPE group/subsidiary/dept/team 组织类型
EMP_TYPE formal/temp/dispatch/intern 员工类型(正式/临时/派遣/实习)
EMP_STATUS pending_entry/probation/regular/pending_leave/left 员工状态(待入职/试用/正式/待离职/离职)
POS_CATEGORY management/professional/skill 职位类别
TRANSFER_TYPE promotion/demotion/position_change/org_adjust 调动类型
LEAVE_REASON personal/company/contract_expire/retire/other 离职原因
CONTRACT_STATUS active/expired/stopped/renewing 合同状态
FLOW_BIZ_TYPE entry/regular/transfer/leave/handover/concurrent/contract_sign/contract_renew/contract_change/contract_stop/roster_self_edit 审批业务类型
INST_STATUS running/approved/rejected/cancelled 实例状态
REMIND_SCENE entry/regular/leave/retire/contract_expire/health_cert/social_insurance/custom 提醒场景
AUDIT_OP create/update/delete/import/export/approve/login 操作类型

枚举一律不硬编码于 dspyCRUD 下拉经 models codes 段引用。

7. staff-mgr 数据迁移策略v1 → 迭代1

迁移工具:repos/hr-system 仓内规划 scripts/migrate_staff_mgr.pyPython + sqlor幂等可重跑输出核对报告

v1 源表staff-mgr 目标表 映射规则
staff_department_cache org_unit 按树形重建 parent_idorg_code=DEPT{id}status 映射 active/inactive
staff_employee roster_employee employee_no/name/gender/phone/email 直映id_number AES 解密后按新方案重加密cipher+hashdepartment_id→org_idposition 文本→预置 org_position无匹配则建"未定职"status: active→regular、probation→probation、inactive→lefthire_date 直映
staff_employee_extra roster_field_value + contract_info education/major/school/graduation_date/previous_company/work_years → 预置 roster_field_def 字段值technical_level/salary_grade → 预置敏感字段值contract_type/start/end → contract_infotype_id 映射正式/外包/实习协议)
staff_change_log roster_timeline change_type→event_type(transfer/field_change)old/new 值入 content_jsonevent_type 前缀 migrate: 标识迁移来源
staff_audit_log sys_audit_log 字段直映module 标记 staff-mgr-legacy

策略与约束:

  1. 顺序org_unit → org_position预置→ roster_field_def/group预置→ roster_employee → roster_field_value → contract_info → timeline/audit。
  2. 幂等:按 employee_no/org_code 去重,重跑仅补差;证件号哈希冲突时输出冲突报告人工裁决(对 baseline-decision Q6冲突员工按离职记录保留不入在职
  3. 切换迭代1 UAT 通过后一次性迁移+双库比对 → staff-mgr 服务下线、仓库冻结只读(保留一个迭代周期)。
  4. 迁移全程写 sys_audit_logoperation=migrate迁移数据在时间轴/日志中可辨识。

8. 与需求验收项的映射(摘选)

验收项function-detail 数据支撑
F01-4 时间轴留痕 org_unit_change
F03-1/2 自定义字段与分组 roster_field_def/group/value
F03-3 多规则工号 roster_empno_rule
F03-4 自助修改审核 roster_field_def.editable_self/need_audit + flow biz_type=roster_self_edit
F03-6 类型差异规则 roster_type_rule + apply_types
F04-4 黑名单拦截 org_blacklistid_number_hash 匹配)
F07-5 离职证明 org_leave.certificate_filefiles/ 存储)
F09-6 电子签预留 contract_info.esign_status
F10-2 字段权限 flow_node_def.field_perm_json
F11-2 双维度数据范围 sys_data_scope(scope_type=org/field)
F12-3 前后对比 sys_audit_log.before_json/after_json
F15-4 多场景提醒 sys_remind_rule(scene_code)