Files
WYGIWYH/app/apps/mini_tools/utils/exchange_rate_map.py

86 lines
2.7 KiB
Python

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()
)
# 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