You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

399 lines
18 KiB

# -*- coding: utf-8 -*-
import copy, datetime
from django.db import models
from django.db.models import Q
from django.db.models.signals import post_save, pre_save
from django.utils.translation import ugettext as _
from django.utils import translation
from django.conf import settings
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from django.contrib.contenttypes import generic
from bitfield import BitField
from service.models import Service
from functions.db import db_table_exists
from organiser.models import Organiser
from manager import ClientManager
from functions.custom_fields import EnumField
from functions.signal_handlers import post_save_handler, pre_save_handler
from functions.models_methods import ExpoManager
from functions.model_mixin import EventMixin, ExpoMixin
from functions.translate import fill_with_signal
from photologue.models import Gallery
from import_xls.model_utils import ExpoImportManager
from functions.models_methods import hvad_to_dict
AUDIENCE1 = ((None,_(u'Не выбрано')),
('experts', _(u'Специалисты')),
('experts and consumers', _(u'Специалисты и потребители')),
('general public', _(u'Широкая публика'))
)
AUDIENCE = (None,'experts', 'experts and consumers', 'general public')
BIT_AUDIENCE = settings.BIT_AUDIENCE
CURRENCY = settings.CURRENCY
# check if table exist and create flags if true
flags = [item.url for item in Service.objects.all()] if db_table_exists('service_service') else []
class Exposition(TranslatableModel, EventMixin, ExpoMixin):
"""
Create Exposition model
Uses hvad.TranslatableModel which is child of django.db.models class
"""
catalog = '/expo/'
catalog_name = _(u'Выставки:')
search_name = None
# type of event
event_type = 'expo'
url = models.SlugField(unique=True, max_length=255)
old_url = models.SlugField(unique=True, max_length=255)
data_begin = models.DateField(verbose_name='Дата начала')
data_end = models.DateField(verbose_name='Дата окончания')
services = BitField(flags=flags)
# relations
country = models.ForeignKey('country.Country', verbose_name='Страна', on_delete=models.PROTECT,
related_name='exposition_country')
city = models.ForeignKey('city.City', verbose_name='Город', on_delete=models.PROTECT,
related_name='exposition_city')
place = models.ForeignKey('place_exposition.PlaceExposition', verbose_name='Место проведения',
blank=True, null=True, on_delete=models.PROTECT, related_name='exposition_place')
theme = models.ManyToManyField('theme.Theme', verbose_name='Тематики',
related_name='exposition_themes')
tag = models.ManyToManyField('theme.Tag', verbose_name='Теги',
blank=True, null=True, related_name='exposition_tags')
organiser = models.ManyToManyField('organiser.Organiser', verbose_name='Организатор',
blank=True, null=True, related_name='exposition_organisers')
org = models.CharField(max_length=255, blank=True, null=True)
place_alt = models.CharField(max_length=255, blank=True, null=True)
company = models.ManyToManyField('company.Company', verbose_name='Компании',
blank=True, null=True, related_name='exposition_companies')
users = models.ManyToManyField('accounts.User', verbose_name='Посетители выставки',
blank=True, null=True, related_name='exposition_users')
photogallery = models.ForeignKey('photologue.Gallery', blank=True, null=True)
logo = models.ImageField(verbose_name='Logo', upload_to='exposition/logo/', blank=True)
rating = models.IntegerField(default=0) # добавить индекс в базе
quality_label = BitField(flags=['ufi', 'rsva', 'exporating'])
visitors = models.PositiveIntegerField(verbose_name='Посетители', blank=True, null=True)
members = models.PositiveIntegerField(verbose_name='Участники', blank=True, null=True)
discount = models.PositiveIntegerField(verbose_name='Скидка', blank=True, null=True)
expohit = models.BooleanField(verbose_name='Expohit', default=0)
# administrator can cancel exposition
canceled_by_administrator = models.BooleanField(default=0)
#can publish not immediately
is_published = models.BooleanField(default=0)
canceled = models.BooleanField(default=0)
moved = models.BooleanField(default=0)
# field saves information about creating and changing model
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
main_page = models.PositiveIntegerField(default=0, db_index=True)
views = models.PositiveIntegerField(default=0)
translations = TranslatedFields(
name = models.CharField(verbose_name='Название', max_length=255),
main_title = models.TextField(verbose_name='Краткое описание', blank=True),
description = models.TextField(verbose_name='Описание', blank=True),
products = models.TextField(verbose_name='Экспонируемые продукты', blank=True),
discount_description = models.TextField(verbose_name='Описание скидки', blank=True),
time = models.TextField(verbose_name='Время работы', blank=True),
# visit and particaption data
price_day = models.CharField(verbose_name='Стоимость билета 1 день', max_length=255, blank=True),
price_all = models.CharField(verbose_name='Стоимость билета все дни', max_length=255, blank=True),
price_day_bar = models.CharField(verbose_name='Стоимость на стойке 1 день', max_length=255, blank=True),
price_all_bar = models.CharField(verbose_name='Стоимость на стойке все дни', max_length=255, blank=True),
stat_countries = models.TextField(verbose_name='Участвующие страны', blank=True),
pre_condition = models.CharField(verbose_name='Условия предварительной регистрации', max_length=255, blank=True),
stand_condition = models.CharField(verbose_name='Условия регистрации на стойке', max_length=255, blank=True),
visit_note = models.CharField(verbose_name='Примечание по посещению', max_length=255, blank=True),
participation_note = models.TextField(verbose_name='Примечание по участии', blank=True),
#-----meta data
title = models.CharField(max_length=250),
descriptions = models.CharField(max_length=250),
keywords = models.CharField(max_length=250),
)
files = generic.GenericRelation('file.FileModel', content_type_field='content_type', object_id_field='object_id')
note = generic.GenericRelation('note.Note', content_type_field='content_type', object_id_field='object_id')
#about
periodic = models.FloatField(verbose_name='Переодичность', blank=True, null=True)
audience = BitField(flags=[k for k, v in BIT_AUDIENCE])
web_page = models.CharField(verbose_name='Вебсайт', max_length=255, blank=True)
foundation_year = models.PositiveIntegerField(verbose_name='Год основания', blank=True, null=True)
area = models.PositiveIntegerField(verbose_name='Площадь', blank=True, null=True)
# conditions of Participation
registration_link = models.URLField(verbose_name='Ссылка на регистрацию', max_length=255, blank=True)
min_area = models.PositiveIntegerField(verbose_name='Минимальная площадь', blank=True, null=True)
currency = EnumField(values=CURRENCY, default='USD')
application_deadline = models.DateField(verbose_name='Срок подачи заявки', null=True)
min_stand_size = models.PositiveIntegerField(verbose_name='Минимальный размер стэнда', blank=True, null=True)
price_catalog = models.PositiveIntegerField(verbose_name='Стоимость каталога', blank=True, null=True)
tax = models.BooleanField(verbose_name='Налог', default=1)
min_closed_area = models.PositiveIntegerField(verbose_name='Минимальная цена закрытой НЕ оборудованной площади',
blank=True, null=True)
max_closed_area = models.PositiveIntegerField(verbose_name='Максимальная цена закрытой НЕ оборудованной площади',
blank=True, null=True)
min_closed_equipped_area = models.PositiveIntegerField(verbose_name='Минимальная цена закрытой оборудованной площади',
blank=True, null=True)
max_closed_equipped_area = models.PositiveIntegerField(verbose_name='Максимальная цена закрытой оборудованной площади',
blank=True, null=True)
min_open_area = models.PositiveIntegerField(verbose_name='Минимальная цена открытой площади',
blank=True, null=True)
max_open_area = models.PositiveIntegerField(verbose_name='Максимальная цена открытой площади',
blank=True, null=True)
registration_payment = models.PositiveIntegerField(verbose_name='Регистрационный взнос', blank=True, null=True)
paid_new = models.ForeignKey('expobanner.Paid', blank=True, null=True, on_delete=models.SET_NULL)
top = models.ForeignKey('expobanner.Top', blank=True, null=True, on_delete=models.SET_NULL)
main = models.ForeignKey('expobanner.MainPage', blank=True, null=True, on_delete=models.SET_NULL)
#set manager of this model(fisrt manager is default)
objects = ExpoManager()
enable = ClientManager()
imports = ExpoImportManager()
def __unicode__(self):
return self.lazy_translation_getter('name', unicode(self.pk))
def get_services(self):
country_ids = [item for item, bool in self.country.services if bool==True]
ids = [item for item, bool in self.services if bool==True]
qs = Service.objects.language().filter(Q(Q(url__in=country_ids) & Q(type=Service.type.expo)) | Q(url__in=ids))
return list(qs)
def get_parent(self):
return {}
def get_absolute_url(self):
return self.get_permanent_url()
def get_index_text(self):
translation.activate('ru')
translations = self.translations.all()
names = ' '.join([tr.name for tr in translations])
titles = ' '.join([tr.main_title for tr in translations])
themes = ' '.join([' '.join(theme.get_all_names()) for theme in self.theme.all()])
tags = ' '.join([' '.join(tag.get_all_names()) for tag in self.tag.all()])
return names + ' ' + titles + ' ' + themes + ' ' + tags
def get_note_by_user(self, user_id):
note = self.note.filter(user__id=user_id)
try:
return note.get().text
except:
return ''
def upload_photo_url(self):
return '/admin/exposition/upload-photo/%s/'%self.id
def get_gallery(self):
if self.photogallery:
return self.photogallery
data = {}
model = type(self)
for code, name in settings.LANGUAGES:
obj = model._meta.translations_model.objects.get(language_code = code,master__id=self.id) #access to translated fields
data['title_%s'%code] = obj.name
data['description_%s'%code] = obj.description
gallery = Gallery()
fill_with_signal(Gallery, gallery, data)
self.photogallery = gallery
self.save()
return gallery
def tags(self):
return self.tag.language().all()
def statistic_exists(self):
return Statistic.objects,filter(exposition=self).exists()
def upload_photo(self, photo ,gallery=None):
"""
uploading photo to gallery
"""
if gallery is None:
gallery = self.get_gallery()
gallery.photos.add(photo)
# def get_index_text(self):
# names = [tr.name for tr in self.translations.all()]
# return names
def get_audience(self):
checked = [item for item, bool in self.audience if bool==True]
audience = []
for k, v in BIT_AUDIENCE:
for item in checked:
if item == k:
audience.append(unicode(v))
return ', '.join(audience)
def get_periodic(self):
periodic = {0: '', 1.0: _(u'Ежегодно'), 2.0: _(u'2 раза в год'), 3.0: _(u'3 раза в год'),
4.0: _(u'4 раза в год'), 5.0: _(u'5 раз в год'), 0.5: _(u'Раз в 2 года'),
0.33: _(u'Раз в 3 года'), 0.25: _(u'Раз в 4 года')}
return periodic.get(self.periodic)
def get_nearest_events(self):
if self.theme.all():
theme = self.theme.all()[0]
now = datetime.datetime.now()
now = now - datetime.timedelta(days=1)
expositions = Exposition.objects.filter(theme__in=[theme], data_begin__gt=now).exclude(id=self.id).order_by('data_begin')
return expositions[:3]
else:
return []
def get_catalog_url(self):
return self.catalog
#return '/expositions/'
def get_event_type(self):
return _(u'Выставки')
def get_calendar_url(self):
return '/exposition-add-calendar/%s/'%self.id
def get_visit_url(self):
return '/exposition-visit/%s/'%self.id
def get_timetables_days(self):
tables = self.business_program.all()
days = []
for t in tables:
d = t.begin.replace(hour = 0, minute = 0, second = 0, microsecond = 0)
if not d in days:
days.append(d)
return days
def get_currency_html(self):
cur = self.currency
currency_codes = {'EUR':'', 'USD':'$', 'RUB':'ք'}
code = currency_codes.get(cur)
if code:
return code
return cur
def theme_ids(self):
return [item['id'] for item in self.theme.all().values('id')]
def get_main_link(self):
if self.main:
return self.main.link.get_click_link()
else:
return self.get_permanent_url()
def get_top_link(self):
if self.top:
return self.top.link.get_click_link()
else:
return self.get_permanent_url()
class Statistic(TranslatableModel):
exposition = models.ForeignKey(Exposition, related_name='statistic')
year = models.PositiveIntegerField(verbose_name='Год')
members = models.PositiveIntegerField(verbose_name='Посетители', blank=True, null=True)
visitors = models.PositiveIntegerField(verbose_name='Участники', blank=True, null=True)
area = models.PositiveIntegerField(verbose_name='Площадь', blank=True, null=True)
countries_number = models.PositiveIntegerField(verbose_name='Количество стран', blank=True, null=True)
translations = TranslatedFields(
countries = models.TextField(blank=True)
)
def to_dict(self):
return hvad_to_dict(self)
class TimeTable(TranslatableModel):
"""
TimeTable for business program
"""
exposition = models.ForeignKey(Exposition, related_name='business_program')
begin = models.DateTimeField(verbose_name='Начало')
end = models.DateTimeField(verbose_name='Конец')
timetable_organiser = models.ForeignKey(Organiser, null=True, blank=True)
#
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
#translated fields
translations = TranslatedFields(
name = models.CharField(verbose_name='Название программы', max_length=255, blank=True),
programe = models.TextField(verbose_name='Программа'),
speaker = models.CharField(verbose_name='Спикеры', max_length=255, blank=True),
place = models.CharField(verbose_name='Место проведения', max_length=255, blank=True)
)
def to_dict(self):
#obj = serializers.serialize('json', [self,])
return hvad_to_dict(self)
class TmpTimeTable(TranslatableModel):
exposition = models.ForeignKey(Exposition, null=True, blank=True)
begin = models.DateTimeField(verbose_name='Начало')
end = models.DateTimeField(verbose_name='Конец')
timetable_organiser = models.ForeignKey(Organiser, null=True, blank=True)
# key uses for checking keys from new objects.
key = models.CharField(max_length=255, blank=True)
#
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
#translated fields
translations = TranslatedFields(
name = models.CharField(verbose_name='Название программы', max_length=255, blank=True),
programe = models.TextField(verbose_name='Программа'),
speaker = models.CharField(verbose_name='Спикеры', max_length=255, blank=True),
place = models.CharField(verbose_name='Место проведения', max_length=255, blank=True)
)
def logo_name(instance, filename):
url = instance.expo.url
return '/'.join(['exposition', url, url+'_org_logo.jpg'])
class Paid(models.Model):
expo = models.OneToOneField(Exposition)
org_logo = models.ImageField(upload_to=logo_name, blank=True, max_length=255)
oficial_link = models.ForeignKey('banners.Redirect', null=True, blank=True, related_name='expo_oficial')
participation_link = models.ForeignKey('banners.Redirect', null=True, blank=True, related_name='expo_participation')
tickets_link = models.ForeignKey('banners.Redirect', null=True, blank=True, related_name='expo_tickets')
organiser = models.EmailField(blank=True)
pre_save.connect(pre_save_handler, sender=Exposition)
post_save.connect(post_save_handler, sender=Exposition)
post_save.connect(post_save_handler, sender=TimeTable)
post_save.connect(post_save_handler, sender=TmpTimeTable)
post_save.connect(post_save_handler, sender=Statistic)