factory/apps/sam/tests.py

179 lines
5.9 KiB
Python

from decimal import Decimal
from django.test import TestCase
from apps.sam.models import Contract, Customer
from apps.sam.serializers import ContractRecordSerializer
from rest_framework.exceptions import ParseError
class ContractSettlementTests(TestCase):
def test_sales_contract_record_updates_received_summary(self):
customer = Customer.objects.create(
name='客户A',
contact='张三',
contact_phone='13800000001',
)
contract = Contract.objects.create(
name='销售合同A',
number='SC-001',
amount=1000,
customer=customer,
sign_date='2026-04-20',
)
from apps.sam.models import ContractRecord
ContractRecord.objects.create(
contract=contract,
record_date='2026-04-21',
amount=Decimal('300.00'),
stage_type=ContractRecord.STAGE_FIRST,
)
ContractRecord.objects.create(
contract=contract,
record_date='2026-04-22',
amount=Decimal('200.00'),
stage_type=ContractRecord.STAGE_MIDDLE,
)
contract.refresh_from_db()
self.assertEqual(contract.received_amount, Decimal('500.00'))
self.assertEqual(contract.unreceived_amount, Decimal('500.00'))
self.assertEqual(contract.receive_progress, Decimal('50.00'))
self.assertEqual(contract.status, Contract.STATUS_ACTIVE)
def test_sales_contract_record_delete_refreshes_summary_and_is_physical(self):
customer = Customer.objects.create(
name='客户B',
contact='李四',
contact_phone='13800000002',
)
contract = Contract.objects.create(
name='销售合同B',
number='SC-002',
amount=1000,
customer=customer,
sign_date='2026-04-20',
)
from apps.sam.models import ContractRecord
record = ContractRecord.objects.create(
contract=contract,
record_date='2026-04-21',
amount=Decimal('300.00'),
stage_type=ContractRecord.STAGE_FIRST,
)
record.delete()
contract.refresh_from_db()
self.assertEqual(contract.received_amount, Decimal('0.00'))
self.assertEqual(contract.unreceived_amount, Decimal('1000.00'))
self.assertEqual(contract.receive_progress, Decimal('0.00'))
self.assertEqual(contract.status, Contract.STATUS_DRAFT)
self.assertFalse(ContractRecord._base_manager.filter(pk=record.pk).exists())
def test_sales_contract_delete_is_physical(self):
customer = Customer.objects.create(
name='客户C',
contact='王五',
contact_phone='13800000003',
)
contract = Contract.objects.create(
name='销售合同C',
number='SC-003',
amount=500,
customer=customer,
sign_date='2026-04-20',
)
contract.delete()
self.assertFalse(Contract._base_manager.filter(pk=contract.pk).exists())
def test_sales_contract_status_auto_transitions_by_records(self):
customer = Customer.objects.create(
name='客户D',
contact='赵六',
contact_phone='13800000004',
)
contract = Contract.objects.create(
name='销售合同D',
number='SC-004',
amount=1000,
customer=customer,
sign_date='2026-04-20',
)
from apps.sam.models import ContractRecord
self.assertEqual(contract.status, Contract.STATUS_DRAFT)
first_record = ContractRecord.objects.create(
contract=contract,
record_date='2026-04-21',
amount=Decimal('300.00'),
stage_type=ContractRecord.STAGE_FIRST,
)
contract.refresh_from_db()
self.assertEqual(contract.status, Contract.STATUS_ACTIVE)
ContractRecord.objects.create(
contract=contract,
record_date='2026-04-22',
amount=Decimal('700.00'),
stage_type=ContractRecord.STAGE_FINAL,
)
contract.refresh_from_db()
self.assertEqual(contract.status, Contract.STATUS_DONE)
first_record.delete()
contract.refresh_from_db()
self.assertEqual(contract.status, Contract.STATUS_ACTIVE)
def test_sales_terminated_contract_forbids_record_changes(self):
customer = Customer.objects.create(
name='客户E',
contact='孙七',
contact_phone='13800000005',
)
contract = Contract.objects.create(
name='销售合同E',
number='SC-005',
amount=1000,
customer=customer,
sign_date='2026-04-20',
status=Contract.STATUS_TERMINATED,
)
serializer = ContractRecordSerializer(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 = Contract.STATUS_DRAFT
contract.save(refresh_settlement=False)
from apps.sam.models import ContractRecord
record = ContractRecord.objects.create(
contract=contract,
record_date='2026-04-20',
amount=Decimal('100.00'),
stage_type=ContractRecord.STAGE_OTHER,
)
contract.status = Contract.STATUS_TERMINATED
contract.save(refresh_settlement=False)
with self.assertRaises(ParseError):
from apps.sam.views import ContractRecordViewSet
viewset = ContractRecordViewSet()
viewset.request = None
viewset.perform_destroy(record)