Api création tarifs et events

This commit is contained in:
Jonas 12t 2021-10-23 14:54:16 +04:00
parent 9006da23d8
commit 4043bae575
19 changed files with 304 additions and 122 deletions

View File

@ -10,7 +10,7 @@ from django.utils.translation import gettext, gettext_lazy as _
from QrcodeCashless.models import Detail, CarteCashless
# from boutique.models import Category, Product, Tag, VAT, Event, LandingPageContent, Billet
# from boutique.models import Category, Product, Tag, VAT, Event, LandingPageContent, TarifBillet
# from solo.admin import SingletonModelAdmin
class PublicAdminSite(AdminSite):

View File

@ -4,7 +4,7 @@ from django.contrib.auth.models import Group
from solo.admin import SingletonModelAdmin
from AuthBillet.models import HumanUser, SuperHumanUser, TermUser
from BaseBillet.models import Configuration, Event, OptionGenerale, Article, Billet, Reservation, LigneArticle
from BaseBillet.models import Configuration, Event, OptionGenerale, Article, TarifBillet, Reservation, LigneArticle
from django.contrib.auth.admin import UserAdmin
from Customers.models import Client
@ -213,7 +213,7 @@ staff_admin_site.register(LigneArticle, admin.ModelAdmin)
staff_admin_site.register(OptionGenerale, OptionGeneraleAdmin)
staff_admin_site.register(Billet, admin.ModelAdmin)
staff_admin_site.register(TarifBillet, admin.ModelAdmin)
class PaiementStripeAdmin(admin.ModelAdmin):

View File

@ -35,15 +35,3 @@ class Command(BaseCommand):
)
tenant_raffinerie = Client.objects.get_or_create(schema_name="raffinerie",
name="raffinerie",
paid_until='2200-12-05',
on_trial=False)[0]
# Add one or more domains for the tenant
tenant_raffinerie_domain = Domain.objects.get_or_create(domain=f'raffinerie.{os.getenv("DOMAIN")}',
tenant=tenant_demo,
is_primary=True,
)

View File

@ -1,17 +1,76 @@
from rest_framework import serializers
from BaseBillet.models import Event
import json
from django.utils.translation import gettext, gettext_lazy as _
from rest_framework.generics import get_object_or_404
from BaseBillet.models import Event, TarifBillet
class TarifsSerializer(serializers.ModelSerializer):
class Meta:
model = TarifBillet
fields = [
'uuid',
"name",
"prix",
"reservation_par_user_max",
]
extra_kwargs = {'event': {'required': False}}
class EventSerializer(serializers.ModelSerializer):
tarifs = TarifsSerializer(
many=True,
read_only=True
)
class EventSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Event
fields = [
'uuid',
'name',
'short_description',
'long_description',
'datetime',
# 'billets',
# 'articles',
'tarifs',
'articles',
'img',
# 'reservations',
# 'complet',
'reservations',
'complet',
]
read_only_fields = ['reservations']
depth = 1
def validate(self, attrs):
tarifs = self.initial_data.get('tarifs')
if tarifs:
try:
tarifs_list = json.loads(tarifs)
except json.decoder.JSONDecodeError as e :
raise serializers.ValidationError(_(f'tarifs doit être un json valide : {e}'))
self.tarif_to_db = []
for tarif in tarifs_list:
self.tarif_to_db.append(get_object_or_404(TarifBillet, uuid=tarif.get('uuid')))
return super().validate(attrs)
else:
raise serializers.ValidationError(_('tarifs doit être un json valide'))
def save(self, **kwargs):
instance = super().save(**kwargs)
instance.tarifs.clear()
for tarif in self.tarif_to_db :
instance.tarifs.add(tarif)
return instance
'''
[
{
"uuid": "37a1093f-565d-4b38-858d-680568269d43",
},
{
"uuid": "94d36be2-9bb9-4aa6-ab60-fc76287a1290",
}
]
'''

View File

