refactor product, prices & event.
This commit is contained in:
parent
26dadfbb4f
commit
cd80c74f90
|
|
@ -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, TarifBillet
|
||||
# from boutique.models import Category, Product, Tag, VAT, Event, LandingPageContent, Price
|
||||
# from solo.admin import SingletonModelAdmin
|
||||
|
||||
class PublicAdminSite(AdminSite):
|
||||
|
|
|
|||
|
|
@ -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, TarifBillet, Reservation, LigneArticle
|
||||
from BaseBillet.models import Configuration, Event, OptionGenerale, Product, Price, Reservation, LigneArticle
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
|
||||
from Customers.models import Client
|
||||
|
|
@ -106,7 +106,7 @@ class ConfigurationAdmin(SingletonModelAdmin):
|
|||
'fields': (
|
||||
'organisation',
|
||||
'short_description',
|
||||
'adresse',
|
||||
'adress',
|
||||
'phone',
|
||||
'email',
|
||||
'site_web',
|
||||
|
|
@ -186,24 +186,19 @@ class ReservationAdmin(admin.ModelAdmin):
|
|||
|
||||
staff_admin_site.register(Reservation, ReservationAdmin)
|
||||
|
||||
class ArticleAdmin(admin.ModelAdmin):
|
||||
class ProductAdmin(admin.ModelAdmin):
|
||||
list_display = (
|
||||
'name',
|
||||
'prix',
|
||||
'stock',
|
||||
'reservation_par_user_max',
|
||||
'vat',
|
||||
'publish',
|
||||
'img',
|
||||
'categorie_article',
|
||||
'id_product_stripe',
|
||||
)
|
||||
list_editable = (
|
||||
'prix',
|
||||
'stock',
|
||||
'reservation_par_user_max',
|
||||
'vat',
|
||||
'publish',
|
||||
)
|
||||
|
||||
staff_admin_site.register(Article, ArticleAdmin)
|
||||
staff_admin_site.register(Product, ProductAdmin)
|
||||
|
||||
|
||||
|
||||
|
|
@ -213,7 +208,7 @@ staff_admin_site.register(LigneArticle, admin.ModelAdmin)
|
|||
|
||||
staff_admin_site.register(OptionGenerale, OptionGeneraleAdmin)
|
||||
|
||||
staff_admin_site.register(TarifBillet, admin.ModelAdmin)
|
||||
staff_admin_site.register(Price, admin.ModelAdmin)
|
||||
|
||||
|
||||
class PaiementStripeAdmin(admin.ModelAdmin):
|
||||
|
|
@ -223,12 +218,8 @@ class PaiementStripeAdmin(admin.ModelAdmin):
|
|||
'total',
|
||||
'order_date',
|
||||
'status',
|
||||
'articles',
|
||||
)
|
||||
ordering = ('-order_date',)
|
||||
# readonly_fields = (
|
||||
# 'reservations',
|
||||
# )
|
||||
|
||||
|
||||
staff_admin_site.register(Paiement_stripe, PaiementStripeAdmin)
|
||||
|
|
|
|||
|
|
@ -3,47 +3,55 @@ 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, Article
|
||||
from BaseBillet.models import Event, Price, Product
|
||||
|
||||
|
||||
class TarifsSerializer(serializers.ModelSerializer):
|
||||
|
||||
|
||||
class ProductSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TarifBillet
|
||||
model = Product
|
||||
fields = [
|
||||
'uuid',
|
||||
"uuid",
|
||||
"name",
|
||||
"prix",
|
||||
"reservation_par_user_max",
|
||||
]
|
||||
read_only_fields = ['uuid']
|
||||
|
||||
|
||||
class ArticleSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Article
|
||||
fields = [
|
||||
'uuid',
|
||||
'name',
|
||||
'prix',
|
||||
'stock',
|
||||
'reservation_par_user_max',
|
||||
'vat',
|
||||
'publish',
|
||||
'img',
|
||||
'categorie_article',
|
||||
'id_product_stripe',
|
||||
'id_price_stripe',
|
||||
"publish",
|
||||
"img",
|
||||
"categorie_article",
|
||||
"prices",
|
||||
"id_product_stripe",
|
||||
]
|
||||
depth = 1
|
||||
read_only_fields = [
|
||||
'uuid',
|
||||
'id_product_stripe',
|
||||
'prices',
|
||||
]
|
||||
|
||||
class PriceSerializer(serializers.ModelSerializer):
|
||||
product = serializers.PrimaryKeyRelatedField(queryset=Product.objects.all())
|
||||
|
||||
class Meta:
|
||||
model = Price
|
||||
fields = [
|
||||
'uuid',
|
||||
'product',
|
||||
'name',
|
||||
'prix',
|
||||
'vat',
|
||||
'id_price_stripe',
|
||||
'stock',
|
||||
'max_per_user',
|
||||
]
|
||||
|
||||
read_only_fields = [
|
||||
'uuid',
|
||||
'id_price_stripe',
|
||||
]
|
||||
depth = 1
|
||||
|
||||
|
||||
class EventSerializer(serializers.ModelSerializer):
|
||||
tarifs = TarifsSerializer(
|
||||
products = ProductSerializer(
|
||||
many=True,
|
||||
read_only=True
|
||||
)
|
||||
|
|
@ -56,8 +64,7 @@ class EventSerializer(serializers.ModelSerializer):
|
|||
'short_description',
|
||||
'long_description',
|
||||
'datetime',
|
||||
'tarifs',
|
||||
'articles',
|
||||
'products',
|
||||
'img',
|
||||
'reservations',
|
||||
'complet',
|
||||
|
|
@ -65,37 +72,36 @@ class EventSerializer(serializers.ModelSerializer):
|
|||
read_only_fields = ['uuid', 'reservations']
|
||||
depth = 1
|
||||
|
||||
|
||||
def validate(self, attrs):
|
||||
|
||||
tarifs = self.initial_data.get('tarifs')
|
||||
if tarifs:
|
||||
products = self.initial_data.get('products')
|
||||
if products:
|
||||
try:
|
||||
tarifs_list = json.loads(tarifs)
|
||||
products_list = json.loads(products)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
raise serializers.ValidationError(_(f'tarifs doit être un json valide : {e}'))
|
||||
raise serializers.ValidationError(_(f'products 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')))
|
||||
self.products_to_db = []
|
||||
for product in products_list:
|
||||
self.products_to_db.append(get_object_or_404(Product, uuid=product.get('uuid')))
|
||||
return super().validate(attrs)
|
||||
else:
|
||||
raise serializers.ValidationError(_('tarifs doit être un json valide'))
|
||||
raise serializers.ValidationError(_('products 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)
|
||||
instance.products.clear()
|
||||
for product in self.products_to_db:
|
||||
instance.products.add(product)
|
||||
return instance
|
||||
|
||||
'''
|
||||
|
||||
products = [
|
||||
{"uuid":"9340a9a1-1b90-488e-ab68-7b358b213dd7"},
|
||||
{"uuid":"60db1531-fd0a-4d92-a785-f384e77cd213"}
|
||||
]
|
||||
|
||||
|
||||
'''
|
||||
[
|
||||
{
|
||||
"uuid": "37a1093f-565d-4b38-858d-680568269d43",
|
||||
},
|
||||
{
|
||||
"uuid": "94d36be2-9bb9-4aa6-ab60-fc76287a1290",
|
||||
}
|
||||
]
|
||||
'''
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ from rest_framework import routers
|
|||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'events', api_view.EventsViewSet, basename='event')
|
||||
router.register(r'tarifs', api_view.TarifBilletViewSet, basename='billet')
|
||||
router.register(r'articles', api_view.ArticleViewSet, basename='article')
|
||||
router.register(r'products', api_view.ProductViewSet, basename='product')
|
||||
router.register(r'prices', api_view.TarifBilletViewSet, basename='price')
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
from rest_framework import serializers
|
||||
import json
|
||||
|
||||
from BaseBillet.models import Event, TarifBillet
|
||||
from BaseBillet.models import Event, Price
|
||||
|
||||
class BilletSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TarifBillet
|
||||
model = Price
|
||||
fields = [
|
||||
'uuid',
|
||||
"name",
|
||||
"prix",
|
||||
"reservation_par_user_max",
|
||||
"max_per_user",
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ class EventSerializer(serializers.ModelSerializer):
|
|||
many=True,
|
||||
read_only=True,
|
||||
)
|
||||
# billets = serializers.PrimaryKeyRelatedField(queryset=TarifBillet.objects.all(), many=True)
|
||||
# billets = serializers.PrimaryKeyRelatedField(queryset=Price.objects.all(), many=True)
|
||||
|
||||
class Meta:
|
||||
model = Event
|
||||
|
|
@ -31,7 +31,7 @@ class EventSerializer(serializers.ModelSerializer):
|
|||
'long_description',
|
||||
'datetime',
|
||||
'billets',
|
||||
# 'articles',
|
||||
# 'products',
|
||||
'img',
|
||||
# 'reservations',
|
||||
'complet',
|
||||
|
|
@ -49,6 +49,6 @@ class EventSerializer(serializers.ModelSerializer):
|
|||
# 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)
|
||||
# value['billets'] = serializers.ManyRelatedField(queryset=Price.objects.filter(uuid__in=billet_to_db), many=True)
|
||||
# return value
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ from django.shortcuts import render
|
|||
from rest_framework.generics import get_object_or_404
|
||||
from rest_framework.response import Response
|
||||
|
||||
from ApiBillet.serializers import EventSerializer, TarifsSerializer, ArticleSerializer
|
||||
from ApiBillet.serializers import EventSerializer, PriceSerializer, ProductSerializer
|
||||
from AuthBillet.models import TenantAdminPermission
|
||||
from Customers.models import Client, Domain
|
||||
from BaseBillet.models import Event, TarifBillet, Article
|
||||
from BaseBillet.models import Event, Price, Product
|
||||
from rest_framework import viewsets, permissions, status
|
||||
|
||||
import os
|
||||
|
|
@ -29,12 +29,12 @@ def new_tenants(schema_name):
|
|||
|
||||
class TarifBilletViewSet(viewsets.ViewSet):
|
||||
def list(self, request):
|
||||
queryset = TarifBillet.objects.all().order_by('prix')
|
||||
serializer = TarifsSerializer(queryset, many=True, context={'request': request})
|
||||
queryset = Price.objects.all().order_by('prix')
|
||||
serializer = PriceSerializer(queryset, many=True, context={'request': request})
|
||||
return Response(serializer.data)
|
||||
|
||||
def create(self, request):
|
||||
serializer = TarifsSerializer(data=request.data)
|
||||
serializer = PriceSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
|
@ -48,15 +48,15 @@ class TarifBilletViewSet(viewsets.ViewSet):
|
|||
return [permission() for permission in permission_classes]
|
||||
|
||||
|
||||
class ArticleViewSet(viewsets.ViewSet):
|
||||
class ProductViewSet(viewsets.ViewSet):
|
||||
|
||||
def list(self, request):
|
||||
serializer = ArticleSerializer(Article.objects.all(), many=True, context={'request': request})
|
||||
serializer = ProductSerializer(Product.objects.all(), many=True, context={'request': request})
|
||||
print(serializer.data)
|
||||
return Response(serializer.data)
|
||||
|
||||
def create(self, request):
|
||||
serializer = ArticleSerializer(data=request.data)
|
||||
serializer = ProductSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 2.2 on 2021-10-23 09:56
|
||||
# Generated by Django 2.2 on 2021-10-24 10:22
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
|
@ -14,26 +14,11 @@ class Migration(migrations.Migration):
|
|||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('PaiementStripe', '0001_initial'),
|
||||
('QrcodeCashless', '0002_cartecashless_user'),
|
||||
('PaiementStripe', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Article',
|
||||
fields=[
|
||||
('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()),
|
||||
('stock', models.SmallIntegerField(blank=True, null=True)),
|
||||
('reservation_par_user_max', models.PositiveSmallIntegerField(default=10)),
|
||||
('publish', models.BooleanField(default=False)),
|
||||
('img', stdimage.models.StdImageField(blank=True, null=True, upload_to='images/', validators=[stdimage.validators.MaxSizeValidator(1920, 1920)], verbose_name='Image')),
|
||||
('categorie_article', models.CharField(choices=[('B', 'Billet'), ('P', "Pack d'objets"), ('R', 'Recharge cashless'), ('T', 'Vetement'), ('M', 'Merchandasing'), ('A', 'Adhésion')], default='B', max_length=3, verbose_name="Type d'article")),
|
||||
('id_product_stripe', models.CharField(blank=True, max_length=30, null=True)),
|
||||
('id_price_stripe', models.CharField(blank=True, max_length=30, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Event',
|
||||
fields=[
|
||||
|
|
@ -45,7 +30,6 @@ class Migration(migrations.Migration):
|
|||
('img', stdimage.models.StdImageField(upload_to='images/', validators=[stdimage.validators.MaxSizeValidator(1920, 1920)])),
|
||||
('reservations', models.PositiveSmallIntegerField(default=0)),
|
||||
('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',
|
||||
|
|
@ -67,25 +51,16 @@ class Migration(migrations.Migration):
|
|||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TarifBillet',
|
||||
name='Product',
|
||||
fields=[
|
||||
('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)),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('publish', models.BooleanField(default=False)),
|
||||
('img', stdimage.models.StdImageField(blank=True, null=True, upload_to='images/', validators=[stdimage.validators.MaxSizeValidator(1920, 1920)], verbose_name='Image')),
|
||||
('categorie_article', models.CharField(choices=[('B', 'Billet'), ('P', "Pack d'objets"), ('R', 'Recharge cashless'), ('T', 'Vetement'), ('M', 'Merchandasing'), ('A', 'Adhésion')], default='B', max_length=3, verbose_name="Type d'article")),
|
||||
('id_product_stripe', models.CharField(blank=True, max_length=30, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='VAT',
|
||||
fields=[
|
||||
('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={
|
||||
'verbose_name': 'TVA',
|
||||
'verbose_name_plural': 'TVA',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Reservation',
|
||||
fields=[
|
||||
|
|
@ -96,31 +71,48 @@ class Migration(migrations.Migration):
|
|||
('user_commande', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Price',
|
||||
fields=[
|
||||
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('prix', models.FloatField()),
|
||||
('vat', models.CharField(choices=[('NA', 'Non applicable'), ('DX', '10 %'), ('VG', '20 %')], default='NA', max_length=2, verbose_name='Taux TVA')),
|
||||
('id_price_stripe', models.CharField(blank=True, max_length=30, null=True)),
|
||||
('stock', models.SmallIntegerField(blank=True, null=True)),
|
||||
('max_per_user', models.PositiveSmallIntegerField(default=10)),
|
||||
('product', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='BaseBillet.Product')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LigneArticle',
|
||||
fields=[
|
||||
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False)),
|
||||
('qty', 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.TarifBillet')),
|
||||
('qty', models.SmallIntegerField()),
|
||||
('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')),
|
||||
('product', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='BaseBillet.Product')),
|
||||
('reservation', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='BaseBillet.Reservation')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='products',
|
||||
field=models.ManyToManyField(blank=True, to='BaseBillet.Product'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='tarifs',
|
||||
field=models.ManyToManyField(to='BaseBillet.TarifBillet'),
|
||||
field=models.ManyToManyField(to='BaseBillet.Price'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Configuration',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('organisation', models.CharField(max_length=50)),
|
||||
('short_description', models.CharField(max_length=250)),
|
||||
('adresse', models.CharField(max_length=250)),
|
||||
('organisation', models.CharField(max_length=50, verbose_name="Nom de l'organisation")),
|
||||
('short_description', models.CharField(max_length=250, verbose_name='Description courte')),
|
||||
('adress', models.CharField(max_length=250)),
|
||||
('phone', models.CharField(max_length=20)),
|
||||
('email', models.EmailField(max_length=254)),
|
||||
('site_web', models.URLField(blank=True, null=True)),
|
||||
|
|
@ -128,15 +120,14 @@ class Migration(migrations.Migration):
|
|||
('facebook', models.URLField(blank=True, null=True)),
|
||||
('instagram', models.URLField(blank=True, null=True)),
|
||||
('adhesion_obligatoire', models.BooleanField(default=False)),
|
||||
('cadeau_adhesion', models.FloatField(default=0, help_text="Recharge cadeau a l'adhésion")),
|
||||
('carte_restaurant', stdimage.models.StdImageField(blank=True, null=True, upload_to='images/', validators=[stdimage.validators.MaxSizeValidator(1920, 1920)], verbose_name='Carte du restaurant')),
|
||||
('img', stdimage.models.StdImageField(blank=True, null=True, upload_to='images/', verbose_name='Background')),
|
||||
('mollie_api_key', models.CharField(blank=True, max_length=50, null=True)),
|
||||
('stripe_api_key', models.CharField(blank=True, max_length=110, null=True)),
|
||||
('stripe_test_api_key', models.CharField(blank=True, max_length=110, null=True)),
|
||||
('stripe_mode_test', models.BooleanField(default=True)),
|
||||
('activer_billetterie', models.BooleanField(default=True)),
|
||||
('jauge_max', models.PositiveSmallIntegerField(default=50)),
|
||||
('activer_billetterie', models.BooleanField(default=True, verbose_name='Activer la billetterie')),
|
||||
('jauge_max', models.PositiveSmallIntegerField(default=50, verbose_name='Jauge maximale')),
|
||||
('server_cashless', models.URLField(blank=True, max_length=300, null=True, verbose_name='Adresse du serveur Cashless')),
|
||||
('key_cashless', models.CharField(blank=True, max_length=41, null=True, verbose_name="Clé d'API du serveur cashless")),
|
||||
('option_generale_checkbox', models.ManyToManyField(blank=True, related_name='checkbox', to='BaseBillet.OptionGenerale')),
|
||||
|
|
@ -146,9 +137,4 @@ class Migration(migrations.Migration):
|
|||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='vat',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='BaseBillet.VAT', verbose_name='TVA'),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.2 on 2021-10-24 10:31
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('BaseBillet', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='price',
|
||||
name='product',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='prices', to='BaseBillet.Product'),
|
||||
),
|
||||
]
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 2.2 on 2021-10-24 10:40
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('BaseBillet', '0002_auto_20211024_1431'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='event',
|
||||
name='tarifs',
|
||||
),
|
||||
]
|
||||
|
|
@ -43,10 +43,10 @@ def poids_option_generale(sender, instance: OptionGenerale, created, **kwargs):
|
|||
|
||||
|
||||
class Configuration(SingletonModel):
|
||||
organisation = models.CharField(max_length=50)
|
||||
short_description = models.CharField(max_length=250)
|
||||
organisation = models.CharField(max_length=50, verbose_name=_("Nom de l'organisation"))
|
||||
short_description = models.CharField(max_length=250, verbose_name=_("Description courte"))
|
||||
|
||||
adresse = models.CharField(max_length=250)
|
||||
adress = models.CharField(max_length=250)
|
||||
phone = models.CharField(max_length=20)
|
||||
email = models.EmailField()
|
||||
|
||||
|
|
@ -57,7 +57,6 @@ class Configuration(SingletonModel):
|
|||
instagram = models.URLField(blank=True, null=True)
|
||||
|
||||
adhesion_obligatoire = models.BooleanField(default=False)
|
||||
cadeau_adhesion = models.FloatField(default=0, help_text="Recharge cadeau a l'adhésion")
|
||||
|
||||
carte_restaurant = StdImageField(upload_to='images/',
|
||||
null=True, blank=True,
|
||||
|
|
@ -69,7 +68,7 @@ class Configuration(SingletonModel):
|
|||
'thumbnail': (150, 90),
|
||||
},
|
||||
delete_orphans=True,
|
||||
verbose_name='Carte du restaurant'
|
||||
verbose_name=_('Carte du restaurant')
|
||||
)
|
||||
|
||||
img = StdImageField(upload_to='images/',
|
||||
|
|
@ -92,9 +91,9 @@ class Configuration(SingletonModel):
|
|||
stripe_test_api_key = models.CharField(max_length=110, blank=True, null=True)
|
||||
stripe_mode_test = models.BooleanField(default=True)
|
||||
|
||||
activer_billetterie = models.BooleanField(default=True)
|
||||
activer_billetterie = models.BooleanField(default=True, verbose_name=_("Activer la billetterie"))
|
||||
|
||||
jauge_max = models.PositiveSmallIntegerField(default=50)
|
||||
jauge_max = models.PositiveSmallIntegerField(default=50, verbose_name=_("Jauge maximale"))
|
||||
|
||||
option_generale_radio = models.ManyToManyField(OptionGenerale,
|
||||
blank=True,
|
||||
|
|
@ -108,56 +107,22 @@ class Configuration(SingletonModel):
|
|||
max_length=300,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Adresse du serveur Cashless"
|
||||
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"
|
||||
verbose_name=_("Clé d'API du serveur cashless")
|
||||
)
|
||||
|
||||
|
||||
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()
|
||||
|
||||
reservation_par_user_max = models.PositiveSmallIntegerField(default=6)
|
||||
|
||||
def range_max(self):
|
||||
return range(self.reservation_par_user_max + 1)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name}"
|
||||
|
||||
|
||||
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:
|
||||
verbose_name = _('TVA')
|
||||
verbose_name_plural = _('TVA')
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.percent}%"
|
||||
|
||||
|
||||
class Article(models.Model):
|
||||
class Product(models.Model):
|
||||
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True, db_index=True)
|
||||
|
||||
name = models.CharField(max_length=50)
|
||||
prix = models.FloatField()
|
||||
stock = models.SmallIntegerField(blank=True, null=True)
|
||||
|
||||
reservation_par_user_max = models.PositiveSmallIntegerField(default=10)
|
||||
vat = models.ForeignKey(VAT, on_delete=models.PROTECT, verbose_name="TVA", null=True, blank=True)
|
||||
|
||||
publish = models.BooleanField(default=False)
|
||||
|
||||
|
|
@ -188,11 +153,11 @@ class Article(models.Model):
|
|||
verbose_name=_("Type d'article"))
|
||||
|
||||
id_product_stripe = models.CharField(max_length=30, null=True, blank=True)
|
||||
id_price_stripe = models.CharField(max_length=30, null=True, blank=True)
|
||||
|
||||
def range_max(self):
|
||||
return range(self.reservation_par_user_max + 1)
|
||||
def __str__(self):
|
||||
return f"{self.name}"
|
||||
|
||||
'''
|
||||
def get_id_product_stripe(self):
|
||||
configuration = Configuration.get_solo()
|
||||
if configuration.stripe_api_key and not self.id_product_stripe:
|
||||
|
|
@ -204,6 +169,7 @@ class Article(models.Model):
|
|||
if self.img:
|
||||
# noinspection PyUnresolvedReferences
|
||||
domain_url = connection.tenant.domains.all()[0].domain
|
||||
# noinspection PyUnresolvedReferences
|
||||
images = [f"https://{domain_url}{self.img.med.url}", ]
|
||||
else:
|
||||
images = []
|
||||
|
|
@ -248,6 +214,37 @@ class Article(models.Model):
|
|||
self.id_price_stripe = None
|
||||
self.id_product_stripe = None
|
||||
self.save()
|
||||
'''
|
||||
|
||||
|
||||
class Price(models.Model):
|
||||
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True, db_index=True)
|
||||
|
||||
product = models.ForeignKey(Product, on_delete=models.PROTECT, related_name="prices")
|
||||
|
||||
name = models.CharField(max_length=50)
|
||||
prix = models.FloatField()
|
||||
|
||||
NA, DIX, VINGT = 'NA', 'DX', 'VG'
|
||||
TVA_CHOICES = [
|
||||
(NA, _('Non applicable')),
|
||||
(DIX, _("10 %")),
|
||||
(VINGT, _('20 %')),
|
||||
]
|
||||
|
||||
vat = models.CharField(max_length=2,
|
||||
choices=TVA_CHOICES,
|
||||
default=NA,
|
||||
verbose_name=_("Taux TVA"),
|
||||
)
|
||||
|
||||
id_price_stripe = models.CharField(max_length=30, null=True, blank=True)
|
||||
|
||||
stock = models.SmallIntegerField(blank=True, null=True)
|
||||
max_per_user = models.PositiveSmallIntegerField(default=10)
|
||||
|
||||
def range_max(self):
|
||||
return range(self.max_per_user + 1)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name}"
|
||||
|
|
@ -255,12 +252,14 @@ 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)
|
||||
datetime = models.DateTimeField()
|
||||
|
||||
short_description = models.CharField(max_length=250)
|
||||
long_description = models.TextField(blank=True, null=True)
|
||||
datetime = models.DateTimeField()
|
||||
tarifs = models.ManyToManyField(TarifBillet)
|
||||
articles = models.ManyToManyField(Article, blank=True)
|
||||
|
||||
products = models.ManyToManyField(Product, blank=True)
|
||||
|
||||
img = StdImageField(upload_to='images/',
|
||||
validators=[MaxSizeValidator(1920, 1920)],
|
||||
|
|
@ -286,7 +285,7 @@ class Event(models.Model):
|
|||
]
|
||||
|
||||
categorie = models.CharField(max_length=3, choices=TYPE_CHOICES, default=CONCERT,
|
||||
verbose_name=_("Catégorie d'évènement"))
|
||||
verbose_name=_("Catégorie d'évènement"))
|
||||
|
||||
def complet(self):
|
||||
# TODO: Benchmarker et tester si c'est pas mieux dans template
|
||||
|
|
@ -343,8 +342,8 @@ class Reservation(models.Model):
|
|||
def total_prix(self):
|
||||
total = 0
|
||||
for ligne in self.lignearticle_set.all():
|
||||
if ligne.article:
|
||||
total += ligne.qty * ligne.article.prix
|
||||
if ligne.product:
|
||||
total += ligne.qty * ligne.product.prix
|
||||
if ligne.billet:
|
||||
total += ligne.qty * ligne.billet.prix
|
||||
|
||||
|
|
@ -357,6 +356,7 @@ class Reservation(models.Model):
|
|||
@receiver(post_save, sender=Reservation)
|
||||
def verif_mail_valide(sender, instance: Reservation, created, **kwargs):
|
||||
if created:
|
||||
# noinspection PyUnresolvedReferences
|
||||
if not instance.user_commande.is_active:
|
||||
instance.status = instance.MAIL_NON_VALIDEE
|
||||
instance.save()
|
||||
|
|
@ -364,10 +364,12 @@ def verif_mail_valide(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, 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(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)
|
||||
|
||||
product = models.ForeignKey(Product, on_delete=models.CASCADE, blank=True, null=True)
|
||||
qty = models.SmallIntegerField()
|
||||
|
||||
reservation = models.ForeignKey(Reservation, on_delete=models.CASCADE, blank=True, null=True)
|
||||
carte = models.ForeignKey(CarteCashless, on_delete=models.PROTECT, blank=True, null=True)
|
||||
|
||||
paiement_stripe = models.ForeignKey(Paiement_stripe, on_delete=models.PROTECT, blank=True, null=True)
|
||||
|
|
|
|||
|
|
@ -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, TarifBillet
|
||||
from BaseBillet.models import OptionGenerale, Configuration, Event, Product, Price
|
||||
|
||||
|
||||
class ReservationValidator(serializers.Serializer):
|
||||
|
|
@ -16,7 +16,7 @@ class ReservationValidator(serializers.Serializer):
|
|||
|
||||
def validate_articles(self, value):
|
||||
value_dict = {}
|
||||
art_obj = Article.objects.all()
|
||||
art_obj = Product.objects.all()
|
||||
for couple in value:
|
||||
pk, qty = art_obj.get(pk=couple.split(',')[0]), int(couple.split(',')[1])
|
||||
value_dict[pk] = qty
|
||||
|
|
@ -25,14 +25,14 @@ class ReservationValidator(serializers.Serializer):
|
|||
|
||||
def validate_billets(self, value):
|
||||
value_dict = {}
|
||||
billet_obj = TarifBillet.objects.all()
|
||||
billet_obj = Price.objects.all()
|
||||
for couple in value:
|
||||
pk, qty = billet_obj.get(pk=couple.split(',')[0]), int(couple.split(',')[1])
|
||||
value_dict[pk] = qty
|
||||
|
||||
return value_dict
|
||||
#
|
||||
# # if value <= configuration.reservation_par_user_max :
|
||||
# # if value <= configuration.max_per_user :
|
||||
# return value
|
||||
# else :
|
||||
# raise serializers.ValidationError(_(f"Pas plus de {configuration.reservation_par_user_max} places en même temps."))
|
||||
# raise serializers.ValidationError(_(f"Pas plus de {configuration.max_per_user} places en même temps."))
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ def creation_de_la_reservation(user: TibilletUser, event: Event, data):
|
|||
qty = qty,
|
||||
)
|
||||
|
||||
for article in data.get('articles'):
|
||||
qty = data.get('articles')[article]
|
||||
for article in data.get('products'):
|
||||
qty = data.get('products')[article]
|
||||
LigneArticle.objects.create(
|
||||
reservation = reservation,
|
||||
article = article,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class Paiement_stripe(models.Model):
|
|||
return self.uuid_8()
|
||||
|
||||
def articles(self):
|
||||
return " - ".join([ f"{ligne.article.name} {ligne.qty * ligne.article.prix }€" for ligne in self.lignearticle_set.all() ])
|
||||
return " - ".join([ f"{ligne.product.name} {ligne.qty * ligne.product.prix }€" for ligne in self.lignearticle_set.all()])
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class creation_paiement_stripe():
|
|||
def _total(self):
|
||||
total = 0
|
||||
for ligne in self.liste_ligne_article:
|
||||
total += float(ligne.qty) * float(ligne.article.prix)
|
||||
total += float(ligne.qty) * float(ligne.product.prix)
|
||||
return total
|
||||
|
||||
def _paiement_stripe_db(self):
|
||||
|
|
@ -96,7 +96,7 @@ class creation_paiement_stripe():
|
|||
ligne: LigneArticle
|
||||
line_items.append(
|
||||
{
|
||||
"price": f"{ligne.article.get_id_price_stripe()}",
|
||||
"price": f"{ligne.product.get_id_price_stripe()}",
|
||||
"quantity": int(ligne.qty),
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from rest_framework.generics import get_object_or_404
|
|||
from django.views import View
|
||||
from rest_framework import status
|
||||
|
||||
from BaseBillet.models import Configuration, Article, LigneArticle
|
||||
from BaseBillet.models import Configuration, Product, LigneArticle
|
||||
from PaiementStripe.models import Paiement_stripe
|
||||
from PaiementStripe.views import creation_paiement_stripe
|
||||
from QrcodeCashless.models import CarteCashless
|
||||
|
|
@ -95,7 +95,7 @@ class index_scan(View):
|
|||
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.")
|
||||
"L'adress du serveur cashless n'est pas renseignée dans la configuration de la billetterie.")
|
||||
if not configuration.stripe_api_key or not configuration.stripe_test_api_key:
|
||||
return HttpResponse(
|
||||
"Pas d'information de configuration pour paiement en ligne.")
|
||||
|
|
@ -114,7 +114,7 @@ class index_scan(View):
|
|||
request,
|
||||
self.template_name,
|
||||
{
|
||||
'tarifs_adhesion': Article.objects.filter(categorie_article=Article.ADHESION).order_by('-prix'),
|
||||
'tarifs_adhesion': Product.objects.filter(categorie_article=Product.ADHESION).order_by('-prix'),
|
||||
'adhesion_obligatoire': configuration.adhesion_obligatoire,
|
||||
'history': json_reponse.get('history'),
|
||||
'carte_resto': configuration.carte_restaurant,
|
||||
|
|
@ -163,10 +163,10 @@ class index_scan(View):
|
|||
metadata = {}
|
||||
metadata['recharge_carte_uuid'] = str(carte.uuid)
|
||||
if montant_recharge:
|
||||
art, created = Article.objects.get_or_create(
|
||||
art, created = Product.objects.get_or_create(
|
||||
name="Recharge Carte",
|
||||
prix=1,
|
||||
categorie_article=Article.RECHARGE_CASHLESS,
|
||||
categorie_article=Product.RECHARGE_CASHLESS,
|
||||
)
|
||||
|
||||
ligne_article_recharge = LigneArticle.objects.create(
|
||||
|
|
@ -180,7 +180,7 @@ class index_scan(View):
|
|||
metadata['recharge_carte_montant'] = str(montant_recharge)
|
||||
|
||||
if pk_adhesion:
|
||||
art_adhesion = Article.objects.get(pk=data.get('pk_adhesion'))
|
||||
art_adhesion = Product.objects.get(pk=data.get('pk_adhesion'))
|
||||
ligne_article_recharge = LigneArticle.objects.create(
|
||||
article=art_adhesion,
|
||||
qty=1,
|
||||
|
|
@ -265,11 +265,11 @@ def changement_paid_to_valid(sender, instance: Paiement_stripe, update_fields=No
|
|||
if ligne_article.carte :
|
||||
data_pour_serveur_cashless['uuid'] = ligne_article.carte.uuid
|
||||
|
||||
if ligne_article.article.categorie_article == Article.RECHARGE_CASHLESS :
|
||||
if ligne_article.product.categorie_article == Product.RECHARGE_CASHLESS :
|
||||
data_pour_serveur_cashless['recharge_qty'] = float(ligne_article.qty)
|
||||
|
||||
if ligne_article.article.categorie_article == Article.ADHESION :
|
||||
data_pour_serveur_cashless['tarif_adhesion'] = ligne_article.article.prix
|
||||
if ligne_article.product.categorie_article == Product.ADHESION :
|
||||
data_pour_serveur_cashless['tarif_adhesion'] = ligne_article.product.prix
|
||||
|
||||
# si il y a autre chose que uuid_commande :
|
||||
if len(data_pour_serveur_cashless) > 1 :
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Pour en savoir plus : https://www.tibillet.re & https://wiki.tibillet.re
|
|||
|
||||
## Introduction.
|
||||
|
||||
TiBillet est en période d'Alpha, et en expérimentation sur plusieurs lieux sur l'ile de la Réunion. Venez nous voir au
|
||||
TiBillet est en période de BETA et en expérimentation sur plusieurs lieux sur l'ile de la Réunion. Venez nous voir au
|
||||
Bisik, à la Raffinerie, à Vavang'Art et au Manapany Festival !
|
||||
|
||||
Le présent dépot ne contient pas encore toutes les sources du projet. La billetterie est en cours de refactoring et les
|
||||
|
|
|
|||
Loading…
Reference in New Issue