feat: 合同班内存领取并写表4
This commit is contained in:
parent
e8ef1a77fc
commit
71fc1c3b60
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue