diff --git a/rpa_oms/README.md b/rpa_oms/README.md index 5fa9b33..7bf1c49 100644 --- a/rpa_oms/README.md +++ b/rpa_oms/README.md @@ -9,7 +9,7 @@ | 1 | 订单中心 → 本方 | `rpa_sales_goods_mapping_data` | `POST /api/oms/v1/sales-goods` | | 2 | 本方 → 订单中心 | `rpa_cart_settlement_goods_data` | `app/outbound/cart_settlement.py` 取 `push_status=0` 组装报文。路径仍空,不发 HTTP | | 3 | 订单中心 → 本方 | `rpa_purchase_contract_data` | `POST /api/oms/v1/purchase-contracts`,按对方 `fid` 幂等 | -| 4 | 本方 → 订单中心 | `rpa_contract_agreement_result` | 未做。将来由合同/返利班调用 | +| 4 | 本方 → 订单中心 | `rpa_contract_agreement_result` | `app/outbound/contract_agreement.py` 取 `push_status=0` 组装报文。路径仍空,不发 HTTP | 入站(1、3): @@ -27,6 +27,15 @@ from app.outbound.oracle_repo import OracleCartSettlementRepo envelope = load_cart_settlement_envelope(OracleCartSettlementRepo.from_env()) ``` +接口 4 出站组装:`load_contract_agreement_envelope(repo)`,同一非空 `contractNo` 不拆批,一批最多 500 条。不改 `push_status`。 + +```python +from app.outbound.contract_agreement import load_contract_agreement_envelope +from app.outbound.oracle_repo import OracleContractAgreementRepo + +envelope = load_contract_agreement_envelope(OracleContractAgreementRepo.from_env()) +``` + 运行时只落 / 读 Oracle。单测用内存替身,不连库:`uv run pytest -v`。 ## 真库 diff --git a/rpa_oms/app/outbound/__init__.py b/rpa_oms/app/outbound/__init__.py index a8971bc..f5cf5bf 100644 --- a/rpa_oms/app/outbound/__init__.py +++ b/rpa_oms/app/outbound/__init__.py @@ -1 +1 @@ -"""出站:从表组装订单中心报文。本期接口 2 只取数组装,不发 HTTP。""" +"""出站:从表组装订单中心报文。本期接口 2、4 只取数组装,不发 HTTP。""" diff --git a/rpa_oms/app/outbound/oracle_repo.py b/rpa_oms/app/outbound/oracle_repo.py index 0c7bb41..052b254 100644 --- a/rpa_oms/app/outbound/oracle_repo.py +++ b/rpa_oms/app/outbound/oracle_repo.py @@ -1,4 +1,4 @@ -"""接口 2:从表 2 读取 push_status=0。不更新推送状态。""" +"""接口 2 / 4:读 push_status=0。不更新推送状态。""" from __future__ import annotations import os @@ -52,3 +52,50 @@ class OracleCartSettlementRepo: raise RepoUnavailable(str(exc)) from exc finally: conn.close() + + +_LIST_AGREEMENT_SQL = """ +SELECT + fid, oms_id, action_code, contract_status, contract_fail_reason, + contract_no, agreement_status, agreement_fail_reason, + agreement_id, agreement_dtl_id, org_code, push_status +FROM rpa_contract_agreement_result +WHERE push_status = 0 +ORDER BY fid +""" + + +class OracleContractAgreementRepo: + def __init__(self, connect: Callable): + self._connect = connect + + @classmethod + def from_env(cls) -> "OracleContractAgreementRepo": + user = os.getenv("RPA_ORACLE_USER", "") + password = os.getenv("RPA_ORACLE_PASSWORD", "") + host = os.getenv("RPA_ORACLE_HOST", "") + if not user or not password or not host: + raise RepoUnavailable("未配置 RPA_ORACLE_HOST / RPA_ORACLE_USER / RPA_ORACLE_PASSWORD") + port = os.getenv("RPA_ORACLE_PORT", "1521") + service = os.getenv("RPA_ORACLE_SERVICE", "rpa") + dsn = f"{host}:{port}/{service}" + + def connect(): + _ensure_client() + import oracledb + + return oracledb.connect(user=user, password=password, dsn=dsn) + + return cls(connect=connect) + + def list_unpushed(self) -> list[dict]: + conn = self._connect() + try: + with conn.cursor() as cur: + cur.execute(_LIST_AGREEMENT_SQL) + cols = [item[0].lower() for item in cur.description] + return [dict(zip(cols, row)) for row in cur.fetchall()] + except Exception as exc: + raise RepoUnavailable(str(exc)) from exc + finally: + conn.close() diff --git a/rpa_oms/examples/contract_agreement_batch.json b/rpa_oms/examples/contract_agreement_batch.json new file mode 100644 index 0000000..90456cf --- /dev/null +++ b/rpa_oms/examples/contract_agreement_batch.json @@ -0,0 +1,30 @@ +{ + "data": [ + { + "fid": 300001, + "omsId": 20260928000001, + "actionCode": 1, + "contractStatus": 2, + "contractFailReason": null, + "contractNo": "HT20260928001", + "agreementStatus": null, + "agreementFailReason": null, + "agreementId": null, + "agreementDtlId": null, + "orgCode": "901" + }, + { + "fid": 300002, + "omsId": 20260928000001, + "actionCode": 2, + "contractStatus": null, + "contractFailReason": null, + "contractNo": "HT20260928001", + "agreementStatus": 1, + "agreementFailReason": null, + "agreementId": "AGR20260928001", + "agreementDtlId": "AGRD20260928001", + "orgCode": "901" + } + ] +}