2018-10-11 07:41:32 +00:00
|
|
|
import uuid
|
2018-10-11 04:07:41 +00:00
|
|
|
from django.db import models
|
2018-10-11 07:41:32 +00:00
|
|
|
from colorfield.fields import ColorField
|
2018-10-14 04:21:18 +00:00
|
|
|
from ckeditor.fields import RichTextField
|
2018-10-14 06:00:28 +00:00
|
|
|
from django.db.models.signals import post_delete
|
|
|
|
from .helpers import file_cleanup
|
|
|
|
from .helpers import RandomFileName
|
2018-10-11 07:41:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
class IntListField(models.CharField):
|
|
|
|
description = "An integer list"
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
if 'max_length' not in kwargs:
|
|
|
|
kwargs['max_length'] = 255
|
|
|
|
if 'default' not in kwargs:
|
|
|
|
kwargs['default'] = ''
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
def from_db_value(self, value, expression, connection):
|
|
|
|
if value is None:
|
|
|
|
return value
|
|
|
|
if value.strip() == '':
|
|
|
|
return list()
|
|
|
|
return list(map(int, map(str.strip, value.split(','))))
|
|
|
|
|
|
|
|
def to_python(self, value):
|
|
|
|
if isinstance(value, list):
|
|
|
|
return value
|
|
|
|
if value is None:
|
|
|
|
return value
|
|
|
|
for i in '[](){}':
|
|
|
|
value = value.replace(i, '')
|
|
|
|
if value.strip() == '':
|
|
|
|
return list()
|
|
|
|
return list(map(int, map(str.strip, value.split(','))))
|
|
|
|
|
|
|
|
def get_prep_value(self, value):
|
|
|
|
return ','.join(list(map(str, value)))
|
|
|
|
|
2018-10-11 04:07:41 +00:00
|
|
|
|
|
|
|
# Create your models here.
|
2018-10-11 07:41:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Timestampable(models.Model):
|
|
|
|
created = models.DateTimeField(auto_now_add=True)
|
|
|
|
modified = models.DateTimeField(auto_now=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
abstract = True
|
|
|
|
|
|
|
|
|
|
|
|
class Remindable(Timestampable):
|
|
|
|
reminder_alias = models.CharField(default='', max_length=255)
|
|
|
|
kind = '???'
|
|
|
|
|
|
|
|
@property
|
|
|
|
def reminder_title(self):
|
|
|
|
return self.__class__.__name__
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f'{self.reminder_title} {self.kind} #{self.pk}: {self.reminder_alias}'
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
abstract = True
|
|
|
|
|
|
|
|
|
|
|
|
class LanguageString(Remindable):
|
|
|
|
resource_uuid = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=False)
|
|
|
|
reminder_title = 'Language'
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
abstract = True
|
|
|
|
|
|
|
|
|
|
|
|
class LanguagePhrase(LanguageString):
|
|
|
|
kind = 'phrase'
|
|
|
|
pt = models.CharField(default='', max_length=255)
|
|
|
|
en = models.CharField(default='', max_length=255)
|
|
|
|
es = models.CharField(default='', max_length=255)
|
|
|
|
|
|
|
|
|
|
|
|
class LanguageText(LanguageString):
|
|
|
|
kind = 'text'
|
|
|
|
pt = models.TextField(default='')
|
|
|
|
en = models.TextField(default='')
|
|
|
|
es = models.TextField(default='')
|
|
|
|
|
|
|
|
|
|
|
|
class LanguageInvariantImage(LanguageString):
|
|
|
|
kind = 'invariant image'
|
2018-10-14 06:00:28 +00:00
|
|
|
picture = models.ImageField(upload_to=RandomFileName(''))
|
2018-10-11 07:41:32 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def pt(self): return self.picture
|
|
|
|
|
|
|
|
@property
|
|
|
|
def en(self): return self.picture
|
|
|
|
|
|
|
|
@property
|
|
|
|
def es(self): return self.picture
|
|
|
|
|
|
|
|
|
2018-10-14 06:00:28 +00:00
|
|
|
post_delete.connect(file_cleanup, sender=LanguageInvariantImage, dispatch_uid="webproj.bff.LanguageInvariantImage.file_cleanup")
|
|
|
|
|
|
|
|
|
2018-10-14 04:21:18 +00:00
|
|
|
class LanguageImage(LanguageString):
|
|
|
|
kind = 'image'
|
|
|
|
pt_image = models.ForeignKey(LanguageInvariantImage, on_delete=models.PROTECT, related_name='+')
|
|
|
|
en_image = models.ForeignKey(LanguageInvariantImage, on_delete=models.PROTECT, related_name='+')
|
|
|
|
es_image = models.ForeignKey(LanguageInvariantImage, on_delete=models.PROTECT, related_name='+')
|
|
|
|
|
|
|
|
@property
|
|
|
|
def pt(self): return self.pt_image.picture
|
|
|
|
|
|
|
|
@property
|
|
|
|
def en(self): return self.en_image.picture
|
|
|
|
|
|
|
|
@property
|
|
|
|
def es(self): return self.es_image.picture
|
|
|
|
|
|
|
|
|
2018-10-11 07:41:32 +00:00
|
|
|
class Announcement(Timestampable):
|
2018-10-14 04:21:18 +00:00
|
|
|
convention = models.ForeignKey('ConventionSeries', on_delete=models.PROTECT, related_name='announcements')
|
2018-10-11 07:41:32 +00:00
|
|
|
title = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
body = models.ForeignKey(LanguageText, on_delete=models.PROTECT, related_name='+')
|
|
|
|
link = models.ForeignKey(LanguagePhrase, blank=True, null=True, on_delete=models.PROTECT, related_name='+')
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f'Announcement #{self.pk}: {self.title}'
|
|
|
|
|
|
|
|
|
|
|
|
class ActivityCategory(Timestampable):
|
|
|
|
name = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f'Category #{self.pk}: {self.name}'
|
|
|
|
|
|
|
|
|
|
|
|
class Place(Timestampable):
|
|
|
|
name = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f'Place #{self.pk}: {self.name}'
|
|
|
|
|
|
|
|
|
|
|
|
class Color(Remindable):
|
|
|
|
color = ColorField(default='#000000')
|
|
|
|
|
|
|
|
|
|
|
|
class Timezone(Remindable):
|
|
|
|
kind = ''
|
|
|
|
hour = models.IntegerField(default=-3)
|
|
|
|
minute = models.IntegerField(default=0)
|
|
|
|
|
|
|
|
|
|
|
|
class RegistrationBenefitDefinition(Timestampable):
|
|
|
|
description = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
|
|
|
|
|
|
|
|
class RegistrationTierDefinition(Timestampable):
|
|
|
|
title = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
|
|
|
|
|
2018-10-14 04:21:18 +00:00
|
|
|
TRILINGUAL_CHOICES = (
|
|
|
|
('pt', 'Portuguese'),
|
|
|
|
('en', 'English'),
|
|
|
|
('es', 'Spanish')
|
|
|
|
)
|
2018-10-11 07:41:32 +00:00
|
|
|
|
|
|
|
|
2018-10-14 04:21:18 +00:00
|
|
|
class ConventionRegistrationTier(Timestampable):
|
2018-10-11 07:41:32 +00:00
|
|
|
level = models.IntegerField(default=0)
|
|
|
|
tier = models.ForeignKey(RegistrationTierDefinition, on_delete=models.PROTECT, related_name='+')
|
2018-10-14 04:21:18 +00:00
|
|
|
benefits = models.ManyToManyField(RegistrationBenefitDefinition, related_name='+')
|
|
|
|
convention = models.ForeignKey('ConventionEdition', on_delete=models.PROTECT, related_name='registration_tiers')
|
|
|
|
is_lowest = models.BooleanField(default=False, blank=True, null=False)
|
2018-10-11 07:41:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
class ConventionActivity(Timestampable):
|
|
|
|
conbook_key = models.CharField(default='', max_length=255)
|
|
|
|
conbook_pages = IntListField()
|
|
|
|
title = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
subtitle = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, blank=True, null=True, related_name='+')
|
|
|
|
description = models.ForeignKey(LanguageText, on_delete=models.PROTECT, related_name='+')
|
|
|
|
time_start = models.DateTimeField()
|
|
|
|
time_end = models.DateTimeField()
|
|
|
|
places = models.ManyToManyField(Place, related_name='+')
|
|
|
|
categories = models.ManyToManyField(ActivityCategory, related_name='+')
|
2018-10-14 04:21:18 +00:00
|
|
|
attendable_by = models.ManyToManyField(ConventionRegistrationTier, related_name='+')
|
2018-10-11 07:41:32 +00:00
|
|
|
language = models.CharField(
|
|
|
|
max_length=2,
|
2018-10-14 04:21:18 +00:00
|
|
|
choices=TRILINGUAL_CHOICES,
|
2018-10-11 07:41:32 +00:00
|
|
|
default='pt',
|
|
|
|
)
|
|
|
|
hidden_from_time_table = models.BooleanField(default=False, blank=True, null=False)
|
|
|
|
picture = models.ForeignKey(LanguageInvariantImage, related_name='+', on_delete=models.PROTECT)
|
2018-10-14 04:21:18 +00:00
|
|
|
convention = models.ForeignKey('ConventionEdition', related_name='events', on_delete=models.PROTECT)
|
|
|
|
|
|
|
|
|
|
|
|
class ConventionSeries(Timestampable):
|
|
|
|
name = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
url = models.SlugField(default='', unique=True, max_length=255)
|
|
|
|
statute = RichTextField(default='')
|
2018-10-14 06:00:28 +00:00
|
|
|
timezone = models.ForeignKey(Timezone, on_delete=models.PROTECT, related_name='+')
|
2018-10-14 04:21:18 +00:00
|
|
|
# banners ← foreign_relation
|
|
|
|
# social_medias ← foreign_relation
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f'Convention series #{self.pk}: {self.name.en} (/{self.url})'
|
|
|
|
|
|
|
|
|
|
|
|
class ConventionBanner(Remindable):
|
|
|
|
convention = models.ForeignKey(ConventionSeries, on_delete=models.PROTECT, related_name='banners')
|
|
|
|
image = models.ForeignKey(LanguageImage, on_delete=models.PROTECT, related_name='+')
|
|
|
|
valid_until = models.DateTimeField()
|
|
|
|
|
|
|
|
|
|
|
|
class SocialMedia(Remindable):
|
|
|
|
convention = models.ForeignKey(ConventionSeries, on_delete=models.PROTECT, related_name='social_medias')
|
|
|
|
name = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
url = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
icon = models.ForeignKey(LanguageInvariantImage, on_delete=models.PROTECT, related_name='+')
|
|
|
|
kind = ''
|
|
|
|
|
|
|
|
|
|
|
|
class ConventionEdition(Timestampable):
|
|
|
|
# id ← inherited
|
|
|
|
# events ← foreign_relation
|
|
|
|
# registration_tiers ← foreign_relation
|
|
|
|
# lowestRegistrationTier ← process
|
|
|
|
# places ← process
|
|
|
|
# tags ← process
|
|
|
|
edition_of = models.ForeignKey(ConventionSeries, on_delete=models.PROTECT, related_name='editions')
|
|
|
|
name = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
theme = models.ForeignKey(LanguagePhrase, on_delete=models.PROTECT, related_name='+')
|
|
|
|
hashtag_reminder = models.CharField(default='', max_length=255)
|
|
|
|
timezone = models.ForeignKey(Timezone, on_delete=models.PROTECT, related_name='+')
|
|
|
|
rule_621_checker = models.BooleanField(default=False, blank=True, null=False)
|
|
|
|
next_edition = models.DateField()
|
|
|
|
ceremony_opening_time = models.DateTimeField()
|
|
|
|
ceremony_closing_time = models.DateTimeField()
|
|
|
|
split_day_into_n_parts = models.IntegerField(default=24, blank=False, null=False)
|
|
|
|
language = models.CharField(
|
|
|
|
max_length=2,
|
|
|
|
choices=TRILINGUAL_CHOICES,
|
|
|
|
default='pt',
|
|
|
|
)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f'Convention #{self.pk}: {self.name}'
|