# 接口 4:从表 4 取未推行,组装文档报文。 # # 同一非空 contractNo 必须在同一批 data 里。空 contractNo(失败行)按行独立。 # 一批上限默认 500,可用 OMS_OUTBOUND_BATCH_LIMIT 覆盖。不改 push_status,不发 HTTP。 from __future__ import annotations from collections import OrderedDict from ..parse import as_int, as_str from .limits import MAX_BATCH, batch_limit __all__ = [ "MAX_BATCH", "batch_limit", "build_contract_agreement_envelope", "load_contract_agreement_envelope", ] # 从仓库取未推行并组装信封。未传 limit 时读环境变量。 def load_contract_agreement_envelope(repo, limit: int | None = None) -> dict: cap = batch_limit() if limit is None else limit return build_contract_agreement_envelope(repo.list_unpushed(limit=cap), limit=cap) # 把已取出的行按合同号整组截到 limit,再转文档字段。 def build_contract_agreement_envelope(rows: list[dict], limit: int = MAX_BATCH) -> dict: chosen = _take_complete_groups(rows, limit) return {"data": [_to_item(row) for row in chosen]} # 非空合同号成一组;空合同号用 fid 自成一组。 def _group_key(row: dict): number = row.get("contract_no") if number is None or str(number).strip() == "": return ("fid", row["fid"]) return ("no", str(number).strip()) # 按合同号保序成组;装不下的整组留下。空批时超限组仍进入。 def _take_complete_groups(rows: list[dict], limit: int) -> list[dict]: groups: OrderedDict = OrderedDict() for row in rows: groups.setdefault(_group_key(row), []).append(row) batch: list[dict] = [] for group in groups.values(): if len(batch) + len(group) > limit and batch: break batch.extend(group) return batch # 把表 4 行转成接口 4 文档字段。 def _to_item(row: dict) -> dict: return { "fid": as_int(row["fid"]), "omsId": as_int(row["oms_id"]), "actionCode": as_int(row["action_code"]), "contractStatus": as_int(row.get("contract_status")), "contractFailReason": as_str(row.get("contract_fail_reason")), "contractNo": as_str(row.get("contract_no")), "agreementStatus": as_int(row.get("agreement_status")), "agreementFailReason": as_str(row.get("agreement_fail_reason")), "agreementId": as_str(row.get("agreement_id")), "agreementDtlId": as_str(row.get("agreement_dtl_id")), "orgCode": as_str(row.get("org_code")), }