from decimal import Decimal from django.test import TestCase from apps.pum.models import Supplier from apps.pum.serializers import PuOrderSerializer from apps.pum.serializers import PuContractRecordSerializer from rest_framework.exceptions import ParseError class PuContractSettlementTests(TestCase): def test_purchase_contract_record_updates_paid_summary(self): supplier = Supplier.objects.create(name='供应商A') from apps.pum.models import PuContract, PuContractRecord contract = PuContract.objects.create( name='采购合同A', number='PC-001', contract_amount=Decimal('2000.00'), supplier=supplier, sign_date='2026-04-20', ) PuContractRecord.objects.create( contract=contract, record_date='2026-04-21', amount=Decimal('800.00'), stage_type=PuContractRecord.STAGE_FIRST, ) contract.refresh_from_db() self.assertEqual(contract.paid_amount, Decimal('800.00')) self.assertEqual(contract.unpaid_amount, Decimal('1200.00')) self.assertEqual(contract.pay_progress, Decimal('40.00')) self.assertEqual(contract.status, contract.STATUS_ACTIVE) def test_purchase_contract_record_delete_refreshes_summary_and_is_physical(self): supplier = Supplier.objects.create(name='供应商C') from apps.pum.models import PuContract, PuContractRecord contract = PuContract.objects.create( name='采购合同C', number='PC-003', contract_amount=Decimal('2000.00'), supplier=supplier, sign_date='2026-04-20', ) record = PuContractRecord.objects.create( contract=contract, record_date='2026-04-21', amount=Decimal('800.00'), stage_type=PuContractRecord.STAGE_FIRST, ) record.delete() contract.refresh_from_db() self.assertEqual(contract.paid_amount, Decimal('0.00')) self.assertEqual(contract.unpaid_amount, Decimal('2000.00')) self.assertEqual(contract.pay_progress, Decimal('0.00')) self.assertEqual(contract.status, contract.STATUS_DRAFT) self.assertFalse(PuContractRecord._base_manager.filter(pk=record.pk).exists()) def test_purchase_contract_delete_is_physical(self): supplier = Supplier.objects.create(name='供应商D') from apps.pum.models import PuContract contract = PuContract.objects.create( name='采购合同D', number='PC-004', contract_amount=Decimal('500.00'), supplier=supplier, sign_date='2026-04-20', ) contract.delete() self.assertFalse(PuContract._base_manager.filter(pk=contract.pk).exists()) def test_purchase_contract_status_auto_transitions_by_records(self): supplier = Supplier.objects.create(name='供应商E') from apps.pum.models import PuContract, PuContractRecord contract = PuContract.objects.create( name='采购合同E', number='PC-005', contract_amount=Decimal('2000.00'), supplier=supplier, sign_date='2026-04-20', ) self.assertEqual(contract.status, PuContract.STATUS_DRAFT) first_record = PuContractRecord.objects.create( contract=contract, record_date='2026-04-21', amount=Decimal('800.00'), stage_type=PuContractRecord.STAGE_FIRST, ) contract.refresh_from_db() self.assertEqual(contract.status, PuContract.STATUS_ACTIVE) PuContractRecord.objects.create( contract=contract, record_date='2026-04-22', amount=Decimal('1200.00'), stage_type=PuContractRecord.STAGE_FINAL, ) contract.refresh_from_db() self.assertEqual(contract.status, PuContract.STATUS_DONE) first_record.delete() contract.refresh_from_db() self.assertEqual(contract.status, PuContract.STATUS_ACTIVE) def test_purchase_terminated_contract_forbids_record_changes(self): supplier = Supplier.objects.create(name='供应商F') from apps.pum.models import PuContract, PuContractRecord contract = PuContract.objects.create( name='采购合同F', number='PC-006', contract_amount=Decimal('1000.00'), supplier=supplier, sign_date='2026-04-20', status=PuContract.STATUS_TERMINATED, ) serializer = PuContractRecordSerializer(data={ 'contract': contract.id, 'record_date': '2026-04-21', 'amount': '100.00', 'stage_type': 10, 'pay_method': 10, }) self.assertFalse(serializer.is_valid()) self.assertIn('合同已终止,不可操作付款流水', str(serializer.errors)) contract.status = PuContract.STATUS_DRAFT contract.save(refresh_settlement=False) record = PuContractRecord.objects.create( contract=contract, record_date='2026-04-20', amount=Decimal('100.00'), stage_type=PuContractRecord.STAGE_OTHER, ) contract.status = PuContract.STATUS_TERMINATED contract.save(refresh_settlement=False) with self.assertRaises(ParseError): from apps.pum.views import PuContractRecordViewSet viewset = PuContractRecordViewSet() viewset.request = None viewset.perform_destroy(record) def test_purchase_order_serializer_accepts_purchase_contract(self): supplier = Supplier.objects.create(name='供应商B') from apps.pum.models import PuContract contract = PuContract.objects.create( name='采购合同B', number='PC-002', contract_amount=Decimal('500.00'), supplier=supplier, sign_date='2026-04-20', ) serializer = PuOrderSerializer(data={'supplier': supplier.id, 'contract': contract.id}) self.assertTrue(serializer.is_valid(), serializer.errors)