From b9f832433358e86c424ba90babdb20ee19d58a70 Mon Sep 17 00:00:00 2001 From: Jonas 12t Date: Thu, 23 Sep 2021 16:14:59 +0400 Subject: [PATCH] check carte sur serveur cashless --- DjangoFiles/Administration/admin_tenant.py | 38 +++++- DjangoFiles/AuthBillet/views.py | 3 +- DjangoFiles/BaseBillet/models.py | 39 ++++-- DjangoFiles/PaiementStripe/__init__.py | 0 DjangoFiles/PaiementStripe/admin.py | 3 + DjangoFiles/PaiementStripe/apps.py | 5 + .../PaiementStripe/migrations/__init__.py | 0 DjangoFiles/PaiementStripe/models.py | 41 ++++++ DjangoFiles/PaiementStripe/tests.py | 3 + DjangoFiles/PaiementStripe/views.py | 3 + DjangoFiles/QrcodeCashless/__init__.py | 0 DjangoFiles/QrcodeCashless/admin.py | 3 + DjangoFiles/QrcodeCashless/apps.py | 5 + .../QrcodeCashless/migrations/__init__.py | 0 DjangoFiles/QrcodeCashless/models.py | 27 ++++ .../templates/RechargementWebUuid.html | 61 +++++++++ DjangoFiles/QrcodeCashless/tests.py | 3 + DjangoFiles/QrcodeCashless/urls.py | 7 ++ DjangoFiles/QrcodeCashless/views.py | 119 ++++++++++++++++++ DjangoFiles/TiBillet/settings.py | 2 + DjangoFiles/TiBillet/urls_tenants.py | 1 + 21 files changed, 353 insertions(+), 10 deletions(-) create mode 100644 DjangoFiles/PaiementStripe/__init__.py create mode 100644 DjangoFiles/PaiementStripe/admin.py create mode 100644 DjangoFiles/PaiementStripe/apps.py create mode 100644 DjangoFiles/PaiementStripe/migrations/__init__.py create mode 100644 DjangoFiles/PaiementStripe/models.py create mode 100644 DjangoFiles/PaiementStripe/tests.py create mode 100644 DjangoFiles/PaiementStripe/views.py create mode 100644 DjangoFiles/QrcodeCashless/__init__.py create mode 100644 DjangoFiles/QrcodeCashless/admin.py create mode 100644 DjangoFiles/QrcodeCashless/apps.py create mode 100644 DjangoFiles/QrcodeCashless/migrations/__init__.py create mode 100644 DjangoFiles/QrcodeCashless/models.py create mode 100644 DjangoFiles/QrcodeCashless/templates/RechargementWebUuid.html create mode 100644 DjangoFiles/QrcodeCashless/tests.py create mode 100644 DjangoFiles/QrcodeCashless/urls.py create mode 100644 DjangoFiles/QrcodeCashless/views.py diff --git a/DjangoFiles/Administration/admin_tenant.py b/DjangoFiles/Administration/admin_tenant.py index a843b11..973aceb 100644 --- a/DjangoFiles/Administration/admin_tenant.py +++ b/DjangoFiles/Administration/admin_tenant.py @@ -97,9 +97,45 @@ staff_admin_site.register(TermUser, TermUserAdmin) ######################################################################## +class ConfigurationAdmin(SingletonModelAdmin): + # readonly_fields = [] + + fieldsets = ( + (None, { + 'fields': ( + 'organisation', + 'short_description', + 'adresse', + 'phone', + 'email', + 'twitter', + 'facebook', + 'instagram', + 'img', + ) + }), + ('Paiements', { + 'fields': ( + 'mollie_api_key', + ), + }), + ('Billetterie', { + 'fields': ( + 'jauge_max', + 'option_generale_radio', + 'option_generale_checkbox', + ), + }), + ('Cashless', { + 'fields': ( + 'server_cashless', + 'key_cashless', + ), + }), + ) -staff_admin_site.register(Configuration, SingletonModelAdmin) +staff_admin_site.register(Configuration, ConfigurationAdmin) class EventAdmin(admin.ModelAdmin): diff --git a/DjangoFiles/AuthBillet/views.py b/DjangoFiles/AuthBillet/views.py index 6e67343..1e9c394 100644 --- a/DjangoFiles/AuthBillet/views.py +++ b/DjangoFiles/AuthBillet/views.py @@ -14,6 +14,7 @@ from TiBillet import settings from djoser import utils User = get_user_model() + class activate(APIView): permission_classes = [AllowAny] @@ -22,7 +23,7 @@ class activate(APIView): print(uid) print(token) - import ipdb; ipdb.set_trace() + # import ipdb; ipdb.set_trace() user = User.objects.get(pk=utils.decode_uid(uid)) PR = PasswordResetTokenGenerator() diff --git a/DjangoFiles/BaseBillet/models.py b/DjangoFiles/BaseBillet/models.py index 5e610f8..4d9b910 100644 --- a/DjangoFiles/BaseBillet/models.py +++ b/DjangoFiles/BaseBillet/models.py @@ -11,9 +11,11 @@ from django.utils.translation import ugettext_lazy as _ from stdimage import StdImageField from stdimage.validators import MaxSizeValidator +from PaiementStripe.models import Paiement_stripe from TiBillet import settings + class OptionGenerale(models.Model): name = models.CharField(max_length=30) poids = models.PositiveSmallIntegerField(default=0, verbose_name=_("Poids")) @@ -28,7 +30,7 @@ class OptionGenerale(models.Model): @receiver(post_save, sender=OptionGenerale) -def poids_option_generaler(sender, instance: OptionGenerale, created, **kwargs): +def poids_option_generale(sender, instance: OptionGenerale, created, **kwargs): if created: # poids d'apparition if instance.poids == 0: @@ -76,6 +78,20 @@ class Configuration(SingletonModel): related_name="checkbox") + server_cashless = models.URLField( + max_length=300, + blank=True, + null=True, + verbose_name="Adresse du serveur Cashless" + ) + + key_cashless = models.CharField( + max_length=41, + blank=True, + null=True, + verbose_name="Clé d'API du serveur cashless" + ) + class Billet(models.Model): name = models.CharField(max_length=50, blank=True, null=True) @@ -133,6 +149,9 @@ class Event(models.Model): else: return False + def __str__(self): + return f"{self.datetime.strftime('%d/%m')} {self.name}" + class Meta: ordering = ('datetime',) verbose_name = _('Evenement') @@ -189,7 +208,7 @@ class Reservation(models.Model): return " - ".join([f"{option.name}" for option in self.options.all()]) @receiver(post_save, sender=Reservation) -def poids_option_generaler(sender, instance: Reservation, created, **kwargs): +def verif_mail_valide(sender, instance: Reservation, created, **kwargs): if created: if not instance.user_commande.is_active : instance.status = instance.MAIL_NON_VALIDEE @@ -199,14 +218,18 @@ def poids_option_generaler(sender, instance: Reservation, created, **kwargs): class LigneArticle(models.Model): uuid = models.UUIDField(primary_key=True, db_index=True, default=uuid.uuid4) - reservation = models.ForeignKey(Reservation, on_delete=models.CASCADE, verbose_name="lignes_article") + reservation = models.ForeignKey(Reservation, on_delete=models.CASCADE, blank=True, null=True) article = models.ForeignKey(Article, on_delete=models.CASCADE, blank=True, null=True) billet = models.ForeignKey(Billet, on_delete=models.CASCADE, blank=True, null=True) qty = models.SmallIntegerField() reste = models.SmallIntegerField() + paiement_stripe = models.ForeignKey(Paiement_stripe, on_delete=models.PROTECT, blank=True, null=True) + + # def __str__(self): + # if self.reservation : + # if self.article : + # return f"{self.reservation.user_commande.email} {self.qty} {self.article}" + # if self.billet : + # return f"{self.reservation.user_commande.email} {self.qty} {self.billet}" + - def __str__(self): - if self.article : - return f"{self.reservation.user_commande.email} {self.qty} {self.article}" - if self.billet : - return f"{self.reservation.user_commande.email} {self.qty} {self.billet}" diff --git a/DjangoFiles/PaiementStripe/__init__.py b/DjangoFiles/PaiementStripe/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/DjangoFiles/PaiementStripe/admin.py b/DjangoFiles/PaiementStripe/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/DjangoFiles/PaiementStripe/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/DjangoFiles/PaiementStripe/apps.py b/DjangoFiles/PaiementStripe/apps.py new file mode 100644 index 0000000..12f2881 --- /dev/null +++ b/DjangoFiles/PaiementStripe/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class PaiementstripeConfig(AppConfig): + name = 'PaiementStripe' diff --git a/DjangoFiles/PaiementStripe/migrations/__init__.py b/DjangoFiles/PaiementStripe/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/DjangoFiles/PaiementStripe/models.py b/DjangoFiles/PaiementStripe/models.py new file mode 100644 index 0000000..50299cb --- /dev/null +++ b/DjangoFiles/PaiementStripe/models.py @@ -0,0 +1,41 @@ +from django.db import models +import uuid +# Create your models here. + + +class Paiement_stripe(models.Model): + """ + La commande + """ + uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True, db_index=True) + + id_stripe = models.CharField(max_length=20, blank=True, null=True) + + order_date = models.DateTimeField(auto_now=True, verbose_name="Date") + + NON, OPEN, PENDING, PAID, VALID, CANCELED = 'N', 'O', 'W', 'P', 'V', 'C' + STATUT_CHOICES = ( + (NON, 'Lien de paiement non crée'), + (OPEN, 'Envoyée a Stripe'), + (PENDING, 'En attente de paiement'), + (PAID, 'Payée'), + (VALID, 'Payée et validée'), # envoyé sur serveur cashless + (CANCELED, 'Annulée'), + ) + status = models.CharField(max_length=1, choices=STATUT_CHOICES, default=NON, verbose_name="Statut de la commande") + + # a remplir par default sur le front par User.email. + email_billet = models.CharField(max_length=30, verbose_name="Email de récéption des billets", blank=True) + + # def total(self): + # total = 0 + # for article in ArticleCommande.objects.filter(commande=self): + # total += article.total() + # + # return total + + def __str__(self): + return self.status + + + diff --git a/DjangoFiles/PaiementStripe/tests.py b/DjangoFiles/PaiementStripe/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/DjangoFiles/PaiementStripe/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/DjangoFiles/PaiementStripe/views.py b/DjangoFiles/PaiementStripe/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/DjangoFiles/PaiementStripe/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/DjangoFiles/QrcodeCashless/__init__.py b/DjangoFiles/QrcodeCashless/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/DjangoFiles/QrcodeCashless/admin.py b/DjangoFiles/QrcodeCashless/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/DjangoFiles/QrcodeCashless/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/DjangoFiles/QrcodeCashless/apps.py b/DjangoFiles/QrcodeCashless/apps.py new file mode 100644 index 0000000..ca31b20 --- /dev/null +++ b/DjangoFiles/QrcodeCashless/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class QrcodecashlessConfig(AppConfig): + name = 'QrcodeCashless' diff --git a/DjangoFiles/QrcodeCashless/migrations/__init__.py b/DjangoFiles/QrcodeCashless/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/DjangoFiles/QrcodeCashless/models.py b/DjangoFiles/QrcodeCashless/models.py new file mode 100644 index 0000000..63fd1c0 --- /dev/null +++ b/DjangoFiles/QrcodeCashless/models.py @@ -0,0 +1,27 @@ +from django.db import models + +# Create your models here. +from Customers.models import Client as Customers_Client + + +class CarteCashless(models.Model): + tag_id = models.CharField( + db_index=True, + max_length=8, + unique=True + ) + + uuid_qrcode = models.UUIDField( + blank=True, null=True, + verbose_name='Uuid', + ) + + number = models.CharField( + db_index=True, + max_length=8, + blank=True, + null=True, + unique=True + ) + + origine = models.ForeignKey(Customers_Client, on_delete=models.PROTECT) \ No newline at end of file diff --git a/DjangoFiles/QrcodeCashless/templates/RechargementWebUuid.html b/DjangoFiles/QrcodeCashless/templates/RechargementWebUuid.html new file mode 100644 index 0000000..268584b --- /dev/null +++ b/DjangoFiles/QrcodeCashless/templates/RechargementWebUuid.html @@ -0,0 +1,61 @@ + + + + + Rechargement Online + + + + + + + + + + + {# #} + + {# #} + + +
+

