diff --git a/app/apps/mini_tools/utils/__init__.py b/app/apps/mini_tools/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/apps/mini_tools/utils/exchange_rate_map.py b/app/apps/mini_tools/utils/exchange_rate_map.py new file mode 100644 index 0000000..0624517 --- /dev/null +++ b/app/apps/mini_tools/utils/exchange_rate_map.py @@ -0,0 +1,85 @@ +from typing import Dict + +from django.db.models import Func, F, Value +from django.db.models.functions import Extract +from django.utils import timezone + +from apps.currencies.models import ExchangeRate + + +def get_currency_exchange_map(date=None) -> Dict[str, dict]: + """ + Creates a nested dictionary of exchange rates and currency information. + + Returns: + { + 'BTC': { + 'decimal_places': 8, + 'prefix': '₿', + 'suffix': '', + 'rates': {'USD': Decimal('34000.00'), 'EUR': Decimal('31000.00')} + }, + 'USD': { + 'decimal_places': 2, + 'prefix': '$', + 'suffix': '', + 'rates': {'BTC': Decimal('0.0000294'), 'EUR': Decimal('0.91')} + }, + ... + } + """ + if date is None: + date = timezone.localtime(timezone.now()) + + # Get all exchange rates for the closest date + exchange_rates = ( + ExchangeRate.objects.select_related( + "from_currency", "to_currency" + ) # Optimize currency queries + .annotate( + date_diff=Func(Extract(F("date") - Value(date), "epoch"), function="ABS"), + effective_rate=F("rate"), + ) + .order_by("from_currency", "to_currency", "date_diff") + .distinct("from_currency", "to_currency") + ) + + # Initialize the result dictionary + rate_map = {} + + # Build the exchange rate mapping with currency info + for rate in exchange_rates: + # Add from_currency info if not exists + if rate.from_currency.name not in rate_map: + rate_map[rate.from_currency.name] = { + "decimal_places": rate.from_currency.decimal_places, + "prefix": rate.from_currency.prefix, + "suffix": rate.from_currency.suffix, + "rates": {}, + } + + # Add to_currency info if not exists + if rate.to_currency.name not in rate_map: + rate_map[rate.to_currency.name] = { + "decimal_places": rate.to_currency.decimal_places, + "prefix": rate.to_currency.prefix, + "suffix": rate.to_currency.suffix, + "rates": {}, + } + + # Add direct rate + rate_map[rate.from_currency.name]["rates"][rate.to_currency.name] = { + "rate": rate.rate, + "decimal_places": rate.to_currency.decimal_places, + "prefix": rate.to_currency.prefix, + "suffix": rate.to_currency.suffix, + } + # Add inverse rate + rate_map[rate.to_currency.name]["rates"][rate.from_currency.name] = { + "rate": 1 / rate.rate, + "decimal_places": rate.from_currency.decimal_places, + "prefix": rate.from_currency.prefix, + "suffix": rate.from_currency.suffix, + } + + return rate_map diff --git a/app/apps/mini_tools/views.py b/app/apps/mini_tools/views.py index 40ef0c8..2acd039 100644 --- a/app/apps/mini_tools/views.py +++ b/app/apps/mini_tools/views.py @@ -5,6 +5,7 @@ from apps.common.widgets.decimal import convert_to_decimal from apps.currencies.models import Currency from apps.currencies.utils.convert import convert from apps.mini_tools.forms import CurrencyConverterForm +from apps.mini_tools.utils.exchange_rate_map import get_currency_exchange_map @login_required @@ -14,11 +15,13 @@ def unit_price_calculator(request): @login_required def currency_converter(request): + rate_map = get_currency_exchange_map() + form = CurrencyConverterForm() return render( request, "mini_tools/currency_converter/currency_converter.html", - context={"form": form}, + context={"form": form, "rate_map": rate_map}, ) diff --git a/app/templates/cotton/ui/info_card.html b/app/templates/cotton/ui/info_card.html index 09c29ba..83d7cc5 100644 --- a/app/templates/cotton/ui/info_card.html +++ b/app/templates/cotton/ui/info_card.html @@ -1,9 +1,9 @@
- + {% if icon %}{% else %}{{ title.0 }}{% endif %}
{{ title }}{% if help_text %}{% include 'includes/help_icon.html' with content=help_text %}{% endif %}
{{ slot }}
-
\ No newline at end of file + diff --git a/app/templates/mini_tools/currency_converter/currency_converter.html b/app/templates/mini_tools/currency_converter/currency_converter.html index 59f50d3..b7be678 100644 --- a/app/templates/mini_tools/currency_converter/currency_converter.html +++ b/app/templates/mini_tools/currency_converter/currency_converter.html @@ -45,7 +45,7 @@
-
{% trans 'Invert' %}
+
+
+ {% for currency, data in rate_map.items %} +
+ + {% for rate in data.rates.values %} +
+
+
+{# #} +
+
+
+ {% if currency.income_projected != 0 %} +
+ +
+ {% else %} +
-
+ {% endif %} +
+ {% endfor %} +
+
+ {% endfor %} +
{% endblock %}