# 接口 3 Oracle 落表。fid 是订单中心来源序号,INSERT 必须绑这一列。 from __future__ import annotations from rpa_oracle.errors import RepoUnavailable, is_contract_fid_duplicate from .oracle_repo import _rollback, in_binds, unique_collisions _INSERT_SQL = """ INSERT INTO rpa_purchase_contract_data ( fid, oms_id, supplier_id, supplier_name, contract_sign_date, contract_start_date, contract_end_date, payment_term, goods_id, goods_name, reg_no, spec, unit, qty, purchase_tax_rate, unit_price, goods_source_id, purchaser_id, purchaser_name, planner_id, planner_name, contract_entry_status, contract_no, org_code, customer_type, goods_mdm_code, supplier_mdm_code, process_status, create_time ) VALUES ( :fid, :oms_id, :supplier_id, :supplier_name, :contract_sign_date, :contract_start_date, :contract_end_date, :payment_term, :goods_id, :goods_name, :reg_no, :spec, :unit, :qty, :purchase_tax_rate, :unit_price, :goods_source_id, :purchaser_id, :purchaser_name, :planner_id, :planner_name, :contract_entry_status, :contract_no, :org_code, :customer_type, :goods_mdm_code, :supplier_mdm_code, 0, SYSTIMESTAMP ) """ _BIND_KEYS = ( "fid", "oms_id", "supplier_id", "supplier_name", "contract_sign_date", "contract_start_date", "contract_end_date", "payment_term", "goods_id", "goods_name", "reg_no", "spec", "unit", "qty", "purchase_tax_rate", "unit_price", "goods_source_id", "purchaser_id", "purchaser_name", "planner_id", "planner_name", "contract_entry_status", "contract_no", "org_code", "customer_type", "goods_mdm_code", "supplier_mdm_code", ) # 接口 3 连 Oracle 的仓库,管表 3 按 fid 查重和批量插入。 # # 连接由调用方从池里借来,一个请求一条。 class OraclePurchaseContractRepo: # 挂上本请求的连接。不要在仓库里再 connect。 def __init__(self, conn): self._conn = conn # 查出表 3 里已经有的 fid。空列表不访问库。 def existing_fids(self, fids: list[int]) -> set[int]: if not fids: return set() placeholders, binds = in_binds(fids) sql = ( "SELECT fid FROM rpa_purchase_contract_data " f"WHERE fid IN ({placeholders})" ) try: with self._conn.cursor() as cur: cur.execute(sql, binds) return {row[0] for row in cur.fetchall()} except Exception as exc: raise RepoUnavailable("数据库不可用") from exc # 一次 executemany 插入待写入行。 # # 返回撞上 pk_rpa_pcd 的 fid。其它唯一约束或库故障抛 RepoUnavailable。 # 成功行在本方法内 commit。 def insert_many(self, records: list[dict]) -> set[int]: if not records: return set() payload = [{key: record[key] for key in _BIND_KEYS} for record in records] try: with self._conn.cursor() as cur: cur.executemany(_INSERT_SQL, payload, batcherrors=True) collided = unique_collisions( cur, records, "fid", is_contract_fid_duplicate ) self._conn.commit() return collided except RepoUnavailable: _rollback(self._conn) raise except Exception as exc: _rollback(self._conn) if is_contract_fid_duplicate(exc) and len(records) == 1: return {records[0]["fid"]} raise RepoUnavailable("数据库不可用") from exc