alkator/alkatorapi/views.py
Martin Quarda 1593c4d599 faktury
2024-10-11 10:18:55 +02:00

453 lines
19 KiB
Python

from django.shortcuts import render
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.shortcuts import redirect
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
from django.contrib.auth import login as auth_login, logout as auth_logout
from django.core.mail import send_mail, mail_admins, EmailMessage
from django.utils.datastructures import MultiValueDictKeyError
from datetime import date, datetime, timedelta
from urllib.parse import parse_qs
import requests
import json
import glob
import PIL.Image
import random
from collections import OrderedDict
from .models import User, ALKATOR_CHOICES_DICT, ALKATOR_CLASSES, Profile, Racer
from alkator.settings import COMGATE_MERCHANT, COMGATE_SECRET, COMGATE_TEST
DEADLINE = date(2025, 10, 5)
ALKATOR_CLASS = 3
@csrf_exempt
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()
auth_login(request, user)
return HttpResponse('{"success":"Úspěšná registrace!", "redirect":"/#"}', content_type='application/json')
@csrf_exempt
def login(request):
try:
user = authenticate(request, username=request.POST['email'], password=request.POST['password'])
except MultiValueDictKeyError:
return HttpResponse('{"reason":"Nezadané jméno nebo heslo!"}', status=400, content_type='application/json')
if user is not None:
auth_login(request, user)
return HttpResponse('{"success":"Úspěšně přihlášen uživatel '+ user.email + '", "redirect":"/#"}', 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):
auth_logout(request)
return redirect("/#")
@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')
if date.today() >= DEADLINE:
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 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()
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_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_racer.invoice_id + 1
except User.DoesNotExist:
invoice_id = invoice_id + 1
if date.today() >= date(2024, 9, 21):
price = 79000
else:
price = 69000
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,
)
racer.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 Dolní Čermná 2025',
'email': user.email,
'fullName': f"{profile.first_name} {profile.last_name}",
'refId': f'{racer.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':
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')
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.all()
return HttpResponse(json.dumps({
"email": user.email,
"first_name": user.profile.first_name,
"last_name": user.profile.last_name,
"address": user.profile.address,
"racers": [{
"invoice_id": racer.invoice_id,
"first_name": racer.first_name,
"last_name": racer.last_name,
"email": racer.email,
"phone": racer.phone,
"team": racer.team,
"date_of_birth": racer.date_of_birth.strftime("%Y-%m-%d"),
"paid": racer.paid,
} for racer in racers]
}), content_type='application/json')
@csrf_exempt
def change_racer(request):
try:
racer = Racer.objects.get(invoice_id=request.POST['invoice_id'])
if request.user != racer.profile.user:
return HttpResponse('{"reason":"Nedostatečná práva!"}', status=400, content_type='application/json')
if date.today() >= DEADLINE:
return HttpResponse('{"reason":"Too late!"}', 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')
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')
racer.first_name = request.POST['first_name']
racer.last_name = request.POST['last_name']
racer.email = request.POST['email']
racer.phone = request.POST['phone']
racer.team = request.POST['team']
racer.date_of_birth = dat
racer.save()
return HttpResponse('{"success":"Úspěšně uloženo."}', content_type='application/json')
except MultiValueDictKeyError:
return HttpResponse('{"reason":"Nějaký údaj chybí!"}', status=400, 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'))
ref_id = int(result['refId'][0])
paid = result['status'][0]
secret_match = result['secret'][0] == COMGATE_SECRET
test = result['test'][0] != 'false'
if not secret_match or test != COMGATE_TEST:
return HttpResponse(status=400)
try:
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':
racer.paid = True
racer.save()
mail = EmailMessage(
subject=f"úspěšná registrace do závodu Alkátor race Dolní Čermná ({racer.first_name} {racer.last_name})",
body=f"""Zdravím tě Alkátore,
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 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.
Budou tě čekat nevídané překážky.
O podrobnostech tě budeme informovat emailem.
Nezapomeň nás sledovat na Facebooku, Instagramu, YouTube a TikToku.
Na tento email není třeba odpovídat, protože je generován automaticky s přijatou platbou. V případě potřeby pište na info@alkator.cz .
ALKÁTOR TEAM
email: info@alkator.cz
tel: + 420 728 018 088
web: https://alkator.cz""",
from_email="info@alkator.cz",
to=[racer.profile.user.email, racer.email] if racer.email else [racer.profile.user.email],
bcc=[],
cc=[]
)
user = request.user
template = TemplateResponse(
None,
'invoice.html',
{
'user': user,
'racer': racer,
'paid_date': racer.register_date + timedelta(days=1),
}
)
template.render()
pdf_name = f"invoices/{user.profile.last_name}_{user.profile.first_name}.pdf"
HTML(string=template.content).write_pdf(pdf_name)
attach = open(pdf_name, 'rb')
mail.attach('faktura.pdf', attach.read(), 'application/pdf')
mail.send()
elif paid == 'CANCELLED' and not user.paid:
racer.delete()
return HttpResponse(status=200)
def payment_state(request):
invoice_id = request.GET['refId']
try:
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 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):
results = []
n = 1
for user in User.objects.filter(alkator_class=2).order_by('duration'):
if user.duration:
if user.alkator_category == 1:
order = f'{n}.'
n += 1
else:
order = 'x.'
results.append({
'order': order,
'duration': str(user.duration),
'alkator_category': ALKATOR_CHOICES_DICT[user.alkator_category],
'starting_number': user.starting_number,
})
for user in User.objects.filter(alkator_class=2).order_by('duration'):
if not user.duration and user.starting_number:
results.append({
'order': 'DNF',
'duration': 'Nedokončil',
'starting_number': user.starting_number,
'alkator_category': ''
})
return HttpResponse(json.dumps(results), content_type='application/json')
def photos(request):
rtn = []
for (i, name) in ALKATOR_CLASSES[:2]:
photos = {}
rtn.append(photos)
photos['name'] = name
photos['index'] = i
photos['photos'] = []
files = glob.glob(f"photos/{i}/*.jpg")
random.shuffle(files)
for file in files:
img = PIL.Image.open(file)
photos['photos'].append({
'original': '/' + file.replace(".jpg", ".webp"),
'thumbnail': '/' + file.replace(f'photos/{i}/', f'photos/{i}/thumbnail/').replace(".jpg", ".webp"),
'original_width': img.width,
'original_height': img.height,
})
return HttpResponse(json.dumps(rtn), content_type='application/json')
@csrf_exempt
def upload_files(request):
for file in request.FILES.getlist('files'):
rand = random.randint(0, 99999)
random_name = f'photos/uploads/{rand}_{file.name}'
with open(random_name, "wb+") as destination:
for chunk in file.chunks():
destination.write(chunk)
return HttpResponse('{"success":"Úspěšně nahráno! Počkejte až dojde ke schválení nahraných souborů."}', content_type='application/json')
@staff_member_required
def invoice(request):
user = User.objects.get(invoice_id=request.GET['invoice_id'])
return TemplateResponse(
None,
'invoice.html',
{
'user': user,
'paid_date': user.register_date + timedelta(days=1),
}
)