Correction bug validation les lignes pour cashless.

Si toute les lignes d'un paiement sont validées, et 200 ok pour serveur cashless, on passe le paiement en validé aussi.
This commit is contained in:
Jonas 12t 2021-11-12 10:33:59 +04:00
parent a1314c683a
commit 7299fb55ae
5 changed files with 171 additions and 110 deletions

View File

@ -1,4 +1,9 @@
# Create your views here. # Create your views here.
import json
import requests
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.utils import timezone from django.utils import timezone
from django_weasyprint import WeasyTemplateView from django_weasyprint import WeasyTemplateView
from rest_framework.generics import get_object_or_404 from rest_framework.generics import get_object_or_404
@ -137,7 +142,56 @@ class ReservationViewset(viewsets.ViewSet):
permission_classes = [TenantAdminPermission] permission_classes = [TenantAdminPermission]
return [permission() for permission in permission_classes] return [permission() for permission in permission_classes]
# class Adhesion(viewsets.ViewSet):
class Membership(viewsets.ViewSet):
def send_mail_to_cashless_for_membership(request, data: dict, carte: any):
sess = requests.Session()
configuration = Configuration.get_solo()
r = sess.post(
f'{configuration.server_cashless}/api/billetterie_qrcode_adhesion',
headers={
'Authorization': f'Api-Key {configuration.key_cashless}'
},
data={
'prenom': data.get('prenom'),
'name': data.get('name'),
'email': data.get('email'),
'tel': data.get('tel'),
'uuid_carte': carte.uuid,
})
sess.close()
# nouveau membre crée avec uniquement l'email on demande la suite.
# HTTP_202_ACCEPTED
# HTTP_201_CREATED
if r.status_code in (201, 204):
messages.success(request, f"{data.get('email')}", extra_tags='email')
return HttpResponseRedirect(f'#demande_nom_prenom_tel')
# partial information :
elif r.status_code == 206:
partial = json.loads(r.text)
messages.success(request, f"{data.get('email')}", extra_tags='email')
if partial.get('name'):
messages.success(request, f"Email déja connu. Name déja connu", extra_tags='name')
if partial.get('prenom'):
messages.success(request, f"Email déja connu. prenom déja connu", extra_tags='prenom')
if partial.get('tel'):
messages.success(request, f"Email déja connu. tel déja connu", extra_tags='tel')
return HttpResponseRedirect(f'#demande_nom_prenom_tel')
# nouveau membre crée, on demande la suite.
elif r.status_code == 202:
messages.success(request, f"Carte liée au membre {data.get('email')}")
return HttpResponseRedirect(f'#adhesionsuccess')
else:
messages.error(request, f'Erreur {r.status_code} {r.text}')
return HttpResponseRedirect(f'#erreur')
class TicketPdf(WeasyTemplateView): class TicketPdf(WeasyTemplateView):
permission_classes = [AllowAny] permission_classes = [AllowAny]

View File

