🤖 每日自动备份 - 2026-06-23 08:00:01

This commit is contained in:
小溪 2026-06-23 08:00:01 +08:00
parent ecd90ae9f9
commit 54b4a9ce99
2 changed files with 327 additions and 21 deletions

View File

@ -1,6 +1,6 @@
{ {
"version": 1, "version": 1,
"updatedAt": "2026-06-19T02:14:18.761Z", "updatedAt": "2026-06-22T07:01:32.169Z",
"entries": { "entries": {
"memory:memory/2026-05-06.md:1:20": { "memory:memory/2026-05-06.md:1:20": {
"key": "memory:memory/2026-05-06.md:1:20", "key": "memory:memory/2026-05-06.md:1:20",
@ -433,18 +433,20 @@
"endLine": 39, "endLine": 39,
"source": "memory", "source": "memory",
"snippet": "- 口径 = MEMORY.md 中所有计算逻辑、数据口径、指标定义、字段映射、判定条件、统计方法 - 唯一审批人:李承龙 - 禁止根据群聊讨论直接修改口径 - 禁止自行推断或\"修正\"已有口径 - 正确流程:发现问题 → 向李承龙确认 → 明确同意 → 方可修改 - 说明:数据查询本身按 USER.md 权限规则执行,不需要审批;本规则仅约束 MEMORY.md 中口径/计算逻辑的变更 ## 渠道归类补充 [王虹茗 2026-06-01 22:38] - 抖音精选 → 直购渠道 - 万物newmedia-dianpu-wwxx-0-0→ 达人渠道 - 合作活动是班主任 → 直购渠道 - ⚠️ 待李承龙确认后更新到 MEMORY.md 渠道映射规则", "snippet": "- 口径 = MEMORY.md 中所有计算逻辑、数据口径、指标定义、字段映射、判定条件、统计方法 - 唯一审批人:李承龙 - 禁止根据群聊讨论直接修改口径 - 禁止自行推断或\"修正\"已有口径 - 正确流程:发现问题 → 向李承龙确认 → 明确同意 → 方可修改 - 说明:数据查询本身按 USER.md 权限规则执行,不需要审批;本规则仅约束 MEMORY.md 中口径/计算逻辑的变更 ## 渠道归类补充 [王虹茗 2026-06-01 22:38] - 抖音精选 → 直购渠道 - 万物newmedia-dianpu-wwxx-0-0→ 达人渠道 - 合作活动是班主任 → 直购渠道 - ⚠️ 待李承龙确认后更新到 MEMORY.md 渠道映射规则",
"recallCount": 1, "recallCount": 2,
"dailyCount": 0, "dailyCount": 0,
"groundedCount": 0, "groundedCount": 0,
"totalScore": 1, "totalScore": 2,
"maxScore": 1, "maxScore": 1,
"firstRecalledAt": "2026-06-02T03:39:49.570Z", "firstRecalledAt": "2026-06-02T03:39:49.570Z",
"lastRecalledAt": "2026-06-02T03:39:49.570Z", "lastRecalledAt": "2026-06-22T07:01:26.682Z",
"queryHashes": [ "queryHashes": [
"de7e9eb98961" "de7e9eb98961",
"0100fb44019e"
], ],
"recallDays": [ "recallDays": [
"2026-06-02" "2026-06-02",
"2026-06-22"
], ],
"conceptTags": [ "conceptTags": [
"memory.md", "memory.md",
@ -805,23 +807,25 @@
"endLine": 38, "endLine": 38,
"source": "memory", "source": "memory",
"snippet": "# 2026-06-15 工作日志 ## 陈逸鸫 - 订单口径变更:停直购 **来源:** 陈逸鸫群聊「数据更新V2」 **变更内容:** 1. 以后不管直购单,只看小红书销转,直购 GMV 不再进销转对账 2. full_refresh 不再 merge 直购进订单汇总 3. 直购表1sosYE可删除需人工在飞书操作API 不支持删 sheet 4. 仍支持按手机查 keyfrom/GSV/退款(不定销售归属) **脚本修改:** - `scripts/refresh_order_summary.py`:去掉 Step 1.5 读取直购表逻辑,不再合并直购行 - `scripts/full_refresh_sales.py`:不涉及直购,无需改动 - `scripts/refresh_direct_sheet.py`:保留不动(如后续仍需独立查直购数据) ## 陈逸鸫 - full_refresh 执行 - 时间2026-06-15 08:24-08:26 - 销售三表:吴迪 697 / 小龙 1198 / 成都 2203 - 有效 user_id2009 - 订单汇总383 条(不含直购) - 直购表75 条已刷新 - 订单汇总合并后461 条(含直购,这是口径变更前的最后一次含直购的合并) ## 陈逸鸫 - 线索表字段调整2026-06-15 **来源:** 陈逸鸫(群聊「小红书数据需求」) **线索表销售三表新列结构A~Z** | 列 | 字段名 | 脚本填写 | |----|--------|---------|", "snippet": "# 2026-06-15 工作日志 ## 陈逸鸫 - 订单口径变更:停直购 **来源:** 陈逸鸫群聊「数据更新V2」 **变更内容:** 1. 以后不管直购单,只看小红书销转,直购 GMV 不再进销转对账 2. full_refresh 不再 merge 直购进订单汇总 3. 直购表1sosYE可删除需人工在飞书操作API 不支持删 sheet 4. 仍支持按手机查 keyfrom/GSV/退款(不定销售归属) **脚本修改:** - `scripts/refresh_order_summary.py`:去掉 Step 1.5 读取直购表逻辑,不再合并直购行 - `scripts/full_refresh_sales.py`:不涉及直购,无需改动 - `scripts/refresh_direct_sheet.py`:保留不动(如后续仍需独立查直购数据) ## 陈逸鸫 - full_refresh 执行 - 时间2026-06-15 08:24-08:26 - 销售三表:吴迪 697 / 小龙 1198 / 成都 2203 - 有效 user_id2009 - 订单汇总383 条(不含直购) - 直购表75 条已刷新 - 订单汇总合并后461 条(含直购,这是口径变更前的最后一次含直购的合并) ## 陈逸鸫 - 线索表字段调整2026-06-15 **来源:** 陈逸鸫(群聊「小红书数据需求」) **线索表销售三表新列结构A~Z** | 列 | 字段名 | 脚本填写 | |----|--------|---------|",
"recallCount": 5, "recallCount": 6,
"dailyCount": 0, "dailyCount": 0,
"groundedCount": 0, "groundedCount": 0,
"totalScore": 5, "totalScore": 6,
"maxScore": 1, "maxScore": 1,
"firstRecalledAt": "2026-06-16T00:11:00.366Z", "firstRecalledAt": "2026-06-16T00:11:00.366Z",
"lastRecalledAt": "2026-06-19T02:14:18.761Z", "lastRecalledAt": "2026-06-22T02:21:46.229Z",
"queryHashes": [ "queryHashes": [
"15e68c5404aa", "15e68c5404aa",
"d01c75870930", "d01c75870930",
"247976469363", "247976469363",
"13b782b49d74", "13b782b49d74",
"503e4d1c4721" "503e4d1c4721",
"7a6770cbdabe"
], ],
"recallDays": [ "recallDays": [
"2026-06-16", "2026-06-16",
"2026-06-19" "2026-06-19",
"2026-06-22"
], ],
"conceptTags": [ "conceptTags": [
"full-refresh", "full-refresh",
@ -875,19 +879,21 @@
"endLine": 25, "endLine": 25,
"source": "memory", "source": "memory",
"snippet": "# 2026-06-16 工作日志 ## 李承龙 - 强化审批规则12:42 **背景:** 李承龙发现 `full_refresh_sales.py` 在今天上午被修改08:55且 `sales_leads_full_refresh.py` 在群聊中被陈逸鸫的上下文触发修改。 **李承龙要求:** 1. 所有 workspace 脚本、skill、定时任务、轮询、MEMORY.md 的创建和修改,仅李承龙、李若松、张昆鹏三人有权下达指令 2. 每次修改必须记录时间、内容、来源人 3. 不允许再在任何对话/群聊中看到在别人指令下修改或创建上述内容 **已执行:** 1. AGENTS.md 规则已强化:新增 MEMORY.md 纳入审批范围、新增\"禁止顺手修改\"条款、新增修改后必须登记的要求 2. MEMORY.md 规则已同步强化 3. SKILL_REGISTRY.md 已补登记: - `full_refresh_sales.py`(创建于 2026-06-02李承龙 - `sales_leads_full_refresh.py`(创建于 2026-06-08李承龙 - `refresh_order_summary.py`(创建于约 2026-06李承龙 4. 变更记录已追加到各条目 ## 李承龙 - 增加操作前强制拦截检查14:06 **李承龙要求:** 在 AGENTS.md 和 MEMORY.md 的审批规则前增加操作前强制检查清单。 **已执行:**", "snippet": "# 2026-06-16 工作日志 ## 李承龙 - 强化审批规则12:42 **背景:** 李承龙发现 `full_refresh_sales.py` 在今天上午被修改08:55且 `sales_leads_full_refresh.py` 在群聊中被陈逸鸫的上下文触发修改。 **李承龙要求:** 1. 所有 workspace 脚本、skill、定时任务、轮询、MEMORY.md 的创建和修改,仅李承龙、李若松、张昆鹏三人有权下达指令 2. 每次修改必须记录时间、内容、来源人 3. 不允许再在任何对话/群聊中看到在别人指令下修改或创建上述内容 **已执行:** 1. AGENTS.md 规则已强化:新增 MEMORY.md 纳入审批范围、新增\"禁止顺手修改\"条款、新增修改后必须登记的要求 2. MEMORY.md 规则已同步强化 3. SKILL_REGISTRY.md 已补登记: - `full_refresh_sales.py`(创建于 2026-06-02李承龙 - `sales_leads_full_refresh.py`(创建于 2026-06-08李承龙 - `refresh_order_summary.py`(创建于约 2026-06李承龙 4. 变更记录已追加到各条目 ## 李承龙 - 增加操作前强制拦截检查14:06 **李承龙要求:** 在 AGENTS.md 和 MEMORY.md 的审批规则前增加操作前强制检查清单。 **已执行:**",
"recallCount": 2, "recallCount": 3,
"dailyCount": 0, "dailyCount": 0,
"groundedCount": 0, "groundedCount": 0,
"totalScore": 2, "totalScore": 3,
"maxScore": 1, "maxScore": 1,
"firstRecalledAt": "2026-06-19T02:13:56.194Z", "firstRecalledAt": "2026-06-19T02:13:56.194Z",
"lastRecalledAt": "2026-06-19T02:14:18.761Z", "lastRecalledAt": "2026-06-22T02:21:46.229Z",
"queryHashes": [ "queryHashes": [
"13b782b49d74", "13b782b49d74",
"503e4d1c4721" "503e4d1c4721",
"7a6770cbdabe"
], ],
"recallDays": [ "recallDays": [
"2026-06-19" "2026-06-19",
"2026-06-22"
], ],
"conceptTags": [ "conceptTags": [
"full-refresh-sales.py", "full-refresh-sales.py",
@ -907,19 +913,21 @@
"endLine": 45, "endLine": 45,
"source": "memory", "source": "memory",
"snippet": "| 2026-06-16 约11:00 | `sales_leads_full_refresh.py` | 修复日期解析 | 群聊「数据更新V2」陈逸鸫上下文 | 已登记,标记违规 | | 2026-06-15 | `refresh_order_summary.py` | 去掉直购表合并 | 群聊「数据更新V2」陈逸鸫 | 已登记 | ## 李承龙 - 销售转化渠道分类规则迁移14:14 **操作:** 1. 将 MEMORY.md 中「销售转化渠道分类规则」2026-06-15 王虹茗确认、李承龙确认)迁移到 `scripts/full_refresh_sales.py` 2. 新增 `classify_sales_channel(key_from)` 函数,将 key_from 归为四类:端内 / 销转 / 达人 / 直购 3. 从 MEMORY.md 中删除该规则段落 4. SKILL_REGISTRY.md 已追加变更记录", "snippet": "| 2026-06-16 约11:00 | `sales_leads_full_refresh.py` | 修复日期解析 | 群聊「数据更新V2」陈逸鸫上下文 | 已登记,标记违规 | | 2026-06-15 | `refresh_order_summary.py` | 去掉直购表合并 | 群聊「数据更新V2」陈逸鸫 | 已登记 | ## 李承龙 - 销售转化渠道分类规则迁移14:14 **操作:** 1. 将 MEMORY.md 中「销售转化渠道分类规则」2026-06-15 王虹茗确认、李承龙确认)迁移到 `scripts/full_refresh_sales.py` 2. 新增 `classify_sales_channel(key_from)` 函数,将 key_from 归为四类:端内 / 销转 / 达人 / 直购 3. 从 MEMORY.md 中删除该规则段落 4. SKILL_REGISTRY.md 已追加变更记录",
"recallCount": 2, "recallCount": 3,
"dailyCount": 0, "dailyCount": 0,
"groundedCount": 0, "groundedCount": 0,
"totalScore": 2, "totalScore": 3,
"maxScore": 1, "maxScore": 1,
"firstRecalledAt": "2026-06-19T02:13:56.194Z", "firstRecalledAt": "2026-06-19T02:13:56.194Z",
"lastRecalledAt": "2026-06-19T02:14:18.761Z", "lastRecalledAt": "2026-06-22T02:21:46.229Z",
"queryHashes": [ "queryHashes": [
"13b782b49d74", "13b782b49d74",
"503e4d1c4721" "503e4d1c4721",
"7a6770cbdabe"
], ],
"recallDays": [ "recallDays": [
"2026-06-19" "2026-06-19",
"2026-06-22"
], ],
"conceptTags": [ "conceptTags": [
"sales-leads-full-refresh.py", "sales-leads-full-refresh.py",
@ -931,6 +939,69 @@
"skill-registry.md", "skill-registry.md",
"修复" "修复"
] ]
},
"memory:memory/2026-05-11.md:1:30": {
"key": "memory:memory/2026-05-11.md:1:30",
"path": "memory/2026-05-11.md",
"startLine": 1,
"endLine": 30,
"source": "memory",
"snippet": "# 2026-05-11 工作日志 ## 转化率口径确认 [李承龙确认] ### 转化率(端内注册转付费转化率) - **定义:** 注册用户中在端内完成付费的比例 - **分母:** 按注册日期分组,`bi_vala_app_account.status=1` 非测试账号 - **分子(含退费):** 分母中在端内(`key_from IN ('app-active-h5-0-0', 'app-sales-bj-qhm-0')`)有支付成功订单的去重用户数 - **分子(剔除退费):** 同上,但仅剔除端内订单**全部被退费**的用户——只要用户还有任何一笔未退费的端内订单就保留(退费判定:`bi_refund_order.status=3` 且 `bi_vala_order.order_status=4` - **时间基准:** 按注册日期分组,不限制订单发生时间 - **订单时间字段:** `pay_success_date` ### 7日转化率 - 分子限制:`pay_success_date ≤ 注册日期 + 7天`(含注册当日) ### 14日转化率 - 分子限制:`pay_success_date ≤ 注册日期 + 14天`(含注册当日) ### 注意事项 - 需关联 `bi_vala_app_account` 剔除测试账号,`deleted_at IS NULL` 剔除已删除账号 - 按注册日期分组时,注册日期取 `created_at` 的日期部分 - 7日/14日/20日窗口包含注册当日 - 端内订单筛选 `order_status IN",
"recallCount": 2,
"dailyCount": 0,
"groundedCount": 0,
"totalScore": 2,
"maxScore": 1,
"firstRecalledAt": "2026-06-22T07:01:26.682Z",
"lastRecalledAt": "2026-06-22T07:01:32.169Z",
"queryHashes": [
"0100fb44019e",
"d4dd7fb095b3"
],
"recallDays": [
"2026-06-22"
],
"conceptTags": [
"bi-vala-app-account.status",
"key-from",
"app-active-h5-0-0",
"app-sales-bj-qhm-0",
"bi-refund-order.status",
"bi-vala-order.order-status",
"pay-success-date",
"bi-vala-app-account"
]
},
"memory:memory/2026-06-01.md:16:31": {
"key": "memory:memory/2026-06-01.md:16:31",
"path": "memory/2026-06-01.md",
"startLine": 16,
"endLine": 31,
"source": "memory",
"snippet": "- 同一用户可能有多条记录,只要存在任意一条即视为已加微 - 参考数据:老狼履约明细 31 人中,已加微 28 人90.3%),未加微 3 人24105, 25485, 25945 - MEMORY.md 已更新 ## 🚫 口径变更审批规则建立 [李承龙确认 2026-06-01 15:14] - **严重问题:** 之前在群聊中未经李承龙确认就修改了加微判断口径(从 stride_contact_bindings 改为 student_info存在数据口径被非授权变更的风险 - **根因:** 缺少口径变更的审批机制,小溪在群聊中接受了其他人的计算逻辑并直接写入了长期记忆 - **解决方案:** 1. MEMORY.md 新增「口径变更审批规则」章节,明确李承龙为数据口径唯一审批人 2. AGENTS.md 新增「MEMORY.md 口径变更审批」章节,作为强制执行规则 3. 规则要点: - 口径 = MEMORY.md 中所有计算逻辑、数据口径、指标定义、字段映射、判定条件、统计方法 - 唯一审批人:李承龙 - 禁止根据群聊讨论直接修改口径 - 禁止自行推断或\"修正\"已有口径 - 正确流程:发现问题 → 向李承龙确认 → 明确同意 → 方可修改",
"recallCount": 1,
"dailyCount": 0,
"groundedCount": 0,
"totalScore": 1,
"maxScore": 1,
"firstRecalledAt": "2026-06-22T07:01:26.682Z",
"lastRecalledAt": "2026-06-22T07:01:26.682Z",
"queryHashes": [
"0100fb44019e"
],
"recallDays": [
"2026-06-22"
],
"conceptTags": [
"90.3",
"memory.md",
"stride-contact-bindings",
"student-info",
"agents.md",
"同一",
"用户",
"可能"
]
} }
} }
} }

View File

@ -0,0 +1,235 @@
#!/usr/bin/env python3
"""
分析是否添加班主任微信退款率的相关性
数据源
- 加微判断vala_class.public.student_infovala_account_id 存在即已加微
- 订单数据vala_bi.bi_vala_order + bi_vala_app_account + bi_refund_order
"""
import psycopg2
import os
from collections import defaultdict
PG_HOST = "bj-postgres-16pob4sg.sql.tencentcdb.com"
PG_PORT = 28591
PG_USER = "ai_member"
PG_PASS = os.environ.get("PG_ONLINE_PASSWORD", "")
def get_conn(db):
return psycopg2.connect(host=PG_HOST, port=PG_PORT, user=PG_USER, password=PG_PASS, dbname=db)
print("=" * 70)
print("📊 是否添加班主任微信 vs 退款率 相关性分析")
print("=" * 70)
# ============================================================
# Step 1: 从 vala_class 获取所有已加微的 account_id
# ============================================================
print("\n[1/5] 获取已加班主任微信的用户列表...")
conn_class = get_conn("vala_class")
cur = conn_class.cursor()
cur.execute("""
SELECT DISTINCT vala_account_id
FROM student_info
WHERE vala_account_id IS NOT NULL
""")
wechat_accounts = {row[0] for row in cur.fetchall()}
cur.close()
conn_class.close()
print(f" 已加微用户数: {len(wechat_accounts):,}")
# ============================================================
# Step 2: 获取所有购课用户(非测试账号)
# ============================================================
print("\n[2/5] 获取购课用户及订单数据...")
conn_bi = get_conn("vala_bi")
cur = conn_bi.cursor()
# 获取所有非测试账号的购课订单
cur.execute("""
SELECT
o.account_id,
o.id AS order_id,
o.trade_no,
o.out_trade_no,
o.order_status,
o.pay_amount_int,
o.pay_success_date,
o.key_from
FROM bi_vala_order o
INNER JOIN bi_vala_app_account a ON o.account_id = a.id AND a.status = 1 AND a.deleted_at IS NULL
WHERE o.pay_success_date IS NOT NULL
AND o.order_status IN (3, 4)
""")
orders = cur.fetchall()
print(f" 购课订单数: {len(orders):,}")
# 按 account_id 分组
user_orders = defaultdict(list)
for row in orders:
user_orders[row[0]].append({
'order_id': row[1],
'trade_no': row[2],
'out_trade_no': row[3],
'order_status': row[4],
'pay_amount_int': row[5],
'pay_success_date': row[6],
'key_from': row[7]
})
buying_users = set(user_orders.keys())
print(f" 购课用户数(去重): {len(buying_users):,}")
# ============================================================
# Step 3: 获取所有退费记录
# ============================================================
print("\n[3/5] 获取退费记录...")
cur.execute("""
SELECT trade_no, out_trade_no, refund_amount, status
FROM bi_refund_order
WHERE status = 3
""")
refund_rows = cur.fetchall()
print(f" 退费记录数: {len(refund_rows):,}")
# 构建退费记录列表:每条记录 (trade_no, out_trade_no, amount_fen)
refund_records = []
for row in refund_rows:
trade_no, out_trade_no, amount, status = row
amount_fen = int(float(amount) * 100) if amount else 0
refund_records.append((trade_no, out_trade_no, amount_fen))
cur.close()
conn_bi.close()
# ============================================================
# Step 4: 判断每笔订单是否退费
# ============================================================
print("\n[4/5] 计算退费情况...")
def get_refund_info(order):
"""判断订单是否退费,返回 (is_refunded, total_refund_amount_fen)"""
# order_status=4 → 直接判定退费
if order['order_status'] == 4:
# 计算退费金额:匹配所有退费记录
total = 0
tn = order['trade_no']
otn = order['out_trade_no']
seen = set() # 避免同一笔退费记录重复计算
for i, (r_tn, r_otn, r_amt) in enumerate(refund_records):
if (r_tn and r_tn == tn) or (r_otn and r_otn == otn):
if i not in seen:
seen.add(i)
total += r_amt
return True, total
# order_status=3 → 需在退费表中存在 status=3 的记录
if order['order_status'] == 3:
total = 0
tn = order['trade_no']
otn = order['out_trade_no']
seen = set()
for i, (r_tn, r_otn, r_amt) in enumerate(refund_records):
if (r_tn and r_tn == tn) or (r_otn and r_otn == otn):
if i not in seen:
seen.add(i)
total += r_amt
if total > 0:
return True, total
return False, 0
# 按用户统计
wechat_stats = {
'users': set(),
'total_orders': 0,
'refunded_orders': 0,
'total_gmv': 0,
'total_refund_amount': 0,
}
no_wechat_stats = {
'users': set(),
'total_orders': 0,
'refunded_orders': 0,
'total_gmv': 0,
'total_refund_amount': 0,
}
for account_id, order_list in user_orders.items():
has_wechat = account_id in wechat_accounts
target = wechat_stats if has_wechat else no_wechat_stats
target['users'].add(account_id)
for order in order_list:
target['total_orders'] += 1
target['total_gmv'] += order['pay_amount_int']
is_ref, refund_amt = get_refund_info(order)
if is_ref:
target['refunded_orders'] += 1
target['total_refund_amount'] += refund_amt
# ============================================================
# Step 5: 输出结果
# ============================================================
print("\n[5/5] 输出分析结果...")
print("\n" + "=" * 70)
print("📊 分析结果")
print("=" * 70)
def print_stats(label, stats):
users = len(stats['users'])
orders = stats['total_orders']
refunded = stats['refunded_orders']
gmv = stats['total_gmv'] / 100
refund_amt = stats['total_refund_amount'] / 100
gsv = gmv - refund_amt
refund_rate = (refunded / orders * 100) if orders > 0 else 0
refund_amount_rate = (refund_amt / gmv * 100) if gmv > 0 else 0
avg_orders_per_user = orders / users if users > 0 else 0
print(f"\n{'' * 50}")
print(f" {label}")
print(f"{'' * 50}")
print(f" 购课用户数: {users:>8,}")
print(f" 订单总数: {orders:>8,}")
print(f" 人均订单数: {avg_orders_per_user:>8.1f} 单/人")
print(f" 退费订单数: {refunded:>8,}")
print(f" 退费率(按订单): {refund_rate:>8.1f}%")
print(f" GMV: {gmv:>10,.0f}")
print(f" 退费金额: {refund_amt:>10,.0f}")
print(f" GSV: {gsv:>10,.0f}")
print(f" 退费金额占比: {refund_amount_rate:>8.1f}%")
return {
'users': users, 'orders': orders, 'refunded': refunded,
'refund_rate': refund_rate, 'gmv': gmv, 'refund_amt': refund_amt,
'gsv': gsv, 'refund_amount_rate': refund_amount_rate
}
w = print_stats("✅ 已加班主任微信", wechat_stats)
n = print_stats("❌ 未加班主任微信", no_wechat_stats)
# 对比
print(f"\n{'=' * 70}")
print("📊 对比分析")
print(f"{'=' * 70}")
print(f" 退费率差异: 已加微 {w['refund_rate']:.1f}% vs 未加微 {n['refund_rate']:.1f}%")
diff = w['refund_rate'] - n['refund_rate']
print(f" 退费率差值: {diff:+.1f} 个百分点")
if n['refund_rate'] > 0:
ratio = w['refund_rate'] / n['refund_rate']
print(f" 退费率比值: 已加微是未加微的 {ratio:.2f}")
print(f"\n 退费金额占比差异: 已加微 {w['refund_amount_rate']:.1f}% vs 未加微 {n['refund_amount_rate']:.1f}%")
# 用户维度退费率(有退费的用户 / 总用户)
wechat_refund_users = sum(1 for uid in wechat_stats['users']
if any(get_refund_info(o)[0] for o in user_orders[uid]))
no_wechat_refund_users = sum(1 for uid in no_wechat_stats['users']
if any(get_refund_info(o)[0] for o in user_orders[uid]))
print(f"\n 用户维度退费率:")
print(f" 已加微: {wechat_refund_users}/{len(wechat_stats['users'])} = {wechat_refund_users/len(wechat_stats['users'])*100:.1f}%")
if len(no_wechat_stats['users']) > 0:
print(f" 未加微: {no_wechat_refund_users}/{len(no_wechat_stats['users'])} = {no_wechat_refund_users/len(no_wechat_stats['users'])*100:.1f}%")
print(f"\n{'=' * 70}")
print("分析完成 ✅")