# 接口 2:从表 2 取未推行,组装文档报文。 # # 同一 omsId 的加购行必须在同一批 data 里。一批上限默认 500,可用 # OMS_OUTBOUND_BATCH_LIMIT 覆盖。不改 push_status,不向订单中心发 HTTP。 from __future__ import annotations from collections import OrderedDict from ..parse import as_int, money4 from .limits import MAX_BATCH, batch_limit __all__ = [ "MAX_BATCH", "batch_limit", "build_cart_settlement_envelope", "load_cart_settlement_envelope", ] # 从仓库取未推行并组装信封。未传 limit 时读环境变量。 def load_cart_settlement_envelope(repo, limit: int | None = None) -> dict: cap = batch_limit() if limit is None else limit return build_cart_settlement_envelope(repo.list_unpushed(limit=cap), limit=cap) # 把已取出的行按 omsId 整组截到 limit,再转文档字段。 def build_cart_settlement_envelope(rows: list[dict], limit: int = MAX_BATCH) -> dict: chosen = _take_complete_groups(rows, limit) return {"data": [_to_item(row) for row in chosen]} # 按 oms_id 保序成组;装不下的整组留下。空批时超限组仍进入。 def _take_complete_groups(rows: list[dict], limit: int) -> list[dict]: groups: OrderedDict = OrderedDict() for row in rows: groups.setdefault(row["oms_id"], []).append(row) batch: list[dict] = [] for group in groups.values(): if len(batch) + len(group) > limit and batch: break batch.extend(group) return batch # 金额四位小数字符串。库里的 NULL 保持 null,不让一行空金额掀掉整批。 def _money4(value) -> str | None: if value is None: return None return money4(value) # 把表 2 行转成接口 2 文档字段。金额四位小数字符串。 def _to_item(row: dict) -> dict: return { "fid": as_int(row["fid"]), "operateType": as_int(row["operate_type"]), "omsId": as_int(row["oms_id"]), "platformType": as_int(row["platform_type"]), "supplierName": row["supplier_name"], "barCode": row["bar_code"], "purchasePrice": _money4(row.get("purchase_price")), "purchaseQty": as_int(row["purchase_qty"]), "purchaseTotal": _money4(row.get("purchase_total")), "status": as_int(row["status"]) if row.get("status") is not None else None, "failReason": row.get("fail_reason"), "payOrderNo": row.get("pay_order_no"), "payOrderDtlId": row.get("pay_order_dtl_id"), "orgCode": row.get("org_code"), }