check carte sur serveur cashless

This commit is contained in:
Jonas 12t 2021-09-23 16:14:59 +04:00
parent a5b64511f6
commit b9f8324333
21 changed files with 353 additions and 10 deletions

View File

@ -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): class EventAdmin(admin.ModelAdmin):

View File

@ -14,6 +14,7 @@ from TiBillet import settings
from djoser import utils from djoser import utils
User = get_user_model() User = get_user_model()
class activate(APIView): class activate(APIView):
permission_classes = [AllowAny] permission_classes = [AllowAny]
@ -22,7 +23,7 @@ class activate(APIView):
print(uid) print(uid)
print(token) print(token)
import ipdb; ipdb.set_trace() # import ipdb; ipdb.set_trace()
user = User.objects.get(pk=utils.decode_uid(uid)) user = User.objects.get(pk=utils.decode_uid(uid))
PR = PasswordResetTokenGenerator() PR = PasswordResetTokenGenerator()

View File

@ -11,9 +11,11 @@ from django.utils.translation import ugettext_lazy as _
from stdimage import StdImageField from stdimage import StdImageField
from stdimage.validators import MaxSizeValidator from stdimage.validators import MaxSizeValidator
from PaiementStripe.models import Paiement_stripe
from TiBillet import settings from TiBillet import settings
class OptionGenerale(models.Model): class OptionGenerale(models.Model):
name = models.CharField(max_length=30) name = models.CharField(max_length=30)
poids = models.PositiveSmallIntegerField(default=0, verbose_name=_("Poids")) poids = models.PositiveSmallIntegerField(default=0, verbose_name=_("Poids"))
@ -28,7 +30,7 @@ class OptionGenerale(models.Model):
@receiver(post_save, sender=OptionGenerale) @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: if created:
# poids d'apparition # poids d'apparition
if instance.poids == 0: if instance.poids == 0:
@ -76,6 +78,20 @@ class Configuration(SingletonModel):
related_name="checkbox") 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): class Billet(models.Model):
name = models.CharField(max_length=50, name = models.CharField(max_length=50,
blank=True, null=True) blank=True, null=True)
@ -133,6 +149,9 @@ class Event(models.Model):
else: else:
return False return False
def __str__(self):
return f"{self.datetime.strftime('%d/%m')} {self.name}"
class Meta: class Meta:
ordering = ('datetime',) ordering = ('datetime',)
verbose_name = _('Evenement') verbose_name = _('Evenement')
@ -189,7 +208,7 @@ class Reservation(models.Model):
return " - ".join([f"{option.name}" for option in self.options.all()]) return " - ".join([f"{option.name}" for option in self.options.all()])
@receiver(post_save, sender=Reservation) @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 created:
if not instance.user_commande.is_active : if not instance.user_commande.is_active :
instance.status = instance.MAIL_NON_VALIDEE instance.status = instance.MAIL_NON_VALIDEE
@ -199,14 +218,18 @@ def poids_option_generaler(sender, instance: Reservation, created, **kwargs):
class LigneArticle(models.Model): class LigneArticle(models.Model):
uuid = models.UUIDField(primary_key=True, db_index=True, default=uuid.uuid4) 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) article = models.ForeignKey(Article, on_delete=models.CASCADE, blank=True, null=True)
billet = models.ForeignKey(Billet, on_delete=models.CASCADE, blank=True, null=True) billet = models.ForeignKey(Billet, on_delete=models.CASCADE, blank=True, null=True)
qty = models.SmallIntegerField() qty = models.SmallIntegerField()
reste = 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}"

View File

View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class PaiementstripeConfig(AppConfig):
name = 'PaiementStripe'

View File

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

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

View File

View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class QrcodecashlessConfig(AppConfig):
name = 'QrcodeCashless'

View File

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

View File

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Rechargement Online</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<!-- Font Awesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css">
<!-- Bootstrap core CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<!-- Material Design Bootstrap -->
{# <link href="css/mdb.min.css" rel="stylesheet">#}
<!-- Your custom styles (optional) -->
{# <link href="css/style.css" rel="stylesheet">#}
</head>
<body>
<br>
<p class="h3 mb-4 text-center">Rechargement Cashless {{ domain.capitalize }}</p>
{% if liste_assets %}
<p class="h5 mb-5 text-center">Disponible sur votre carte :
{% for asset in liste_assets %}
<p class="h6 mb-6 text-center"> {{ asset }} </p>
{% endfor %}
</p>
{% else %}
<p class="h4 mb-4 text-center">Votre carte est vide.</p>
{% endif %}
<br>
<form class="border border-light p-5" name="form" method="POST">
{% csrf_token %}
<label for="numero_carte">Merci de vérifier votre numéro de la carte cashless ( au dessous du QRCode ) :</label>
<input type="text" id="numero_carte_cashless" class="form-control" placeholder="Numéro de la carte cashless"
value="{{ numero_carte }}" name="numero_carte_cashless" required="True" readonly>
<br>
<label for="Email">Email :</label>
{% if email %}
<input type="email" id="Email" class="form-control mb-4" placeholder="E-mail" name="email" required="True"
value="{{ email }}">
{% else %}
<input type="email" id="Email" class="form-control mb-4" placeholder="E-mail" name="email" required="True">
{% endif %}
<br>
<label for="thune">Somme à recharger (€) :</label>
<input id="thune" class="form-control" type="number" min="1" step="any" name="thune" required="True"/>
<button class="btn btn-info btn-block" type="submit">Payer</button>
</form>
</body>
</html>

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -0,0 +1,7 @@
from django.urls import include, path, re_path
from .views import index_scan
urlpatterns = [
path('<uuid:uuid>', index_scan.as_view()),
]

View File

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

View File

@ -43,6 +43,7 @@ SHARED_APPS = (
# everything below here is optional # everything below here is optional
'django.contrib.auth', 'django.contrib.auth',
'AuthBillet', 'AuthBillet',
'QrcodeCashless',
'rest_framework', 'rest_framework',
'rest_framework.authtoken', 'rest_framework.authtoken',
@ -70,6 +71,7 @@ TENANT_APPS = (
'BaseBillet', 'BaseBillet',
'ApiBillet', 'ApiBillet',
'PaiementStripe',
) )

View File

@ -32,6 +32,7 @@ urlpatterns = [
re_path(r'^user/', include('AuthBillet.urls')), re_path(r'^user/', include('AuthBillet.urls')),
re_path(r'api/', include('ApiBillet.urls')), re_path(r'api/', include('ApiBillet.urls')),
re_path(r'qr/', include('QrcodeCashless.urls')),
path('', include('BaseBillet.urls')), path('', include('BaseBillet.urls')),