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

60 lines
2.0 KiB
Python

from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
from django.conf import settings
AMOUNT_MODE_HAOBUYE_INTEGER = 'haobuye_integer_round_half_up'
AMOUNT_MODE_STANDARD_DECIMAL_2 = 'standard_decimal_2'
AMOUNT_MODES = {
AMOUNT_MODE_HAOBUYE_INTEGER,
AMOUNT_MODE_STANDARD_DECIMAL_2,
}
INTEGER_QUANT = Decimal('1')
DECIMAL_2_QUANT = Decimal('0.01')
def to_decimal(value, *, field_name: str = 'value') -> Decimal:
try:
return Decimal(str(value))
except (InvalidOperation, TypeError, ValueError) as exc:
raise ValueError(f'{field_name} 必须是数字') from exc
def normalize_money_amount(value, *, field_name: str = 'amount') -> Decimal:
decimal_value = to_decimal(value, field_name=field_name)
return decimal_value.quantize(_money_quant(), rounding=ROUND_HALF_UP)
def calculate_line_amount(*, quantity, price, standard_quantity=None) -> Decimal:
raw_quantity = quantity
if _amount_mode() == AMOUNT_MODE_STANDARD_DECIMAL_2 and standard_quantity is not None:
raw_quantity = standard_quantity
quantity_value = to_decimal(
raw_quantity,
field_name='quantity',
)
price_value = to_decimal(price, field_name='price')
return (quantity_value * price_value).quantize(_money_quant(), rounding=ROUND_HALF_UP)
def calculate_settlement_amount(*, amount, discount_amount=Decimal('0')) -> Decimal:
return normalize_money_amount(
normalize_money_amount(amount, field_name='amount')
+ normalize_money_amount(discount_amount or Decimal('0'), field_name='discount_amount'),
field_name='settlement_amount',
)
def _amount_mode() -> str:
mode = getattr(settings, 'BUSINESS_AMOUNT_MODE', AMOUNT_MODE_HAOBUYE_INTEGER)
if mode not in AMOUNT_MODES:
raise ValueError(f'BUSINESS_AMOUNT_MODE 不合法: {mode}')
return mode
def _money_quant() -> Decimal:
if _amount_mode() == AMOUNT_MODE_STANDARD_DECIMAL_2:
return DECIMAL_2_QUANT
return INTEGER_QUANT