155 lines
5.3 KiB
Python
155 lines
5.3 KiB
Python
"""DEBUG 联调发现的问题。一次性脚本。"""
|
|
import psycopg2, psycopg2.extras, os, json
|
|
from dotenv import load_dotenv
|
|
from pathlib import Path
|
|
|
|
load_dotenv(Path(__file__).resolve().parents[2] / ".env")
|
|
dsn = os.environ["PG_DSN"]
|
|
conn = psycopg2.connect(dsn)
|
|
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
|
|
|
print("=" * 60)
|
|
print("1. dwd.dwd_settlement_head 中 member 相关列")
|
|
print("=" * 60)
|
|
cur.execute("""
|
|
SELECT column_name, data_type
|
|
FROM information_schema.columns
|
|
WHERE table_schema='dwd' AND table_name='dwd_settlement_head'
|
|
AND column_name LIKE '%%member%%'
|
|
ORDER BY ordinal_position
|
|
""")
|
|
for r in cur.fetchall():
|
|
print(f" {r['column_name']} ({r['data_type']})")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("2. dws_member_consumption_summary 金额负值记录")
|
|
print("=" * 60)
|
|
# 先查表结构
|
|
cur.execute("""
|
|
SELECT column_name FROM information_schema.columns
|
|
WHERE table_schema='dws' AND table_name='dws_member_consumption_summary'
|
|
AND column_name LIKE '%%consume%%' OR (table_schema='dws' AND table_name='dws_member_consumption_summary' AND column_name LIKE '%%amount%%')
|
|
ORDER BY ordinal_position
|
|
""")
|
|
print(" consume/amount 相关列:")
|
|
for r in cur.fetchall():
|
|
print(f" {r['column_name']}")
|
|
|
|
conn.rollback()
|
|
cur.execute("""
|
|
SELECT member_id, total_consume_amount, site_id
|
|
FROM dws.dws_member_consumption_summary
|
|
WHERE total_consume_amount < 0
|
|
ORDER BY total_consume_amount
|
|
LIMIT 3
|
|
""")
|
|
neg_rows = cur.fetchall()
|
|
for r in neg_rows:
|
|
print(f" member_id={r['member_id']}, amount={r['total_consume_amount']}, site={r['site_id']}")
|
|
|
|
neg_member = neg_rows[0]['member_id'] if neg_rows else None
|
|
neg_site = neg_rows[0]['site_id'] if neg_rows else None
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("3. 追溯负值会员的上游数据链")
|
|
print("=" * 60)
|
|
if neg_member is None:
|
|
print(" 无负值记录,跳过")
|
|
else:
|
|
# 先查 dwd_payment 的 member 相关列
|
|
conn.rollback()
|
|
cur.execute("""
|
|
SELECT column_name FROM information_schema.columns
|
|
WHERE table_schema='dwd' AND table_name='dwd_payment'
|
|
AND column_name LIKE '%%member%%'
|
|
""")
|
|
pay_member_cols = [r['column_name'] for r in cur.fetchall()]
|
|
print(f" dwd_payment member 列: {pay_member_cols}")
|
|
|
|
# 查 dwd_settlement_head 中该会员的结算记录
|
|
cur.execute("""
|
|
SELECT column_name FROM information_schema.columns
|
|
WHERE table_schema='dwd' AND table_name='dwd_settlement_head'
|
|
AND (column_name LIKE '%%amount%%' OR column_name LIKE '%%total%%')
|
|
""")
|
|
settle_amt_cols = [r['column_name'] for r in cur.fetchall()]
|
|
print(f" dwd_settlement_head amount/total 列: {settle_amt_cols}")
|
|
|
|
# 用实际列名查
|
|
if settle_amt_cols:
|
|
amt_col = settle_amt_cols[0]
|
|
cur.execute(f"""
|
|
SELECT COUNT(*) as cnt, SUM({amt_col}) as total,
|
|
MIN({amt_col}) as min_amt, MAX({amt_col}) as max_amt
|
|
FROM dwd.dwd_settlement_head
|
|
WHERE member_id = %s AND site_id = %s
|
|
""", (neg_member, neg_site))
|
|
r = cur.fetchone()
|
|
print(f" dwd_settlement_head ({amt_col}): {r['cnt']} 条, 总额={r['total']}, min={r['min_amt']}, max={r['max_amt']}")
|
|
|
|
# 查该会员的退款
|
|
cur.execute("""
|
|
SELECT column_name FROM information_schema.columns
|
|
WHERE table_schema='dwd' AND table_name='dwd_refund'
|
|
AND column_name LIKE '%%member%%'
|
|
""")
|
|
refund_member_cols = [r['column_name'] for r in cur.fetchall()]
|
|
print(f" dwd_refund member 列: {refund_member_cols}")
|
|
|
|
# 查 DWS 汇总的完整记录
|
|
cur.execute("""
|
|
SELECT * FROM dws.dws_member_consumption_summary
|
|
WHERE member_id = %s AND site_id = %s
|
|
""", (neg_member, neg_site))
|
|
row = cur.fetchone()
|
|
if row:
|
|
print(f" dws_member_consumption_summary 完整记录:")
|
|
for k, v in row.items():
|
|
if v is not None and str(v) != '0' and str(v) != '0.00':
|
|
print(f" {k} = {v}")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("4. API_SAMPLE_CACHE_ROOT 检查")
|
|
print("=" * 60)
|
|
api_cache = os.environ.get("API_SAMPLE_CACHE_ROOT", "NOT SET")
|
|
print(f" API_SAMPLE_CACHE_ROOT = {api_cache}")
|
|
if api_cache != "NOT SET":
|
|
p = Path(api_cache)
|
|
print(f" exists: {p.exists()}")
|
|
if p.exists():
|
|
files = list(p.glob("*.json"))
|
|
print(f" json files: {len(files)}")
|
|
for f in files[:10]:
|
|
print(f" {f.name}")
|
|
else:
|
|
print(" 目录不存在 — FlowRunner 内置检查找不到 API JSON 缓存")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("5. FETCH_ROOT (ODS JSON 落盘) 检查")
|
|
print("=" * 60)
|
|
fetch_root = os.environ.get("FETCH_ROOT", "NOT SET")
|
|
print(f" FETCH_ROOT = {fetch_root}")
|
|
if fetch_root != "NOT SET":
|
|
p = Path(fetch_root)
|
|
print(f" exists: {p.exists()}")
|
|
if p.exists():
|
|
subdirs = [d for d in p.iterdir() if d.is_dir()]
|
|
print(f" 子目录数: {len(subdirs)}")
|
|
for d in sorted(subdirs)[:10]:
|
|
print(f" {d.name}/")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("6. FlowRunner 注入 ODS_STAFF_INFO 的来源")
|
|
print("=" * 60)
|
|
print(" ODS_STAFF_INFO 在 ENABLED_ODS_CODES 中: 是")
|
|
print(" ODS_STAFF_INFO 在 task_registry 中: 是 (is_common=True)")
|
|
print(" 但 FlowRunner 的 api_full flow 可能有自己的任务列表注入逻辑")
|
|
print(" 需要检查 flow_runner.py 中 api_full 的任务解析")
|
|
|
|
conn.close()
|