179 lines
6.1 KiB
Python
179 lines
6.1 KiB
Python
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)
|