# BD 手册 — auth.tenant_admins 新增 deleted_at 软删除字段

## 变更日期
2026-03-22

## 变更说明

### 新增字段
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `deleted_at` | `TIMESTAMPTZ` | `NULL` | 软删除时间戳：NULL=正常，非 NULL=已删除 |

### 新增索引
| 索引名 | 说明 |
|--------|------|
| `idx_tenant_admins_active_not_deleted` | 部分索引 `(is_active) WHERE deleted_at IS NULL`，加速列表和登录查询 |

### 语义变更
- 删除与禁用分离：`is_active` 仅控制启用/禁用，`deleted_at` 控制软删除
- DELETE 接口改为设置 `deleted_at = NOW()`，不再检查 `is_active` 状态
- 所有查询（列表、登录、编辑、重置密码）默认过滤 `deleted_at IS NULL`
- 用户名唯一性校验仅在未删除记录中生效

## 兼容性影响

| 模块 | 影响 |
|------|------|
| 后端 DELETE 接口 | 改为设置 `deleted_at`，不再返回 409（已禁用） |
| 后端列表接口 | 新增 `deleted_at IS NULL` 过滤，已删除记录不再出现 |
| 租户登录接口 | 新增 `deleted_at IS NULL` 过滤，已删除账号无法登录 |
| 编辑/重置密码接口 | WHERE 条件加 `deleted_at IS NULL`，已删除记录返回 404 |
| 前端 | 无需改动，删除按钮已存在 |
| ETL | 无影响（不涉及 tenant_admins 表） |

## 回滚策略
```sql
DROP INDEX IF EXISTS auth.idx_tenant_admins_active_not_deleted;
ALTER TABLE auth.tenant_admins DROP COLUMN IF EXISTS deleted_at;
```
回滚后需同步还原后端代码中的 DELETE 接口逻辑。

## 验证 SQL
```sql
-- 1) 字段存在性
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema = 'auth' AND table_name = 'tenant_admins' AND column_name = 'deleted_at';
-- 预期：1 行

-- 2) 索引存在性
SELECT indexname FROM pg_indexes
WHERE schemaname = 'auth' AND tablename = 'tenant_admins'
  AND indexname = 'idx_tenant_admins_active_not_deleted';
-- 预期：1 行

-- 3) 现有数据不受影响
SELECT COUNT(*) FROM auth.tenant_admins WHERE deleted_at IS NOT NULL;
-- 预期：0
```
