# 接口 3 Oracle 仓库:INSERT 绑 fid;按主键认重复;一批 executemany。不连真库。 from __future__ import annotations from datetime import date from decimal import Decimal import pytest from app.inbound.repo import RepoUnavailable from tests.fake_oracle import FakeDb # 构造一条表 3 落库记录。 def _record(**overrides): row = { "fid": 200001, "oms_id": 20260928000001, "supplier_id": "SUP001", "supplier_name": "示例供应商", "contract_sign_date": date(2026, 9, 28), "contract_start_date": date(2026, 10, 1), "contract_end_date": date(2027, 9, 30), "payment_term": 90, "goods_id": "G000123456789", "goods_name": "阿莫西林胶囊", "reg_no": "国药准字H20201234", "spec": "0.25g*24粒", "unit": "盒", "qty": Decimal("10.0000"), "purchase_tax_rate": Decimal("0.1300"), "unit_price": Decimal("100.0000"), "goods_source_id": "GS001", "purchaser_id": "P001", "purchaser_name": "张三", "planner_id": "PL001", "planner_name": "李四", "contract_entry_status": None, "contract_no": None, "org_code": "901", "customer_type": 1, "goods_mdm_code": "QX0100167583", "supplier_mdm_code": "DW0100046361", "process_status": 0, } row.update(overrides) return row # 缺 host 时 get_pool 抛「数据库不可用」。 def test_from_env_without_host_raises(monkeypatch): monkeypatch.delenv("RPA_ORACLE_HOST", raising=False) import app.main as main main._pool = None with pytest.raises(RepoUnavailable) as caught: main.get_pool() assert caught.value.message == "数据库不可用" # pk_rpa_pcd 冲突时 insert_many 把该 fid 放进重复集合。 def test_insert_unique_violation_is_duplicate_fid(): from app.inbound.oracle_contract_repo import OraclePurchaseContractRepo db = FakeDb() db.collide_contracts.add(200001) repo = OraclePurchaseContractRepo(db.connection()) collided = repo.insert_many([_record()]) assert collided == {200001} # 未知唯一约束不当成 fid 重复,抛「数据库不可用」。 def test_unknown_unique_constraint_raises_unavailable(): from app.inbound.oracle_contract_repo import OraclePurchaseContractRepo db = FakeDb() db.collide_contracts.add(200001) db.collide_constraint = "UK_SOMETHING_ELSE" repo = OraclePurchaseContractRepo(db.connection()) with pytest.raises(RepoUnavailable) as caught: repo.insert_many([_record()]) assert caught.value.message == "数据库不可用" # 待插入多行时一次 executemany,且 batcherrors=True。 def test_insert_many_uses_executemany(): from app.inbound.oracle_contract_repo import OraclePurchaseContractRepo db = FakeDb() repo = OraclePurchaseContractRepo(db.connection()) assert repo.existing_fids([1, 2]) == set() collided = repo.insert_many([_record(fid=1, oms_id=1), _record(fid=2, oms_id=2)]) assert collided == set() assert set(db.contracts) == {1, 2} many = [c for c in db.calls if c[0] == "executemany"] assert len(many) == 1 assert many[0][3] is True # INSERT 绑来源 fid,process_status 用字面量 0。 def test_insert_sql_binds_source_fid_and_pending_status(): from app.inbound.oracle_contract_repo import _BIND_KEYS, _INSERT_SQL sql = " ".join(_INSERT_SQL.split()) assert "fid" in sql assert ":fid" in sql assert "process_status" in sql assert "SYSTIMESTAMP" in sql assert "fid" in _BIND_KEYS assert "oms_id" in _BIND_KEYS assert "goods_mdm_code" in _BIND_KEYS assert "supplier_mdm_code" in _BIND_KEYS