87 lines
3.1 KiB
Python
87 lines
3.1 KiB
Python
# 接口 4 Oracle 取数:SQL 按非空 contractNo 整组截断;一次 UPDATE 回写。不连真库。
|
||
|
||
from __future__ import annotations
|
||
|
||
import pytest
|
||
|
||
from app.inbound.repo import RepoUnavailable
|
||
from app.outbound.oracle_repo import _LIST_AGREEMENT_SQL, OracleContractAgreementRepo
|
||
from tests.fake_oracle import FakeDb, ora_error
|
||
|
||
|
||
# 构造一条表 4 未推行。
|
||
def _agreement(**overrides) -> dict:
|
||
row = {
|
||
"fid": 1,
|
||
"oms_id": 1,
|
||
"action_code": 1,
|
||
"contract_status": 1,
|
||
"contract_fail_reason": None,
|
||
"contract_no": "HT1",
|
||
"agreement_status": None,
|
||
"agreement_fail_reason": None,
|
||
"agreement_id": None,
|
||
"agreement_dtl_id": None,
|
||
"org_code": "901",
|
||
"push_status": 0,
|
||
}
|
||
row.update(overrides)
|
||
return row
|
||
|
||
|
||
# 取数 SQL 只捞 push_status=0,按非空合同号分组,并用 :limit 在库侧截断。
|
||
def test_list_sql_filters_unpushed_and_partitions_by_contract_no():
|
||
sql = " ".join(_LIST_AGREEMENT_SQL.split()).lower()
|
||
assert "rpa_contract_agreement_result" in sql
|
||
assert "push_status = 0" in sql
|
||
assert "partition by" in sql
|
||
assert "contract_no" in sql
|
||
assert ":limit" in sql
|
||
assert "running_start" in sql
|
||
|
||
|
||
# limit=3 时同一非空 contractNo 三行整组进批,多出的另一组留下。
|
||
def test_list_unpushed_keeps_whole_contract_no_group_when_limit_is_3():
|
||
db = FakeDb()
|
||
db.agreements[1] = _agreement(fid=1, oms_id=1, contract_no="HT-A")
|
||
db.agreements[2] = _agreement(fid=2, oms_id=2, contract_no="HT-A")
|
||
db.agreements[3] = _agreement(fid=3, oms_id=3, contract_no="HT-A")
|
||
db.agreements[4] = _agreement(fid=4, oms_id=4, contract_no="HT-B")
|
||
repo = OracleContractAgreementRepo(db.connection())
|
||
rows = repo.list_unpushed(limit=3)
|
||
assert [row["fid"] for row in rows] == [1, 2, 3]
|
||
execute_calls = [call for call in db.calls if call[0] == "execute"]
|
||
sql, params = execute_calls[-1][1], execute_calls[-1][2]
|
||
assert "partition by" in sql.lower()
|
||
assert params["limit"] == 3
|
||
|
||
|
||
# 库故障对外固定「数据库不可用」,不含 ORA 原文。
|
||
def test_list_unpushed_hides_ora_text():
|
||
db = FakeDb()
|
||
db.raise_execute = ora_error(12541, "ORA-12541: TNS:no listener")
|
||
repo = OracleContractAgreementRepo(db.connection())
|
||
with pytest.raises(RepoUnavailable) as caught:
|
||
repo.list_unpushed(limit=500)
|
||
assert caught.value.message == "数据库不可用"
|
||
assert "ORA-" not in str(caught.value)
|
||
|
||
|
||
# 回写 push_status 只发一条 UPDATE ... WHERE fid IN (...)。
|
||
def test_mark_pushed_updates_in_one_statement():
|
||
db = FakeDb()
|
||
db.agreements[1] = _agreement(fid=1)
|
||
db.agreements[2] = _agreement(fid=2)
|
||
repo = OracleContractAgreementRepo(db.connection())
|
||
repo.mark_pushed([1, 2], status=1, reason="ok")
|
||
updates = [
|
||
call for call in db.calls if call[0] == "execute" and "UPDATE" in call[1].upper()
|
||
]
|
||
assert len(updates) == 1
|
||
sql = updates[0][1].upper()
|
||
assert "RPA_CONTRACT_AGREEMENT_RESULT" in sql
|
||
assert "FID IN" in sql
|
||
assert db.agreements[1]["push_status"] == 1
|
||
assert db.agreements[2]["push_result"] == "ok"
|
||
assert db.commits == 1
|