class Release(models.Model): types = [ ('release', 'release'), ('event', 'event'), ] release_date = models.DateField() release_type = models.CharField(max_length=999, choices=types) title = models.CharField(max_length=999) important_tags = tagulous.models.TagField( to="general.customtag", related_name="release_important_tags", default=None, blank=True) other_tags = tagulous.models.TagField(to="general.customtag", related_name="release_other_tags", default=None, blank=True) snippet = models.CharField(max_length=999, blank=True, null=True) description = models.TextField( blank=True, null=True, ) video = models.CharField(max_length=999, blank=True, null=True) external_link = models.CharField(max_length=999, blank=True, null=True) review_link = models.ForeignKey(Publication, blank=True, null=True, related_name="review_link", on_delete=models.CASCADE) def __str__(self): return self.title
class DeveloperInvitation(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) email = models.EmailField(unique=True, validators=[validate_email]) type = models.IntegerField(choices=USER_TYPE_CHOICES, default=USER_TYPE_DEVELOPER) invitation_key = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) invitation_sent_at = models.DateTimeField(blank=True, null=True, editable=False) used = models.BooleanField(default=False) used_at = models.DateTimeField(blank=True, null=True, editable=False) resent = models.BooleanField(default=False) resent_at = models.DateTimeField(blank=True, null=True, editable=False) created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) class Meta: verbose_name = 'user invitation' def __unicode__(self): return self.display_name @property def display_name(self): return '%s %s' % (self.first_name, self.last_name)
class UserProfile(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) bio = models.TextField(max_length=500, blank=True, null=True) country = CountryField(blank=True, null=True) city = tagulous.models.SingleTagField(to=City, blank=True, null=True) street = models.CharField(max_length=100, blank=True, null=True) plot_number = models.CharField(max_length=100, blank=True, null=True) postal_code = models.IntegerField(blank=True, null=True) postal_address = models.CharField(max_length=100, blank=True, null=True) phone_number = models.CharField(max_length=15, blank=True, null=True) company = models.CharField(max_length=200, blank=True, null=True) skills = tagulous.models.TagField(to=Skill, blank=True) website = models.URLField(blank=True, null=True) def __unicode__(self): return self.user.get_short_name() @property def city_name(self): return str(self.city) @property def country_name(self): return self.country.name @allow_staff_or_superuser def has_object_read_permission(self, request): return True @allow_staff_or_superuser def has_object_write_permission(self, request): return request.user == self.user
class PublicationScore(models.Model): publication = models.ForeignKey(Publication, related_name="scores", on_delete=models.CASCADE) types = [ ('adiccion', 'ADICCIÓN'), ('ambientacion', 'AMBIENTACIÓN'), ('combate', 'COMBATE'), ('dificultad', 'DIFICULTAD'), ('equipo', 'EQUIPO'), ('estrategia', 'ESTRATEGIA'), ('terror', 'TERROR'), ('puzzles', 'PUZZLES'), ('monstruos', 'MONSTRUOS'), ('narrativa', 'NARRATIVA'), ] name = models.CharField(max_length=100, choices=types) types = [(1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5')] value = models.IntegerField(choices=types) description = models.CharField(max_length=999, default=None, null=True) def __str__(self): return self.publication.slug + " - " + self.name
class DeveloperApplication(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) email = models.EmailField(unique=True, validators=[validate_email]) phone_number = models.CharField(max_length=15) country = CountryField() city = models.CharField(max_length=50) stack = models.TextField() experience = models.TextField() discovery_story = models.TextField() status = models.PositiveSmallIntegerField( choices=APPLICATION_STATUS_CHOICES, help_text=','.join(['%s - %s' % (item[0], item[1]) for item in APPLICATION_STATUS_CHOICES]), default=REQUEST_STATUS_INITIAL ) created_at = models.DateTimeField(auto_now_add=True) confirmation_key = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) confirmation_sent_at = models.DateTimeField(blank=True, null=True, editable=False) used = models.BooleanField(default=False) used_at = models.DateTimeField(blank=True, null=True, editable=False) def __str__(self): return self.display_name @property def display_name(self): return '%s %s' % (self.first_name, self.last_name) @property def country_name(self): return self.country.name country_name.fget.short_description = 'country'
class Education(AbstractExperience): institution = models.CharField(max_length=200) award = models.CharField(max_length=200) def __str__(self): return '%s - %s' % (self.user.get_short_name, self.institution) class Meta: verbose_name_plural = 'education'
class Work(AbstractExperience): company = models.CharField(max_length=200) position = models.CharField(max_length=200) def __str__(self): return '%s - %s' % (self.user.get_short_name, self.company) class Meta: verbose_name_plural = 'work'
class Chair(models.Model): name = models.CharField('Lehrstuhl-Name', max_length=100, blank=False) head = models.CharField('Leitung', max_length=50, default='') def __str__(self): return self.name+" ("+self.head+")" class Meta: verbose_name = "Lehrstuhl" verbose_name_plural = "Lehrstühle"
class WhitePaperUser(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) company = models.CharField(max_length=100) email = models.EmailField(max_length=100) phone_number = models.CharField(max_length=20) country = CountryField() created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return '{} {} - {}'.format(self.first_name, self.email, self.company)
class Document(models.Model): project = models.ForeignKey(Project) type = models.CharField(choices=PROJECT_DOCUMENT_CHOICES, max_length=30, default=DOC_OTHER) url = models.URLField(blank=True, null=True) file = models.FileField(verbose_name='Upload', upload_to='documents/%Y/%m/%d', blank=True, null=True) title = models.CharField(max_length=100, blank=True, null=True) description = models.TextField(blank=True, null=True) created_by = models.ForeignKey(settings.AUTH_USER_MODEL) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) legacy_id = models.PositiveIntegerField(blank=True, null=True) migrated_at = models.DateTimeField(blank=True, null=True) def __str__(self): return '{} | {}'.format(self.type, self.project) class Meta: ordering = ['-created_at'] @staticmethod @allow_staff_or_superuser def has_read_permission(request): return True @allow_staff_or_superuser def has_object_read_permission(self, request): return self.project.is_participant(request.user) @staticmethod @allow_staff_or_superuser def has_write_permission(request): return request.user.is_project_manager or request.user.is_project_owner @allow_staff_or_superuser def has_object_write_permission(self, request): return request.user == self.created_by @property def download_url(self): if self.file: return '{}{}'.format( not re.match(r'://', self.file.url) and TUNGA_URL or '', self.file.url) elif self.url: return self.url return None
class Post(models.Model): POST_TYPE = ( (1, 'Article'), (2, 'Course'), (3, 'Job'), (4, 'Project'), ) identifier = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) slug = models.SlugField(unique=True, null=True, blank=True, max_length=512) type = models.PositiveSmallIntegerField(choices=POST_TYPE, default=1) tags = tagulous.models.TagField(related_name='posts', to=Tag, blank=True) author = models.ForeignKey('users.CustomUser', on_delete=models.CASCADE, related_name='blogs') title = models.CharField(max_length=255) body = BleachField() preview = models.CharField( max_length=300, help_text='A short preview of this post that is shown in list of posts.' ) likes = models.ManyToManyField('users.CustomUser', blank=True) allow_comments = models.BooleanField(default=True) def save(self, *args, **kwargs): self.slug = slugify(f'{self.title} {self.identifier}', allow_unicode=True) super(Post, self).save(*args, **kwargs) def __str__(self): return f'{self.title}, by {self.author.first_name} {self.author.last_name}' @property def likes_count(self): return self.likes.count() @property def relative_url(self): return reverse('blog-post', kwargs={'slug': self.slug}) def get_absolute_url(self): domain = Site.objects.get_current().domain protocol = "https" if settings.PRODUCTION_SERVER else "http" absolute_url = f'{protocol}://{domain}{self.relative_url}' return absolute_url
class Employee(models.Model): company = models.ForeignKey('business.Company') profile = models.ForeignKey('accounts.Profile') primary = models.BooleanField(default=False) title = models.CharField(max_length=255, blank=True, null=True) start_date = models.DateField(blank=True, null=True) end_date = models.DateField(blank=True, null=True) current = models.BooleanField(default=True) city = models.CharField(max_length=255, blank=True, null=True) state = models.CharField(max_length=255, blank=True, null=True) country = models.CharField(max_length=255, blank=True, null=True) description = models.TextField(blank=True, null=True) class Meta: ordering = ['-current', '-end_date', '-start_date']
class BaseModel(TimetrackingBaseModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name=_('BaseModel.id.verbose_name'), help_text=_('BaseModel.id.help_text')) user = models.ForeignKey( # "Owner" of this entry settings.AUTH_USER_MODEL, related_name='+', on_delete=models.CASCADE, editable=False, # Must be set automatically and never changed verbose_name=_('BaseModel.user.verbose_name'), help_text=_('BaseModel.user.help_text')) name = models.CharField(max_length=255, verbose_name=_('BaseModel.name.verbose_name'), help_text=_('BaseModel.name.help_text')) tags = tagulous.models.TagField( blank=True, case_sensitive=False, force_lowercase=False, space_delimiter=False, max_count=10, verbose_name=_('BaseModel.tags.verbose_name'), help_text=_('BaseModel.tags.help_text')) def __str__(self): return self.name class Meta: abstract = True
class BaseAttachmentModel(BaseModel): """ Base model to store files or images to Items """ name = models.CharField( null=True, blank=True, max_length=255, verbose_name=_('BaseItemAttachmentModel.name.verbose_name'), help_text=_('BaseItemAttachmentModel.name.help_text')) position = models.PositiveSmallIntegerField( # Note: Will be set in admin via adminsortable2 # The JavaScript which performs the sorting is 1-indexed ! default=0, blank=False, null=False) def __str__(self): return self.name def full_clean(self, *, parent_instance, **kwargs): if self.user_id is None: # inherit owner of this link from parent model instance self.user_id = parent_instance.user_id return super().full_clean(**kwargs) class Meta: abstract = True
class ProsAndCons(models.Model): types = [('pro', 'pro'), ('con', 'contra')] publication = models.ForeignKey( Publication, related_name="pros_and_cons", on_delete=models.CASCADE, ) type = models.CharField(max_length=100, default=None, null=True, choices=types) content = models.CharField(max_length=9999, default=None, null=True) def __str__(self): return self.publication.slug + " - " + self.type
class SkillTest(models.Model): class Meta: unique_together = ("profile", "expertratings_test") profile = models.ForeignKey('accounts.Profile') expertratings_test = models.ForeignKey('expertratings.SkillTest') skills = tagulous.models.TagField(to=Skills) ticket_url = models.CharField(max_length=255, blank=True, null=True) @property def developer(self): return self.profile def create_ticket(self): self.ticket_url = self.expertratings_test.create_ticket( user_id=self.developer.id) self.save() return self.ticket_url @property def results(self): return self.expertratings_test.results(user=self.developer) @property def test_details(self): return self.expertratings_test
class WhitePaperUser(models.Model): white_paper_choices = ( ('best_african_countries_for_outsourcing', 'best_african_countries_for_outsourcing'), ('scaling_your_team_with_remote_developers', 'scaling_your_team_with_remote_developers') ) paper = models.CharField(max_length=255, choices=white_paper_choices) first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) company = models.CharField(max_length=100) email = models.EmailField(max_length=100) phone_number = models.CharField(max_length=20) country = CountryField() created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return '{} {} - {}'.format(self.first_name, self.email, self.company)
class Connection(models.Model): from_user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='connections_initiated') to_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='connection_requests') accepted = models.BooleanField(default=False) responded = models.BooleanField(default=False) status = models.CharField( max_length=30, choices=CONNECTION_STATUS_CHOICES, default=STATUS_INITIAL, help_text=', '.join(['%s - %s' % (item[0], item[1]) for item in CONNECTION_STATUS_CHOICES]) ) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return '%s -> %s' % (self.from_user.get_short_name, self.to_user.get_short_name) class Meta: ordering = ['-created_at'] @allow_staff_or_superuser def has_object_read_permission(self, request): return request.user == self.from_user or request.user == self.to_user @allow_staff_or_superuser def has_object_write_permission(self, request): return request.user == self.from_user or request.user == self.to_user
class Participation(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING) task = models.ForeignKey(Task, on_delete=models.CASCADE) accepted = models.BooleanField(default=False) responded = models.BooleanField(default=False) assignee = models.BooleanField(default=False) role = models.CharField(max_length=100, default='Developer') share = models.IntegerField(blank=True, null=True) satisfaction = models.SmallIntegerField(blank=True, null=True) created_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='participants_added') created_at = models.DateTimeField(auto_now_add=True) activated_at = models.DateTimeField(blank=True, null=True) ratings = GenericRelation(Rating, related_query_name='participants') def __unicode__(self): return '%s - %s' % (self.user.get_short_name() or self.user.username, self.task.title) class Meta: unique_together = ('user', 'task') verbose_name_plural = 'participation' @allow_staff_or_superuser def has_object_read_permission(self, request): return self.task.has_object_read_permission(request) @allow_staff_or_superuser def has_object_write_permission(self, request): return request.user == self.user or request.user == self.task.user
class AppIntegration(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) provider = models.CharField( max_length=30, choices=APP_INTEGRATION_PROVIDER_CHOICES, help_text=','.join([ '%s - %s' % (item[0], item[1]) for item in APP_INTEGRATION_PROVIDER_CHOICES ])) token = models.TextField( verbose_name='token', help_text='"oauth_token" (OAuth1) or access token (OAuth2)') token_secret = models.TextField( blank=True, verbose_name='token secret', help_text='"oauth_token_secret" (OAuth1) or refresh token (OAuth2)') extra = models.TextField(blank=True, null=True) # JSON formatted extra details expires_at = models.DateTimeField(blank=True, null=True, verbose_name='expires at') updated_at = models.DateTimeField(auto_now_add=True) class Meta: unique_together = ('user', 'provider') verbose_name = 'app integration' verbose_name_plural = 'app integrations' def __unicode__(self): return '%s - %s' % (self.user.get_short_name(), self.get_provider_display())
class BTCWallet(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) provider = models.CharField(max_length=30, choices=BTC_WALLET_PROVIDER_CHOICES, help_text=','.join([ '%s - %s' % (item[0], item[1]) for item in BTC_WALLET_PROVIDER_CHOICES ])) token = models.TextField( verbose_name='token', help_text='"oauth_token" (OAuth1) or access token (OAuth2)') token_secret = models.TextField( blank=True, verbose_name='token secret', help_text='"oauth_token_secret" (OAuth1) or refresh token (OAuth2)') expires_at = models.DateTimeField(blank=True, null=True, verbose_name='expires at') updated_at = models.DateTimeField(auto_now_add=True) class Meta: unique_together = ('user', 'provider') verbose_name = 'bitcoin wallet' def __unicode__(self): return '%s - %s' % (self.user.get_short_name(), self.get_provider_display())
class IntegrationEvent(models.Model): id = models.CharField(max_length=30, primary_key=True) name = models.CharField(max_length=30) description = models.CharField(max_length=200, blank=True, null=True) created_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name='integration_events_created', on_delete=models.DO_NOTHING) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __unicode__(self): return '%s - %s' % (self.id, self.name) class Meta: ordering = ['id', 'name']
class IntegrationMeta(models.Model): integration = models.ForeignKey(Integration, on_delete=models.CASCADE) meta_key = models.CharField(max_length=30) meta_value = models.CharField(max_length=30) created_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='integration_meta_created', blank=True, null=True, on_delete=models.DO_NOTHING) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __unicode__(self): return '%s | %s - %s' % (self.integration, self.meta_key, self.meta_value) class Meta: ordering = ['created_at']
class ContactForm(models.Model): """ Contact form """ submission_types = {("tecnico", "tecnico"), ("particular", "particular"), ("empresa", "empresa"), ("inapropiado", "inapropiado"), ("patreon_link", "patreon_link"), ("otros", "otros")} content = models.TextField() subject = models.TextField() username = models.CharField(max_length=100) email = models.CharField(max_length=100) submission_type = models.CharField(max_length=100, choices=submission_types) timestamp = models.DateTimeField(auto_now_add=True) def __str__(self): return str(self.content)
class ProgressEvent(models.Model): task = models.ForeignKey(Task, on_delete=models.CASCADE) type = models.PositiveSmallIntegerField( choices=PROGRESS_EVENT_TYPE_CHOICES, default=PROGRESS_EVENT_TYPE_DEFAULT, help_text=','.join([ '%s - %s' % (item[0], item[1]) for item in PROGRESS_EVENT_TYPE_CHOICES ])) due_at = models.DateTimeField() title = models.CharField(max_length=200, blank=True, null=True) description = models.CharField(max_length=1000, blank=True, null=True) created_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='progress_events_created', blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True) last_reminder_at = models.DateTimeField(blank=True, null=True) def __unicode__(self): return '%s | %s - %s' % (self.get_type_display(), self.task.summary, self.due_at) class Meta: unique_together = ('task', 'due_at') ordering = ['due_at'] @staticmethod @allow_staff_or_superuser def has_read_permission(request): return True @allow_staff_or_superuser def has_object_read_permission(self, request): return self.task.has_object_read_permission(request) @staticmethod @allow_staff_or_superuser def has_write_permission(request): return request.user.type == USER_TYPE_PROJECT_OWNER @allow_staff_or_superuser def has_object_write_permission(self, request): return request.user == self.task.user
class Inquirer(models.Model): name = models.CharField(max_length=50, blank=True, null=True) email = models.EmailField(blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return '%s (%s)' % (self.name, self.email or self.id) class Meta: ordering = ['-created_at']
class Questionnaire(models.Model): PHASE_CHOICES = ( (1, 'Phase-1'), (2, 'Phase-2'), (3, 'Phase-3'), (4, 'Phase-4'), ) identifier = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) name = models.CharField(max_length=500) phase = models.PositiveSmallIntegerField(choices=PHASE_CHOICES, default=1) root = models.BooleanField( default=False, help_text='Note that you cannot delete the root questionnaire.') def __str__(self): return self.name # TODO needed? (already enforced in forms.py) def save(self, force_insert=False, force_update=False, using=None, update_fields=None, *args, **kwargs): root_field = self.root if Questionnaire.objects.filter(root=True).exists(): invalid = False if self.pk is None: # if new questionnaire is being added if root_field is True: invalid = True else: # if existing questionnaire is being edited if Questionnaire.objects.get(root=True).pk != self.pk: if root_field is True: invalid = True if invalid: raise ValidationError('You already have a root questionnaire!') super(Questionnaire, self).save(force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields, *args, **kwargs) # TODO needed? (already enforced in admin.py) def delete(self, using=None, keep_parents=False): if self.root: raise ValidationError( 'You cannot delete a root question! Consider editing it instead.' ) super(Questionnaire, self).delete(using=using, keep_parents=keep_parents)
class ContactDetails(models.Model): """ All Contact Details / PII for a user """ profile = models.ForeignKey('accounts.Profile', primary_key=True) email = models.CharField(max_length=50, blank=True, null=True, default='') email_confirmed = models.BooleanField(default=False) phone = models.CharField(max_length=50, blank=True, null=True, default='') website = models.CharField(max_length=50, blank=True, null=True) skype = models.CharField(max_length=50, blank=True, null=True) linkedin = models.CharField(max_length=50, blank=True, null=True) angellist = models.CharField(max_length=50, blank=True, null=True) github = models.CharField(max_length=50, blank=True, null=True) instagram = models.CharField(max_length=50, blank=True, null=True) twitter = models.CharField(max_length=50, blank=True, null=True) facebook = models.CharField(max_length=50, blank=True, null=True) @property def id(self): return self.profile.id
class Content(models.Model): """Model to store content related to a subject""" subject = models.ManyToManyField(Subject, blank=True, related_name='content') title = models.CharField(max_length=255, verbose_name="Title") slug = models.SlugField(max_length=150, unique=True, editable=False, verbose_name="Slug") url = models.URLField(blank=True, null=True, default='', verbose_name="URL") content_id = models.CharField(max_length=255) type = models.CharField(max_length=150, choices=media_types, default='other', verbose_name="Type") image = models.ImageField(upload_to='content_images', blank=True, null=True, verbose_name="Image") image_thumbnail = ImageSpecField(source='image', processors=[ResizeToFill(100, 150)], options={'quality': 100}) description = models.TextField(blank=True, verbose_name="Description") tags = tagulous.models.TagField(to=Tag, related_name='content_tag') topics = tagulous.models.TagField(to=Topic, related_name='content_topic') class Meta: ordering = ['title'] def __str__(self): return self.title def save(self, *args, **kwargs): self.slug = str(self.content_id) + '-' + slugify(self.title) super().save(*args, **kwargs) def url_text(self): if self.url and '//' not in self.url: self.url = '%s%s' % ('https://', self.url) parsed_url = urlparse(self.url) if parsed_url.hostname: return parsed_url.hostname.replace("www.", "") + "/..." else: return ""
class List(models.Model): """Content lists which can be created for each user.""" user = models.ForeignKey(BucketUser, on_delete=models.CASCADE) date_created = models.DateTimeField(auto_now_add=True) name = models.CharField(max_length=255, verbose_name="Name") slug = models.SlugField(max_length=150, unique=True, editable=False, verbose_name="Slug") description = models.TextField(blank=True, verbose_name="Description") image = models.ImageField(upload_to='list_images', blank=True, null=True, verbose_name="Image") image_thumbnail = ImageSpecField(source='image', processors=[ResizeToFill(100, 150)], options={'quality': 100}) content = models.ManyToManyField(Content, blank=True, related_name='content', verbose_name='Content') visibility = models.CharField(max_length=150, choices=visibility, default='public', verbose_name="Visibility") topics = tagulous.models.TagField(to=Topic, related_name='list_topic') list_bookmarked_by = models.ManyToManyField(BucketUser, related_name='list_bookmark') class Meta: ordering = ['name'] def __str__(self): return "{0} by {1}".format(self.name, self.user) def save(self, *args, **kwargs): self.slug = add_slug(self) super().save(*args, **kwargs)