forked from erp-dev/erp
102 lines
4.1 KiB
Python
102 lines
4.1 KiB
Python
from decimal import Decimal
|
|
|
|
from django.test import TestCase, override_settings
|
|
from django.utils import timezone
|
|
|
|
from basic_info import models as basic_models
|
|
from business import services
|
|
from business.amounts import calculate_line_amount, normalize_money_amount
|
|
|
|
from .fixtures import create_basic_fixtures
|
|
|
|
|
|
class BusinessAmountRulesTestCase(TestCase):
|
|
def setUp(self):
|
|
(
|
|
self.merchant,
|
|
self.supplier,
|
|
self.warehouse_strict,
|
|
self.warehouse_relaxed,
|
|
self.product,
|
|
self.operator,
|
|
) = create_basic_fixtures()
|
|
|
|
def test_line_amount_rounds_half_up_to_integer(self):
|
|
self.assertEqual(calculate_line_amount(quantity='1', price='1.49'), Decimal('1'))
|
|
self.assertEqual(calculate_line_amount(quantity='1', price='1.50'), Decimal('2'))
|
|
self.assertEqual(calculate_line_amount(quantity='1.5', price='1.5'), Decimal('2'))
|
|
self.assertEqual(calculate_line_amount(quantity='1', price='2.5'), Decimal('3'))
|
|
|
|
def test_order_total_sums_rounded_line_amounts(self):
|
|
order = services.create_purchase_order(
|
|
merchant=self.merchant,
|
|
supplier=self.supplier,
|
|
order_date=timezone.now().date(),
|
|
warehouse=self.warehouse_relaxed,
|
|
operator=self.operator,
|
|
items=[
|
|
{'product_id': self.product.id, 'quantity': '1', 'num_of_rolls': 1, 'price': '1.5', 'unit': '米'},
|
|
{'product_id': self.product.id, 'quantity': '1', 'num_of_rolls': 1, 'price': '1.5', 'unit': '米'},
|
|
],
|
|
)
|
|
|
|
self.assertEqual([item.total_amount() for item in order.items.order_by('id')], [Decimal('2'), Decimal('2')])
|
|
self.assertEqual(order.get_total_amount(), Decimal('4'))
|
|
|
|
def test_payment_and_receipt_amounts_are_normalized_on_create(self):
|
|
payment = services.create_payment_order(
|
|
merchant=self.merchant,
|
|
supplier=self.supplier,
|
|
payment_date=timezone.now().date(),
|
|
amount='120.50',
|
|
discount_amount='20.49',
|
|
operator=self.operator,
|
|
)
|
|
self.assertEqual(payment.amount, Decimal('121'))
|
|
self.assertEqual(payment.discount_amount, Decimal('20'))
|
|
self.assertEqual(payment.settlement_amount, Decimal('141'))
|
|
|
|
customer = basic_models.Customer.objects.create(
|
|
merchant=self.merchant,
|
|
name='金额测试客户',
|
|
created_by=None,
|
|
)
|
|
receipt = services.create_receipt_order(
|
|
merchant=self.merchant,
|
|
customer=customer,
|
|
receipt_date=timezone.now().date(),
|
|
amount='80.49',
|
|
discount_amount='5.50',
|
|
operator=self.operator,
|
|
)
|
|
self.assertEqual(receipt.amount, Decimal('80'))
|
|
self.assertEqual(receipt.discount_amount, Decimal('6'))
|
|
self.assertEqual(receipt.settlement_amount, Decimal('86'))
|
|
|
|
def test_normalize_money_amount_rounds_negative_half_away_from_zero(self):
|
|
self.assertEqual(normalize_money_amount('-25.50'), Decimal('-26'))
|
|
|
|
@override_settings(BUSINESS_AMOUNT_MODE='standard_decimal_2')
|
|
def test_standard_decimal_mode_preserves_original_precision(self):
|
|
self.assertEqual(
|
|
calculate_line_amount(quantity='10', standard_quantity='9.50', price='12.345'),
|
|
Decimal('117.28'),
|
|
)
|
|
|
|
payment = services.create_payment_order(
|
|
merchant=self.merchant,
|
|
supplier=self.supplier,
|
|
payment_date=timezone.now().date(),
|
|
amount='120.50',
|
|
discount_amount='20.49',
|
|
operator=self.operator,
|
|
)
|
|
self.assertEqual(payment.amount, Decimal('120.50'))
|
|
self.assertEqual(payment.discount_amount, Decimal('20.49'))
|
|
self.assertEqual(payment.settlement_amount, Decimal('140.99'))
|
|
|
|
@override_settings(BUSINESS_AMOUNT_MODE='unknown_mode')
|
|
def test_invalid_amount_mode_fails_fast(self):
|
|
with self.assertRaisesMessage(ValueError, 'BUSINESS_AMOUNT_MODE 不合法'):
|
|
calculate_line_amount(quantity='1', price='1')
|