"""Main app models.""" from typing import Iterable from django.conf import settings from django.contrib.contenttypes import fields as generic from django.contrib.contenttypes.models import ContentType from django.contrib.postgres.fields import JSONField from django.core.validators import EMPTY_VALUES from django.db import models from django.db.models import Q from django.utils.translation import gettext_lazy as _ from configuration.models import TranslationSettings from location.models import Country from main import methods from review.models import Review from utils.models import (ProjectBaseMixin, TJSONField, URLImageMixin, TranslatedFieldsMixin, PlatformMixin) class Currency(TranslatedFieldsMixin, models.Model): """Currency model.""" name = TJSONField( _('name'), null=True, blank=True, default=None, help_text='{"en-GB":"some text"}') sign = models.CharField(_('sign'), max_length=255) slug = models.SlugField(max_length=255, unique=True) code = models.CharField(max_length=5, unique=True, null=True, default=None) class Meta: verbose_name = _('currency') verbose_name_plural = _('currencies') def __str__(self): return f'{self.name}' class SiteSettingsQuerySet(models.QuerySet): """Extended queryset for SiteSettings model.""" def with_country(self): return self.filter(country__isnull=False) def by_country_code(self, code): return self.filter(country__code=code) class SiteSettings(ProjectBaseMixin): subdomain = models.CharField(max_length=255, db_index=True, unique=True, verbose_name=_('Subdomain')) country = models.OneToOneField(Country, on_delete=models.PROTECT, null=True, blank=True, default=None, verbose_name=_('Country')) default_site = models.BooleanField(default=False, verbose_name=_('Default site')) pinterest_page_url = models.URLField(blank=True, null=True, default=None, verbose_name=_('Pinterest page URL')) twitter_page_url = models.URLField(blank=True, null=True, default=None, verbose_name=_('Twitter page URL')) facebook_page_url = models.URLField(blank=True, null=True, default=None, verbose_name=_('Facebook page URL')) instagram_page_url = models.URLField(blank=True, null=True, default=None, verbose_name=_('Instagram page URL')) contact_email = models.EmailField(blank=True, null=True, default=None, verbose_name=_('Contact email')) config = JSONField(blank=True, null=True, default=None, verbose_name=_('Config')) ad_config = models.TextField(blank=True, null=True, default=None, verbose_name=_('AD config')) currency = models.ForeignKey(Currency, on_delete=models.PROTECT, null=True, default=None) old_id = models.IntegerField(blank=True, null=True) objects = SiteSettingsQuerySet.as_manager() class Meta: """Meta class.""" verbose_name = _('Site setting') verbose_name_plural = _('Site settings') def __str__(self): return f'ID: "{self.id}". Site: "{self.subdomain}"' @property def published_features(self): return self.feature_set.filter(sitefeature__site_settings=self, sitefeature__published=True) @property def published_sitefeatures(self): return self.sitefeature_set. \ filter(Q(published=True) & Q(feature__source__in=[PlatformMixin.WEB, PlatformMixin.ALL])) @property def site_url(self): return methods.site_url(schema=settings.SCHEMA_URI, subdomain=self.subdomain, domain=settings.SITE_DOMAIN_URI) class Feature(ProjectBaseMixin, PlatformMixin): """Feature model.""" slug = models.SlugField(max_length=255, unique=True) priority = models.IntegerField(unique=True, null=True, default=None) route = models.ForeignKey('PageType', on_delete=models.PROTECT, null=True, default=None) site_settings = models.ManyToManyField(SiteSettings, through='SiteFeature') old_id = models.IntegerField(null=True, blank=True) class Meta: """Meta class.""" verbose_name = _('Feature') verbose_name_plural = _('Features') def __str__(self): return f'{self.slug}' class SiteFeatureQuerySet(models.QuerySet): """Extended queryset for SiteFeature model.""" def published(self, switcher=True): return self.filter(published=switcher) def by_country_code(self, country_code: str): return self.filter(site_settings__country__code=country_code) def by_sources(self, sources: Iterable[int]): return self.filter(feature__source__in=sources) class SiteFeature(ProjectBaseMixin): """SiteFeature model.""" site_settings = models.ForeignKey(SiteSettings, on_delete=models.CASCADE) feature = models.ForeignKey(Feature, on_delete=models.PROTECT) published = models.BooleanField(default=False, verbose_name=_('Published')) main = models.BooleanField(default=False, verbose_name=_('Main')) nested = models.ManyToManyField('self', symmetrical=False) old_id = models.IntegerField(null=True, blank=True) objects = SiteFeatureQuerySet.as_manager() class Meta: """Meta class.""" verbose_name = _('Site feature') verbose_name_plural = _('Site features') unique_together = ('site_settings', 'feature') class Award(TranslatedFieldsMixin, URLImageMixin, models.Model): """Award model.""" WAITING = 0 PUBLISHED = 1 STATE_CHOICES = ( (WAITING, 'waiting'), (PUBLISHED, 'published') ) award_type = models.ForeignKey('main.AwardType', on_delete=models.CASCADE) title = TJSONField( _('title'), null=True, blank=True, default=None, help_text='{"en-GB":"some text"}') vintage_year = models.CharField(_('vintage year'), max_length=255, default='') content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey('content_type', 'object_id') state = models.PositiveSmallIntegerField(default=WAITING, choices=STATE_CHOICES, verbose_name=_('State')) old_id = models.IntegerField(null=True, blank=True) def __str__(self): title = 'None' lang = TranslationSettings.get_solo().default_language if self.title and lang in self.title: title = self.title[lang] return f'id:{self.id}-{title}' class AwardType(models.Model): """AwardType model.""" country = models.ForeignKey( 'location.Country', verbose_name=_('country'), on_delete=models.CASCADE) name = models.CharField(_('name'), max_length=255) old_id = models.IntegerField(null=True, blank=True) def __str__(self): return self.name class CarouselQuerySet(models.QuerySet): """Carousel QuerySet.""" def is_parsed(self): """Parsed carousel objects.""" return self.filter(is_parse=True) def active(self): """Active carousel objects.""" return self.filter(active=True) def by_country_code(self, code): """Filter collection by country code.""" return self.filter(country__code=code) class Carousel(models.Model): """Carousel model.""" content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, blank=True, null=True, default=None) object_id = models.PositiveIntegerField(blank=True, null=True, default=None) content_object = generic.GenericForeignKey('content_type', 'object_id') old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None) title = models.CharField(_('old title'), max_length=255, blank=True, null=True, default=None) link = models.CharField(_('old link'), max_length=255, blank=True, null=True, default=None) attachment_suffix_url = models.TextField(_('old attachment_suffix_url'), blank=True, null=True, default=None) description = models.CharField(_('old description'), max_length=255, blank=True, null=True, default=None) link_title = models.CharField(_('old link_title'), max_length=255, blank=True, null=True, default=None) country = models.ForeignKey( Country, blank=True, null=True, on_delete=models.SET_NULL, verbose_name=_('country') ) active = models.BooleanField(_('old active'), default=False) is_parse = models.BooleanField(_('is parse'), default=False) objects = CarouselQuerySet.as_manager() class Meta: """Meta class.""" verbose_name = _('Carousel') verbose_name_plural = _('Carousel') @property def name(self): # Check if Generic obj has name or title if hasattr(self.content_object, 'name'): return self.content_object.name if hasattr(self.content_object, 'title'): return self.content_object.title_translated @property def awards(self): if hasattr(self.content_object, 'awards'): return self.content_object.awards @property def vintage_year(self): if hasattr(self.content_object, 'reviews'): last_review = self.content_object.reviews.by_status(Review.READY).last() if last_review: return last_review.vintage @property def toque_number(self): if hasattr(self.content_object, 'toque_number'): return self.content_object.toque_number @property def public_mark(self): if hasattr(self.content_object, 'public_mark'): return self.content_object.public_mark @property def image_url(self): if self.attachment_suffix_url: return f'https://s3.eu-central-1.amazonaws.com/gm-test.com/media/{self.attachment_suffix_url}' if hasattr(self.content_object, 'image_url'): return self.content_object.image_url @property def slug(self): if hasattr(self.content_object, 'slug'): return self.content_object.slug @property def the_most_recent_award(self): if hasattr(self.content_object, 'the_most_recent_award'): return self.content_object.the_most_recent_award @property def model_name(self): from establishment.models import Establishment from news.models import News if isinstance(self.content_object, Establishment): return self.content_object.establishment_type.index_name elif isinstance(self.content_object, News): return self.content_type.model elif self.link not in EMPTY_VALUES: return 'external' return None class PageQuerySet(models.QuerySet): """QuerySet for model Page.""" def by_platform(self, platform: int): """Filter by platform.""" return self.filter(source=platform) class Page(URLImageMixin, PlatformMixin, ProjectBaseMixin): """Page model.""" advertisement = models.ForeignKey('advertisement.Advertisement', on_delete=models.PROTECT, null=True, related_name='pages', verbose_name=_('advertisement')) width = models.PositiveIntegerField(null=True, verbose_name=_('Block width')) # 300 height = models.PositiveIntegerField(null=True, verbose_name=_('Block height')) # 250 objects = PageQuerySet.as_manager() class Meta: """Meta class.""" verbose_name = _('page') verbose_name_plural = _('pages') def __str__(self): """Overridden dunder method.""" return self.get_source_display() class PageTypeQuerySet(models.QuerySet): """QuerySet for model PageType.""" class PageType(ProjectBaseMixin): """Page type model.""" name = models.CharField(max_length=255, unique=True, verbose_name=_('name')) objects = PageTypeQuerySet.as_manager() class Meta: """Meta class.""" verbose_name = _('page type') verbose_name_plural = _('page types') def __str__(self): """Overridden dunder method.""" return self.name