From 4043bae57577ae0444594a8f5b418455ef9bd4e1 Mon Sep 17 00:00:00 2001 From: Jonas 12t Date: Sat, 23 Oct 2021 14:54:16 +0400 Subject: [PATCH] =?UTF-8?q?Api=20cr=C3=A9ation=20tarifs=20et=20events?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DjangoFiles/Administration/admin_public.py | 2 +- DjangoFiles/Administration/admin_tenant.py | 4 +- .../management/commands/createdemo.py | 12 --- DjangoFiles/ApiBillet/serializers.py | 73 ++++++++++++++++-- DjangoFiles/ApiBillet/urls.py | 3 +- DjangoFiles/ApiBillet/validators.py | 54 +++++++++++++ DjangoFiles/ApiBillet/views.py | 77 ++++++++++++++++++- DjangoFiles/AuthBillet/models.py | 21 ++++- DjangoFiles/AuthBillet/views.py | 24 +++++- .../BaseBillet/migrations/0001_initial.py | 47 +++++------ .../0002_remove_lignearticle_reste.py | 17 ---- .../migrations/0003_delete_tarifsadhesion.py | 16 ---- .../migrations/0004_lignearticle_carte.py | 20 ----- DjangoFiles/BaseBillet/models.py | 32 ++++++-- DjangoFiles/BaseBillet/validator.py | 4 +- DjangoFiles/BaseBillet/views.py | 4 + DjangoFiles/TiBillet/urls_public.py | 5 +- DjangoFiles/TiBillet/urls_tenants.py | 5 ++ README.md | 6 +- 19 files changed, 304 insertions(+), 122 deletions(-) create mode 100644 DjangoFiles/ApiBillet/validators.py delete mode 100644 DjangoFiles/BaseBillet/migrations/0002_remove_lignearticle_reste.py delete mode 100644 DjangoFiles/BaseBillet/migrations/0003_delete_tarifsadhesion.py delete mode 100644 DjangoFiles/BaseBillet/migrations/0004_lignearticle_carte.py diff --git a/DjangoFiles/Administration/admin_public.py b/DjangoFiles/Administration/admin_public.py index e159eaa..ad36be2 100644 --- a/DjangoFiles/Administration/admin_public.py +++ b/DjangoFiles/Administration/admin_public.py @@ -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): diff --git a/DjangoFiles/Administration/admin_tenant.py b/DjangoFiles/Administration/admin_tenant.py index 83205af..3fee623 100644 --- a/DjangoFiles/Administration/admin_tenant.py +++ b/DjangoFiles/Administration/admin_tenant.py @@ -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): diff --git a/DjangoFiles/Administration/management/commands/createdemo.py b/DjangoFiles/Administration/management/commands/createdemo.py index 7a328fd..724dfba 100644 --- a/DjangoFiles/Administration/management/commands/createdemo.py +++ b/DjangoFiles/Administration/management/commands/createdemo.py @@ -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, - ) - diff --git a/DjangoFiles/ApiBillet/serializers.py b/DjangoFiles/ApiBillet/serializers.py index a87b99b..45c3063 100644 --- a/DjangoFiles/ApiBillet/serializers.py +++ b/DjangoFiles/ApiBillet/serializers.py @@ -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", + } +] +''' diff --git a/DjangoFiles/ApiBillet/urls.py b/DjangoFiles/ApiBillet/urls.py index 76a63dc..96aca7e 100644 --- a/DjangoFiles/ApiBillet/urls.py +++ b/DjangoFiles/ApiBillet/urls.py @@ -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 = [ diff --git a/DjangoFiles/ApiBillet/validators.py b/DjangoFiles/ApiBillet/validators.py new file mode 100644 index 0000000..012b19e --- /dev/null +++ b/DjangoFiles/ApiBillet/validators.py @@ -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 + diff --git a/DjangoFiles/ApiBillet/views.py b/DjangoFiles/ApiBillet/views.py index 221dba1..658bc7b 100644 --- a/DjangoFiles/ApiBillet/views.py +++ b/DjangoFiles/ApiBillet/views.py @@ -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): """ diff --git a/DjangoFiles/AuthBillet/models.py b/DjangoFiles/AuthBillet/models.py index 7fb3048..69edf63 100644 --- a/DjangoFiles/AuthBillet/models.py +++ b/DjangoFiles/AuthBillet/models.py @@ -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' diff --git a/DjangoFiles/AuthBillet/views.py b/DjangoFiles/AuthBillet/views.py index 1e9c394..eafe667 100644 --- a/DjangoFiles/AuthBillet/views.py +++ b/DjangoFiles/AuthBillet/views.py @@ -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] diff --git a/DjangoFiles/BaseBillet/migrations/0001_initial.py b/DjangoFiles/BaseBillet/migrations/0001_initial.py index 782b7be..c061e73 100644 --- a/DjangoFiles/BaseBillet/migrations/0001_initial.py +++ b/DjangoFiles/BaseBillet/migrations/0001_initial.py @@ -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=[ diff --git a/DjangoFiles/BaseBillet/migrations/0002_remove_lignearticle_reste.py b/DjangoFiles/BaseBillet/migrations/0002_remove_lignearticle_reste.py deleted file mode 100644 index 561a77d..0000000 --- a/DjangoFiles/BaseBillet/migrations/0002_remove_lignearticle_reste.py +++ /dev/null @@ -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', - ), - ] diff --git a/DjangoFiles/BaseBillet/migrations/0003_delete_tarifsadhesion.py b/DjangoFiles/BaseBillet/migrations/0003_delete_tarifsadhesion.py deleted file mode 100644 index 06e94fc..0000000 --- a/DjangoFiles/BaseBillet/migrations/0003_delete_tarifsadhesion.py +++ /dev/null @@ -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', - ), - ] diff --git a/DjangoFiles/BaseBillet/migrations/0004_lignearticle_carte.py b/DjangoFiles/BaseBillet/migrations/0004_lignearticle_carte.py deleted file mode 100644 index c87698f..0000000 --- a/DjangoFiles/BaseBillet/migrations/0004_lignearticle_carte.py +++ /dev/null @@ -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'), - ), - ] diff --git a/DjangoFiles/BaseBillet/models.py b/DjangoFiles/BaseBillet/models.py index c01330d..00b55ee 100644 --- a/DjangoFiles/BaseBillet/models.py +++ b/DjangoFiles/BaseBillet/models.py @@ -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: @@ -200,10 +202,10 @@ class Article(models.Model): else: stripe.api_key = configuration.stripe_api_key - if self.img : + if self.img: # noinspection PyUnresolvedReferences domain_url = connection.tenant.domains.all()[0].domain - images = [f"https://{domain_url}{self.img.med.url}",] + images = [f"https://{domain_url}{self.img.med.url}", ] else: images = [] @@ -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) diff --git a/DjangoFiles/BaseBillet/validator.py b/DjangoFiles/BaseBillet/validator.py index 1517852..89ca191 100644 --- a/DjangoFiles/BaseBillet/validator.py +++ b/DjangoFiles/BaseBillet/validator.py @@ -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 diff --git a/DjangoFiles/BaseBillet/views.py b/DjangoFiles/BaseBillet/views.py index 3087014..1f8f516 100644 --- a/DjangoFiles/BaseBillet/views.py +++ b/DjangoFiles/BaseBillet/views.py @@ -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() diff --git a/DjangoFiles/TiBillet/urls_public.py b/DjangoFiles/TiBillet/urls_public.py index 1fcbc82..ba5e7b5 100644 --- a/DjangoFiles/TiBillet/urls_public.py +++ b/DjangoFiles/TiBillet/urls_public.py @@ -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"), diff --git a/DjangoFiles/TiBillet/urls_tenants.py b/DjangoFiles/TiBillet/urls_tenants.py index 9c1f3e1..82883f7 100644 --- a/DjangoFiles/TiBillet/urls_tenants.py +++ b/DjangoFiles/TiBillet/urls_tenants.py @@ -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')), diff --git a/README.md b/README.md index c5a0d17..3cfe86a 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,12 @@ 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 # or you can use the alias from the .bashrc :