from django.contrib.auth import get_user_model from django.db import connection from django.utils.text import slugify from rest_framework import serializers import json from django.utils.translation import gettext, gettext_lazy as _ from rest_framework.generics import get_object_or_404 from AuthBillet.models import TibilletUser, HumanUser from BaseBillet.models import Event, Price, Product, Reservation, Configuration, LigneArticle, Ticket, Paiement_stripe from PaiementStripe.views import creation_paiement_stripe import logging logger = logging.getLogger(__name__) class ProductSerializer(serializers.ModelSerializer): class Meta: model = Product fields = [ "uuid", "name", "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 ConfigurationSerializer(serializers.ModelSerializer): class Meta: model = Configuration fields = [ "organisation", "short_description", "long_description", "adress", "phone", "email", "site_web", "twitter", "facebook", "instagram", "adhesion_obligatoire", "button_adhesion", "name_required_for_ticket", "map_img", "carte_restaurant", "img", "logo", ] read_only_fields = fields class EventSerializer(serializers.ModelSerializer): products = ProductSerializer( many=True, read_only=True ) class Meta: model = Event fields = [ 'uuid', 'name', 'slug', 'short_description', 'long_description', 'event_facebook_url', 'datetime', 'products', 'img', 'reservations', 'complet', ] read_only_fields = ['uuid', 'reservations'] depth = 1 def validate(self, attrs): # import ipdb; ipdb.set_trace() # slug = slugify(f"{self.initial_data.get('name')} {self.initial_data.get('datetime').strftime('%D %R')}") products = self.initial_data.get('products') if products: try: products_list = json.loads(products) except json.decoder.JSONDecodeError as e: raise serializers.ValidationError(_(f'products doit être un json valide : {e}')) 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(_('products doit être un json valide')) def save(self, **kwargs): instance = super().save(**kwargs) 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"} ] ''' class ReservationSerializer(serializers.ModelSerializer): class Meta: model = Reservation fields = [ 'uuid', 'datetime', 'user_commande', 'event', 'status', 'options', 'tickets', 'paiements', ] read_only_fields = [ 'uuid', 'datetime', 'status', ] depth = 1 class MembreshipValidator(serializers.Serializer): email = serializers.EmailField() first_name = serializers.CharField(max_length=200,) last_name = serializers.CharField(max_length=200,) phone = serializers.CharField(max_length=20, required=False) postal_code = serializers.IntegerField(required=False) birth_date = serializers.DateField(required=False) contribution_value = serializers.FloatField() def validate_email(self, value): User: TibilletUser = get_user_model() user_paiement, created = User.objects.get_or_create( email=value, username=value) if created: user_paiement: HumanUser user_paiement.client_source = connection.tenant user_paiement.client_achat.add(connection.tenant) user_paiement.is_active = False else: user_paiement.client_achat.add(connection.tenant) user_paiement.save() return user_paiement.email class ReservationValidator(serializers.Serializer): email = serializers.EmailField() event = serializers.PrimaryKeyRelatedField(queryset=Event.objects.all()) prices = serializers.JSONField(required=True) def validate_email(self, value): User: TibilletUser = get_user_model() user_paiement, created = User.objects.get_or_create( email=value, username=value) if created: user_paiement: HumanUser user_paiement.client_source = connection.tenant user_paiement.client_achat.add(connection.tenant) user_paiement.is_active = False else: user_paiement.client_achat.add(connection.tenant) user_paiement.save() self.user_commande = user_paiement return user_paiement.email def validate_prices(self, value): print(value) # on vérifie que chaque article existe et a sa quantité. # et qu'il y ai au moins un billet pour la reservation. config = Configuration.get_solo() self.nbr_ticket = 0 self.prices_list = [] for entry in value: try: price = Price.objects.get(pk=entry['uuid']) price_object = { 'price': price, 'qty': float(entry['qty']), } if price.product.categorie_article == Product.BILLET: self.nbr_ticket += entry['qty'] # Si les noms sont requis pour la billetterie if config.name_required_for_ticket and entry['qty'] > 0: if not entry.get('customers'): raise serializers.ValidationError(_(f'customers non trouvés')) if len(entry.get('customers')) != entry['qty']: raise serializers.ValidationError(_(f'nombre customers non conforme')) price_object['customers'] = entry.get('customers') self.prices_list.append(price_object) except Price.DoesNotExist as e: raise serializers.ValidationError(_(f'price non trouvé : {e}')) except ValueError as e: raise serializers.ValidationError(_(f'qty doit être un entier ou un flottant : {e}')) ''' products = [ { "uuid": "8c419d35-11a1-43b6-b500-b79db665d560", "qty": 2, "customers": [ { "first_name": "Jean-Michel", "last_name": "Amoitié" }, { "first_name": "Ellen", "last_name": "Ripley" } ] }, { "uuid": "c6e847d4-baaa-4d21-a4f0-a572b8319615", "qty": 1, "customers": [ { "first_name": "Douglas", "last_name": "Adams" } ] } ] products = [ { "uuid": "8c419d35-11a1-43b6-b500-b79db665d560", "qty": 2 }, { "uuid": "c6e847d4-baaa-4d21-a4f0-a572b8319615", "qty": 1 } ] ''' return value def validate(self, attrs): if self.nbr_ticket == 0: raise serializers.ValidationError(_(f'pas de billet dans la reservation')) event : Event = attrs.get('event') if event.complet() : raise serializers.ValidationError(_(f'Jauge atteinte : Evenement complet.')) config = Configuration.get_solo() reservation = Reservation.objects.create( user_commande=self.user_commande, event=event, ) lignes_article = [] for price in self.prices_list: ligne_article = LigneArticle.objects.create( price=price.get('price'), qty=price.get('qty'), ) lignes_article.append(ligne_article) if config.name_required_for_ticket and price.get('customers'): for customer in price.get('customers'): ticket = Ticket.objects.create( reservation=reservation, first_name=customer.get('first_name'), last_name=customer.get('last_name'), ) metadata = {'reservation':f'{reservation.uuid}'} new_paiement_stripe = creation_paiement_stripe( email_paiement=self.user_commande.email, liste_ligne_article=lignes_article, metadata=metadata, source=Paiement_stripe.API_BILLETTERIE, reservation=reservation, absolute_domain=self.context.get('request').build_absolute_uri().partition('/api')[0], ) if new_paiement_stripe.is_valid(): paiement_stripe : Paiement_stripe = new_paiement_stripe.paiement_stripe_db paiement_stripe.lignearticle_set.all().update(status=LigneArticle.UNPAID) reservation.tickets.all().update(status=Ticket.NOT_ACTIV) reservation.paiement = paiement_stripe reservation.status = Reservation.UNPAID reservation.save() print(new_paiement_stripe.checkout_session.stripe_id) # return new_paiement_stripe.redirect_to_stripe() self.checkout_session = new_paiement_stripe.checkout_session return super().validate(attrs) else: raise serializers.ValidationError(_(f'checkout strip not valid')) def to_representation(self, instance): representation = super().to_representation(instance) logger.info(f"{self.checkout_session.url}") representation['checkout_url'] = self.checkout_session.url # import ipdb;ipdb.set_trace() return representation