feat: 合同班内存领取并写表4

This commit is contained in:
Yuuuu 2026-10-05 22:56:46 +08:00
parent e8ef1a77fc
commit 71fc1c3b60
3 changed files with 197 additions and 1 deletions

91
rpa_contract/persist.py Normal file
View File

@ -0,0 +1,91 @@
"""合同班结果:ContractOutcome → 表 4 行 + 表 3 状态。"""
from __future__ import annotations
from dataclasses import dataclass
from repo import PurchaseContractRow
KIND_OK = "ok"
KIND_DILIGENCE = "diligence"
KIND_FAIL = "fail"
STAMP = "合同班"
PROCESS_RESULT_MAX = 1000
FAIL_REASON_MAX = 500
@dataclass(frozen=True)
class ContractOutcome:
kind: str
contract_no: str | None
reason: str | None
@dataclass(frozen=True)
class GroupSave:
fids: list[int]
process_status: int
process_result: str
table4_rows: list[dict]
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 build_save(rows: list[PurchaseContractRow], outcome: ContractOutcome) -> GroupSave:
kind = outcome.kind
number = (outcome.contract_no or "").strip() or None
if kind == KIND_OK and number:
process_status = 1
process_result = "合同已提交"
contract_status = 1
fail_reason = None
contract_no = number
elif kind == KIND_DILIGENCE:
process_status = 2
process_result = clip("客户未尽调", PROCESS_RESULT_MAX)
contract_status = 3
fail_reason = "客户未尽调"
contract_no = None
else:
reason = outcome.reason or "合同录入失败"
if kind == KIND_OK and not number:
reason = "submit 模式未读取到真实合同编号"
process_status = 2
process_result = clip(reason, PROCESS_RESULT_MAX)
contract_status = 3
fail_reason = clip(reason, FAIL_REASON_MAX)
contract_no = None
seen: dict[int, PurchaseContractRow] = {}
for row in rows:
seen.setdefault(row.oms_id, row)
table4 = [
{
"oms_id": row.oms_id,
"action_code": 1,
"contract_status": contract_status,
"contract_fail_reason": fail_reason,
"contract_no": contract_no,
"agreement_status": None,
"agreement_fail_reason": None,
"agreement_id": None,
"agreement_dtl_id": None,
"push_status": 0,
"org_code": row.org_code,
"create_user_id": 0,
"create_user_name": STAMP,
"update_user_id": 0,
"update_user_name": STAMP,
}
for row in seen.values()
]
return GroupSave(
fids=[row.fid for row in rows],
process_status=process_status,
process_result=process_result,
table4_rows=table4,
)

View File

@ -1,9 +1,10 @@
"""表 3 合同行与仓库。Memory / Oracle 在后续任务补全。"""
"""表 3 领取、表 4 写入。Oracle 仓库后续任务补全。"""
from __future__ import annotations
from dataclasses import dataclass
from datetime import date
from decimal import Decimal
from typing import Any
@dataclass
@ -34,3 +35,35 @@ class PurchaseContractRow:
goods_mdm_code: str | None
supplier_mdm_code: str | None
process_result: str = ""
class MemoryContractRepo:
def __init__(self, rows: list[PurchaseContractRow]):
self.table3 = {row.fid: row for row in rows}
self.table4: list[dict] = []
self._next_fid = 1
def claim_pending(self, limit: int | None = None) -> list[PurchaseContractRow]:
from group import is_claimable
pending = sorted(
(row for row in self.table3.values() if is_claimable(row)),
key=lambda row: row.fid,
)
if limit is not None:
pending = pending[:limit]
for row in pending:
row.process_status = 3
return pending
def save_group(self, payload: Any) -> None:
for row in payload.table4_rows:
item = dict(row)
item["fid"] = self._next_fid
self._next_fid += 1
self.table4.append(item)
for fid in payload.fids:
target = self.table3[fid]
target.process_status = payload.process_status
target.process_result = payload.process_result

View File

@ -0,0 +1,72 @@
from datetime import date
from decimal import Decimal
from persist import KIND_OK, ContractOutcome, build_save
from repo import MemoryContractRepo, PurchaseContractRow
def _row(**overrides) -> PurchaseContractRow:
data = dict(
fid=1,
oms_id=2026100501,
supplier_id="SUP001",
supplier_name="示例供应商",
contract_sign_date=date(2026, 10, 1),
contract_start_date=date(2026, 10, 2),
contract_end_date=date(2027, 9, 30),
payment_term=90,
goods_id="G0001",
goods_name="阿莫西林胶囊",
reg_no="国药准字H20201234",
spec="0.25g*24粒",
unit="盒",
qty=Decimal("10.0000"),
unit_price=Decimal("100.0000"),
purchaser_id="P001",
purchaser_name="张三",
planner_id="PL001",
planner_name="李四",
contract_entry_status=None,
contract_no=None,
process_status=0,
org_code="901",
goods_mdm_code="QX0100167583",
supplier_mdm_code="DW0100046361",
)
data.update(overrides)
return PurchaseContractRow(**data)
def test_claim_pending_sets_processing_and_skips_protocol_rerun():
repo = MemoryContractRepo(
[
_row(),
_row(fid=2, oms_id=2026100502, process_status=1),
_row(fid=3, oms_id=2026100503, contract_entry_status=0, contract_no="HT-OLD"),
]
)
claimed = repo.claim_pending()
assert [row.fid for row in claimed] == [1]
assert repo.table3[1].process_status == 3
assert repo.table3[3].process_status == 0
def test_save_group_inserts_one_table4_row_per_oms_id():
repo = MemoryContractRepo(
[
_row(),
_row(fid=2, oms_id=2026100501, goods_id="G0002"),
_row(fid=3, oms_id=2026100502, goods_id="G0003"),
]
)
repo.claim_pending()
outcome = ContractOutcome(KIND_OK, "HT20261005001", None)
payload = build_save(list(repo.table3.values()), outcome)
repo.save_group(payload)
assert [row["oms_id"] for row in repo.table4] == [2026100501, 2026100502]
assert {row["contract_no"] for row in repo.table4} == {"HT20261005001"}
assert {row["action_code"] for row in repo.table4} == {1}
assert {row["contract_status"] for row in repo.table4} == {1}
assert {row["push_status"] for row in repo.table4} == {0}
assert repo.table3[1].process_status == 1
assert repo.table3[3].process_status == 1