test_pl_dibang_plan_quantity.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. """地磅月计划量运输联动累加/回减单元测试"""
  2. from decimal import Decimal
  3. from unittest.mock import MagicMock, patch
  4. import pytest
  5. from app.models.db_models import DbInboundOutbound, DbPurchasePlan
  6. from app.models.pl_models import PlTransportDbLink
  7. from app.services.pl_dibang_bridge_service import (
  8. _apply_plan_quantity_delta,
  9. _resolve_link_contributed_qty,
  10. resolve_stop_dibang_partner,
  11. revoke_regeneratable_dibang_for_transport,
  12. )
  13. class _StopStub:
  14. def __init__(self, customer_name: str):
  15. self.customer_name = customer_name
  16. def test_resolve_stop_dibang_partner_load_uses_first_delivery():
  17. load = _StopStub("安庆市山峡化工有限公司")
  18. deliveries = [_StopStub("外部客户A"), _StopStub("外部客户B")]
  19. assert resolve_stop_dibang_partner("load", load, deliveries) == "外部客户A"
  20. def test_resolve_stop_dibang_partner_delivery_uses_load():
  21. load = _StopStub("外部客户A")
  22. deliveries = [_StopStub("安庆市山峡化工有限公司")]
  23. assert resolve_stop_dibang_partner("delivery", load, deliveries) == "外部客户A"
  24. def test_resolve_stop_dibang_partner_load_fallback_without_delivery():
  25. load = _StopStub("安庆市山峡化工有限公司")
  26. assert resolve_stop_dibang_partner("load", load, []) == "安庆市山峡化工有限公司"
  27. def test_apply_plan_quantity_delta_accumulates():
  28. db_plan = DbPurchasePlan(planned_quantity=30.0)
  29. _apply_plan_quantity_delta(db_plan, 31, user_id="u1")
  30. assert db_plan.planned_quantity == 61.0
  31. assert db_plan.update_by == "u1"
  32. def test_apply_plan_quantity_delta_never_below_zero():
  33. db_plan = DbPurchasePlan(planned_quantity=30.0)
  34. _apply_plan_quantity_delta(db_plan, -50, user_id="u1")
  35. assert db_plan.planned_quantity == 0.0
  36. def test_resolve_link_contributed_qty_prefers_link_field():
  37. link = PlTransportDbLink(contributed_qty=Decimal("30"))
  38. inventory = DbInboundOutbound(quantity=Decimal("99"))
  39. assert _resolve_link_contributed_qty(link, inventory) == 30.0
  40. def test_resolve_link_contributed_qty_falls_back_to_inventory():
  41. link = PlTransportDbLink(contributed_qty=None)
  42. inventory = DbInboundOutbound(quantity=Decimal("31"))
  43. assert _resolve_link_contributed_qty(link, inventory) == 31.0
  44. def test_resolve_link_contributed_qty_zero_when_missing():
  45. link = PlTransportDbLink(contributed_qty=None)
  46. assert _resolve_link_contributed_qty(link, None) == 0.0
  47. @patch("app.services.pl_dibang_bridge_service._inventory_has_weighing_slip", return_value=False)
  48. def test_revoke_subtracts_plan_quantity_on_cancel(_mock_weighing):
  49. db_plan = DbPurchasePlan(id="plan-1", tenant_no="t1", planned_quantity=61.0, del_flag=0)
  50. inventory = DbInboundOutbound(
  51. id="inv-1",
  52. tenant_no="t1",
  53. del_flag=0,
  54. status="待入库",
  55. quantity=Decimal("30"),
  56. batch_no="CRKDH0000001",
  57. )
  58. link = PlTransportDbLink(
  59. id="link-1",
  60. tenant_no="t1",
  61. transport_id="tr-1",
  62. db_inventory_id="inv-1",
  63. db_purchase_plan_id="plan-1",
  64. contributed_qty=Decimal("30"),
  65. del_flag=0,
  66. )
  67. db = MagicMock()
  68. link_query = MagicMock()
  69. link_query.filter.return_value.all.return_value = [link]
  70. inv_query = MagicMock()
  71. inv_query.filter.return_value.first.return_value = inventory
  72. plan_query = MagicMock()
  73. plan_query.filter.return_value.first.return_value = db_plan
  74. def query_router(model):
  75. if model is PlTransportDbLink:
  76. return link_query
  77. if model is DbInboundOutbound:
  78. return inv_query
  79. if model is DbPurchasePlan:
  80. return plan_query
  81. return MagicMock()
  82. db.query.side_effect = query_router
  83. revoke_regeneratable_dibang_for_transport(
  84. db,
  85. tenant_no="t1",
  86. transport_id="tr-1",
  87. user_id="u1",
  88. )
  89. assert db_plan.planned_quantity == 31.0
  90. assert inventory.del_flag == 1
  91. assert link.del_flag == 1
  92. @patch("app.services.pl_dibang_bridge_service._inventory_has_weighing_slip", return_value=True)
  93. def test_revoke_blocks_when_weighing_exists(_mock_weighing):
  94. inventory = DbInboundOutbound(
  95. id="inv-1",
  96. tenant_no="t1",
  97. del_flag=0,
  98. status="待入库",
  99. batch_no="CRKDH0000001",
  100. )
  101. link = PlTransportDbLink(
  102. id="link-1",
  103. tenant_no="t1",
  104. transport_id="tr-1",
  105. db_inventory_id="inv-1",
  106. db_purchase_plan_id="plan-1",
  107. contributed_qty=Decimal("30"),
  108. del_flag=0,
  109. )
  110. db = MagicMock()
  111. link_query = MagicMock()
  112. link_query.filter.return_value.all.return_value = [link]
  113. inv_query = MagicMock()
  114. inv_query.filter.return_value.first.return_value = inventory
  115. db.query.side_effect = lambda model: link_query if model is PlTransportDbLink else inv_query
  116. with pytest.raises(ValueError, match="已关联地磅"):
  117. revoke_regeneratable_dibang_for_transport(
  118. db,
  119. tenant_no="t1",
  120. transport_id="tr-1",
  121. user_id="u1",
  122. )
  123. assert inventory.del_flag == 0
  124. assert link.del_flag == 0