110 lines
3.6 KiB
Python
110 lines
3.6 KiB
Python
# 接口 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
|