test_pl_feedback_brand_qty.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. from decimal import Decimal
  2. import pytest
  3. from app.services.pl_feedback_brand_qty import format_brand_qty_summary, require_brand_qtys_if_needed
  4. def test_format_brand_qty_summary():
  5. s = format_brand_qty_summary([
  6. {"brandName": "君正", "qty": Decimal("16")},
  7. {"brandName": "红四方", "qty": Decimal("12.000")},
  8. ])
  9. assert s == "君正 16 / 红四方 12"
  10. def test_format_brand_qty_summary_empty():
  11. assert format_brand_qty_summary([]) is None
  12. def test_format_brand_qty_summary_zero_only():
  13. assert format_brand_qty_summary([{"brandName": "君正", "qty": Decimal("0")}]) is None
  14. def test_require_skips_when_no_brand_mode():
  15. require_brand_qtys_if_needed(
  16. brand_mode=None,
  17. required_brand_id=None,
  18. actual_qty=Decimal("10"),
  19. rows=[],
  20. enforce=True,
  21. )
  22. def test_require_skips_when_not_enforced():
  23. require_brand_qtys_if_needed(
  24. brand_mode="any",
  25. required_brand_id=None,
  26. actual_qty=Decimal("10"),
  27. rows=[],
  28. enforce=False,
  29. )
  30. def test_require_enforces_when_completed():
  31. with pytest.raises(ValueError, match="至少一个品牌数量"):
  32. require_brand_qtys_if_needed(
  33. brand_mode="any",
  34. required_brand_id=None,
  35. actual_qty=Decimal("10"),
  36. rows=[],
  37. enforce=True,
  38. )
  39. def test_require_calls_validate_when_positive_rows(monkeypatch):
  40. called = {}
  41. def mock_validate(**kwargs):
  42. called.update(kwargs)
  43. monkeypatch.setattr(
  44. "app.services.pl_feedback_brand_qty.validate_brand_qty_rows",
  45. mock_validate,
  46. )
  47. rows = [{"brandId": "b1", "brandName": "君正", "qty": Decimal("10")}]
  48. require_brand_qtys_if_needed(
  49. brand_mode="any",
  50. required_brand_id=None,
  51. actual_qty=Decimal("10"),
  52. rows=rows,
  53. enforce=True,
  54. )
  55. assert called["brand_mode"] == "any"
  56. assert called["actual_qty"] == Decimal("10")
  57. assert called["rows"] == rows
  58. def test_persist_io_item_brand_qtys_writes_when_brand_mode_missing():
  59. """计划行 brand_mode 丢失时,客户端提交的多品牌明细仍应落库(不能只软删不写)。"""
  60. from app.services.pl_feedback_brand_qty import persist_io_item_brand_qtys
  61. class _Row:
  62. def __init__(self):
  63. self.del_flag = 0
  64. self.update_by = None
  65. existing = [_Row()]
  66. added = []
  67. class _Query:
  68. def filter(self, *args, **kwargs):
  69. return self
  70. def all(self):
  71. return existing
  72. class _Db:
  73. def query(self, model):
  74. return _Query()
  75. def add(self, obj):
  76. added.append(obj)
  77. class _Model:
  78. order_item_id = object()
  79. tenant_no = object()
  80. del_flag = object()
  81. def __init__(self, **kwargs):
  82. self.__dict__.update(kwargs)
  83. persist_io_item_brand_qtys(
  84. _Db(),
  85. model=_Model,
  86. tenant_no="t1",
  87. order_id="o1",
  88. order_item_id="i1",
  89. plan_product_id="p1",
  90. brand_mode=None,
  91. rows=[
  92. {"brandId": "b1", "brandName": "君正", "qty": Decimal("20")},
  93. {"brandId": "b2", "brandName": "红四方", "qty": Decimal("30")},
  94. ],
  95. user_id="u1",
  96. )
  97. assert existing[0].del_flag == 1
  98. assert len(added) == 2
  99. assert {a.brand_id for a in added} == {"b1", "b2"}