Files
nexus/Project/fonrey/TECH_STACK/组织人事技术方案.md
2026-04-30 20:33:51 +08:00

11 KiB
Raw Blame History

For AI assistants: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked.

Fonrey 组织人事技术方案

版本: 1.0
项目: Fonrey 房产经纪管理系统
技术栈: Django 4.x + HTMX + Alpine.js + PostgreSQL 16 + Redis + Celery
关联 PRD: PRD/组织人事管理/组织人事管理模块PRD.mdv1.2
关联数据模型: DATA_MODEL/DATA_MODEL_ORG.md(本方案不重复 DDL
关联契约规范: TECH_STACK/API_CONTRACT.md(全局 API 契约权威)
关联枚举字典: DATA_MODEL/ENUMS.md
最后更新: 2026-04-27


变更历史

日期 变更人 变更内容
2026-04-30 Atlas 补充“变更历史”章节(文档治理)

一、文档定位与边界

本文件只定义组织人事模块的:

  1. 服务边界与模块协作
  2. API 端点设计(重点)
  3. HTMX 局刷协议
  4. 权限接入、异动审计、缓存与性能约束
  5. 测试与验收映射

不在本文件展开org_units/staff/staff_transfer_logs/staff_reward_punish/staff_accounts 结构细节。以 DATA_MODEL_ORG.md 为唯一权威。


二、范围定义(以 TASK.md 为准)

2.1 P0 必须覆盖

  • US-ORG-001管理员维护公司组织结构部门/门店树)
  • US-ORG-002管理员查看与维护员工列表
  • US-ORG-003管理员办理员工入职并创建系统账号

2.2 P1/P2 预留

  • US-ORG-010员工离职与调动
  • US-ORG-011员工通讯录
  • US-ORG-012员工职务管理
  • US-ORG-020全局异动记录
  • US-ORG-021员工奖惩记录
  • US-ORG-022门店分布地图

三、模块架构边界

3.1 模块职责(apps/org

  • 管理组织树(公司→事业部→大区→区域→片区→门店→店组→职能)
  • 管理员工主档(任职、联系方式、账号、状态)
  • 管理入职与账号开通主流程
  • 维护人事异动审计链路(入职/调动/离职/复职等)

3.2 外部依赖

依赖模块 依赖内容 依赖方式
apps/account 新员工账号创建、初始密码策略、登录状态联动 Service 调用
apps/permission 组织/员工管理权限校验 PermissionChecker
apps/property 员工离职/调动时业务归属迁移(预留) 异步任务
apps/client 客源归属迁移(预留) 异步任务
core/encryption.py 手机号/证件号加密存储与脱敏 统一工具
core/cache.py 组织树缓存、员工选择器缓存 Redis
Celery 批量导出、跨模块归属迁移、异动统计重算 异步任务

3.3 分层约束

  • views.py 仅做参数校验、权限门禁、响应组装
  • 组织层级规则(店组必须挂门店、经纪人归属限制)必须在 services/ 强校验
  • 员工状态变更必须联动写 staff_transfer_logs(不可删除)
  • 与账号相关操作通过 AccountService,禁止跨模块直写登录表

四、API 设计原则

  1. 页面路由与数据 API 分离:
    • 页面:/org/...
    • 数据:/api/org/...
  2. 组织树、员工列表、异动记录采用 HTMX 局刷,减少全页刷新。
  3. 手机号/证件号默认脱敏展示,明文查看须权限与审计。
  4. 账号状态(启用/冻结)与员工状态变更必须一致性联动。
  5. 所有异动事件统一错误协议与日志结构,便于审计与报表。

五、端点清单(核心)

5.1 页面路由SSR + HTMX 容器)

