signal return after stripe paiement ok
This commit is contained in:
parent
a6eff19fa2
commit
d1a22548cd
|
|
@ -5,11 +5,13 @@ import json
|
||||||
from django.utils.translation import gettext, gettext_lazy as _
|
from django.utils.translation import gettext, gettext_lazy as _
|
||||||
from rest_framework.generics import get_object_or_404
|
from rest_framework.generics import get_object_or_404
|
||||||
|
|
||||||
import PaiementStripe
|
|
||||||
from AuthBillet.models import TibilletUser, HumanUser
|
from AuthBillet.models import TibilletUser, HumanUser
|
||||||
from BaseBillet.models import Event, Price, Product, Reservation, Configuration, LigneArticle, Ticket, Paiement_stripe
|
from BaseBillet.models import Event, Price, Product, Reservation, Configuration, LigneArticle, Ticket, Paiement_stripe
|
||||||
from PaiementStripe.views import creation_paiement_stripe
|
from PaiementStripe.views import creation_paiement_stripe
|
||||||
|
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ProductSerializer(serializers.ModelSerializer):
|
class ProductSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -265,9 +267,15 @@ class ReservationValidator(serializers.Serializer):
|
||||||
)
|
)
|
||||||
|
|
||||||
if new_paiement_stripe.is_valid():
|
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.status = Reservation.UNPAID
|
||||||
reservation.save()
|
reservation.save()
|
||||||
|
|
||||||
print(new_paiement_stripe.checkout_session.stripe_id)
|
print(new_paiement_stripe.checkout_session.stripe_id)
|
||||||
# return new_paiement_stripe.redirect_to_stripe()
|
# return new_paiement_stripe.redirect_to_stripe()
|
||||||
self.checkout_session = new_paiement_stripe.checkout_session
|
self.checkout_session = new_paiement_stripe.checkout_session
|
||||||
|
|
@ -278,6 +286,7 @@ class ReservationValidator(serializers.Serializer):
|
||||||
|
|
||||||
def to_representation(self, instance):
|
def to_representation(self, instance):
|
||||||
representation = super().to_representation(instance)
|
representation = super().to_representation(instance)
|
||||||
|
logger.info(f"{self.checkout_session.url}")
|
||||||
representation['checkout_url'] = self.checkout_session.url
|
representation['checkout_url'] = self.checkout_session.url
|
||||||
# import ipdb;ipdb.set_trace()
|
# import ipdb;ipdb.set_trace()
|
||||||
return representation
|
return representation
|
||||||
|
|
|
||||||
|
|
@ -440,41 +440,14 @@
|
||||||
<strong>Grand merci pour votre reservation !</strong>
|
<strong>Grand merci pour votre reservation !</strong>
|
||||||
<br><br>
|
<br><br>
|
||||||
{% if reservation.tickets %}
|
{% if reservation.tickets %}
|
||||||
Vous trouverez vos tickets en pièce jointe.
|
Vous trouverez vos billets en pièce jointe.
|
||||||
{% else %}
|
{% else %}
|
||||||
Aucun ticket pour un concert ? Etrange etrange
|
Aucun billets pour un concert ? Etrange etrange
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- END BODY COPY -->
|
<!-- 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>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
<body>
|
<body>
|
||||||
<section id="informations">
|
<section id="informations">
|
||||||
<h1 id="name">{{ ticket.first_name }} {{ ticket.last_name }}</h1>
|
<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>
|
<dl>
|
||||||
<dt>Flight</dt>
|
<dt>Flight</dt>
|
||||||
<dd>DL31</dd>
|
<dd>DL31</dd>
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
<section id="ticket">
|
<section id="ticket">
|
||||||
<p>1257797706706</p>
|
<p>1257797706706</p>
|
||||||
<h2>Théodore Marcelin</h2>
|
<h2>{{ ticket.first_name }} {{ ticket.last_name }}</h2>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Flight</dt>
|
<dt>Flight</dt>
|
||||||
<dd>DL31</dd>
|
<dd>DL31</dd>
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
<dd>4</dd>
|
<dd>4</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<ul>
|
<ul>
|
||||||
<li>CDG ✈ LFLL</li>
|
<li>{{ ticket.reservation.event.name }}</li>
|
||||||
<li>5:10pm</li>
|
<li>5:10pm</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ from weasyprint import HTML
|
||||||
from BaseBillet.models import Configuration, Reservation, Ticket
|
from BaseBillet.models import Configuration, Reservation, Ticket
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from ApiBillet.thread_mailer import ThreadMaileur
|
from ApiBillet.thread_mailer import ThreadMaileur
|
||||||
|
|
@ -23,34 +23,28 @@ mail.send_with_tread()
|
||||||
|
|
||||||
class ThreadMaileur():
|
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.title = title
|
||||||
self.email = email
|
self.email = email
|
||||||
self.text = text
|
self.text = text
|
||||||
self.html = html
|
self.html = html
|
||||||
self.config = Configuration.get_solo()
|
self.config = Configuration.get_solo()
|
||||||
self.context = None
|
self.context = context
|
||||||
if template and context :
|
self.urls_for_attached_files = urls_for_attached_files
|
||||||
|
|
||||||
|
if template and context:
|
||||||
self.html = render_to_string(template, context=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):
|
def config_valid(self):
|
||||||
EMAIL_HOST = os.environ.get('EMAIL_HOST')
|
EMAIL_HOST = os.environ.get('EMAIL_HOST')
|
||||||
|
|
@ -58,58 +52,42 @@ class ThreadMaileur():
|
||||||
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
|
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
|
||||||
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
|
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
|
||||||
|
|
||||||
if EMAIL_HOST and EMAIL_PORT and EMAIL_HOST_USER and EMAIL_HOST_PASSWORD and self.config.email :
|
if EMAIL_HOST and EMAIL_PORT and EMAIL_HOST_USER and EMAIL_HOST_PASSWORD and self.config.email:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def send(self):
|
def send(self):
|
||||||
if self.html and self.config_valid() :
|
if self.html and self.config_valid():
|
||||||
logger.info(f' send_mail')
|
logger.info(f' send_mail')
|
||||||
mail = EmailMultiAlternatives(
|
mail = EmailMultiAlternatives(
|
||||||
self.title,
|
self.title,
|
||||||
self.text,
|
self.text,
|
||||||
self.config.email,
|
self.config.email,
|
||||||
[self.email,],
|
[self.email, ],
|
||||||
)
|
)
|
||||||
mail.attach_alternative(self.html, "text/html")
|
mail.attach_alternative(self.html, "text/html")
|
||||||
|
|
||||||
attached_file = []
|
for filename, url in self.urls_for_attached_files.items():
|
||||||
for ticket in self.tickets_uuid :
|
response = requests.get(url)
|
||||||
|
|
||||||
response = requests.get(f"{self.url}{ticket}")
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
attached_file.append(response.content)
|
mail.attach(filename, response.content, 'application/pdf')
|
||||||
|
|
||||||
# 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_return = mail.send(fail_silently=False)
|
mail_return = mail.send(fail_silently=False)
|
||||||
if mail_return == 1 :
|
|
||||||
|
if mail_return == 1:
|
||||||
logger.info(f' mail envoyé : {mail_return} - {self.email}')
|
logger.info(f' mail envoyé : {mail_return} - {self.email}')
|
||||||
else :
|
else:
|
||||||
logger.error(f' mail non envoyé : {mail_return} - {self.email}')
|
logger.error(f' mail non envoyé : {mail_return} - {self.email}')
|
||||||
return mail
|
return mail
|
||||||
else :
|
else:
|
||||||
logger.error(f'Pas de contenu HTML ou de configuration email valide')
|
logger.error(f'Pas de contenu HTML ou de configuration email valide')
|
||||||
raise ValueError('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):
|
def send_with_tread(self):
|
||||||
|
|
||||||
# self.send()
|
# self.send()
|
||||||
logger.info(f'{timezone.now()} on lance le thread email {self.email}')
|
logger.info(f'{timezone.now()} on lance le thread email {self.email}')
|
||||||
thread_email = threading.Thread(target=self.send)
|
thread_email = threading.Thread(target=self.send)
|
||||||
thread_email.start()
|
thread_email.start()
|
||||||
logger.info(f'{timezone.now()} Thread email lancé')
|
logger.info(f'{timezone.now()} Thread email lancé')
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ router.register(r'reservations', api_view.ReservationViewset, basename='reservat
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include(router.urls)),
|
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'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
@ -150,11 +150,10 @@ class TicketPdf(WeasyTemplateView):
|
||||||
kwargs['ticket'] = ticket
|
kwargs['ticket'] = ticket
|
||||||
kwargs['config'] = self.config
|
kwargs['config'] = self.config
|
||||||
|
|
||||||
self.nom_prenom = f"{ticket.first_name.upper()}_{ticket.last_name.capitalize()}"
|
self.pdf_filename = ticket.pdf_filename()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def get_pdf_filename(self, **kwargs):
|
def get_pdf_filename(self, **kwargs):
|
||||||
nom_prenom = self.nom_prenom
|
return self.pdf_filename
|
||||||
return f"Ticket_{nom_prenom}.pdf"
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ from django.db.models.aggregates import Sum
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.db.models.signals import post_save, pre_save
|
from django.db.models.signals import post_save, pre_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.contrib.postgres.fields import JSONField
|
from django.contrib.postgres.fields import JSONField
|
||||||
from solo.models import SingletonModel
|
from solo.models import SingletonModel
|
||||||
|
|
@ -325,7 +326,7 @@ class Reservation(models.Model):
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name="reservation")
|
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 = [
|
TYPE_CHOICES = [
|
||||||
(CANCELED, _('Annulée')),
|
(CANCELED, _('Annulée')),
|
||||||
(CREATED, _('Crée')),
|
(CREATED, _('Crée')),
|
||||||
|
|
@ -356,7 +357,7 @@ class Reservation(models.Model):
|
||||||
|
|
||||||
def articles_paid(self):
|
def articles_paid(self):
|
||||||
articles_paid = []
|
articles_paid = []
|
||||||
for paiement in self.paiements_paid():
|
for paiement in self.paiements.all():
|
||||||
for ligne in paiement.lignearticle_set.filter(
|
for ligne in paiement.lignearticle_set.filter(
|
||||||
Q(status=LigneArticle.PAID) | Q(status=LigneArticle.VALID)
|
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")
|
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 = [
|
SCAN_CHOICES = [
|
||||||
|
(CREATED, _('Crée')),
|
||||||
(NOT_ACTIV, _('Non actif')),
|
(NOT_ACTIV, _('Non actif')),
|
||||||
(NOT_SCANNED, _('Non scanné')),
|
(NOT_SCANNED, _('Non scanné')),
|
||||||
(SCANNED, _('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"))
|
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):
|
def event(self):
|
||||||
return self.reservation.event
|
return self.reservation.event
|
||||||
|
|
||||||
|
|
@ -454,11 +478,11 @@ class Paiement_stripe(models.Model):
|
||||||
(VALID, 'Payée et validée'), # envoyé sur serveur cashless
|
(VALID, 'Payée et validée'), # envoyé sur serveur cashless
|
||||||
(CANCELED, 'Annulée'),
|
(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,
|
reservation = models.ForeignKey(Reservation, on_delete=models.PROTECT, blank=True, null=True,
|
||||||
related_name="paiements")
|
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'
|
QRCODE, API_BILLETTERIE = 'Q', 'B'
|
||||||
SOURCE_CHOICES = (
|
SOURCE_CHOICES = (
|
||||||
|
|
@ -493,15 +517,16 @@ class LigneArticle(models.Model):
|
||||||
|
|
||||||
paiement_stripe = models.ForeignKey(Paiement_stripe, on_delete=models.PROTECT, blank=True, null=True)
|
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 = [
|
TYPE_CHOICES = [
|
||||||
(CANCELED, _('Annulée')),
|
(CANCELED, _('Annulée')),
|
||||||
|
(CREATED, _('Non envoyé en paiement')),
|
||||||
(UNPAID, _('Non payée')),
|
(UNPAID, _('Non payée')),
|
||||||
(PAID, _('Payée')),
|
(PAID, _('Payée')),
|
||||||
(VALID, _('Validée par serveur cashless')),
|
(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"))
|
verbose_name=_("Status de ligne article"))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,9 @@ from ApiBillet.thread_mailer import ThreadMaileur
|
||||||
from BaseBillet.models import Reservation, LigneArticle, Ticket, Product, Configuration, Paiement_stripe
|
from BaseBillet.models import Reservation, LigneArticle, Ticket, Product, Configuration, Paiement_stripe
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
from TiBillet import settings
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
logger.info(f'import basebillet.signals')
|
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 ########################
|
######################## TRIGGER LIGNE ARTICLE ########################
|
||||||
|
|
||||||
# post_save ici nécéssaire pour mettre a jour le status du paiement stripe en validé
|
# post_save ici nécéssaire pour mettre a jour le status du paiement stripe en validé
|
||||||
# si toutes les lignes articles sont VALID.
|
# si toutes les lignes articles sont save en VALID.
|
||||||
@receiver(post_save, sender=LigneArticle)
|
# @receiver(post_save, sender=LigneArticle)
|
||||||
def set_paiement_and_reservation_valid(sender, instance: LigneArticle, **kwargs):
|
|
||||||
if instance.status == LigneArticle.VALID:
|
def set_paiement_and_reservation_valid(old_instance, new_instance):
|
||||||
lignes_dans_paiement_stripe = instance.paiement_stripe.lignearticle_set.all()
|
lignes_dans_paiement_stripe = new_instance.paiement_stripe.lignearticle_set.all()
|
||||||
if len(lignes_dans_paiement_stripe) == len(lignes_dans_paiement_stripe.filter(status=LigneArticle.VALID)):
|
# TODO: calculer -1 ??
|
||||||
# on passe le status du paiement stripe en VALID
|
if len(lignes_dans_paiement_stripe) == len(lignes_dans_paiement_stripe.filter(status=LigneArticle.VALID)) :
|
||||||
logger.info(f" TRIGGER LIGNE ARTICLE set_paiement_and_reservation_valid {instance.price} "
|
# on passe le status du paiement stripe en VALID
|
||||||
f"paiement stripe {instance.paiement_stripe} {instance.paiement_stripe.status} à VALID")
|
logger.info(f" TRIGGER LIGNE ARTICLE set_paiement_and_reservation_valid {new_instance.price} "
|
||||||
instance.paiement_stripe.status = Paiement_stripe.VALID
|
f"paiement stripe {new_instance.paiement_stripe} {new_instance.paiement_stripe.status} à VALID")
|
||||||
instance.paiement_stripe.save()
|
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):
|
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}")
|
f"erreur réponse serveur cashless {r.status_code} {r.text} pour paiement stripe {instance.price} uuid {instance.uuid}")
|
||||||
|
|
||||||
|
|
||||||
######################## TRIGGER PAIEMENT STRIPE ########################
|
def check_paid(old_instance, new_instance):
|
||||||
|
|
||||||
|
|
||||||
def set_ligne_article_paid(old_instance, new_instance):
|
|
||||||
# Type :
|
# Type :
|
||||||
old_instance: Paiement_stripe
|
old_instance: LigneArticle
|
||||||
new_instance: Paiement_stripe
|
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}.")
|
if new_instance.price.product.categorie_article in \
|
||||||
logger.info(f" On passe toutes les lignes d'article non validées en payées !")
|
[Product.RECHARGE_CASHLESS, Product.ADHESION]:
|
||||||
|
send_to_cashless(new_instance)
|
||||||
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 RESERVATION ########################
|
######################## 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):
|
def send_billet_to_mail(old_instance, new_instance):
|
||||||
# On active les tickets
|
# On active les tickets
|
||||||
|
urls_for_attached_files = {}
|
||||||
if new_instance.tickets:
|
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')
|
logger.info(f'trigger_reservation, activation des tickets {ticket} NOT_SCANNED')
|
||||||
ticket.status = Ticket.NOT_SCANNED
|
ticket.status = Ticket.NOT_SCANNED
|
||||||
ticket.save()
|
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 :
|
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
|
new_instance : Reservation
|
||||||
config = Configuration.get_solo()
|
config = Configuration.get_solo()
|
||||||
|
|
||||||
|
|
@ -152,13 +164,15 @@ def send_billet_to_mail(old_instance, new_instance):
|
||||||
'config': config,
|
'config': config,
|
||||||
'reservation': new_instance,
|
'reservation': new_instance,
|
||||||
},
|
},
|
||||||
|
urls_for_attached_files = urls_for_attached_files,
|
||||||
)
|
)
|
||||||
# import ipdb; ipdb.set_trace()
|
# import ipdb; ipdb.set_trace()
|
||||||
mail.send_with_tread()
|
mail.send_with_tread()
|
||||||
except Exception as e :
|
except Exception as e :
|
||||||
logger.error(f"{timezone.now()} Erreur envoie de mail pour reservation {new_instance} : {e}")
|
logger.error(f"{timezone.now()} Erreur envoie de mail pour reservation {new_instance} : {e}")
|
||||||
|
|
||||||
else :
|
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 ########################
|
######################## 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
|
# Exemple première ligne : Si status passe de PENDING vers PAID, alors on lance set_ligne_article_paid
|
||||||
|
|
||||||
TRANSITIONS = {
|
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': {
|
||||||
Paiement_stripe.PENDING: {
|
Paiement_stripe.PENDING: {
|
||||||
Paiement_stripe.PAID: set_ligne_article_paid,
|
Paiement_stripe.PAID: set_ligne_article_paid,
|
||||||
|
|
@ -202,19 +203,34 @@ TRANSITIONS = {
|
||||||
'_all_': error_regression,
|
'_all_': error_regression,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'LIGNEARTICLE': {
|
'LIGNEARTICLE': {
|
||||||
LigneArticle.UNPAID: {
|
LigneArticle.UNPAID: {
|
||||||
LigneArticle.PAID: check_paid,
|
LigneArticle.PAID: check_paid,
|
||||||
},
|
},
|
||||||
LigneArticle.PAID: {
|
LigneArticle.PAID: {
|
||||||
LigneArticle.PAID: check_paid,
|
LigneArticle.PAID: check_paid,
|
||||||
# LigneArticle.VALID: valide_stripe_paiement,
|
LigneArticle.VALID: set_paiement_and_reservation_valid,
|
||||||
'_else_': error_regression,
|
'_else_': error_regression,
|
||||||
},
|
},
|
||||||
LigneArticle.VALID: {
|
LigneArticle.VALID: {
|
||||||
'_all_': error_regression,
|
'_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)
|
@receiver(pre_save)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,6 @@ from django.urls import include, path, re_path
|
||||||
from BaseBillet import views as base_view
|
from BaseBillet import views as base_view
|
||||||
|
|
||||||
urlpatterns = [
|
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"),
|
path('', base_view.index.as_view(), name="index"),
|
||||||
]
|
]
|
||||||
|
|
@ -1,24 +1,12 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
from django.http import HttpResponseRedirect
|
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.generics import get_object_or_404
|
||||||
from rest_framework.permissions import AllowAny
|
from rest_framework.permissions import AllowAny
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.response import Response
|
from BaseBillet.models import Configuration, Event, Ticket
|
||||||
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):
|
class index(APIView):
|
||||||
|
|
@ -44,128 +32,14 @@ class index(APIView):
|
||||||
return render(request, 'html5up-massively/index.html', context=context)
|
return render(request, 'html5up-massively/index.html', context=context)
|
||||||
|
|
||||||
|
|
||||||
def creation_de_la_reservation(user: TibilletUser, event: Event, data):
|
class Ticket_html_view(APIView):
|
||||||
|
|
||||||
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]
|
permission_classes = [AllowAny]
|
||||||
|
|
||||||
|
def get(self, request, pk_uuid):
|
||||||
|
ticket = get_object_or_404(Ticket, uuid=pk_uuid)
|
||||||
def get(self, request, id):
|
|
||||||
event = get_object_or_404(Event, pk=id)
|
|
||||||
configuration = Configuration.get_solo()
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'configuration': configuration,
|
'ticket': ticket,
|
||||||
'event': event,
|
'config': Configuration.get_solo(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, 'html5up-massively/event.html', context=context)
|
return render(request, 'ticket/ticket.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)
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -229,9 +229,13 @@ class retour_stripe(View):
|
||||||
return HttpResponseRedirect(f"/qr/{ligne_article.carte.uuid}#erreurpaiement")
|
return HttpResponseRedirect(f"/qr/{ligne_article.carte.uuid}#erreurpaiement")
|
||||||
|
|
||||||
elif paiement_stripe.source == Paiement_stripe.API_BILLETTERIE :
|
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 :
|
if paiement_stripe.status == Paiement_stripe.VALID :
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
'Coucou')
|
'Paiement validé !')
|
||||||
|
|
||||||
|
|
||||||
raise Http404(f'{paiement_stripe.status}')
|
raise Http404(f'{paiement_stripe.status}')
|
||||||
|
|
|
||||||
|
|
@ -224,11 +224,11 @@ LOGGING = {
|
||||||
'disable_existing_loggers': False,
|
'disable_existing_loggers': False,
|
||||||
'handlers': {
|
'handlers': {
|
||||||
'console': {
|
'console': {
|
||||||
'level': 'DEBUG',
|
'level': 'INFO',
|
||||||
'class': 'logging.StreamHandler',
|
'class': 'logging.StreamHandler',
|
||||||
},
|
},
|
||||||
'logfile': {
|
'logfile': {
|
||||||
'level': 'DEBUG',
|
'level': 'INFO',
|
||||||
'class': 'logging.FileHandler',
|
'class': 'logging.FileHandler',
|
||||||
'filename': f"{BASE_DIR}/www/Djangologfile",
|
'filename': f"{BASE_DIR}/www/Djangologfile",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
from python:3.8-slim
|
from python:3.8-bullseye
|
||||||
|
|
||||||
## UPDATE
|
## UPDATE
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get upgrade -y
|
RUN apt-get upgrade -y
|
||||||
|
RUN apt install -y python3-pip
|
||||||
|
|
||||||
RUN pip install pip --upgrade
|
RUN pip install pip --upgrade
|
||||||
|
|
||||||
## PYTHON
|
## PYTHON
|
||||||
|
|
@ -61,17 +63,27 @@ RUN pip install django-stdimage
|
||||||
RUN pip install stripe
|
RUN pip install stripe
|
||||||
|
|
||||||
|
|
||||||
RUN apt-get install -y fonts-font-awesome
|
# RUN apt-get install -y fonts-font-awesome
|
||||||
RUN apt-get install -y libffi-dev
|
# RUN apt-get install -y libffi-dev
|
||||||
RUN apt-get install -y libgdk-pixbuf2.0-0
|
# RUN apt-get install -y libgdk-pixbuf2.0-0
|
||||||
RUN apt-get install -y libpango1.0-0
|
# RUN apt-get install -y libpango1.0-0
|
||||||
RUN apt-get install -y python-dev
|
# RUN apt-get install -y python-dev
|
||||||
# RUN apt-get install -y python-lxml
|
# RUN apt-get install -y python-lxml
|
||||||
RUN apt-get install -y shared-mime-info
|
# RUN apt-get install -y shared-mime-info
|
||||||
RUN apt-get install -y libcairo2
|
# 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 pip install django-weasyprint
|
||||||
|
|
||||||
RUN apt-get -y clean
|
RUN apt-get -y clean
|
||||||
|
|
||||||
RUN python --version
|
RUN python --version
|
||||||
RUN django-admin --version
|
RUN django-admin --version
|
||||||
|
RUN pip freeze
|
||||||
|
|
||||||
|
RUN weasyprint --version
|
||||||
|
RUN pip freeze | grep weasyprint
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue