From d0252d1e6193da9ddf56d05bc5872578a3afae99 Mon Sep 17 00:00:00 2001 From: Martin Quarda Date: Wed, 9 Oct 2024 14:27:03 +0200 Subject: [PATCH] new registration --- alkator/urls.py | 18 +++- alkatorapi/models.py | 27 +++++ alkatorapi/views.py | 241 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 237 insertions(+), 49 deletions(-) diff --git a/alkator/urls.py b/alkator/urls.py index ad6f677..44f5319 100644 --- a/alkator/urls.py +++ b/alkator/urls.py @@ -16,15 +16,27 @@ Including another URLconf """ from django.contrib import admin from django.urls import path -from alkatorapi.views import register, results, photos, payment_result, payment_state, invoice, upload_files +from alkatorapi.views import ( + register_racer, register_racer, + login, logout, + results, photos, + payment_result, payment_state, + invoice, upload_files, + login_status, +) urlpatterns = [ path('admin/', admin.site.urls), - path('api/register', register), + path('api/register_user', register_racer), + path('api/register_racer', register_racer), + path('api/login', login), + path('api/login_status', login_status), + path('api/logout', logout), + #path('api/register', register), path('api/results', results), path('api/photos', photos), path('api/payment_result', payment_result), path('api/payment_state', payment_state), path('api/invoice', invoice), - path('api/upload_files', upload_files) + path('api/upload_files', upload_files), ] diff --git a/alkatorapi/models.py b/alkatorapi/models.py index ae2811f..9506d9f 100644 --- a/alkatorapi/models.py +++ b/alkatorapi/models.py @@ -1,5 +1,6 @@ from django.db import models from django.contrib import admin +from django.contrib.auth.models import User as DjangoUser ALKATOR_CHOICES = ( (1, "Alkátor"), @@ -10,6 +11,7 @@ ALKATOR_CHOICES = ( ALKATOR_CLASSES = ( (1, "Jaro 2024 Sobkovice"), (2, "Podzim 2024 Studené"), + (3, "Jaro 2025 Dolní Čermná") ) ALKATOR_CHOICES_DICT = { @@ -41,3 +43,28 @@ class User(models.Model): def __str__(self): return f"" + + +class Profile(models.Model): + user = models.OneToOneField(DjangoUser, related_name='profile') + first_name = models.CharField(max_length=120) + last_name = models.CharField(max_length=120) + address = models.CharField(max_length=255, null=True, blank=True) + + +class Racer(models.Model): + profile = models.ForeignKey(Profile, related_name='racers', null=True, empty=True) + first_name = models.CharField(max_length=120) + last_name = models.CharField(max_length=120) + email = models.EmailField(max_length=120, null=True, blank=True) + team = models.CharField(max_length=120, null=True, blank=True) + phone = models.CharField(max_length=120, null=True, blank=True) + date_of_birth = models.DateField(null=True, blank=True) + duration = models.DurationField(null=True, blank=True) + starting_number = models.IntegerField(null=True, blank=True) + alkator_category = models.IntegerField(choices=ALKATOR_CHOICES, default=1) + alkator_class = models.IntegerField(choices=ALKATOR_CLASSES) + trans_id = models.CharField(null=True, blank=True, max_length=120) + price = models.IntegerField(default=690) + paid = models.BooleanField(default=False) + invoice_id = models.IntegerField(null=True, blank=True, unique=True) diff --git a/alkatorapi/views.py b/alkatorapi/views.py index 2dab8ec..4aa03e0 100644 --- a/alkatorapi/views.py +++ b/alkatorapi/views.py @@ -3,6 +3,8 @@ from django.http import HttpResponse from django.template.response import TemplateResponse from django.views.decorators.csrf import csrf_exempt from django.contrib.admin.views.decorators import staff_member_required +from django.contrib.auth.models import User as DjangoUser +from django.contrib.auth import authenticate, login from django.core.mail import send_mail, mail_admins from datetime import date, datetime, timedelta from urllib.parse import parse_qs @@ -13,13 +15,56 @@ import PIL.Image import random from collections import OrderedDict -from .models import User, ALKATOR_CHOICES_DICT, ALKATOR_CLASSES +from .models import User, ALKATOR_CHOICES_DICT, ALKATOR_CLASSES, Profile, Racer from alkator.settings import COMGATE_MERCHANT, COMGATE_SECRET, COMGATE_TEST @csrf_exempt -def register(request): - ALKATOR_CLASS = 2 +def register_user(request): + if not request.POST['first_name']: + return HttpResponse('{"reason":"Jméno je povinné!"}', status=400, content_type='application/json') + if not request.POST['last_name']: + return HttpResponse('{"reason":"Přijmení je povinné!"}', status=400, content_type='application/json') + if not request.POST['email']: + return HttpResponse('{"reason":"Email je povinný!"}', status=400, content_type='application/json') + if not request.POST['address']: + return HttpResponse('{"reason":"Adresa je povinná!"}', status=400, content_type='application/json') + if not request.POST['password1'] or not request.POST['password2']: + return HttpResponse('{"reason":"Heslo je povinné!"}', status=400, content_type='application/json') + if request.POST['password1'] != request.POST['password2']: + return HttpResponse('{"reason":"Hesla se neshodují!"}', status=400, content_type='application/json') + if DjangoUser.objects.filter(email=request.POST['email']): + return HttpResponse('{"reason":"Email je již registrován!"}', status=400, content_type='application/json') + email = request.POST['email'] + + user = DjangoUser.objects.create_user( + email, email, request.POST['password1'] + ) + profile = Profile(user=user, first_name=request.POST['first_name'], last_name=request.POST['last_name'], address=request.POST['address']) + profile.save() + login(request, user) + + +@csrf_exempt +def login(request): + user = authenticate(request, username=request.POST['email'], password=request.POST['password']) + if user is not None: + login(request, user) + return HttpResponse('{"success":"Úspěšně přihlášen uživatel '+ user.email + '"}', content_type='application/json') + else: + return HttpResponse('{"reason":"Nesprávné jméno nebo heslo!"}', status=400, content_type='application/json') + + +@csrf_exempt +def logout(request): + logout(request) + + +@csrf_exempt +def register_racer(request): + if not request.user.is_authenticated: + return HttpResponse('{"reason":"Je potřeba se přihlásit!"}', status=400, content_type='application/json') + ALKATOR_CLASS = 3 if date.today() >= date(2024, 10, 5): return HttpResponse('{"reason":"Too late!"}', status=400, content_type='application/json') @@ -29,15 +74,7 @@ def register(request): return HttpResponse('{"reason":"Jméno je povinné!"}', status=400, content_type='application/json') if not request.POST['last_name']: return HttpResponse('{"reason":"Přijmení je povinné!"}', status=400, content_type='application/json') - if not request.POST['email']: - return HttpResponse('{"reason":"Email je povinný!"}', status=400, content_type='application/json') - if not request.POST['address']: - return HttpResponse('{"reason":"Adresa je povinná!"}', status=400, content_type='application/json') - if not request.POST['phone']: - return HttpResponse('{"reason":"Telefoní číslo je povinný!"}', status=400, content_type='application/json') - if User.objects.filter(email=request.POST['email'], alkator_class=ALKATOR_CLASS): - return HttpResponse('{"reason":"Email je již registrován!"}', status=400, content_type='application/json') - if User.objects.filter(alkator_class=ALKATOR_CLASS, paid=True).count() >= 50: + if Racer.objects.filter(alkator_class=ALKATOR_CLASS, paid=True).count() >= 100: return HttpResponse('{"reason":"Kapacita závodu byla naplněna!"}', status=400, content_type='application/json') try: dat = datetime.strptime(request.POST['date_of_birth'], "%Y-%m-%d").date() @@ -52,11 +89,11 @@ def register(request): invoice_id = invoice_date.year * 1000000 + invoice_date.month * 10000 + invoice_date.day * 100 try: - latest_user = User.objects.latest("invoice_id") - if latest_user.invoice_id is None or latest_user.invoice_id < invoice_id: + latest_racer = Racer.objects.latest("invoice_id") + if latest_racer.invoice_id is None or latest_racer.invoice_id < invoice_id: invoice_id = invoice_id + 1 else: - invoice_id = latest_user.invoice_id + 1 + invoice_id = latest_racer.invoice_id + 1 except User.DoesNotExist: invoice_id = invoice_id + 1 @@ -65,18 +102,22 @@ def register(request): else: price = 69000 - user = User( - first_name=request.POST['first_name'], - last_name=request.POST['last_name'], - email=request.POST['email'], - date_of_birth=dat, - address=request.POST['address'], - phone=request.POST['phone'], - alkator_class=ALKATOR_CLASS, - invoice_id=invoice_id, - price=price//100 + profile = request.user.profile + user = request.user + + racer = Racer( + profile = profile, + first_name = request.POST['first_name'], + last_name = request.POST['last_name'], + email = request.POST['email'], + team = request.POST['team'], + phone = request.POST['phone'], + date_of_birth = dat, + alkator_class = ALKATOR_CLASS, + price = price, + invoice_id = invoice_id, ) - user.save() + racer.save() payment_data = { 'merchant': COMGATE_MERCHANT, @@ -86,8 +127,8 @@ def register(request): 'method': 'ALL', 'label': 'Startovné na závod Alkátor Race Studené 2024', 'email': user.email, - 'fullName': f"{user.first_name} {user.last_name}", - 'refId': f'{user.invoice_id}', + 'fullName': f"{profile.first_name} {profile.last_name}", + 'refId': f'{racer.invoice_id}', 'secret': COMGATE_SECRET, 'prepareOnly': 'true', } @@ -96,15 +137,125 @@ def register(request): result = parse_qs(result.text) if result['code'][0] != '0': - user.delete() + racer.delete() return HttpResponse('{"reason":"Chyba na straně platební brány: ' + result['message'][0] + ', zkuste prosím registraci později."}', status=400, content_type='application/json') - user.trans_id = result['transId'][0] - user.save() + racer.trans_id = result['transId'][0] + racer.save() return HttpResponse('{"success":"", "redirect":"' + result['redirect'][0] + '"}', content_type='application/json') +def login_status(request): + if not request.user.is_authenticated: + return HttpResponse('{}', content_type='application/json') + + user = request.user + racers = user.profile.racers + return HttpResponse(json.dumps({ + "email": user.email, + "first_name": user.profile.first_name, + "last_name": user.profile.last_name, + "address": user.profile.address, + "racers": [{ + "first_name": racer.first_name, + "last_name": racer.last_name, + "email": racer.email, + "team": racer.team, + "date_of_birth": racer.date_of_birth, + "paid": racer.paid, + } for racer in racers] + }), content_type='application/json') + + +#@csrf_exempt +#def register(request): +# ALKATOR_CLASS = 2 +# +# if date.today() >= date(2024, 10, 5): +# return HttpResponse('{"reason":"Too late!"}', status=400, content_type='application/json') +# if not request.POST.get('agreement'): +# return HttpResponse('{"reason":"Je potřeba souhlasit se zpracováním údajů!"}', status=400, content_type='application/json') +# if not request.POST['first_name']: +# return HttpResponse('{"reason":"Jméno je povinné!"}', status=400, content_type='application/json') +# if not request.POST['last_name']: +# return HttpResponse('{"reason":"Přijmení je povinné!"}', status=400, content_type='application/json') +# if not request.POST['email']: +# return HttpResponse('{"reason":"Email je povinný!"}', status=400, content_type='application/json') +# if not request.POST['address']: +# return HttpResponse('{"reason":"Adresa je povinná!"}', status=400, content_type='application/json') +# if not request.POST['phone']: +# return HttpResponse('{"reason":"Telefoní číslo je povinný!"}', status=400, content_type='application/json') +# if User.objects.filter(email=request.POST['email'], alkator_class=ALKATOR_CLASS): +# return HttpResponse('{"reason":"Email je již registrován!"}', status=400, content_type='application/json') +# if User.objects.filter(alkator_class=ALKATOR_CLASS, paid=True).count() >= 50: +# return HttpResponse('{"reason":"Kapacita závodu byla naplněna!"}', status=400, content_type='application/json') +# try: +# dat = datetime.strptime(request.POST['date_of_birth'], "%Y-%m-%d").date() +# if dat > date(2006, 10, 5): +# return HttpResponse('{"reason":"Je potřeba mít 18 let v den závodu!"}', status=400, content_type='application/json') +# elif dat < date(1924, 10, 5): +# return HttpResponse('{"reason":"Opravdu vám je 100 let?"}', status=400, content_type='application/json') +# except: +# return HttpResponse('{"reason":"Špatný formát datu narození!"}', status=400, content_type='application/json') +# +# invoice_date = datetime.today() +# invoice_id = invoice_date.year * 1000000 + invoice_date.month * 10000 + invoice_date.day * 100 +# +# try: +# latest_user = User.objects.latest("invoice_id") +# if latest_user.invoice_id is None or latest_user.invoice_id < invoice_id: +# invoice_id = invoice_id + 1 +# else: +# invoice_id = latest_user.invoice_id + 1 +# except User.DoesNotExist: +# invoice_id = invoice_id + 1 +# +# if date.today() >= date(2024, 9, 21): +# price = 79000 +# else: +# price = 69000 +# +# user = User( +# first_name=request.POST['first_name'], +# last_name=request.POST['last_name'], +# email=request.POST['email'], +# date_of_birth=dat, +# address=request.POST['address'], +# phone=request.POST['phone'], +# alkator_class=ALKATOR_CLASS, +# invoice_id=invoice_id, +# price=price//100 +# ) +# user.save() +# +# payment_data = { +# 'merchant': COMGATE_MERCHANT, +# 'test': 'true' if COMGATE_TEST else 'false', +# 'price': price, +# 'curr': 'CZK', +# 'method': 'ALL', +# 'label': 'Startovné na závod Alkátor Race Studené 2024', +# 'email': user.email, +# 'fullName': f"{user.first_name} {user.last_name}", +# 'refId': f'{user.invoice_id}', +# 'secret': COMGATE_SECRET, +# 'prepareOnly': 'true', +# } +# result = requests.post('https://payments.comgate.cz/v1.0/create', data=payment_data) +# +# result = parse_qs(result.text) +# +# if result['code'][0] != '0': + user.delete() + return HttpResponse('{"reason":"Chyba na straně platební brány: ' + result['message'][0] + ', zkuste prosím registraci později."}', status=400, content_type='application/json') +# +# user.trans_id = result['transId'][0] +# user.save() +# +# return HttpResponse('{"success":"", "redirect":"' + result['redirect'][0] + '"}', content_type='application/json') + + @csrf_exempt def payment_result(request): result = parse_qs(request.body.decode('utf8')) @@ -115,20 +266,20 @@ def payment_result(request): if not secret_match or test != COMGATE_TEST: return HttpResponse(status=400) try: - user = User.objects.get(invoice_id=ref_id) - except User.DoesNotExist: + racer = Racer.objects.get(invoice_id=ref_id) + except Racer.DoesNotExist: mail_admins('Chyba s platbou!', f'invoice_id={ref_id}&paid={paid}') return HttpResponse(status=404) if paid == 'PAID': - user.paid = True - user.save() + racer.paid = True + racer.save() send_mail( - "úspěšná registrace do závodu Alkátor race Studené", + f"úspěšná registrace do závodu Alkátor race Dolní Čermná ({racer.first_name} {racer.last_name})", f"""Zdravím tě Alkátore, -toto je potvrzovací email o tvé účasti v nezapomenutelném závodě Alkátor-race. +toto je potvrzovací email o účasti v nezapomenutelném závodě Alkátor-race. Prosíme kontrolujete si své hromadné schránky a spamy. -Závod se koná 5.10.2024 na Studeném v Orlických horách, hned u Podskaláku. +Závod se koná 5.10.2024 v Dolní Čermné. Zajištěno je stanování, občerstvení a také večerní after párty. Připrav na zkoušku své tělo, játra a tvé mozkové buňky. @@ -144,24 +295,22 @@ email: info@alkator.cz tel: + 420 728 018 088 web: https://alkator.cz""", "info@alkator.cz", - [user.email], + [racer.profile.user.email, racer.email] if racer.email else [racer.profile.user.email], ) elif paid == 'CANCELLED' and not user.paid: - #effectively disabling email adress as email address cannot contain ' ' - user.email = ' '+user.email - user.save() + racer.delete() return HttpResponse(status=200) def payment_state(request): invoice_id = request.GET['refId'] try: - if User.objects.get(invoice_id=invoice_id).paid: + if Racer.objects.get(invoice_id=invoice_id).paid: return HttpResponse('{"status":"success", "reason":"Úspěšná platba"}', content_type='application/json') else: return HttpResponse('{"status":"failed", "reason":"Zatím nemáme informace o provedené platbě. Zkuste reload nebo zkontrolujte email."}', content_type='application/json') - except User.DoesNotExist: - return HttpResponse('{"status":"failed", "reason":"Uživatel neexistuje, registraci prosím opakujte."}', content_type='application/json') + except Racer.DoesNotExist: + return HttpResponse('{"status":"failed", "reason":"Závodník neexistuje, registraci závodníka prosím opakujte."}', content_type='application/json') def results(request): @@ -194,7 +343,7 @@ def results(request): def photos(request): rtn = [] - for (i, name) in ALKATOR_CLASSES: + for (i, name) in ALKATOR_CLASSES[:2]: photos = {} rtn.append(photos) photos['name'] = name