路径 方法 鉴权 说明
/org/structure/ GET 组织结构主页面(组织树 + 员工列表)
/org/departments/create/ GET 新增部门页面
/org/departments/{org_id}/ GET 部门详情
/org/departments/{org_id}/edit/ GET 编辑部门
/org/staff/{staff_id}/ GET 员工详情页(多 Tab
/org/transfer-logs/ GET 全局异动记录页(预留)

5.2 HTMX 片段端点

路径 方法 用途 返回
/org/fragments/org-tree/ GET 左侧组织树局刷 HTML
/org/fragments/staff-table/ POST 员工列表筛选/分页局刷 HTML
/org/staff/{id}/fragments/tab/{tab}/ GET 员工详情 Tab 懒加载 HTML
/org/fragments/department-staff-selector/ GET 选择器弹层局刷 HTML

fragment 端点必须校验 HX-Request=true,否则 400。

5.3 JSON APIP0

端点 方法 权限 code建议 说明
/api/org/departments/tree/ GET hr.org.view.scope 组织树加载US-001
/api/org/departments/ POST hr.org.edit.allow 新增部门US-001
/api/org/departments/{id}/ PATCH hr.org.edit.allow 编辑部门US-001
/api/org/departments/{id}/close/ POST hr.org.edit.allow 关闭部门
/api/org/staff/query/ POST hr.staff.view.scope 员工列表查询US-002
/api/org/staff/{id}/detail/ GET hr.staff.view.scope 员工详情US-002
/api/org/staff/onboard/ POST hr.staff.create.allow 办理入职+建账号US-003
/api/org/staff/{id}/base-info/ PATCH hr.staff.edit.allow 编辑员工基础信息US-002
/api/org/staff/{id}/account/freeze/ POST hr.staff.account.manage.allow 冻结账号(预留)
/api/org/staff/{id}/account/unfreeze/ POST hr.staff.account.manage.allow 解冻账号(预留)
/api/org/staff/{id}/phone/view/ POST hr.staff.phone.view.allow 查看完整手机号(审计)

六、关键 API 规范(请求/响应)

6.1 新增部门

POST /api/org/departments/

{
  "name": "都市港湾店二组",
  "parent_id": "uuid",
  "type": "group",
  "address_city": "上海",
  "address_district": "闵行区",
  "address_detail": "XX路XX号",
  "manager_id": "uuid"
}

规则:

  • type=group 时父节点必须为 store
  • 违反层级约束返回 400

6.2 员工列表查询

POST /api/org/staff/query/

{
  "keyword": "张三",
  "filters": {
    "org_unit_ids": ["uuid"],
    "status": ["active", "probation"],
    "job_category": ["置业顾问"]
  },
  "sort": {"field": "updated_at", "order": "desc"},
  "pagination": {"mode": "keyset", "cursor": "opaque_cursor", "limit": 20}
}

6.3 办理入职并创建账号

POST /api/org/staff/onboard/

{
  "name": "李雷",
  "phone": "13800000000",
  "org_unit_id": "uuid",
  "job_title": "高级业务员",
  "job_category": "置业顾问",
  "role_codes": ["agent"],
  "supervisor_id": "uuid"
}

成功 201

{
  "staff_id": "uuid",
  "user_id": 12345,
  "initial_password_sent": true,
  "message": "入职办理成功"
}

联动要求:

  • 创建 staff
  • 创建/绑定 auth_user
  • 写入一条 staff_transfer_logs(transfer_type='onboard')

6.4 查看员工手机号(审计)

POST /api/org/staff/{id}/phone/view/

{
  "reason": "入职资料核对"
}

规则:

  • 必须有 hr.staff.phone.view.allow
  • 返回明文仅本次有效
  • 必须写入审计日志(操作者、时间、原因)

七、HTMX 交互约定

7.1 Header 约定

  • 请求:HX-Request: true
  • 成功:HX-Trigger: {"toast":{"level":"success","message":"操作成功"}}
  • 失败:HX-Trigger: {"toast":{"level":"error","message":"操作失败"}}
  • 跳转:HX-Redirect: /org/staff/{id}/

7.2 模板分片命名

场景 模板
组织树 templates/org/fragments/org_tree.html
员工列表 templates/org/fragments/staff_table.html
员工详情-异动记录 templates/org/fragments/staff_transfer_logs.html
部门人员选择器 templates/org/fragments/department_staff_selector.html

八、权限与数据范围

8.1 最小权限矩阵P0 建议)

