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-21 21:13:15 +00:00
from django . core . validators import MaxValueValidator , MinValueValidator , RegexValidator
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 )
2018-10-14 21:23:57 +00:00
resource_uuid = models . UUIDField ( default = uuid . uuid4 , editable = False , primary_key = False )
2018-10-11 07:41:32 +00:00
class Meta :
abstract = True
class Remindable ( Timestampable ) :
2018-10-21 21:13:15 +00:00
reminder_alias = models . CharField ( default = ' ' , unique = True , max_length = 255 , validators = [
RegexValidator ( r ' ^[A-Za-z_][A-Za-z0-9_]*$ ' ) ,
] , help_text = ' All characters must be alphanumerical or underline, except by the first character, which must not be alphanumerical. ' )
2018-10-11 07:41:32 +00:00
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 ) :
2018-10-14 21:23:57 +00:00
resource_uuid = models . UUIDField ( default = uuid . uuid4 , editable = False , unique = True , primary_key = False )
2018-10-11 07:41:32 +00:00
reminder_title = ' Language '
class Meta :
abstract = True
2018-10-21 21:13:15 +00:00
ordering = ( ' reminder_alias ' , )
2018-10-11 07:41:32 +00:00
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 = ' ' )
2018-10-14 21:23:57 +00:00
class LanguageRichText ( LanguageString ) :
kind = ' rich text '
pt = RichTextField ( default = ' ' )
en = RichTextField ( default = ' ' )
es = RichTextField ( default = ' ' )
2018-10-11 07:41:32 +00:00
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 } '
2018-10-15 20:52:39 +00:00
class Color ( Remindable ) :
color = ColorField ( default = ' #000000 ' )
opacity = models . IntegerField ( default = 255 , validators = [ MinValueValidator ( 0 ) , MaxValueValidator ( 255 ) ] , help_text = " Opacity: 0 is transparent, 255 is opaque. " )
kind = ' '
2018-10-11 07:41:32 +00:00
class ActivityCategory ( Timestampable ) :
name = models . ForeignKey ( LanguagePhrase , on_delete = models . PROTECT , related_name = ' + ' )
2018-10-15 20:52:39 +00:00
color = models . ForeignKey ( Color , on_delete = models . PROTECT , related_name = ' + ' )
2018-12-13 02:48:50 +00:00
ordering = models . IntegerField ( default = 0 , blank = True , null = False )
2018-10-11 07:41:32 +00:00
def __str__ ( self ) :
2018-10-16 19:40:40 +00:00
return f ' Category # { self . pk } : { self . name . en } '
2018-10-11 07:41:32 +00:00
2018-12-13 02:48:50 +00:00
class Meta :
ordering = ( ' ordering ' , ' -pk ' , )
2018-10-11 07:41:32 +00:00
class Place ( Timestampable ) :
name = models . ForeignKey ( LanguagePhrase , on_delete = models . PROTECT , related_name = ' + ' )
2018-10-15 20:52:39 +00:00
color = models . ForeignKey ( Color , on_delete = models . PROTECT , related_name = ' + ' )
2018-12-13 02:48:50 +00:00
ordering = models . IntegerField ( default = 0 , blank = True , null = False )
2018-10-11 07:41:32 +00:00
def __str__ ( self ) :
2018-10-16 19:40:40 +00:00
return f ' Place # { self . pk } : { self . name . en } '
2018-10-11 07:41:32 +00:00
2018-12-13 02:48:50 +00:00
class Meta :
ordering = ( ' ordering ' , ' -pk ' , )
2018-10-11 07:41:32 +00:00
class Timezone ( Remindable ) :
kind = ' '
2018-10-14 21:23:57 +00:00
hour = models . IntegerField ( default = - 3 , validators = [ MinValueValidator ( - 24 ) , MaxValueValidator ( 24 ) ] )
minute = models . IntegerField ( default = 0 , validators = [ MinValueValidator ( 0 ) , MaxValueValidator ( 60 ) ] )
2018-10-11 07:41:32 +00:00
class RegistrationBenefitDefinition ( Timestampable ) :
description = models . ForeignKey ( LanguagePhrase , on_delete = models . PROTECT , related_name = ' + ' )
2018-12-13 02:48:50 +00:00
ordering = models . IntegerField ( default = 0 , blank = True , null = False )
2018-10-11 07:41:32 +00:00
2018-10-14 21:23:57 +00:00
def __str__ ( self ) :
return f ' Registration benefit definition # { self . pk } : { self . description . en } '
2018-12-13 02:48:50 +00:00
class Meta :
ordering = ( ' ordering ' , ' -pk ' , )
2018-10-11 07:41:32 +00:00
class RegistrationTierDefinition ( Timestampable ) :
title = models . ForeignKey ( LanguagePhrase , on_delete = models . PROTECT , related_name = ' + ' )
2018-12-13 02:48:50 +00:00
ordering = models . IntegerField ( default = 0 , blank = True , null = False )
2018-10-11 07:41:32 +00:00
2018-10-14 21:23:57 +00:00
def __str__ ( self ) :
return f ' Registration tier definition # { self . pk } : { self . title . en } '
2018-12-13 02:48:50 +00:00
class Meta :
ordering = ( ' ordering ' , ' -pk ' , )
2018-10-11 07:41:32 +00:00
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 21:23:57 +00:00
benefits = models . ManyToManyField ( RegistrationBenefitDefinition , blank = True , related_name = ' + ' )
2018-10-14 04:21:18 +00:00
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
2018-10-14 21:23:57 +00:00
def __str__ ( self ) :
return f ' Convention registration tier # { self . pk } : { self . convention . name . en } - { self . tier . title . en } ( { self . benefits . count ( ) } ) '
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 = ' + ' )
2018-10-14 21:23:57 +00:00
time_start = models . DateTimeField ( help_text = " fill with the time on the timezone of the event. " )
time_end = models . DateTimeField ( help_text = " fill with the time on the timezone of the event. " )
2018-10-16 19:40:40 +00:00
places = models . ManyToManyField ( Place , related_name = ' on_activities ' )
2018-10-14 21:23:57 +00:00
categories = models . ManyToManyField ( ActivityCategory , blank = True , related_name = ' on_activities ' )
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 )
2018-10-14 21:23:57 +00:00
picture = models . ForeignKey ( LanguageInvariantImage , blank = True , null = True , 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 )
2018-10-14 21:23:57 +00:00
class Meta :
ordering = ( ' -time_start ' , ' -time_end ' , ' conbook_key ' )
def __str__ ( self ) :
2018-10-14 22:38:25 +00:00
return f ' Convention activity # { self . pk } : { self . convention . name . en } - { self . title . en } [ { self . conbook_key } ] ( { self . time_start } - { self . time_end } ) '
2018-10-14 21:23:57 +00:00
2018-10-14 04:21:18 +00:00
class ConventionSeries ( Timestampable ) :
name = models . ForeignKey ( LanguagePhrase , on_delete = models . PROTECT , related_name = ' + ' )
url = models . SlugField ( default = ' ' , unique = True , max_length = 255 )
2018-10-14 22:38:25 +00:00
featured = models . ForeignKey ( ' ConventionEdition ' , null = True , blank = True , on_delete = models . PROTECT , related_name = ' + ' )
2018-10-14 21:23:57 +00:00
statute = models . ForeignKey ( LanguageRichText , on_delete = models . PROTECT , related_name = ' + ' )
2018-10-14 06:00:28 +00:00
timezone = models . ForeignKey ( Timezone , on_delete = models . PROTECT , related_name = ' + ' )
2018-12-20 04:37:19 +00:00
default_banner = models . ForeignKey ( LanguageImage , default = None , on_delete = models . PROTECT , related_name = ' + ' )
2018-10-21 21:40:27 +00:00
language = models . CharField (
max_length = 2 ,
choices = TRILINGUAL_CHOICES ,
default = ' pt ' ,
)
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 SocialMedia ( Remindable ) :
2018-10-21 21:13:15 +00:00
ordering = models . IntegerField ( default = 0 )
2018-10-14 04:21:18 +00:00
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 = ' + ' )
2018-10-21 21:13:15 +00:00
icon = models . CharField ( default = None , blank = True , null = True , max_length = 255 , choices = [
( None , ' -- no icon -- ' ) ,
( ' ic_telegram ' , ' Telegram ' ) ,
( ' ic_twitter ' , ' Twitter ' ) ,
( ' ic_facebook_official ' , ' Facebook ' ) ,
( ' ic_youtube_play ' , ' YouTube ' ) ,
( ' ic_instagram ' , ' Instagram ' ) ,
( ' ic_web_black_24dp ' , ' Web browser ' ) ,
] )
2018-10-14 04:21:18 +00:00
kind = ' '
2018-10-21 21:13:15 +00:00
color = models . ForeignKey ( Color , on_delete = models . PROTECT , related_name = ' + ' )
class Meta :
ordering = ( ' ordering ' , ' name__reminder_alias ' , ' -pk ' , )
2018-10-14 04:21:18 +00:00
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 = ' + ' )
2018-12-13 02:48:50 +00:00
fire_notifications_n_minutes_before = models . PositiveIntegerField ( default = 15 )
convention_day_start_time = models . TimeField ( help_text = " fill with the time on the timezone of the event. " )
convention_day_end_time = models . TimeField ( help_text = " fill with the time on the timezone of the event. " )
2018-10-14 04:21:18 +00:00
rule_621_checker = models . BooleanField ( default = False , blank = True , null = False )
2018-10-14 21:23:57 +00:00
next_edition_date = models . DateField ( help_text = " fill with the time on the timezone of the event. " )
ceremony_opening_time = models . DateTimeField ( help_text = " fill with the time on the timezone of the event. " )
ceremony_closing_time = models . DateTimeField ( help_text = " fill with the time on the timezone of the event. " )
2018-12-20 05:24:02 +00:00
image_default_event = models . ForeignKey ( LanguageImage , default = None , null = True , blank = True , on_delete = models . PROTECT , related_name = ' + ' )
image_favorites = models . ForeignKey ( LanguageImage , default = None , null = True , blank = True , on_delete = models . PROTECT , related_name = ' + ' )
2018-10-14 21:23:57 +00:00
split_day_into_n_parts = models . IntegerField ( default = 24 , blank = False , null = False , validators = [ MaxValueValidator ( 1440 ) , MinValueValidator ( 1 ) ] )
2018-10-14 04:21:18 +00:00
language = models . CharField (
max_length = 2 ,
choices = TRILINGUAL_CHOICES ,
default = ' pt ' ,
)
def __str__ ( self ) :
2018-10-14 21:23:57 +00:00
return f ' Convention # { self . pk } : { self . name . en } '
2018-12-13 02:48:50 +00:00
2018-12-20 04:37:19 +00:00
class Meta :
ordering = ( ' ceremony_opening_time ' , ' -pk ' , )
class BannerChange ( Remindable ) :
convention = models . ForeignKey ( ConventionSeries , default = None , blank = False , null = False , on_delete = models . PROTECT , related_name = " banners " )
show_up_after = models . DateTimeField ( help_text = " fill with the time on the timezone of the event. " )
2018-12-20 16:10:07 +00:00
hide_after = models . DateTimeField ( help_text = " fill with the time on the timezone of the event. " )
2018-12-20 04:37:19 +00:00
banner = models . ForeignKey ( LanguageImage , default = None , on_delete = models . PROTECT , related_name = ' + ' )
reminder_title = ' Banner change '
kind = ' '
class Meta :
ordering = ( ' show_up_after ' , ' -pk ' , )
2018-12-13 02:48:50 +00:00
2018-12-20 17:12:29 +00:00
class MapImage ( Remindable ) :
ordering = models . IntegerField ( default = 0 )
convention = models . ForeignKey ( ConventionEdition , default = None , blank = False , null = False , on_delete = models . PROTECT , related_name = " maps " )
name = models . ForeignKey ( LanguagePhrase , blank = False , null = False , on_delete = models . PROTECT , related_name = ' + ' )
image = models . ForeignKey ( LanguageImage , blank = False , null = False , on_delete = models . PROTECT , related_name = ' + ' )
2018-12-20 17:29:07 +00:00
reminder_title = ' Map '
kind = ' image '
2018-12-20 17:12:29 +00:00
class Meta :
ordering = ( ' convention__ceremony_opening_time ' , ' ordering ' , ' -pk ' , )
2018-12-25 05:17:17 +00:00
2018-12-28 01:20:54 +00:00
class ConventionRegistrationLink ( Remindable ) :
ordering = models . IntegerField ( default = 0 )
convention = models . ForeignKey ( ConventionEdition , default = None , blank = False , null = False , on_delete = models . PROTECT , related_name = " registration_links " )
name = models . ForeignKey ( LanguagePhrase , blank = False , null = False , on_delete = models . PROTECT , related_name = ' + ' )
url = models . ForeignKey ( LanguagePhrase , blank = False , null = False , on_delete = models . PROTECT , related_name = ' + ' )
color = models . ForeignKey ( Color , on_delete = models . PROTECT , null = True , blank = True , related_name = ' + ' )
appears = models . DateTimeField ( help_text = " fill with the time on the timezone of the event. " )
vanishes = models . DateTimeField ( help_text = " fill with the time on the timezone of the event. " )
reminder_title = ' Registration '
kind = ' link '
class Meta :
ordering = ( ' convention__ceremony_opening_time ' , ' ordering ' , ' -pk ' , )
2018-12-13 02:48:50 +00:00
class AdditionalRules ( Timestampable ) :
convention = models . ForeignKey ( ConventionEdition , blank = False , null = False , on_delete = models . PROTECT , related_name = ' additional_rules ' )
name = models . ForeignKey ( LanguagePhrase , blank = False , null = False , on_delete = models . PROTECT , related_name = ' + ' )
rules = models . ForeignKey ( LanguageRichText , blank = False , null = False , on_delete = models . PROTECT , related_name = ' + ' )
ordering = models . IntegerField ( default = 0 , blank = True , null = False )
def __str__ ( self ) :
return f ' Additional rules # { self . pk } @ { self . convention . name . en } : { self . name . en } '
class Meta :
ordering = ( ' ordering ' , ' -pk ' , )