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 weasyprint import HTML 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, Invoice, Product, InvoiceProduct 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 not request.POST['phone']: 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'], phone=request.POST['phone'], ) 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') try: dob = datetime.strptime(request.POST['date_of_birth'], "%Y-%m-%d").date() if dob > 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 dob < 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_id = Invoice.next_invoice_id() profile = request.user.profile user = request.user product = Product.objects.get(id=1) price = product.price if product.quantity <= 0: return HttpResponse('{"reason":"Jsme vyprodaní!"}', status=400, content_type='application/json') invoice = Invoice( invoice_id=invoice_id, user=user, total_price=price, address="", ) racer = Racer( product=product, invoice=invoice, quantity=1, 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 = dob, alkator_class = ALKATOR_CLASS, price=price, ) invoice.save() racer.save() payment_data = { 'merchant': COMGATE_MERCHANT, 'test': 'true' if COMGATE_TEST else 'false', 'price': price * 100, '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'{invoice.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() invoice.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') product.quantity -= 1 product.save() invoice.trans_id = result['transId'][0] invoice.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": [{ "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.invoice.paid, } for racer in racers] }), content_type='application/json') @csrf_exempt def change_racer(request): try: racer = Racer.objects.get(invoice_id=request.POST['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":"Příliš pozdě na změnu účastníka!"}', 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: dob = datetime.strptime(request.POST['date_of_birth'], "%Y-%m-%d").date() if dob > 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 dob < 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 = dob 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 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: invoice = Invoice.objects.get(invoice_id=ref_id) except Invoice.DoesNotExist: mail_admins('Chyba s platbou!', f'invoice_id={ref_id}&paid={paid}') return HttpResponse(status=404) if paid == 'PAID': invoice.paid = True invoice.save() try: racer = Racer.objects.get(invoice=invoice) 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=["info@alkator.cz"], cc=[] ) except Racer.DoesNotExist: mail = EmailMessage( subject=f"úspěšně zaplacený nákup v Alkátor shopu", body=f"""Zdravím tě Alkátore, úspěšně si zakoupil merch na Alkátor shopu. 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=["info@alkator.cz"], cc=[] ) return HttpResponse(status=200) user = invoice.user template = TemplateResponse( None, 'invoice.html', { 'user': user, 'invoice': invoice, 'products': InvoiceProduct.objects.filter(invoice=invoice), 'paid_date': invoice.paid_date + timedelta(days=1), } ) template.render() pdf_name = f"invoices/{invoice.invoice_id}_{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') if not mail.send(): return HttpResponse(status=500) elif paid == 'CANCELLED' and not user.paid: racer.product.quantity += 1 racer.product.save() racer.delete() invoice.delete() return HttpResponse(status=200) def payment_state(request): invoice_id = request.GET['refId'] try: if Invoice.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 Invoice.DoesNotExist: return HttpResponse('{"status":"failed", "reason":"Závodník neexistuje, registraci závodníka prosím opakujte."}', content_type='application/json') def products(request): return HttpResponse(json.dumps([ { 'id': product.id, 'name': product.name, 'description': product.description, 'img': product.img.url, 'price': product.price, 'quantity': product.quantity, } for product in Product.objects.all()[1:] ]), 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): invoice = Invoice.objects.get(invoice_id=request.GET['invoice_id']) user = DjangoUser.objects.get(id=invoice.user_id) return TemplateResponse( None, 'invoice.html', { 'user': user, 'invoice': invoice, 'products': InvoiceProduct.objects.filter(invoice=invoice), 'paid_date': invoice.paid_date + timedelta(days=1), } )