Moteur de billetterie, envoie de mail, traitement en cours
This commit is contained in:
parent
047d66cbc3
commit
2d70329a2c
|
|
@ -227,6 +227,7 @@ class PaiementStripeAdmin(admin.ModelAdmin):
|
||||||
'total',
|
'total',
|
||||||
'order_date',
|
'order_date',
|
||||||
'status',
|
'status',
|
||||||
|
'traitement_en_cours',
|
||||||
'source',
|
'source',
|
||||||
)
|
)
|
||||||
ordering = ('-order_date',)
|
ordering = ('-order_date',)
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ class ReservationValidator(serializers.Serializer):
|
||||||
def validate_email(self, value):
|
def validate_email(self, value):
|
||||||
User: TibilletUser = get_user_model()
|
User: TibilletUser = get_user_model()
|
||||||
user_paiement, created = User.objects.get_or_create(
|
user_paiement, created = User.objects.get_or_create(
|
||||||
email=value)
|
email=value, username=value)
|
||||||
|
|
||||||
if created:
|
if created:
|
||||||
user_paiement: HumanUser
|
user_paiement: HumanUser
|
||||||
|
|
@ -150,6 +150,7 @@ class ReservationValidator(serializers.Serializer):
|
||||||
user_paiement.is_active = False
|
user_paiement.is_active = False
|
||||||
else:
|
else:
|
||||||
user_paiement.client_achat.add(connection.tenant)
|
user_paiement.client_achat.add(connection.tenant)
|
||||||
|
|
||||||
user_paiement.save()
|
user_paiement.save()
|
||||||
self.user_commande = user_paiement
|
self.user_commande = user_paiement
|
||||||
return user_paiement.email
|
return user_paiement.email
|
||||||
|
|
|
||||||
|
|
@ -326,12 +326,13 @@ 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', 'U', 'P', 'V'
|
CANCELED, CREATED, UNPAID, PAID, PAID_ERROR, VALID, = 'C', 'R', 'U', 'P', 'PE', 'V'
|
||||||
TYPE_CHOICES = [
|
TYPE_CHOICES = [
|
||||||
(CANCELED, _('Annulée')),
|
(CANCELED, _('Annulée')),
|
||||||
(CREATED, _('Crée')),
|
(CREATED, _('Crée')),
|
||||||
(UNPAID, _('Non payée')),
|
(UNPAID, _('Non payée')),
|
||||||
(PAID, _('Payée')),
|
(PAID, _('Payée')),
|
||||||
|
(PAID_ERROR, _('Payée mais mail non valide')),
|
||||||
(VALID, _('Validée')),
|
(VALID, _('Validée')),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -339,6 +340,7 @@ class Reservation(models.Model):
|
||||||
verbose_name=_("Status de la réservation"))
|
verbose_name=_("Status de la réservation"))
|
||||||
|
|
||||||
mail_send = models.BooleanField(default=False)
|
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,
|
# paiement = models.OneToOneField(Paiement_stripe, on_delete=models.PROTECT, blank=True, null=True,
|
||||||
# related_name='reservation')
|
# 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")
|
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,
|
reservation = models.ForeignKey(Reservation, on_delete=models.PROTECT, blank=True, null=True,
|
||||||
related_name="paiements")
|
related_name="paiements")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,6 @@ def expire_paiement_stripe(old_instance, new_instance):
|
||||||
|
|
||||||
def valide_stripe_paiement(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}")
|
logger.info(f" TRIGGER PAIEMENT STRIPE valide_stripe_paiement {old_instance.status} to {new_instance.status}")
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
######################## TRIGGER LIGNE ARTICLE ########################
|
######################## 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} "
|
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")
|
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.status = Paiement_stripe.VALID
|
||||||
|
new_instance.paiement_stripe.traitement_en_cours = False
|
||||||
new_instance.paiement_stripe.save()
|
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
|
# https://github.com/psf/requests/issues/5832
|
||||||
else :
|
else :
|
||||||
logger.info(f" TRIGGER RESERVATION mail déja envoyé {new_instance} : {new_instance.mail_send} - status : {new_instance.status}")
|
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 ########################
|
######################## MOTEUR TRIGGER ########################
|
||||||
|
|
||||||
def error_regression(old_instance, new_instance):
|
def error_regression(old_instance, new_instance):
|
||||||
|
|
@ -169,6 +183,9 @@ TRANSITIONS = {
|
||||||
Paiement_stripe.EXPIRE: expire_paiement_stripe,
|
Paiement_stripe.EXPIRE: expire_paiement_stripe,
|
||||||
Paiement_stripe.CANCELED: 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: {
|
||||||
Paiement_stripe.PAID: set_ligne_article_paid,
|
Paiement_stripe.PAID: set_ligne_article_paid,
|
||||||
Paiement_stripe.VALID: valide_stripe_paiement,
|
Paiement_stripe.VALID: valide_stripe_paiement,
|
||||||
|
|
@ -198,8 +215,9 @@ TRANSITIONS = {
|
||||||
Reservation.PAID: send_billet_to_mail,
|
Reservation.PAID: send_billet_to_mail,
|
||||||
},
|
},
|
||||||
Reservation.PAID: {
|
Reservation.PAID: {
|
||||||
Reservation.VALID: send_billet_to_mail,
|
Reservation.PAID_ERROR: error_in_mail,
|
||||||
Reservation.PAID: send_billet_to_mail,
|
Reservation.PAID: send_billet_to_mail,
|
||||||
|
Reservation.VALID: set_paiement_valid,
|
||||||
'_else_': error_regression,
|
'_else_': error_regression,
|
||||||
},
|
},
|
||||||
Reservation.VALID: {
|
Reservation.VALID: {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
# import base64
|
# import base64
|
||||||
import os
|
import os
|
||||||
|
import smtplib
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
import segno
|
import segno
|
||||||
import barcode
|
import barcode
|
||||||
|
|
@ -169,14 +170,26 @@ def ticket_celery_mailer(reservation_uuid: str):
|
||||||
},
|
},
|
||||||
attached_files=attached_files,
|
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 :
|
||||||
if mail.sended :
|
reservation.mail_send = True
|
||||||
reservation.mail_send = True
|
reservation.status = Reservation.VALID
|
||||||
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()
|
reservation.save()
|
||||||
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{timezone.now()} Erreur envoie de mail pour reservation {reservation} : {e}")
|
logger.error(f"{timezone.now()} Erreur envoie de mail pour reservation {reservation} : {e}")
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,19 @@ class retour_stripe(View):
|
||||||
def get(self, request, uuid_stripe):
|
def get(self, request, uuid_stripe):
|
||||||
paiement_stripe = get_object_or_404(Paiement_stripe, uuid=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()
|
configuration = Configuration.get_solo()
|
||||||
if configuration.stripe_mode_test:
|
if configuration.stripe_mode_test:
|
||||||
stripe.api_key = configuration.stripe_test_api_key
|
stripe.api_key = configuration.stripe_test_api_key
|
||||||
|
|
@ -170,7 +183,8 @@ class retour_stripe(View):
|
||||||
stripe.api_key = configuration.stripe_api_key
|
stripe.api_key = configuration.stripe_api_key
|
||||||
|
|
||||||
print(paiement_stripe.status)
|
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)
|
checkout_session = stripe.checkout.Session.retrieve(paiement_stripe.id_stripe)
|
||||||
|
|
||||||
|
|
@ -179,14 +193,12 @@ class retour_stripe(View):
|
||||||
|
|
||||||
if checkout_session.payment_status == "unpaid":
|
if checkout_session.payment_status == "unpaid":
|
||||||
paiement_stripe.status = Paiement_stripe.PENDING
|
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.status = Paiement_stripe.EXPIRE
|
||||||
paiement_stripe.save()
|
paiement_stripe.save()
|
||||||
|
|
||||||
elif checkout_session.payment_status == "paid":
|
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
|
# le .save() lance le process pre_save BaseBillet.models.send_to_cashless
|
||||||
# qui modifie le status de chaque ligne
|
# 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 validé par le serveur cashless, alors la ligne sera VALID.
|
||||||
# Si toute les lignes sont VALID, le paiement_stripe sera aussi VALID
|
# Si toute les lignes sont VALID, le paiement_stripe sera aussi VALID
|
||||||
# grace au post_save BaseBillet.models.check_status_stripe
|
# 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.last_action = timezone.now()
|
||||||
|
paiement_stripe.traitement_en_cours = True
|
||||||
paiement_stripe.save()
|
paiement_stripe.save()
|
||||||
|
logger.info(f"retour_stripe - paiement_stripe.save() {paiement_stripe.status}")
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
paiement_stripe.status = Paiement_stripe.CANCELED
|
paiement_stripe.status = Paiement_stripe.CANCELED
|
||||||
|
|
@ -203,8 +221,10 @@ class retour_stripe(View):
|
||||||
else:
|
else:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
|
|
||||||
# on vérifie que le status n'ai pas changé
|
# on vérifie que le status n'ai pas changé
|
||||||
paiement_stripe.refresh_from_db()
|
paiement_stripe.refresh_from_db()
|
||||||
|
# import ipdb; ipdb.set_trace()
|
||||||
|
|
||||||
# si c'est depuis le qrcode, on renvoie vers la vue mobile :
|
# si c'est depuis le qrcode, on renvoie vers la vue mobile :
|
||||||
if paiement_stripe.source == Paiement_stripe.QRCODE :
|
if paiement_stripe.source == Paiement_stripe.QRCODE :
|
||||||
|
|
@ -229,13 +249,15 @@ 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 :
|
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(
|
return HttpResponse(
|
||||||
'Paiement okay, on lance les process de validation.')
|
'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}')
|
raise Http404(f'{paiement_stripe.status}')
|
||||||
|
|
|
||||||
|
|
@ -223,7 +223,6 @@ CELERY_RESULT_BACKEND=os.environ.get('CELERY_BACKEND', 'redis://redis:6379/0')
|
||||||
|
|
||||||
# Jet Menu
|
# Jet Menu
|
||||||
# -------------------------------------/
|
# -------------------------------------/
|
||||||
|
|
||||||
JET_SIDE_MENU_COMPACT = True
|
JET_SIDE_MENU_COMPACT = True
|
||||||
JET_CHANGE_FORM_SIBLING_LINKS = False
|
JET_CHANGE_FORM_SIBLING_LINKS = False
|
||||||
|
|
||||||
|
|
@ -238,11 +237,11 @@ LOGGING = {
|
||||||
},
|
},
|
||||||
'handlers': {
|
'handlers': {
|
||||||
'console': {
|
'console': {
|
||||||
'level': 'DEBUG',
|
'level': 'INFO',
|
||||||
'class': 'logging.StreamHandler',
|
'class': 'logging.StreamHandler',
|
||||||
},
|
},
|
||||||
'logfile': {
|
'logfile': {
|
||||||
'level': 'DEBUG',
|
'level': 'INFO',
|
||||||
'class': 'logging.handlers.RotatingFileHandler',
|
'class': 'logging.handlers.RotatingFileHandler',
|
||||||
'filename': f"{BASE_DIR}/www/Djangologfile",
|
'filename': f"{BASE_DIR}/www/Djangologfile",
|
||||||
'formatter': 'simple',
|
'formatter': 'simple',
|
||||||
|
|
@ -250,7 +249,7 @@ LOGGING = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'root': {
|
'root': {
|
||||||
'level': 'DEBUG',
|
'level': 'INFO',
|
||||||
'handlers': ['console', 'logfile']
|
'handlers': ['console', 'logfile']
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue