Files
Neo-ZQYY/docs/audit/changes/2026-03-26__net-income-calibration-all-pages.md
Neo 14a12342b5 chore(audit): 补追 96 份未入仓审计孤本 — 覆盖 2026-02-26 ~ 2026-04-08
这些审计记录原本堆积在 docs/audit/changes/changes/ 嵌套误产物目录下(由开发机迁移
79d3c2e 前后的不明批量操作产生)。由于同期 .gitignore 屏蔽了 docs/audit/ 全目录,
它们从未入过 git 任何分支 history。删除即永久丢失。

按 docs/specs/audit-gap-recovery/tasks.md 阶段 1 执行,将全部 96 份 D 类孤本
(主目录无同名、git history 亦无记录)复制到 docs/audit/changes/ 主目录入仓。

涵盖主题: P1-P18 全栈集成 / 多模块累积变更 / ETL bug 修复 / 业务日切 /
   召回与任务引擎改造 / 租户管理与审批 / 董事会财务 / 客户与助教详情 /
   DDL 基线合并 / Kiro 到 Claude Code 迁移

阶段 2(B 类内容漂移 1 份)和阶段 4(嵌套目录删除)独立推进。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 06:35:42 +08:00

4.7 KiB
Raw Blame History

变更审计记录:到手金额口径修复(全小程序统一)

字段
日期 2026-03-26 02:48:42
Prompt-ID P20260325-090826
Session-ID 0ef5e906
Session 路径 docs/audit/session_logs/2026-03/25/24_e10246a9_090825

操作摘要

修复小程序全场景"到手金额"计算口径。原实现使用 ledger_amount(毛收入,未扣抽成),标注"到手"但实际不是到手。修复后统一为:hours × net_rate,其中 net_rate 从 DWS 层 v_dws_assistant_salary_calc 获取抽成参数计算:

  • 基础课:base_course_price - base_deduction
  • 激励课/超休课:bonus_course_price × (1 - bonus_deduction_ratio)

验证:小燕×轩哥 3月10日 → 毛收入 ¥154.94 → 到手 ¥134.001.117h × 120

影响范围

文件 函数/方法 变更类型
apps/backend/app/services/fdw_queries.py get_service_records() 修改
apps/backend/app/services/fdw_queries.py get_service_records_for_task() 修改
apps/backend/app/services/fdw_queries.py get_coach_service_records() 修改
apps/backend/app/services/fdw_queries.py get_service_records_90days() 修改
apps/backend/app/services/coach_service.py get_coach_detail() 修改

技术方案

SQL 层fdw_queries.py 四个函数统一改法)

每个查询新增 LEFT JOIN app.v_dws_assistant_salary_calc sc,按 assistant_id + salary_monthdate_trunc('month', create_time)::date)关联。income 字段从原来的 sl.ledger_amount 改为 CASE 表达式:

CASE
    WHEN sl.skill_name ILIKE '%%激励%%' OR sl.skill_name ILIKE '%%超休%%'
    THEN (sl.income_seconds / 3600.0) * COALESCE(sc.bonus_course_price * (1 - sc.bonus_deduction_ratio), 0)
    ELSE (sl.income_seconds / 3600.0) * COALESCE(sc.base_course_price - sc.base_deduction, 0)
END AS income

Service 层coach_service.py

get_coach_detail()monthly_salary 从原来的 gross_salary 改为 DWS 层已扣抽成的四项之和:

"monthly_salary": (
    salary_this.get("assistant_pd_money_total", 0.0)
    + salary_this.get("assistant_cx_money_total", 0.0)
    + salary_this.get("bonus_money", 0.0)
    + salary_this.get("room_income", 0.0)
)

风险评估

  • salary_calc 无当月数据时 COALESCE 回退 0到手=0但这种情况说明 DWS 未跑完,属于数据质量问题而非代码 bug
  • LEFT JOIN 不会导致行膨胀salary_calc 按 assistant_id + salary_month 唯一)
  • get_service_records_90days() 的 SUM 聚合也已同步改为到手口径

本次对话文件变更

删除的文件

  • docs/audit/session_logs/2026-03/25/19_e69c9fee_040048/main_01_c847b139.md

改动注解

apps/backend/app/services/fdw_queries.py

  • 变更类型:修改
  • 原始原因:服务记录列表和绩效页顶部卡片使用 ledger_amount(毛收入,未扣抽成),标注"到手"但实际不是到手金额。用户反馈 60 天内服务记录列表中到手金额计算不对。
  • 思路分析:在 SQL 层通过 LEFT JOIN v_dws_assistant_salary_calc 获取每月的课程定价和抽成参数,用 CASE 表达式区分基础课和激励课/超休课两种费率计算方式。选择 LEFT JOIN 而非 INNER JOIN 确保 salary_calc 缺失时不丢失记录COALESCE 回退 0。四个查询函数get_service_recordsget_service_records_for_taskget_coach_service_recordsget_service_records_90days)统一改法,保证全小程序口径一致。
  • 修改结果:所有服务记录列表页面的 income 字段现在返回真正的到手金额。影响页面绩效页服务记录、任务详情页服务记录、助教详情页服务记录、常客统计90天聚合

apps/backend/app/services/coach_service.py

  • 变更类型:修改
  • 原始原因:绩效页顶部卡片的 monthly_salary 使用 gross_salary(毛收入),与行级到手金额口径不一致。
  • 思路分析DWS 层 salary_calc 已经提供了扣抽成后的分项金额(assistant_pd_money_totalassistant_cx_money_totalbonus_moneyroom_income),直接求和即为到手总额,无需重复计算抽成逻辑。
  • 修改结果:绩效页顶部卡片的月收入数字与行级服务记录的到手金额口径统一。

apps/admin-web/src/__tests__/tabUrlSync.property.test.tsx

  • 变更类型:修改(非高风险,简要注解)
  • 与本次到手金额修复无关,属于同一 commit 范围内的其他变更。

DDL/迁移检查

  • 无新增迁移 SQL
  • DDL 基线状态:未更新(⚠️ DDL 基线待合并)

合规检查

  • api_changed: false — 接口签名未变,仅返回值语义修正
  • openapi_spec_stale: false — 无需重新导出