Skip to content

Commit bac76ca

Browse files
committed
Added api for changing currency + tests
1 parent d9910f6 commit bac76ca

File tree

8 files changed

+130
-70
lines changed

8 files changed

+130
-70
lines changed

backend/api/settings/currency.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from django.http import HttpResponse
2+
from django.shortcuts import redirect, render
3+
from django.contrib import messages
4+
from django.views.decorators.http import require_http_methods
5+
6+
from backend.models import UserSettings # Replace with your actual model
7+
8+
9+
@require_http_methods(["POST"])
10+
def update_currency_view(request):
11+
currency = request.POST.get("currency", None)
12+
usersettings, created = UserSettings.objects.get_or_create(user=request.user)
13+
14+
htmx_return = "partials/base/toasts.html"
15+
16+
if not request.htmx and not currency:
17+
return HttpResponse("Invalid Request", status=400)
18+
elif not currency or currency not in usersettings.CURRENCIES:
19+
messages.error(request, "Invalid Currency")
20+
return render(request, htmx_return)
21+
22+
if usersettings.currency == currency:
23+
messages.warning(
24+
request, "You are already using this currency, no change was made"
25+
)
26+
return render(request, htmx_return)
27+
28+
usersettings.currency = currency
29+
usersettings.save()
30+
messages.success(request, "Successfully updated currency")
31+
32+
return render(request, htmx_return)

backend/api/settings/urls.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from django.urls import path
2+
from . import currency
3+
4+
urlpatterns = [
5+
path(
6+
"change_currency/",
7+
currency.update_currency_view,
8+
name="change_currency",
9+
),
10+
]
11+
12+
app_name = "settings"

backend/api/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
path("receipts/", include("backend.api.receipts.urls")),
77
path("invoices/", include("backend.api.invoices.urls")),
88
path("clients/", include("backend.api.clients.urls")),
9+
path("settings/", include("backend.api.settings.urls")),
910
]
1011

1112
app_name = "api"

backend/views/core/settings/view.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,9 @@ def settings_page(request: HttpRequest):
2626
)
2727

2828
if request.method == "POST" and request.htmx:
29-
currency = request.POST.get("currency")
3029
section = request.POST.get("section")
3130
profile_picture = request.FILES.get("profile_image")
3231

33-
if section == "account_preferences":
34-
if currency in usersettings.CURRENCIES:
35-
usersettings.currency = currency
36-
usersettings.save()
37-
messages.success(request, "Successfully updated currency")
38-
else:
39-
messages.error(request, "Invalid currency")
40-
41-
context.update(
42-
{
43-
"post_return": "currency",
44-
"currency": usersettings.currency,
45-
"user_settings": usersettings,
46-
}
47-
)
4832
if section == "profile_picture":
4933
if profile_picture:
5034
try:

frontend/templates/pages/settings/settings/preferences.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
<div class="flex items-center justify-between py-4">
2525
<div class="flex flex-col flex-grow">
2626
<div class="text-lg font-semibold text-gray-900 dark:text-white">Currency</div>
27-
<div class="text-base font-normal text-gray-500 dark:text-gray-400 whitespace-nowrap">This will change the
28-
default currency
27+
<div class="text-base font-normal text-gray-500 dark:text-gray-400 whitespace-nowrap">
28+
This will change the default currency for your account
2929
</div>
3030
</div>
3131
<select name="currency" class="select select-bordered w-[25%]">
@@ -40,7 +40,7 @@
4040
</div>
4141
<button class="btn btn-primary mb-2 loading-htmx"
4242
name="section" value="account_preferences"
43-
hx-post="{% url 'user settings' %}"
43+
hx-post="{% url 'api:settings:change_currency' %}"
4444
hx-swap="none"
4545
hx-trigger="click">
4646
<span class="loading-htmx-text">Save</span>

