MP-2 经 4 轮调研 + Neo 反馈,采纳方案 C(推迟到 F1-6 沙箱时光机阶段 B): - 第 1 轮原方案 D(双口径) → 第 2 轮 D'(单口径) - 第 3 轮 Neo 架构纠正:不读 DWD,走 Core/DWS/app - 第 4 轮 DWS 视图靠谱性审计:dws_assistant_daily_detail 是计费明细 (ledger_amount),不是助教工资(gross_salary 需等级时薪 + 抽成 + 罚分),且缺 effective_hours / work_days - 结论:MP-2 真正实施需要新建 dws_assistant_daily_salary 表(ETL 改造),跟其他 14 个 P1 指标一起做更高效 → 推迟到 F1-6 本次 Wave B 只做 prep:DB schema + 模块 spec + tasks.md 状态调整。 DB 迁移(zqyy_app): - db/zqyy_app/migrations/20260505__add_effective_date_for_excel_adjustments.sql - 3 张 Excel 暂存表(全空,Neo 确认尚无 Excel 上传)ADD COLUMN effective_date DATE NOT NULL(无 DEFAULT,强制未来 Excel 上传必须带): * biz.salary_adjustments(助教薪资扣款/奖励) * biz.stg_finance_expense(月度支出) * biz.stg_platform_income(平台结算收入) - 3 个复合索引 (site_id, effective_date) 支持后续 daily 截断查询 - biz.stg_recharge_commission 已有 recharge_date,无需改造 测试库执行 + 5/5 校验 PASS: - 字段存在(NOT NULL DATE 无 default) - 复合索引存在 + 列序正确 - 字段注释含 'F1-5b MP-2 prep' - INSERT 不带 effective_date 触发 NotNullViolation docs/database/ 同步: - docs/database/changes/2026-05-05__add_effective_date_for_excel_adjustments.md 完整变更说明 + 兼容性 + 回滚 + 5 条校验 SQL + 正式库执行说明 沙箱时光机模块 spec(主干任务排期登记): - docs/_overview/sandbox-replay-engine-spec.md - 22 个相关指标分 P1/P2/P3 优先级: * P1 14 项(daily 视图已有,后端切换) * P2 5 项(算法重算,含 MP-2 完整 daily salary) * P3 3 项(状态算法 + sandbox_audit_log 用户行为) - 4 阶段实施路径: * 阶段 0(本次 prep) * 阶段 A(F1-5a/b 已完成) * 阶段 B(F1-6,2-3 周)— MP-2 真正实施在此 * 阶段 C(F1-7+,1-2 周) - sandbox_replay 模块结构 + runtime_aware decorator 接口契约 - 性能 + 测试 + 前置依赖清单 F1-5b-tasks.md 状态调整: - §4.3 顺序 15:MP-2 从"待开始/C4" → "延期 F1-6" - §6 进度表 MP-2 行同步标"延期 F1-6 + 改方向说明" - 关联到 mp2_prep.md 审计 业务影响: - board-coach sandbox 行为暂遗留(F1-6 解决) - 旧 Excel 模板上传将因 NOT NULL 失败,需 F1-6 同期 ETL UI 改造 + 操作员培训 - 跨页面已 audit:board-finance / customer-records / coach-service-records / customer-service-records 等已合规(F1-5b A1/A3 + MP-1/3/5 收益) 审计:docs/audit/changes/2026-05-05__wave1_f1_5b_mp2_prep.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
db/zqyy_app — 业务数据库
zqyy_app 是 NeoZQYY 的业务数据库,存储用户认证、任务队列、调度配置、执行日志等数据。
测试库:test_zqyy_app(开发和测试环境默认连接)。
Schema 架构
| Schema | 用途 | 状态 |
|---|---|---|
auth |
用户认证与权限(微信用户、角色、权限、申请、绑定) | 已建表 |
biz |
业务数据(预留,未来存储门店业务数据) | 已创建,待建表 |
public |
管理后台(admin_users、task_queue、scheduled_tasks、task_execution_log) | 已建表 |
auth Schema — 认证系统(8 张表)
auth.users — 微信用户主表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | SERIAL PK | 自增主键 |
| wx_openid | VARCHAR(128) UNIQUE | 微信 OpenID |
| wx_union_id | VARCHAR(128) | 微信 UnionID |
| wx_avatar_url | VARCHAR(512) | 头像 URL |
| nickname | VARCHAR(50) | 昵称 |
| phone | VARCHAR(20) | 手机号 |
| status | VARCHAR(20) | 状态:pending / approved / rejected / disabled |
| created_at | TIMESTAMPTZ | 创建时间 |
| updated_at | TIMESTAMPTZ | 更新时间 |
auth.site_code_mapping — 球房ID与门店映射
| 字段 | 类型 | 说明 |
|---|---|---|
| id | SERIAL PK | 自增主键 |
| site_code | VARCHAR(10) UNIQUE | 球房ID(格式:2字母+3数字,如 AB123) |
| site_id | BIGINT UNIQUE | 门店 ID(对应 ETL 库的 site_id) |
| site_name | VARCHAR(100) | 门店名称 |
| tenant_id | INT | 租户 ID |
auth.roles — 角色定义
| 字段 | 类型 | 说明 |
|---|---|---|
| id | SERIAL PK | 自增主键 |
| code | VARCHAR(50) UNIQUE | 角色编码 |
| name | VARCHAR(100) | 角色名称 |
| description | TEXT | 描述 |
预置角色:
| code | name | 权限 |
|---|---|---|
coach |
助教 | view_tasks, view_board_coach |
staff |
员工 | view_tasks, view_board |
site_admin |
店铺管理员 | 全部 5 个权限 |
tenant_admin |
租户管理员 | 全部 5 个权限 |
auth.permissions — 权限定义
| 字段 | 类型 | 说明 |
|---|---|---|
| id | SERIAL PK | 自增主键 |
| code | VARCHAR(50) UNIQUE | 权限编码 |
| name | VARCHAR(100) | 权限名称 |
| description | TEXT | 描述 |
预置权限:
| code | name |
|---|---|
view_tasks |
查看任务 |
view_board |
查看看板 |
view_board_finance |
查看财务看板 |
view_board_customer |
查看客户看板 |
view_board_coach |
查看助教看板 |
auth.role_permissions — 角色-权限关联
联合主键 (role_id, permission_id),外键级联删除。
auth.user_applications — 用户入驻申请
| 字段 | 类型 | 说明 |
|---|---|---|
| id | SERIAL PK | 自增主键 |
| user_id | INT FK | 关联 auth.users |
| site_code | VARCHAR(10) | 球房ID |
| site_id | BIGINT | 门店 ID(后端自动填充) |
| applied_role_text | VARCHAR(100) | 申请身份文本 |
| employee_number | VARCHAR(50) | 员工编号 |
| phone | VARCHAR(20) | 手机号 |
| status | VARCHAR(20) | pending / approved / rejected |
| reviewer_id | INT | 审核人 |
| review_note | TEXT | 审核备注 |
| created_at | TIMESTAMPTZ | 申请时间 |
| reviewed_at | TIMESTAMPTZ | 审核时间 |
auth.user_site_roles — 用户-门店-角色关联
| 字段 | 类型 | 说明 |
|---|---|---|
| id | SERIAL PK | 自增主键 |
| user_id | INT FK | 关联 auth.users |
| site_id | BIGINT | 门店 ID |
| role_id | INT FK | 关联 auth.roles |
唯一约束:(user_id, site_id, role_id) — 同一用户在同一门店下不能重复分配同一角色。
auth.user_assistant_binding — 用户-人员绑定
| 字段 | 类型 | 说明 |
|---|---|---|
| id | SERIAL PK | 自增主键 |
| user_id | INT FK | 关联 auth.users |
| site_id | BIGINT | 门店 ID |
| assistant_id | BIGINT | 助教 ID(ETL 库) |
| staff_id | BIGINT | 员工 ID(ETL 库) |
| binding_type | VARCHAR(20) | 绑定类型 |
public Schema — 管理后台
admin_users — 管理后台用户
用于管理后台(apps/admin-web/)的用户名密码登录。
默认种子数据:admin / admin123(生产环境部署后务必修改)。
task_queue — 任务执行队列
存储待执行和执行中的 ETL 任务,按 site_id 隔离。
scheduled_tasks — 调度任务配置
存储定时调度规则,由后端 Scheduler 服务消费。
task_execution_log — 任务执行日志
记录每次 ETL 任务执行的状态、耗时、日志输出。
FDW 跨库访问
zqyy_app 通过 Foreign Data Wrapper(FDW)只读访问 etl_feiqiu 数据库:
- 迁移脚本:
2026-02-24__p1_setup_fdw_etl.sql - 用途:小程序认证时的人员匹配(查询 ETL 库中的助教/员工记录)
- 安全:FDW 连接使用只读用户
目录结构
db/zqyy_app/
├── migrations/ # 迁移脚本(日期前缀)
│ ├── 2026-02-24__p1_create_auth_biz_schemas.sql # 创建 auth + biz Schema
│ ├── 2026-02-24__p1_setup_fdw_etl.sql # 设置 FDW 跨库访问
│ ├── 2026-02-25__p3_create_auth_tables.sql # 创建 auth 8 张表
│ └── 2026-02-25__p3_seed_roles_permissions.sql # 预置角色和权限
├── schemas/ # Schema DDL(待补充)
├── seeds/
│ └── admin_web_seed.sql # 管理后台默认管理员
├── scripts/
│ └── create_test_db.sql # 创建测试库脚本
└── README.md
迁移执行顺序
p1_create_auth_biz_schemas.sql— 创建 Schemap1_setup_fdw_etl.sql— 设置 FDWp3_create_auth_tables.sql— 创建认证表p3_seed_roles_permissions.sql— 插入种子数据
所有迁移脚本使用 IF NOT EXISTS / ON CONFLICT DO NOTHING 幂等语法,可重复执行。
与其他模块的关系
apps/backend/— 通过get_connection()读写此库apps/miniprogram/— 通过后端 API 间接访问apps/admin-web/— 通过后端 API 间接访问db/etl_feiqiu/— 通过 FDW 被此库只读引用