refactor(api): yun8_sync 并入 tests 分层框架(接口层 apis/yun8 + 用例层 api + Allure)

- 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 兼容
This commit is contained in:
xst
2026-09-08 11:38:17 +08:00
parent e62e3224bf
commit 52b73f456c
26 changed files with 2147 additions and 1786 deletions
+173
View File
@@ -0,0 +1,173 @@
"""审核 & 付款接口 Mixin — step10-16(管理端)。
所有方法签名/返回值/默认值与旧 yun8_sync/client.py 逐字一致,
仅将原始 requests.Session 调用替换为 BaseHttpClient(self.admin_http)。
Usage:
from tests.apis.yun8.audit_payment_api import AuditPaymentApi
class Yun8ApiClient(AuditPaymentApi, ...): ...
"""
import math
class AuditPaymentApi:
"""审核 & 付款接口(挂载于 Yun8ApiClient,依赖 admin_http / ac / pm 属性)。"""
# ==================================================================
# Step 10: 查询运单审核
# ==================================================================
def step10_query_audit(self, order_code: str,
page_size: int = 20, page_num: int = 1) -> dict:
"""
GET /ntocc-tms-api/orderDetail (status=6 已结算, isSettle=1)
Admin 端查询已结算运单用于审核。
"""
params = {
"isAbnormalHelp": "",
"gmtCreatedRange": "",
"lastLoadingTimeRange": "",
"fillTimeRange": "",
"lastUnloadingTimeRange": "",
"signTimeRange": "",
"settleTimeRange": "",
"gmtModifiedRange": "",
"pageNum": page_num,
"pageSize": page_size,
"isSettle": "1",
"status": "6",
"payerReceiverLinkMan": self.ac.get("payer_receiver_link_man", ""),
"sortField": "",
"sortType": "",
"orderCode": order_code,
}
return self.admin_http.get("/ntocc-tms-api/orderDetail", params)
# ==================================================================
# Step 11: 核算审核通过
# ==================================================================
def step11_approve_audit(self, code: str) -> dict:
"""
POST /ntocc-tms-api/orderDetail/auditOrderDetail?orderDetailCodes={code}&isPass=true
"""
params = {"orderDetailCodes": code, "isPass": "true"}
return self.admin_http.request_with_encoded_query(
"POST", "/ntocc-tms-api/orderDetail/auditOrderDetail", params=params)
# ==================================================================
# Step 12: 队长分账预览 (captainSplitAdjustPreview)
# ==================================================================
def step12_captain_split_preview(self, order_detail_code: str) -> dict:
"""
GET /ntocc-tms-api/orderDetail/captainSplitAdjustPreview/{code}
仅在 payerReceiver 不为空且 captainSplitMode=2 时调用。
"""
path = f"/ntocc-tms-api/orderDetail/captainSplitAdjustPreview/{order_detail_code}"
return self.admin_http.get(path)
# Step 13: 队长分账调整 (adjustCaptainSplit)
# ==================================================================
def step13_adjust_captain_split(self, order_detail_code: str,
latest_driver_amount: float,
delivery_oil_fee: float) -> dict:
"""
POST /ntocc-tms-api/orderDetail/adjustCaptainSplit
Content-Type: application/json;charset=UTF-8
driverAmount = ceil(latestDriverAmount * 0.8 * 100) / 100
captainAmount = latestDriverAmount - driverAmount
oilFee = deliveryOilFee
"""
driver_amount = math.ceil(latest_driver_amount * 0.8 * 100) / 100.0
captain_amount = round(latest_driver_amount - driver_amount, 2)
body = {
"orderDetailCode": order_detail_code,
"driverAmount": str(driver_amount),
"captainAmount": str(captain_amount),
"oilFee": delivery_oil_fee,
}
return self.admin_http.post_json(
"/ntocc-tms-api/orderDetail/adjustCaptainSplit", body)
# Step 14: 单油卡充值 (singleOil)
# ==================================================================
def step14_single_oil(self, order_detail_code: str, amount: str = "0.03",
pay_type: str = "1", category: str = "1") -> dict:
"""
POST /ntocc-tms-api/finance/singleOil
Query params: payType, amount, orderDetailCode, category, isAdvancePayment
No body (content-length: 0)
在垫资-财务打款之前调用,处理油卡充值。
"""
params = {
"payType": pay_type,
"amount": amount,
"orderDetailCode": order_detail_code,
"category": category,
"isAdvancePayment": "1",
}
return self.admin_http.request_with_encoded_query(
"POST", "/ntocc-tms-api/finance/singleOil", params=params)
# ==================================================================
# Step 15: 垫资-财务打款
# ==================================================================
def step15_pay_to_driver(self, code: str, amount: str = None,
delivery_cash_fee: str = None,
driver_actual_freight: str = None,
plan_driver_payout: str = "0",
plan_captain_payout: str = "0") -> dict:
"""
POST /ntocc-tms-api/arpaTransfer/payToDriver
amount / deliveryCashFee / driverActualFreight 由 pipeline 从 step07 传入
planDriverPayout / planCaptainPayout 来自队长分账步骤,无分账时为 "0"
"""
if amount is None:
amount = "0.27"
if delivery_cash_fee is None:
delivery_cash_fee = "0.27"
if driver_actual_freight is None:
driver_actual_freight = "0.3"
params = {
"payTypes": self.pm.get("pay_types", "3,4,5,9,10,11"),
"amount": amount,
"orderDetailCode": code,
"infoFee": "0",
"pageNum": "1",
"pageSize": "20",
"totaltotal": "0",
"payerRole": "0",
"isAdvancePayment": "1",
"planDriverPayout": plan_driver_payout,
"planCaptainPayout": plan_captain_payout,
"allotAmount": "0",
"deliveryCashFee": delivery_cash_fee,
"driverActualFreight": driver_actual_freight,
"total": "0",
"payPlatform": self.pm.get("pay_platform", "3"),
"smsCode": self.pm.get("sms_code", "1234"),
"phone": self.pm.get("phone", "13888888888"),
}
return self.admin_http.request_with_encoded_query(
"POST", "/ntocc-tms-api/arpaTransfer/payToDriver", params=params)
# ==================================================================
# Step 16: 垫资-货主打款 (申请付款)
# ==================================================================
def step16_apply_for_payment(self, code: str, total_amount: str = None) -> dict:
"""
POST /ntocc-tms-api/orderDetail/applicationForPayment
totalAmount 应从 pipeline 传入 (step06 的 shipmentActualCash)
"""
if total_amount is None:
total_amount = "0.32"
params = {
"payType": self.pm.get("pay_type", "arpa_2"),
"totalAmount": total_amount,
"codes": code,
"payPlatform": self.pm.get("pay_platform", "3"),
"isAdvancePayment": "1",
}
return self.admin_http.request_with_encoded_query(
"POST", "/ntocc-tms-api/orderDetail/applicationForPayment", params=params)