diff --git a/application/app/admin.py b/application/app/admin.py
index 7e81374..e72e506 100644
--- a/application/app/admin.py
+++ b/application/app/admin.py
@@ -49,6 +49,10 @@ class CustomUserAdmin(UserAdmin):
{"fields": ("balance", "allow_order_with_negative_balance")},
))
fieldsets_.insert(2, (
+ "Supply",
+ {"fields": ("allowed_to_supply",)},
+ ))
+ fieldsets_.insert(3, (
"Profile Picture",
{"fields": ("profile_picture_filename",)},
))
diff --git a/application/app/models.py b/application/app/models.py
index 370a0dd..b92672c 100644
--- a/application/app/models.py
+++ b/application/app/models.py
@@ -21,6 +21,7 @@ class User(AbstractUser):
balance = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)
allow_order_with_negative_balance = models.BooleanField(default=False)
profile_picture_filename = models.CharField(default="default.svg", max_length=25)
+ allowed_to_supply = models.BooleanField(default=False)
def delete(self, *args, **kwargs):
self.balance = 0
diff --git a/application/app/templates/supply.html b/application/app/templates/supply.html
new file mode 100644
index 0000000..0f62ad5
--- /dev/null
+++ b/application/app/templates/supply.html
@@ -0,0 +1,61 @@
+{% extends "baseLayout.html" %}
+
+{% load i18n %}
+{% load l10n %}
+
+{% block title %}
+{% translate "Drinks - Supply" %}
+{% endblock %}
+
+{% block headAdditional %}
+
+
+{% endblock %}
+
+{% block heading %}
+ {% translate "Supply" %}
+{% endblock %}
+
+{% block content %}
+
+ {% if user.is_superuser or user.allowed_to_supply %}
+
+
+
+
+
+
+ {% else %}
+
+
+
+ {% endif %}
+
+
+
+{% endblock %}
diff --git a/application/app/templates/userPanel.html b/application/app/templates/userPanel.html
index b634cd3..447c2d8 100644
--- a/application/app/templates/userPanel.html
+++ b/application/app/templates/userPanel.html
@@ -32,6 +32,9 @@
{% if user.is_superuser or user.is_staff %}
Admin Panel
{% endif %}
+ {% if user.is_superuser or user.allowed_to_supply %}
+ {% translate "Supply" %}
+ {% endif %}
{% translate "Change Password" %}
diff --git a/application/app/urls.py b/application/app/urls.py
index c7a221a..e720876 100644
--- a/application/app/urls.py
+++ b/application/app/urls.py
@@ -10,6 +10,7 @@ urlpatterns = [
path('history/', views.history),
path('deposit/', views.deposit),
path('statistics/', views.statistics),
+ path('supply/', views.supply),
path('accounts/login/', views.login_page, name="login"),
path('accounts/logout/', auth_views.LogoutView.as_view(), name='logout'),
path('accounts/password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'),
@@ -18,5 +19,6 @@ urlpatterns = [
# API #
path('api/order-drink', views.api_order_drink),
path('api/deposit', views.api_deposit),
+ path('api/supply', views.api_supply)
#path('api/get-statistics', views.api_get_statistics)
]
\ No newline at end of file
diff --git a/application/app/views.py b/application/app/views.py
index 152d8bd..8511249 100644
--- a/application/app/views.py
+++ b/application/app/views.py
@@ -103,6 +103,10 @@ def statistics(request):
}
return render(request, "statistics.html", context)
+@login_required
+def supply(request):
+ return render(request, "supply.html")
+
@login_required
def redirect_home(request):
return HttpResponseRedirect("/")
@@ -132,7 +136,7 @@ def api_order_drink(request):
else:
return HttpResponse("notAvailable", status=400)
- else: raise Exception("Balance below zero.")
+ else: raise Exception("Unexpected input or missing privileges.")
except Exception as e:
print(f"An exception occured while processing an order: User: {user.username} - Exception: {e}", file=sys.stderr)
@@ -163,5 +167,33 @@ def api_deposit(request):
else: raise Exception("Deposit amount too big or small.")
except Exception as e:
- print(f"An exception occured while processing an transaction: User: {user.username} - Exception: {e}", file=sys.stderr)
+ print(f"An exception occured while processing a transaction: User: {user.username} - Exception: {e}", file=sys.stderr)
+ return HttpResponse(b"", status=500)
+
+@login_required
+def api_supply(request):
+
+ # check request -> supply
+
+ user = request.user
+
+ try:
+
+ price = decimal.Decimal(request.POST["supplyPrice"])
+ description = str(request.POST["supplyDescription"])
+
+ if 0.00 < price < 9999.99 and (user.allowed_to_supply or user.is_superuser):
+ # create transaction
+ RegisterTransaction.objects.create(
+ transaction_sum=-price,
+ comment=f"Supply: {description}",
+ is_user_deposit=False,
+ user=user
+ )
+ #
+ return HttpResponse("success", status=200)
+ else: raise Exception("Unexpected input or missing privileges.")
+
+ except Exception as e:
+ print(f"An exception occured while processing a supply transaction: User: {user.username} - Exception: {e}", file=sys.stderr)
return HttpResponse(b"", status=500)
diff --git a/application/locale/de/LC_MESSAGES/django.mo b/application/locale/de/LC_MESSAGES/django.mo
index 07c684c..1f4683e 100644
Binary files a/application/locale/de/LC_MESSAGES/django.mo and b/application/locale/de/LC_MESSAGES/django.mo differ
diff --git a/application/locale/de/LC_MESSAGES/django.po b/application/locale/de/LC_MESSAGES/django.po
index 22c05b2..997e989 100644
--- a/application/locale/de/LC_MESSAGES/django.po
+++ b/application/locale/de/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-06-13 19:01+0200\n"
+"POT-Creation-Date: 2022-10-15 19:20+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Julian Müller (W13R)\n"
"Language: DE\n"
@@ -17,221 +17,266 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: app/templates/admin/base_site.html:7
+#: application/app/templates/admin/base_site.html:7
msgid "Django site admin"
msgstr "Django Administrator"
-#: app/templates/admin/base_site.html:15
+#: application/app/templates/admin/base_site.html:15
msgid "Django administration"
msgstr "Django Administration"
-#: app/templates/baseLayout.html:41
+#: application/app/templates/baseLayout.html:41
msgid "An error occured. Please log out and log in again."
msgstr "Ein Fehler ist aufgetreten. Bitte ab- und wieder anmelden."
-#: app/templates/deposit.html:6
+#: application/app/templates/deposit.html:6
msgid "Drinks - Deposit"
msgstr "Getränke - Einzahlen"
-#: app/templates/deposit.html:14 app/templates/userPanel.html:19
+#: application/app/templates/deposit.html:14
+#: application/app/templates/userPanel.html:23
msgid "Deposit"
msgstr "Einzahlen"
-#: app/templates/deposit.html:23
+#: application/app/templates/deposit.html:23
msgid "Amount"
msgstr "Summe"
-#: app/templates/deposit.html:31 app/templates/order.html:72
-#: app/templates/registration/login.html:56
+#: application/app/templates/deposit.html:31
+#: application/app/templates/order.html:72
+#: application/app/templates/registration/login.html:57
+#: application/app/templates/supply.html:41
msgid "cancel"
msgstr "Abbrechen"
-#: app/templates/deposit.html:32
+#: application/app/templates/deposit.html:32
msgid "confirm"
msgstr "Bestätigen"
-#: app/templates/history.html:6
+#: application/app/templates/history.html:6
msgid "Drinks - History"
msgstr "Getränke - Verlauf"
-#: app/templates/history.html:14 app/templates/userPanel.html:25
+#: application/app/templates/history.html:14
+#: application/app/templates/userPanel.html:30
msgid "History"
msgstr "Verlauf"
-#: app/templates/history.html:22
+#: application/app/templates/history.html:22
msgid "last 30 actions"
msgstr "letzte 30 Vorgänge"
-#: app/templates/history.html:33 app/templates/statistics.html:41
-#: app/templates/statistics.html:61 app/templates/statistics.html:81
-#: app/templates/statistics.html:101 app/templates/statistics.html:121
-#: app/templates/statistics.html:141
+#: application/app/templates/history.html:33
+#: application/app/templates/statistics.html:41
+#: application/app/templates/statistics.html:61
+#: application/app/templates/statistics.html:81
+#: application/app/templates/statistics.html:101
+#: application/app/templates/statistics.html:121
+#: application/app/templates/statistics.html:141
msgid "No history."
msgstr "Kein Verlauf verfügbar."
-#: app/templates/index.html:6
+#: application/app/templates/index.html:6
msgid "Drinks - Home"
msgstr "Getränke - Home"
-#: app/templates/index.html:14
+#: application/app/templates/index.html:14
msgid "Available Drinks"
msgstr "Verfügbare Getränke"
-#: app/templates/index.html:27 app/templates/index.html:34
+#: application/app/templates/index.html:27
+#: application/app/templates/index.html:34
msgid "available"
msgstr "verfügbar"
-#: app/templates/index.html:43
+#: application/app/templates/index.html:43
msgid "No drinks available."
msgstr "Es sind gerade keine Getränke verfügbar."
-#: app/templates/order.html:7
+#: application/app/templates/order.html:7
msgid "Drinks - Order"
msgstr "Getränke - Bestellen"
-#: app/templates/order.html:16
+#: application/app/templates/order.html:16
+#: packages/django/forms/formsets.py:405 packages/django/forms/formsets.py:412
msgid "Order"
msgstr "Bestellung"
-#: app/templates/order.html:29
+#: application/app/templates/order.html:29
msgid "Drink"
msgstr "Getränk"
-#: app/templates/order.html:34
+#: application/app/templates/order.html:34
msgid "Price per Item"
msgstr "Preis pro Getränk"
-#: app/templates/order.html:40
+#: application/app/templates/order.html:40
msgid "Available"
msgstr "Verfügbar"
-#: app/templates/order.html:46
+#: application/app/templates/order.html:46
msgid "Count"
msgstr "Anzahl"
-#: app/templates/order.html:63
+#: application/app/templates/order.html:63
msgid "Sum"
msgstr "Summe"
-#: app/templates/order.html:73
+#: application/app/templates/order.html:73
msgid "order"
msgstr "Bestellen"
-#: app/templates/order.html:85
+#: application/app/templates/order.html:85
msgid "Your balance is too low to order a drink."
msgstr "Dein Saldo ist zu niedrig um Getränke zu bestellen."
-#: app/templates/order.html:86 app/templates/order.html:95
+#: application/app/templates/order.html:86
+#: application/app/templates/order.html:95
+#: application/app/templates/supply.html:54
msgid "back"
msgstr "zurück"
-#: app/templates/order.html:94
+#: application/app/templates/order.html:94
msgid "This drink is not available."
msgstr "Dieses Getränk ist gerade nicht verfügbar."
-#: app/templates/registration/logged_out.html:7
+#: application/app/templates/registration/logged_out.html:7
msgid "Drinks - Logged Out"
msgstr "Getränke - Abgemeldet"
-#: app/templates/registration/logged_out.html:17
+#: application/app/templates/registration/logged_out.html:17
msgid "Logged out! You will be redirected shortly."
msgstr "Du wurdest abgemeldet und wirst in Kürze weitergeleitet."
-#: app/templates/registration/logged_out.html:19
+#: application/app/templates/registration/logged_out.html:19
msgid "Click here if automatic redirection does not work."
msgstr ""
"Bitte klicke hier, wenn die automatische Weiterleitung nicht funktioniert."
-#: app/templates/registration/login.html:7
+#: application/app/templates/registration/login.html:8
msgid "Drinks - Login"
msgstr "Getränke - Anmeldung"
-#: app/templates/registration/login.html:26
+#: application/app/templates/registration/login.html:27
msgid "Log in"
msgstr "Anmelden"
-#: app/templates/registration/login.html:28
+#: application/app/templates/registration/login.html:29
msgid "Password/PIN"
msgstr "Passwort/PIN"
-#: app/templates/registration/login.html:57
+#: application/app/templates/registration/login.html:58
msgid "login"
msgstr "Anmelden"
-#: app/templates/registration/login.html:65
+#: application/app/templates/registration/login.html:66
msgid "Choose your account"
msgstr "Wähle deinen Account"
-#: app/templates/statistics.html:6
+#: application/app/templates/statistics.html:6
msgid "Drinks - Statistics"
msgstr "Getränke - Statistiken"
-#: app/templates/statistics.html:15 app/templates/userPanel.html:26
+#: application/app/templates/statistics.html:15
+#: application/app/templates/userPanel.html:31
msgid "Statistics"
msgstr "Statistiken"
-#: app/templates/statistics.html:26
+#: application/app/templates/statistics.html:26
msgid "Your orders per drink"
msgstr "Deine Bestellungen pro Getränk"
-#: app/templates/statistics.html:30 app/templates/statistics.html:50
+#: application/app/templates/statistics.html:30
+#: application/app/templates/statistics.html:50
msgid "drink"
msgstr "Getränk"
-#: app/templates/statistics.html:31 app/templates/statistics.html:51
-#: app/templates/statistics.html:71 app/templates/statistics.html:91
-#: app/templates/statistics.html:111 app/templates/statistics.html:131
+#: application/app/templates/statistics.html:31
+#: application/app/templates/statistics.html:51
+#: application/app/templates/statistics.html:71
+#: application/app/templates/statistics.html:91
+#: application/app/templates/statistics.html:111
+#: application/app/templates/statistics.html:131
msgid "count"
msgstr "Anzahl"
-#: app/templates/statistics.html:46
+#: application/app/templates/statistics.html:46
msgid "All orders per drink"
msgstr "Alle Bestellungen pro Getränk"
-#: app/templates/statistics.html:66
+#: application/app/templates/statistics.html:66
msgid "Your orders per month (last 12 months)"
msgstr "Deine Bestellungen pro Monat (letzte 12 Monate)"
-#: app/templates/statistics.html:70 app/templates/statistics.html:90
+#: application/app/templates/statistics.html:70
+#: application/app/templates/statistics.html:90
msgid "month"
msgstr "Monat"
-#: app/templates/statistics.html:86
+#: application/app/templates/statistics.html:86
msgid "All orders per month (last 12 months)"
msgstr "Alle Bestellungen pro Monat (letzte 12 Monate)"
-#: app/templates/statistics.html:106
+#: application/app/templates/statistics.html:106
msgid "Your orders per weekday"
msgstr "Deine Bestellungen pro Wochentag"
-#: app/templates/statistics.html:110 app/templates/statistics.html:130
+#: application/app/templates/statistics.html:110
+#: application/app/templates/statistics.html:130
msgid "day"
msgstr "Tag"
-#: app/templates/statistics.html:126
+#: application/app/templates/statistics.html:126
msgid "All orders per weekday"
msgstr "Alle Bestellungen pro Wochentag"
-#: app/templates/userPanel.html:6 app/templates/userPanel.html:8
+#: application/app/templates/supply.html:7
+msgid "Drinks - Supply"
+msgstr "Getränke - Beschaffung"
+
+#: application/app/templates/supply.html:16
+#: application/app/templates/userPanel.html:36
+msgid "Supply"
+msgstr "Beschaffung"
+
+#: application/app/templates/supply.html:27
+msgid "Description"
+msgstr "Beschreibung"
+
+#: application/app/templates/supply.html:32
+msgid "Price"
+msgstr "Preis"
+
+#: application/app/templates/supply.html:42
+msgid "submit"
+msgstr "Senden"
+
+#: application/app/templates/supply.html:53
+msgid "You are not allowed to view this site."
+msgstr "Dir fehlt die Berechtigung, diese Seite anzuzeigen."
+
+#: application/app/templates/userPanel.html:9
+#: application/app/templates/userPanel.html:11
msgid "User"
msgstr "Benutzer"
-#: app/templates/userPanel.html:12 app/templates/userPanel.html:14
+#: application/app/templates/userPanel.html:15
+#: application/app/templates/userPanel.html:17
msgid "Balance"
msgstr "Saldo"
-#: app/templates/userPanel.html:22
-msgid "Account"
-msgstr "Account"
-
-#: app/templates/userPanel.html:30
-msgid "Change Password"
-msgstr "Passwort ändern"
-
-#: app/templates/userPanel.html:31
+#: application/app/templates/userPanel.html:24
msgid "Logout"
msgstr "Abmelden"
-#: app/views.py:47
+#: application/app/templates/userPanel.html:27
+msgid "Account"
+msgstr "Account"
+
+#: application/app/templates/userPanel.html:38
+msgid "Change Password"
+msgstr "Passwort ändern"
+
+#: application/app/views.py:47
msgid "Invalid username or password."
msgstr "Benutzername oder Passwort ungültig."
diff --git a/static/css/supply.css b/static/css/supply.css
new file mode 100644
index 0000000..a149993
--- /dev/null
+++ b/static/css/supply.css
@@ -0,0 +1,6 @@
+form {
+ width: 24rem;
+}
+#supplyPrice {
+ width: 10rem;
+}
\ No newline at end of file
diff --git a/static/js/supply.js b/static/js/supply.js
new file mode 100644
index 0000000..054b08d
--- /dev/null
+++ b/static/js/supply.js
@@ -0,0 +1,56 @@
+document.addEventListener("DOMContentLoaded", () => {
+
+ // elements
+
+ let supply_description = document.getElementById("supplyDescription");
+ let supply_price = document.getElementById("supplyPrice");
+
+ let supply_form = document.getElementById("supplyForm");
+ let status_info = document.getElementById("statusInfo");
+ let supply_submit_button = document.getElementById("supplySubmitBtn");
+
+ // custom submit method
+
+ supply_form.addEventListener("submit", (event) => {
+
+ supply_submit_button.disabled = true;
+
+ event.preventDefault(); // Don't do the default submit action!
+
+ if (isNaN(parseFloat(supply_price.value)) || supply_description.value == "") {
+ status_info.innerText = "Please enter a description and price."
+ supply_submit_button.disabled = false;
+ }
+
+ let xhr = new XMLHttpRequest();
+ let formData = new FormData(supply_form);
+
+ xhr.addEventListener("load", (event) => {
+
+ status_ = event.target.status;
+ response_ = event.target.responseText;
+
+ if (status_ == 200 && response_ == "success") {
+ status_info.innerText = "Success.";
+ window.location.replace("/");
+ }
+ else {
+ status_info.classList.add("errorText");
+ status_info.innerText = "An error occured.";
+ window.setTimeout(() => { window.location.reload() }, 5000);
+ }
+
+ })
+
+ xhr.addEventListener("error", (event) => {
+ status_info.classList.add("errorText");
+ status_info.innerText = "An error occured.";
+ window.setTimeout(() => { window.location.reload() }, 5000);
+ })
+
+ xhr.open("POST", "/api/supply");
+ xhr.send(formData);
+
+ });
+
+})
\ No newline at end of file