ai_member_xiaoxi/scripts/check_gap_57_v4.py
2026-06-15 08:00:01 +08:00

194 lines
11 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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','')}")