tests/api/test_account_settings.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
from django.urls import reverse, resolve
2+
from backend.models import UserSettings
3+
from tests.handler import ViewTestCase, assert_url_matches_view
4+
5+
6+
class CurrencyAPIChange(ViewTestCase):
7+
# Setting up common data for tests
8+
def setUp(self):
9+
super().setUp()
10+
self.url_path = "/api/settings/change_currency/"
11+
self.url_name = "api:settings:change_currency"
12+
self.view_function_path = "backend.api.settings.currency.update_currency_view"
13+
14+
# Test that the URL resolves to the correct view function
15+
def test_url_matches_api(self):
16+
assert_url_matches_view(self.url_path, self.url_name, self.view_function_path)
17+
18+
# Test that the view returns a 405 Method Not Allowed for GET requests
19+
def test_405_for_get_requests(self):
20+
self.login_user()
21+
response = self.make_request(method="get", with_htmx=False)
22+
self.assertEqual(response.status_code, 405)
23+
self.assertEqual(response.content.decode("utf-8"), "")
24+
25+
# Test that the view returns a 400 Bad Request for POST requests without HTMX
26+
def test_400_for_all_normal_get_requests(self):
27+
self.login_user()
28+
response = self.make_request(method="post", with_htmx=False)
29+
self.assertEqual(response.status_code, 400)
30+
self.assertEqual(response.content.decode("utf-8"), "Invalid Request")
31+
32+
# Test that non-authenticated users are redirected to the login page for GET requests
33+
def test_302_for_non_authenticated_users(self):
34+
response = self.client.get(reverse(self.url_name))
35+
self.assertRedirects(response, f"/login/?next={self.url_path}", 302)
36+
37+
# Test that an error message is displayed when no currency is provided in the POST request
38+
def test_no_currency_provided(self):
39+
self.login_user()
40+
response = self.make_request(method="post", with_htmx=True)
41+
self.assertEqual(response.status_code, 200)
42+
messages = self.get_all_messages(response)
43+
self.assertEqual(len(messages), 1)
44+
self.assertEqual(str(messages[0]), "Invalid Currency")
45+
46+
# Test that users receive a message when trying to update to their current currency
47+
def test_currency_is_already_that(self):
48+
self.login_user()
49+
response = self.make_request(
50+
method="post", data={"currency": "GBP"}, with_htmx=True
51+
)
52+
self.assertEqual(response.status_code, 200)
53+
messages = self.get_all_messages(response)
54+
self.assertEqual(len(messages), 1)
55+
self.assertEqual(
56+
str(messages[0]), "You are already using this currency, no change was made"
57+
)
58+
59+
# Test that the user's currency is updated successfully
60+
def test_currency_is_updated(self):
61+
self.login_user()
62+
response = self.make_request(
63+
method="post", data={"currency": "EUR"}, with_htmx=True
64+
)
65+
self.assertEqual(response.status_code, 200)
66+
messages = self.get_all_messages(response)
67+
self.assertEqual(len(messages), 1)
68+
self.assertEqual(str(messages[0]), "Successfully updated currency")
69+
user_settings = UserSettings.objects.get(user=self.log_in_user)
70+
self.assertEqual(user_settings.currency, "EUR")

tests/handler.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.contrib.messages import get_messages
12
from django.urls import reverse
23
from django.test import TestCase
34
from backend.models import User, Receipt, UserSettings
@@ -73,9 +74,18 @@ def call_index(self):
7374
def login_user(self):
7475
self.client.login(username="user@example.com", password="user")
7576

76-
def make_request(self, with_htmx=True):
77+
def make_request(self, method="get", data={}, with_htmx=True):
7778
"""
7879
Makes request to self.url_name, defaults "with htmx"
7980
"""
8081
headers = self.htmx_headers if with_htmx else {}
81-
return self.client.get(reverse(self.url_name), **headers)
82+
if method == "post":
83+
return self.client.post(reverse(self.url_name), data, **headers)
84+
else:
85+
return self.client.get(reverse(self.url_name), **headers)
86+
87+
def get_all_messages(self, response):
88+
try:
89+
return list(get_messages(response.wsgi_request))
90+
except:
91+
return []

tests/views/test_usersettings_preferences.py

Lines changed: 0 additions & 49 deletions
This file was deleted.

0 commit comments

Comments
 (0)