Release 16 (devel -> main) #39

Merged
ChaoticByte merged 13 commits from devel into main 2023-04-17 19:10:52 +00:00
11 changed files with 164 additions and 30 deletions
Showing only changes of commit 8702233934 - Show all commits

View file

@ -45,9 +45,10 @@ def select_history(user, language_code="en") -> list:
result = _db_select(f""" result = _db_select(f"""
select select
concat( concat(
price_sum, '{settings.CURRENCY_SUFFIX} - ',
product_name, ' (', product_name, ' (',
content_litres::real, -- converting to real removes trailing zeros content_litres::real, -- converting to real removes trailing zeros
'l) x ', amount, ' - ', price_sum, '{settings.CURRENCY_SUFFIX}') as "text", 'l) x ', amount) as "text",
datetime datetime
from app_order from app_order
where user_id = {user_id} where user_id = {user_id}
@ -55,11 +56,19 @@ def select_history(user, language_code="en") -> list:
union union
select select
concat('Deposit: +', transaction_sum, '{settings.CURRENCY_SUFFIX}') as "text", concat(transaction_sum, '{settings.CURRENCY_SUFFIX} - Deposit') as "text",
datetime datetime
from app_userdeposits_view from app_userdeposits_view
where user_id = {user_id} where user_id = {user_id}
union
select
concat(transaction_sum, '{settings.CURRENCY_SUFFIX} - ', comment) as "text",
datetime
from app_registertransaction
where user_id = {user_id} and is_transfer = true
order by datetime desc order by datetime desc
fetch first 30 rows only; fetch first 30 rows only;
""") """)

Binary file not shown.

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-13 20:50+0200\n" "POT-Creation-Date: 2023-04-14 23:37+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Julian MĂĽller (ChaoticByte)\n" "Last-Translator: Julian MĂĽller (ChaoticByte)\n"
"Language: DE\n" "Language: DE\n"
@ -33,20 +33,21 @@ msgstr "Ein Fehler ist aufgetreten. Bitte ab- und wieder anmelden."
msgid "Drinks - Deposit" msgid "Drinks - Deposit"
msgstr "Getränke - Einzahlen" msgstr "Getränke - Einzahlen"
#: app/templates/deposit.html:17 app/templates/userpanel.html:23 #: app/templates/deposit.html:17 app/templates/userpanel.html:18
msgid "Deposit" msgid "Deposit"
msgstr "Einzahlen" msgstr "Einzahlen"
#: app/templates/deposit.html:19 #: app/templates/deposit.html:19 app/templates/transfer.html:43
msgid "Amount" msgid "Amount"
msgstr "Summe" msgstr "Summe"
#: app/templates/deposit.html:30 app/templates/order.html:54 #: app/templates/deposit.html:30 app/templates/order.html:54
#: app/templates/registration/login.html:28 app/templates/supply.html:29 #: app/templates/registration/login.html:28 app/templates/supply.html:29
#: app/templates/transfer.html:54
msgid "cancel" msgid "cancel"
msgstr "Abbrechen" msgstr "Abbrechen"
#: app/templates/deposit.html:31 #: app/templates/deposit.html:31 app/templates/transfer.html:55
msgid "confirm" msgid "confirm"
msgstr "Bestätigen" msgstr "Bestätigen"
@ -54,7 +55,7 @@ msgstr "Bestätigen"
msgid "Drinks - History" msgid "Drinks - History"
msgstr "Getränke - Verlauf" msgstr "Getränke - Verlauf"
#: app/templates/history.html:10 app/templates/userpanel.html:30 #: app/templates/history.html:10 app/templates/userpanel.html:25
msgid "History" msgid "History"
msgstr "Verlauf" msgstr "Verlauf"
@ -164,7 +165,7 @@ msgstr "Wähle deinen Account"
msgid "Drinks - Statistics" msgid "Drinks - Statistics"
msgstr "Getränke - Statistiken" msgstr "Getränke - Statistiken"
#: app/templates/statistics.html:10 app/templates/userpanel.html:31 #: app/templates/statistics.html:10 app/templates/userpanel.html:26
msgid "Statistics" msgid "Statistics"
msgstr "Statistiken" msgstr "Statistiken"
@ -206,7 +207,7 @@ msgstr "Tag"
msgid "Drinks - Supply" msgid "Drinks - Supply"
msgstr "Getränke - Beschaffung" msgstr "Getränke - Beschaffung"
#: app/templates/supply.html:14 app/templates/userpanel.html:36 #: app/templates/supply.html:14 app/templates/userpanel.html:32
msgid "Supply" msgid "Supply"
msgstr "Beschaffung" msgstr "Beschaffung"
@ -226,19 +227,36 @@ msgstr "Senden"
msgid "You are not allowed to view this site." msgid "You are not allowed to view this site."
msgstr "Dir fehlt die Berechtigung, diese Seite anzuzeigen." msgstr "Dir fehlt die Berechtigung, diese Seite anzuzeigen."
#: app/templates/userpanel.html:15 app/templates/userpanel.html:17 #: app/templates/transfer.html:6
#| msgid "Drinks - Order"
msgid "Drinks - Transfer"
msgstr "Getränke - Geld senden"
#: app/templates/transfer.html:17
msgid "Transfer Money"
msgstr "Geld senden"
#: app/templates/transfer.html:19
msgid "Recipient"
msgstr "Empfänger"
#: app/templates/userpanel.html:10 app/templates/userpanel.html:12
msgid "Balance" msgid "Balance"
msgstr "Saldo" msgstr "Saldo"
#: app/templates/userpanel.html:24 #: app/templates/userpanel.html:19
msgid "Logout" msgid "Logout"
msgstr "Abmelden" msgstr "Abmelden"
#: app/templates/userpanel.html:27 #: app/templates/userpanel.html:22
msgid "Account" msgid "Account"
msgstr "Account" msgstr "Account"
#: app/templates/userpanel.html:38 #: app/templates/userpanel.html:30
msgid "Transfer"
msgstr "Geld senden"
#: app/templates/userpanel.html:34
msgid "Change Password" msgid "Change Password"
msgstr "Passwort ändern" msgstr "Passwort ändern"

