Files
Yb-QaAutomationHub/tests/apis/yun8/accounting_api.py
T
xst 52b73f456c 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 兼容
2026-09-08 11:38:17 +08:00

338 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""运费核算接口 Mixin — step06-09(管理端,含 ~190 字段核算提交报文)。
所有方法签名/返回值/默认值与旧 yun8_sync/client.py 逐字一致,
仅将原始 requests.Session 调用替换为 BaseHttpClient(self.admin_http)。
Usage:
from tests.apis.yun8.accounting_api import AccountingApi
class Yun8ApiClient(AccountingApi, ...): ...
"""
class AccountingApi:
"""运费核算接口(挂载于 Yun8ApiClient,依赖 admin_http / ac / dp 属性)。"""
# ==================================================================
# Step 06: 运费核算查询运单
# ==================================================================
def step06_query_for_accounting(self, order_code: str,
page_size: int = 20, page_num: int = 1) -> dict:
"""
Postman Test Script: 设置 30+ 个 collection variables
从 data.records[0] 中提取所有字段
Returns: dict with all fields from records[0]
"""
params = {
"status": "3",
"lastLoadingTimeRange": "",
"fillTimeRange": "",
"lastUnloadingTimeRange": "",
"signTimeRange": "",
"gmtModifiedRange": "",
"rangeValue_start_1": "",
"rangeValue_end_1": "",
"rangeValue_start_2": "",
"rangeValue_end_2": "",
"rangeValue_start_3": "",
"rangeValue_end_3": "",
"pageNum": page_num,
"pageSize": page_size,
"gmtCreatedStart": "",
"gmtCreatedEnd": "",
"lastUnloadingTimeStart": "",
"lastUnloadingTimeEnd": "",
"lastLoadingTimeStart": "",
"lastLoadingTimeEnd": "",
"gmtModifiedStart": "",
"gmtModifiedEnd": "",
"fillTimeStart": "",
"fillTimeEnd": "",
"signTimeStart": "",
"signTimeEnd": "",
"ordCreatedByName": "",
"isUnloadingConfirm": "1",
"isCannotAccounting": "0",
"riskControlStatus": "",
"riskControlReason": "",
"sortField": "",
"sortType": "",
"orderCode": order_code,
}
data = self.admin_http.get("/ntocc-tms-api/orderDetail/orderDetailHandlePageList", params)
records = data.get("data", {}).get("records", [])
if not records:
raise RuntimeError("运费核算查询运单: 无记录返回")
return records[0]
# ==================================================================
# Step 07: 查询运单详情
# ==================================================================
def step07_query_order_expenses(self, code: str) -> dict:
"""
Postman Test Script:
pm.collectionVariables.set("canWastage", ...);
pm.collectionVariables.set("deliveryCashFee", ...);
pm.collectionVariables.set("deliveryFeeDeserved", ...);
pm.collectionVariables.set("deliveryFeePractical", ...);
pm.collectionVariables.set("driverActualCash", ...);
pm.collectionVariables.set("driverActualFreight", ...);
Returns: {canWastage, deliveryCashFee, deliveryFeeDeserved,
deliveryFeePractical, driverActualCash, driverActualFreight}
"""
params = {"codes": code}
data = self.admin_http.post(
"/ntocc-tms-api/orderDetail/getOrderDetailExpensesParamList",
params=params)
items = data.get("data", [])
if not items:
raise RuntimeError("查询运单详情: 无数据返回")
r = items[0]
return {
"canWastage": str(r.get("canWastage", "")),
"deliveryCashFee": str(r.get("deliveryCashFee", "")),
"deliveryFeeDeserved": str(r.get("deliveryFeeDeserved", "")),
"deliveryFeePractical": str(r.get("deliveryFeePractical", "")),
"driverActualCash": str(r.get("driverActualCash", "")),
"driverActualFreight": str(r.get("driverActualFreight", "")),
}
# ==================================================================
# Step 08: 核算试算 (calculateOrderDetail)
# ==================================================================
def step08_calculate_order_detail(self, code: str) -> dict:
"""
Postman Test Script:
pm.collectionVariables.set("ticketImageUrls[]", jsonData.data.ticketImageUrls);
Returns: dict with ticketImageUrls + 其他 step08 返回的核算数据 (taxPrice 等)
"""
params = {"code": code, "isFirst": "1"}
data = self.admin_http.put("/ntocc-tms-api/orderDetail/calculateOrderDetail", params=params)
inner = data.get("data", {}) or {}
ticket_urls = inner.get("ticketImageUrls", "")
if isinstance(ticket_urls, list):
ticket_urls = ticket_urls[0] if ticket_urls else ""
# 返回所有有用字段,供 pipeline 存入 vars
result = {"ticketImageUrls": str(ticket_urls)}
for key in ("taxPrice", "taxFee", "taxPayFee", "taxPoint",
"price", "realPrice", "shipmentActualCash",
"shipmentActualFreight"):
if key in inner:
result[key] = str(inner[key])
return result
# ==================================================================
# Step 09: 核算提交
# ==================================================================
def step09_submit_accounting(self, accounting_vars: dict) -> dict:
"""
提交核算,参数来自前面步骤累积的所有变量。
accounting_vars 应包含 steps 03/06/07/08 的全部字段。
优先从 step06 返回值取值,取不到再用 config.yaml 默认值。
"""
av = accounting_vars
# 便捷取值:vars 优先 → config 兜底
def _v(key, cfg_key, default=""):
return av.get(key) or self.ac.get(cfg_key, default)
# Build the massive query string
params = {
"abnormalFee": "0",
"accountCheckAuthStatus": "0",
"accountCheckInfoAuthStatus": "0",
"accountCheckUpAuthStatus": "0",
"accountStatus": "0",
"allTrans": "0",
"allotAmount": "0",
"allotOil": "0",
"allotTaxAmount": "0",
"appSendLoadLocation": "0",
"appSendUnloadLocation": "0",
"applyStatus": "0",
"branchCode": _v("branchCode", "branch_code"),
"businessTypeCode": _v("businessTypeCode", "business_type_code"),
"canWastage": av.get("canWastage", ""),
"cancelTrans": "0",
"cancelType": "0",
"captainSplitCurrentVersion": "0",
"captainSplitMode": self.ac.get("captain_split_mode") or av.get("captainSplitMode", ""),
"cashDeposit": "0",
"coalName": "",
"coalPrice": av.get("coalPrice", ""),
"coalType": av.get("coalType", ""),
"coalTypeName": av.get("coalTypeName", ""),
"coalUnit": "0",
"coalUnitName": av.get("coalUnitName", ""),
"code": av.get("code", ""),
"contractStatus": "1",
"createdBy": av.get("createdBy", ""),
"createdByName": av.get("createdByName", ""),
"deleted": "0",
"deliveryCashFee": av.get("deliveryCashFee", ""),
"deliveryFeeDeserved": av.get("deliveryFeeDeserved", ""),
"deliveryFeePractical": av.get("deliveryFeePractical", ""),
"deliveryOilFee": "0",
"distance": av.get("distance", ""),
"driverActualCash": av.get("driverActualCash", ""),
"driverActualFreight": av.get("driverActualFreight", ""),
"driverCode": av.get("driverCode", ""),
"driverName": av.get("driverName", ""),
"driverPhone": av.get("driverPhone", ""),
"energyCardType": av.get("energyCardType", ""),
"etcType": "0",
"extraFee": "0",
"fillTime": av.get("fillTime", ""),
"finishedTrans": "0",
"gmtCreated": av.get("gmtCreated", ""),
"gmtModified": av.get("gmtModified", ""),
"id": av.get("id", ""),
"inFee": "0",
"infoFee": "0",
"insuranceAmount": "0",
"insuranceFee": "0",
"invoiceIsAll": "0",
"invoiceStatus": "0",
"invoiceStatusCaptain": "0",
"invoiceStatusDriver": "0",
"isAbnormal": "0",
"isCancel": "0",
"isCaptainOrder": "0",
"isCash": "0",
"isCuikuan": "0",
"isDriverComment": "0",
"isEqualDriver": "1",
"isEqualTeam": "1",
"isEqualVehicle": "1",
"isEtcHistory": "0",
"isFill": "1",
"isImport": "0",
"isInsure": "0",
"isLoadingConfirm": "1",
"isLoadingConfirmDate": av.get("isLoadingConfirmDate", ""),
"isOriginalOrder": "1",
"isPaperReturns": "0",
"isReceiptReturn": "0",
"isReportOrder": "0",
"isSend": "0",
"isSendDishonestyVehicle": "0",
"isSendFund": "0",
"isSendFundZhongLian": "0",
"isSendLoadLocation": "0",
"isSendTax": "0",
"isSendUnloadLocation": "0",
"isSendZhongLian": "0",
"isSettle": "0",
"isShipmentComment": "0",
"isSign": "1",
"isSplitOrder": "0",
"isSupplementary": "0",
"isTransfer": "0",
"isTrunkName": av.get("isTrunkName", ""),
"isUnloadingComfirmDate": av.get("isUnloadingComfirmDate", ""),
"isUnloadingConfirm": "1",
"isWsShare": "0",
"loadImgUrls[]": av.get("ticketImageUrls", ""),
"loadLatitude": av.get("loadLatitude", ""),
"loadLongitude": av.get("loadLongitude", ""),
"loadPlace": av.get("loadPlace", ""),
"loadQuantity": av.get("loadQuantity", ""),
"loadWeight": av.get("loadWeight", "1"),
"mainOrderCode": av.get("mainOrderCode", ""),
"modifiedBy": av.get("modifiedBy", ""),
"modifiedByName": av.get("modifiedByName", ""),
"monthlySettlementStatus": "0",
"oilFee": av.get("oilFee", ""),
"onTrans": "0",
"orderCode": av.get("orderCode", ""),
"payAmount": "0",
"payOil": "0",
"payStatus": "0",
"payStep": "10",
"payTaxAmount": "0",
"payTotalAmount": av.get("payTotalAmount", ""),
"payType": "0",
"payeeCode": _v("createdBy", "payee_code"), # step06 createdBy = payeeCode
"payeeName": av.get("payeeName", ""),
"payerReceiver": self.ac.get("payer_receiver", ""),
"payerReceiverLinkMan": self.ac.get("payer_receiver_link_man", ""),
"platformPrepayment": "0",
"prepaidStatus": "0",
"price": av.get("price", ""),
"proofAmount": "0",
"proofStatus": "0",
"realPrice": av.get("realPrice", ""),
"receiptNum": "",
"receiptPayAmount": "0",
"refuelProportion": "0",
"reportMark": "0",
"reportStage": "0",
"settlementCash": "0",
"settlementOil": "0",
"settlementType": self.ac.get("settlement_type", "2"),
"settlementWeight": av.get("settlementWeight", "1"),
"shipmentActualCash": av.get("shipmentActualCash", ""),
"shipmentActualFreight": av.get("shipmentActualFreight", ""),
"shipmentCardScale": "10",
"shipmentDeliveryFeePractical": av.get("shipmentDeliveryFeePractical", ""),
"shipmentName": av.get("shipmentName", ""),
"shipmentPayStatus": "0",
"shipmentPhone": _v("shipmentPhone", "shipment_phone"),
"shipperDeliveryFee": av.get("shipperDeliveryFee", ""),
"shippingNoteNumber": av.get("shippingNoteNumber", ""),
"signTime": av.get("signTime", ""),
"status": "3",
"takeLatitude": av.get("takeLatitude", ""),
"takeLongitude": av.get("takeLongitude", ""),
"takeOrderType": "2",
"takePlace": av.get("takePlace", ""),
"taxFee": av.get("taxFee", ""),
"taxPayFee": av.get("taxPayFee", ""),
"taxPrice": av.get("taxPrice", ""),
"ticketImageUrls[]": av.get("ticketImageUrls", ""),
"txStatus": "0",
"unloadLatitude": self.dp.get("latitude", ""),
"unloadLongitude": self.dp.get("longitude", ""),
"unloadPlace": av.get("unloadPlace", ""),
"unloadQuantity": av.get("unloadQuantity", ""),
"unloadWeight": av.get("unloadWeight", "1"),
"vehicleCode": av.get("vehicleCode", ""),
"vehicleLicense": av.get("vehicleLicense", ""),
"waitCar": "0",
"waitCheckTrans": "0",
"waitDriverCheckTrans": "0",
"waitPay": "0",
"waitSettle": "0",
"waitTrans": "0",
"wastage": "0",
"weight": av.get("weight", "1"),
"whetherOverload": "0",
"wsShareRatio": "0",
"deductionFee": "0",
"driverErase": "0",
"driverFixedPay": "0",
"driverSettlementWeight": av.get("driverSettlementWeight", "1"),
"electricityCardScale": "10",
"gasCardScale": "10",
"isTrunk": "0",
"limitWastageAmount": "500",
"limitWastageType": "1",
"shipmentErase": "0",
"shipmentPartyCode": _v("shipmentPartyCode", "shipment_party_code"),
"shipmentSettlementWeight": av.get("shipmentSettlementWeight", "1"),
"shipperFixedPay": "0",
"taxPoint": av.get("taxPoint", ""),
"taxPriceFixedPay": "0",
"orderExtraFeeListStr": "[]",
"BranchCode": _v("branchCode", "branch_code"),
"unloadImgaes": av.get("ticketImageUrls", ""),
"truckLoadingImgaes": av.get("ticketImageUrls", ""),
"IsTaxPoint": "0",
"RealPrice": av.get("realPrice", ""),
"gmtCreated2": av.get("gmtCreated", ""),
"gmtModified2": av.get("gmtModified", ""),
}
return self.admin_http.request_with_encoded_query(
"PUT", "/ntocc-tms-api/orderDetail/orderHandleEditSubmitHandle", params=params)