- tests/core: 新增 BaseHttpClient 统一 HTTP 封装(直连绕行/超时/日志/自定义编码); db_helper 追加 Db 长连接类(事务/mogrify/自动重连),既有函数不动 - tests/apis/yun8: 21 个 step 方法按域拆分为 5 个 Mixin(driver/accounting/ audit_payment/receipt/third_party),Yun8Pipeline 24 步编排原样迁移, SQL 全部参数化并集中至 sql_templates - tests/api: 5 阶段有序 P0 E2E 用例(业务失败由 print 改为真实报错)+ README 迁移(删除明文密码段,修正步骤编号漂移) - yun8_sync 目录退役:配置并入 test_config.yaml 的 yun8_api 段; 造数 CLI 保留(python -m tests.apis.yun8.cli,兼容旧 config.yaml 结构) - pytest.ini 注册 api/yun8_sync marker;requirements.txt 补 requests>=2.28 - 静态验证: compileall / 全仓 collect 24 条 / marker 过滤 / CLI --help / 客户端与 pipeline 离线实例化 / SQL 占位符核对 / cross_end 兼容
143 lines
5.5 KiB
Python
143 lines
5.5 KiB
Python
"""回单/上报接口 Mixin — step17-20(管理端)。
|
||
|
||
所有方法签名/返回值/默认值与旧 yun8_sync/client.py 逐字一致,
|
||
仅将原始 requests.Session 调用替换为 BaseHttpClient(self.admin_http)。
|
||
|
||
Usage:
|
||
from tests.apis.yun8.receipt_api import ReceiptApi
|
||
class Yun8ApiClient(ReceiptApi, ...): ...
|
||
"""
|
||
|
||
import re
|
||
|
||
|
||
class ReceiptApi:
|
||
"""回单/上报接口(挂载于 Yun8ApiClient,依赖 admin_http / ac 属性)。"""
|
||
|
||
# ==================================================================
|
||
# Step 17: 查询运单上传 → 提取 payNo
|
||
# ==================================================================
|
||
def step17_query_upload_for_payno(self, order_code: str,
|
||
page_size: int = 20, page_num: int = 1) -> dict:
|
||
"""
|
||
Postman Test Script:
|
||
var sendMsg = jsonData.data.records[0].sendMsg || "";
|
||
var match = sendMsg.match(/【([^】]+)】/);
|
||
var result = match ? match[1] : "";
|
||
pm.collectionVariables.set("payNo", result);
|
||
|
||
Returns: {"payNo": str, "raw_records": list}
|
||
"""
|
||
params = {
|
||
"gmtCreatedRange[]": ["", ""],
|
||
"lastLoadingTimeRange": "",
|
||
"fillTimeRange": "",
|
||
"lastUnloadingTimeRange": "",
|
||
"signTimeRange": "",
|
||
"settleTimeRange": "",
|
||
"gmtModifiedRange": "",
|
||
"pageNum": page_num,
|
||
"pageSize": page_size,
|
||
"status": "5", # <-- 注意:status=5
|
||
"payerReceiverLinkMan": self.ac.get("payer_receiver_link_man", ""),
|
||
"sortField": "",
|
||
"sortType": "",
|
||
"gmtCreatedStart": "",
|
||
"gmtCreatedEnd": "",
|
||
"orderCode": order_code,
|
||
}
|
||
data = self.admin_http.get("/ntocc-basic-api/dytBusiness/orderDetail", params)
|
||
records = data.get("data", {}).get("records", [])
|
||
pay_no = ""
|
||
if records:
|
||
send_msg = records[0].get("sendMsg", "")
|
||
match = re.search(r"【([^】]+)】", send_msg)
|
||
if match:
|
||
pay_no = match.group(1)
|
||
|
||
return {"payNo": pay_no, "raw_records": records}
|
||
|
||
# ==================================================================
|
||
# Step 18: 查询打款记录 → 提取所有 code
|
||
# ==================================================================
|
||
def step18_query_remit_records(self, order_code: str,
|
||
page_size: int = 20) -> list[dict]:
|
||
"""
|
||
Postman Test Script:
|
||
pm.collectionVariables.set("remitCode", jsonData.data.records[0].code);
|
||
|
||
分页获取全部打款记录。Returns: [{code, ...}, ...]
|
||
"""
|
||
all_records = []
|
||
page_num = 1
|
||
|
||
while True:
|
||
params = {
|
||
"pageNum": page_num,
|
||
"pageSize": page_size,
|
||
"pageForm": "arpa_2",
|
||
"orderDetailNumber": order_code,
|
||
"sortField": "",
|
||
"sortType": "",
|
||
"isPayAdvance": "",
|
||
"platPayType": "",
|
||
"gmtModifiedStart": "",
|
||
"gmtModifiedEnd": "",
|
||
}
|
||
data = self.admin_http.get("/ntocc-tms-api/remitDefinite", params)
|
||
# code 可能是 0 (成功) 或 None/null (也是成功)
|
||
resp_code = data.get("code")
|
||
if resp_code is not None and resp_code != 0:
|
||
raise RuntimeError(f"查询打款记录失败: {data.get('msg')}")
|
||
|
||
page_data = data.get("data", {})
|
||
records = page_data.get("records", [])
|
||
all_records.extend(records)
|
||
|
||
total = page_data.get("total", 0)
|
||
if page_num * page_size >= total:
|
||
break
|
||
page_num += 1
|
||
|
||
return all_records
|
||
|
||
# ==================================================================
|
||
# Step 19: 查询文件名前缀 → 提取 filePrefix
|
||
# ==================================================================
|
||
def step19_query_file_prefix(self, remit_code: str) -> str:
|
||
"""
|
||
Postman Test Script:
|
||
const msg = jsonData.msg || '';
|
||
const prefix = '文件名前缀:';
|
||
const index = msg.indexOf(prefix);
|
||
const filePrefix = index !== -1 ? msg.substring(index + prefix.length).trim() : '';
|
||
pm.collectionVariables.set('filePrefix', filePrefix);
|
||
|
||
Returns: filePrefix string
|
||
"""
|
||
params = {"code": remit_code}
|
||
data = self.admin_http.get(
|
||
"/ntocc-tms-api/centralizedPayment/downLoadElectronicReceipt",
|
||
params)
|
||
msg = data.get("msg", "")
|
||
prefix_marker = "文件名前缀:"
|
||
idx = msg.find(prefix_marker)
|
||
if idx != -1:
|
||
return msg[idx + len(prefix_marker):].strip()
|
||
return ""
|
||
|
||
# ==================================================================
|
||
# Step 20: 上报运单 (reportOrderDetail)
|
||
# ==================================================================
|
||
def step20_report_order_detail(self, codes: str, report_type: int = 1) -> dict:
|
||
"""
|
||
POST /ntocc-basic-api/dytBusiness/reportOrderDetail
|
||
Content-Type: application/json;charset=UTF-8
|
||
Body: {"codes": "...", "type": 1}
|
||
|
||
在打款完成后上报运单,完成整个流程闭环。
|
||
"""
|
||
body = {"codes": codes, "type": report_type}
|
||
return self.admin_http.post_json(
|
||
"/ntocc-basic-api/dytBusiness/reportOrderDetail", body)
|