Rechargement Cashless {{ domain.capitalize }}

+{% if liste_assets %} +

Disponible sur votre carte : + {% for asset in liste_assets %} +

{{ asset }}

+ {% endfor %} +

+{% else %} +

Votre carte est vide.

+{% endif %} +
+
+ + {% csrf_token %} + + + + +
+ + + {% if email %} + + {% else %} + + {% endif %} + +
+ + + + + + +
+ + + diff --git a/DjangoFiles/QrcodeCashless/tests.py b/DjangoFiles/QrcodeCashless/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/DjangoFiles/QrcodeCashless/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/DjangoFiles/QrcodeCashless/urls.py b/DjangoFiles/QrcodeCashless/urls.py new file mode 100644 index 0000000..9a4e228 --- /dev/null +++ b/DjangoFiles/QrcodeCashless/urls.py @@ -0,0 +1,7 @@ +from django.urls import include, path, re_path + +from .views import index_scan + +urlpatterns = [ + path('', index_scan.as_view()), +] \ No newline at end of file diff --git a/DjangoFiles/QrcodeCashless/views.py b/DjangoFiles/QrcodeCashless/views.py new file mode 100644 index 0000000..2f244b7 --- /dev/null +++ b/DjangoFiles/QrcodeCashless/views.py @@ -0,0 +1,119 @@ +import requests, json +from django.http import HttpResponseRedirect, HttpResponse +from django.shortcuts import render + +# Create your views here. +from django.views import View +from rest_framework import status +from rest_framework.response import Response + +from BaseBillet.models import Configuration + + +class index_scan(View): + template_name = "RechargementWebUuid.html" + + def check_carte(self, uuid): + configuration = Configuration.get_solo() + # on questionne le serveur cashless pour voir si la carte existe : + + sess = requests.Session() + try: + reponse = sess.post( + f'{configuration.server_cashless}/api/billetterie_endpoint', + headers={ + 'Authorization': f'Api-Key {configuration.key_cashless}' + }, + data={ + 'uuid': f'{uuid}', + }) + except requests.exceptions.ConnectionError: + reponse = HttpResponse("Serveur non disponible. Merci de revenir ultérieurement.", status=status.HTTP_503_SERVICE_UNAVAILABLE) + + sess.close() + return reponse + + def post(self, request, uuid): + data = request.POST + reponse_server_cashless = self.check_carte(uuid) + + if data.get('numero_carte_cashless') == str(uuid).split('-')[0].upper() and \ + reponse_server_cashless.status_code == 200: + + userWeb, created = User.objects.get_or_create( + username="RechargementWeb", + email="rechargementweb@tibillet.re") + + vat, created = VAT.objects.get_or_create(percent=0) + + commande = Commande.objects.create( + user=userWeb, + email_billet=data.get('email'), + ) + + art, created = Product.objects.get_or_create( + name="CashlessRechargementWeb", + price_ttc="1", + publish=False, + vat=vat + ) + + ArticleCommande.objects.create( + product=art, + quantity=data.get('thune'), + commande=commande, + ) + + domain = get_domain(request) + sub_domain = str(domain).split('.')[0] + absolute_domain = request.build_absolute_uri().partition('/qr')[0] + + Paiement = CreationPaiementMollie(commande, domain, + description=f"Rechargez votre carte {sub_domain.capitalize()}", + redirectUrl=f"{absolute_domain}/RechargementWebAfterMollie/{commande.uuid}", + webhookUrl=f"{absolute_domain}/RechargementWebAfterMollie/{commande.uuid}", + numero_carte_cashless=data.get('numero_carte_cashless')) + + if Paiement.is_send(): + return HttpResponseRedirect(Paiement.is_send()) + + + def get(self, request, uuid): + + # pour rediriger les carte imprimés a la raffinerie vers le bon tenant. + address = request.build_absolute_uri() + host = address.partition('://')[2] + sub_addr = host.partition('.')[0] + if sub_addr == "m": + return HttpResponseRedirect(address.replace("://m.", "://raffinerie.")) + + configuration = Configuration.get_solo() + if not configuration.server_cashless: + return HttpResponse( + "L'adresse du serveur cashless n'est pas renseignée dans la configuration de la billetterie.") + + reponse_server_cashless = self.check_carte(uuid) + json_reponse = json.loads(reponse_server_cashless.json()) + liste_assets = json_reponse.get('liste_assets') + email = json_reponse.get('email') + + if reponse_server_cashless.status_code == 200: + return render( + request, + self.template_name, + { + 'numero_carte': str(uuid).split('-')[0].upper(), + 'domain': sub_addr, + 'informations_carte': reponse_server_cashless.text, + 'liste_assets': liste_assets, + 'email': email, + } + ) + + + elif reponse_server_cashless.status_code == 400: + # Carte non trouvée + return HttpResponse('Carte inconnue', status=status.HTTP_400_BAD_REQUEST) + elif reponse_server_cashless.status_code == 500: + # Serveur cashless hors ligne + return reponse_server_cashless \ No newline at end of file diff --git a/DjangoFiles/TiBillet/settings.py b/DjangoFiles/TiBillet/settings.py index 5d6f317..2c6fcf3 100644 --- a/DjangoFiles/TiBillet/settings.py +++ b/DjangoFiles/TiBillet/settings.py @@ -43,6 +43,7 @@ SHARED_APPS = ( # everything below here is optional 'django.contrib.auth', 'AuthBillet', + 'QrcodeCashless', 'rest_framework', 'rest_framework.authtoken', @@ -70,6 +71,7 @@ TENANT_APPS = ( 'BaseBillet', 'ApiBillet', + 'PaiementStripe', ) diff --git a/DjangoFiles/TiBillet/urls_tenants.py b/DjangoFiles/TiBillet/urls_tenants.py index 4da9246..5c0643a 100644 --- a/DjangoFiles/TiBillet/urls_tenants.py +++ b/DjangoFiles/TiBillet/urls_tenants.py @@ -32,6 +32,7 @@ urlpatterns = [ re_path(r'^user/', include('AuthBillet.urls')), re_path(r'api/', include('ApiBillet.urls')), + re_path(r'qr/', include('QrcodeCashless.urls')), path('', include('BaseBillet.urls')),