@ -5,7 +5,8 @@ from ApiBillet import views as api_view
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'events', api_view.EventViewSet)
router.register(r'events', api_view.EventsViewSet, basename='event')
router.register(r'tarifs', api_view.TarifBilletViewSet, basename='billet')
urlpatterns = [

View File

@ -0,0 +1,54 @@
from rest_framework import serializers
import json
from BaseBillet.models import Event, TarifBillet
class BilletSerializer(serializers.ModelSerializer):
class Meta:
model = TarifBillet
fields = [
'uuid',
"name",
"prix",
"reservation_par_user_max",
]
class EventSerializer(serializers.ModelSerializer):
billets = BilletSerializer(
many=True,
read_only=True,
)
# billets = serializers.PrimaryKeyRelatedField(queryset=TarifBillet.objects.all(), many=True)
class Meta:
model = Event
fields = [
'uuid',
'name',
'short_description',
'long_description',
'datetime',
'billets',
# 'articles',
'img',
# 'reservations',
'complet',
]
# depth = 1
def save(self, **kwargs):
return super().save(**kwargs)
# def validate(self, value):
# pass
# billets = self.initial_data.get('billets')
# if billets:
# billets_list = json.loads(billets)
# billet_to_db = []
# for billet in billets_list :
# billet_to_db.append(billet.get('uuid'))
# value['billets'] = serializers.ManyRelatedField(queryset=TarifBillet.objects.filter(uuid__in=billet_to_db), many=True)
# return value

View File

@ -1,10 +1,14 @@
from django.shortcuts import render
# Create your views here.
from ApiBillet.serializers import EventSerializer
from rest_framework.generics import get_object_or_404
from rest_framework.response import Response
from ApiBillet.serializers import EventSerializer, TarifsSerializer
from AuthBillet.models import TenantAdminPermission
from Customers.models import Client, Domain
from BaseBillet.models import Event
from rest_framework import viewsets, permissions
from BaseBillet.models import Event, TarifBillet
from rest_framework import viewsets, permissions, status
import os
@ -23,8 +27,75 @@ def new_tenants(schema_name):
return tenant, tenant_domain
class TarifBilletViewSet(viewsets.ViewSet):
def list(self, request):
queryset = TarifBillet.objects.all().order_by('prix')
serializer = TarifsSerializer(queryset, many=True, context={'request': request})
return Response(serializer.data)
def create(self, request):
serializer = TarifsSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
if self.action in ['list','retrieve']:
permission_classes = [permissions.AllowAny]
else:
permission_classes = [TenantAdminPermission]
return [permission() for permission in permission_classes]
class EventsViewSet(viewsets.ViewSet):
queryset = Event.objects.all().order_by('-datetime')
def list(self, request):
serializer = EventSerializer(self.queryset, many=True, context={'request': request})
return Response(serializer.data)
def retrieve(self, request, pk=None):
print(f"retrieve : {pk}")
event = get_object_or_404(self.queryset, pk=pk)
serializer = EventSerializer(event)
return Response(serializer.data)
def create(self, request):
serializer = EventSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def update(self, request, pk=None):
print(f"update : {pk}")
event = get_object_or_404(self.queryset, pk=pk)
print(event)
serializer = EventSerializer(event, data=request.data)
if serializer.is_valid(raise_exception=True):
# import ipdb; ipdb.set_trace()
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def destroy(self, request, pk=None):
event = get_object_or_404(self.queryset, pk=pk)
event.delete()
return Response(('deleted'), status=status.HTTP_200_OK)
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
if self.action in ['list','retrieve']:
permission_classes = [permissions.AllowAny]
else:
permission_classes = [TenantAdminPermission]
return [permission() for permission in permission_classes]
class EventViewSet(viewsets.ModelViewSet):
"""

View File

@ -5,8 +5,19 @@ import uuid
from django.contrib.auth.models import AbstractUser, Group, Permission
from Customers.models import Client
from django.db import connection
from rest_framework import permissions
class TenantAdminPermission(permissions.BasePermission):
message = 'No admin in tenant'
def has_permission(self, request, view):
if request.user.is_authenticated :
return bool((connection.tenant in request.user.client_admin.all() and request.user.is_staff) or request.user.is_superuser)
else :
return False
class TibilletManager(BaseUserManager):
def _create_user(self, email, password, **extra_fields):
# import ipdb; ipdb.set_trace()
@ -14,7 +25,9 @@ class TibilletManager(BaseUserManager):
raise ValueError(_("email obligatoire"))
email = self.normalize_email(email)
user = self.model(username=email, email=email, **extra_fields)
user = self.model(**extra_fields)
user.username = email
user.email = email
user.set_password(password)
user.client_source = connection.tenant
@ -50,11 +63,11 @@ class TibilletUser(AbstractUser):
uuid = models.UUIDField(default=uuid.uuid4, editable=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [] # removes email from REQUIRED_FIELDS
# USERNAME_FIELD = 'email'
# REQUIRED_FIELDS = [] # removes email from REQUIRED_FIELDS
email = models.EmailField(_('email'), unique=True) # changes email to unique and blank to false
username = models.CharField(max_length=200, null=True, blank=True)
username = models.CharField(max_length=200, unique=True)
phone = models.CharField(max_length=20, null=True, blank=True)
TYPE_TERM, TYPE_HUM, TYPE_ANDR = 'TE', 'HU', 'AN'

View File

@ -7,13 +7,35 @@ from rest_framework import status
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
from djoser.views import UserViewSet
from djoser.views import UserViewSet, TokenCreateView
import requests
from django.db import connection
from TiBillet import settings
from djoser.conf import settings as djoser_settings
from djoser import utils
User = get_user_model()
class TokenCreateView_custom(TokenCreateView):
"""
Use this endpoint to obtain user authentication token.
"""
serializer_class = djoser_settings.SERIALIZERS.token_create
permission_classes = djoser_settings.PERMISSIONS.token_create
def _action(self, serializer):
token = utils.login_user(self.request, serializer.user)
token_serializer_class = djoser_settings.SERIALIZERS.token
# on modifie la creation du token pour rajouter access_token dans la réponse pour Postman
data_response = token_serializer_class(token).data
data_response['access_token'] = data_response.get('auth_token')
# import ipdb; ipdb.set_trace()
print(f'data_response {data_response}')
return Response(
data=data_response, status=status.HTTP_200_OK
)
class activate(APIView):
permission_classes = [AllowAny]

View File

@ -1,4 +1,4 @@
# Generated by Django 2.2 on 2021-09-27 13:39
# Generated by Django 2.2 on 2021-10-23 09:56
from django.conf import settings
from django.db import migrations, models
@ -13,8 +13,9 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('PaiementStripe', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('PaiementStripe', '0001_initial'),
('QrcodeCashless', '0002_cartecashless_user'),
]
operations = [
@ -33,27 +34,18 @@ class Migration(migrations.Migration):
('id_price_stripe', models.CharField(blank=True, max_length=30, null=True)),
],
),
migrations.CreateModel(
name='Billet',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=50, null=True)),
('prix', models.FloatField()),
('reservation_par_user_max', models.PositiveSmallIntegerField(default=6)),
],
),
migrations.CreateModel(
name='Event',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
('name', models.CharField(max_length=200)),
('short_description', models.CharField(max_length=250)),
('long_description', models.TextField(blank=True, null=True)),
('datetime', models.DateTimeField()),
('img', stdimage.models.StdImageField(blank=True, null=True, upload_to='images/', validators=[stdimage.validators.MaxSizeValidator(1920, 1920)])),
('img', stdimage.models.StdImageField(upload_to='images/', validators=[stdimage.validators.MaxSizeValidator(1920, 1920)])),
('reservations', models.PositiveSmallIntegerField(default=0)),
('articles', models.ManyToManyField(to='BaseBillet.Article')),
('billets', models.ManyToManyField(to='BaseBillet.Billet')),
('categorie', models.CharField(choices=[('LIV', 'Concert'), ('FES', 'Festival'), ('REU', 'Réunion'), ('CON', 'Conférence')], default='LIV', max_length=3, verbose_name="Catégorie d'évènement")),
('articles', models.ManyToManyField(blank=True, to='BaseBillet.Article')),
],
options={
'verbose_name': 'Evenement',
@ -64,7 +56,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='OptionGenerale',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
('name', models.CharField(max_length=30)),
('poids', models.PositiveSmallIntegerField(default=0, verbose_name='Poids')),
],
@ -75,20 +67,18 @@ class Migration(migrations.Migration):
},
),
migrations.CreateModel(
name='TarifsAdhesion',
name='TarifBillet',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=30)),
('tarif', models.FloatField()),
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
('name', models.CharField(blank=True, max_length=50, null=True)),
('prix', models.FloatField()),
('reservation_par_user_max', models.PositiveSmallIntegerField(default=6)),
],
options={
'ordering': ('-tarif',),
},
),
migrations.CreateModel(
name='VAT',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
('percent', models.FloatField(verbose_name='Taux de TVA (%)')),
],
options={
@ -111,14 +101,19 @@ class Migration(migrations.Migration):
fields=[
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False)),
('qty', models.SmallIntegerField()),
('reste', models.SmallIntegerField()),
('datetime', models.DateTimeField(auto_now=True)),
('article', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='BaseBillet.Article')),
('billet', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='BaseBillet.Billet')),
('billet', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='BaseBillet.TarifBillet')),
('carte', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='QrcodeCashless.CarteCashless')),
('paiement_stripe', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='PaiementStripe.Paiement_stripe')),
('reservation', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='BaseBillet.Reservation')),
],
),
migrations.AddField(
model_name='event',
name='tarifs',
field=models.ManyToManyField(to='BaseBillet.TarifBillet'),
),
migrations.CreateModel(
name='Configuration',
fields=[

View File

@ -1,17 +0,0 @@
# Generated by Django 2.2 on 2021-09-27 13:59
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('BaseBillet', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='lignearticle',
name='reste',
),
]

View File

@ -1,16 +0,0 @@
# Generated by Django 2.2 on 2021-09-27 14:24
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('BaseBillet', '0002_remove_lignearticle_reste'),
]
operations = [
migrations.DeleteModel(
name='TarifsAdhesion',
),
]

View File

@ -1,20 +0,0 @@
# Generated by Django 2.2 on 2021-09-30 08:15
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('QrcodeCashless', '0002_cartecashless_user'),
('BaseBillet', '0003_delete_tarifsadhesion'),
]
operations = [
migrations.AddField(
model_name='lignearticle',
name='carte',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='QrcodeCashless.CarteCashless'),
),
]

View File

@ -19,6 +19,7 @@ import stripe
class OptionGenerale(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True, db_index=True)
name = models.CharField(max_length=30)
poids = models.PositiveSmallIntegerField(default=0, verbose_name=_("Poids"))
@ -41,7 +42,6 @@ def poids_option_generale(sender, instance: OptionGenerale, created, **kwargs):
instance.save()
class Configuration(SingletonModel):
organisation = models.CharField(max_length=50)
short_description = models.CharField(max_length=250)
@ -119,7 +119,8 @@ class Configuration(SingletonModel):
)
class Billet(models.Model):
class TarifBillet(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True, db_index=True)
name = models.CharField(max_length=50,
blank=True, null=True)
prix = models.FloatField()
@ -137,6 +138,7 @@ class VAT(models.Model):
"""
Les différents taux de TVA sont associés à des produits.
"""
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True, db_index=True)
percent = models.FloatField(verbose_name="Taux de TVA (%)")
class Meta:
@ -253,15 +255,15 @@ class Article(models.Model):
class Event(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True, db_index=True)
name = models.CharField(max_length=200)
short_description = models.CharField(max_length=250)
long_description = models.TextField(blank=True, null=True)
datetime = models.DateTimeField()
billets = models.ManyToManyField(Billet)
articles = models.ManyToManyField(Article)
tarifs = models.ManyToManyField(TarifBillet)
articles = models.ManyToManyField(Article, blank=True)
img = StdImageField(upload_to='images/',
null=True, blank=True,
validators=[MaxSizeValidator(1920, 1920)],
variations={
'fhd': (1920, 1920),
@ -273,6 +275,20 @@ class Event(models.Model):
reservations = models.PositiveSmallIntegerField(default=0)
CONCERT = "LIV"
FESTIVAL = "FES"
REUNION = "REU"
CONFERENCE = "CON"
TYPE_CHOICES = [
(CONCERT, _('Concert')),
(FESTIVAL, _('Festival')),
(REUNION, _('Réunion')),
(CONFERENCE, _('Conférence')),
]
categorie = models.CharField(max_length=3, choices=TYPE_CHOICES, default=CONCERT,
verbose_name=_("Catégorie d'évènement"))
def complet(self):
# TODO: Benchmarker et tester si c'est pas mieux dans template
if self.reservations >= Configuration.get_solo().jauge_max:
@ -352,7 +368,7 @@ class LigneArticle(models.Model):
reservation = models.ForeignKey(Reservation, on_delete=models.CASCADE, blank=True, null=True)
article = models.ForeignKey(Article, on_delete=models.CASCADE, blank=True, null=True)
carte = models.ForeignKey(CarteCashless, on_delete=models.PROTECT, blank=True, null=True)
billet = models.ForeignKey(Billet, on_delete=models.CASCADE, blank=True, null=True)
billet = models.ForeignKey(TarifBillet, on_delete=models.CASCADE, blank=True, null=True)
qty = models.SmallIntegerField()
paiement_stripe = models.ForeignKey(Paiement_stripe, on_delete=models.PROTECT, blank=True, null=True)
datetime = models.DateTimeField(auto_now=True)

View File

@ -1,7 +1,7 @@
from rest_framework import serializers
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from BaseBillet.models import OptionGenerale, Configuration, Event, Article, Billet
from BaseBillet.models import OptionGenerale, Configuration, Event, Article, TarifBillet
class ReservationValidator(serializers.Serializer):
@ -25,7 +25,7 @@ class ReservationValidator(serializers.Serializer):
def validate_billets(self, value):
value_dict = {}
billet_obj = Billet.objects.all()
billet_obj = TarifBillet.objects.all()
for couple in value:
pk, qty = billet_obj.get(pk=couple.split(',')[0]), int(couple.split(',')[1])
value_dict[pk] = qty

View File

@ -77,9 +77,13 @@ def creation_de_la_reservation(user: TibilletUser, event: Event, data):
return reservation
#Modèle MVC
class event(APIView):
permission_classes = [AllowAny]
def get(self, request, id):
event = get_object_or_404(Event, pk=id)
configuration = Configuration.get_solo()

View File

@ -16,11 +16,14 @@ Including another URLconf
from django.contrib import admin
from django.urls import path, include, re_path
from Administration.admin_public import public_admin_site
# on modifie la creation du token pour rajouter access_token dans la réponse pour Postman
# from AuthBillet.views import TokenCreateView_custom
urlpatterns = [
path('jet/', include('jet.urls', 'jet')), # Django JET URLS
re_path(r'^jet/dashboard/', include('jet.dashboard.urls', 'jet-dashboard')), # Django JET dashboard URLS
# on modifie la creation du token pour rajouter access_token dans la réponse pour Postman
# re_path(r"^auth/token/login/?$", TokenCreateView_custom.as_view(), name="login"),
re_path(r'^auth/', include('djoser.urls')),
path('admin/', public_admin_site.urls, name="public_admin_url"),

View File

@ -19,6 +19,8 @@ from django.conf.urls.static import static
from django.conf import settings
from Administration.admin_tenant import staff_admin_site
# on modifie la creation du token pour rajouter access_token dans la réponse pour Postman
from AuthBillet.views import TokenCreateView_custom
urlpatterns = [
path('jet/', include('jet.urls', 'jet')), # Django JET URLS
@ -26,6 +28,9 @@ urlpatterns = [
# path('admin/', staff_admin_site.urls, name="staff_admin_site"),
re_path(r'^admin\/{0,}', staff_admin_site.urls, name="staff_admin_site"),
# on modifie la creation du token pour rajouter access_token dans la réponse pour Postman
re_path(r"^auth/token/login/?$", TokenCreateView_custom.as_view(), name="login"),
re_path(r'^auth/', include('djoser.urls')),
re_path(r'^auth/', include('djoser.urls.authtoken')),
re_path(r'^auth/', include('djoser.urls.jwt')),

View File

@ -57,7 +57,11 @@ docker exec -ti tibillet_django bash
python manage.py migrate
# Populate the database with example
python manage.py create_demo_tenant
python manage.py createdemo
# Create the root user
python manage.py create_tenant_superuser
-> public
# Launch the http dev' server ( for production, see the Django & gunicorn doc )
python /DjangoFiles/manage.py runserver_plus 0.0.0.0:8002