77 lines
4.2 KiB
Python
77 lines
4.2 KiB
Python
"""以同一主账号的实际数据请求新旧明细导出,并逐单元格核对,文件保留在仓库外。"""
|
|
|
|
import argparse
|
|
import decimal
|
|
import io
|
|
import json
|
|
import time
|
|
import urllib.parse
|
|
import urllib.request
|
|
from pathlib import Path
|
|
|
|
import openpyxl
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--runtime", type=Path, required=True)
|
|
parser.add_argument("--old-url", default="http://127.0.0.1:18080")
|
|
parser.add_argument("--new-url", default="http://127.0.0.1:19001")
|
|
parser.add_argument("--output", type=Path, required=True)
|
|
args = parser.parse_args()
|
|
if args.runtime.resolve().is_relative_to(Path(__file__).resolve().parents[1]):
|
|
raise ValueError("导出文件必须保存在仓库外")
|
|
client = json.loads((args.runtime / "legacy-client.json").read_text(encoding="utf-8"))["client_id"]
|
|
headers = [{"Authorization": "Bearer " + (args.runtime / "legacy-admin.token").read_text().strip(), "clientid": client},
|
|
{"x-token": (args.runtime / "new-admin.token").read_text().strip()}]
|
|
reports = []
|
|
for kind, time_key in (("register", "Register"), ("spend", "Pay")):
|
|
params = {"sourceDb": "lx", "pageSize": 10, "begin" + time_key + "Time": "2026-11-03", "end" + time_key + "Time": "2026-11-03"}
|
|
request = urllib.request.Request(args.new_url + "/sw/" + kind + "/list?" + urllib.parse.urlencode(params), headers=headers[1])
|
|
with urllib.request.urlopen(request, timeout=60) as response:
|
|
body = json.load(response)
|
|
if body.get("code") != 0:
|
|
raise RuntimeError("读取导出样本失败:" + kind)
|
|
sample = next(row for row in body["data"]["rows"] if row.get("userId") is not None)
|
|
params["userId"] = sample["userId"]
|
|
sheets, durations = [], []
|
|
for i, base in enumerate((args.old_url, args.new_url)):
|
|
payload = urllib.parse.urlencode(params).encode()
|
|
request = urllib.request.Request(base + ("/system/" if i == 0 else "/sw/") + kind + "/export", data=payload,
|
|
headers={**headers[i], "Content-Type": "application/x-www-form-urlencoded"}, method="POST")
|
|
started = time.monotonic()
|
|
with urllib.request.urlopen(request, timeout=120) as response:
|
|
raw = response.read()
|
|
durations.append(round((time.monotonic() - started) * 1000))
|
|
if not raw.startswith(b"PK"):
|
|
raise RuntimeError("导出未返回工作簿:" + kind + "/" + str(i))
|
|
(args.runtime / (("legacy-" if i == 0 else "new-") + kind + "-export.xlsx")).write_bytes(raw)
|
|
workbook = openpyxl.load_workbook(io.BytesIO(raw), read_only=True, data_only=True)
|
|
sheets.append(list(workbook.worksheets[0].values))
|
|
workbook.close()
|
|
differences = []
|
|
for row_number, (old, new) in enumerate(zip(*sheets), 1):
|
|
if len(old) != len(new):
|
|
differences.append({"row": row_number, "kind": "columns"})
|
|
for col, (a, b) in enumerate(zip(old, new), 1):
|
|
if a == b or (a in (None, "") and b in (None, "")):
|
|
continue
|
|
if isinstance(a, (int, float)) or isinstance(b, (int, float)):
|
|
try:
|
|
if decimal.Decimal(str(a)) == decimal.Decimal(str(b)):
|
|
continue
|
|
except decimal.InvalidOperation:
|
|
pass
|
|
differences.append({"row": row_number, "column": col, "kind": "value"})
|
|
rows = [len(sheet) - 1 for sheet in sheets]
|
|
reports.append({"kind": kind, "rows": rows, "columns": [len(sheet[0]) for sheet in sheets], "elapsed_ms": durations,
|
|
"differences": differences, "passed": rows[0] > 0 and rows[0] == rows[1] and not differences})
|
|
print(json.dumps(reports[-1], ensure_ascii=False), flush=True)
|
|
args.output.write_text(json.dumps({"checks": reports, "passed": all(row["passed"] for row in reports)}, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
|
if not all(row["passed"] for row in reports):
|
|
raise SystemExit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|