Files
Yb-QaAutomationHub/tests/apis/yun8/sql_templates.py
T
xst 26b6fa9c1a fix(api): ETC 发票 INSERT 中 URL 签名 %3D 在参数化 SQL 下按 %% 转义
pymysql 执行 sql % params 时把字面量 %3D 当作格式符,抛
unsupported format character 'D' (index 906)。参数化模板中的字面量
百分号必须写成 %%,渲染后仍为 %3D,与旧工具 f-string 产出的 SQL 一致。
已用 pymysql 同款插值离线验证全部 7 类模板渲染通过。
2026-09-08 11:53:22 +08:00

134 lines
6.7 KiB
Python

"""yun8 全部 SQL 语句与参数化构造器。
所有语句统一使用 %s 参数占位(由 Db.execute 交给 pymysql 转义),
字面量列值(固定 code/时间戳/URL 等)从旧 yun8_sync 实现逐字保留。
Usage:
from tests.apis.yun8.sql_templates import (
RECEIPT_FILE_INSERT_SQL, receipt_file_insert_params,
ETC_INVOICE_INSERT_SQL, ETC_PUSH_INSERT_SQL,
driver_reset_statements, post_unload_reset_update, risk_control_update,
)
"""
# ── 回单文件 INSERT (base_gd_mft_file) ────────────────────────────
# 仅 file_name / front_seq_no(=payNo) 为参数;其余列值固定。
RECEIPT_FILE_INSERT_SQL = """
INSERT INTO `ntocc`.`base_gd_mft_file`
(`id`, `code`, `file_name`, `remark`, `is_deleted`,
`created_by`, `gmt_created`, `modified_by`, `gmt_modified`,
`modified_by_name`, `is_directory`, `parent_directory`,
`local_path`, `url_path`, `front_seq_no`)
VALUES
(NULL, '10cd8a53b921463ab8079ea61376574e', %s,
'批量写入回单编号20260608', 0,
'', '2025-12-21 16:24:11', '', '2025-12-21 16:24:11',
'', 0, '415612025121420251215274330494862543.zip',
'/data/cebBankService/tempFile/415612025121420251215274330494862543/41561202512141330494250466_1_signed.pdf',
'https://public-yun8.eos-chongqing-1.cmecloud.cn/d83a1298991040a4a125a84acadd88b9.pdf',
%s)
"""
def receipt_file_insert_params(file_prefix: str, pay_no: str,
file_name_template: str) -> tuple:
"""回单 INSERT 参数: (file_name, pay_no)。"""
file_name = file_name_template.format(file_prefix=file_prefix)
return (file_name, pay_no)
# ── ETC 发票 INSERT (base_etc_invoice) ────────────────────────────
# 参数: code, order_code, push_order_no, order_detail_code, invoice_time,
# import_station, export_station, transaction_time, total_price,
# amount, invoice_number, en_date, ex_date, ex_time
ETC_INVOICE_INSERT_SQL = (
"INSERT INTO `ntocc`.`base_etc_invoice` ("
"`id`, `code`, `order_code`, `push_order_no`, `order_detail_code`, "
"`invoice_time`, `sale_tax_code`, `sale_name`, `import_station`, `export_station`, "
"`transaction_time`, `total_price`, `amount`, `tax_rate`, `tax_amount`, "
"`invoice_type`, `invoice_code`, `invoice_number`, `waybill_start_time`, `waybill_end_time`, "
"`invoice_url`, `invoice_html_url`, `en_date`, `ex_date`, `ex_time`, "
"`is_valid`, `task_name`, `plate_num`, `etc_invoice_status`, `tax_deduction_status`, "
"`sign`, `is_deleted`, `created_by`, `modified_by`, `gmt_created`, `gmt_modified`) "
"VALUES ("
"NULL, %s, %s, %s, %s, "
"%s, '9141010055833160XE', '河南省视博电子股份有限公司', "
"%s, %s, "
"%s, %s, %s, 0.03, 0.03, "
"'征税发票', '*', %s, '2026-05-13 15:35:38', '2026-05-15 13:35:43', "
# 注意: URL 签名中的 % 必须写成 %%(参数化 SQL 里 % 是格式转义符),
# 经 pymysql 渲染后仍为 %3D;写成单个 % 会在 execute 时抛
# "unsupported format character 'D'"
"'https://hdfs.txffp.com/e/1102e1en66nPPP1ChAeC161e1C6Pei16.zip?Expires=1812122633&OSSAccessKeyId=LTAIYAJbICRhyCD8&Signature=TLjlHgKtCxwWpPliPRQ0xQ6HdKY%%3D', "
"'https://gateway.txffp.com/alle/common/htmlurl/getinvoice/41012526221804003093/1102e1en66nPPP1ChAeC161e1C6Pei16', "
"%s, %s, %s, "
"0, 'etc开票申请2026070604', '冀D8E016', 3, 0, "
"NULL, 0, '', '04b7e539c77d4bdbb4fe4e87eaaf41e4', '2026-07-06 09:55:16', '2026-07-06 10:03:26')"
)
def etc_invoice_insert_params(inv: dict, order_code: str, push_order_no: str,
order_detail_code: str) -> tuple:
"""ETC 发票 INSERT 参数(inv 为 pipeline._gen_etc_invoice 的产出)。"""
return (
inv["code"], order_code, push_order_no, order_detail_code,
inv["invoice_time"],
inv["import_station"], inv["export_station"],
inv["transaction_time"], inv["total_price"], inv["amount"],
inv["invoice_number"],
inv["en_date"], inv["ex_date"], inv["ex_time"],
)
# ── ETC 推送记录 INSERT (tms_order_etc_push) ──────────────────────
# 参数: code, push_order_no, order_no, order_detail_code;其余固定。
ETC_PUSH_INSERT_SQL = (
"INSERT INTO `ntocc`.`tms_order_etc_push` ("
"`id`, `code`, `push_order_no`, `order_no`, `order_detail_code`, "
"`start_time`, `end_time`, `year`, `month`, `vendor`, "
"`request`, `start_request`, `end_request`, `invoice_pull_status`, `invoice_pull_time`, "
"`start_status`, `start_push_time`, `start_result`, `end_status`, `end_push_time`, `end_result`, "
"`is_deleted`, `created_by`, `modified_by`, `gmt_created`, `gmt_modified`) "
"VALUES ("
"NULL, %s, %s, %s, %s, "
"'2026-07-07 15:08:25', '2026-07-07 15:08:28', 2026, 6, 1, "
"NULL, '11111', '11111', 2, '2026-07-07 11:40:21', "
"1, '2026-07-07 15:17:02', '成功', 1, '2026-07-07 15:11:04', '成功', "
"0, NULL, NULL, '2026-07-07 11:09:17', '2026-07-07 15:15:18')"
)
# ── 司机流程 reset / 风控状态 UPDATE ──────────────────────────────
def driver_reset_statements(reset_code: str, order_code: str) -> list[tuple]:
"""step03 后的重置序列(3 DELETE + 1 UPDATE),需在一个事务内执行。"""
return [
("DELETE FROM tms_order_detail WHERE code = %s", (reset_code,)),
("DELETE FROM tms_order_detail_ext WHERE order_detail_code = %s", (reset_code,)),
("DELETE FROM tms_order_detail_abnormal_status WHERE order_detail_code = %s", (reset_code,)),
("UPDATE tms_order_detail SET code = %s WHERE order_code = %s",
(reset_code, order_code)),
]
def post_unload_reset_update(reset_code: str, order_code: str) -> tuple:
"""reset 模式卸货后的运单号/装货签收时间回写。"""
sql = ("UPDATE tms_order_detail SET code = %s, "
"fill_time = '2026-07-05 19:30:56', "
"sign_time = '2026-07-05 19:52:30' "
"WHERE order_code = %s")
return (sql, (reset_code, order_code))
def risk_control_update(order_detail_code: str, status: int = 1) -> tuple:
"""卸货后风控状态回写(按 order_detail_code 直更)。"""
sql = ("UPDATE tms_order_detail_ext SET risk_control_status = %s "
"WHERE order_detail_code = %s")
return (sql, (status, order_detail_code))
def etc_status_update(order_code: str, status: int = 3) -> tuple:
"""运单 ETC 开票状态更新 (tms_order_detail.etc_invoice_status)。"""
sql = ("UPDATE `ntocc`.`tms_order_detail` SET etc_invoice_status = %s "
"WHERE order_code = %s")
return (sql, (status, order_code))