Make it possible to convert prices automatically
Some checks failed
Django CI/CD / test (push) Failing after 1m19s
Django CI/CD / build-and-push (push) Has been skipped

This commit is contained in:
2024-11-10 15:34:08 +01:00
parent f61cde180f
commit 527cf4ba52
8 changed files with 449 additions and 202 deletions

View File

@ -1,6 +1,20 @@
from datetime import timedelta
from django.apps import AppConfig
from django.utils.timezone import now
from django_q.models import Schedule
from django_q.tasks import schedule
class GamesConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "games"
def ready(self):
if not Schedule.objects.filter(name="Update converted prices").exists():
schedule(
"games.tasks.update_converted_prices",
name="Update converted prices",
schedule_type="D",
next_run=now() + timedelta(days=1),
)

48
games/convert_price.py Normal file
View File

@ -0,0 +1,48 @@
import requests
from games.models import ExchangeRate, Purchase
def update_converted_prices():
purchases = Purchase.objects.filter(
converted_price__isnull=True, converted_currency__isnull=True
)
for purchase in purchases:
if purchase.price == 0:
continue
year = purchase.date_purchased.year
currency_from = purchase.price_currency
# fixme: save preferred currency in user model
currency_to = "CZK"
exchange_rate = ExchangeRate.objects.filter(
currency_from=currency_from, currency_to=currency_to, year=year
).first()
if not exchange_rate:
try:
response = requests.get(
f"https://api.exchangeratesapi.io/{year}-01-01",
params={"base": currency_to, "symbols": "currency_from"},
)
response.raise_for_status()
data = response.json()
rate = data["rates"].get(currency_from)
if rate:
exchange_rate = ExchangeRate.objects.create(
currency_from=currency_from,
currency_to=currency_to,
year=year,
rate=rate,
)
except requests.RequestException as e:
print(
f"Failed to fetch exchange rate for {currency_from} in {year}: {e}"
)
if exchange_rate:
converted_price = purchase.price * exchange_rate.rate
purchase.converted_price = converted_price
purchase.converted_currency = currency_to
purchase.save()

View File

@ -0,0 +1,24 @@
from datetime import timedelta
from django.core.management.base import BaseCommand
from django.utils.timezone import now
from django_q.models import Schedule
from django_q.tasks import schedule
class Command(BaseCommand):
help = "Manually schedule the next update_converted_prices task"
def handle(self, *args, **kwargs):
if not Schedule.objects.filter(name="Update converted prices").exists():
schedule(
"games.tasks.update_converted_prices",
name="Update converted prices",
schedule_type="D",
next_run=now() + timedelta(days=1),
)
self.stdout.write(
self.style.SUCCESS("Scheduled the update_converted_prices task.")
)
else:
self.stdout.write(self.style.WARNING("Task is already scheduled."))

View File

@ -124,6 +124,8 @@ class Purchase(models.Model):
infinite = models.BooleanField(default=False)
price = models.FloatField(default=0)
price_currency = models.CharField(max_length=3, default="USD")
converted_price = models.FloatField()
converted_currency = models.CharField(max_length=3)
ownership_type = models.CharField(
max_length=2, choices=OWNERSHIP_TYPES, default=DIGITAL
)
@ -279,3 +281,16 @@ class Device(models.Model):
def __str__(self):
return f"{self.name} ({self.type})"
class ExchangeRate(models.Model):
currency_from = models.CharField(max_length=255)
currency_to = models.CharField(max_length=255)
year = models.PositiveIntegerField()
rate = models.FloatField()
class Meta:
unique_together = ("currency_from", "currency_to", "year")
def __str__(self):
return f"{self.currency_from}/{self.currency_to} - {self.rate} ({self.year})"

View File

@ -300,9 +300,9 @@ def stats(request: HttpRequest, year: int = 0) -> HttpResponse:
).distinct()
this_year_purchases = Purchase.objects.filter(date_purchased__year=year)
this_year_purchases_with_currency = this_year_purchases.select_related(
"edition"
).filter(price_currency__exact=selected_currency)
this_year_purchases_with_currency = this_year_purchases.select_related("edition")
# fixme: add conversion table for currencies
# ).filter(price_currency__exact=selected_currency)
this_year_purchases_without_refunded = this_year_purchases_with_currency.filter(
date_refunded=None
)