View file

@ -0,0 +1,17 @@
# Generated by Django 4.1.6 on 2023-04-14 20:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("app", "0003_user_hide_from_userlist"),
]
operations = [
migrations.AddField(
model_name="registertransaction",
name="is_transfer",
field=models.BooleanField(default=False),
),
]

View file

@ -59,30 +59,29 @@ class RegisterTransaction(models.Model):
old_transaction_sum = models.DecimalField(max_digits=6, decimal_places=2, default=0.00) old_transaction_sum = models.DecimalField(max_digits=6, decimal_places=2, default=0.00)
datetime = models.DateTimeField(default=timezone.now) datetime = models.DateTimeField(default=timezone.now)
is_user_deposit = models.BooleanField(default=False) is_user_deposit = models.BooleanField(default=False)
is_transfer = models.BooleanField(default=False)
comment = models.TextField(default=" ") comment = models.TextField(default=" ")
user = models.ForeignKey(User, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if self._state.adding: if self._state.adding:
if self.is_user_deposit == True: # update user balance if self.is_user_deposit or self.is_transfer: # update user balance
self.user.balance += self.transaction_sum self.user.balance += self.transaction_sum
self.user.save() self.user.save()
self.old_transaction_sum = self.transaction_sum self.old_transaction_sum = self.transaction_sum
super().save(*args, **kwargs) super().save(*args, **kwargs)
else: else:
# update register transaction
sum_diff = self.transaction_sum - self.old_transaction_sum
# update user balance # update user balance
if self.is_user_deposit == True: if self.is_user_deposit or self.is_transfer:
ub_sum_diff = self.transaction_sum - self.old_transaction_sum self.user.balance += self.transaction_sum - self.old_transaction_sum
self.user.balance += ub_sum_diff
self.user.save() self.user.save()
# update register transaction
self.old_transaction_sum = self.transaction_sum self.old_transaction_sum = self.transaction_sum
super().save(*args, **kwargs) super().save(*args, **kwargs)
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
# update user deposit # update user deposit
if self.is_user_deposit: if self.is_user_deposit or self.is_transfer:
self.user.balance -= self.transaction_sum self.user.balance -= self.transaction_sum
self.user.save() self.user.save()
super().delete(*args, kwargs) super().delete(*args, kwargs)

View file

@ -50,7 +50,7 @@ input[type="number"]::-webkit-inner-spin-button {
display: none; display: none;
} }
input[type="text"], input[type="password"], input[type="number"] { input[type="text"], input[type="password"], input[type="number"], select {
padding: .6rem .8rem; padding: .6rem .8rem;
text-align: center; text-align: center;
font-size: 1rem; font-size: 1rem;

View file

@ -48,6 +48,8 @@
{{ user_.last_name }}, {{ user_.last_name }},
{% endif %} {% endif %}
{{ user_.first_name }} {{ user_.first_name }}
{% elif user_.last_name %}
{{ user_.last_name }}
{% else %} {% else %}
{{ user_.username }} {{ user_.username }}
{% endif %} {% endif %}

View file

@ -0,0 +1,60 @@
{% extends "baselayout.html" %}
{% load i18n %}
{% block title %}
{% translate "Drinks - Transfer" %}
{% endblock %}
{% block headAdditional %}
<link rel="stylesheet" href="/static/css/simple-keyboard.css">
<link rel="stylesheet" href="/static/css/simple-keyboard_dark.css">
{% endblock %}
{% block content %}
<form id="customform" class="flex flex-column flex-center appform gap-1rem" action="/api/transfer">
{% csrf_token %}
<h1 class="formheading">{% translate "Transfer Money" %}</h1>
<div class="flex forminput">
<span>{% translate "Recipient" %}:</span>
<span>
<select name="recipientuser" required>
<option></option>
{% for user_ in user_list %}
{% if user_.id != user.id %}
<option value="{{user_.id}}">
{% if user_.first_name %}
{% if user_.last_name %}
{{ user_.last_name }},
{% endif %}
{{ user_.first_name }}
{% elif user_.last_name %}
{{ user_.last_name }}
{% else %}
{{ user_.username }}
{% endif %}
{% endif %}
</option>
{% endfor %}
</select>
</span>
</div>
<div class="flex forminput">
<span>{% translate "Amount" %} {{ currency_suffix }}:</span>
<span>
<input type="number" name="transferamount" class="keyboard-input" max="{{ user.balance }}" min="0.01" step="0.01" autofocus required>
</span>
</div>
<div id="statusinfo"></div>
<!-- Virtual Keyboard -->
<div id="keyboard" class="simple-keyboard" data-layout="numeric"></div>
<script src="/static/js/simple-keyboard.js"></script>
<script src="/static/js/simple-keyboard_configure.js"></script>
<div class="flex-center buttons">
<a href="/" class="button">{% translate "cancel" %}</a>
<input type="submit" id="submitbtn" class="button" value='{% translate "confirm" %}'>
</div>
</form>
<script src="/static/js/custom_form.js"></script>
<script src="/static/js/autoreload.js"></script>
{% endblock %}

View file

@ -27,6 +27,7 @@
{% if user.is_superuser or user.is_staff %} {% if user.is_superuser or user.is_staff %}
<a class="button dropdownchoice" href="/admin/">Admin Panel</a> <a class="button dropdownchoice" href="/admin/">Admin Panel</a>
{% endif %} {% endif %}
<a class="button dropdownchoice" href="/transfer/">{% translate "Transfer" %}</a>
{% if user.is_superuser or user.allowed_to_supply %} {% if user.is_superuser or user.allowed_to_supply %}
<a class="button dropdownchoice" href="/supply/">{% translate "Supply" %}</a> <a class="button dropdownchoice" href="/supply/">{% translate "Supply" %}</a>
{% endif %} {% endif %}

View file

@ -10,6 +10,7 @@ urlpatterns = [
path('history/', views.history), path('history/', views.history),
path('deposit/', views.deposit), path('deposit/', views.deposit),
path('statistics/', views.statistics), path('statistics/', views.statistics),
path('transfer/', views.transfer),
path('supply/', views.supply), path('supply/', views.supply),
path('accounts/login/', views.login_page, name="login"), path('accounts/login/', views.login_page, name="login"),
path('accounts/logout/', auth_views.LogoutView.as_view(), name='logout'), path('accounts/logout/', auth_views.LogoutView.as_view(), name='logout'),
@ -19,5 +20,6 @@ urlpatterns = [
# API # # API #
path('api/order-drink', views.api_order_drink), path('api/order-drink', views.api_order_drink),
path('api/deposit', views.api_deposit), path('api/deposit', views.api_deposit),
path('api/transfer', views.api_transfer),
path('api/supply', views.api_supply) path('api/supply', views.api_supply)
] ]

View file

@ -50,7 +50,6 @@ def login_page(request):
"user_list": userlist "user_list": userlist
}) })
@login_required @login_required
def index(request): def index(request):
context = { context = {
@ -58,7 +57,6 @@ def index(request):
} }
return render(request, "index.html", context) return render(request, "index.html", context)
@login_required @login_required
def history(request): def history(request):
context = { context = {
@ -66,7 +64,6 @@ def history(request):
} }
return render(request, "history.html", context) return render(request, "history.html", context)
@login_required @login_required
def order(request, drinkid): def order(request, drinkid):
try: try:
@ -76,7 +73,6 @@ def order(request, drinkid):
except Drink.DoesNotExist: except Drink.DoesNotExist:
return HttpResponseRedirect("/") return HttpResponseRedirect("/")
@login_required @login_required
def deposit(request): def deposit(request):
return render(request, "deposit.html", {}) return render(request, "deposit.html", {})
@ -91,17 +87,19 @@ def statistics(request):
} }
return render(request, "statistics.html", context) return render(request, "statistics.html", context)
@login_required
def transfer(request):
userlist = get_user_model().objects.filter(hide_from_userlist=False).filter(is_active=True).order_by("username")
return render(request, "transfer.html", {"user_list": userlist})
@login_required @login_required
def supply(request): def supply(request):
return render(request, "supply.html") return render(request, "supply.html")
@login_required @login_required
def redirect_home(request): def redirect_home(request):
return HttpResponseRedirect("/") return HttpResponseRedirect("/")
# API for XHR requests # # API for XHR requests #
@login_required @login_required
@ -123,7 +121,6 @@ def api_order_drink(request):
print(f"An exception occured while processing an order: User: {user.username} - Exception: {e}", file=sys.stderr) print(f"An exception occured while processing an order: User: {user.username} - Exception: {e}", file=sys.stderr)
return HttpResponse(b"", status=500) return HttpResponse(b"", status=500)
@login_required @login_required
def api_deposit(request): def api_deposit(request):
# check request -> deposit # check request -> deposit
@ -140,9 +137,38 @@ def api_deposit(request):
return HttpResponse("success", status=200) return HttpResponse("success", status=200)
else: raise Exception("Deposit amount too big or small.") else: raise Exception("Deposit amount too big or small.")
except Exception as e: except Exception as e:
print(f"An exception occured while processing a transaction: User: {user.username} - Exception: {e}", file=sys.stderr) print(f"An exception occured while processing a deposit transaction: User: {user.username} - Exception: {e}", file=sys.stderr)
return HttpResponse(b"", status=500) return HttpResponse(b"", status=500)
@login_required
def api_transfer(request):
# check request -> transfer
user = request.user
try:
recipient = get_user_model().objects.get(id=int(request.POST["recipientuser"]))
if recipient.id == user.id:
raise Exception(f"User {user.username} tried to transfer to themself.")
amount = decimal.Decimal(request.POST["transferamount"])
if 0.00 < amount <= user.balance:
print("sender:", user.username)
print("recipient:", recipient.username)
print("amount:", amount)
# create transaction
RegisterTransaction.objects.create(
transaction_sum=-amount,
comment=f"Transfer to {recipient.username}",
is_transfer=True,
user=user)
RegisterTransaction.objects.create(
transaction_sum=amount,
comment=f"Transfer from {user.username}",
is_transfer=True,
user=recipient)
return HttpResponse("success", status=200)
else: raise Exception("Transfer amount too big or small.")
except Exception as e:
print(f"An exception occured while processing a transfer transaction: User: {user.username} - Exception: {e}", file=sys.stderr)
return HttpResponse(b"", status=500)
@login_required @login_required
def api_supply(request): def api_supply(request):