forked from erp-dev/erp
feat: add discount_amount to payment_order and receipt_order, and change total_amount logic
This commit is contained in:
215
api_v1/tests.py
215
api_v1/tests.py
@@ -10,6 +10,7 @@ from django.contrib.auth.models import User, Permission
|
||||
from rest_framework.test import APIClient
|
||||
from rest_framework import status
|
||||
from basic_info.models import (
|
||||
BankAccount,
|
||||
Customer,
|
||||
Employee,
|
||||
EmployeeStatusEnum,
|
||||
@@ -770,6 +771,11 @@ class PaymentOrderAPITestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.merchant = Merchant.objects.create(name='付款商户', type=MerchantTypeEnum.FACTORY)
|
||||
self.supplier = Supplier.objects.create(merchant=self.merchant, name='付款供应商')
|
||||
self.bank_account = BankAccount.objects.create(
|
||||
merchant=self.merchant,
|
||||
name='主账户',
|
||||
auto_number='BANK001',
|
||||
)
|
||||
self.user = User.objects.create_user(username='pay_user', password='pass123')
|
||||
self.employee = Employee.objects.create(
|
||||
merchant=self.merchant,
|
||||
@@ -781,9 +787,12 @@ class PaymentOrderAPITestCase(TestCase):
|
||||
self.client.force_authenticate(user=self.user)
|
||||
self.payload = {
|
||||
'supplier': self.supplier.id,
|
||||
'bank_account': self.bank_account.id,
|
||||
'payment_date': '2025-11-26',
|
||||
'amount': '120.5',
|
||||
'discount_amount': '5.50',
|
||||
'remarks': '付款备注',
|
||||
'markup': '附言',
|
||||
}
|
||||
|
||||
def test_create_payment_order_success(self):
|
||||
@@ -802,6 +811,8 @@ class PaymentOrderAPITestCase(TestCase):
|
||||
response = self.client.post(f'/api/v1/payment-orders/{order_id}/review/', {'action': 'approve'}, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['status'], business_models.PaymentOrderStatusEnum.APPROVED)
|
||||
self.assertEqual(response.data['discount_amount'], '5.50')
|
||||
self.assertEqual(response.data['settlement_amount'], '126.00')
|
||||
response_cancel = self.client.post(
|
||||
f'/api/v1/payment-orders/{order_id}/review/',
|
||||
{'action': 'cancel'},
|
||||
@@ -822,6 +833,35 @@ class PaymentOrderAPITestCase(TestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIn('amount 必须大于 0', response.data['error'])
|
||||
|
||||
def test_payment_order_invalid_bank_account(self):
|
||||
other_merchant = Merchant.objects.create(name='其他商户', type=MerchantTypeEnum.FACTORY)
|
||||
other_bank = BankAccount.objects.create(merchant=other_merchant, name='其他账户', auto_number='BANK999')
|
||||
payload = {**self.payload, 'bank_account': other_bank.id}
|
||||
response = self.client.post('/api/v1/payment-orders/', payload, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIn('银行账户不存在', response.data['error'])
|
||||
|
||||
def test_payment_order_stores_bank_account_and_markup(self):
|
||||
response = self.client.post('/api/v1/payment-orders/', self.payload, format='json')
|
||||
order = business_models.PaymentOrder.objects.get(id=response.data['id'])
|
||||
self.assertEqual(order.bank_account_id, self.bank_account.id)
|
||||
self.assertEqual(order.markup, '附言')
|
||||
self.assertEqual(str(order.discount_amount), '5.50')
|
||||
self.assertEqual(str(order.settlement_amount), '126.00')
|
||||
|
||||
def test_payment_order_discount_can_exceed_amount(self):
|
||||
payload = {**self.payload, 'discount_amount': '200.00'}
|
||||
response = self.client.post('/api/v1/payment-orders/', payload, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
order = business_models.PaymentOrder.objects.get(id=response.data['id'])
|
||||
self.assertEqual(str(order.discount_amount), '200.00')
|
||||
self.assertEqual(str(order.settlement_amount), '320.50')
|
||||
|
||||
def test_payment_order_discount_cannot_be_negative(self):
|
||||
payload = {**self.payload, 'discount_amount': '-1'}
|
||||
response = self.client.post('/api/v1/payment-orders/', payload, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIn('discount_amount 不能小于 0', response.data['error'])
|
||||
|
||||
class ReceiptOrderAPITestCase(TestCase):
|
||||
def setUp(self):
|
||||
@@ -832,6 +872,11 @@ class ReceiptOrderAPITestCase(TestCase):
|
||||
mobile='13812345678',
|
||||
created_by=None,
|
||||
)
|
||||
self.bank_account = BankAccount.objects.create(
|
||||
merchant=self.merchant,
|
||||
name='收款账户',
|
||||
auto_number='BANK100',
|
||||
)
|
||||
self.user = User.objects.create_user(username='receipt_user', password='pass123')
|
||||
self.employee = Employee.objects.create(
|
||||
merchant=self.merchant,
|
||||
@@ -843,9 +888,12 @@ class ReceiptOrderAPITestCase(TestCase):
|
||||
self.client.force_authenticate(user=self.user)
|
||||
self.payload = {
|
||||
'customer': self.customer.id,
|
||||
'bank_account': self.bank_account.id,
|
||||
'receipt_date': '2025-11-26',
|
||||
'amount': '88.00',
|
||||
'discount_amount': '3.00',
|
||||
'remarks': '收款备注',
|
||||
'markup': '收款附言',
|
||||
}
|
||||
|
||||
def test_create_receipt_order_success(self):
|
||||
@@ -868,6 +916,8 @@ class ReceiptOrderAPITestCase(TestCase):
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['status'], business_models.ReceiptOrderStatusEnum.CANCELLED)
|
||||
self.assertEqual(response.data['discount_amount'], '3.00')
|
||||
self.assertEqual(response.data['settlement_amount'], '91.00')
|
||||
|
||||
def test_receipt_order_requires_amount(self):
|
||||
payload = {**self.payload}
|
||||
@@ -882,6 +932,34 @@ class ReceiptOrderAPITestCase(TestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIn('amount 必须大于 0', response.data['error'])
|
||||
|
||||
def test_receipt_order_stores_bank_account_and_markup(self):
|
||||
response = self.client.post('/api/v1/receipt-orders/', self.payload, format='json')
|
||||
order = business_models.ReceiptOrder.objects.get(id=response.data['id'])
|
||||
self.assertEqual(order.bank_account_id, self.bank_account.id)
|
||||
self.assertEqual(order.markup, '收款附言')
|
||||
self.assertEqual(str(order.discount_amount), '3.00')
|
||||
self.assertEqual(str(order.settlement_amount), '91.00')
|
||||
|
||||
def test_receipt_order_discount_can_exceed_amount(self):
|
||||
payload = {**self.payload, 'discount_amount': '150.00'}
|
||||
response = self.client.post('/api/v1/receipt-orders/', payload, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
order = business_models.ReceiptOrder.objects.get(id=response.data['id'])
|
||||
self.assertEqual(str(order.settlement_amount), '238.00')
|
||||
|
||||
def test_receipt_order_discount_cannot_be_negative(self):
|
||||
payload = {**self.payload, 'discount_amount': '-1'}
|
||||
response = self.client.post('/api/v1/receipt-orders/', payload, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIn('discount_amount 不能小于 0', response.data['error'])
|
||||
|
||||
def test_receipt_order_invalid_bank_account(self):
|
||||
other_merchant = Merchant.objects.create(name='其他收款商户', type=MerchantTypeEnum.FACTORY)
|
||||
other_bank = BankAccount.objects.create(merchant=other_merchant, name='其他收款账户', auto_number='BANK888')
|
||||
payload = {**self.payload, 'bank_account': other_bank.id}
|
||||
response = self.client.post('/api/v1/receipt-orders/', payload, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIn('银行账户不存在', response.data['error'])
|
||||
|
||||
class CustomerBalanceAPITestCase(TestCase):
|
||||
def setUp(self):
|
||||
@@ -976,6 +1054,143 @@ class SupplierBalanceAPITestCase(TestCase):
|
||||
response = self.client.get(f'/api/v1/suppliers/{self.supplier.id}/balance/')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['supplier'], self.supplier.id)
|
||||
|
||||
|
||||
class StatementRecordAPITestCase(TestCase):
|
||||
"""对账单单条记录查询 API 测试"""
|
||||
|
||||
def setUp(self):
|
||||
self.merchant = Merchant.objects.create(name='对账商户', type=MerchantTypeEnum.FACTORY)
|
||||
self.customer = Customer.objects.create(
|
||||
merchant=self.merchant,
|
||||
name='对账客户',
|
||||
mobile='13800000000',
|
||||
created_by=None,
|
||||
)
|
||||
self.supplier = Supplier.objects.create(merchant=self.merchant, name='对账供应商')
|
||||
category = ProductCategory.objects.create(
|
||||
merchant=self.merchant,
|
||||
name='对账品类',
|
||||
product_prefix='STM',
|
||||
)
|
||||
self.product = Product.objects.create(
|
||||
merchant=self.merchant,
|
||||
category=category,
|
||||
name='对账产品',
|
||||
human_id='STM-001',
|
||||
unit=ProductUnitEnum.METER,
|
||||
)
|
||||
self.warehouse = WareHouse.objects.create(
|
||||
merchant=self.merchant,
|
||||
name='对账仓库',
|
||||
mode=WareHouseModeEnum.UNRESTRICTED,
|
||||
)
|
||||
self.user = User.objects.create_user(username='statement_user', password='pass123')
|
||||
self.employee = Employee.objects.create(
|
||||
merchant=self.merchant,
|
||||
sys_user=self.user,
|
||||
name='财务',
|
||||
status=EmployeeStatusEnum.ACTIVE,
|
||||
)
|
||||
self.client = APIClient()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
|
||||
self.sales_order = business_models.SalesOrder.objects.create(
|
||||
merchant=self.merchant,
|
||||
customer=self.customer,
|
||||
sales_date='2025-11-20',
|
||||
operator=self.employee,
|
||||
warehouse=self.warehouse,
|
||||
status=business_models.SalesOrderStatusEnum.APPROVED,
|
||||
)
|
||||
business_models.SalesOrderItem.objects.create(
|
||||
sales_order=self.sales_order,
|
||||
product=self.product,
|
||||
price=Decimal('12.50'),
|
||||
quantity=Decimal('5'),
|
||||
unit='米',
|
||||
empty_diff_percent=Decimal('0'),
|
||||
)
|
||||
|
||||
self.purchase_order = business_models.PurchaseOrder.objects.create(
|
||||
merchant=self.merchant,
|
||||
supplier=self.supplier,
|
||||
purchase_date='2025-11-21',
|
||||
operator=self.employee,
|
||||
warehouse=self.warehouse,
|
||||
status=business_models.PurchaseOrderStatusEnum.APPROVED,
|
||||
)
|
||||
business_models.PurchaseOrderItem.objects.create(
|
||||
purchase_order=self.purchase_order,
|
||||
product=self.product,
|
||||
price=Decimal('8.30'),
|
||||
quantity=Decimal('10'),
|
||||
unit='米',
|
||||
empty_diff_percent=Decimal('0'),
|
||||
)
|
||||
|
||||
def test_get_customer_sales_order_record(self):
|
||||
response = self.client.get(
|
||||
'/api/v1/statements/record/',
|
||||
{
|
||||
'counterparty_type': 'customer',
|
||||
'counterparty_id': self.customer.id,
|
||||
'order_type': 'sales_order',
|
||||
'order_id': self.sales_order.id,
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['counterparty'], self.customer.id)
|
||||
self.assertEqual(response.data['counterparty_name'], self.customer.name)
|
||||
self.assertEqual(len(response.data['records']), 1)
|
||||
record = response.data['records'][0]
|
||||
self.assertEqual(record['source_type'], 'sales_order')
|
||||
self.assertEqual(record['source_id'], self.sales_order.id)
|
||||
self.assertEqual(record['counterparty'], self.customer.id)
|
||||
|
||||
def test_get_supplier_purchase_order_record(self):
|
||||
response = self.client.get(
|
||||
'/api/v1/statements/record/',
|
||||
{
|
||||
'counterparty_type': 'supplier',
|
||||
'counterparty_id': self.supplier.id,
|
||||
'order_type': 'purchase_order',
|
||||
'order_id': self.purchase_order.id,
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
record = response.data['records'][0]
|
||||
self.assertEqual(record['source_type'], 'purchase_order')
|
||||
self.assertEqual(record['source_id'], self.purchase_order.id)
|
||||
self.assertEqual(record['counterparty'], self.supplier.id)
|
||||
|
||||
def test_statement_record_not_found(self):
|
||||
response = self.client.get(
|
||||
'/api/v1/statements/record/',
|
||||
{
|
||||
'counterparty_type': 'customer',
|
||||
'counterparty_id': self.customer.id,
|
||||
'order_type': 'sales_order',
|
||||
'order_id': 9999,
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
self.assertIn('未找到匹配的对账记录', response.data['error'])
|
||||
|
||||
def test_invalid_order_type_returns_400(self):
|
||||
response = self.client.get(
|
||||
'/api/v1/statements/record/',
|
||||
{
|
||||
'counterparty_type': 'customer',
|
||||
'counterparty_id': self.customer.id,
|
||||
'order_type': 'unknown',
|
||||
'order_id': self.sales_order.id,
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIn('order_type', response.data)
|
||||
|
||||
|
||||
@override_settings(
|
||||
CELERY_TASK_ALWAYS_EAGER=True,
|
||||
CELERY_TASK_EAGER_PROPAGATES=True,
|
||||
|
||||
Reference in New Issue
Block a user