diff --git a/apps/booking/models/services.py b/apps/booking/models/services.py index 5f48f15f..e6a2dd46 100644 --- a/apps/booking/models/services.py +++ b/apps/booking/models/services.py @@ -27,10 +27,12 @@ class AbstractBookingService(ABC): self.url = settings.LASTABLE_SERVICE @staticmethod - def get_certain_keys(d: dict, keys_to_preserve: set, required=True) -> dict: + def get_certain_keys(d: dict, keys_to_preserve: set, required: set = {}, check: bool = True) -> dict: """ Helper """ - if required: - diff = keys_to_preserve - d.keys() + if len(required) == 0 and check: + required = keys_to_preserve.copy() + if required and check: + diff = required - d.keys() if diff: raise serializers.ValidationError({field: _(f'This field is required') for field in diff}) return {key: d[key] for key in d.keys() & keys_to_preserve} diff --git a/apps/booking/views.py b/apps/booking/views.py index 6e850f3b..653503e7 100644 --- a/apps/booking/views.py +++ b/apps/booking/views.py @@ -96,13 +96,15 @@ class UpdatePendingBooking(generics.UpdateAPIView): data['pending_booking_id'] = instance.pending_booking_id r = service.update_booking(service.get_certain_keys(data, { 'email', 'phone', 'last_name', 'first_name', 'country_code', 'pending_booking_id', 'note', + }, { + 'email', 'phone', 'last_name', 'first_name', 'country_code', 'pending_booking_id', })) if isinstance(r, Response): return r if data.get('newsletter'): Subscriber.objects.make_subscriber(email=data['email'], country_code=data['country_code'], locale=request.locale, ip_address=get_user_ip(request), - user=request.user) + user=None if request.user.is_anonymous else request.user) if service.response: # если есть предоплата, возвращаем фронту страйп-ключ для совершения оплаты и цену amount = service.response.get('amount') diff --git a/apps/tag/filters.py b/apps/tag/filters.py index 8816f820..ad53e18d 100644 --- a/apps/tag/filters.py +++ b/apps/tag/filters.py @@ -40,3 +40,32 @@ class TagCategoryFilterSet(filters.FilterSet): # todo: filter by establishment type def by_establishment_type(self, queryset, name, value): return queryset.by_establishment_type(value) + + +class TagsFilterSet(filters.FilterSet): + """Chosen tags filterset.""" + + # Object type choices + NEWS = 'news' + ESTABLISHMENT = 'establishment' + + TYPE_CHOICES = ( + (NEWS, 'News'), + (ESTABLISHMENT, 'Establishment'), + ) + + type = filters.MultipleChoiceFilter(choices=TYPE_CHOICES, + method='filter_by_type') + + class Meta: + """Meta class.""" + + model = models.Tag + fields = ('type',) + + def filter_by_type(self, queryset, name, value): + if self.NEWS in value: + queryset = queryset.for_news() + if self.ESTABLISHMENT in value: + queryset = queryset.for_establishments() + return queryset diff --git a/apps/tag/migrations/0008_auto_20191101_1244.py b/apps/tag/migrations/0008_auto_20191101_1244.py new file mode 100644 index 00000000..94ff0b96 --- /dev/null +++ b/apps/tag/migrations/0008_auto_20191101_1244.py @@ -0,0 +1,37 @@ +# Generated by Django 2.2.4 on 2019-11-01 12:44 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('location', '0020_merge_20191030_1714'), + ('tag', '0007_auto_20191030_1514'), + ] + + operations = [ + migrations.RemoveField( + model_name='tag', + name='priority', + ), + migrations.CreateModel( + name='ChosenTagSettings', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('priority', models.IntegerField(default=0)), + ('country', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='location.Country')), + ('tag', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='tag.Tag')), + ], + options={ + 'verbose_name': 'Tag', + 'verbose_name_plural': 'Tags', + }, + ), + migrations.AddField( + model_name='tag', + name='chosen_tag_settings', + field=models.ManyToManyField(through='tag.ChosenTagSettings', to='location.Country'), + ), + ] diff --git a/apps/tag/models.py b/apps/tag/models.py index e3967f0f..8c248a04 100644 --- a/apps/tag/models.py +++ b/apps/tag/models.py @@ -1,16 +1,26 @@ """Tag app models.""" +from django.contrib.contenttypes.models import ContentType from django.db import models from django.utils.translation import gettext_lazy as _ + from configuration.models import TranslationSettings +from location.models import Country from utils.models import TJSONField, TranslatedFieldsMixin class TagQuerySet(models.QuerySet): - def filter_chosen(self): - return self.exclude(priority__isnull=True) + + def for_news(self): + """Select chosen tags for news.""" + return self.filter(category__news_types__isnull=False) + + def for_establishments(self): + """Select chosen tags for establishments.""" + return self.filter(models.Q(category__establishment_types__isnull=False) | + models.Q(category__establishment_subtypes__isnull=False)) def order_by_priority(self): - return self.order_by('priority') + return self.order_by('chosentagsettings__priority') class Tag(TranslatedFieldsMixin, models.Model): @@ -24,7 +34,8 @@ class Tag(TranslatedFieldsMixin, models.Model): category = models.ForeignKey('TagCategory', on_delete=models.CASCADE, null=True, related_name='tags', verbose_name=_('Category')) - priority = models.IntegerField(unique=True, null=True, default=None) + + chosen_tag_settings = models.ManyToManyField(Country, through='ChosenTagSettings') objects = TagQuerySet.as_manager() @@ -35,11 +46,29 @@ class Tag(TranslatedFieldsMixin, models.Model): verbose_name_plural = _('Tags') def __str__(self): - label = 'None' - lang = TranslationSettings.get_solo().default_language - if self.label and lang in self.label: - label = self.label[lang] - return f'id:{self.id}-{label}' + return f'Tag (id = {self.id}, label_translated = {self.label_translated})' + + +class ChosenTagSettingsQuerySet(models.QuerySet): + + def by_country_code(self, country_code): + return self.filter(country__code=country_code) + + +class ChosenTagSettings(models.Model): + """Tag model.""" + + tag = models.ForeignKey(Tag, on_delete=models.PROTECT) + country = models.ForeignKey(Country, on_delete=models.PROTECT) + priority = models.IntegerField(null=False, default=0) + + objects = ChosenTagSettingsQuerySet.as_manager() + + class Meta: + """Meta class.""" + + verbose_name = _('Tag') + verbose_name_plural = _('Tags') class TagCategoryQuerySet(models.QuerySet): diff --git a/apps/tag/views.py b/apps/tag/views.py index 6d98f39f..e965f8b5 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -10,10 +10,14 @@ class ChosenTagsView(generics.ListAPIView, viewsets.GenericViewSet): pagination_class = None permission_classes = (permissions.AllowAny,) serializer_class = serializers.TagBaseSerializer + filterset_class = filters.TagsFilterSet def get_queryset(self): - return models.Tag.objects\ - .filter_chosen() \ + result_tags_ids = models.ChosenTagSettings.objects \ + .by_country_code(self.request.country_code) \ + .values('tag_id') + return models.Tag.objects \ + .filter(id__in=result_tags_ids) \ .order_by_priority() @@ -23,8 +27,8 @@ class TagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): filterset_class = filters.TagCategoryFilterSet pagination_class = None - permission_classes = (permissions.AllowAny, ) - queryset = models.TagCategory.objects.with_tags().with_base_related().\ + permission_classes = (permissions.AllowAny,) + queryset = models.TagCategory.objects.with_tags().with_base_related(). \ distinct() serializer_class = serializers.TagCategoryBaseSerializer @@ -62,7 +66,7 @@ class TagBackOfficeViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, """List/create tag view.""" pagination_class = None - permission_classes = (permissions.IsAuthenticated, ) + permission_classes = (permissions.IsAuthenticated,) queryset = models.Tag.objects.all() serializer_class = serializers.TagBackOfficeSerializer bind_object_serializer_class = serializers.TagBindObjectSerializer @@ -96,7 +100,7 @@ class TagCategoryBackOfficeViewSet(mixins.CreateModelMixin, TagCategoryViewSet): """ViewSet for TagCategory model for BackOffice users.""" - permission_classes = (permissions.IsAuthenticated, ) + permission_classes = (permissions.IsAuthenticated,) queryset = TagCategoryViewSet.queryset.with_extended_related() serializer_class = serializers.TagCategoryBackOfficeDetailSerializer bind_object_serializer_class = serializers.TagCategoryBindObjectSerializer