From 86ea7c0000cd7daf34ad21431119a21ae8300474 Mon Sep 17 00:00:00 2001
From: W13R <9070224-W13R@users.noreply.gitlab.com>
Date: Sat, 15 Oct 2022 19:37:01 +0200
Subject: [PATCH] Added 'supply' page to create negative register transactions,
updated translation
---
application/app/admin.py | 4 +
application/app/models.py | 1 +
application/app/templates/supply.html | 61 +++++++
application/app/templates/userPanel.html | 3 +
application/app/urls.py | 2 +
application/app/views.py | 36 +++-
application/locale/de/LC_MESSAGES/django.mo | Bin 3469 -> 3806 bytes
application/locale/de/LC_MESSAGES/django.po | 177 ++++++++++++--------
static/css/supply.css | 6 +
static/js/supply.js | 56 +++++++
10 files changed, 278 insertions(+), 68 deletions(-)
create mode 100644 application/app/templates/supply.html
create mode 100644 static/css/supply.css
create mode 100644 static/js/supply.js
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 07c684c8c574ed25adf7f9061611ea3ad5285e44..1f4683e4dba324f38b3068033447107f11c95ead 100644
GIT binary patch
delta 1595
zcmYk+TWC~A9LMpA=GJ86B{p7@I;mzgO^h{F6RV{lYEfH=ET}IQH_0S9WOEYEp7j!>
zt0)S=LSd<3iDtmC4P_fqPrNNLCWTXTxlq=Y8B>AH_#tk4c2kM7kU^VWs}Cy+n$2NxaDKd9%=P)9TE+h5@x
z>Sd%)6Lz6CbO4pXbT#?c03i)Z^%-O><|3;7GU`nKL=F4^_0m1}&);~f7)=?o-cHnp
zy08fkqQ?CWx8ONn|2skcKcV3s4NGwbS+tqQ8^x_zhT2&YYq1rX(|qaM_xk!iY^D7W
zYN9dx3=6msCsCPvi|etT7sle(d2Te}5NgH8P$@cznrIA_x(lc?zJ!`!9F>_XzJ43E
z&`DJPhp2u}krOt{2_2ov3ZjkBQRh3jyes;CHMq)}S&G*=T$d3_NWxvhe5e4C3)~>Uu+{j4gc;RsQPfeyP3VNI!agp5}yCIW`({YfEgPyEO
z<*3g7vbG|*%BCY{!{OMbGnwI|uGhxH_DJB4+IS$y+H4TJw!+4WN9EaE_fQZ|%&pAN
zNo;2Y1Ca~5b76nsRMq_@U%5EC^J_ThSVi$+y01^q_Et|78WYLt_uF8;raR6w&TS^m%0_KQ8*9@1D95NpAFC`3q=MQ+wX01K7)59UxoB0J
zOH@!$)TTuQO|=LVqKJ@L8H7+sXhG1*ASjCJ|6GsI;lAg0&-LE(@t!lzG+)VNV-~%k+1g^wSScAWCGe%=(ORr2-A23>+vM=
ze%VI2;j%|mdhsbX;5aVFx5#Cmsnp?D=Wq0B`;4v*v$zbqojcs~{iuFVU^AXVF1t+C
z!T5I7J$Q~<;R~$Acc_79F@;}H1ANCMdi1I!rBRuyN0MMYSi}-)A;+*C&*Cb)h04$q
z^cdeJxS>ybiCi{GrGckV15CU22UH4YUHhB!hw~3Mv3*`*p`SdXwD5iryKn&4;yG0R
z*Ri~vo7>!IMboGm&$$1~LbG=$=1AZBZ4~
z-$&HhnNN~`eV8EMvIUi*K4dXAhy^@^>hJ!!g$$$BndK<7%8o`nDwdr7dfqs>4>~
zPgX*$d^dLDo)r04$HP46!%*bkt4Jv
zI{7-hi$#O$=UVQh($7pqd!lq|=K6o2)RBPj@IZK&l;&PFC|a4aq0`+)EEd)juCf(-
z+(TtAODJ3VwWyFWeY%k960RY%|BZyoIzs8RN+Fhy1P5yF1+ng>_
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