test_protocol_pay_mode_switch.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. """缴费模式切换校验"""
  2. import unittest
  3. from app.services.protocol_pay_mode_switch import (
  4. dj_due_amount_mismatch_hint,
  5. validate_payment_details_for_save,
  6. )
  7. class TestValidatePaymentDetailsForSave(unittest.TestCase):
  8. def test_dj_single_dfj_full_contract(self):
  9. validate_payment_details_for_save(
  10. "dj",
  11. 10000,
  12. None,
  13. [{"payStatus": "dfj", "dueAmount": 10000}],
  14. )
  15. def test_dj_allows_multiple_dfj_when_sum_matches(self):
  16. validate_payment_details_for_save(
  17. "dj",
  18. 10000,
  19. None,
  20. [
  21. {"payStatus": "dfj", "dueAmount": 2000},
  22. {"payStatus": "dfj", "dueAmount": 8000},
  23. ],
  24. )
  25. def test_dj_allows_multiple_dfj_wrong_sum(self):
  26. """应缴合计与合同不一致不阻断保存,仅提示。"""
  27. validate_payment_details_for_save(
  28. "dj",
  29. 10000,
  30. None,
  31. [
  32. {"payStatus": "dfj", "dueAmount": 2000},
  33. {"payStatus": "dfj", "dueAmount": 7000},
  34. ],
  35. )
  36. hint = dj_due_amount_mismatch_hint(
  37. 10000,
  38. [
  39. {"payStatus": "dfj", "dueAmount": 2000},
  40. {"payStatus": "dfj", "dueAmount": 7000},
  41. ],
  42. )
  43. self.assertIsNotNone(hint)
  44. self.assertIn("之和应为", hint or "")
  45. def test_dj_partial_paid_remaining(self):
  46. validate_payment_details_for_save(
  47. "dj",
  48. 10000,
  49. None,
  50. [
  51. {"payStatus": "yjf", "dueAmount": 2000},
  52. {"payStatus": "dfj", "dueAmount": 8000},
  53. ],
  54. )
  55. def test_dj_partial_paid_wrong_remaining_allowed(self):
  56. validate_payment_details_for_save(
  57. "dj",
  58. 10000,
  59. None,
  60. [
  61. {"payStatus": "yjf", "dueAmount": 2000},
  62. {"payStatus": "dfj", "dueAmount": 10000},
  63. ],
  64. )
  65. hint = dj_due_amount_mismatch_hint(
  66. 10000,
  67. [
  68. {"payStatus": "yjf", "dueAmount": 2000},
  69. {"payStatus": "dfj", "dueAmount": 10000},
  70. ],
  71. )
  72. self.assertIsNotNone(hint)
  73. def test_djfq_same_as_fq(self):
  74. validate_payment_details_for_save(
  75. "djfq",
  76. 41000,
  77. 4,
  78. [
  79. {"payStatus": "dfj", "installmentNo": 1, "dueAmount": 29360},
  80. {"payStatus": "dfj", "installmentNo": 2, "dueAmount": 3880},
  81. {"payStatus": "dfj", "installmentNo": 3, "dueAmount": 3880},
  82. {"payStatus": "dfj", "installmentNo": 4, "dueAmount": 3880},
  83. ],
  84. installment_ratios=[29360, 3880, 3880, 3880],
  85. )
  86. def test_fq_count_mismatch(self):
  87. with self.assertRaises(ValueError):
  88. validate_payment_details_for_save(
  89. "fq",
  90. 6000,
  91. 6,
  92. [{"payStatus": "dfj", "dueAmount": 6000}],
  93. )
  94. def test_fq_partial_paid_valid(self):
  95. validate_payment_details_for_save(
  96. "fq",
  97. 10000,
  98. 4,
  99. [
  100. {"payStatus": "yjf", "installmentNo": 1, "dueAmount": 2500},
  101. {"payStatus": "yjf", "installmentNo": 2, "dueAmount": 2500},
  102. {"payStatus": "dfj", "installmentNo": 3, "dueAmount": 2500},
  103. {"payStatus": "dfj", "installmentNo": 4, "dueAmount": 2500},
  104. ],
  105. )
  106. def test_fq_jfqrz_rejected(self):
  107. with self.assertRaises(ValueError):
  108. validate_payment_details_for_save(
  109. "fq",
  110. 6000,
  111. 2,
  112. [
  113. {"payStatus": "jfqrz", "dueAmount": 3000},
  114. {"payStatus": "dfj", "dueAmount": 3000},
  115. ],
  116. )
  117. def test_dj_ytf_allowed(self):
  118. """已退费为终态,保存协议单时不应阻断。"""
  119. validate_payment_details_for_save(
  120. "dj",
  121. 10000,
  122. None,
  123. [{"payStatus": "ytf", "dueAmount": 10000}],
  124. )
  125. def test_fq_ytf_allowed(self):
  126. validate_payment_details_for_save(
  127. "fq",
  128. 6000,
  129. 2,
  130. [
  131. {"payStatus": "ytf", "installmentNo": 1, "dueAmount": 3000},
  132. {"payStatus": "dfj", "installmentNo": 2, "dueAmount": 3000},
  133. ],
  134. )
  135. def test_blocking_status_rejected(self):
  136. with self.assertRaises(ValueError):
  137. validate_payment_details_for_save(
  138. "dj",
  139. 10000,
  140. None,
  141. [{"payStatus": "jfqrz", "dueAmount": 10000}],
  142. )
  143. def test_tfqrz_blocking_rejected(self):
  144. with self.assertRaises(ValueError):
  145. validate_payment_details_for_save(
  146. "dj",
  147. 10000,
  148. None,
  149. [{"payStatus": "tfqrz", "dueAmount": 10000}],
  150. )
  151. if __name__ == "__main__":
  152. unittest.main()