Added feature to transfer money to another account + some minor improvements

This commit is contained in:
Julian Müller (ChaoticByte) 2023-04-14 23:47:12 +02:00
parent 2bab323b86
commit 8702233934
11 changed files with 164 additions and 30 deletions

View file

@ -45,9 +45,10 @@ def select_history(user, language_code="en") -> list:
result = _db_select(f"""
select
concat(
price_sum, '{settings.CURRENCY_SUFFIX} - ',
product_name, ' (',
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
from app_order
where user_id = {user_id}
@ -55,11 +56,19 @@ def select_history(user, language_code="en") -> list:
union
select
concat('Deposit: +', transaction_sum, '{settings.CURRENCY_SUFFIX}') as "text",
concat(transaction_sum, '{settings.CURRENCY_SUFFIX} - Deposit') as "text",
datetime
from app_userdeposits_view
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
fetch first 30 rows only;
""")

Binary file not shown.

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\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"
"Last-Translator: Julian Müller (ChaoticByte)\n"
"Language: DE\n"
@ -33,20 +33,21 @@ msgstr "Ein Fehler ist aufgetreten. Bitte ab- und wieder anmelden."
msgid "Drinks - Deposit"
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"
msgstr "Einzahlen"
#: app/templates/deposit.html:19
#: app/templates/deposit.html:19 app/templates/transfer.html:43
msgid "Amount"
msgstr "Summe"
#: app/templates/deposit.html:30 app/templates/order.html:54
#: app/templates/registration/login.html:28 app/templates/supply.html:29
#: app/templates/transfer.html:54
msgid "cancel"
msgstr "Abbrechen"
#: app/templates/deposit.html:31
#: app/templates/deposit.html:31 app/templates/transfer.html:55
msgid "confirm"
msgstr "Bestätigen"
@ -54,7 +55,7 @@ msgstr "Bestätigen"
msgid "Drinks - History"
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"
msgstr "Verlauf"
@ -164,7 +165,7 @@ msgstr "Wähle deinen Account"
msgid "Drinks - Statistics"
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"
msgstr "Statistiken"
@ -206,7 +207,7 @@ msgstr "Tag"
msgid "Drinks - Supply"
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"
msgstr "Beschaffung"
@ -226,19 +227,36 @@ msgstr "Senden"
msgid "You are not allowed to view this site."
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"
msgstr "Saldo"
#: app/templates/userpanel.html:24
#: app/templates/userpanel.html:19
msgid "Logout"
msgstr "Abmelden"
#: app/templates/userpanel.html:27
#: app/templates/userpanel.html:22
msgid "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"
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)
datetime = models.DateTimeField(default=timezone.now)
is_user_deposit = models.BooleanField(default=False)
is_transfer = models.BooleanField(default=False)
comment = models.TextField(default=" ")
user = models.ForeignKey(User, on_delete=models.CASCADE)
def save(self, *args, **kwargs):
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.save()
self.old_transaction_sum = self.transaction_sum
super().save(*args, **kwargs)
else:
# update register transaction
sum_diff = self.transaction_sum - self.old_transaction_sum
# update user balance
if self.is_user_deposit == True:
ub_sum_diff = self.transaction_sum - self.old_transaction_sum
self.user.balance += ub_sum_diff
if self.is_user_deposit or self.is_transfer:
self.user.balance += self.transaction_sum - self.old_transaction_sum
self.user.save()
# update register transaction
self.old_transaction_sum = self.transaction_sum
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
# 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.save()
super().delete(*args, kwargs)

View file

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

View file

@ -48,6 +48,8 @@
{{ user_.last_name }},
{% endif %}
{{ user_.first_name }}
{% elif user_.last_name %}
{{ user_.last_name }}
{% else %}
{{ user_.username }}
{% 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 %}
<a class="button dropdownchoice" href="/admin/">Admin Panel</a>
{% endif %}
<a class="button dropdownchoice" href="/transfer/">{% translate "Transfer" %}</a>
{% if user.is_superuser or user.allowed_to_supply %}
<a class="button dropdownchoice" href="/supply/">{% translate "Supply" %}</a>
{% endif %}

View file

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

View file

@ -50,7 +50,6 @@ def login_page(request):
"user_list": userlist
})
@login_required
def index(request):
context = {
@ -58,7 +57,6 @@ def index(request):
}
return render(request, "index.html", context)
@login_required
def history(request):
context = {
@ -66,7 +64,6 @@ def history(request):
}
return render(request, "history.html", context)
@login_required
def order(request, drinkid):
try:
@ -76,7 +73,6 @@ def order(request, drinkid):
except Drink.DoesNotExist:
return HttpResponseRedirect("/")
@login_required
def deposit(request):
return render(request, "deposit.html", {})
@ -91,17 +87,19 @@ def statistics(request):
}
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
def supply(request):
return render(request, "supply.html")
@login_required
def redirect_home(request):
return HttpResponseRedirect("/")
# API for XHR requests #
@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)
return HttpResponse(b"", status=500)
@login_required
def api_deposit(request):
# check request -> deposit
@ -140,9 +137,38 @@ def api_deposit(request):
return HttpResponse("success", status=200)
else: raise Exception("Deposit amount too big or small.")
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)
@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
def api_supply(request):