微信小程序页面迁移校验之前 P5任务处理之前

This commit is contained in:
Neo
2026-03-09 01:19:21 +08:00
parent 263bf96035
commit 6e20987d2f
1112 changed files with 153824 additions and 219694 deletions

View File

@@ -0,0 +1,237 @@
# -*- coding: utf-8 -*-
"""
精准抓取复杂订单的原始 JSON 数据。
策略:
- 无时间窗口 endpoint全量分页拉取本地按目标 ID 过滤
- 有时间窗口 endpoint根据订单时间计算最小窗口
- 输出到 EXPORT_ROOT/complex_order_samples/
使用方式:
cd apps/etl/connectors/feiqiu
python C:/NeoZQYY/scripts/ops/fetch_complex_orders.py
"""
from __future__ import annotations
import json
import sys
from datetime import datetime, timedelta
from pathlib import Path
from zoneinfo import ZoneInfo
# 加载 ETL 配置cwd 必须是 apps/etl/connectors/feiqiu
sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "apps" / "etl" / "connectors" / "feiqiu"))
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from ops._env_paths import get_output_path
from config.settings import AppConfig
from api.client import APIClient
TZ = ZoneInfo("Asia/Shanghai")
# 目标结算单 ID多台桌 Top 10 + 多助教 1 个,去重)
TARGET_SETTLE_IDS = {
3074058525934981,
2990834049419973,
2988030668589701,
2985297809476293,
3038949978147525,
3038784012766405,
2996296638500997,
2973323104635077,
3079943731579077,
3077096251540933,
3090257727786373, # 多助教
}
# 目标 order_trade_no按 trade_no 复杂度 Top 10
TARGET_TRADE_NOS = {
3046483289245381,
3089564402716037,
3083627248651781,
3026717319448517,
3022503741327173,
3010113035667909,
2995425896140997,
2988736415615685,
3092230766020741,
3091871356586309,
}
# 合并所有需要关注的 ID
ALL_SETTLE_IDS = TARGET_SETTLE_IDS.copy()
ALL_TRADE_NOS = TARGET_TRADE_NOS.copy()
def fetch_all_pages(client: APIClient, endpoint: str, params: dict, list_key: str | None = None) -> list[dict]:
"""全量分页拉取,返回所有记录。"""
records, _ = client.get_paginated(
endpoint=endpoint,
params=params,
page_size=200,
list_key=list_key,
)
return records
def filter_by_settle_or_trade(records: list[dict], settle_ids: set, trade_nos: set) -> list[dict]:
"""按 order_settle_id 或 order_trade_no 过滤。"""
out = []
for r in records:
sid = r.get("order_settle_id", 0)
tno = r.get("order_trade_no", 0)
if sid in settle_ids or tno in trade_nos:
out.append(r)
return out
def filter_by_relate_id(records: list[dict], settle_ids: set) -> list[dict]:
"""按 relate_id= order_settle_id过滤支付/退款。"""
return [r for r in records if r.get("relate_id", 0) in settle_ids]
def save_json(out_dir: Path, filename: str, data: list[dict], meta: dict | None = None):
"""保存 JSON 文件。"""
payload = {"meta": meta or {}, "count": len(data), "records": data}
fp = out_dir / filename
fp.write_text(json.dumps(payload, ensure_ascii=False, indent=2, default=str), encoding="utf-8")
print(f" → 保存 {fp.name}: {len(data)} 条记录")
def main():
cfg = AppConfig.load()
site_id = cfg.get("app.store_id")
base_url = cfg.get("api.base_url")
token = cfg.get("api.token")
if not token:
raise RuntimeError("API_TOKEN 未配置,请检查 .env")
client = APIClient(base_url=base_url, token=token, timeout=cfg.get("api.timeout_sec", 20))
# 输出目录
export_root = get_output_path("EXPORT_ROOT")
out_dir = export_root / "complex_order_samples"
out_dir.mkdir(parents=True, exist_ok=True)
base_params = {"siteId": site_id}
# 第一步:先拉台桌使用记录,建立 settle_id ↔ trade_no 映射
print("=== 1/7 拉取台桌使用记录 ===")
table_use_all = fetch_all_pages(client, "/Site/GetSiteTableOrderDetails", base_params, "siteTableUseDetailsList")
print(f" 总记录: {len(table_use_all)}")
# 从台桌使用记录中补充 settle_id ↔ trade_no 映射
settle_to_trades: dict[int, set[int]] = {}
trade_to_settle: dict[int, int] = {}
for r in table_use_all:
sid = r.get("order_settle_id", 0)
tno = r.get("order_trade_no", 0)
if sid and tno:
settle_to_trades.setdefault(sid, set()).add(tno)
trade_to_settle[tno] = sid
# 扩展:从 trade_no 反查 settle_id从 settle_id 扩展 trade_no
for tno in list(ALL_TRADE_NOS):
sid = trade_to_settle.get(tno)
if sid:
ALL_SETTLE_IDS.add(sid)
for sid in list(ALL_SETTLE_IDS):
for tno in settle_to_trades.get(sid, set()):
ALL_TRADE_NOS.add(tno)
print(f" 扩展后目标: {len(ALL_SETTLE_IDS)} settle_ids, {len(ALL_TRADE_NOS)} trade_nos")
# 过滤台桌使用记录
table_use = filter_by_settle_or_trade(table_use_all, ALL_SETTLE_IDS, ALL_TRADE_NOS)
save_json(out_dir, "table_fee_transactions.json", table_use, {"endpoint": "/Site/GetSiteTableOrderDetails"})
# 2. 台费折扣
print("\n=== 2/7 拉取台费折扣记录 ===")
discount_all = fetch_all_pages(client, "/Site/GetTaiFeeAdjustList", base_params, "taiFeeAdjustInfos")
print(f" 总记录: {len(discount_all)}")
discount = filter_by_settle_or_trade(discount_all, ALL_SETTLE_IDS, ALL_TRADE_NOS)
save_json(out_dir, "table_fee_discount_records.json", discount, {"endpoint": "/Site/GetTaiFeeAdjustList"})
# 3. 团购核销
print("\n=== 3/7 拉取团购核销记录 ===")
groupbuy_all = fetch_all_pages(client, "/Site/GetSiteTableUseDetails", base_params, "siteTableUseDetailsList")
print(f" 总记录: {len(groupbuy_all)}")
groupbuy = filter_by_settle_or_trade(groupbuy_all, ALL_SETTLE_IDS, ALL_TRADE_NOS)
save_json(out_dir, "group_buy_redemption_records.json", groupbuy, {"endpoint": "/Site/GetSiteTableUseDetails"})
# 4. 商品销售
print("\n=== 4/7 拉取商品销售记录 ===")
goods_all = fetch_all_pages(client, "/TenantGoods/GetGoodsSalesList", base_params, "orderGoodsLedgers")
print(f" 总记录: {len(goods_all)}")
goods = filter_by_settle_or_trade(goods_all, ALL_SETTLE_IDS, ALL_TRADE_NOS)
save_json(out_dir, "store_goods_sales_records.json", goods, {"endpoint": "/TenantGoods/GetGoodsSalesList"})
# 5. 助教服务有时间窗口startTime/endTime
# 计算最小窗口:从目标订单的 create_time 推算
print("\n=== 5/7 拉取助教服务记录 ===")
target_times = []
for r in table_use:
ct = r.get("create_time", "")
if ct:
try:
target_times.append(datetime.strptime(ct, "%Y-%m-%d %H:%M:%S"))
except ValueError:
pass
if target_times:
win_start = min(target_times) - timedelta(hours=24)
win_end = max(target_times) + timedelta(hours=24)
else:
win_start = datetime(2025, 11, 1)
win_end = datetime(2026, 3, 1)
assistant_params = {
"siteId": site_id,
"startTime": win_start.strftime("%Y-%m-%d %H:%M:%S"),
"endTime": win_end.strftime("%Y-%m-%d %H:%M:%S"),
}
assistant_all = fetch_all_pages(client, "/AssistantPerformance/GetOrderAssistantDetails", assistant_params, "orderAssistantDetails")
print(f" 时间窗口: {assistant_params['startTime']} ~ {assistant_params['endTime']}")
print(f" 总记录: {len(assistant_all)}")
assistant = filter_by_settle_or_trade(assistant_all, ALL_SETTLE_IDS, ALL_TRADE_NOS)
save_json(out_dir, "assistant_service_records.json", assistant, {
"endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
"window": {"start": assistant_params["startTime"], "end": assistant_params["endTime"]},
})
# 6. 支付记录有时间窗口StartPayTime/EndPayTime
print("\n=== 6/7 拉取支付记录 ===")
pay_params = {
"siteId": site_id,
"StartPayTime": win_start.strftime("%Y-%m-%d %H:%M:%S"),
"EndPayTime": win_end.strftime("%Y-%m-%d %H:%M:%S"),
}
payment_all = fetch_all_pages(client, "/PayLog/GetPayLogListPage", pay_params)
print(f" 时间窗口: {pay_params['StartPayTime']} ~ {pay_params['EndPayTime']}")
print(f" 总记录: {len(payment_all)}")
payment = filter_by_relate_id(payment_all, ALL_SETTLE_IDS)
save_json(out_dir, "payment_transactions.json", payment, {
"endpoint": "/PayLog/GetPayLogListPage",
"window": {"start": pay_params["StartPayTime"], "end": pay_params["EndPayTime"]},
})
# 7. 退款记录
print("\n=== 7/7 拉取退款记录 ===")
refund_all = fetch_all_pages(client, "/Order/GetRefundPayLogList", base_params)
print(f" 总记录: {len(refund_all)}")
refund = filter_by_relate_id(refund_all, ALL_SETTLE_IDS)
save_json(out_dir, "refund_transactions.json", refund, {"endpoint": "/Order/GetRefundPayLogList"})
# 汇总
print(f"\n{'=' * 60}")
print(f"抓取完成,输出目录: {out_dir}")
print(f"目标结算单: {len(ALL_SETTLE_IDS)}")
print(f"目标台桌订单: {len(ALL_TRADE_NOS)}")
print(f"文件列表:")
for f in sorted(out_dir.glob("*.json")):
data = json.loads(f.read_text(encoding="utf-8"))
print(f" {f.name}: {data.get('count', '?')}")
if __name__ == "__main__":
main()