# 需求文档:助教废除(Abolish)全链路清理 ## 简介 上游 SaaS 系统提供了一个独立的"助教废除记录"API(`/AssistantPerformance/GetAbolitionAssistant`), ETL 系统为此建立了完整的 ODS → DWD → DWS 数据链路。但经排查发现: 1. **废除表 `dwd_assistant_trash_event` 无法与服务记录表 `dwd_assistant_service_log` 做 1:1 关联**——废除表没有 `assistant_service_id` 外键,两个 ID 不同源。 2. **DWS 层已改用 `dwd_assistant_service_log_ex.is_trash` 字段**(来自 `assistant_service_records` API)直接判断服务是否被废除,不再依赖废除表做跨表匹配。 3. 废除表的 `_extract_trash_records` 和 `_build_trash_index` 虽然仍被调用,但 `trash_index` 实际上不再参与废除判断逻辑(仅"备查"),属于死代码。 4. `trashed_seconds` / `trashed_count` 等 DWS 字段的数据来源已从废除表切换为服务记录自身的 `income_seconds`,废除表数据不再被消费。 因此,整条 abolish 独立链路(API 抓取 → ODS 表 → DWD 表 → DWS 引用)可以安全移除, 同时保留 `assistant_service_records` 中已有的 `is_trash` / `trash_reason` / `trash_applicant_*` 字段作为废除判断的唯一数据源。 ## 术语表 - **ETL_System**:飞球 ETL Connector(`apps/etl/connectors/feiqiu/`) - **ODS_Layer**:原始数据层(`ods` schema),存储从上游 API 抓取的原始记录 - **DWD_Layer**:明细数据层(`dwd` schema),存储清洗后的事实表和维度表 - **DWS_Layer**:汇总数据层(`dws` schema),存储按业务粒度聚合的汇总表 - **Abolish_Chain**:助教废除独立链路,包括 `ODS_ASSISTANT_ABOLISH` 任务、`ods.assistant_cancellation_records` 表、`dwd.dwd_assistant_trash_event` / `_ex` 表,以及 DWS 层中引用这些表的代码 - **Service_Trash_Fields**:`assistant_service_records` API 中自带的废除标记字段(`is_trash`、`trash_reason`、`trash_applicant_id`、`trash_applicant_name`),已映射到 `dwd_assistant_service_log_ex` 表 - **FACT_MAPPINGS**:`dwd_load_task.py` 中定义的 ODS → DWD 字段映射字典 - **Task_Registry**:`orchestration/task_registry.py` 中的任务注册表 ## 需求 ### 需求 1:移除 ODS 层废除任务 **用户故事:** 作为 ETL 维护者,我希望移除不再使用的 ODS 抓取任务,以减少无效 API 调用和维护负担。 #### 验收标准 1. WHEN ETL_System 执行调度时,THE Task_Registry SHALL 不包含 `ODS_ASSISTANT_ABOLISH` 任务注册 2. WHEN ETL_System 加载 ODS 任务定义时,THE ETL_System SHALL 不包含 `OdsAssistantAbolishTask` 的 `OdsTaskSpec` 定义 3. WHEN ETL_System 构建默认执行序列时,THE ETL_System SHALL 不包含 `ODS_ASSISTANT_ABOLISH` 任务代码 ### 需求 2:移除 DWD 层废除表映射 **用户故事:** 作为 ETL 维护者,我希望移除废除表的 FACT_MAPPINGS 和 DWD 加载配置,以消除死代码。 #### 验收标准 1. WHEN DWD_Layer 执行装载时,THE FACT_MAPPINGS SHALL 不包含 `dwd.dwd_assistant_trash_event` 的映射条目 2. WHEN DWD_Layer 执行装载时,THE FACT_MAPPINGS SHALL 不包含 `dwd.dwd_assistant_trash_event_ex` 的映射条目 3. WHEN DWD_Layer 构建 ODS→DWD 表映射时,THE ETL_System SHALL 不包含 `dwd.dwd_assistant_trash_event` 到 `ods.assistant_cancellation_records` 的映射关系 4. WHEN DWD_Layer 构建 ODS→DWD 表映射时,THE ETL_System SHALL 不包含 `dwd.dwd_assistant_trash_event_ex` 到 `ods.assistant_cancellation_records` 的映射关系 ### 需求 3:清理 DWS 层废除表引用 **用户故事:** 作为 ETL 维护者,我希望移除 DWS 任务中对废除表的查询和索引构建代码,以消除死代码路径。 #### 验收标准 1. WHEN DWS_Layer 执行 `DWS_ASSISTANT_DAILY` 任务时,THE AssistantDailyTask SHALL 不调用 `_extract_trash_records` 方法 2. WHEN DWS_Layer 执行 `DWS_ASSISTANT_DAILY` 任务时,THE AssistantDailyTask SHALL 不调用 `_build_trash_index` 方法 3. WHEN DWS_Layer 执行 `DWS_ASSISTANT_DAILY` 任务时,THE AssistantDailyTask SHALL 不向 `_aggregate_by_assistant_date` 传递 `trash_index` 参数 4. WHEN DWS_Layer 聚合服务记录时,THE AssistantDailyTask SHALL 仅通过 `is_trash` 字段(来自 `dwd_assistant_service_log_ex` JOIN)判断服务是否被废除 ### 需求 4:清理 DWD 验证器配置 **用户故事:** 作为 ETL 维护者,我希望移除验证器中对废除表的引用,以避免验证器尝试校验已不存在的表。 #### 验收标准 1. WHEN DWD_Layer 执行数据验证时,THE DwdVerifier SHALL 不包含 `dwd_assistant_trash_event` 的 ID 映射配置 2. WHEN DWD_Layer 执行数据验证时,THE DwdVerifier SHALL 不包含 `dwd_assistant_trash_event_ex` 的 ID 映射配置 3. WHEN DWD_Layer 执行数据验证时,THE DwdVerifier SHALL 不包含 `dwd_assistant_trash_event` 的时间字段映射配置 4. WHEN DWD_Layer 执行数据验证时,THE DwdVerifier SHALL 不包含 `dwd_assistant_trash_event_ex` 的时间字段映射配置 ### 需求 5:创建数据库迁移脚本 **用户故事:** 作为数据库管理员,我希望通过迁移脚本安全地移除废除相关的数据库对象,以保持 schema 整洁。 #### 验收标准 1. WHEN 迁移脚本执行时,THE 迁移脚本 SHALL 删除 `dwd.dwd_assistant_trash_event` 表 2. WHEN 迁移脚本执行时,THE 迁移脚本 SHALL 删除 `dwd.dwd_assistant_trash_event_ex` 表 3. WHEN 迁移脚本执行时,THE 迁移脚本 SHALL 删除 `ods.assistant_cancellation_records` 表 4. WHEN 迁移脚本执行时,THE 迁移脚本 SHALL 在 DROP 前使用 `IF EXISTS` 防止重复执行报错 5. WHEN 迁移脚本执行时,THE 迁移脚本 SHALL 包含注释说明移除原因 ### 需求 6:同步更新 DDL 文档 **用户故事:** 作为 ETL 维护者,我希望 DDL schema 文件与实际数据库结构保持一致。 #### 验收标准 1. WHEN DDL 文件更新后,THE `db/etl_feiqiu/schemas/dwd.sql` SHALL 不包含 `dwd_assistant_trash_event` 表的 CREATE TABLE 语句 2. WHEN DDL 文件更新后,THE `db/etl_feiqiu/schemas/dwd.sql` SHALL 不包含 `dwd_assistant_trash_event_ex` 表的 CREATE TABLE 语句 3. WHEN DDL 文件更新后,THE `db/etl_feiqiu/schemas/ods.sql` SHALL 不包含 `assistant_cancellation_records` 表的 CREATE TABLE 语句 4. WHEN DDL 文件更新后,THE `db/etl_feiqiu/schemas/schema_dwd_doc.sql` SHALL 不包含 `dwd_assistant_trash_event` 相关的 CREATE TABLE 和 COMMENT 语句 5. WHEN DDL 文件更新后,THE `db/etl_feiqiu/schemas/schema_ODS_doc.sql` SHALL 不包含 `assistant_cancellation_records` 相关的 CREATE TABLE 和 COMMENT 语句 6. WHEN DDL 文件更新后,THE `db/etl_feiqiu/schemas/dws.sql` 中 `dws_assistant_daily_detail` 的注释 SHALL 不再引用 `dwd_assistant_trash_event` 作为数据来源 7. WHEN DDL 文件更新后,THE `db/etl_feiqiu/schemas/schema_dws.sql` 中 `dws_assistant_daily_detail` 的注释 SHALL 不再引用 `dwd_assistant_trash_event` 作为数据来源 ### 需求 7:更新属性测试 **用户故事:** 作为开发者,我希望属性测试反映清理后的实际状态,以确保测试的准确性。 #### 验收标准 1. WHEN 属性测试执行时,THE `test_property_1_fact_mappings.py` SHALL 不包含 `dwd.dwd_assistant_trash_event` 在 A 类表列表中 2. WHEN 属性测试执行时,THE `test_property_1_fact_mappings.py` SHALL 不包含 `assistant_cancellation_records → dwd_assistant_trash_event` 的映射期望(`_REQ3_EXPECTED`) 3. WHEN 属性测试执行后,THE 所有现有属性测试 SHALL 通过(无回归) ### 需求 8:更新运维脚本引用 **用户故事:** 作为运维人员,我希望运维脚本中不再引用已移除的表和任务,以避免脚本执行错误。 #### 验收标准 1. WHEN 运维脚本加载 ODS 任务映射时,THE 脚本 SHALL 不包含 `ODS_ASSISTANT_ABOLISH` 到 `assistant_cancellation_records` 的映射 2. WHEN 运维脚本加载 DWD 表映射时,THE 脚本 SHALL 不包含 `dwd.dwd_assistant_trash_event` 到 `ods.assistant_cancellation_records` 的映射 3. WHEN 运维脚本列举 ODS 表时,THE 脚本 SHALL 不包含 `assistant_cancellation_records` 4. WHEN 运维脚本列举 DWD 表时,THE 脚本 SHALL 不包含 `dwd_assistant_trash_event` 和 `dwd_assistant_trash_event_ex` ### 需求 9:保留 Service_Trash_Fields 不受影响 **用户故事:** 作为 ETL 维护者,我希望确认清理操作不会影响 `assistant_service_records` 中已有的废除标记字段。 #### 验收标准 1. WHILE 清理操作执行期间,THE `dwd_assistant_service_log_ex` 表 SHALL 保留 `is_trash`、`trash_reason`、`trash_applicant_id`、`trash_applicant_name` 字段不变 2. WHILE 清理操作执行期间,THE `ods.assistant_service_records` 表 SHALL 保留 `is_trash`、`trash_reason`、`trash_applicant_id`、`trash_applicant_name` 字段不变 3. WHILE 清理操作执行期间,THE AssistantDailyTask 中通过 `is_trash` 判断废除的逻辑 SHALL 保持正常工作