forked from erp-dev/erp
beta
This commit is contained in:
59
business/amounts.py
Normal file
59
business/amounts.py
Normal file
@@ -0,0 +1,59 @@
|
||||
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
|
||||
Reference in New Issue
Block a user