from datetime import date from decimal import Decimal from job import run_batch from persist import KIND_DILIGENCE, 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 def test_job_merges_same_supplier_and_writes_table4(): repo = MemoryContractRepo( [ _row(), _row(fid=2, oms_id=2026100502, goods_id="G0002"), _row(fid=3, oms_id=2026100503, contract_entry_status=0, contract_no="HT-OLD"), ] ) calls: list = [] def runner(draft): calls.append(draft) return ContractOutcome(KIND_OK, "HT20261005001", None) run_batch(repo, runner=runner) assert len(calls) == 1 assert [line.goods_code for line in calls[0].goods_lines] == ["G0001", "G0002"] assert calls[0].customer_code == "DW0100046361" 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[2].process_status == 1 assert repo.table3[3].process_status == 0 def test_job_marks_diligence_fail(): repo = MemoryContractRepo([_row()]) def runner(draft): return ContractOutcome(KIND_DILIGENCE, None, "客户未尽调") run_batch(repo, runner=runner) assert repo.table3[1].process_status == 2 assert "客户未尽调" in repo.table3[1].process_result assert repo.table4[0]["contract_status"] == 3 assert repo.table4[0]["contract_no"] is None assert repo.table4[0]["contract_fail_reason"] == "客户未尽调" def test_job_skips_runner_when_mdm_missing(): repo = MemoryContractRepo([_row(supplier_mdm_code="")]) called = {"n": 0} def runner(draft): called["n"] += 1 return ContractOutcome(KIND_OK, "HT-X", None) run_batch(repo, runner=runner) assert called["n"] == 0 assert repo.table3[1].process_status == 2 assert "缺少供应商MDM码" in repo.table3[1].process_result