"""安排运输时合同数量硬拦 / 提醒纯函数单测。""" from app.services.pl_contract_plan_qty import ( contract_product_has_fixed_qty, effective_arranged_total, evaluate_product_qty_for_arrange, ) def test_effective_arranged_total_subtracts_old(): assert effective_arranged_total(arranged_total=100, old_plan_qty=30, new_plan_qty=40) == 110.0 def test_effective_arranged_total_rounds(): assert effective_arranged_total(arranged_total=10.1234, old_plan_qty=1.1, new_plan_qty=2.2) == 11.223 def test_framework_customer_demand_not_fixed(): assert ( contract_product_has_fixed_qty( contract_type="framework_sale", quantity=0, quantity_mode="customer_demand", ) is False ) def test_framework_fixed_mode_with_qty_is_fixed(): assert ( contract_product_has_fixed_qty( contract_type="framework_purchase", quantity=50, quantity_mode="fixed", ) is True ) def test_sale_positive_qty_is_fixed(): assert ( contract_product_has_fixed_qty( contract_type="sale", quantity=100, quantity_mode="fixed", ) is True ) def test_zero_or_empty_qty_not_fixed(): assert contract_product_has_fixed_qty(contract_type="sale", quantity=0, quantity_mode="fixed") is False assert contract_product_has_fixed_qty(contract_type="sale", quantity=None, quantity_mode="fixed") is False def test_evaluate_skip_when_no_new_qty(): assert ( evaluate_product_qty_for_arrange( has_fixed_qty=True, contract_qty=100, arranged_total=80, old_plan_qty=0, new_plan_qty=0, ) is None ) def test_evaluate_overflow_violation(): r = evaluate_product_qty_for_arrange( has_fixed_qty=True, contract_qty=100, arranged_total=80, old_plan_qty=0, new_plan_qty=30, ) assert r is not None assert r["kind"] == "violation" assert r["overflowQty"] == 10.0 assert r["effectiveTotal"] == 110.0 assert r["arrangedTotalQty"] == 110.0 def test_evaluate_remaining_reminder(): r = evaluate_product_qty_for_arrange( has_fixed_qty=True, contract_qty=200, arranged_total=150, old_plan_qty=0, new_plan_qty=40, ) assert r is not None assert r["kind"] == "remaining" assert r["remainingQty"] == 10.0 assert r["arrangedTotalQty"] == 190.0 def test_evaluate_rearrange_deducts_old(): # arranged 已含旧 30;改为 40 → effective 110 r = evaluate_product_qty_for_arrange( has_fixed_qty=True, contract_qty=100, arranged_total=100, old_plan_qty=30, new_plan_qty=40, ) assert r is not None assert r["kind"] == "violation" assert r["overflowQty"] == 10.0 def test_evaluate_framework_cumulative(): r = evaluate_product_qty_for_arrange( has_fixed_qty=False, contract_qty=None, arranged_total=126.5, old_plan_qty=0, new_plan_qty=28, ) assert r is not None assert r["kind"] == "framework_cumulative" assert r["arrangedTotalQty"] == 154.5 assert r["thisPlanQty"] == 28.0