1
0
forked from erp-dev/erp
Files
erpnew/business/tests/test_payment_receipt.py

250 lines
9.5 KiB
Python

from decimal import Decimal
from django.test import TestCase
from django.utils import timezone
from basic_info import models as basic_models
from business import models as business_models, services
from .fixtures import create_basic_fixtures
class PaymentReceiptServiceTestCase(TestCase):
def setUp(self):
(
self.merchant,
self.supplier,
self.warehouse_strict,
self.warehouse_relaxed,
self.product,
self.operator,
) = create_basic_fixtures()
self.customer = basic_models.Customer.objects.create(
merchant=self.merchant,
name='客户B',
mobile='13888888888',
created_by=None,
)
self.bank_account = basic_models.BankAccount.objects.create(
merchant=self.merchant,
name='测试账户',
auto_number='BANK-SVC',
)
def test_create_payment_order_and_approve(self):
order = services.create_payment_order(
merchant=self.merchant,
supplier=self.supplier,
payment_date=timezone.now().date(),
amount='120.50',
discount_amount='20.50',
operator=self.operator,
remarks='付款测试',
bank_account=self.bank_account,
markup='服务层附言',
)
self.assertEqual(order.status, business_models.PaymentOrderStatusEnum.PENDING)
self.assertEqual(order.bank_account, self.bank_account)
self.assertEqual(order.markup, '服务层附言')
self.assertEqual(order.discount_amount, Decimal('20.50'))
self.assertEqual(order.settlement_amount, Decimal('141.00'))
reviewed = services.review_payment_order(
payment_order=order,
target_status=business_models.PaymentOrderStatusEnum.APPROVED,
reviewed_by=self.operator,
)
self.assertEqual(reviewed.status, business_models.PaymentOrderStatusEnum.APPROVED)
balance = business_models.SupplierBalance.objects.get(
merchant=self.merchant,
supplier=self.supplier,
)
self.assertEqual(balance.balance, Decimal('-141.00'))
record = business_models.BalanceChangeRecord.objects.get(
merchant=self.merchant,
source_type=business_models.BalanceChangeSourceEnum.PAYMENT_ORDER,
source_id=order.id,
)
self.assertEqual(record.direction, business_models.BalanceChangeDirectionEnum.DECREASE)
self.assertEqual(record.delta, Decimal('-141.00'))
self.assertEqual(record.balance_after, balance.balance)
with self.assertRaises(ValueError):
services.review_payment_order(
payment_order=order,
target_status=business_models.PaymentOrderStatusEnum.CANCELLED,
reviewed_by=self.operator,
)
def test_create_receipt_order_and_cancel(self):
order = services.create_receipt_order(
merchant=self.merchant,
customer=self.customer,
receipt_date=timezone.now().date(),
amount='80.00',
discount_amount='5',
operator=self.operator,
remarks='收款测试',
bank_account=self.bank_account,
markup='收款附言',
)
self.assertEqual(order.bank_account, self.bank_account)
self.assertEqual(order.discount_amount, Decimal('5'))
self.assertEqual(order.settlement_amount, Decimal('85'))
cancelled = services.review_receipt_order(
receipt_order=order,
target_status=business_models.ReceiptOrderStatusEnum.CANCELLED,
reviewed_by=self.operator,
)
self.assertEqual(cancelled.status, business_models.ReceiptOrderStatusEnum.CANCELLED)
self.assertFalse(
business_models.BalanceChangeRecord.objects.filter(
merchant=self.merchant,
source_type=business_models.BalanceChangeSourceEnum.RECEIPT_ORDER,
source_id=order.id,
).exists()
)
def test_payment_amount_can_be_negative(self):
order = services.create_payment_order(
merchant=self.merchant,
supplier=self.supplier,
payment_date=timezone.now().date(),
amount='-25.50',
operator=self.operator,
)
self.assertEqual(order.amount, Decimal('-25.50'))
def test_payment_discount_can_exceed_amount(self):
order = services.create_payment_order(
merchant=self.merchant,
supplier=self.supplier,
payment_date=timezone.now().date(),
amount='50',
discount_amount='60',
operator=self.operator,
)
self.assertEqual(order.settlement_amount, Decimal('110'))
def test_receipt_discount_can_exceed_amount(self):
order = services.create_receipt_order(
merchant=self.merchant,
customer=self.customer,
receipt_date=timezone.now().date(),
amount='50',
discount_amount='60',
operator=self.operator,
)
self.assertEqual(order.settlement_amount, Decimal('110'))
def test_receipt_amount_can_be_negative(self):
order = services.create_receipt_order(
merchant=self.merchant,
customer=self.customer,
receipt_date=timezone.now().date(),
amount='-40',
operator=self.operator,
)
self.assertEqual(order.amount, Decimal('-40'))
def test_payment_order_rejects_foreign_bank_account(self):
other_merchant = basic_models.Merchant.objects.create(
name='无关商户',
type=basic_models.MerchantTypeEnum.FACTORY,
)
foreign_bank = basic_models.BankAccount.objects.create(
merchant=other_merchant,
name='其他账户',
auto_number='BANK-FOREIGN',
)
with self.assertRaises(ValueError):
services.create_payment_order(
merchant=self.merchant,
supplier=self.supplier,
payment_date=timezone.now().date(),
amount='10',
operator=self.operator,
bank_account=foreign_bank,
)
def test_receipt_order_rejects_foreign_bank_account(self):
other_merchant = basic_models.Merchant.objects.create(
name='第二商户',
type=basic_models.MerchantTypeEnum.FACTORY,
)
foreign_bank = basic_models.BankAccount.objects.create(
merchant=other_merchant,
name='第二账户',
auto_number='BANK-SECOND',
)
with self.assertRaises(ValueError):
services.create_receipt_order(
merchant=self.merchant,
customer=self.customer,
receipt_date=timezone.now().date(),
amount='10',
operator=self.operator,
bank_account=foreign_bank,
)
def test_receipt_approval_is_idempotent(self):
order = services.create_receipt_order(
merchant=self.merchant,
customer=self.customer,
receipt_date=timezone.now().date(),
amount='10',
operator=self.operator,
)
services.review_receipt_order(
receipt_order=order,
target_status=business_models.ReceiptOrderStatusEnum.APPROVED,
reviewed_by=self.operator,
)
reviewed_again = services.review_receipt_order(
receipt_order=order,
target_status=business_models.ReceiptOrderStatusEnum.APPROVED,
reviewed_by=self.operator,
)
self.assertEqual(reviewed_again.status, business_models.ReceiptOrderStatusEnum.APPROVED)
balance = business_models.CustomerBalance.objects.get(
merchant=self.merchant,
customer=self.customer,
)
self.assertEqual(balance.balance, Decimal('-10'))
records = business_models.BalanceChangeRecord.objects.filter(
merchant=self.merchant,
source_type=business_models.BalanceChangeSourceEnum.RECEIPT_ORDER,
source_id=order.id,
)
self.assertEqual(records.count(), 1)
self.assertEqual(records.first().balance_after, balance.balance)
def test_payment_approval_is_idempotent(self):
order = services.create_payment_order(
merchant=self.merchant,
supplier=self.supplier,
payment_date=timezone.now().date(),
amount='75.00',
operator=self.operator,
)
services.review_payment_order(
payment_order=order,
target_status=business_models.PaymentOrderStatusEnum.APPROVED,
reviewed_by=self.operator,
)
services.review_payment_order(
payment_order=order,
target_status=business_models.PaymentOrderStatusEnum.APPROVED,
reviewed_by=self.operator,
)
balance = business_models.SupplierBalance.objects.get(
merchant=self.merchant,
supplier=self.supplier,
)
self.assertEqual(balance.balance, Decimal('-75.00'))
records = business_models.BalanceChangeRecord.objects.filter(
merchant=self.merchant,
source_type=business_models.BalanceChangeSourceEnum.PAYMENT_ORDER,
source_id=order.id,
)
self.assertEqual(records.count(), 1)
self.assertEqual(records.first().balance_after, balance.balance)