# 评查点数据库执行说明与验证SQL

> 适用范围：`evaluation_points` 旧表 tenant 化收尾  
> 更新日期：2026-05-21  
> 文档定位：给 DBA / 开发 / 审核人明确“评查点 tenant_code 补列脚本”执行前看什么、执行什么、执行后怎么验。

---

## 1. 本次要执行什么

`P0` 当前只处理评查点旧表 `evaluation_points` 的数据库收尾，不涉及业务逻辑大改。

本次数据库动作只有一条主线：

1. 执行前预检
2. 执行补列与历史回填脚本
3. 执行后验收

当前对应文件：

1. 预检 SQL
   - [precheck_evaluation_points_tenant_cleanup.sql](/home/wren-dev/Porject/leaudit-platform/scripts/创建sql/precheck_evaluation_points_tenant_cleanup.sql)
2. 正式脚本
   - [schema_evaluation_points_tenant_cleanup.sql](/home/wren-dev/Porject/leaudit-platform/scripts/创建sql/schema_evaluation_points_tenant_cleanup.sql)
3. 模块收尾说明
   - [评查点模块收尾清单.md](/home/wren-dev/Porject/leaudit-platform/docs/权限与地区隔离/评查点模块收尾清单.md)
4. 预检结果判读模板
   - [评查点预检结果判读模板.md](/home/wren-dev/Porject/leaudit-platform/docs/权限与地区隔离/评查点预检结果判读模板.md)

补充说明：

1. 预检脚本已经兼容“旧库尚未补 `tenant_code / tenant_name` 列”的场景
2. 也就是说，正式落库前就可以先在旧环境直接执行预检，不会因为缺列而先报错

---

## 2. 为什么现在要先做数据库

当前评查点模块代码已经进入“tenant-first 兼容态”：

1. 有 `tenant_code / tenant_name` 列时，service 会优先读写它们
2. 没有列时，service 仍会回退到 `area`

这说明：

1. 代码首轮收口已经做了
2. 但数据库不补字段，模块永远停留在兼容态
3. 只有把旧表补成真实 `tenant_code` 模型，后续才能继续削掉 `area` fallback

---

## 3. 执行前必须确认的 4 件事

### 3.1 表结构现状

先确认目标库里的 `evaluation_points` 目前到底有没有：

1. `tenant_code`
2. `tenant_name`
3. `evaluation_point_groups_id`
4. `evaluation_point_groups_pid`

预检脚本已经包含表结构查询。

### 3.2 `area` 值分布

必须先看真实分布，不要假设只有：

1. `梅州`
2. `公共`
3. `省级`
4. `default`

否则容易在历史脏值上翻车。

### 3.3 无法映射租户的残留

需要先找出：

1. 别名表映射不到
2. 租户名映射不到
3. 也不属于 `PUBLIC / PROVINCIAL` 兼容集合

这些记录不能在执行前忽略，否则执行后仍会留下空 `tenant_code`。

### 3.4 `code` 唯一性现状

这点非常关键。

当前后端 [evaluationPointServiceImpl.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/services/impl/evaluationPointServiceImpl.py) 里的 `_ensure_code_unique()` 仍是：

1. 按全局 `LOWER(code)` 查重
2. 不是按 `tenant_code + code` 查重

所以本轮数据库补列后：

1. 不能立刻把“编码唯一性”切成租户内唯一
2. 只能先做预检，确认是否存在未来会影响规则切换的跨租户重复编码

---

## 4. 建议执行顺序

### 第一步：跑预检 SQL

执行：

```sql
\i scripts/创建sql/precheck_evaluation_points_tenant_cleanup.sql
```

重点看 5 类输出：

1. `area` 分布
2. 无法映射租户的残留清单
3. 共享域残留统计
4. alias / tenant_name 冲突
5. 编码重复情况

### 第二步：人工确认预检结果

至少确认：

1. 是否存在无法映射租户的记录
2. 是否存在 alias 映射冲突
3. 是否存在 tenant_name 映射冲突
4. 是否存在需要特殊处理的共享域值

如果这一步没确认，不建议直接执行正式脚本。

### 第三步：执行正式脚本

执行：

```sql
\i scripts/创建sql/schema_evaluation_points_tenant_cleanup.sql
```

本脚本会：

1. 补 `tenant_code / tenant_name`
2. 建 3 个基础索引
3. 确保 `PUBLIC / PROVINCIAL` 与关键 alias 存在
4. 对历史 `area` 做首轮回填

### 第四步：执行后验收

执行完以后，至少重新确认：

1. `tenant_code` 空值数量
2. `tenant_name` 空值数量
3. `PUBLIC / PROVINCIAL` 记录数
4. 无法映射残留是否归零或是否仅剩人工待处理项

---

## 5. 预检 SQL 已覆盖的风险点

当前预检脚本已经覆盖：

1. 当前表结构确认
2. 总记录数与缺失字段数
3. `area` 分布统计
4. 无法映射租户的记录清单
5. `公共 / 省级 / 省局 / default / 空值` 残留统计
6. `sys_tenants.tenant_name` 冲突预检
7. `sys_tenant_aliases.alias_value` 冲突预检
8. `code` 全局重复预检
9. “如果以后改成租户内唯一”时的跨租户重复预检

---

## 6. 执行后验收标准

### 6.1 数据层

至少满足：

1. `evaluation_points.tenant_code` 已存在
2. `evaluation_points.tenant_name` 已存在
3. 大部分历史数据已具备可解析 `tenant_code`
4. `PUBLIC / PROVINCIAL` 共享域记录能稳定统计

### 6.2 服务层联动

执行完数据库后，下一步就应马上联调：

1. 列表查询
2. 详情查询
3. 创建评查点
4. 更新评查点
5. 删除评查点

目标是确认：

1. 新数据会真实落 `tenant_code / tenant_name`
2. 旧数据不会因为回填而突然查不到
3. 共享域查询开始优先命中标准编码

### 6.3 规则约束提醒

当前不要误判为“补完字段就能立刻做按租户唯一编码”。

因为当前后端仍是全局校验 `code` 唯一。

所以本轮数据库执行后的正确状态是：

1. 评查点归属边界先 tenant 化
2. 编码唯一性策略保持原行为不变
3. 后续若要改成“租户内唯一”，必须单独开一轮设计和回归

---

## 7. 本轮结论

`P0` 当前最合理的收口方式不是直接继续改 service，而是：

1. 先把旧表补成真实 tenant 字段模型
2. 再联调接口
3. 再削减 service 中最厚的 `area` 兼容层

这是目前最小、最稳、最容易审计的推进顺序。
