Moteur de billetterie, envoie de mail, traitement en cours

This commit is contained in:
Jonas 12t 2021-11-09 14:27:57 +04:00
parent 047d66cbc3
commit 2d70329a2c
7 changed files with 81 additions and 23 deletions

View File

@ -227,6 +227,7 @@ class PaiementStripeAdmin(admin.ModelAdmin):
'total',
'order_date',
'status',
'traitement_en_cours',
'source',
)
ordering = ('-order_date',)

View File

@ -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

View File

@ -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")

View File

@ -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: {

View File

@ -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

View File

@ -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}')

View File

@ -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']
},
}