"""缴费模式切换校验""" import unittest from app.services.protocol_pay_mode_switch import ( dj_due_amount_mismatch_hint, validate_payment_details_for_save, ) class TestValidatePaymentDetailsForSave(unittest.TestCase): def test_dj_single_dfj_full_contract(self): validate_payment_details_for_save( "dj", 10000, None, [{"payStatus": "dfj", "dueAmount": 10000}], ) def test_dj_allows_multiple_dfj_when_sum_matches(self): validate_payment_details_for_save( "dj", 10000, None, [ {"payStatus": "dfj", "dueAmount": 2000}, {"payStatus": "dfj", "dueAmount": 8000}, ], ) def test_dj_allows_multiple_dfj_wrong_sum(self): """应缴合计与合同不一致不阻断保存,仅提示。""" validate_payment_details_for_save( "dj", 10000, None, [ {"payStatus": "dfj", "dueAmount": 2000}, {"payStatus": "dfj", "dueAmount": 7000}, ], ) hint = dj_due_amount_mismatch_hint( 10000, [ {"payStatus": "dfj", "dueAmount": 2000}, {"payStatus": "dfj", "dueAmount": 7000}, ], ) self.assertIsNotNone(hint) self.assertIn("之和应为", hint or "") def test_dj_partial_paid_remaining(self): validate_payment_details_for_save( "dj", 10000, None, [ {"payStatus": "yjf", "dueAmount": 2000}, {"payStatus": "dfj", "dueAmount": 8000}, ], ) def test_dj_partial_paid_wrong_remaining_allowed(self): validate_payment_details_for_save( "dj", 10000, None, [ {"payStatus": "yjf", "dueAmount": 2000}, {"payStatus": "dfj", "dueAmount": 10000}, ], ) hint = dj_due_amount_mismatch_hint( 10000, [ {"payStatus": "yjf", "dueAmount": 2000}, {"payStatus": "dfj", "dueAmount": 10000}, ], ) self.assertIsNotNone(hint) def test_djfq_same_as_fq(self): validate_payment_details_for_save( "djfq", 41000, 4, [ {"payStatus": "dfj", "installmentNo": 1, "dueAmount": 29360}, {"payStatus": "dfj", "installmentNo": 2, "dueAmount": 3880}, {"payStatus": "dfj", "installmentNo": 3, "dueAmount": 3880}, {"payStatus": "dfj", "installmentNo": 4, "dueAmount": 3880}, ], installment_ratios=[29360, 3880, 3880, 3880], ) def test_fq_count_mismatch(self): with self.assertRaises(ValueError): validate_payment_details_for_save( "fq", 6000, 6, [{"payStatus": "dfj", "dueAmount": 6000}], ) def test_fq_partial_paid_valid(self): validate_payment_details_for_save( "fq", 10000, 4, [ {"payStatus": "yjf", "installmentNo": 1, "dueAmount": 2500}, {"payStatus": "yjf", "installmentNo": 2, "dueAmount": 2500}, {"payStatus": "dfj", "installmentNo": 3, "dueAmount": 2500}, {"payStatus": "dfj", "installmentNo": 4, "dueAmount": 2500}, ], ) def test_fq_jfqrz_rejected(self): with self.assertRaises(ValueError): validate_payment_details_for_save( "fq", 6000, 2, [ {"payStatus": "jfqrz", "dueAmount": 3000}, {"payStatus": "dfj", "dueAmount": 3000}, ], ) def test_dj_ytf_allowed(self): """已退费为终态,保存协议单时不应阻断。""" validate_payment_details_for_save( "dj", 10000, None, [{"payStatus": "ytf", "dueAmount": 10000}], ) def test_fq_ytf_allowed(self): validate_payment_details_for_save( "fq", 6000, 2, [ {"payStatus": "ytf", "installmentNo": 1, "dueAmount": 3000}, {"payStatus": "dfj", "installmentNo": 2, "dueAmount": 3000}, ], ) def test_blocking_status_rejected(self): with self.assertRaises(ValueError): validate_payment_details_for_save( "dj", 10000, None, [{"payStatus": "jfqrz", "dueAmount": 10000}], ) def test_tfqrz_blocking_rejected(self): with self.assertRaises(ValueError): validate_payment_details_for_save( "dj", 10000, None, [{"payStatus": "tfqrz", "dueAmount": 10000}], ) if __name__ == "__main__": unittest.main()