diff --git a/InvenTree/InvenTree/format.py b/InvenTree/InvenTree/format.py index afb16bc146..5bf650508d 100644 --- a/InvenTree/InvenTree/format.py +++ b/InvenTree/InvenTree/format.py @@ -3,8 +3,14 @@ import re import string +from django.conf import settings +from django.utils import translation from django.utils.translation import gettext_lazy as _ +from babel import Locale +from babel.numbers import parse_pattern +from djmoney.money import Money + def parse_format_string(fmt_string: str) -> dict: """Extract formatting information from the provided format string. @@ -160,3 +166,34 @@ def extract_named_group(name: str, value: str, fmt_string: str) -> str: # And return the value we are interested in # Note: This will raise an IndexError if the named group was not matched return result.group(name) + + +def format_money(money: Money, decimal_places: int = None, format: str = None) -> str: + """Format money object according to the currently set local + + Args: + decimal_places: Number of decimal places to use + format: Format pattern according LDML / the babel format pattern syntax (https://babel.pocoo.org/en/latest/numbers.html) + + Returns: + str: The formatted string + + Raises: + ValueError: format string is incorrectly specified + """ + language = None and translation.get_language() or settings.LANGUAGE_CODE + locale = Locale.parse(translation.to_locale(language)) + if format: + pattern = parse_pattern(format) + else: + pattern = locale.currency_formats["standard"] + if decimal_places: + pattern.frac_prec = (decimal_places, decimal_places) + + return pattern.apply( + money.amount, + locale, + currency=money.currency.code, + currency_digits=decimal_places is None, + decimal_quantization=decimal_places is not None, + ) diff --git a/InvenTree/InvenTree/helpers_model.py b/InvenTree/InvenTree/helpers_model.py index 2f9272655e..e63419a16f 100644 --- a/InvenTree/InvenTree/helpers_model.py +++ b/InvenTree/InvenTree/helpers_model.py @@ -10,7 +10,6 @@ from django.core.validators import URLValidator from django.db.utils import OperationalError, ProgrammingError from django.utils.translation import gettext_lazy as _ -import moneyed.localization import requests from djmoney.contrib.exchange.models import convert_money from djmoney.money import Money @@ -22,6 +21,7 @@ import InvenTree.helpers_model import InvenTree.version from common.notifications import (InvenTreeNotificationBodies, NotificationBody, trigger_notification) +from InvenTree.format import format_money logger = logging.getLogger('inventree') @@ -167,14 +167,13 @@ def download_image_from_url(remote_url, timeout=2.5): return img -def render_currency(money, decimal_places=None, currency=None, include_symbol=True, min_decimal_places=None, max_decimal_places=None): +def render_currency(money, decimal_places=None, currency=None, min_decimal_places=None, max_decimal_places=None): """Render a currency / Money object to a formatted string (e.g. for reports) Arguments: money: The Money instance to be rendered decimal_places: The number of decimal places to render to. If unspecified, uses the PRICING_DECIMAL_PLACES setting. currency: Optionally convert to the specified currency - include_symbol: Render with the appropriate currency symbol min_decimal_places: The minimum number of decimal places to render to. If unspecified, uses the PRICING_DECIMAL_PLACES_MIN setting. max_decimal_places: The maximum number of decimal places to render to. If unspecified, uses the PRICING_DECIMAL_PLACES setting. """ @@ -216,11 +215,7 @@ def render_currency(money, decimal_places=None, currency=None, include_symbol=Tr decimal_places = max(decimal_places, max_decimal_places) - return moneyed.localization.format_money( - money, - decimal_places=decimal_places, - include_symbol=include_symbol, - ) + return format_money(money, decimal_places=decimal_places) def getModelsWithMixin(mixin_class) -> list: