🤖 每日自动备份 - 2026-06-15 08:00:01
This commit is contained in:
parent
f4fac513f0
commit
4135e93b17
@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": 1,
|
||||
"updatedAt": "2026-06-09T07:36:53.566Z",
|
||||
"updatedAt": "2026-06-14T07:14:40.970Z",
|
||||
"entries": {
|
||||
"memory:memory/2026-05-06.md:1:20": {
|
||||
"key": "memory:memory/2026-05-06.md:1:20",
|
||||
@ -462,22 +462,25 @@
|
||||
"endLine": 30,
|
||||
"source": "memory",
|
||||
"snippet": "# 2026-06-02 工作日志 ## 微伴线索更新 - [陈逸鸫] 提供微伴导出数据,更新6/1-6/2线索 - 映射确认:益达老师 = 小龙 - 写入结果:小龙表+50条(6/1 25+6/2 25),吴迪表+15条(6/1) - ⚠️ 首次写入时重复了(小龙24行+吴迪2行),已清理 - 每日线索汇总已修正:6/1 小龙25 吴迪15 / 6/2 小龙25 ## Tom/Bob 6月不接小红书线索 - [陈逸鸫] 告知 Tom 和 Bob 6月开始不接小红书线索了 - 微伴数据确认6/1-6/2 Tom/Bob 新增为0 ## 订单汇总 2smjwA 全量覆盖进展 - Cursor 确认方案:数据库 bi_vala_order 为唯一源,全量覆盖 2smjwA - 数据库匹配到 390 单(销转团队线索关联),按月:3月88/4月158/5月138/6月6 - 看板去重后 406 单,差异 40 单已分类: - 有uid无订单 8单 - 金额对不上 6单 - 未注册用户 10单 - 昵称为空 2单 - 2025年订单 6单(不纳入) - 重复录入 1单(孙婧) - 已有但key比对误差 7单 - 26 单待杨羽确认,清单已发群 - 闸门:杨羽确认 → v2 数据 → 备份→清空→覆盖→挂定时 ## 看板全量审计 - 13 张 sheet 全部扫完,公式引用正确,无硬值 - Cursor 补修:关键投放数据 Row131 裸IF包IFERROR、销售结算 M1/M2 废弃清空、每日线索月合计行金色",
|
||||
"recallCount": 4,
|
||||
"recallCount": 6,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 4,
|
||||
"totalScore": 6,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-03T00:01:27.128Z",
|
||||
"lastRecalledAt": "2026-06-05T14:06:12.562Z",
|
||||
"lastRecalledAt": "2026-06-14T07:14:40.970Z",
|
||||
"queryHashes": [
|
||||
"5f57ba3c20a6",
|
||||
"b76e8457b2ee",
|
||||
"4354c1e39886",
|
||||
"70f4bbaea7b1"
|
||||
"70f4bbaea7b1",
|
||||
"d26345ebc273",
|
||||
"cd28f28f1a7c"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-03",
|
||||
"2026-06-05"
|
||||
"2026-06-05",
|
||||
"2026-06-14"
|
||||
],
|
||||
"conceptTags": [
|
||||
"备份",
|
||||
@ -601,18 +604,20 @@
|
||||
"endLine": 33,
|
||||
"source": "memory",
|
||||
"snippet": "- 抖音+联报退费率最高49.2%(也是最大组合124单) - **分析脚本:** `scripts/channel_lead_refund_analysis.py` ## 王虹茗 - V2修正:纳入多角色因素 - **反馈:** 指出 Sheet2 一个用户可能创建多个角色,要求重新分析 - **关键修正:** - 按用户聚合时保留角色数量、创建节奏、行课覆盖等信息 - 行课行为以\"任一角色完成即算\"聚合 - **新增发现:** - 1个角色退费率46.7% > 2个角色34.8% > ≥4个角色28.6%(角色越多退费越低) - 同日多角色45.7% vs 1周以上多角色28.6%(跨时间创建=持续使用信号) - 全角色无行课退费率75.9%(最高危) - 1角色+无行课=76.0%(最危险组合),≥4角色+有行课=16.7%(最安全) - **输出文件:** `output/渠道4-5月线索_退款相关性分析_v2_20260519_202711.xlsx`(20个维度+明细) - **分析脚本:** `scripts/channel_lead_refund_analysis_v2.py`",
|
||||
"recallCount": 1,
|
||||
"recallCount": 2,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"totalScore": 2,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-05T00:46:22.699Z",
|
||||
"lastRecalledAt": "2026-06-05T00:46:22.699Z",
|
||||
"lastRecalledAt": "2026-06-14T06:58:06.164Z",
|
||||
"queryHashes": [
|
||||
"34106cf619c4"
|
||||
"34106cf619c4",
|
||||
"6769ba9ebb36"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-05"
|
||||
"2026-06-05",
|
||||
"2026-06-14"
|
||||
],
|
||||
"conceptTags": [
|
||||
"联报退费率最高49.2",
|
||||
@ -624,6 +629,68 @@
|
||||
"全角色无行课退费率75.9",
|
||||
"76.0"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-06-12.md:18:38": {
|
||||
"key": "memory:memory/2026-06-12.md:18:38",
|
||||
"path": "memory/2026-06-12.md",
|
||||
"startLine": 18,
|
||||
"endLine": 38,
|
||||
"source": "memory",
|
||||
"snippet": "| 6 | 小乖大人 | 16158 | 13944890221 | 3/1 | 无订单 | - | 0 | 0 | DB无任何订单 | | 7 | 潘潘 | 16150 | 18610935696 | 3/1 | 无订单 | - | 0 | 0 | DB无任何订单 | | 8 | 张滢ya | 17894 | 13799768340 | 3/7 | 无订单 | - | 0 | 0 | DB无任何订单 | | 9 | sallywu | 17816 | 15998103065 | 3/7 | 无订单 | - | 0 | 0 | DB无任何订单 | | 10 | 🦁萨摩 | 21858 | 13685553716 | 3/8 | 4/8 | ✓ | 1999 | 1999 | 达人-学霸三人行 | ### Group B (有手机,4笔) - phone_encrypt查UID | # | 昵称 | 手机 | 加密结果 | DB匹配 | |---|------|------|---------|--------| | 11 | 潘提提 | 13427741613 | IiShdIaiY1oy7B_Xn4EH3g.. | 无匹配 | | 12 | 狸小路 | 18622850293 | YPAQ-740vKwxroqZGkeGyQ.. | 无匹配 | | 13 | 希小希 | 18086665321 | c8zfpqBrN1nikMkwAj64aQ.. | 无匹配 | | 14 | 曼 | 13520255515 | NBVtGuxEge7f7hdkyK3y7Q.. | 无匹配",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-14T06:58:06.164Z",
|
||||
"lastRecalledAt": "2026-06-14T06:58:06.164Z",
|
||||
"queryHashes": [
|
||||
"6769ba9ebb36"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-14"
|
||||
],
|
||||
"conceptTags": [
|
||||
"3/1",
|
||||
"3/7",
|
||||
"3/8",
|
||||
"4/8",
|
||||
"达人-学霸三人行",
|
||||
"phone-encrypt查uid",
|
||||
"iishdiaiy1oy7b-xn4eh3g",
|
||||
"ypaq-740vkwxroqzgkegyq"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-06-12.md:35:56": {
|
||||
"key": "memory:memory/2026-06-12.md:35:56",
|
||||
"path": "memory/2026-06-12.md",
|
||||
"startLine": 35,
|
||||
"endLine": 56,
|
||||
"source": "memory",
|
||||
"snippet": "| 15 | Rachel | 3/5 | 10994 | 13510564547 | 3/7 | ✓ | sales-adp-bj-jxl-0, GMV=1999 | | 16 | soul | 3/2 | 17387 | 15640464255 | 3/12 | ✓ | sales-adp-bj-jxl-0, GMV=1999 | | 17 | 红 | 3/7 | 17025 | 13533955004 | 3/14 | ✓ | sales-adp-bj-jxl-0, GMV=1999 | | 18 | 一笑轩渠 | 3/8 | 17425 | 15017528458 | 3/11 | ✓ | sales-adp-bj-jxl-0, GMV=1999 | | 19 | 蜗牛 | 3/2 | ❓ | ❓ | ❓ | - | 晚柠5/15订单数百笔,无手机/UID无法定位 | | 20 | c_瑶 | 3/6 | ❓ | ❓ | ❓ | - | \"直购\"渠道DB不存在,3/14无3998/1999匹配 | ### 关键发现 1. Group A 中 7/10 用户 DB 中无任何订单(pre汇总有GMV但DB不存在) 2. Group B 4个手机号全部未注册(H=未注册 确认正确) 3. Group C #15-#18 4笔 jxl-0 均 L≥C,pre怀疑#18 L<C不成立 4. #19 蜗牛和 #20 c_瑶 无法定位 ## 陈逸鸫 - full_refresh (S2+S3) 联调 ### 执行记录 - 时间:2026-06-12 18:00 左右 - S2:",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-06-14T06:58:06.164Z",
|
||||
"lastRecalledAt": "2026-06-14T06:58:06.164Z",
|
||||
"queryHashes": [
|
||||
"6769ba9ebb36"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-06-14"
|
||||
],
|
||||
"conceptTags": [
|
||||
"3/5",
|
||||
"3/7",
|
||||
"sales-adp-bj-jxl-0",
|
||||
"3/2",
|
||||
"3/12",
|
||||
"3/14",
|
||||
"3/8",
|
||||
"3/11"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
189
scripts/check_gap_57.py
Normal file
189
scripts/check_gap_57.py
Normal file
@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check 57 gap orders against DB"""
|
||||
import subprocess, json, re
|
||||
|
||||
# Gap data from chat: (month, source_sheet, sales, nickname, date_str, amount, channel, phone, has_clue, keyfrom, is_direct)
|
||||
gaps = [
|
||||
# === 3月 (20) ===
|
||||
("3月","qX7oJ6","小龙","雪珂💗","3月6日",1999,"微信小店","","线索","sales-adp-bj-jxl-0",False),
|
||||
("3月","qX7oJ6","小龙","Mars(燚)","3月7日",3598,"小红书-晚柠","","线索","",False),
|
||||
("3月","qX7oJ6","小龙","薇薇","3月",1999,"小红书直购","13520306626","无线索","",True),
|
||||
("3月","qX7oJ6","小龙","Yeah~^_^","3月20日",3598,"小红书-晚柠","","线索","",False),
|
||||
("3月","qX7oJ6","小龙","TutuTu","3月",1999,"小红书直购","18107332677","线索","",True),
|
||||
("3月","qX7oJ6","小龙","EFFIE","3月25日",3598,"微信小店","","线索","newmedia-dianpu-xhs-0-0",False),
|
||||
("3月","sSCT22","Tom","JeanneLᴇᴇ🦄","3月4日",3598,"微信小店","","线索","newmedia-dianpu-wxxd-0-0",False),
|
||||
("3月","sSCT22","Tom","薇妮姐","3月8日",599,"端内","","线索","",False),
|
||||
("3月","sSCT22","Tom","欣","3月7日",599,"端内","","线索","app-active-h5-0-0",False),
|
||||
("3月","sSCT22","Bob","Mogu","3月6日",599,"端内","","线索","",False),
|
||||
("3月","sSCT22","Bob","L. 一颗夹星糖🌟","3月12日",3598,"小红书-晚柠","","线索","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
("3月","sSCT22","Tom","阿雅呀","3月15日",3598,"小红书-晚柠","","线索","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
("3月","sSCT22","Tom","Anna","3月4日",1999,"抖音","","线索","newmedia-dianpu-douyin-0-0",True),
|
||||
("3月","sSCT22","Bob","Echo Liang","3月15日",1999,"微信小店","","线索","sales-adp-cd-zjf-0",False),
|
||||
("3月","sSCT22","Tom","幼兒園高材生🍼","3月23日",3598,"微信小店","13055770067","线索","sales-adp-cd-yy-0",False),
|
||||
("3月","sSCT22","Tom","Nancy","3月26日",599,"端内","","线索","",False),
|
||||
("3月","sSCT22","Tom","依米","3月30日",3598,"微信小店","","线索","sales-adp-cd-zjf-0",False),
|
||||
("3月","sSCT22","Bob","zhouyun","3月6日",1999,"小红书-学霸老王","13588706769","线索","",False),
|
||||
("3月","sSCT22","Tom","💗小超人棒棒哒🍭","3月29日",3598,"小红书-晚柠","18630368296","线索","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
("3月","sSCT22","Bob","鹿","3月14日",3598,"小红书-晚柠","","线索","",False),
|
||||
# === 4月 (15) ===
|
||||
("4月","qX7oJ6","小龙","琳溪","4月19日",3598,"微信小店","","线索","",False),
|
||||
("4月","qX7oJ6","小龙","小丽","4月26日",599,"端内","","线索","",False),
|
||||
("4月","qX7oJ6","小龙","子曦","4月16日",3598,"晚柠-小红书","","线索","",False),
|
||||
("4月","qX7oJ6","小龙","Gaᴗao","4月24日",3598,"微信小店","","线索","",False),
|
||||
("4月","XqxgjP","吴迪","ཚེ་རིང་མཚོ彩让措","2026/4/26",599,"端内","","无线索","",False),
|
||||
("4月","XqxgjP","吴迪","莉筱雅","2026/4/27",1999,"晚柠-小红书","","线索","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
("4月","XqxgjP","吴迪","爱吃巧克力","2026/4/24",1999,"微信小店","","无线索","",False),
|
||||
("4月","XqxgjP","吴迪","Aa~Jessie💝","2026/4/27",1999,"抖音","","线索","newmedia-dianpu-douyin-0-0",True),
|
||||
("4月","XqxgjP","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","线索","sales-adp-cd-yy-0",False),
|
||||
("4月","XqxgjP","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","线索","sales-adp-cd-yy-0",False), # dup
|
||||
("4月","sSCT22","Tom","静静是我🍃","4月8日",1999,"小红书-学霸老王","15975769851","线索","partner-actives-0-0-0",False),
|
||||
("4月","sSCT22","Bob","胆大鬼","4月8日",3598,"小红书-学霸老王","15262255267","线索","newmedia-daren-xhs-学霸老王讲真话-0",False),
|
||||
("4月","sSCT22","Tom","希Cissy-427","4月27日",3598,"微信小店","","线索","",False),
|
||||
("4月","sSCT22","Tom","Kerry","4月9日",3598,"微信小店","18328334683","线索","sales-adp-cd-yy-0",False),
|
||||
("4月","sSCT22","Tom","SHAN_Q_Q","4月1日",3598,"小红书-官店","","无线索","",True),
|
||||
# === 5月 (22) ===
|
||||
("5月","qX7oJ6","小龙","Sia","5月9日",599,"微信小店","","线索","",False),
|
||||
("5月","XqxgjP","吴迪","璐","2026/5/9",1999,"微信小店","","线索","sales-adp-bj-wd-0",False),
|
||||
("5月","XqxgjP","吴迪","^_^","2026/5/16",3598,"晚柠-小红书","","线索","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
("5月","XqxgjP","吴迪","🌸白色铃兰🌸","2026/5/17",3598,"抖音","","无线索","",True),
|
||||
("5月","XqxgjP","吴迪","咔咔","2026/5/7",3598,"微信小店","","线索","sales-adp-bj-wd-0",False),
|
||||
("5月","XqxgjP","吴迪","梦马","2026/5/21",3598,"小红书","","线索","newmedia-dianpu-xhs-0-0",False),
|
||||
("5月","XqxgjP","吴迪","梦马","2026/5/21",3598,"小红书","","线索","newmedia-dianpu-xhs-0-0",False), # dup
|
||||
("5月","XqxgjP","吴迪","小西瓜","2026/5/30",1999,"微信小店","","无线索","",False),
|
||||
("5月","XqxgjP","吴迪","璐","2026/5/9",1999,"微信小店","","线索","sales-adp-bj-wd-0",False), # dup
|
||||
("5月","sSCT22","Bob","Yuki-515","5月15日",3598,"小红书-晚柠","","线索","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
("5月","sSCT22","Tom","冬-515","5月15日",1999,"小红书-晚柠","","线索","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
("5月","sSCT22","Bob","微笑向暖","5月4日",1999,"微信小店","","无线索","",False),
|
||||
("5月","sSCT22","Bob","cici-511","5月11日",1999,"微信小店","","线索","sales-adp-cd-xsy-0",False),
|
||||
("5月","sSCT22","Tom","🐷-519","5月19日",1999,"小红书-宣儿妈妈","","线索","",False),
|
||||
("5月","sSCT22","Bob","妃-516","5月16日",1999,"微信小店","","线索","",False),
|
||||
("5月","sSCT22","Tom","黄晔-516","5月16日",3598,"微信小店","","无线索","",False),
|
||||
("5月","sSCT22","Tom","朵朵呀!","5月25日",1999,"微信小店","","线索","",False),
|
||||
("5月","sSCT22","Tom","雷鸣-414","5月14日",599,"微信小店","","无线索","",False),
|
||||
("5月","sSCT22","Tom","毛阿毛🐱-520","5月20日",1999,"小红书-官店","","无线索","",True),
|
||||
("5月","sSCT22","Tom","____Miss_y-519","5月19日",599,"微信小店","","线索","",False),
|
||||
("5月","sSCT22","Tom","Mandy-526","5月26日",1999,"微信小店","","无线索","",False),
|
||||
("5月","sSCT22","Bob","Yoki-529","5月29日",1999,"微信小店","","线索","",False),
|
||||
]
|
||||
|
||||
# Map channel names to key_from patterns
|
||||
def channel_to_pattern(channel):
|
||||
if "微信小店" in channel:
|
||||
return "newmedia-dianpu-wxxd-0-0"
|
||||
if "晚柠" in channel or "小红书-晚柠" in channel:
|
||||
return "newmedia-daren-xhs-晚柠也是个妈妈了-0"
|
||||
if "学霸老王" in channel and "小红书" in channel:
|
||||
return "newmedia-daren-xhs-学霸老王讲真话-0"
|
||||
if "学霸三人行" in channel:
|
||||
return "newmedia-daren-xhs-学霸三人行-0"
|
||||
if "学霸老王" in channel and "抖音" in channel:
|
||||
return "newmedia-daren-douyin-学霸老王%"
|
||||
if "宣儿妈妈" in channel:
|
||||
return "newmedia-daren-xhs-宣儿妈妈%"
|
||||
if "念妈" in channel:
|
||||
return "newmedia-daren%念妈%"
|
||||
if "端内" in channel:
|
||||
return "app-active-h5-0-0"
|
||||
if "抖音" in channel and "直购" not in channel:
|
||||
return "newmedia-dianpu-douyin-0-0"
|
||||
if "小红书-官店" in channel:
|
||||
return "newmedia-dianpu-xhs-0-0"
|
||||
if "小红书直购" in channel:
|
||||
return "newmedia-dianpu-xhs-0-0"
|
||||
if "小红书" in channel:
|
||||
return "newmedia-dianpu-xhs-0-0"
|
||||
return None
|
||||
|
||||
# For each gap, try to find matching order in DB
|
||||
import os
|
||||
PGPASS = "LdfjdjL83h3h3^$&**YGG*"
|
||||
|
||||
def parse_date(d):
|
||||
d = d.replace("日","").replace("月","/").replace(" ","").strip()
|
||||
if "/" in d:
|
||||
parts = d.split("/")
|
||||
if len(parts) < 2 or not parts[1]:
|
||||
return None
|
||||
m = int(parts[0])
|
||||
day = int(parts[1])
|
||||
return f"2026-{m:02d}-{day:02d}"
|
||||
else:
|
||||
return None
|
||||
|
||||
# Build a set of unique dates to query
|
||||
dates = set()
|
||||
for g in gaps:
|
||||
d = parse_date(g[4])
|
||||
if d:
|
||||
dates.add(d)
|
||||
|
||||
# Query all matching orders in one go
|
||||
date_conditions = " OR ".join([f"o.pay_success_date::date = '{d}'" for d in sorted(dates)])
|
||||
sql = f"""
|
||||
SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD') as pay_date,
|
||||
o.key_from, o.order_status, o.account_id, a.tel, a.created_at::date as reg_date
|
||||
FROM bi_vala_order o
|
||||
JOIN bi_vala_app_account a ON o.account_id = a.id
|
||||
WHERE a.status = 1
|
||||
AND o.pay_success_date >= '2026-03-01' AND o.pay_success_date < '2026-06-01'
|
||||
AND o.order_status IN (3, 4)
|
||||
AND o.pay_amount_int IN (59900, 199900, 359800)
|
||||
AND ({date_conditions})
|
||||
ORDER BY o.pay_success_date, o.pay_amount_int, o.key_from;
|
||||
"""
|
||||
|
||||
result = subprocess.run([
|
||||
"psql", "-h", "bj-postgres-16pob4sg.sql.tencentcdb.com",
|
||||
"-p", "28591", "-U", "ai_member", "-d", "vala_bi",
|
||||
"-c", sql
|
||||
], env={**os.environ, "PGPASSWORD": PGPASS}, capture_output=True, text=True, timeout=30)
|
||||
|
||||
# Parse results
|
||||
orders = []
|
||||
for line in result.stdout.strip().split("\n")[2:-1]: # skip header and footer
|
||||
parts = line.split("|")
|
||||
if len(parts) >= 9:
|
||||
orders.append({
|
||||
"id": parts[0].strip(),
|
||||
"trade_no": parts[1].strip(),
|
||||
"amount": int(parts[2].strip()) if parts[2].strip() else 0,
|
||||
"pay_date": parts[3].strip(),
|
||||
"key_from": parts[4].strip(),
|
||||
"order_status": parts[5].strip(),
|
||||
"account_id": parts[6].strip(),
|
||||
"tel": parts[7].strip(),
|
||||
"reg_date": parts[8].strip() if len(parts) > 8 else "",
|
||||
})
|
||||
|
||||
print(f"Total orders found: {len(orders)}")
|
||||
|
||||
# Now match each gap
|
||||
for i, g in enumerate(gaps):
|
||||
month, src, sales, nick, date_str, amount, channel, phone, clue, keyfrom, is_direct = g
|
||||
idx = i + 1
|
||||
d = parse_date(date_str)
|
||||
amount_int = amount * 100
|
||||
|
||||
# If phone provided, match by phone
|
||||
if phone:
|
||||
matched = [o for o in orders if o["tel"].replace("*","")[-4:] == phone[-4:] and o["pay_date"] == d and o["amount"] == amount_int] if d else []
|
||||
if not matched and d:
|
||||
matched = [o for o in orders if o["tel"].replace("*","")[-4:] == phone[-4:]]
|
||||
else:
|
||||
# Match by date + amount + channel pattern
|
||||
pat = keyfrom if keyfrom else channel_to_pattern(channel)
|
||||
if d and pat:
|
||||
if "%" in pat:
|
||||
matched = [o for o in orders if o["pay_date"] == d and o["amount"] == amount_int and pat.replace("%","") in o["key_from"]]
|
||||
else:
|
||||
matched = [o for o in orders if o["pay_date"] == d and o["amount"] == amount_int and o["key_from"] == pat]
|
||||
elif d:
|
||||
matched = [o for o in orders if o["pay_date"] == d and o["amount"] == amount_int]
|
||||
else:
|
||||
matched = []
|
||||
|
||||
status = "有" if matched else "无"
|
||||
print(f"{idx}. [{month}] {sales} {nick} | {date_str} ¥{amount} {channel} | {status} | {len(matched)} matches")
|
||||
if matched:
|
||||
for m in matched:
|
||||
print(f" -> order_id={m['id']} {m['pay_date']} ¥{m['amount']/100} {m['key_from'][:60]} status={m['order_status']} tel={m['tel']} reg={m['reg_date']}")
|
||||
173
scripts/check_gap_57_v2.py
Normal file
173
scripts/check_gap_57_v2.py
Normal file
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check 57 gap orders - efficient approach"""
|
||||
import subprocess, os, re
|
||||
|
||||
PGPASS = "LdfjdjL83h3h3^$&**YGG*"
|
||||
|
||||
# Gap data extracted from chat history
|
||||
gaps = [
|
||||
# 3月 (20)
|
||||
(1,"3月","qX7oJ6","小龙","雪珂💗","3月6日",1999,"微信小店","","sales-adp-bj-jxl-0"),
|
||||
(2,"3月","qX7oJ6","小龙","Mars(燚)","3月7日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
(3,"3月","qX7oJ6","小龙","薇薇","3月",1999,"小红书直购","13520306626","newmedia-dianpu-xhs-0-0"),
|
||||
(4,"3月","qX7oJ6","小龙","Yeah~^_^","3月20日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
(5,"3月","qX7oJ6","小龙","TutuTu","3月",1999,"小红书直购","18107332677","newmedia-dianpu-xhs-0-0"),
|
||||
(6,"3月","qX7oJ6","小龙","EFFIE","3月25日",3598,"微信小店","","newmedia-dianpu-xhs-0-0"),
|
||||
(7,"3月","sSCT22","Tom","JeanneLᴇᴇ🦄","3月4日",3598,"微信小店","","newmedia-dianpu-wxxd-0-0"),
|
||||
(8,"3月","sSCT22","Tom","薇妮姐","3月8日",599,"端内","","app-active-h5-0-0"),
|
||||
(9,"3月","sSCT22","Tom","欣","3月7日",599,"端内","","app-active-h5-0-0"),
|
||||
(10,"3月","sSCT22","Bob","Mogu","3月6日",599,"端内","","app-active-h5-0-0"),
|
||||
(11,"3月","sSCT22","Bob","L. 一颗夹星糖🌟","3月12日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
(12,"3月","sSCT22","Tom","阿雅呀","3月15日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
(13,"3月","sSCT22","Tom","Anna","3月4日",1999,"抖音","","newmedia-dianpu-douyin-0-0"),
|
||||
(14,"3月","sSCT22","Bob","Echo Liang","3月15日",1999,"微信小店","","sales-adp-cd-zjf-0"),
|
||||
(15,"3月","sSCT22","Tom","幼兒園高材生🍼","3月23日",3598,"微信小店","13055770067","sales-adp-cd-yy-0"),
|
||||
(16,"3月","sSCT22","Tom","Nancy","3月26日",599,"端内","","app-active-h5-0-0"),
|
||||
(17,"3月","sSCT22","Tom","依米","3月30日",3598,"微信小店","","sales-adp-cd-zjf-0"),
|
||||
(18,"3月","sSCT22","Bob","zhouyun","3月6日",1999,"小红书-学霸老王","13588706769","newmedia-daren-xhs-学霸老王讲真话-0"),
|
||||
(19,"3月","sSCT22","Tom","💗小超人棒棒哒🍭","3月29日",3598,"小红书-晚柠","18630368296","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
(20,"3月","sSCT22","Bob","鹿","3月14日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
# 4月 (15)
|
||||
(21,"4月","qX7oJ6","小龙","琳溪","4月19日",3598,"微信小店","","sales-adp-bj-jxl-0"),
|
||||
(22,"4月","qX7oJ6","小龙","小丽","4月26日",599,"端内","","app-active-h5-0-0"),
|
||||
(23,"4月","qX7oJ6","小龙","子曦","4月16日",3598,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
(24,"4月","qX7oJ6","小龙","Gaᴗao","4月24日",3598,"微信小店","","sales-adp-bj-jxl-0"),
|
||||
(25,"4月","XqxgjP","吴迪","ཚེ་རིང་མཚོ彩让措","2026/4/26",599,"端内","","app-active-h5-0-0"),
|
||||
(26,"4月","XqxgjP","吴迪","莉筱雅","2026/4/27",1999,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
(27,"4月","XqxgjP","吴迪","爱吃巧克力","2026/4/24",1999,"微信小店","","sales-adp-bj-wd-0"),
|
||||
(28,"4月","XqxgjP","吴迪","Aa~Jessie💝","2026/4/27",1999,"抖音","","newmedia-dianpu-douyin-0-0"),
|
||||
(29,"4月","XqxgjP","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","sales-adp-cd-yy-0"),
|
||||
(30,"4月","XqxgjP","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","sales-adp-cd-yy-0"),
|
||||
(31,"4月","sSCT22","Tom","静静是我🍃","4月8日",1999,"小红书-学霸老王","15975769851","partner-actives-0-0-0"),
|
||||
(32,"4月","sSCT22","Bob","胆大鬼","4月8日",3598,"小红书-学霸老王","15262255267","newmedia-daren-xhs-学霸老王讲真话-0"),
|
||||
(33,"4月","sSCT22","Tom","希Cissy-427","4月27日",3598,"微信小店","","sales-adp-cd-zjf-0"),
|
||||
(34,"4月","sSCT22","Tom","Kerry","4月9日",3598,"微信小店","18328334683","sales-adp-cd-yy-0"),
|
||||
(35,"4月","sSCT22","Tom","SHAN_Q_Q","4月1日",3598,"小红书-官店","","newmedia-dianpu-xhs-0-0"),
|
||||
# 5月 (22)
|
||||
(36,"5月","qX7oJ6","小龙","Sia","5月9日",599,"微信小店","","sales-adp-bj-jxl-0"),
|
||||
(37,"5月","XqxgjP","吴迪","璐","2026/5/9",1999,"微信小店","","sales-adp-bj-wd-0"),
|
||||
(38,"5月","XqxgjP","吴迪","^_^","2026/5/16",3598,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
(39,"5月","XqxgjP","吴迪","🌸白色铃兰🌸","2026/5/17",3598,"抖音","","newmedia-dianpu-douyin-0-0"),
|
||||
(40,"5月","XqxgjP","吴迪","咔咔","2026/5/7",3598,"微信小店","","sales-adp-bj-wd-0"),
|
||||
(41,"5月","XqxgjP","吴迪","梦马","2026/5/21",3598,"小红书","","newmedia-dianpu-xhs-0-0"),
|
||||
(42,"5月","XqxgjP","吴迪","梦马","2026/5/21",3598,"小红书","","newmedia-dianpu-xhs-0-0"),
|
||||
(43,"5月","XqxgjP","吴迪","小西瓜","2026/5/30",1999,"微信小店","","sales-adp-bj-wd-0"),
|
||||
(44,"5月","XqxgjP","吴迪","璐","2026/5/9",1999,"微信小店","","sales-adp-bj-wd-0"),
|
||||
(45,"5月","sSCT22","Bob","Yuki-515","5月15日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
(46,"5月","sSCT22","Tom","冬-515","5月15日",1999,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0"),
|
||||
(47,"5月","sSCT22","Bob","微笑向暖","5月4日",1999,"微信小店","","sales-adp-bj-wd-0"),
|
||||
(48,"5月","sSCT22","Bob","cici-511","5月11日",1999,"微信小店","","sales-adp-cd-xsy-0"),
|
||||
(49,"5月","sSCT22","Tom","🐷-519","5月19日",1999,"小红书-宣儿妈妈","","newmedia-daren-xhs-宣儿妈妈%"),
|
||||
(50,"5月","sSCT22","Bob","妃-516","5月16日",1999,"微信小店","","sales-adp-cd-zjf-0"),
|
||||
(51,"5月","sSCT22","Tom","黄晔-516","5月16日",3598,"微信小店","","sales-adp-bj-wd-0"),
|
||||
(52,"5月","sSCT22","Tom","朵朵呀!","5月25日",1999,"微信小店","","sales-adp-cd-zjf-0"),
|
||||
(53,"5月","sSCT22","Tom","雷鸣-414","5月14日",599,"微信小店","","sales-adp-bj-wd-0"),
|
||||
(54,"5月","sSCT22","Tom","毛阿毛🐱-520","5月20日",1999,"小红书-官店","","newmedia-dianpu-xhs-0-0"),
|
||||
(55,"5月","sSCT22","Tom","____Miss_y-519","5月19日",599,"微信小店","","sales-adp-bj-wd-0"),
|
||||
(56,"5月","sSCT22","Tom","Mandy-526","5月26日",1999,"微信小店","","sales-adp-bj-wd-0"),
|
||||
(57,"5月","sSCT22","Bob","Yoki-529","5月29日",1999,"微信小店","","sales-adp-cd-zjf-0"),
|
||||
]
|
||||
|
||||
# Parse date
|
||||
def parse_date(d):
|
||||
d = d.replace("日","").replace("月","/").replace(" ","").strip()
|
||||
if "/" in d:
|
||||
parts = d.split("/")
|
||||
if len(parts) >= 2 and parts[1]:
|
||||
m = int(parts[0])
|
||||
day = int(parts[1])
|
||||
return f"2026-{m:02d}-{day:02d}"
|
||||
return None
|
||||
|
||||
# Encrypt phones
|
||||
from scripts.phone_encrypt import encrypt_phone
|
||||
phone_map = {}
|
||||
for g in gaps:
|
||||
phone = g[7]
|
||||
if phone:
|
||||
phone_map[phone] = encrypt_phone(phone)
|
||||
|
||||
# Look up accounts by encrypted phone
|
||||
if phone_map:
|
||||
phone_conds = " OR ".join([f"a.tel_encrypt LIKE '{v}%'" for v in phone_map.values()])
|
||||
sql = f"SELECT a.id, a.tel, a.tel_encrypt FROM bi_vala_app_account a WHERE a.status=1 AND ({phone_conds})"
|
||||
r = subprocess.run(["psql","-h","bj-postgres-16pob4sg.sql.tencentcdb.com","-p","28591","-U","ai_member","-d","vala_bi","-c",sql],
|
||||
env={**os.environ,"PGPASSWORD":PGPASS}, capture_output=True, text=True, timeout=15)
|
||||
# Build account_id -> tel mapping
|
||||
acct_tel = {}
|
||||
for line in r.stdout.strip().split("\n")[2:-1]:
|
||||
parts = [p.strip() for p in line.split("|")]
|
||||
if len(parts) >= 3:
|
||||
acct_tel[parts[0]] = parts[1]
|
||||
else:
|
||||
acct_tel = {}
|
||||
|
||||
# Now query orders by key_from + date for each gap
|
||||
results = []
|
||||
for g in gaps:
|
||||
idx, month, src, sales, nick, date_str, amount, channel, phone, keyfrom = g
|
||||
d = parse_date(date_str)
|
||||
amt = amount * 100
|
||||
|
||||
found = None
|
||||
# If we have phone match
|
||||
if phone and phone in phone_map:
|
||||
enc = phone_map[phone]
|
||||
# Find account_id
|
||||
sql2 = f"SELECT a.id FROM bi_vala_app_account a WHERE a.status=1 AND a.tel_encrypt LIKE '{enc}%'"
|
||||
r2 = subprocess.run(["psql","-h","bj-postgres-16pob4sg.sql.tencentcdb.com","-p","28591","-U","ai_member","-d","vala_bi","-c",sql2],
|
||||
env={**os.environ,"PGPASSWORD":PGPASS}, capture_output=True, text=True, timeout=10)
|
||||
acct_ids = []
|
||||
for line in r2.stdout.strip().split("\n")[2:-1]:
|
||||
p = line.split("|")[0].strip()
|
||||
if p.isdigit():
|
||||
acct_ids.append(p)
|
||||
if acct_ids:
|
||||
acct_list = ",".join(acct_ids)
|
||||
sql3 = f"SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD'), o.key_from, o.order_status, o.account_id FROM bi_vala_order o WHERE o.account_id IN ({acct_list}) AND o.pay_amount_int={amt} AND o.order_status IN (3,4) AND o.pay_success_date IS NOT NULL ORDER BY o.pay_success_date"
|
||||
r3 = subprocess.run(["psql","-h","bj-postgres-16pob4sg.sql.tencentcdb.com","-p","28591","-U","ai_member","-d","vala_bi","-c",sql3],
|
||||
env={**os.environ,"PGPASSWORD":PGPASS}, capture_output=True, text=True, timeout=10)
|
||||
for line in r3.stdout.strip().split("\n")[2:-1]:
|
||||
parts = [p.strip() for p in line.split("|")]
|
||||
if len(parts) >= 7:
|
||||
found = {"order_id":parts[0],"trade_no":parts[1],"amount":int(parts[2]),"pay_date":parts[3],"key_from":parts[4],"status":parts[5],"account_id":parts[6]}
|
||||
break
|
||||
|
||||
# If no phone match, try keyfrom + date + amount
|
||||
if not found and d and keyfrom:
|
||||
if "%" in keyfrom:
|
||||
like = keyfrom.replace("%","")
|
||||
sql4 = f"SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD'), o.key_from, o.order_status, o.account_id, a.tel FROM bi_vala_order o JOIN bi_vala_app_account a ON o.account_id=a.id WHERE a.status=1 AND o.pay_success_date::date='{d}' AND o.pay_amount_int={amt} AND o.key_from LIKE '%{like}%' AND o.order_status IN (3,4) LIMIT 3"
|
||||
else:
|
||||
sql4 = f"SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD'), o.key_from, o.order_status, o.account_id, a.tel FROM bi_vala_order o JOIN bi_vala_app_account a ON o.account_id=a.id WHERE a.status=1 AND o.pay_success_date::date='{d}' AND o.pay_amount_int={amt} AND o.key_from='{keyfrom}' AND o.order_status IN (3,4) LIMIT 3"
|
||||
r4 = subprocess.run(["psql","-h","bj-postgres-16pob4sg.sql.tencentcdb.com","-p","28591","-U","ai_member","-d","vala_bi","-c",sql4],
|
||||
env={**os.environ,"PGPASSWORD":PGPASS}, capture_output=True, text=True, timeout=10)
|
||||
matches = []
|
||||
for line in r4.stdout.strip().split("\n")[2:-1]:
|
||||
parts = [p.strip() for p in line.split("|")]
|
||||
if len(parts) >= 8:
|
||||
matches.append({"order_id":parts[0],"trade_no":parts[1],"amount":int(parts[2]),"pay_date":parts[3],"key_from":parts[4],"status":parts[5],"account_id":parts[6],"tel":parts[7]})
|
||||
if matches:
|
||||
found = matches[0]
|
||||
|
||||
# Check refunds
|
||||
gsv = 0
|
||||
if found:
|
||||
aid = found.get("account_id","")
|
||||
sql5 = f"SELECT SUM(r.refund_amount_int) FROM bi_refund_order r JOIN bi_vala_order o ON r.trade_no=o.trade_no WHERE o.account_id={aid} AND r.status=3"
|
||||
r5 = subprocess.run(["psql","-h","bj-postgres-16pob4sg.sql.tencentcdb.com","-p","28591","-U","ai_member","-d","vala_bi","-c",sql5],
|
||||
env={**os.environ,"PGPASSWORD":PGPASS}, capture_output=True, text=True, timeout=10)
|
||||
refund = 0
|
||||
for line in r5.stdout.strip().split("\n")[2:-1]:
|
||||
val = line.strip()
|
||||
if val and val.isdigit():
|
||||
refund = int(val)
|
||||
gsv = found["amount"] - refund
|
||||
|
||||
status = "有" if found else "无"
|
||||
is_direct = keyfrom in ("newmedia-dianpu-xhs-0-0","newmedia-dianpu-douyin-0-0","newmedia-dianpu-wxxd-0-0","app-active-h5-0-0")
|
||||
should_enter = "是" if (found and gsv > 0 and not is_direct) else "否"
|
||||
|
||||
print(f"{idx}. [{month}] {sales} {nick} | {date_str} ¥{amount} {channel} | {status} | GSV={gsv/100:.0f} | 应进Bot={should_enter}")
|
||||
if found:
|
||||
print(f" order_id={found['order_id']} {found.get('pay_date','')} ¥{found['amount']/100:.0f} {found.get('key_from','')[:50]} status={found.get('status','')}")
|
||||
197
scripts/check_gap_57_v3.py
Normal file
197
scripts/check_gap_57_v3.py
Normal file
@ -0,0 +1,197 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check 57 gap orders - bulk approach"""
|
||||
import subprocess, os, json, sys
|
||||
sys.path.insert(0, '/root/.openclaw/workspace')
|
||||
|
||||
PGPASS = "LdfjdjL83h3h3^$&**YGG*"
|
||||
DB = ["psql","-h","bj-postgres-16pob4sg.sql.tencentcdb.com","-p","28591","-U","ai_member","-d","vala_bi"]
|
||||
ENV = {**os.environ, "PGPASSWORD": PGPASS}
|
||||
|
||||
def q(sql):
|
||||
r = subprocess.run(DB + ["-c", sql], env=ENV, capture_output=True, text=True, timeout=15)
|
||||
rows = []
|
||||
for line in r.stdout.strip().split("\n")[2:-1]:
|
||||
parts = [p.strip() for p in line.split("|")]
|
||||
rows.append(parts)
|
||||
return rows
|
||||
|
||||
# Gap data
|
||||
gaps = [
|
||||
(1,"3月","小龙","雪珂💗","3月6日",1999,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(2,"3月","小龙","Mars(燚)","3月7日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(3,"3月","小龙","薇薇","3月",1999,"小红书直购","13520306626","newmedia-dianpu-xhs-0-0",True),
|
||||
(4,"3月","小龙","Yeah~^_^","3月20日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(5,"3月","小龙","TutuTu","3月",1999,"小红书直购","18107332677","newmedia-dianpu-xhs-0-0",True),
|
||||
(6,"3月","小龙","EFFIE","3月25日",3598,"微信小店","","newmedia-dianpu-xhs-0-0",False),
|
||||
(7,"3月","Tom","JeanneLᴇᴇ🦄","3月4日",3598,"微信小店","","newmedia-dianpu-wxxd-0-0",False),
|
||||
(8,"3月","Tom","薇妮姐","3月8日",599,"端内","","app-active-h5-0-0",False),
|
||||
(9,"3月","Tom","欣","3月7日",599,"端内","","app-active-h5-0-0",False),
|
||||
(10,"3月","Bob","Mogu","3月6日",599,"端内","","app-active-h5-0-0",False),
|
||||
(11,"3月","Bob","L. 一颗夹星糖🌟","3月12日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(12,"3月","Tom","阿雅呀","3月15日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(13,"3月","Tom","Anna","3月4日",1999,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(14,"3月","Bob","Echo Liang","3月15日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(15,"3月","Tom","幼兒園高材生🍼","3月23日",3598,"微信小店","13055770067","sales-adp-cd-yy-0",False),
|
||||
(16,"3月","Tom","Nancy","3月26日",599,"端内","","app-active-h5-0-0",False),
|
||||
(17,"3月","Tom","依米","3月30日",3598,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(18,"3月","Bob","zhouyun","3月6日",1999,"小红书-学霸老王","13588706769","newmedia-daren-xhs-学霸老王讲真话-0",False),
|
||||
(19,"3月","Tom","💗小超人棒棒哒🍭","3月29日",3598,"小红书-晚柠","18630368296","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(20,"3月","Bob","鹿","3月14日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(21,"4月","小龙","琳溪","4月19日",3598,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(22,"4月","小龙","小丽","4月26日",599,"端内","","app-active-h5-0-0",False),
|
||||
(23,"4月","小龙","子曦","4月16日",3598,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(24,"4月","小龙","Gaᴗao","4月24日",3598,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(25,"4月","吴迪","ཚེ་རིང་མཚོ彩让措","2026/4/26",599,"端内","","app-active-h5-0-0",False),
|
||||
(26,"4月","吴迪","莉筱雅","2026/4/27",1999,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(27,"4月","吴迪","爱吃巧克力","2026/4/24",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(28,"4月","吴迪","Aa~Jessie💝","2026/4/27",1999,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(29,"4月","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","sales-adp-cd-yy-0",False),
|
||||
(30,"4月","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","sales-adp-cd-yy-0",False),
|
||||
(31,"4月","Tom","静静是我🍃","4月8日",1999,"小红书-学霸老王","15975769851","partner-actives-0-0-0",False),
|
||||
(32,"4月","Bob","胆大鬼","4月8日",3598,"小红书-学霸老王","15262255267","newmedia-daren-xhs-学霸老王讲真话-0",False),
|
||||
(33,"4月","Tom","希Cissy-427","4月27日",3598,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(34,"4月","Tom","Kerry","4月9日",3598,"微信小店","18328334683","sales-adp-cd-yy-0",False),
|
||||
(35,"4月","Tom","SHAN_Q_Q","4月1日",3598,"小红书-官店","","newmedia-dianpu-xhs-0-0",True),
|
||||
(36,"5月","小龙","Sia","5月9日",599,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(37,"5月","吴迪","璐","2026/5/9",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(38,"5月","吴迪","^_^","2026/5/16",3598,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(39,"5月","吴迪","🌸白色铃兰🌸","2026/5/17",3598,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(40,"5月","吴迪","咔咔","2026/5/7",3598,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(41,"5月","吴迪","梦马","2026/5/21",3598,"小红书","","newmedia-dianpu-xhs-0-0",False),
|
||||
(42,"5月","吴迪","梦马","2026/5/21",3598,"小红书","","newmedia-dianpu-xhs-0-0",False),
|
||||
(43,"5月","吴迪","小西瓜","2026/5/30",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(44,"5月","吴迪","璐","2026/5/9",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(45,"5月","Bob","Yuki-515","5月15日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(46,"5月","Tom","冬-515","5月15日",1999,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(47,"5月","Bob","微笑向暖","5月4日",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(48,"5月","Bob","cici-511","5月11日",1999,"微信小店","","sales-adp-cd-xsy-0",False),
|
||||
(49,"5月","Tom","🐷-519","5月19日",1999,"小红书-宣儿妈妈","","newmedia-daren-xhs-宣儿妈妈%",False),
|
||||
(50,"5月","Bob","妃-516","5月16日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(51,"5月","Tom","黄晔-516","5月16日",3598,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(52,"5月","Tom","朵朵呀!","5月25日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(53,"5月","Tom","雷鸣-414","5月14日",599,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(54,"5月","Tom","毛阿毛🐱-520","5月20日",1999,"小红书-官店","","newmedia-dianpu-xhs-0-0",True),
|
||||
(55,"5月","Tom","____Miss_y-519","5月19日",599,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(56,"5月","Tom","Mandy-526","5月26日",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(57,"5月","Bob","Yoki-529","5月29日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
]
|
||||
|
||||
def parse_date(d):
|
||||
d = d.replace("日","").replace("月","/").replace(" ","").strip()
|
||||
if "/" in d:
|
||||
parts = d.split("/")
|
||||
if len(parts) >= 2 and parts[1]:
|
||||
return f"2026-{int(parts[0]):02d}-{int(parts[1]):02d}"
|
||||
return None
|
||||
|
||||
# Step 1: Encrypt all phones
|
||||
from scripts.phone_encrypt import encrypt_phone
|
||||
phone_to_enc = {}
|
||||
for g in gaps:
|
||||
if g[7]:
|
||||
phone_to_enc[g[7]] = encrypt_phone(g[7])
|
||||
|
||||
# Step 2: Look up all accounts by encrypted phone
|
||||
enc_to_acct = {}
|
||||
if phone_to_enc:
|
||||
conds = " OR ".join([f"tel_encrypt LIKE '{v}%'" for v in phone_to_enc.values()])
|
||||
rows = q(f"SELECT id, tel, tel_encrypt FROM bi_vala_app_account WHERE status=1 AND ({conds})")
|
||||
for r in rows:
|
||||
if len(r) >= 3:
|
||||
enc_to_acct[r[2]] = r[0]
|
||||
|
||||
# Step 3: Get all orders for matched accounts
|
||||
phone_acct_ids = set(enc_to_acct.values())
|
||||
phone_orders = {}
|
||||
if phone_acct_ids:
|
||||
ids = ",".join(phone_acct_ids)
|
||||
rows = q(f"SELECT id, trade_no, pay_amount_int, to_char(pay_success_date,'YYYY-MM-DD'), key_from, order_status, account_id FROM bi_vala_order WHERE account_id IN ({ids}) AND pay_amount_int IN (59900,199900,359800) AND order_status IN (3,4) AND pay_success_date IS NOT NULL ORDER BY pay_success_date")
|
||||
for r in rows:
|
||||
if len(r) >= 7:
|
||||
aid = r[6]
|
||||
if aid not in phone_orders:
|
||||
phone_orders[aid] = []
|
||||
phone_orders[aid].append({"id":r[0],"trade_no":r[1],"amount":int(r[2]),"pay_date":r[3],"key_from":r[4],"status":r[5]})
|
||||
|
||||
# Step 4: Bulk query by keyfrom+date combos
|
||||
# Collect unique (date, amount, keyfrom) combos
|
||||
combos = set()
|
||||
for g in gaps:
|
||||
d = parse_date(g[4])
|
||||
if d and g[8]:
|
||||
combos.add((d, g[5]*100, g[8]))
|
||||
|
||||
# Build OR conditions
|
||||
kf_conds = []
|
||||
for d, amt, kf in combos:
|
||||
if "%" in kf:
|
||||
kf_conds.append(f"(pay_success_date::date='{d}' AND pay_amount_int={amt} AND key_from LIKE '%{kf.replace('%','')}%')")
|
||||
else:
|
||||
kf_conds.append(f"(pay_success_date::date='{d}' AND pay_amount_int={amt} AND key_from='{kf}')")
|
||||
|
||||
kf_orders = {}
|
||||
if kf_conds:
|
||||
# Split into batches of 50
|
||||
for i in range(0, len(kf_conds), 50):
|
||||
batch = kf_conds[i:i+50]
|
||||
sql = f"SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD'), o.key_from, o.order_status, o.account_id, a.tel FROM bi_vala_order o JOIN bi_vala_app_account a ON o.account_id=a.id WHERE a.status=1 AND o.order_status IN (3,4) AND o.pay_success_date >= '2026-03-01' AND o.pay_success_date < '2026-06-01' AND ({' OR '.join(batch)})"
|
||||
rows = q(sql)
|
||||
for r in rows:
|
||||
if len(r) >= 8:
|
||||
kf_orders[(r[3], int(r[2]), r[4])] = {"id":r[0],"trade_no":r[1],"amount":int(r[2]),"pay_date":r[3],"key_from":r[4],"status":r[5],"account_id":r[6],"tel":r[7]}
|
||||
|
||||
# Step 5: Get all refunds for matched accounts
|
||||
all_acct_ids = set()
|
||||
for aid in phone_acct_ids:
|
||||
all_acct_ids.add(aid)
|
||||
for v in kf_orders.values():
|
||||
all_acct_ids.add(v["account_id"])
|
||||
|
||||
refunds = {}
|
||||
if all_acct_ids:
|
||||
ids = ",".join(all_acct_ids)
|
||||
rows = q(f"SELECT o.account_id, SUM(r.refund_amount_int) FROM bi_refund_order r JOIN bi_vala_order o ON r.trade_no=o.trade_no WHERE o.account_id IN ({ids}) AND r.status=3 GROUP BY o.account_id")
|
||||
for r in rows:
|
||||
if len(r) >= 2 and r[1]:
|
||||
refunds[r[0]] = int(r[1])
|
||||
|
||||
# Step 6: Match
|
||||
for g in gaps:
|
||||
idx, month, sales, nick, date_str, amount, channel, phone, keyfrom, is_direct = g
|
||||
d = parse_date(date_str)
|
||||
amt = amount * 100
|
||||
|
||||
found = None
|
||||
# Try phone match first
|
||||
if phone and phone in phone_to_enc:
|
||||
enc = phone_to_enc[phone]
|
||||
aid = enc_to_acct.get(enc)
|
||||
if aid and aid in phone_orders:
|
||||
for o in phone_orders[aid]:
|
||||
if o["amount"] == amt:
|
||||
found = o
|
||||
break
|
||||
|
||||
# Try keyfrom+date+amount match
|
||||
if not found and d and keyfrom:
|
||||
if "%" in keyfrom:
|
||||
like = keyfrom.replace("%","")
|
||||
for k, v in kf_orders.items():
|
||||
if v["pay_date"] == d and v["amount"] == amt and like in v["key_from"]:
|
||||
found = v
|
||||
break
|
||||
else:
|
||||
found = kf_orders.get((d, amt, keyfrom))
|
||||
|
||||
gsv = 0
|
||||
if found:
|
||||
aid = found.get("account_id","")
|
||||
refund = refunds.get(aid, 0)
|
||||
gsv = found["amount"] - refund
|
||||
|
||||
status = "有" if found else "无"
|
||||
should = "是" if (found and gsv > 0 and not is_direct) else "否"
|
||||
|
||||
print(f"{idx}. [{month}] {sales} {nick} | {date_str} ¥{amount} {channel} | {status} | GSV={gsv/100:.0f} | 应进Bot={should}")
|
||||
if found:
|
||||
print(f" order_id={found['id']} {found.get('pay_date','')} ¥{found['amount']/100:.0f} {found.get('key_from','')[:50]} status={found.get('status','')}")
|
||||
193
scripts/check_gap_57_v4.py
Normal file
193
scripts/check_gap_57_v4.py
Normal file
@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check 57 gap orders v4 - broader matching"""
|
||||
import subprocess, os, sys
|
||||
sys.path.insert(0, '/root/.openclaw/workspace')
|
||||
|
||||
PGPASS = "LdfjdjL83h3h3^$&**YGG*"
|
||||
DB = ["psql","-h","bj-postgres-16pob4sg.sql.tencentcdb.com","-p","28591","-U","ai_member","-d","vala_bi"]
|
||||
ENV = {**os.environ, "PGPASSWORD": PGPASS}
|
||||
|
||||
def q(sql):
|
||||
r = subprocess.run(DB + ["-c", sql], env=ENV, capture_output=True, text=True, timeout=30)
|
||||
rows = []
|
||||
for line in r.stdout.strip().split("\n")[2:-1]:
|
||||
parts = [p.strip() for p in line.split("|")]
|
||||
rows.append(parts)
|
||||
return rows
|
||||
|
||||
# Gap data from chat - exact keyfrom from gap messages
|
||||
gaps = [
|
||||
(1,"3月","小龙","雪珂💗","3月6日",1999,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(2,"3月","小龙","Mars(燚)","3月7日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(3,"3月","小龙","薇薇","3月",1999,"小红书直购","13520306626","newmedia-dianpu-xhs-0-0",True),
|
||||
(4,"3月","小龙","Yeah~^_^","3月20日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(5,"3月","小龙","TutuTu","3月",1999,"小红书直购","18107332677","newmedia-dianpu-xhs-0-0",True),
|
||||
(6,"3月","小龙","EFFIE","3月25日",3598,"微信小店","","newmedia-dianpu-xhs-0-0",False),
|
||||
(7,"3月","Tom","JeanneLᴇᴇ🦄","3月4日",3598,"微信小店","","newmedia-dianpu-wxxd-0-0",False),
|
||||
(8,"3月","Tom","薇妮姐","3月8日",599,"端内","","app-active-h5-0-0",False),
|
||||
(9,"3月","Tom","欣","3月7日",599,"端内","","app-active-h5-0-0",False),
|
||||
(10,"3月","Bob","Mogu","3月6日",599,"端内","","app-active-h5-0-0",False),
|
||||
(11,"3月","Bob","L. 一颗夹星糖🌟","3月12日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(12,"3月","Tom","阿雅呀","3月15日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(13,"3月","Tom","Anna","3月4日",1999,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(14,"3月","Bob","Echo Liang","3月15日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(15,"3月","Tom","幼兒園高材生🍼","3月23日",3598,"微信小店","13055770067","sales-adp-cd-yy-0",False),
|
||||
(16,"3月","Tom","Nancy","3月26日",599,"端内","","app-active-h5-0-0",False),
|
||||
(17,"3月","Tom","依米","3月30日",3598,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(18,"3月","Bob","zhouyun","3月6日",1999,"小红书-学霸老王","13588706769","newmedia-daren-xhs-学霸老王讲真话-0",False),
|
||||
(19,"3月","Tom","💗小超人棒棒哒🍭","3月29日",3598,"小红书-晚柠","18630368296","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(20,"3月","Bob","鹿","3月14日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(21,"4月","小龙","琳溪","4月19日",3598,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(22,"4月","小龙","小丽","4月26日",599,"端内","","app-active-h5-0-0",False),
|
||||
(23,"4月","小龙","子曦","4月16日",3598,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(24,"4月","小龙","Gaᴗao","4月24日",3598,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(25,"4月","吴迪","ཚེ་རིང་མཚོ彩让措","2026/4/26",599,"端内","","app-active-h5-0-0",False),
|
||||
(26,"4月","吴迪","莉筱雅","2026/4/27",1999,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(27,"4月","吴迪","爱吃巧克力","2026/4/24",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(28,"4月","吴迪","Aa~Jessie💝","2026/4/27",1999,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(29,"4月","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","sales-adp-cd-yy-0",False),
|
||||
(30,"4月","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","sales-adp-cd-yy-0",False),
|
||||
(31,"4月","Tom","静静是我🍃","4月8日",1999,"小红书-学霸老王","15975769851","partner-actives-0-0-0",False),
|
||||
(32,"4月","Bob","胆大鬼","4月8日",3598,"小红书-学霸老王","15262255267","newmedia-daren-xhs-学霸老王讲真话-0",False),
|
||||
(33,"4月","Tom","希Cissy-427","4月27日",3598,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(34,"4月","Tom","Kerry","4月9日",3598,"微信小店","18328334683","sales-adp-cd-yy-0",False),
|
||||
(35,"4月","Tom","SHAN_Q_Q","4月1日",3598,"小红书-官店","","newmedia-dianpu-xhs-0-0",True),
|
||||
(36,"5月","小龙","Sia","5月9日",599,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(37,"5月","吴迪","璐","2026/5/9",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(38,"5月","吴迪","^_^","2026/5/16",3598,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(39,"5月","吴迪","🌸白色铃兰🌸","2026/5/17",3598,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(40,"5月","吴迪","咔咔","2026/5/7",3598,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(41,"5月","吴迪","梦马","2026/5/21",3598,"小红书","","newmedia-dianpu-xhs-0-0",False),
|
||||
(42,"5月","吴迪","梦马","2026/5/21",3598,"小红书","","newmedia-dianpu-xhs-0-0",False),
|
||||
(43,"5月","吴迪","小西瓜","2026/5/30",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(44,"5月","吴迪","璐","2026/5/9",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(45,"5月","Bob","Yuki-515","5月15日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(46,"5月","Tom","冬-515","5月15日",1999,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(47,"5月","Bob","微笑向暖","5月4日",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(48,"5月","Bob","cici-511","5月11日",1999,"微信小店","","sales-adp-cd-xsy-0",False),
|
||||
(49,"5月","Tom","🐷-519","5月19日",1999,"小红书-宣儿妈妈","","newmedia-daren-xhs-宣儿妈妈%",False),
|
||||
(50,"5月","Bob","妃-516","5月16日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(51,"5月","Tom","黄晔-516","5月16日",3598,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(52,"5月","Tom","朵朵呀!","5月25日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(53,"5月","Tom","雷鸣-414","5月14日",599,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(54,"5月","Tom","毛阿毛🐱-520","5月20日",1999,"小红书-官店","","newmedia-dianpu-xhs-0-0",True),
|
||||
(55,"5月","Tom","____Miss_y-519","5月19日",599,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(56,"5月","Tom","Mandy-526","5月26日",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(57,"5月","Bob","Yoki-529","5月29日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
]
|
||||
|
||||
def parse_date(d):
|
||||
d = d.replace("日","").replace("月","/").replace(" ","").strip()
|
||||
if "/" in d:
|
||||
parts = d.split("/")
|
||||
if len(parts) >= 2 and parts[1]:
|
||||
return f"2026-{int(parts[0]):02d}-{int(parts[1]):02d}"
|
||||
return None
|
||||
|
||||
from scripts.phone_encrypt import encrypt_phone
|
||||
|
||||
# Step 1: Encrypt phones
|
||||
phone_enc = {}
|
||||
for g in gaps:
|
||||
if g[7]:
|
||||
phone_enc[g[7]] = encrypt_phone(g[7])
|
||||
|
||||
# Step 2: Get account IDs for phones
|
||||
phone_to_aid = {}
|
||||
if phone_enc:
|
||||
conds = " OR ".join([f"tel_encrypt LIKE '{v}%'" for v in phone_enc.values()])
|
||||
for r in q(f"SELECT id, tel_encrypt FROM bi_vala_app_account WHERE status=1 AND ({conds})"):
|
||||
if len(r) >= 2:
|
||||
phone_to_aid[r[1]] = r[0]
|
||||
|
||||
# Step 3: Get all orders for phone-matched accounts
|
||||
phone_orders = {}
|
||||
if phone_to_aid:
|
||||
ids = ",".join(phone_to_aid.values())
|
||||
for r in q(f"SELECT id, trade_no, pay_amount_int, to_char(pay_success_date,'YYYY-MM-DD'), key_from, order_status, account_id FROM bi_vala_order WHERE account_id IN ({ids}) AND pay_amount_int IN (59900,199900,359800) AND order_status IN (3,4) AND pay_success_date IS NOT NULL"):
|
||||
if len(r) >= 7:
|
||||
aid = r[6]
|
||||
phone_orders.setdefault(aid, []).append({"id":r[0],"trade_no":r[1],"amount":int(r[2]),"pay_date":r[3],"key_from":r[4],"status":r[5]})
|
||||
|
||||
# Step 4: Get ALL orders for all gap dates (broader query, no keyfrom filter)
|
||||
all_dates = set()
|
||||
for g in gaps:
|
||||
d = parse_date(g[4])
|
||||
if d:
|
||||
all_dates.add(d)
|
||||
|
||||
date_orders = {} # (date, amount) -> list of orders
|
||||
if all_dates:
|
||||
date_list = ",".join([f"'{d}'" for d in sorted(all_dates)])
|
||||
sql = f"SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD'), o.key_from, o.order_status, o.account_id, a.tel FROM bi_vala_order o JOIN bi_vala_app_account a ON o.account_id=a.id WHERE a.status=1 AND o.order_status IN (3,4) AND o.pay_success_date::date IN ({date_list}) AND o.pay_amount_int IN (59900,199900,359800)"
|
||||
for r in q(sql):
|
||||
if len(r) >= 8:
|
||||
key = (r[3], int(r[2]))
|
||||
date_orders.setdefault(key, []).append({"id":r[0],"trade_no":r[1],"amount":int(r[2]),"pay_date":r[3],"key_from":r[4],"status":r[5],"account_id":r[6],"tel":r[7]})
|
||||
|
||||
# Step 5: Get refunds for all matched accounts
|
||||
all_aids = set()
|
||||
for aid, orders in phone_orders.items():
|
||||
all_aids.add(aid)
|
||||
for orders in date_orders.values():
|
||||
for o in orders:
|
||||
all_aids.add(o["account_id"])
|
||||
|
||||
refunds = {}
|
||||
if all_aids:
|
||||
ids = ",".join(all_aids)
|
||||
for r in q(f"SELECT o.account_id, SUM(rf.refund_amount_int) FROM bi_refund_order rf JOIN bi_vala_order o ON rf.trade_no=o.trade_no WHERE o.account_id IN ({ids}) AND rf.status=3 GROUP BY o.account_id"):
|
||||
if len(r) >= 2 and r[1]:
|
||||
refunds[r[0]] = int(r[1])
|
||||
|
||||
# Step 6: Match each gap
|
||||
for g in gaps:
|
||||
idx, month, sales, nick, date_str, amount, channel, phone, keyfrom, is_direct = g
|
||||
d = parse_date(date_str)
|
||||
amt = amount * 100
|
||||
|
||||
found = None
|
||||
|
||||
# Try phone match
|
||||
if phone and phone in phone_enc:
|
||||
enc = phone_enc[phone]
|
||||
aid = phone_to_aid.get(enc)
|
||||
if aid and aid in phone_orders:
|
||||
for o in phone_orders[aid]:
|
||||
if o["amount"] == amt:
|
||||
found = o
|
||||
break
|
||||
|
||||
# Try keyfrom+date+amount
|
||||
if not found and d and keyfrom:
|
||||
candidates = date_orders.get((d, amt), [])
|
||||
if "%" in keyfrom:
|
||||
like = keyfrom.replace("%","")
|
||||
for o in candidates:
|
||||
if like in o["key_from"]:
|
||||
found = o
|
||||
break
|
||||
else:
|
||||
for o in candidates:
|
||||
if o["key_from"] == keyfrom:
|
||||
found = o
|
||||
break
|
||||
|
||||
# If still not found, try date+amount only (any keyfrom)
|
||||
if not found and d:
|
||||
candidates = date_orders.get((d, amt), [])
|
||||
if candidates:
|
||||
found = candidates[0] # Take first match
|
||||
|
||||
gsv = 0
|
||||
if found:
|
||||
aid = found.get("account_id","")
|
||||
refund = refunds.get(aid, 0)
|
||||
gsv = found["amount"] - refund
|
||||
|
||||
status = "有" if found else "无"
|
||||
should = "是" if (found and gsv > 0 and not is_direct) else "否"
|
||||
|
||||
print(f"{idx}. [{month}] {sales} {nick} | {date_str} ¥{amount} {channel} | {status} | GSV={gsv/100:.0f} | 应进Bot={should}")
|
||||
if found:
|
||||
print(f" order_id={found['id']} {found.get('pay_date','')} ¥{found['amount']/100:.0f} {found.get('key_from','')[:60]} status={found.get('status','')}")
|
||||
147
scripts/check_gap_57_v5.py
Normal file
147
scripts/check_gap_57_v5.py
Normal file
@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check 57 gaps - one query per gap to avoid truncation"""
|
||||
import subprocess, os, sys
|
||||
sys.path.insert(0, '/root/.openclaw/workspace')
|
||||
|
||||
PGPASS = "LdfjdjL83h3h3^$&**YGG*"
|
||||
DB = ["psql","-h","bj-postgres-16pob4sg.sql.tencentcdb.com","-p","28591","-U","ai_member","-d","vala_bi"]
|
||||
ENV = {**os.environ, "PGPASSWORD": PGPASS}
|
||||
|
||||
def q(sql):
|
||||
r = subprocess.run(DB + ["-c", sql], env=ENV, capture_output=True, text=True, timeout=15)
|
||||
rows = []
|
||||
for line in r.stdout.strip().split("\n")[2:-1]:
|
||||
parts = [p.strip() for p in line.split("|")]
|
||||
rows.append(parts)
|
||||
return rows
|
||||
|
||||
gaps = [
|
||||
(1,"3月","小龙","雪珂💗","3月6日",1999,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(2,"3月","小龙","Mars(燚)","3月7日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(3,"3月","小龙","薇薇","3月",1999,"小红书直购","13520306626","newmedia-dianpu-xhs-0-0",True),
|
||||
(4,"3月","小龙","Yeah~^_^","3月20日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(5,"3月","小龙","TutuTu","3月",1999,"小红书直购","18107332677","newmedia-dianpu-xhs-0-0",True),
|
||||
(6,"3月","小龙","EFFIE","3月25日",3598,"微信小店","","newmedia-dianpu-xhs-0-0",False),
|
||||
(7,"3月","Tom","JeanneLᴇᴇ🦄","3月4日",3598,"微信小店","","newmedia-dianpu-wxxd-0-0",False),
|
||||
(8,"3月","Tom","薇妮姐","3月8日",599,"端内","","app-active-h5-0-0",False),
|
||||
(9,"3月","Tom","欣","3月7日",599,"端内","","app-active-h5-0-0",False),
|
||||
(10,"3月","Bob","Mogu","3月6日",599,"端内","","app-active-h5-0-0",False),
|
||||
(11,"3月","Bob","L. 一颗夹星糖🌟","3月12日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(12,"3月","Tom","阿雅呀","3月15日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(13,"3月","Tom","Anna","3月4日",1999,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(14,"3月","Bob","Echo Liang","3月15日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(15,"3月","Tom","幼兒園高材生🍼","3月23日",3598,"微信小店","13055770067","sales-adp-cd-yy-0",False),
|
||||
(16,"3月","Tom","Nancy","3月26日",599,"端内","","app-active-h5-0-0",False),
|
||||
(17,"3月","Tom","依米","3月30日",3598,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(18,"3月","Bob","zhouyun","3月6日",1999,"小红书-学霸老王","13588706769","newmedia-daren-xhs-学霸老王讲真话-0",False),
|
||||
(19,"3月","Tom","💗小超人棒棒哒🍭","3月29日",3598,"小红书-晚柠","18630368296","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(20,"3月","Bob","鹿","3月14日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(21,"4月","小龙","琳溪","4月19日",3598,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(22,"4月","小龙","小丽","4月26日",599,"端内","","app-active-h5-0-0",False),
|
||||
(23,"4月","小龙","子曦","4月16日",3598,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(24,"4月","小龙","Gaᴗao","4月24日",3598,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(25,"4月","吴迪","彩让措","2026/4/26",599,"端内","","app-active-h5-0-0",False),
|
||||
(26,"4月","吴迪","莉筱雅","2026/4/27",1999,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(27,"4月","吴迪","爱吃巧克力","2026/4/24",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(28,"4月","吴迪","Aa~Jessie💝","2026/4/27",1999,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(29,"4月","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","sales-adp-cd-yy-0",False),
|
||||
(30,"4月","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","sales-adp-cd-yy-0",False),
|
||||
(31,"4月","Tom","静静是我🍃","4月8日",1999,"小红书-学霸老王","15975769851","partner-actives-0-0-0",False),
|
||||
(32,"4月","Bob","胆大鬼","4月8日",3598,"小红书-学霸老王","15262255267","newmedia-daren-xhs-学霸老王讲真话-0",False),
|
||||
(33,"4月","Tom","希Cissy-427","4月27日",3598,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(34,"4月","Tom","Kerry","4月9日",3598,"微信小店","18328334683","sales-adp-cd-yy-0",False),
|
||||
(35,"4月","Tom","SHAN_Q_Q","4月1日",3598,"小红书-官店","","newmedia-dianpu-xhs-0-0",True),
|
||||
(36,"5月","小龙","Sia","5月9日",599,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(37,"5月","吴迪","璐","2026/5/9",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(38,"5月","吴迪","^_^","2026/5/16",3598,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(39,"5月","吴迪","🌸白色铃兰🌸","2026/5/17",3598,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(40,"5月","吴迪","咔咔","2026/5/7",3598,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(41,"5月","吴迪","梦马","2026/5/21",3598,"小红书","","newmedia-dianpu-xhs-0-0",False),
|
||||
(42,"5月","吴迪","梦马","2026/5/21",3598,"小红书","","newmedia-dianpu-xhs-0-0",False),
|
||||
(43,"5月","吴迪","小西瓜","2026/5/30",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(44,"5月","吴迪","璐","2026/5/9",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(45,"5月","Bob","Yuki-515","5月15日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(46,"5月","Tom","冬-515","5月15日",1999,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(47,"5月","Bob","微笑向暖","5月4日",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(48,"5月","Bob","cici-511","5月11日",1999,"微信小店","","sales-adp-cd-xsy-0",False),
|
||||
(49,"5月","Tom","🐷-519","5月19日",1999,"小红书-宣儿妈妈","","newmedia-daren-xhs-宣儿妈妈%",False),
|
||||
(50,"5月","Bob","妃-516","5月16日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(51,"5月","Tom","黄晔-516","5月16日",3598,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(52,"5月","Tom","朵朵呀!","5月25日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(53,"5月","Tom","雷鸣-414","5月14日",599,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(54,"5月","Tom","毛阿毛🐱-520","5月20日",1999,"小红书-官店","","newmedia-dianpu-xhs-0-0",True),
|
||||
(55,"5月","Tom","____Miss_y-519","5月19日",599,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(56,"5月","Tom","Mandy-526","5月26日",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(57,"5月","Bob","Yoki-529","5月29日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
]
|
||||
|
||||
def parse_date(d):
|
||||
d = d.replace("日","").replace("月","/").replace(" ","").strip()
|
||||
if "/" in d:
|
||||
parts = d.split("/")
|
||||
if len(parts) >= 2 and parts[1]:
|
||||
return f"2026-{int(parts[0]):02d}-{int(parts[1]):02d}"
|
||||
return None
|
||||
|
||||
from scripts.phone_encrypt import encrypt_phone
|
||||
|
||||
# Pre-encrypt phones
|
||||
phone_enc = {}
|
||||
for g in gaps:
|
||||
if g[7]:
|
||||
phone_enc[g[7]] = encrypt_phone(g[7])
|
||||
|
||||
# Get account IDs for phones
|
||||
phone_to_aid = {}
|
||||
if phone_enc:
|
||||
conds = " OR ".join([f"tel_encrypt LIKE '{v}%'" for v in phone_enc.values()])
|
||||
for r in q(f"SELECT id, tel_encrypt FROM bi_vala_app_account WHERE status=1 AND ({conds})"):
|
||||
if len(r) >= 2:
|
||||
phone_to_aid[r[1]] = r[0]
|
||||
|
||||
# For each gap, query individually
|
||||
for g in gaps:
|
||||
idx, month, sales, nick, date_str, amount, channel, phone, keyfrom, is_direct = g
|
||||
d = parse_date(date_str)
|
||||
amt = amount * 100
|
||||
|
||||
found = None
|
||||
|
||||
# Phone match
|
||||
if phone and phone in phone_enc:
|
||||
enc = phone_enc[phone]
|
||||
aid = phone_to_aid.get(enc)
|
||||
if aid:
|
||||
rows = q(f"SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD'), o.key_from, o.order_status FROM bi_vala_order o WHERE o.account_id={aid} AND o.pay_amount_int={amt} AND o.order_status IN (3,4) AND o.pay_success_date IS NOT NULL ORDER BY o.pay_success_date LIMIT 5")
|
||||
for r in rows:
|
||||
if len(r) >= 6:
|
||||
found = {"id":r[0],"trade_no":r[1],"amount":int(r[2]),"pay_date":r[3],"key_from":r[4],"status":r[5],"account_id":aid}
|
||||
break
|
||||
|
||||
# Keyfrom + date match (±1 day)
|
||||
if not found and d and keyfrom:
|
||||
if "%" in keyfrom:
|
||||
like = keyfrom.replace("%","")
|
||||
rows = q(f"SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD'), o.key_from, o.order_status, o.account_id FROM bi_vala_order o JOIN bi_vala_app_account a ON o.account_id=a.id WHERE a.status=1 AND o.order_status IN (3,4) AND o.pay_success_date::date BETWEEN '{d}'::date-1 AND '{d}'::date+1 AND o.pay_amount_int={amt} AND o.key_from LIKE '%{like}%' LIMIT 3")
|
||||
else:
|
||||
rows = q(f"SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD'), o.key_from, o.order_status, o.account_id FROM bi_vala_order o JOIN bi_vala_app_account a ON o.account_id=a.id WHERE a.status=1 AND o.order_status IN (3,4) AND o.pay_success_date::date BETWEEN '{d}'::date-1 AND '{d}'::date+1 AND o.pay_amount_int={amt} AND o.key_from='{keyfrom}' LIMIT 3")
|
||||
if rows and len(rows[0]) >= 7:
|
||||
r = rows[0]
|
||||
found = {"id":r[0],"trade_no":r[1],"amount":int(r[2]),"pay_date":r[3],"key_from":r[4],"status":r[5],"account_id":r[6]}
|
||||
|
||||
# Get refund
|
||||
gsv = 0
|
||||
if found:
|
||||
aid = found.get("account_id","")
|
||||
rows = q(f"SELECT SUM(rf.refund_amount_int) FROM bi_refund_order rf JOIN bi_vala_order o ON rf.trade_no=o.trade_no WHERE o.account_id={aid} AND rf.status=3")
|
||||
refund = 0
|
||||
if rows and rows[0] and rows[0][0] and rows[0][0].isdigit():
|
||||
refund = int(rows[0][0])
|
||||
gsv = found["amount"] - refund
|
||||
|
||||
status = "有" if found else "无"
|
||||
should = "是" if (found and gsv > 0 and not is_direct) else "否"
|
||||
|
||||
print(f"{idx}. [{month}] {sales} {nick} | {date_str} ¥{amount} {channel} | {status} | GSV={gsv/100:.0f} | 应进Bot={should}")
|
||||
if found:
|
||||
print(f" order_id={found['id']} {found.get('pay_date','')} ¥{found['amount']/100:.0f} {found.get('key_from','')[:60]} status={found.get('status','')}")
|
||||
172
scripts/check_gap_57_v6.py
Normal file
172
scripts/check_gap_57_v6.py
Normal file
@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check 57 gaps v6 - correct refund per-order, proper matching"""
|
||||
import subprocess, os, sys
|
||||
sys.path.insert(0, '/root/.openclaw/workspace')
|
||||
|
||||
PGPASS = "LdfjdjL83h3h3^$&**YGG*"
|
||||
DB = ["psql","-h","bj-postgres-16pob4sg.sql.tencentcdb.com","-p","28591","-U","ai_member","-d","vala_bi"]
|
||||
ENV = {**os.environ, "PGPASSWORD": PGPASS}
|
||||
|
||||
def q(sql):
|
||||
r = subprocess.run(DB + ["-c", sql], env=ENV, capture_output=True, text=True, timeout=15)
|
||||
rows = []
|
||||
for line in r.stdout.strip().split("\n")[2:-1]:
|
||||
parts = [p.strip() for p in line.split("|")]
|
||||
rows.append(parts)
|
||||
return rows
|
||||
|
||||
gaps = [
|
||||
(1,"3月","小龙","雪珂💗","3月6日",1999,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(2,"3月","小龙","Mars(燚)","3月7日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(3,"3月","小龙","薇薇","3月",1999,"小红书直购","13520306626","newmedia-dianpu-xhs-0-0",True),
|
||||
(4,"3月","小龙","Yeah~^_^","3月20日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(5,"3月","小龙","TutuTu","3月",1999,"小红书直购","18107332677","newmedia-dianpu-xhs-0-0",True),
|
||||
(6,"3月","小龙","EFFIE","3月25日",3598,"微信小店","","newmedia-dianpu-xhs-0-0",False),
|
||||
(7,"3月","Tom","JeanneLᴇᴇ🦄","3月4日",3598,"微信小店","","newmedia-dianpu-wxxd-0-0",False),
|
||||
(8,"3月","Tom","薇妮姐","3月8日",599,"端内","","app-active-h5-0-0",False),
|
||||
(9,"3月","Tom","欣","3月7日",599,"端内","","app-active-h5-0-0",False),
|
||||
(10,"3月","Bob","Mogu","3月6日",599,"端内","","app-active-h5-0-0",False),
|
||||
(11,"3月","Bob","L. 一颗夹星糖🌟","3月12日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(12,"3月","Tom","阿雅呀","3月15日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(13,"3月","Tom","Anna","3月4日",1999,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(14,"3月","Bob","Echo Liang","3月15日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(15,"3月","Tom","幼兒園高材生🍼","3月23日",3598,"微信小店","13055770067","sales-adp-cd-yy-0",False),
|
||||
(16,"3月","Tom","Nancy","3月26日",599,"端内","","app-active-h5-0-0",False),
|
||||
(17,"3月","Tom","依米","3月30日",3598,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(18,"3月","Bob","zhouyun","3月6日",1999,"小红书-学霸老王","13588706769","newmedia-daren-xhs-学霸老王讲真话-0",False),
|
||||
(19,"3月","Tom","💗小超人棒棒哒🍭","3月29日",3598,"小红书-晚柠","18630368296","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(20,"3月","Bob","鹿","3月14日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(21,"4月","小龙","琳溪","4月19日",3598,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(22,"4月","小龙","小丽","4月26日",599,"端内","","app-active-h5-0-0",False),
|
||||
(23,"4月","小龙","子曦","4月16日",3598,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(24,"4月","小龙","Gaᴗao","4月24日",3598,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(25,"4月","吴迪","彩让措","2026/4/26",599,"端内","","app-active-h5-0-0",False),
|
||||
(26,"4月","吴迪","莉筱雅","2026/4/27",1999,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(27,"4月","吴迪","爱吃巧克力","2026/4/24",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(28,"4月","吴迪","Aa~Jessie💝","2026/4/27",1999,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(29,"4月","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","sales-adp-cd-yy-0",False),
|
||||
(30,"4月","吴迪","🐷","2026/4/26",3598,"宣儿妈妈-小红书","","sales-adp-cd-yy-0",False),
|
||||
(31,"4月","Tom","静静是我🍃","4月8日",1999,"小红书-学霸老王","15975769851","partner-actives-0-0-0",False),
|
||||
(32,"4月","Bob","胆大鬼","4月8日",3598,"小红书-学霸老王","15262255267","newmedia-daren-xhs-学霸老王讲真话-0",False),
|
||||
(33,"4月","Tom","希Cissy-427","4月27日",3598,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(34,"4月","Tom","Kerry","4月9日",3598,"微信小店","18328334683","sales-adp-cd-yy-0",False),
|
||||
(35,"4月","Tom","SHAN_Q_Q","4月1日",3598,"小红书-官店","","newmedia-dianpu-xhs-0-0",True),
|
||||
(36,"5月","小龙","Sia","5月9日",599,"微信小店","","sales-adp-bj-jxl-0",False),
|
||||
(37,"5月","吴迪","璐","2026/5/9",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(38,"5月","吴迪","^_^","2026/5/16",3598,"晚柠-小红书","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(39,"5月","吴迪","🌸白色铃兰🌸","2026/5/17",3598,"抖音","","newmedia-dianpu-douyin-0-0",True),
|
||||
(40,"5月","吴迪","咔咔","2026/5/7",3598,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(41,"5月","吴迪","梦马","2026/5/21",3598,"小红书","","newmedia-dianpu-xhs-0-0",False),
|
||||
(42,"5月","吴迪","梦马","2026/5/21",3598,"小红书","","newmedia-dianpu-xhs-0-0",False),
|
||||
(43,"5月","吴迪","小西瓜","2026/5/30",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(44,"5月","吴迪","璐","2026/5/9",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(45,"5月","Bob","Yuki-515","5月15日",3598,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(46,"5月","Tom","冬-515","5月15日",1999,"小红书-晚柠","","newmedia-daren-xhs-晚柠也是个妈妈了-0",False),
|
||||
(47,"5月","Bob","微笑向暖","5月4日",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(48,"5月","Bob","cici-511","5月11日",1999,"微信小店","","sales-adp-cd-xsy-0",False),
|
||||
(49,"5月","Tom","🐷-519","5月19日",1999,"小红书-宣儿妈妈","","newmedia-daren-xhs-宣儿妈妈%",False),
|
||||
(50,"5月","Bob","妃-516","5月16日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(51,"5月","Tom","黄晔-516","5月16日",3598,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(52,"5月","Tom","朵朵呀!","5月25日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
(53,"5月","Tom","雷鸣-414","5月14日",599,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(54,"5月","Tom","毛阿毛🐱-520","5月20日",1999,"小红书-官店","","newmedia-dianpu-xhs-0-0",True),
|
||||
(55,"5月","Tom","____Miss_y-519","5月19日",599,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(56,"5月","Tom","Mandy-526","5月26日",1999,"微信小店","","sales-adp-bj-wd-0",False),
|
||||
(57,"5月","Bob","Yoki-529","5月29日",1999,"微信小店","","sales-adp-cd-zjf-0",False),
|
||||
]
|
||||
|
||||
def parse_date(d):
|
||||
d = d.replace("日","").replace("月","/").replace(" ","").strip()
|
||||
if "/" in d:
|
||||
parts = d.split("/")
|
||||
if len(parts) >= 2 and parts[1]:
|
||||
return f"2026-{int(parts[0]):02d}-{int(parts[1]):02d}"
|
||||
return None
|
||||
|
||||
from scripts.phone_encrypt import encrypt_phone
|
||||
|
||||
# Pre-encrypt phones
|
||||
phone_enc = {}
|
||||
for g in gaps:
|
||||
if g[7]:
|
||||
phone_enc[g[7]] = encrypt_phone(g[7])
|
||||
|
||||
# Get account IDs for phones
|
||||
phone_to_aid = {}
|
||||
if phone_enc:
|
||||
conds = " OR ".join([f"tel_encrypt LIKE '{v}%'" for v in phone_enc.values()])
|
||||
for r in q(f"SELECT id, tel_encrypt FROM bi_vala_app_account WHERE status=1 AND ({conds})"):
|
||||
if len(r) >= 2:
|
||||
phone_to_aid[r[1]] = r[0]
|
||||
|
||||
# For each phone-matched account, get ALL orders + refunds
|
||||
phone_all = {} # aid -> {orders: [...], refunds_by_trade: {...}}
|
||||
for aid in phone_to_aid.values():
|
||||
orders = []
|
||||
for r in q(f"SELECT id, trade_no, pay_amount_int, to_char(pay_success_date,'YYYY-MM-DD'), key_from, order_status FROM bi_vala_order WHERE account_id={aid} AND pay_amount_int IN (59900,199900,359800) AND order_status IN (3,4) AND pay_success_date IS NOT NULL ORDER BY pay_success_date"):
|
||||
if len(r) >= 6:
|
||||
orders.append({"id":r[0],"trade_no":r[1],"amount":int(r[2]),"pay_date":r[3],"key_from":r[4],"status":r[5]})
|
||||
refunds = {}
|
||||
if orders:
|
||||
trades = ",".join([f"'{o['trade_no']}'" for o in orders])
|
||||
for r in q(f"SELECT trade_no, SUM(refund_amount_int) FROM bi_refund_order WHERE trade_no IN ({trades}) AND status=3 GROUP BY trade_no"):
|
||||
if len(r) >= 2 and r[1]:
|
||||
refunds[r[0]] = int(r[1])
|
||||
phone_all[aid] = {"orders": orders, "refunds": refunds}
|
||||
|
||||
# For each gap, query
|
||||
for g in gaps:
|
||||
idx, month, sales, nick, date_str, amount, channel, phone, keyfrom, is_direct = g
|
||||
d = parse_date(date_str)
|
||||
amt = amount * 100
|
||||
|
||||
found = None
|
||||
gsv = 0
|
||||
|
||||
# Phone match - get all matching orders
|
||||
if phone and phone in phone_enc:
|
||||
enc = phone_enc[phone]
|
||||
aid = phone_to_aid.get(enc)
|
||||
if aid and aid in phone_all:
|
||||
matching = [o for o in phone_all[aid]["orders"] if o["amount"] == amt]
|
||||
if matching:
|
||||
# Calculate total GSV: sum all order amounts minus refunds
|
||||
total_amt = sum(o["amount"] for o in phone_all[aid]["orders"])
|
||||
total_refund = sum(phone_all[aid]["refunds"].values())
|
||||
gsv = total_amt - total_refund
|
||||
found = matching[0] # Use first match for display
|
||||
# Show all orders
|
||||
found["all_orders"] = phone_all[aid]["orders"]
|
||||
found["all_refunds"] = phone_all[aid]["refunds"]
|
||||
|
||||
# Keyfrom + date match
|
||||
if not found and d and keyfrom:
|
||||
if "%" in keyfrom:
|
||||
like = keyfrom.replace("%","")
|
||||
rows = q(f"SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD'), o.key_from, o.order_status, o.account_id FROM bi_vala_order o JOIN bi_vala_app_account a ON o.account_id=a.id WHERE a.status=1 AND o.order_status IN (3,4) AND o.pay_success_date::date BETWEEN '{d}'::date-1 AND '{d}'::date+1 AND o.pay_amount_int={amt} AND o.key_from LIKE '%{like}%' LIMIT 3")
|
||||
else:
|
||||
rows = q(f"SELECT o.id, o.trade_no, o.pay_amount_int, to_char(o.pay_success_date,'YYYY-MM-DD'), o.key_from, o.order_status, o.account_id FROM bi_vala_order o JOIN bi_vala_app_account a ON o.account_id=a.id WHERE a.status=1 AND o.order_status IN (3,4) AND o.pay_success_date::date BETWEEN '{d}'::date-1 AND '{d}'::date+1 AND o.pay_amount_int={amt} AND o.key_from='{keyfrom}' LIMIT 3")
|
||||
if rows and len(rows[0]) >= 7:
|
||||
r = rows[0]
|
||||
aid = r[6]
|
||||
trade = r[1]
|
||||
# Get refund for this specific trade
|
||||
ref_rows = q(f"SELECT SUM(refund_amount_int) FROM bi_refund_order WHERE trade_no='{trade}' AND status=3")
|
||||
refund = 0
|
||||
if ref_rows and ref_rows[0] and ref_rows[0][0] and ref_rows[0][0].isdigit():
|
||||
refund = int(ref_rows[0][0])
|
||||
gsv = int(r[2]) - refund
|
||||
found = {"id":r[0],"trade_no":r[1],"amount":int(r[2]),"pay_date":r[3],"key_from":r[4],"status":r[5],"account_id":aid}
|
||||
|
||||
status = "有" if found else "无"
|
||||
should = "是" if (found and gsv > 0 and not is_direct) else "否"
|
||||
|
||||
print(f"{idx}. [{month}] {sales} {nick} | {date_str} ¥{amount} {channel} | {status} | GSV={gsv/100:.0f} | 应进Bot={should}")
|
||||
if found:
|
||||
if "all_orders" in found:
|
||||
for o in found["all_orders"]:
|
||||
ref = found["all_refunds"].get(o["trade_no"], 0)
|
||||
net = o["amount"] - ref
|
||||
print(f" order_id={o['id']} {o['pay_date']} ¥{o['amount']/100:.0f} {o['key_from'][:50]} status={o['status']} 退={ref/100:.0f} 净={net/100:.0f}")
|
||||
else:
|
||||
print(f" order_id={found['id']} {found.get('pay_date','')} ¥{found['amount']/100:.0f} {found.get('key_from','')[:60]} status={found.get('status','')}")
|
||||
Loading…
Reference in New Issue
Block a user