From 2d70329a2cc83c20a59a4c513f678c2c3cf8b52e Mon Sep 17 00:00:00 2001 From: Jonas 12t Date: Tue, 9 Nov 2021 14:27:57 +0400 Subject: [PATCH] Moteur de billetterie, envoie de mail, traitement en cours --- DjangoFiles/Administration/admin_tenant.py | 1 + DjangoFiles/ApiBillet/serializers.py | 3 +- DjangoFiles/BaseBillet/models.py | 6 +++- DjangoFiles/BaseBillet/signals.py | 24 +++++++++++-- DjangoFiles/BaseBillet/tasks.py | 23 ++++++++++--- DjangoFiles/PaiementStripe/views.py | 40 +++++++++++++++++----- DjangoFiles/TiBillet/settings.py | 7 ++-- 7 files changed, 81 insertions(+), 23 deletions(-) diff --git a/DjangoFiles/Administration/admin_tenant.py b/DjangoFiles/Administration/admin_tenant.py index f156252..4f09e22 100644 --- a/DjangoFiles/Administration/admin_tenant.py +++ b/DjangoFiles/Administration/admin_tenant.py @@ -227,6 +227,7 @@ class PaiementStripeAdmin(admin.ModelAdmin): 'total', 'order_date', 'status', + 'traitement_en_cours', 'source', ) ordering = ('-order_date',) diff --git a/DjangoFiles/ApiBillet/serializers.py b/DjangoFiles/ApiBillet/serializers.py index 788475e..2126ec1 100644 --- a/DjangoFiles/ApiBillet/serializers.py +++ b/DjangoFiles/ApiBillet/serializers.py @@ -141,7 +141,7 @@ class ReservationValidator(serializers.Serializer): def validate_email(self, value): User: TibilletUser = get_user_model() user_paiement, created = User.objects.get_or_create( - email=value) + email=value, username=value) if created: user_paiement: HumanUser @@ -150,6 +150,7 @@ class ReservationValidator(serializers.Serializer): user_paiement.is_active = False else: user_paiement.client_achat.add(connection.tenant) + user_paiement.save() self.user_commande = user_paiement return user_paiement.email diff --git a/DjangoFiles/BaseBillet/models.py b/DjangoFiles/BaseBillet/models.py index 71ad109..2bc0a95 100644 --- a/DjangoFiles/BaseBillet/models.py +++ b/DjangoFiles/BaseBillet/models.py @@ -326,12 +326,13 @@ class Reservation(models.Model): on_delete=models.PROTECT, related_name="reservation") - CANCELED, CREATED, UNPAID, PAID, VALID, = 'C', 'R', 'U', 'P', 'V' + CANCELED, CREATED, UNPAID, PAID, PAID_ERROR, VALID, = 'C', 'R', 'U', 'P', 'PE', 'V' TYPE_CHOICES = [ (CANCELED, _('Annulée')), (CREATED, _('Crée')), (UNPAID, _('Non payée')), (PAID, _('Payée')), + (PAID_ERROR, _('Payée mais mail non valide')), (VALID, _('Validée')), ] @@ -339,6 +340,7 @@ class Reservation(models.Model): verbose_name=_("Status de la réservation")) mail_send = models.BooleanField(default=False) + mail_error = models.BooleanField(default=False) # paiement = models.OneToOneField(Paiement_stripe, on_delete=models.PROTECT, blank=True, null=True, # related_name='reservation') @@ -483,6 +485,8 @@ class Paiement_stripe(models.Model): ) status = models.CharField(max_length=1, choices=STATUT_CHOICES, default=NON, verbose_name="Statut de la commande") + traitement_en_cours = models.BooleanField(default=False) + reservation = models.ForeignKey(Reservation, on_delete=models.PROTECT, blank=True, null=True, related_name="paiements") diff --git a/DjangoFiles/BaseBillet/signals.py b/DjangoFiles/BaseBillet/signals.py index 33cc20e..677a873 100644 --- a/DjangoFiles/BaseBillet/signals.py +++ b/DjangoFiles/BaseBillet/signals.py @@ -52,8 +52,6 @@ def expire_paiement_stripe(old_instance, new_instance): 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 ######################## @@ -69,6 +67,7 @@ def set_paiement_and_reservation_valid(old_instance, new_instance): 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.traitement_en_cours = False new_instance.paiement_stripe.save() @@ -148,8 +147,23 @@ def send_billet_to_mail(old_instance, new_instance): # https://github.com/psf/requests/issues/5832 else : logger.info(f" TRIGGER RESERVATION mail déja envoyé {new_instance} : {new_instance.mail_send} - status : {new_instance.status}") + set_paiement_valid(old_instance, new_instance) +def set_paiement_valid(old_instance, new_instance): + new_instance: Reservation + if new_instance.mail_send : + logger.info(f" TRIGGER RESERVATION set_paiement_valid Mail envoyé {new_instance.mail_send}, on valide les paiement payés") + for paiement in new_instance.paiements.filter(status=Paiement_stripe.PAID): + paiement.status = Paiement_stripe.VALID + paiement.traitement_en_cours = False + paiement.save() + +def error_in_mail(old_instance, new_instance): + logger.info(f" TRIGGER RESERVATION error_in_mail") + new_instance.paiements.all().update(traitement_en_cours = False) + # TODO: Prévenir l'admin q'un billet a été acheté, mais pas envoyé + ######################## MOTEUR TRIGGER ######################## def error_regression(old_instance, new_instance): @@ -169,6 +183,9 @@ TRANSITIONS = { Paiement_stripe.EXPIRE: expire_paiement_stripe, Paiement_stripe.CANCELED: expire_paiement_stripe, }, + Paiement_stripe.EXPIRE: { + Paiement_stripe.PAID: set_ligne_article_paid, + }, Paiement_stripe.PAID: { Paiement_stripe.PAID: set_ligne_article_paid, Paiement_stripe.VALID: valide_stripe_paiement, @@ -198,8 +215,9 @@ TRANSITIONS = { Reservation.PAID: send_billet_to_mail, }, Reservation.PAID: { - Reservation.VALID: send_billet_to_mail, + Reservation.PAID_ERROR: error_in_mail, Reservation.PAID: send_billet_to_mail, + Reservation.VALID: set_paiement_valid, '_else_': error_regression, }, Reservation.VALID: { diff --git a/DjangoFiles/BaseBillet/tasks.py b/DjangoFiles/BaseBillet/tasks.py index fd17416..45ee0b6 100644 --- a/DjangoFiles/BaseBillet/tasks.py +++ b/DjangoFiles/BaseBillet/tasks.py @@ -1,5 +1,6 @@ # import base64 import os +import smtplib from io import BytesIO import segno import barcode @@ -169,14 +170,26 @@ def ticket_celery_mailer(reservation_uuid: str): }, attached_files=attached_files, ) - mail.send() + try : + mail.send() + logger.info(f"mail.sended : {mail.sended}") - logger.info(f"mail.sended : {mail.sended}") - if mail.sended : - reservation.mail_send = True - reservation.status = Reservation.VALID + if mail.sended : + reservation.mail_send = True + reservation.status = Reservation.VALID + reservation.save() + + except smtplib.SMTPRecipientsRefused as e: + + logger.error(f"ERROR {timezone.now()} Erreur envoie de mail pour reservation {reservation} : {e}") + logger.error(f"mail.sended : {mail.sended}") + reservation.mail_send = False + reservation.mail_error = True + + reservation.status = Reservation.PAID_ERROR reservation.save() + except Exception as e: logger.error(f"{timezone.now()} Erreur envoie de mail pour reservation {reservation} : {e}") raise Exception diff --git a/DjangoFiles/PaiementStripe/views.py b/DjangoFiles/PaiementStripe/views.py index bd3de7d..6900a73 100644 --- a/DjangoFiles/PaiementStripe/views.py +++ b/DjangoFiles/PaiementStripe/views.py @@ -163,6 +163,19 @@ class retour_stripe(View): def get(self, request, uuid_stripe): paiement_stripe = get_object_or_404(Paiement_stripe, uuid=uuid_stripe) + if paiement_stripe.traitement_en_cours : + return HttpResponse( + 'traitement_en_cours') + + if paiement_stripe.reservation.status == Reservation.PAID_ERROR : + return HttpResponse( + "Erreur dans l'envoie du mail. Merci de vérifier l'adresse") + + if paiement_stripe.status == Paiement_stripe.VALID or paiement_stripe.reservation.status == Reservation.VALID : + return HttpResponse( + 'Paiement déja validé !') + + configuration = Configuration.get_solo() if configuration.stripe_mode_test: stripe.api_key = configuration.stripe_test_api_key @@ -170,7 +183,8 @@ class retour_stripe(View): stripe.api_key = configuration.stripe_api_key print(paiement_stripe.status) - if paiement_stripe.status != Paiement_stripe.VALID: + if paiement_stripe.status != Paiement_stripe.VALID and \ + paiement_stripe.reservation.status != Reservation.VALID : checkout_session = stripe.checkout.Session.retrieve(paiement_stripe.id_stripe) @@ -179,14 +193,12 @@ class retour_stripe(View): if checkout_session.payment_status == "unpaid": paiement_stripe.status = Paiement_stripe.PENDING - if checkout_session.expires_at > datetime.now().timestamp(): + # import ipdb; ipdb.set_trace() + if datetime.now().timestamp() > checkout_session.expires_at : paiement_stripe.status = Paiement_stripe.EXPIRE paiement_stripe.save() elif checkout_session.payment_status == "paid": - paiement_stripe.status = Paiement_stripe.PAID - logger.info(f"retour_stripe - checkout_session.payment_status : {checkout_session.payment_status}") - # le .save() lance le process pre_save BaseBillet.models.send_to_cashless # qui modifie le status de chaque ligne @@ -194,8 +206,14 @@ class retour_stripe(View): # si validé par le serveur cashless, alors la ligne sera VALID. # Si toute les lignes sont VALID, le paiement_stripe sera aussi VALID # grace au post_save BaseBillet.models.check_status_stripe + + logger.info(f"retour_stripe - checkout_session.payment_status : {checkout_session.payment_status}") + paiement_stripe.status = Paiement_stripe.PAID paiement_stripe.last_action = timezone.now() + paiement_stripe.traitement_en_cours = True paiement_stripe.save() + logger.info(f"retour_stripe - paiement_stripe.save() {paiement_stripe.status}") + else: paiement_stripe.status = Paiement_stripe.CANCELED @@ -203,8 +221,10 @@ class retour_stripe(View): else: raise Http404 + # on vérifie que le status n'ai pas changé paiement_stripe.refresh_from_db() + # import ipdb; ipdb.set_trace() # si c'est depuis le qrcode, on renvoie vers la vue mobile : if paiement_stripe.source == Paiement_stripe.QRCODE : @@ -229,13 +249,15 @@ 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 : + if paiement_stripe.status == Paiement_stripe.VALID or paiement_stripe.reservation.status == Reservation.VALID : + return HttpResponse( + 'Paiement déja validé !') + + elif paiement_stripe.status == Paiement_stripe.PAID : + logger.info(f"Paiement_stripe.API_BILLETTERIE : {paiement_stripe.status}") return HttpResponse( 'Paiement okay, on lance les process de validation.') - if paiement_stripe.status == Paiement_stripe.VALID : - return HttpResponse( - 'Paiement validé !') raise Http404(f'{paiement_stripe.status}') diff --git a/DjangoFiles/TiBillet/settings.py b/DjangoFiles/TiBillet/settings.py index 683ed2e..5422dd4 100644 --- a/DjangoFiles/TiBillet/settings.py +++ b/DjangoFiles/TiBillet/settings.py @@ -223,7 +223,6 @@ CELERY_RESULT_BACKEND=os.environ.get('CELERY_BACKEND', 'redis://redis:6379/0') # Jet Menu # -------------------------------------/ - JET_SIDE_MENU_COMPACT = True JET_CHANGE_FORM_SIBLING_LINKS = False @@ -238,11 +237,11 @@ LOGGING = { }, 'handlers': { 'console': { - 'level': 'DEBUG', + 'level': 'INFO', 'class': 'logging.StreamHandler', }, 'logfile': { - 'level': 'DEBUG', + 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', 'filename': f"{BASE_DIR}/www/Djangologfile", 'formatter': 'simple', @@ -250,7 +249,7 @@ LOGGING = { }, }, 'root': { - 'level': 'DEBUG', + 'level': 'INFO', 'handlers': ['console', 'logfile'] }, } \ No newline at end of file