AutoRpa/rpa_rebate/persist.py

193 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 返利班结果:查号 / 送审 → 表 4 更新与插入、表 3 状态。
#
# 搜不到把表 4 process_status 改回 0、表 3 改回 0。送审成功才插 action_code=2。
# 系统故障原因列写短码,不写异常原文。人名固定系统管理员。
from __future__ import annotations
from dataclasses import dataclass, field
KIND_OK = "ok"
KIND_FAIL = "fail"
KIND_NOT_FOUND = "not_found"
KIND_HOLD = "hold"
USER_NAME = "系统管理员"
PROCESS_PENDING = 0
PROCESS_DONE = 1
PROCESS_RESULT_MAX = 1000
AGREEMENT_REASON_MAX = 500
# 一组合同的查号/录协议结果:成功带总单/细单号,失败带原因。
#
# error_text 只给审计表,不进原因列。
@dataclass(frozen=True)
class AgreementOutcome:
kind: str
agreement_id: str | None
agreement_dtl_id: str | None
reason: str | None
error_text: str | None = None
# 同一合同号下本班领到的起草行和只录协议行。
@dataclass
class RebateGroup:
contract_no: str
drafts: list[dict] = field(default_factory=list)
protocols: list[dict] = field(default_factory=list)
# 一组合同要写回 Oracle 的表 4 更新/插入/释放和表 3 回写。
@dataclass(frozen=True)
class GroupSave:
table4_updates: list[dict]
table4_inserts: list[dict]
table4_release_fids: list[int]
table3_updates: list[dict]
# 把原因截到 max_len 字,超长末尾加省略号。
def clip(text: str, max_len: int) -> str:
text = (text or "").strip()
if len(text) <= max_len:
return text
return text[: max_len - 1] + "…"
# 送审成功且总单号非空才算这一组过。
def agreement_ok(outcome: AgreementOutcome) -> bool:
return outcome.kind == KIND_OK and bool((outcome.agreement_id or "").strip())
# 搜不到:起草行 process_status 改回 0,表 3 改回 0,不插协议行。
def build_not_found(group: RebateGroup) -> GroupSave:
return GroupSave(
table4_updates=[],
table4_inserts=[],
table4_release_fids=[int(row["fid"]) for row in group.drafts],
table3_updates=[
{"fid": int(row["fid"]), "process_status": 0, "process_result": ""}
for row in group.protocols
],
)
def build_found(group: RebateGroup, outcome: AgreementOutcome) -> GroupSave:
"""搜到后按成败写表 4 / 表 3。
送审成功:起草行 contract_status=2、process_status=1,并按 oms_id 插 action_code=2。
确认失败:起草行 process_status 改回 0。读号失败保持 process_status=3,不插协议行。
只录协议行先补一条 action_code=1。只有确认没有单据才放回待领。
"""
if outcome.kind == KIND_HOLD:
reason = clip(outcome.reason or "读号失败", AGREEMENT_REASON_MAX)
return GroupSave(
table4_updates=[
{
"fid": int(row["fid"]),
"contract_status": 1,
"process_status": 3,
"agreement_fail_reason": reason,
}
for row in group.drafts
],
table4_inserts=[],
table4_release_fids=[],
table3_updates=[
{
"fid": int(row["fid"]),
"process_status": 3,
"process_result": reason,
}
for row in group.protocols
],
)
ok = agreement_ok(outcome)
number = (group.contract_no or "").strip()
fail_reason = clip(outcome.reason or "协议录入失败", AGREEMENT_REASON_MAX)
updates = [
{
"fid": int(row["fid"]),
"contract_status": 2 if ok else 1,
"process_status": PROCESS_DONE if ok else PROCESS_PENDING,
"agreement_fail_reason": None if ok else fail_reason,
}
for row in group.drafts
]
inserts: list[dict] = []
seen_protocol: dict[int, dict] = {}
for row in group.protocols:
seen_protocol.setdefault(int(row["oms_id"]), row)
for row in seen_protocol.values():
inserts.append(_action1_success(row, number))
if ok:
seen_oms: dict[int, dict] = {}
for row in group.drafts + group.protocols:
seen_oms.setdefault(int(row["oms_id"]), row)
for row in seen_oms.values():
inserts.append(_action2(row, number, outcome))
process_status = 1
process_result = "协议已录入"
else:
process_status = 2
process_result = clip(outcome.reason or "协议录入失败", PROCESS_RESULT_MAX)
table3_updates = [
{
"fid": int(row["fid"]),
"process_status": process_status,
"process_result": process_result,
}
for row in group.protocols
]
return GroupSave(
table4_updates=updates,
table4_inserts=inserts,
table4_release_fids=[],
table3_updates=table3_updates,
)
# 只录协议行补一条表 4 起草成功记录,action_code=1、contract_status=2。
def _action1_success(row: dict, contract_no: str) -> dict:
return {
"oms_id": int(row["oms_id"]),
"action_code": 1,
"contract_status": 2,
"contract_fail_reason": None,
"contract_no": contract_no,
"agreement_status": None,
"agreement_fail_reason": None,
"agreement_id": None,
"agreement_dtl_id": None,
"push_status": 0,
"process_status": PROCESS_DONE,
"org_code": row.get("org_code"),
"create_user_id": 0,
"create_user_name": USER_NAME,
"update_user_id": 0,
"update_user_name": USER_NAME,
}
# 送审成功插一条协议行,action_code=2、agreement_status=1,带总单/细单号。
def _action2(row: dict, contract_no: str, outcome: AgreementOutcome) -> dict:
return {
"oms_id": int(row["oms_id"]),
"action_code": 2,
"contract_status": None,
"contract_fail_reason": None,
"contract_no": contract_no,
"agreement_status": 1,
"agreement_fail_reason": None,
"agreement_id": (outcome.agreement_id or "").strip() or None,
"agreement_dtl_id": (outcome.agreement_dtl_id or "").strip() or None,
"push_status": 0,
"process_status": PROCESS_DONE,
"org_code": row.get("org_code"),
"create_user_id": 0,
"create_user_name": USER_NAME,
"update_user_id": 0,
"update_user_name": USER_NAME,
}