能力 权限 code
查看组织结构范围 hr.org.view.scope
编辑组织结构 hr.org.edit.allow
查看员工列表范围 hr.staff.view.scope
新建员工 hr.staff.create.allow
编辑员工 hr.staff.edit.allow
账号冻结/恢复 hr.staff.account.manage.allow
查看员工手机号 hr.staff.phone.view.allow

8.2 数据范围叠加

最终可见数据 = scope 过滤员工状态过滤组织层级过滤

  • 系统管理员可走 is_system_admin 短路
  • 普通管理员按 scope 限制组织子树

九、异步任务与缓存策略

9.1 Celery 任务

任务 触发时机 说明
org_staff_export_task 导出员工列表 异步导出 Excel
org_transfer_affiliation_task 离职/调动后(预留) 迁移房源/客源归属
org_transfer_summary_task 每日定时 异动统计重算

9.2 Redis Key 规范

Key TTL 说明
{schema}:org:tree:{staff_id} 300s 组织树缓存
{schema}:org:staff:list:{hash} 60s 员工筛选缓存
{schema}:org:staff:detail:{staff_id} 120s 员工详情聚合缓存
{schema}:org:selector:staff:{org_unit_id} 300s 选择器缓存

写操作成功后必须主动失效相关 key。


十、性能与可靠性约束

  1. 组织树查询基于 path 前缀与索引,避免递归 N+1。
  2. 员工列表采用 Keyset 分页,避免深分页性能退化。
  3. 员工详情按 Tab 懒加载,避免一次加载全量档案。
  4. 批量操作(导入/导出/调动)需限流与幂等控制。

十一、安全与合规

  1. 手机号与证件号全程加密存储,前端默认脱敏。
  2. 以下动作必须写 staff_transfer_logs:入职、调动、离职、复职、上级变更、冻结/解冻。
  3. staff.status='resigned'staff.status='frozen' 时,auth_user.is_active=False
  4. 恢复在职后才可重新启用账号。

十二、错误码建议

code HTTP 场景
ORG_UNIT_NOT_FOUND 404 部门不存在或无权限
ORG_INVALID_HIERARCHY 400 组织层级违反规则(如店组不挂门店)
STAFF_NOT_FOUND 404 员工不存在或无权限
STAFF_PHONE_DUPLICATED 409 手机号冲突
STAFF_ACCOUNT_CREATE_FAILED 500 账号创建失败
ORG_PERMISSION_DENIED 403 权限不足

十三、测试映射

13.1 P0 User Story 映射

User Story 最低覆盖
US-ORG-001 组织树查询、新增/编辑部门、层级约束校验
US-ORG-002 员工列表筛选、详情加载、权限过滤
US-ORG-003 入职建档+账号创建、必填校验、异动日志写入

测试文件:tests/integration/org/test_us_org.py

13.2 强制测试约束

  • 集成测试使用 TenantClient
  • HTMX 请求携带 HTTP_HX_REQUEST=true
  • 权限三态200 / 403 / 302
  • 外部服务(短信/邮件/Redis/Celery全部 mock

十四、落地顺序建议

  1. 先实现组织树与员工列表查询US-ORG-001/002
  2. 再实现入职流程与账号开通US-ORG-003
  3. 补齐审计与缓存失效机制
  4. 再推进离职/调动、通讯录、奖惩等 P1/P2 能力

十五、文档同步规则

  • 枚举变更:同步 DATA_MODEL/ENUMS.md
  • 权限 code 变更:同步 DATA_MODEL/DATA_MODEL_PERMISSION.md
  • 数据结构变更:同步 DATA_MODEL/DATA_MODEL_ORG.md
  • API 变更:同步本文件与 PRD/TASK.md 对应条目