"""按样本缴费:转账状态机与批次已缴/欠缴计算""" from decimal import Decimal import unittest from app.services.protocol_transfer_status import ( can_confirm_receipt, can_edit_transfer, can_submit_receipt, schedule_paid_and_arrears, ) class TestTransferStatusRules(unittest.TestCase): def test_submit_only_dfj(self): self.assertTrue(can_submit_receipt("dfj")) self.assertFalse(can_submit_receipt("jfqrz")) self.assertFalse(can_submit_receipt("yjf")) self.assertFalse(can_submit_receipt("")) self.assertFalse(can_submit_receipt(None)) def test_confirm_only_jfqrz(self): self.assertTrue(can_confirm_receipt("jfqrz")) self.assertFalse(can_confirm_receipt("dfj")) self.assertFalse(can_confirm_receipt("yjf")) def test_edit_before_finance_confirm(self): """已付款、付款确认中可编辑;付款完成不可编辑。""" self.assertTrue(can_edit_transfer("dfj")) self.assertTrue(can_edit_transfer("jfqrz")) self.assertFalse(can_edit_transfer("yjf")) self.assertFalse(can_edit_transfer("")) self.assertFalse(can_edit_transfer(None)) def test_schedule_arrears(self): paid, arrears = schedule_paid_and_arrears( due=Decimal("1000"), confirmed_transfers=[Decimal("300"), Decimal("200")], ) self.assertEqual(paid, Decimal("500")) self.assertEqual(arrears, Decimal("500")) def test_schedule_arrears_overpay(self): paid, arrears = schedule_paid_and_arrears( due=Decimal("100"), confirmed_transfers=[Decimal("60"), Decimal("50")], ) self.assertEqual(paid, Decimal("110")) self.assertEqual(arrears, Decimal("-10")) class TestProtocolWithdrawReceipt(unittest.TestCase): def test_withdraw_sets_dfj_keeps_finance_remark(self): from types import SimpleNamespace from unittest.mock import MagicMock from app.crud import protocol_sample_payment as psp t = SimpleNamespace( id="t1", pay_status="jfqrz", finance_remark="keep-me", finance_confirm_attachments="http://x", update_by=None, update_time=None, tenant_no="zkxw", del_flag=0, ) db = MagicMock() orig = psp._get_transfer_with_schedule_lock psp._get_transfer_with_schedule_lock = lambda *a, **k: t try: out = psp.withdraw_receipt( db, transfer_id="t1", tenant_no="zkxw", user_id="u1" ) self.assertEqual(out.pay_status, "dfj") self.assertEqual(out.finance_remark, "keep-me") self.assertEqual(out.finance_confirm_attachments, "http://x") db.commit.assert_called() finally: psp._get_transfer_with_schedule_lock = orig def test_withdraw_rejects_non_jfqrz(self): from types import SimpleNamespace from unittest.mock import MagicMock from app.crud import protocol_sample_payment as psp t = SimpleNamespace( id="t1", pay_status="dfj", finance_remark="x", tenant_no="zkxw", del_flag=0, ) db = MagicMock() orig = psp._get_transfer_with_schedule_lock psp._get_transfer_with_schedule_lock = lambda *a, **k: t try: with self.assertRaises(ValueError) as ctx: psp.withdraw_receipt( db, transfer_id="t1", tenant_no="zkxw", user_id="u1" ) self.assertIn("撤回", str(ctx.exception)) finally: psp._get_transfer_with_schedule_lock = orig if __name__ == "__main__": unittest.main()