# 1 号药城导出行 → 表 2 operate_type=2。不对加购行。 from __future__ import annotations import uuid from dataclasses import dataclass from decimal import Decimal, ROUND_HALF_UP from typing import Any YAOEX_PLATFORM_TYPE = 66 OPERATE_TYPE_PAY = 2 PUSH_NOT_SENT = 0 UNASSIGNED_OMS_ID = 0 PAID_STATUSES = {"待发货", "待收货", "已完成"} # 金额收到四位小数,四舍五入。接口 2 组包也按这个精度。 def money4(value: object) -> Decimal: return Decimal(str(value)).quantize(Decimal("0.0001"), rounding=ROUND_HALF_UP) # 生成支付明细号。表 2 用它区分同一订单下的不同行。 def new_pay_dtl_id() -> str: return uuid.uuid4().hex # 1 号药城导出的一行订单明细。只取已支付状态落表。 @dataclass(frozen=True) class MallLine: order_no: str parent_order_no: str supplier_name: str status: str goods_name: str product_code: str bar_code: str unit_price: Decimal pay_price: Decimal qty: int goods_amount: Decimal order_paid: Decimal # 支付匹配结果:可落库的行、对不上的行、重复订单、状态未付。 @dataclass class MatchResult: rows: list[dict[str, Any]] unmatched: list[tuple[MallLine, str]] skipped_dup: list[MallLine] skipped_status: list[MallLine] # 筛出待发货、待收货、已完成的行。同一支付订单号已落过的跳过。条码超长不对上。 def match_pay_lines( lines: list[MallLine], existing_order_nos: set[str], ) -> MatchResult: result = MatchResult(rows=[], unmatched=[], skipped_dup=[], skipped_status=[]) for line in lines: if line.status not in PAID_STATUSES: result.skipped_status.append(line) continue if line.order_no in existing_order_nos: result.skipped_dup.append(line) continue if len(line.bar_code) > 40: result.unmatched.append((line, "BAR_CODE_TOO_LONG")) continue result.rows.append(build_pay_row(line)) return result # 把一条已支付明细收成表 2 支付行。operate_type=2,oms_id 先填 0,不改加购行。 def build_pay_row(line: MallLine) -> dict[str, Any]: price = money4(line.pay_price) qty = int(line.qty) return { "operate_type": OPERATE_TYPE_PAY, "oms_id": UNASSIGNED_OMS_ID, "platform_type": YAOEX_PLATFORM_TYPE, "supplier_name": line.supplier_name, "bar_code": line.bar_code, "purchase_price": price, "purchase_qty": qty, "purchase_total": money4(price * qty), "status": None, "fail_reason": None, "pay_order_no": line.order_no, "pay_order_dtl_id": new_pay_dtl_id(), "push_status": PUSH_NOT_SENT, "org_code": None, "multi_platform_flag": 0, }