198 lines
11 KiB
Python
198 lines
11 KiB
Python
#!/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','')}")
|