69 lines
2.5 KiB
Python
69 lines
2.5 KiB
Python
# 接口 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")),
|
||
}
|