Make it possible to convert prices automatically
This commit is contained in:
@ -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
48
games/convert_price.py
Normal 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()
|
24
games/management/commands/schedule_update_task.py
Normal file
24
games/management/commands/schedule_update_task.py
Normal 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."))
|
@ -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})"
|
||||
|
@ -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
|
||||
)
|
||||
|
Reference in New Issue
Block a user