1
0
forked from erp-dev/erp
Files
erpnew/business/tests/test_amounts.py
2026-07-02 18:26:09 +08:00

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')