Added feature to transfer money to another account + some minor improvements
This commit is contained in:
parent
2bab323b86
commit
8702233934
11 changed files with 164 additions and 30 deletions
|
@ -45,21 +45,30 @@ 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}
|
||||
|
||||
union
|
||||
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.
|
@ -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"
|
||||
|
||||
|
|
17
app/migrations/0004_registertransaction_is_transfer.py
Normal file
17
app/migrations/0004_registertransaction_is_transfer.py
Normal 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),
|
||||
),
|
||||
]
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
{{ user_.last_name }},
|
||||
{% endif %}
|
||||
{{ user_.first_name }}
|
||||
{% elif user_.last_name %}
|
||||
{{ user_.last_name }}
|
||||
{% else %}
|
||||
{{ user_.username }}
|
||||
{% endif %}
|
||||
|
|
60
app/templates/transfer.html
Normal file
60
app/templates/transfer.html
Normal 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 %}
|
|
@ -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 %}
|
||||
|
|
|
@ -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)
|
||||
]
|
||||
|
|
42
app/views.py
42
app/views.py
|
@ -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):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue