signal return after stripe paiement ok

This commit is contained in:
Jonas 12t 2021-11-01 15:18:02 +04:00
parent a6eff19fa2
commit d1a22548cd
14 changed files with 375 additions and 312 deletions

View File

@ -5,11 +5,13 @@ import json
from django.utils.translation import gettext, gettext_lazy as _
from rest_framework.generics import get_object_or_404
import PaiementStripe
from AuthBillet.models import TibilletUser, HumanUser
from BaseBillet.models import Event, Price, Product, Reservation, Configuration, LigneArticle, Ticket, Paiement_stripe
from PaiementStripe.views import creation_paiement_stripe
import logging
logger = logging.getLogger(__name__)
class ProductSerializer(serializers.ModelSerializer):
class Meta:
@ -265,9 +267,15 @@ class ReservationValidator(serializers.Serializer):
)
if new_paiement_stripe.is_valid():
reservation.paiement = new_paiement_stripe.paiement_stripe_db
paiement_stripe : Paiement_stripe = new_paiement_stripe.paiement_stripe_db
paiement_stripe.lignearticle_set.all().update(status=LigneArticle.UNPAID)
reservation.tickets.all().update(status=Ticket.NOT_ACTIV)
reservation.paiement = paiement_stripe
reservation.status = Reservation.UNPAID
reservation.save()
print(new_paiement_stripe.checkout_session.stripe_id)
# return new_paiement_stripe.redirect_to_stripe()
self.checkout_session = new_paiement_stripe.checkout_session
@ -278,6 +286,7 @@ class ReservationValidator(serializers.Serializer):
def to_representation(self, instance):
representation = super().to_representation(instance)
logger.info(f"{self.checkout_session.url}")
representation['checkout_url'] = self.checkout_session.url
# import ipdb;ipdb.set_trace()
return representation

View File

@ -440,41 +440,14 @@
<strong>Grand merci pour votre reservation !</strong>
<br><br>
{% if reservation.tickets %}
Vous trouverez vos tickets en pièce jointe.
Vous trouverez vos billets en pièce jointe.
{% else %}
Aucun ticket pour un concert ? Etrange etrange
Aucun billets pour un concert ? Etrange etrange
{% endif %}
</td>
</tr>
<!-- END BODY COPY -->
<!-- BUTTON -->
<tr>
<td align="left"
style="padding: 18px 18px 18px 18px; mso-alt-padding: 18px 18px 18px 18px!important;">
<table width="100%" border="0" cellspacing="0"
cellpadding="0">
<tr>
<td>
<table border="0" cellspacing="0"
cellpadding="0">
<tr>
<td align="left"
style="border-radius: 3px;"
bgcolor="#17bef7">
<a class="button raised"
href="{{ config.domaine_cashless }}/rapport/invoice/{{ adhesion.commande }}"
target="_blank"
style="font-size: 14px; line-height: 14px; font-weight: 500; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; border-radius: 3px; padding: 10px 25px; border: 1px solid #17bef7; display: inline-block;">
TELECHARGER REÇU</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- END BUTTON -->
</table>
</td>
</tr>

View File

@ -12,7 +12,7 @@
<body>
<section id="informations">
<h1 id="name">{{ ticket.first_name }} {{ ticket.last_name }}</h1>
<h1 id="destination">CDG ✈ LFLL</h1>
<h1 id="destination">{{ ticket.reservation.event.name }}</h1>
<dl>
<dt>Flight</dt>
<dd>DL31</dd>
@ -33,7 +33,7 @@
<section id="ticket">
<p>1257797706706</p>
<h2>Théodore Marcelin</h2>
<h2>{{ ticket.first_name }} {{ ticket.last_name }}</h2>
<dl>
<dt>Flight</dt>
<dd>DL31</dd>
@ -45,7 +45,7 @@
<dd>4</dd>
</dl>
<ul>
<li>CDG ✈ LFLL</li>
<li>{{ ticket.reservation.event.name }}</li>
<li>5:10pm</li>
</ul>
</section>

View File

@ -9,8 +9,8 @@ from weasyprint import HTML
from BaseBillet.models import Configuration, Reservation, Ticket
import logging
logger = logging.getLogger(__name__)
logger = logging.getLogger(__name__)
'''
from ApiBillet.thread_mailer import ThreadMaileur
@ -23,34 +23,28 @@ mail.send_with_tread()
class ThreadMaileur():
def __init__(self, email, title, text=None, html=None, template=None, context=None):
def __init__(self,
email: str,
title: str,
text=None,
html=None,
template=None,
context=None,
urls_for_attached_files=None,
):
self.title = title
self.email = email
self.text = text
self.html = html
self.config = Configuration.get_solo()
self.context = None
self.context = context
self.urls_for_attached_files = urls_for_attached_files
if template and context:
self.html = render_to_string(template, context=context)
self.context = context
self.tickets_uuid = self._tickets_uuid()
self.url = self._url()
def _url(self):
url = f"http://{connection.tenant.domains.all()[0].domain}:8002/api/ticket/"
return url
def _tickets_uuid(self):
tickets_uuid = []
if self.context :
if self.context.get('reservation'):
reservation: Reservation = self.context.get('reservation')
tickets = reservation.tickets.filter(status=Ticket.NOT_SCANNED)
if len(tickets) > 0:
for ticket in tickets :
tickets_uuid.append(f"{ticket.uuid}")
return tickets_uuid
def config_valid(self):
EMAIL_HOST = os.environ.get('EMAIL_HOST')
@ -74,28 +68,13 @@ class ThreadMaileur():
)
mail.attach_alternative(self.html, "text/html")
attached_file = []
for ticket in self.tickets_uuid :
response = requests.get(f"{self.url}{ticket}")
for filename, url in self.urls_for_attached_files.items():
response = requests.get(url)
if response.status_code == 200:
attached_file.append(response.content)
# attached_file.append(render_to_string('ticket/ticket.html', context={'context': 'context'}))
# msg = EmailMessage(subject, html_content, from_email, [to])
# msg.content_subtype = "html" # Main content is now text/html
# msg.send()
# import ipdb; ipdb.set_trace()
i=1
for file in attached_file:
# html_before_pdf = HTML(string=file)
# mail.attach(f'ticket_{i}.pdf', html_before_pdf.write_pdf(), 'application/pdf')
mail.attach(f'ticket_{i}.pdf', file, 'application/pdf')
i += 1
mail.attach(filename, response.content, 'application/pdf')
mail_return = mail.send(fail_silently=False)
if mail_return == 1:
logger.info(f' mail envoyé : {mail_return} - {self.email}')
else:
@ -105,7 +84,6 @@ class ThreadMaileur():
logger.error(f'Pas de contenu HTML ou de configuration email valide')
raise ValueError('Pas de contenu HTML ou de configuration email valide')
def send_with_tread(self):
# self.send()

View File

@ -15,6 +15,8 @@ router.register(r'reservations', api_view.ReservationViewset, basename='reservat
urlpatterns = [
path('', include(router.urls)),
path('ticket/<uuid:pk_uuid>', TicketPdf.as_view(), name='ticket_uuid'),
#download ticket :
path('ticket/pdf/<uuid:pk_uuid>', TicketPdf.as_view(), name='ticket_uuid_to_pdf'),
]

View File

@ -150,11 +150,10 @@ class TicketPdf(WeasyTemplateView):
kwargs['ticket'] = ticket
kwargs['config'] = self.config
self.nom_prenom = f"{ticket.first_name.upper()}_{ticket.last_name.capitalize()}"
self.pdf_filename = ticket.pdf_filename()
return kwargs
def get_pdf_filename(self, **kwargs):
nom_prenom = self.nom_prenom
return f"Ticket_{nom_prenom}.pdf"
return self.pdf_filename
#

View File

@ -9,6 +9,7 @@ from django.db.models.aggregates import Sum
from django.db.models import Q
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
from django.urls import reverse
from django.utils import timezone
from django.contrib.postgres.fields import JSONField
from solo.models import SingletonModel
@ -325,7 +326,7 @@ class Reservation(models.Model):
on_delete=models.PROTECT,
related_name="reservation")
CANCELED, CREATED, UNPAID, PAID, VALID, = 'C', 'R', 'N', 'P', 'V'
CANCELED, CREATED, UNPAID, PAID, VALID, = 'C', 'R', 'U', 'P', 'V'
TYPE_CHOICES = [
(CANCELED, _('Annulée')),
(CREATED, _('Crée')),
@ -356,7 +357,7 @@ class Reservation(models.Model):
def articles_paid(self):
articles_paid = []
for paiement in self.paiements_paid():
for paiement in self.paiements.all():
for ligne in paiement.lignearticle_set.filter(
Q(status=LigneArticle.PAID) | Q(status=LigneArticle.VALID)
):
@ -401,16 +402,39 @@ class Ticket(models.Model):
reservation = models.ForeignKey(Reservation, on_delete=models.CASCADE, related_name="tickets")
NOT_ACTIV, NOT_SCANNED, SCANNED = 'N', 'K', 'S'
CREATED, NOT_ACTIV, NOT_SCANNED, SCANNED = 'C', 'N', 'K', 'S'
SCAN_CHOICES = [
(CREATED, _('Crée')),
(NOT_ACTIV, _('Non actif')),
(NOT_SCANNED, _('Non scanné')),
(SCANNED, _('scanné')),
]
status = models.CharField(max_length=1, choices=SCAN_CHOICES, default=NOT_ACTIV,
status = models.CharField(max_length=1, choices=SCAN_CHOICES, default=CREATED,
verbose_name=_("Status du scan"))
seat = models.CharField(max_length=20, default=_('Placement libre'))
def pdf_filename(self):
config = Configuration.get_solo()
return f"{config.organisation.upper()} " \
f"{self.reservation.event.datetime.astimezone().strftime('%d/%m/%Y')} " \
f"{self.first_name.upper()} " \
f"{self.last_name.capitalize()}" \
f".pdf"
def pdf_url(self):
domain = connection.tenant.domains.all().first().domain
api_pdf = reverse("ticket_uuid_to_pdf", args=[f"{self.uuid}"])
protocol = "https://"
port = ""
if settings.DEBUG:
protocol = "http://"
port = ":8002"
return f"{protocol}{domain}{port}{api_pdf}"
def event(self):
return self.reservation.event
@ -454,11 +478,11 @@ class Paiement_stripe(models.Model):
(VALID, 'Payée et validée'), # envoyé sur serveur cashless
(CANCELED, 'Annulée'),
)
status = models.CharField(max_length=1, choices=STATUT_CHOICES, default=NON, verbose_name="Statut de la commande")
reservation = models.ForeignKey(Reservation, on_delete=models.PROTECT, blank=True, null=True,
related_name="paiements")
status = models.CharField(max_length=1, choices=STATUT_CHOICES, default=NON, verbose_name="Statut de la commande")
QRCODE, API_BILLETTERIE = 'Q', 'B'
SOURCE_CHOICES = (
@ -493,15 +517,16 @@ class LigneArticle(models.Model):
paiement_stripe = models.ForeignKey(Paiement_stripe, on_delete=models.PROTECT, blank=True, null=True)
CANCELED, UNPAID, PAID, VALID, = 'C', 'N', 'P', 'V'
CANCELED, CREATED, UNPAID, PAID, VALID, = 'C', 'O', 'U', 'P', 'V'
TYPE_CHOICES = [
(CANCELED, _('Annulée')),
(CREATED, _('Non envoyé en paiement')),
(UNPAID, _('Non payée')),
(PAID, _('Payée')),
(VALID, _('Validée par serveur cashless')),
]
status = models.CharField(max_length=3, choices=TYPE_CHOICES, default=UNPAID,
status = models.CharField(max_length=3, choices=TYPE_CHOICES, default=CREATED,
verbose_name=_("Status de ligne article"))
class Meta:

View File

@ -9,8 +9,9 @@ from ApiBillet.thread_mailer import ThreadMaileur
from BaseBillet.models import Reservation, LigneArticle, Ticket, Product, Configuration, Paiement_stripe
import logging
logger = logging.getLogger(__name__)
from TiBillet import settings
logger = logging.getLogger(__name__)
logger.info(f'import basebillet.signals')
@ -26,31 +27,58 @@ logger.info(f'import basebillet.signals')
########################################################################
######################## TRIGGER PAIEMENT STRIPE ########################
def set_ligne_article_paid(old_instance, new_instance):
# Type :
old_instance: Paiement_stripe
new_instance: Paiement_stripe
logger.info(f" TRIGGER PAIEMENT STRIPE set_ligne_article_paid {old_instance}.")
logger.info(f" On passe toutes les lignes d'article non validées en payées !")
lignes_article = new_instance.lignearticle_set.exclude(status=LigneArticle.VALID)
for ligne_article in lignes_article:
logger.info(f" {ligne_article.price} {ligne_article.status} to P")
ligne_article.status = LigneArticle.PAID
ligne_article.save()
# si ya une reservation, on la met aussi en payée :
# try :
if new_instance.reservation:
new_instance.reservation.status = Reservation.PAID
new_instance.reservation.save()
# except new_instance.reservation.RelatedObjectDoesNotExist:
def expire_paiement_stripe(old_instance, new_instance):
logger.info(f" TRIGGER PAIEMENT STRIPE expire_paiement_stripe {old_instance.status} to {new_instance.status}")
pass
def valide_stripe_paiement(old_instance, new_instance):
logger.info(f" TRIGGER PAIEMENT STRIPE valide_stripe_paiement {old_instance.status} to {new_instance.status}")
pass
######################## TRIGGER LIGNE ARTICLE ########################
# post_save ici nécéssaire pour mettre a jour le status du paiement stripe en validé
# si toutes les lignes articles sont VALID.
@receiver(post_save, sender=LigneArticle)
def set_paiement_and_reservation_valid(sender, instance: LigneArticle, **kwargs):
if instance.status == LigneArticle.VALID:
lignes_dans_paiement_stripe = instance.paiement_stripe.lignearticle_set.all()
# si toutes les lignes articles sont save en VALID.
# @receiver(post_save, sender=LigneArticle)
def set_paiement_and_reservation_valid(old_instance, new_instance):
lignes_dans_paiement_stripe = new_instance.paiement_stripe.lignearticle_set.all()
# TODO: calculer -1 ??
if len(lignes_dans_paiement_stripe) == len(lignes_dans_paiement_stripe.filter(status=LigneArticle.VALID)) :
# on passe le status du paiement stripe en VALID
logger.info(f" TRIGGER LIGNE ARTICLE set_paiement_and_reservation_valid {instance.price} "
f"paiement stripe {instance.paiement_stripe} {instance.paiement_stripe.status} à VALID")
instance.paiement_stripe.status = Paiement_stripe.VALID
instance.paiement_stripe.save()
logger.info(f" TRIGGER LIGNE ARTICLE set_paiement_and_reservation_valid {new_instance.price} "
f"paiement stripe {new_instance.paiement_stripe} {new_instance.paiement_stripe.status} à VALID")
new_instance.paiement_stripe.status = Paiement_stripe.VALID
new_instance.paiement_stripe.save()
def check_paid(old_instance, new_instance):
# Type :
old_instance: LigneArticle
new_instance: LigneArticle
logger.info(f" TRIGGER LIGNE ARTICLE check_paid {old_instance.price}")
if new_instance.price.product.categorie_article in \
[Product.RECHARGE_CASHLESS, Product.ADHESION]:
send_to_cashless(new_instance)
def send_to_cashless(instance):
@ -89,56 +117,40 @@ def send_to_cashless(instance):
f"erreur réponse serveur cashless {r.status_code} {r.text} pour paiement stripe {instance.price} uuid {instance.uuid}")
######################## TRIGGER PAIEMENT STRIPE ########################
def set_ligne_article_paid(old_instance, new_instance):
def check_paid(old_instance, new_instance):
# Type :
old_instance: Paiement_stripe
new_instance: Paiement_stripe
old_instance: LigneArticle
new_instance: LigneArticle
logger.info(f" TRIGGER LIGNE ARTICLE check_paid {old_instance.price}")
logger.info(f" TRIGGER PAIEMENT STRIPE set_ligne_article_paid {old_instance}.")
logger.info(f" On passe toutes les lignes d'article non validées en payées !")
lignes_article = new_instance.lignearticle_set.exclude(status=LigneArticle.VALID)
for ligne_article in lignes_article:
logger.info(f" {ligne_article.price} {ligne_article.status} to P]")
ligne_article.status = LigneArticle.PAID
ligne_article.save()
# si ya une reservation, on la met aussi en payée :
# try :
if new_instance.reservation:
new_instance.reservation.status = Reservation.PAID
new_instance.reservation.save()
# except new_instance.reservation.RelatedObjectDoesNotExist:
def expire_paiement_stripe(old_instance, new_instance):
logger.info(f" TRIGGER PAIEMENT STRIPE expire_paiement_stripe {old_instance.status} to {new_instance.status}")
pass
def valide_stripe_paiement(old_instance, new_instance):
logger.info(f" TRIGGER PAIEMENT STRIPE valide_stripe_paiement {old_instance.status} to {new_instance.status}")
pass
if new_instance.price.product.categorie_article in \
[Product.RECHARGE_CASHLESS, Product.ADHESION]:
send_to_cashless(new_instance)
######################## TRIGGER RESERVATION ########################
# @receiver(post_save, sender=Reservation)
# def send_billet_to_mail(sender, instance: Reservation, **kwargs):
def send_billet_to_mail(old_instance, new_instance):
# On active les tickets
urls_for_attached_files = {}
if new_instance.tickets:
for ticket in new_instance.tickets.filter(status=Ticket.NOT_ACTIV):
# On prend aussi ceux qui sont déja activé ( avec les Q() )
# pour pouvoir les envoyer par mail en cas de nouvelle demande
for ticket in new_instance.tickets.filter(Q(status=Ticket.NOT_ACTIV) | Q(status=Ticket.NOT_SCANNED)):
logger.info(f'trigger_reservation, activation des tickets {ticket} NOT_SCANNED')
ticket.status = Ticket.NOT_SCANNED
ticket.save()
# On vérifier qu'on a pas déja envoyé le mail
# on rajoute les urls du pdf pour le thread async
urls_for_attached_files[ticket.pdf_filename()] = ticket.pdf_url()
# import ipdb; ipdb.set_trace()
# On vérifie qu'on a pas déja envoyé le mail
if not new_instance.mail_send :
logger.info(f" TRIGGER RESERVATION send_billet_to_mail {old_instance.status} to {new_instance.status}")
logger.info(f" TRIGGER RESERVATION send_billet_to_mail {new_instance.status}")
new_instance : Reservation
config = Configuration.get_solo()
@ -152,13 +164,15 @@ def send_billet_to_mail(old_instance, new_instance):
'config': config,
'reservation': new_instance,
},
urls_for_attached_files = urls_for_attached_files,
)
# import ipdb; ipdb.set_trace()
mail.send_with_tread()
except Exception as e :
logger.error(f"{timezone.now()} Erreur envoie de mail pour reservation {new_instance} : {e}")
else :
logger.info(f" TRIGGER RESERVATION mail déja envoyé {new_instance} : {new_instance.mail_send} - status : {old_instance.status} to {new_instance.status}")
logger.info(f" TRIGGER RESERVATION mail déja envoyé {new_instance} : {new_instance.mail_send} - status : {new_instance.status}")
######################## MOTEUR TRIGGER ########################
@ -174,19 +188,6 @@ def error_regression(old_instance, new_instance):
# Exemple première ligne : Si status passe de PENDING vers PAID, alors on lance set_ligne_article_paid
TRANSITIONS = {
'RESERVATION': {
Reservation.UNPAID: {
Reservation.PAID: send_billet_to_mail,
},
Reservation.PAID: {
Reservation.VALID: send_billet_to_mail,
Reservation.PAID: send_billet_to_mail,
'_else_': error_regression,
},
Reservation.VALID: {
'_all_': error_regression,
}
},
'PAIEMENT_STRIPE': {
Paiement_stripe.PENDING: {
Paiement_stripe.PAID: set_ligne_article_paid,
@ -202,19 +203,34 @@ TRANSITIONS = {
'_all_': error_regression,
}
},
'LIGNEARTICLE': {
LigneArticle.UNPAID: {
LigneArticle.PAID: check_paid,
},
LigneArticle.PAID: {
LigneArticle.PAID: check_paid,
# LigneArticle.VALID: valide_stripe_paiement,
LigneArticle.VALID: set_paiement_and_reservation_valid,
'_else_': error_regression,
},
LigneArticle.VALID: {
'_all_': error_regression,
}
},
'RESERVATION': {
Reservation.UNPAID: {
Reservation.PAID: send_billet_to_mail,
},
Reservation.PAID: {
Reservation.VALID: send_billet_to_mail,
Reservation.PAID: send_billet_to_mail,
'_else_': error_regression,
},
Reservation.VALID: {
'_all_': error_regression,
}
},
}
@receiver(pre_save)

View File

@ -3,6 +3,6 @@ from django.urls import include, path, re_path
from BaseBillet import views as base_view
urlpatterns = [
path('event/<str:id>', base_view.event.as_view()),
path('ticket/<uuid:pk_uuid>', base_view.Ticket_html_view.as_view()),
path('', base_view.index.as_view(), name="index"),
]

View File

@ -1,24 +1,12 @@
from datetime import datetime
from django.contrib.auth import get_user_model
from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect
from django.shortcuts import render
# Create your views here.
from rest_framework import serializers, status
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import AllowAny
from rest_framework.views import APIView
from rest_framework.response import Response
from django.utils.translation import ugettext_lazy as _
from AuthBillet.email import ActivationEmail
from BaseBillet.models import Configuration, Event, Reservation, LigneArticle
from BaseBillet.validator import ReservationValidator
from django.db import connection
from AuthBillet.models import TibilletUser
from threading import Thread
from BaseBillet.models import Configuration, Event, Ticket
class index(APIView):
@ -44,128 +32,14 @@ class index(APIView):
return render(request, 'html5up-massively/index.html', context=context)
def creation_de_la_reservation(user: TibilletUser, event: Event, data):
reservation = Reservation.objects.create(
user_commande = user,
event= event,
)
if data.get('radio_generale'):
reservation.options.add(data.get('radio_generale')[0])
for option_checkbox in data.get('option_checkbox'):
reservation.options.add(option_checkbox)
# import ipdb; ipdb.set_trace()
#
for billet in data.get('billets'):
qty = data.get('billets')[billet]
LigneArticle.objects.create(
reservation = reservation,
billet = billet,
qty = qty,
)
for article in data.get('products'):
qty = data.get('products')[article]
LigneArticle.objects.create(
reservation = reservation,
article = article,
qty = qty,
)
return reservation
#Modèle MVC
class event(APIView):
class Ticket_html_view(APIView):
permission_classes = [AllowAny]
def get(self, request, id):
event = get_object_or_404(Event, pk=id)
configuration = Configuration.get_solo()
def get(self, request, pk_uuid):
ticket = get_object_or_404(Ticket, uuid=pk_uuid)
context = {
'configuration': configuration,
'event': event,
'ticket': ticket,
'config': Configuration.get_solo(),
}
return render(request, 'html5up-massively/event.html', context=context)
def post(self, request, id):
print(request.data)
reservation_validator = ReservationValidator(data=request.data)
if reservation_validator.is_valid():
print(reservation_validator.validated_data)
configuration = Configuration.get_solo()
context = {}
data_reservation = reservation_validator.validated_data
event = get_object_or_404(Event, pk=id)
# import ipdb; ipdb.set_trace()
# reste_place = configuration.jauge_max - event.reservations
# if data_reservation.get('qty') > reste_place:
# raise serializers.ValidationError(_(f"Il ne reste plus que {reste_place} places"))
if request.user.is_anonymous:
User: TibilletUser = get_user_model()
email = data_reservation.get('email')
user, created = User.objects.get_or_create(username=email, email=email)
if created:
user.is_active = False
user.first_name = data_reservation.get('nom')
user.last_name = data_reservation.get('prenom')
user.phone = data_reservation.get('phone')
user.client_source = connection.tenant
user.client_achat.add(connection.tenant)
user.save()
request.user = user
if not request.user.is_active or not request.user.password :
print(f"{request.user} not active or no password")
# on retire les commande non validé pour éviter les doublons
# et on le remet non actif si pas de mot de passe :
asupr = Reservation.objects.filter(user_commande=request.user, status=Reservation.MAIL_NON_VALIDEE, event=event)
asupr.delete()
request.user.is_active = False
request.user.save()
email_activation = ActivationEmail(request)
# email_activation.send(to=[email,])
thread_email = Thread(
target=email_activation.send,
kwargs={'to': [request.user.email, ],
'from_email': configuration.email}
)
thread_email.start()
context['message'] = "Merci pour votre réservation ! \n" \
"Il semble que vous n'avez pas encore de compte TiBillet. \n" \
"Merci de vérifier votre boite mail pour valider votre réservation. \n" \
"( N'oubliez pas de regarder dans les spams si vous ne voyez rien venir. ) \n" \
"Merci !"
elif request.user.is_active:
print("is is_active !")
reservation = creation_de_la_reservation(request.user, event, data_reservation)
context['configuration'] = configuration
context['event'] = event
return render(request, 'html5up-massively/event.html', context=context)
else:
print(f"validator.errors : {reservation_validator.errors}")
return Response(reservation_validator.errors, status=status.HTTP_400_BAD_REQUEST)
return render(request, 'ticket/ticket.html', context=context)

View File

@ -0,0 +1,171 @@
from datetime import datetime
from django.contrib.auth import get_user_model
from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect
# Create your views here.
from rest_framework import serializers, status
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import AllowAny
from rest_framework.views import APIView
from rest_framework.response import Response
from django.utils.translation import ugettext_lazy as _
from AuthBillet.email import ActivationEmail
from BaseBillet.models import Configuration, Event, Reservation, LigneArticle
from BaseBillet.validator import ReservationValidator
from django.db import connection
from AuthBillet.models import TibilletUser
from threading import Thread
class index(APIView):
permission_classes = [AllowAny]
def get(self, request):
configuration = Configuration.get_solo()
if not configuration.activer_billetterie :
return HttpResponseRedirect('https://www.tibillet.re')
events = Event.objects.filter(datetime__gt=datetime.now())
if len(events) > 0:
first_event = events[0]
else:
first_event = None
context = {
'configuration': configuration,
'events': events[1:],
'first_event': first_event,
}
return render(request, 'html5up-massively/index.html', context=context)
def creation_de_la_reservation(user: TibilletUser, event: Event, data):
reservation = Reservation.objects.create(
user_commande = user,
event= event,
)
if data.get('radio_generale'):
reservation.options.add(data.get('radio_generale')[0])
for option_checkbox in data.get('option_checkbox'):
reservation.options.add(option_checkbox)
# import ipdb; ipdb.set_trace()
#
for billet in data.get('billets'):
qty = data.get('billets')[billet]
LigneArticle.objects.create(
reservation = reservation,
billet = billet,
qty = qty,
)
for article in data.get('products'):
qty = data.get('products')[article]
LigneArticle.objects.create(
reservation = reservation,
article = article,
qty = qty,
)
return reservation
#Modèle MVC
class event(APIView):
permission_classes = [AllowAny]
def get(self, request, id):
event = get_object_or_404(Event, pk=id)
configuration = Configuration.get_solo()
context = {
'configuration': configuration,
'event': event,
}
return render(request, 'html5up-massively/event.html', context=context)
def post(self, request, id):
print(request.data)
reservation_validator = ReservationValidator(data=request.data)
if reservation_validator.is_valid():
print(reservation_validator.validated_data)
configuration = Configuration.get_solo()
context = {}
data_reservation = reservation_validator.validated_data
event = get_object_or_404(Event, pk=id)
# import ipdb; ipdb.set_trace()
# reste_place = configuration.jauge_max - event.reservations
# if data_reservation.get('qty') > reste_place:
# raise serializers.ValidationError(_(f"Il ne reste plus que {reste_place} places"))
if request.user.is_anonymous:
User: TibilletUser = get_user_model()
email = data_reservation.get('email')
user, created = User.objects.get_or_create(username=email, email=email)
if created:
user.is_active = False
user.first_name = data_reservation.get('nom')
user.last_name = data_reservation.get('prenom')
user.phone = data_reservation.get('phone')
user.client_source = connection.tenant
user.client_achat.add(connection.tenant)
user.save()
request.user = user
if not request.user.is_active or not request.user.password :
print(f"{request.user} not active or no password")
# on retire les commande non validé pour éviter les doublons
# et on le remet non actif si pas de mot de passe :
asupr = Reservation.objects.filter(user_commande=request.user, status=Reservation.MAIL_NON_VALIDEE, event=event)
asupr.delete()
request.user.is_active = False
request.user.save()
email_activation = ActivationEmail(request)
# email_activation.send(to=[email,])
thread_email = Thread(
target=email_activation.send,
kwargs={'to': [request.user.email, ],
'from_email': configuration.email}
)
thread_email.start()
context['message'] = "Merci pour votre réservation ! \n" \
"Il semble que vous n'avez pas encore de compte TiBillet. \n" \
"Merci de vérifier votre boite mail pour valider votre réservation. \n" \
"( N'oubliez pas de regarder dans les spams si vous ne voyez rien venir. ) \n" \
"Merci !"
elif request.user.is_active:
print("is is_active !")
reservation = creation_de_la_reservation(request.user, event, data_reservation)
context['configuration'] = configuration
context['event'] = event
return render(request, 'html5up-massively/event.html', context=context)
else:
print(f"validator.errors : {reservation_validator.errors}")
return Response(reservation_validator.errors, status=status.HTTP_400_BAD_REQUEST)

View File

@ -229,9 +229,13 @@ class retour_stripe(View):
return HttpResponseRedirect(f"/qr/{ligne_article.carte.uuid}#erreurpaiement")
elif paiement_stripe.source == Paiement_stripe.API_BILLETTERIE :
if paiement_stripe.status == Paiement_stripe.PAID :
return HttpResponse(
'Paiement okay, on lance les process de validation.')
if paiement_stripe.status == Paiement_stripe.VALID :
return HttpResponse(
'Coucou')
'Paiement validé !')
raise Http404(f'{paiement_stripe.status}')

View File

@ -224,11 +224,11 @@ LOGGING = {
'disable_existing_loggers': False,
'handlers': {
'console': {
'level': 'DEBUG',
'level': 'INFO',
'class': 'logging.StreamHandler',
},
'logfile': {
'level': 'DEBUG',
'level': 'INFO',
'class': 'logging.FileHandler',
'filename': f"{BASE_DIR}/www/Djangologfile",
},

View File

@ -1,8 +1,10 @@
from python:3.8-slim
from python:3.8-bullseye
## UPDATE
RUN apt-get update
RUN apt-get upgrade -y
RUN apt install -y python3-pip
RUN pip install pip --upgrade
## PYTHON
@ -61,17 +63,27 @@ RUN pip install django-stdimage
RUN pip install stripe
RUN apt-get install -y fonts-font-awesome
RUN apt-get install -y libffi-dev
RUN apt-get install -y libgdk-pixbuf2.0-0
RUN apt-get install -y libpango1.0-0
RUN apt-get install -y python-dev
# RUN apt-get install -y fonts-font-awesome
# RUN apt-get install -y libffi-dev
# RUN apt-get install -y libgdk-pixbuf2.0-0
# RUN apt-get install -y libpango1.0-0
# RUN apt-get install -y python-dev
# RUN apt-get install -y python-lxml
RUN apt-get install -y shared-mime-info
RUN apt-get install -y libcairo2
# RUN apt-get install -y shared-mime-info
# RUN apt-get install -y libcairo2
RUN apt install -y python3-cffi
RUN apt install -y python3-brotli
RUN apt install -y libpango-1.0-0
RUN apt install -y libpangoft2-1.0-0
RUN pip install django-weasyprint
RUN apt-get -y clean
RUN python --version
RUN django-admin --version
RUN pip freeze
RUN weasyprint --version
RUN pip freeze | grep weasyprint