@ -12,6 +12,7 @@ from BaseBillet.tasks import ticket_celery_mailer
# from TiBillet import settings # from TiBillet import settings
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -28,7 +29,7 @@ def set_ligne_article_paid(old_instance, new_instance):
old_instance: Paiement_stripe old_instance: Paiement_stripe
new_instance: Paiement_stripe new_instance: Paiement_stripe
logger.info(f" TRIGGER PAIEMENT STRIPE set_ligne_article_paid {old_instance}.") logger.info(f" TRIGGER PAIEMENT STRIPE set_ligne_article_paid {new_instance}.")
logger.info(f" On passe toutes les lignes d'article non validées en payées !") 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) lignes_article = new_instance.lignearticle_set.exclude(status=LigneArticle.VALID)
@ -53,6 +54,7 @@ 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}")
######################## 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é
@ -60,17 +62,27 @@ def valide_stripe_paiement(old_instance, new_instance):
# @receiver(post_save, sender=LigneArticle) # @receiver(post_save, sender=LigneArticle)
def set_paiement_and_reservation_valid(old_instance, new_instance): def set_paiement_and_reservation_valid(old_instance, new_instance):
lignes_dans_paiement_stripe = new_instance.paiement_stripe.lignearticle_set.all() if new_instance.status == LigneArticle.VALID:
# TODO: calculer -1 ?? logger.info(
if len(lignes_dans_paiement_stripe) == len(lignes_dans_paiement_stripe.filter(status=LigneArticle.VALID)) : f" TRIGGER LIGNE ARTICLE set_paiement_and_reservation_valid {new_instance.price}. On test si toute les lignes sont validées")
# On exclu l'instance en cours car elle n'est pas encore validé en DB comme Valide.
# on test ici : Si toute les autre ligne sont valide et que celle ci l'est aussi.
lignes_dans_paiement_stripe = new_instance.paiement_stripe.lignearticle_set.all().exclude(
uuid=new_instance.uuid)
lignes_valide_dans_paiement_stripe = lignes_dans_paiement_stripe.filter(status=LigneArticle.VALID).exclude(
uuid=new_instance.uuid)
if len(lignes_dans_paiement_stripe) == len(lignes_valide_dans_paiement_stripe):
# on passe le status du paiement stripe en VALID # on passe le status du paiement stripe en VALID
logger.info(f" TRIGGER LIGNE ARTICLE set_paiement_and_reservation_valid {new_instance.price} " logger.info(
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.traitement_en_cours = False
new_instance.paiement_stripe.save() new_instance.paiement_stripe.save()
else:
logger.info(
f" len(lignes_dans_paiement_stripe) {len(lignes_dans_paiement_stripe)} != len(lignes_valide_dans_paiement_stripe) {len(lignes_valide_dans_paiement_stripe)} ")
def send_to_cashless(instance): def send_to_cashless(instance):
@ -100,14 +112,14 @@ def send_to_cashless(instance):
sess.close() sess.close()
logger.info( logger.info(
f" demande au serveur cashless pour un rechargement. réponse : {r.status_code} ") f" demande au serveur cashless pour {instance.price}. réponse : {r.status_code} ")
if r.status_code == 200: if r.status_code != 200:
instance.status = LigneArticle.VALID
else:
logger.error( logger.error(
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}")
return r.status_code
def check_paid(old_instance, new_instance): def check_paid(old_instance, new_instance):
# Type : # Type :
@ -117,7 +129,9 @@ def check_paid(old_instance, new_instance):
if new_instance.price.product.categorie_article in \ if new_instance.price.product.categorie_article in \
[Product.RECHARGE_CASHLESS, Product.ADHESION]: [Product.RECHARGE_CASHLESS, Product.ADHESION]:
send_to_cashless(new_instance) if send_to_cashless(new_instance) == 200:
new_instance.status = LigneArticle.VALID
set_paiement_and_reservation_valid(old_instance, new_instance)
######################## TRIGGER RESERVATION ######################## ######################## TRIGGER RESERVATION ########################
@ -137,33 +151,37 @@ def send_billet_to_mail(old_instance, new_instance):
# import ipdb; ipdb.set_trace() # import ipdb; ipdb.set_trace()
# On vérifie qu'on a pas déja envoyé le mail # 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 {new_instance.status}") logger.info(f" TRIGGER RESERVATION send_billet_to_mail {new_instance.status}")
new_instance : Reservation new_instance: Reservation
if new_instance.user_commande.email: if new_instance.user_commande.email:
# import ipdb; ipdb.set_trace() # import ipdb; ipdb.set_trace()
task = ticket_celery_mailer.delay(new_instance.pk) task = ticket_celery_mailer.delay(new_instance.pk)
# 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) set_paiement_valid(old_instance, new_instance)
def set_paiement_valid(old_instance, new_instance): def set_paiement_valid(old_instance, new_instance):
new_instance: Reservation new_instance: Reservation
if new_instance.mail_send : 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") 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): for paiement in new_instance.paiements.filter(status=Paiement_stripe.PAID):
paiement.status = Paiement_stripe.VALID paiement.status = Paiement_stripe.VALID
paiement.traitement_en_cours = False paiement.traitement_en_cours = False
paiement.save() paiement.save()
def error_in_mail(old_instance, new_instance): def error_in_mail(old_instance, new_instance):
logger.info(f" TRIGGER RESERVATION error_in_mail") logger.info(f" TRIGGER RESERVATION error_in_mail")
new_instance.paiements.all().update(traitement_en_cours = False) new_instance.paiements.all().update(traitement_en_cours=False)
# TODO: Prévenir l'admin q'un billet a été acheté, mais pas envoyé # 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):
@ -197,6 +215,9 @@ TRANSITIONS = {
}, },
'LIGNEARTICLE': { 'LIGNEARTICLE': {
LigneArticle.CREATED: {
LigneArticle.PAID: check_paid,
},
LigneArticle.UNPAID: { LigneArticle.UNPAID: {
LigneArticle.PAID: check_paid, LigneArticle.PAID: check_paid,
}, },
@ -211,6 +232,9 @@ TRANSITIONS = {
}, },
'RESERVATION': { 'RESERVATION': {
Reservation.CREATED: {
Reservation.PAID: send_billet_to_mail,
},
Reservation.UNPAID: { Reservation.UNPAID: {
Reservation.PAID: send_billet_to_mail, Reservation.PAID: send_billet_to_mail,
}, },
@ -226,6 +250,7 @@ TRANSITIONS = {
}, },
} }
@receiver(pre_save) @receiver(pre_save)
def pre_save_signal_status(sender, instance, **kwargs): def pre_save_signal_status(sender, instance, **kwargs):
# if not create # if not create

View File

@ -41,26 +41,3 @@
</form> </form>
</div> </div>
<!-- END ADHESION MODAL MENU --> <!-- END ADHESION MODAL MENU -->
<h2>Adhésion</h2>
<h2 class="major">{{ client_name }}</h2>
<form method="post" action="#">
{% csrf_token %}
<div class="fields">
<div class="field">
{% if email %}
<label for="email">Vérifiez votre adresse Email</label>
<input type="email" name="email" id="Email" required="True" value="{{ email }}"
style="text-transform: lowercase;"/>
{% else %}
<label for="email">Entrez votre adresse Email</label>
<input type="email" name="email" id="email" required="True"
style="text-transform: lowercase;"/>
{% endif %}
</div>
</div>
<ul class="actions">
<li><input type="submit" value="continuer" class="primary"/></li>
</ul>
</form>

View File

@ -15,6 +15,7 @@ from AuthBillet.models import HumanUser
from BaseBillet.models import Configuration, LigneArticle, Paiement_stripe, Reservation from BaseBillet.models import Configuration, LigneArticle, Paiement_stripe, Reservation
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -48,7 +49,9 @@ class creation_paiement_stripe():
def _user_paiement(self): def _user_paiement(self):
User = get_user_model() User = get_user_model()
user_paiement, created = User.objects.get_or_create( user_paiement, created = User.objects.get_or_create(
email=self.email_paiement) email=self.email_paiement,
username=self.email_paiement,
)
# On ne lie pas tout de suite la carte a l'user, # On ne lie pas tout de suite la carte a l'user,
# on attendra une réponse positive du serveur cashless. # on attendra une réponse positive du serveur cashless.
@ -163,19 +166,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 : if paiement_stripe.traitement_en_cours:
return HttpResponse( return HttpResponse(
'traitement_en_cours') 'traitement_en_cours')
if paiement_stripe.reservation.status == Reservation.PAID_ERROR : if paiement_stripe.reservation:
if paiement_stripe.reservation.status == Reservation.PAID_ERROR:
return HttpResponse( return HttpResponse(
"Erreur dans l'envoie du mail. Merci de vérifier l'adresse") "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 : if paiement_stripe.status == Paiement_stripe.VALID or paiement_stripe.reservation.status == Reservation.VALID:
return HttpResponse( return HttpResponse(
'Paiement déja validé !') '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
@ -183,8 +186,7 @@ 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 and \ if paiement_stripe.status != Paiement_stripe.VALID:
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)
@ -193,7 +195,7 @@ 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 datetime.now().timestamp() > checkout_session.expires_at : 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()
return HttpResponse( return HttpResponse(
@ -222,25 +224,24 @@ 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() # 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:
# SI le paiement est valide, c'est que les presave et postsave # SI le paiement est valide, c'est que les presave et postsave
# ont validé la réponse du serveur cashless pour les recharges # ont validé la réponse du serveur cashless pour les recharges
if paiement_stripe.status == Paiement_stripe.VALID : if paiement_stripe.status == Paiement_stripe.VALID:
# on boucle ici pour récuperer l'uuid de la carte. # on boucle ici pour récuperer l'uuid de la carte.
for ligne_article in paiement_stripe.lignearticle_set.all(): for ligne_article in paiement_stripe.lignearticle_set.all():
if ligne_article.carte: if ligne_article.carte:
messages.success(request, f"Paiement validé. Merci !") messages.success(request, f"Paiement validé. Merci !")
return HttpResponseRedirect(f"/qr/{ligne_article.carte.uuid}#success") return HttpResponseRedirect(f"/qr/{ligne_article.carte.uuid}#success")
else : else:
# on boucle ici pour récuperer l'uuid de la carte. # on boucle ici pour récuperer l'uuid de la carte.
for ligne_article in paiement_stripe.lignearticle_set.all(): for ligne_article in paiement_stripe.lignearticle_set.all():
if ligne_article.carte: if ligne_article.carte:
@ -249,18 +250,20 @@ class retour_stripe(View):
f"Merci de vérifier votre moyen de paiement et/ou contactez un responsable.") f"Merci de vérifier votre moyen de paiement et/ou contactez un responsable.")
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.VALID or paiement_stripe.reservation.status == Reservation.VALID : if paiement_stripe.reservation:
if paiement_stripe.reservation.status == Reservation.VALID:
return HttpResponse(
'Paiement déja validé !')
if paiement_stripe.status == Paiement_stripe.VALID:
return HttpResponse( return HttpResponse(
'Paiement déja validé !') 'Paiement déja validé !')
elif paiement_stripe.status == Paiement_stripe.PAID : elif paiement_stripe.status == Paiement_stripe.PAID:
logger.info(f"Paiement_stripe.API_BILLETTERIE : {paiement_stripe.status}") 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.')
raise Http404(f'{paiement_stripe.status}') raise Http404(f'{paiement_stripe.status}')

View File

@ -11,6 +11,7 @@ from rest_framework.generics import get_object_or_404
from django.views import View from django.views import View
from rest_framework import status from rest_framework import status
from ApiBillet.views import Membership
from BaseBillet.models import Configuration, Product, LigneArticle, Price, Paiement_stripe from BaseBillet.models import Configuration, Product, LigneArticle, Price, Paiement_stripe
from PaiementStripe.views import creation_paiement_stripe from PaiementStripe.views import creation_paiement_stripe
from QrcodeCashless.models import CarteCashless from QrcodeCashless.models import CarteCashless
@ -213,48 +214,49 @@ class index_scan(View):
# Email seul sans montant, c'est une adhésion # Email seul sans montant, c'est une adhésion
elif data.get('email'): elif data.get('email'):
return Membership.send_mail_to_cashless_for_membership(request, data, carte)
sess = requests.Session() #
configuration = Configuration.get_solo() # sess = requests.Session()
r = sess.post( # configuration = Configuration.get_solo()
f'{configuration.server_cashless}/api/billetterie_qrcode_adhesion', # r = sess.post(
headers={ # f'{configuration.server_cashless}/api/billetterie_qrcode_adhesion',
'Authorization': f'Api-Key {configuration.key_cashless}' # headers={
}, # 'Authorization': f'Api-Key {configuration.key_cashless}'
data={ # },
'prenom': data.get('prenom'), # data={
'name': data.get('name'), # 'prenom': data.get('prenom'),
'email': data.get('email'), # 'name': data.get('name'),
'tel': data.get('tel'), # 'email': data.get('email'),
'uuid_carte': carte.uuid, # 'tel': data.get('tel'),
}) # 'uuid_carte': carte.uuid,
# })
sess.close() #
# sess.close()
# nouveau membre crée avec uniquement l'email on demande la suite. #
# HTTP_202_ACCEPTED # # nouveau membre crée avec uniquement l'email on demande la suite.
# HTTP_201_CREATED # # HTTP_202_ACCEPTED
if r.status_code in (201, 204): # # HTTP_201_CREATED
messages.success(request, f"{data.get('email')}", extra_tags='email') # if r.status_code in (201, 204):
return HttpResponseRedirect(f'#demande_nom_prenom_tel') # messages.success(request, f"{data.get('email')}", extra_tags='email')
# return HttpResponseRedirect(f'#demande_nom_prenom_tel')
# partial information : #
elif r.status_code == 206: # # partial information :
partial = json.loads(r.text) # elif r.status_code == 206:
messages.success(request, f"{data.get('email')}", extra_tags='email') # partial = json.loads(r.text)
if partial.get('name'): # messages.success(request, f"{data.get('email')}", extra_tags='email')
messages.success(request, f"Email déja connu. Name déja connu", extra_tags='name') # if partial.get('name'):
if partial.get('prenom'): # messages.success(request, f"Email déja connu. Name déja connu", extra_tags='name')
messages.success(request, f"Email déja connu. prenom déja connu", extra_tags='prenom') # if partial.get('prenom'):
if partial.get('tel'): # messages.success(request, f"Email déja connu. prenom déja connu", extra_tags='prenom')
messages.success(request, f"Email déja connu. tel déja connu", extra_tags='tel') # if partial.get('tel'):
return HttpResponseRedirect(f'#demande_nom_prenom_tel') # messages.success(request, f"Email déja connu. tel déja connu", extra_tags='tel')
# return HttpResponseRedirect(f'#demande_nom_prenom_tel')
# nouveau membre crée, on demande la suite. #
elif r.status_code == 202: # # nouveau membre crée, on demande la suite.
messages.success(request, f"Carte liée au membre {data.get('email')}") # elif r.status_code == 202:
return HttpResponseRedirect(f'#adhesionsuccess') # messages.success(request, f"Carte liée au membre {data.get('email')}")
# return HttpResponseRedirect(f'#adhesionsuccess')
else: #
messages.error(request, f'Erreur {r.status_code} {r.text}') # else:
return HttpResponseRedirect(f'#erreur') # messages.error(request, f'Erreur {r.status_code} {r.text}')
# return HttpResponseRedirect(f'#erreur')