Beispiel #1
0
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())
Beispiel #2
0
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())
Beispiel #3
0
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 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
Beispiel #5
0
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 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)
Beispiel #7
0
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
Beispiel #8
0
class ProgressReport(models.Model):
    event = models.OneToOneField(ProgressEvent, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.DO_NOTHING)
    status = models.PositiveSmallIntegerField(
        choices=PROGRESS_REPORT_STATUS_CHOICES,
        help_text=','.join([
            '%s - %s' % (item[0], item[1])
            for item in PROGRESS_REPORT_STATUS_CHOICES
        ]))
    percentage = models.PositiveIntegerField(
        validators=[MinValueValidator(0),
                    MaxValueValidator(100)])
    accomplished = models.TextField()
    next_steps = models.TextField(blank=True, null=True)
    remarks = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    uploads = GenericRelation(Upload, related_query_name='progress_reports')

    def __unicode__(self):
        return '{0} - {1}%'.format(self.event, self.percentage)

    @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.event.task.has_object_read_permission(request)

    @staticmethod
    @allow_staff_or_superuser
    def has_write_permission(request):
        return request.user.type == USER_TYPE_DEVELOPER

    @allow_staff_or_superuser
    def has_object_write_permission(self, request):
        return request.user == self.user
Beispiel #9
0
class Application(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.CASCADE)
    task = models.ForeignKey(Task, on_delete=models.CASCADE)
    accepted = models.BooleanField(default=False)
    responded = models.BooleanField(default=False)
    pitch = models.CharField(max_length=1000, blank=True, null=True)
    hours_needed = models.PositiveIntegerField(blank=True, null=True)
    hours_available = models.PositiveIntegerField(blank=True, null=True)
    remarks = models.TextField(
        blank=True,
        null=True)  # These will also be delivered as messages to the client
    deliver_at = models.DateTimeField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    channels = GenericRelation(Channel, related_query_name='task_applications')

    def __unicode__(self):
        return '%s - %s' % (self.user.get_short_name()
                            or self.user.username, self.task.summary)

    class Meta:
        unique_together = ('user', 'task')

    @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.has_object_update_permission(request)

    @staticmethod
    @allow_staff_or_superuser
    def has_write_permission(request):
        return request.user.type == USER_TYPE_DEVELOPER

    @staticmethod
    @allow_staff_or_superuser
    def has_update_permission(request):
        return True

    @allow_staff_or_superuser
    def has_object_write_permission(self, request):
        return request.user == self.user

    @allow_staff_or_superuser
    def has_object_update_permission(self, request):
        # Task owner can update applications
        return request.user == self.user or request.user == self.task.user
Beispiel #10
0
class Subject(models.Model):
    """Model to store information about a Subject"""
    name = models.CharField(max_length=255, unique=True, verbose_name="Name")
    slug = models.SlugField(max_length=150, unique=True, editable=False, verbose_name="Slug")
    description = models.TextField(blank=True, verbose_name="Description")

    class Meta:
        ordering = ['name']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name, allow_unicode=True)
        super().save(*args, **kwargs)
Beispiel #11
0
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']
Beispiel #12
0
class ProjectMeta(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    meta_key = models.CharField(max_length=30)
    meta_value = models.TextField()
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL,
                                   related_name='project_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 __str__(self):
        return '{} | {} - {}'.format(self.project, self.meta_key,
                                     self.meta_value)

    class Meta:
        ordering = ['created_at']
        unique_together = ('project', 'meta_key')
Beispiel #13
0
class Project(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             related_name='projects_created',
                             on_delete=models.DO_NOTHING)
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True, null=True)
    deadline = models.DateTimeField(blank=True, null=True)
    closed = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    closed_at = models.DateTimeField(blank=True, null=True)

    def __unicode__(self):
        return self.title

    class Meta:
        ordering = ['-created_at']
        unique_together = ('user', 'title')

    @staticmethod
    @allow_staff_or_superuser
    def has_read_permission(request):
        return request.user.type == USER_TYPE_PROJECT_OWNER

    @allow_staff_or_superuser
    def has_object_read_permission(self, request):
        return request.user == self.user

    @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.user

    @property
    def excerpt(self):
        try:
            return strip_tags(self.description).strip()
        except:
            return None
Beispiel #14
0
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 ""
Beispiel #15
0
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)
Beispiel #16
0
class IntegrationActivity(models.Model):
    integration = models.ForeignKey(Integration,
                                    on_delete=models.CASCADE,
                                    related_name='activities')
    event = models.ForeignKey(IntegrationEvent,
                              related_name='integration_activities')
    action = models.CharField(max_length=30, blank=True, null=True)
    url = models.URLField(blank=True, null=True)
    ref = models.CharField(max_length=30, blank=True, null=True)
    ref_name = models.CharField(max_length=50, blank=True, null=True)
    username = models.CharField(max_length=30, blank=True, null=True)
    fullname = models.CharField(max_length=50, blank=True, null=True)
    avatar_url = models.URLField(blank=True, null=True)
    title = models.CharField(max_length=200, blank=True, null=True)
    body = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return '%s | ' % (self.integration, )

    class Meta:
        ordering = ['created_at']
Beispiel #17
0
class ProgressEvent(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    type = models.CharField(max_length=50,
                            choices=PROGRESS_EVENT_TYPE_CHOICES,
                            default=PROGRESS_EVENT_DEVELOPER,
                            help_text=','.join([
                                '{} - {}'.format(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.TextField(blank=True, null=True)
    last_reminder_at = models.DateTimeField(blank=True, null=True)
    missed_notification_at = models.DateTimeField(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)
    updated_at = models.DateTimeField(auto_now=True)

    legacy_id = models.PositiveIntegerField(blank=True, null=True)
    migrated_at = models.DateTimeField(blank=True, null=True)

    activity_objects = GenericRelation(
        Action,
        object_id_field='target_object_id',
        content_type_field='target_content_type',
        related_query_name='progress_events')

    def __str__(self):
        return '{} | {} - {}'.format(self.type, self.title, self.due_at)

    class Meta:
        unique_together = ('project', 'type', '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.project.is_participant(request.user)

    @staticmethod
    @allow_staff_or_superuser
    def has_write_permission(request):
        return request.user.is_project_owner or 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.project.user or request.user == self.project.owner

    @property
    def participants(self):
        participants = []
        if self.type in [PROGRESS_EVENT_CLIENT, PROGRESS_EVENT_MILESTONE]:
            if self.project.owner:
                participants.append(self.project.owner)
            else:
                participants.append(self.project.user)
        if self.type in [
                PROGRESS_EVENT_PM, PROGRESS_EVENT_MILESTONE,
                PROGRESS_EVENT_INTERNAL
        ] and self.project.pm:
            participants.append(self.project.pm)
        if self.type in [PROGRESS_EVENT_DEVELOPER, PROGRESS_EVENT_MILESTONE]:
            participants.extend([
                participant.user
                for participant in self.project.participation_set.filter(
                    status=STATUS_ACCEPTED, updates_enabled=True)
            ])
        return participants

    @property
    def status(self):
        if self.progressreport_set.count() > 0:
            return 'completed'
        past_by_24_hours = datetime.datetime.utcnow() - relativedelta(hours=24)
        if self.due_at > past_by_24_hours:
            return 'upcoming'
        return 'missed'
Beispiel #18
0
class Task(models.Model):
    project = models.ForeignKey(Project,
                                related_name='tasks',
                                on_delete=models.DO_NOTHING,
                                blank=True,
                                null=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             related_name='tasks_created',
                             on_delete=models.DO_NOTHING)
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True, null=True)
    remarks = models.TextField(blank=True, null=True)
    url = models.URLField(blank=True, null=True)
    fee = models.BigIntegerField()
    currency = models.CharField(max_length=5,
                                choices=CURRENCY_CHOICES,
                                default=CURRENCY_CHOICES[0][0])
    deadline = models.DateTimeField(blank=True, null=True)
    skills = tagulous.models.TagField(Skill, blank=True)
    visibility = models.PositiveSmallIntegerField(
        choices=VISIBILITY_CHOICES, default=VISIBILITY_CHOICES[0][0])
    update_interval = models.PositiveIntegerField(blank=True, null=True)
    update_interval_units = models.PositiveSmallIntegerField(
        choices=UPDATE_SCHEDULE_CHOICES, blank=True, null=True)
    apply = models.BooleanField(default=True)
    closed = models.BooleanField(default=False)
    paid = models.BooleanField(default=False)
    applicants = models.ManyToManyField(settings.AUTH_USER_MODEL,
                                        through='Application',
                                        through_fields=('task', 'user'),
                                        related_name='task_applications',
                                        blank=True)
    participants = models.ManyToManyField(settings.AUTH_USER_MODEL,
                                          through='Participation',
                                          through_fields=('task', 'user'),
                                          related_name='task_participants',
                                          blank=True)
    satisfaction = models.SmallIntegerField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    apply_closed_at = models.DateTimeField(blank=True, null=True)
    closed_at = models.DateTimeField(blank=True, null=True)
    paid_at = models.DateTimeField(blank=True, null=True)
    comments = GenericRelation(Comment, related_query_name='tasks')
    uploads = GenericRelation(Upload, related_query_name='tasks')
    ratings = GenericRelation(Rating, related_query_name='tasks')

    def __unicode__(self):
        return self.summary

    class Meta:
        ordering = ['-created_at']
        unique_together = ('user', 'title', 'fee')

    @staticmethod
    @allow_staff_or_superuser
    def has_read_permission(request):
        return True

    @allow_staff_or_superuser
    def has_object_read_permission(self, request):
        if self.visibility == VISIBILITY_DEVELOPER:
            return request.user.type == USER_TYPE_DEVELOPER
        elif self.visibility == VISIBILITY_MY_TEAM:
            return bool(
                Connection.objects.exclude(accepted=False).filter(
                    Q(from_user=self.user, to_user=request.user)
                    | Q(from_user=request.user, to_user=self.user)).count())
        elif self.visibility == VISIBILITY_CUSTOM:
            return self.participation_set.filter(
                (Q(accepted=True) | Q(responded=False)),
                user=request.user).count()
        return False

    @staticmethod
    @allow_staff_or_superuser
    def has_write_permission(request):
        return request.user.type == USER_TYPE_PROJECT_OWNER

    @staticmethod
    @allow_staff_or_superuser
    def has_update_permission(request):
        return True

    @allow_staff_or_superuser
    def has_object_write_permission(self, request):
        return request.user == self.user

    @allow_staff_or_superuser
    def has_object_update_permission(self, request):
        if self.has_object_write_permission(request):
            return True
        # Participants can edit participation info directly on task object
        if request.method in ['PUT', 'PATCH']:
            allowed_keys = [
                'assignee', 'participants', 'confirmed_participants',
                'rejected_participants'
            ]
            if not [x for x in request.data.keys() if not x in allowed_keys]:
                return self.participation_set.filter(
                    (Q(accepted=True) | Q(responded=False)),
                    user=request.user).count()
        return False

    def display_fee(self, amount=None):
        if amount is None:
            amount = self.fee
        if self.currency in CURRENCY_SYMBOLS:
            return '%s%s' % (CURRENCY_SYMBOLS[self.currency],
                             floatformat(amount, arg=-2))
        return amount

    @property
    def summary(self):
        return '%s - Fee: %s' % (self.title, self.display_fee())

    @property
    def excerpt(self):
        try:
            return strip_tags(self.description).strip()
        except:
            return None

    @property
    def skills_list(self):
        return str(self.skills)

    @property
    def milestones(self):
        return self.progressevent_set.filter(type__in=[
            PROGRESS_EVENT_TYPE_MILESTONE, PROGRESS_EVENT_TYPE_SUBMIT
        ])

    @property
    def progress_events(self):
        return self.progressevent_set.all()

    @property
    def participation(self):
        return self.participation_set.filter(
            Q(accepted=True) | Q(responded=False))

    @property
    def assignee(self):
        try:
            return self.participation_set.get(
                (Q(accepted=True) | Q(responded=False)), assignee=True)
        except:
            return None

    @property
    def update_schedule_display(self):
        if self.update_interval and self.update_interval_units:
            if self.update_interval == 1 and self.update_interval_units == UPDATE_SCHEDULE_DAILY:
                return 'Daily'
            interval_units = str(
                self.get_update_interval_units_display()).lower()
            if self.update_interval == 1:
                return 'Every %s' % interval_units
            return 'Every %s %ss' % (self.update_interval, interval_units)
        return None

    @property
    def applications(self):
        return self.application_set.filter(responded=False)

    @property
    def all_uploads(self):
        return Upload.objects.filter(
            Q(tasks=self) | Q(comments__tasks=self)
            | Q(progress_reports__event__task=self))

    @property
    def meta_payment(self):
        return {
            'task_url': '/task/%s/' % self.id,
            'amount': self.fee,
            'currency': self.currency
        }

    def get_default_participation(self):
        tags = ['tunga.io', 'tunga']
        if self.skills:
            tags.extend(str(self.skills).split(','))
        tunga_share = '{share}%'.format(**{'share': TUNGA_SHARE_PERCENTAGE})
        return {
            'type':
            'payment',
            'language':
            'EN',
            'title':
            self.summary,
            'description':
            self.excerpt or self.summary,
            'keywords':
            tags,
            'participants': [{
                'id': 'mailto:%s' % TUNGA_SHARE_EMAIL,
                'role': 'owner',
                'share': tunga_share
            }]
        }

    def mobbr_participation(self, check_only=False):
        participation_meta = self.get_default_participation()
        if not self.url:
            return participation_meta, False

        mobbr_info_url = '%s?url=%s' % (
            'https://api.mobbr.com/api_v1/uris/info',
            urllib.quote_plus(self.url))
        r = requests.get(mobbr_info_url,
                         **{'headers': {
                             'Accept': 'application/json'
                         }})
        has_script = False
        if r.status_code == 200:
            response = r.json()
            task_script = response['result']['script']
            for meta_key in participation_meta:
                if meta_key == 'keywords':
                    if isinstance(task_script[meta_key], list):
                        participation_meta[meta_key].extend(
                            task_script[meta_key])
                elif meta_key == 'participants':
                    if isinstance(task_script[meta_key], list):
                        absolute_shares = []
                        relative_shares = []
                        absolute_participants = []
                        relative_participants = []

                        for key, participant in enumerate(
                                task_script[meta_key]):
                            if re.match(r'\d+%$', participant['share']):
                                share = int(participant['share'].replace(
                                    "%", ""))
                                if share > 0:
                                    absolute_shares.append(share)
                                    new_participant = participant
                                    new_participant['share'] = share
                                    absolute_participants.append(
                                        new_participant)
                            else:
                                share = int(participant['share'])
                                if share > 0:
                                    relative_shares.append(share)
                                    new_participant = participant
                                    new_participant['share'] = share
                                    relative_participants.append(
                                        new_participant)

                        additional_participants = []
                        total_absolutes = sum(absolute_shares)
                        total_relatives = sum(relative_shares)
                        if total_absolutes >= 100 or total_relatives == 0:
                            additional_participants = absolute_participants
                        elif total_absolutes == 0:
                            additional_participants = relative_participants
                        else:
                            additional_participants = absolute_participants
                            for participant in relative_participants:
                                share = int(
                                    round(((participant['share'] *
                                            (100 - total_absolutes)) /
                                           total_relatives), 0))
                                if share > 0:
                                    new_participant = participant
                                    new_participant['share'] = share
                                    additional_participants.append(
                                        new_participant)
                        if len(additional_participants):
                            participation_meta[meta_key].extend(
                                additional_participants)
                            has_script = True
                elif meta_key in task_script:
                    participation_meta[meta_key] = task_script[meta_key]
        return participation_meta, has_script

    @property
    def meta_participation(self):
        participation_meta, has_script = self.mobbr_participation()
        # TODO: Update local participation script to use defined shares
        if not has_script:
            participants = self.participation_set.filter(
                accepted=True).order_by('share')
            total_shares = 100 - TUNGA_SHARE_PERCENTAGE
            num_participants = participants.count()
            for participant in participants:
                participation_meta['participants'].append({
                    'id':
                    'mailto:%s' % participant.user.email,
                    'role':
                    participant.role,
                    'share':
                    int(total_shares / num_participants)
                })
        return participation_meta
Beispiel #19
0
class Project(models.Model):
    company = models.ForeignKey(Company, blank=True, null=True)
    project_manager = models.ForeignKey('accounts.Profile')
    title = models.CharField(max_length=255, unique=True)
    slug = models.SlugField(max_length=255)
    type = models.CharField(max_length=100,
                            choices=PROJECT_TYPES,
                            blank=True,
                            null=True)
    category = models.CharField(max_length=100, blank=True, null=True)
    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    expire_date = models.DateField(blank=True, null=True)
    skills = tagulous.models.TagField(to='accounts.Skills',
                                      blank=True,
                                      null=True)
    deleted = models.BooleanField(default=False)
    estimated_hours = models.IntegerField(blank=True, null=True)
    estimated_cash = models.IntegerField(blank=True, null=True)
    estimated_equity_percentage = models.DecimalField(blank=True,
                                                      null=True,
                                                      max_digits=4,
                                                      decimal_places=2)
    estimated_equity_shares = models.DecimalField(blank=True,
                                                  null=True,
                                                  max_digits=9,
                                                  decimal_places=2)
    date_created = models.DateTimeField(auto_now_add=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=100, blank=True, null=True)
    country_code = models.CharField(max_length=100, blank=True, null=True)
    location = models.CharField(max_length=150, blank=True, null=True)
    status = models.CharField(max_length=100, blank=True, null=True)
    remote = models.BooleanField(default=False)
    featured = models.BooleanField(default=False)
    mix = models.BooleanField(default=False)
    background = models.TextField(blank=True, null=True)
    progress = models.TextField(blank=True, null=True)
    scope = models.TextField(blank=True, null=True)
    specs = models.TextField(blank=True, null=True)
    private_info = models.TextField(blank=True, null=True)
    published = models.BooleanField(default=False)
    approved = models.BooleanField(default=False)
    role = models.CharField(max_length=100, blank=True, null=True)
    years = models.IntegerField(blank=True, null=True)
    employment_type = models.CharField(max_length=100, default='freelance')
    autorenew = models.BooleanField(default=False)
    sku = models.CharField(max_length=50, blank=True, null=True)
    views = models.IntegerField(default=0)

    objects = ProjectManager()

    def __str__(self):
        return self.title

    def __unicode__(self):
        return self.title

    class Meta:
        ordering = ['-date_created']

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super(Project, self).save(*args, **kwargs)

    def preauth(self, promo=None):
        product = Product.objects.get(sku=self.sku)
        try:
            order = Order.objects.get(content_type__pk=self.content_type.id,
                                      object_id=self.id,
                                      status='preauth')
        except Order.DoesNotExist:
            if promo:
                promo = Promo.objects.get(code=promo.lower())
            order = Order(content_object=self,
                          product=product,
                          user=self.project_manager,
                          status='preauth',
                          promo=promo)
            order.save()
            order.charge()
        return order

    def activate(self):
        today = datetime.now().date()
        if not self.sku:
            self.sku = 'free'
        product = Product.objects.get(sku=self.sku)
        self.expire_date = today + timedelta(days=product.interval)
        self.status = 'active'
        self.save()
        return self

    def subscribe(self, promo=None):
        try:
            order = Order.objects.get(content_type__pk=self.content_type.id,
                                      object_id=self.id,
                                      status='preauth')
        except Order.DoesNotExist:
            order = self.preauth(promo=promo)
        if order.product.sku != self.sku:
            product = Product.objects.get(sku=self.sku)
            order.product = product
            order.save()
        order.capture()
        if self.project_manager.referral_code:
            response = vl_conversion(self.project_manager)
            context = {
                'name': self.project_manager.name,
                'title': self.title,
                'email': self.project_manager.email,
                'location': self.project_manager.location,
                'referral_code': self.project_manager.referral_code,
                'url': settings.VL_CAMPAIGN_URL
            }
            send_to_emails('referral-conversion', settings.ADMINS, context)
        self.activate()
        return self

    def deactivate(self):
        today = datetime.now().date()
        if self.expire_date and self.expire_date <= today:
            if self.sku != 'free':
                order = Order.objects.get(
                    content_type__pk=self.content_type.id,
                    object_id=self.id,
                    status='active')
                order.status = 'expired'
                order.save()
            self.status = 'expired'
            self.published = False
            self.save()
            if not self.deleted:
                template = 'project-expired-free' if self.sku == 'free' else 'project-expired'
                url = '{0}/project/upgrade/{1}/'.format(
                    settings.BASE_URL, self.slug
                ) if self.sku == 'free' else '{0}/project/renew/{1}/'.format(
                    settings.BASE_URL, self.slug)
                send_mail(
                    template, [self.project_manager], {
                        'fname': self.project_manager.first_name,
                        'title': self.title,
                        'url': url
                    })
        return self

    @property
    def content_type(self):
        return ContentType.objects.get_for_model(self)

    @property
    def location(self):
        return self.city if self.city else self.project_manager.city

    @property
    def skills_str(self):
        return self.skills.get_tag_string()

    @property
    def nda_list(self):
        ndas = NDA.objects.filter(proposal__project=self)
        nda_list = [nda.receiver.id for nda in ndas]
        nda_list.append(self.project_manager.id)
        return nda_list
Beispiel #20
0
class UserProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL,
                                on_delete=models.CASCADE)
    bio = models.TextField(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.CharField(max_length=20, 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)

    id_document = models.ImageField(upload_to='ids/%Y/%m/%d',
                                    blank=True,
                                    null=True)

    skills = tagulous.models.TagField(to=Skill, blank=True)

    company = models.CharField(max_length=200, blank=True, null=True)
    website = models.URLField(blank=True, null=True)
    company_profile = models.TextField(blank=True, null=True)
    company_bio = models.TextField(blank=True, null=True)
    vat_number = models.CharField(max_length=50, blank=True, null=True)
    company_reg_no = models.CharField(max_length=50, blank=True, null=True)

    payment_method = models.CharField(max_length=30,
                                      choices=PAYMENT_METHOD_CHOICES,
                                      help_text=','.join([
                                          '%s - %s' % (item[0], item[1])
                                          for item in PAYMENT_METHOD_CHOICES
                                      ]),
                                      blank=True,
                                      null=True)
    btc_wallet = models.ForeignKey(BTCWallet,
                                   blank=True,
                                   null=True,
                                   on_delete=models.SET_NULL)
    btc_address = models.CharField(max_length=40,
                                   blank=True,
                                   null=True,
                                   validators=[validate_btc_address])
    mobile_money_cc = models.CharField(max_length=5,
                                       choices=MOBILE_MONEY_CC_CHOICES,
                                       help_text=','.join([
                                           '%s - %s' % (item[0], item[1])
                                           for item in MOBILE_MONEY_CC_CHOICES
                                       ]),
                                       blank=True,
                                       null=True)
    mobile_money_number = models.CharField(max_length=15,
                                           blank=True,
                                           null=True)

    def __unicode__(self):
        return self.user.get_short_name()

    @property
    def city_name(self):
        return self.city and str(self.city) or ""

    @property
    def country_name(self):
        return str(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
Beispiel #21
0
class Company(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='user_company')

    # Description
    name = models.CharField(max_length=100, blank=True, null=True)
    bio = models.TextField(blank=True, null=True)
    website = models.URLField(blank=True, null=True)

    # Contact Info
    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.CharField(max_length=20, blank=True, null=True)
    postal_address = models.CharField(max_length=100, blank=True, null=True)
    tel_number = models.CharField(max_length=15, blank=True, null=True)

    # Stack
    skills = tagulous.models.TagField(to=Skill, blank=True)

    # KYC
    vat_number = models.CharField(max_length=50, blank=True, null=True)
    reg_no = models.CharField(max_length=50, blank=True, null=True)
    ref_no = models.CharField(max_length=50, blank=True, null=True)

    class Meta:
        verbose_name = 'company'
        verbose_name_plural = 'companies'

    def __str__(self):
        return self.name or 'Company #{}'.format(self.id)

    @property
    def city_name(self):
        return self.city and str(self.city) or ""

    @property
    def country_name(self):
        return str(self.country.name)

    @property
    def location(self):
        location = self.city
        if self.country_name:
            location = '{}{}{}'.format(location, location and ', ' or '', self.country.name)
        return location or ''

    @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

    def get_category_skills(self, skill_type):
        return self.skills.filter(type=skill_type)

    @property
    def skills_details(self):
        return dict(
            language=self.get_category_skills(SKILL_TYPE_LANGUAGE),
            framework=self.get_category_skills(SKILL_TYPE_FRAMEWORK),
            platform=self.get_category_skills(SKILL_TYPE_PLATFORM),
            library=self.get_category_skills(SKILL_TYPE_LIBRARY),
            storage=self.get_category_skills(SKILL_TYPE_STORAGE),
            api=self.get_category_skills(SKILL_TYPE_API),
            other=self.get_category_skills(SKILL_TYPE_OTHER),
        )
Beispiel #22
0
class UserProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    # Personal Info
    bio = models.TextField(blank=True, null=True)

    # Contact Info
    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.CharField(max_length=20, 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)

    # Professional Info
    skills = tagulous.models.TagField(to=Skill, blank=True)

    # KYC
    id_document = models.ImageField(upload_to='ids/%Y/%m/%d', blank=True, null=True)
    company = models.CharField(max_length=200, blank=True, null=True)
    website = models.URLField(blank=True, null=True)
    company_profile = models.TextField(blank=True, null=True)
    company_bio = models.TextField(blank=True, null=True)
    vat_number = models.CharField(max_length=50, blank=True, null=True)
    company_reg_no = models.CharField(max_length=50, blank=True, null=True)
    reference_number = models.CharField(max_length=50, blank=True, null=True)
    company_details = models.CharField(max_length=50, blank=True, null=True)

    # Payment Information
    payment_method = models.CharField(
        max_length=30, choices=PAYMENT_METHOD_CHOICES,
        help_text=','.join(['%s - %s' % (item[0], item[1]) for item in PAYMENT_METHOD_CHOICES]),
        blank=True, null=True
    )
    btc_wallet = models.ForeignKey(BTCWallet, blank=True, null=True, on_delete=models.SET_NULL)
    btc_address = models.CharField(max_length=40, blank=True, null=True, validators=[validate_btc_address])
    mobile_money_cc = models.CharField(
        max_length=5, choices=MOBILE_MONEY_CC_CHOICES,
        help_text=','.join(['%s - %s' % (item[0], item[1]) for item in MOBILE_MONEY_CC_CHOICES]),
        blank=True, null=True)
    mobile_money_number = models.CharField(max_length=15, blank=True, null=True)

    # Tax Information
    tax_name = models.CharField(max_length=200, blank=True, null=True)
    tax_percentage = models.FloatField(blank=True, null=True)

    def __str__(self):
        return self.user.get_short_name()

    @property
    def city_name(self):
        return self.city and str(self.city) or ""

    @property
    def country_name(self):
        return str(self.country.name)

    @property
    def location(self):
        location = self.city
        if self.country_name:
            location = '{}{}{}'.format(location, location and ', ' or '', self.country.name)
        return location or ''

    @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

    def get_category_skills(self, skill_type):
        return self.skills.filter(type=skill_type)

    @property
    def skills_details(self):
        return dict(
            language=self.get_category_skills(SKILL_TYPE_LANGUAGE),
            framework=self.get_category_skills(SKILL_TYPE_FRAMEWORK),
            platform=self.get_category_skills(SKILL_TYPE_PLATFORM),
            library=self.get_category_skills(SKILL_TYPE_LIBRARY),
            storage=self.get_category_skills(SKILL_TYPE_STORAGE),
            api=self.get_category_skills(SKILL_TYPE_API),
            other=self.get_category_skills(SKILL_TYPE_OTHER),
        )
Beispiel #23
0
class Profile(AbstractUser):

    address = models.CharField(max_length=255, blank=True, null=True)
    address2 = models.CharField(max_length=255, blank=True, null=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=100, blank=True, null=True)
    country_code = models.CharField(max_length=100, blank=True, null=True)
    zipcode = models.IntegerField(blank=True, null=True)
    location = models.CharField(max_length=100, blank=True, null=True)
    capacity = models.IntegerField(blank=True, null=True)
    notes = models.TextField(blank=True, null=True)
    photo = models.ImageField(blank=True, null=True, upload_to=path_and_rename)
    skills = tagulous.models.TagField(to=Skills, blank=True)
    signup_code = models.CharField(max_length=25, blank=True, null=True)
    title = models.CharField(max_length=100, blank=True, null=True)
    roles = models.ManyToManyField(Role, blank=True)
    stripe = models.CharField(max_length=255, blank=True, null=True)
    stripe_connect = models.CharField(max_length=255, blank=True, null=True)
    verification = models.CharField(max_length=255, default='unverified')
    payouts_enabled = models.BooleanField(default=False)
    biography = models.TextField(blank=True, null=True)
    long_description = models.TextField(blank=True, null=True)
    objects = CustomUserManager()
    email_notifications = models.BooleanField(default=True)
    email_confirmed = models.BooleanField(default=False)
    featured = models.BooleanField(default=False)
    tos = models.BooleanField(default=False)
    work_examples = GenericRelation('generics.Attachment')
    score = models.DecimalField(blank=True,
                                null=True,
                                max_digits=5,
                                decimal_places=2)
    referral_code = models.CharField(max_length=50, blank=True, null=True)
    full_time = models.BooleanField(default=True)
    contract_to_hire = models.BooleanField(default=True)
    freelance = models.BooleanField(default=True)

    @property
    def name(self):
        return '{0} {1}'.format(self.first_name, self.last_name)

    @property
    def get_photo(self):
        if self.photo:
            return '{0}{1}'.format(settings.MEDIA_URL, self.photo)
        else:
            try:
                return self.social_auth.get(
                    provider='linkedin-oauth2'
                ).extra_data['picture_urls']['values'][0]
            except:
                return ''

    @property
    def linkedin(self):
        try:
            return self.social_auth.get(provider='linkedin-oauth2')
        except UserSocialAuth.DoesNotExist:
            return None

    @property
    def company(self):
        """
        TODO Needs to support multiple primary companies
        """
        try:
            return Employee.objects.get(profile=self, primary=True).company
        except Employee.DoesNotExist:
            return None

    @property
    def contact_details(self):
        details, created = ContactDetails.objects.get_or_create(profile=self)
        if (created):
            details.email = self.email
            details.email_confirmed = self.email_confirmed
            details.save()
        return details

    def get_skills(self):
        return self.skills.all()

    @property
    def skilltests(self):
        return SkillTest.objects.filter(profile=self)

    @property
    def taken_tests(self):
        return [t.expertratings_test for t in self.skilltests]

    def get_default_payment(self):
        if self.stripe:
            stripe.api_key = settings.STRIPE_KEY
            stripe_customer = stripe.Customer.retrieve(self.stripe)
            for card in stripe_customer['sources']['data']:
                if card['id'] == stripe_customer['default_source']:
                    # TODO Manually serialize card, circular import error if using api serializer
                    return card
        return None

    @property
    def subscribed(self):
        active_projects = Project.objects.filter(project_manager=self,
                                                 status='active')
        if len(active_projects) > 0:
            return True
        return False

    def invite(self, sender):
        invite, created = Invite.objects.get_or_create(recipient=self,
                                                       sender=sender)
        if created:
            return True
        return False
Beispiel #24
0
class Thesis(models.Model):
    """
    This class defines the field that a thesis can have.
    The following fields are optional: additional, pdf
    A thesis can be promoted for either BSc, MSc, BEd, MEd, or as being part of a project.
    Each thesis is referenced with the chair that is providing it via a ForeignKey field.
    """
    THESIS_CHOICES = (
        ('BSC', 'Bachelor of Science'),
        ('MSC', 'Master of Science'),
        ('BED', 'Bachelor of Education'),
        ('MED', 'Master of Education'),
        ('PRO', 'Forschungsprojekt'),
        ('ETC', 'nach Absprache')
    )

    title = models.CharField('Titel der Arbeit',
                             blank=False,
                             max_length=200)

    description = models.TextField('Beschreibung',
                                   blank=False)

    date_added = models.DateTimeField('Erstellungsdatum',
                                      default=timezone.now,
                                      editable=False)

    additional = models.TextField('weitere Beschreibung',
                                  blank=True,
                                  max_length=1000)

    contact = models.EmailField('E-Mail der Kontaktperson:',
                                blank=False)

    chair = models.ForeignKey(Chair, on_delete=models.CASCADE,
                              related_name="provided_by",
                              verbose_name='angeboten durch Lehrstuhl')

    start_date = models.DateField('frühester Beginn',
                                  blank=False,
                                  default=timezone.now)

    is_active = models.BooleanField('aktiv',
                                    default=True)

    pdf = models.FileField('PDF mit Ausschreibung',
                           validators=[FileExtensionValidator(allowed_extensions=['pdf'])],
                           blank=True)

    type = MultiSelectField('Art der Arbeit',
                            choices=THESIS_CHOICES,
                            blank=False)

    tags = tagulous.models.TagField(get_absolute_url=lambda tag: reverse(
            'by_tag',
            args=parse_tags(tag.slug)))

    user = models.ForeignKey(AAIUser, null=True,
                             on_delete=models.DO_NOTHING,
                             related_name="uploaded_by",
                             verbose_name="hochgeladen von")

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return "/%i/" % self.id

    class Meta:
        verbose_name = "Abschlussarbeit"
        verbose_name_plural = "Abschlussarbeiten"
Beispiel #25
0
class UserProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    # Personal Info
    bio = models.TextField(blank=True, null=True)

    # Contact Info
    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.CharField(max_length=20, 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)

    # Professional Info
    skills = tagulous.models.TagField(to=Skill, blank=True)

    # KYC
    id_document = models.ImageField(upload_to='ids/%Y/%m/%d', blank=True, null=True)
    company = models.CharField(max_length=200, blank=True, null=True)
    website = models.URLField(blank=True, null=True)
    company_profile = models.TextField(blank=True, null=True)
    company_bio = models.TextField(blank=True, null=True)
    vat_number = models.CharField(max_length=50, blank=True, null=True)
    company_reg_no = models.CharField(max_length=50, blank=True, null=True)
    reference_number = models.CharField(max_length=50, blank=True, null=True)
    company_details = models.CharField(max_length=50, blank=True, null=True)

    # Payment Information
    payment_method = models.CharField(
        max_length=30, choices=PAYMENT_METHOD_CHOICES,
        help_text=','.join(['%s - %s' % (item[0], item[1]) for item in PAYMENT_METHOD_CHOICES]),
        blank=True, null=True
    )
    btc_wallet = models.ForeignKey(BTCWallet, blank=True, null=True, on_delete=models.SET_NULL)
    btc_address = models.CharField(max_length=40, blank=True, null=True, validators=[validate_btc_address])
    mobile_money_cc = models.CharField(
        max_length=5, choices=MOBILE_MONEY_CC_CHOICES,
        help_text=','.join(['%s - %s' % (item[0], item[1]) for item in MOBILE_MONEY_CC_CHOICES]),
        blank=True, null=True)
    mobile_money_number = models.CharField(max_length=15, blank=True, null=True)

    # Tax Information
    tax_name = models.CharField(max_length=200, blank=True, null=True)
    tax_percentage = models.FloatField(blank=True, null=True)

    def __str__(self):
        return self.user.get_short_name()

    @property
    def city_name(self):
        return self.city and str(self.city) or ""

    @property
    def country_name(self):
        return str(self.country.name)

    @property
    def location(self):
        location = self.city
        if self.country_name:
            location = '{}{}{}'.format(location, location and ', ' or '', self.country.name)
        return location or ''

    @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

    def get_category_skills(self, skill_type):
        return self.skills.filter(type=skill_type)

    @property
    def skills_details(self):
        return dict(
            language=self.get_category_skills(SKILL_TYPE_LANGUAGE),
            framework=self.get_category_skills(SKILL_TYPE_FRAMEWORK),
            platform=self.get_category_skills(SKILL_TYPE_PLATFORM),
            library=self.get_category_skills(SKILL_TYPE_LIBRARY),
            storage=self.get_category_skills(SKILL_TYPE_STORAGE),
            api=self.get_category_skills(SKILL_TYPE_API),
            other=self.get_category_skills(SKILL_TYPE_OTHER),
        )

    @property
    def tunga_badge(self):
        badge = TUNGA_DEVELOPER_BADGE
        user_projects = self.user.projects
        total_projects = len(user_projects)
        user_dedicated_months = self.get_months_of_participation()

        if total_projects in range(1, 4) or user_dedicated_months in range(1, 7):
            badge = TUNGA_TALENT_BADGE

        if total_projects in range(4, 9) or user_dedicated_months in range(7, 19):
            badge = TUNGA_VETERAN_BADGE

        if total_projects > 8 or user_dedicated_months > 18:
            badge = TUNGA_GURU_BADGE

        return badge

    def get_months_of_participation(self):
        total_months = 0
        user_participations = self.user.project_participation.filter(status=STATUS_ACCEPTED)
        for participation in user_participations:
            start_date = participation.created_at
            end_or_current_date = participation.project.closed_at or datetime.datetime.now()

            period = relativedelta.relativedelta(end_or_current_date, start_date)
            total_months += period.months
        return total_months
Beispiel #26
0
class Project(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             related_name='projects_created',
                             on_delete=models.DO_NOTHING)
    title = models.CharField(max_length=200)
    description = models.TextField()
    owner = models.ForeignKey(settings.AUTH_USER_MODEL,
                              related_name='projects_owned',
                              on_delete=models.DO_NOTHING,
                              blank=True,
                              null=True)
    pm = models.ForeignKey(settings.AUTH_USER_MODEL,
                           related_name='projects_managed',
                           on_delete=models.DO_NOTHING,
                           blank=True,
                           null=True)
    skills = tagulous.models.TagField(Skill, blank=True)
    budget = models.DecimalField(max_digits=17,
                                 decimal_places=2,
                                 blank=True,
                                 null=True,
                                 default=None)
    currency = models.CharField(max_length=5,
                                choices=CURRENCY_CHOICES_EUR_ONLY,
                                default=CURRENCY_EUR)
    type = models.ManyToManyField(ProjectType, blank=True)
    expected_duration = models.CharField(
        max_length=20,
        choices=PROJECT_EXPECTED_DURATION_CHOICES,
        blank=True,
        null=True)
    stage = models.CharField(max_length=20,
                             choices=PROJECT_STAGE_CHOICES,
                             default=PROJECT_STAGE_ACTIVE)

    # State identifiers
    client_survey_enabled = models.BooleanField(default=True)
    pm_updates_enabled = models.BooleanField(default=True)
    closed = models.BooleanField(default=False)
    archived = models.BooleanField(default=False)

    # Significant event dates
    start_date = models.DateTimeField(blank=True, null=True)
    deadline = models.DateTimeField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    closed_at = models.DateTimeField(blank=True, null=True)
    archived_at = models.DateTimeField(blank=True, null=True)

    participants = models.ManyToManyField(settings.AUTH_USER_MODEL,
                                          through='Participation',
                                          through_fields=('project', 'user'),
                                          related_name='project_participants',
                                          blank=True)

    legacy_id = models.PositiveIntegerField(blank=True, null=True)
    migrated_at = models.DateTimeField(blank=True, null=True)
    hubspot_deal_id = models.CharField(editable=False,
                                       null=True,
                                       max_length=12)

    activity_objects = GenericRelation(
        Action,
        object_id_field='target_object_id',
        content_type_field='target_content_type',
        related_query_name='projects')

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-created_at']

    @allow_staff_or_superuser
    def is_participant(self, user, active=True):
        if user == self.user or user == self.owner:
            return True
        elif user.is_project_manager and self.pm == user:
            return True
        elif user.is_developer and self.participation_set.filter(
                user=user,
                status__in=active and [STATUS_ACCEPTED]
                or [STATUS_ACCEPTED, STATUS_INITIAL]).count() > 0:
            return True
        else:
            return False

    @staticmethod
    @allow_staff_or_superuser
    def has_read_permission(request):
        return True

    @allow_staff_or_superuser
    def has_object_read_permission(self, request):
        return True

    @staticmethod
    @allow_staff_or_superuser
    def has_write_permission(request):
        return request.user.is_project_owner or request.user.is_project_manager

    @allow_staff_or_superuser
    def has_object_write_permission(self, request):
        return request.user == self.user or request.user == self.owner or request.user == self.pm

    @property
    def margin(self):
        from tunga_payments.models import Invoice
        sales_amount = Invoice.objects.filter(
            project=self, type=INVOICE_TYPE_SALE).aggregate(Sum('amount'))
        project_amount = Invoice.objects.filter(
            project=self, type=INVOICE_TYPE_PURCHASE).aggregate(Sum('amount'))
        sales_amount = sales_amount['amount__sum'] or 0
        project_amount = project_amount['amount__sum'] or 0
        return sales_amount - project_amount
Beispiel #27
0
class ProgressReport(models.Model):
    event = models.ForeignKey(ProgressEvent, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.DO_NOTHING)

    # Status details
    status = models.CharField(max_length=50,
                              choices=PROGRESS_REPORT_STATUS_CHOICES,
                              help_text=','.join([
                                  '%s - %s' % (item[0], item[1])
                                  for item in PROGRESS_REPORT_STATUS_CHOICES
                              ]),
                              blank=True,
                              null=True)
    percentage = models.PositiveIntegerField(
        validators=[MinValueValidator(0),
                    MaxValueValidator(100)],
        blank=True,
        null=True)
    accomplished = models.TextField(blank=True, null=True)
    todo = models.TextField(blank=True, null=True)
    obstacles = models.TextField(blank=True, null=True)
    obstacles_prevention = models.TextField(blank=True, null=True)
    remarks = models.TextField(blank=True, null=True)
    stuck_reason = models.CharField(
        max_length=50,
        choices=PROGRESS_REPORT_STUCK_REASON_CHOICES,
        help_text=','.join([
            '%s - %s' % (item[0], item[1])
            for item in PROGRESS_REPORT_STUCK_REASON_CHOICES
        ]),
        blank=True,
        null=True)
    stuck_details = models.TextField(blank=True, null=True)

    # Deliverables
    rate_deliverables = models.PositiveIntegerField(
        validators=[MinValueValidator(1),
                    MaxValueValidator(5)],
        blank=True,
        null=True)

    # Deadline Info
    started_at = models.DateTimeField(blank=True, null=True)
    last_deadline_met = models.NullBooleanField(blank=True, null=True)
    deadline_miss_communicated = models.NullBooleanField(blank=True, null=True)
    deadline_report = models.TextField(blank=True, null=True)
    next_deadline = models.DateTimeField(blank=True, null=True)
    next_deadline_meet = models.NullBooleanField(blank=True, null=True)
    next_deadline_fail_reason = models.TextField(blank=True, null=True)

    # PMs only
    team_appraisal = models.TextField(blank=True, null=True)

    # Clients only
    deliverable_satisfaction = models.NullBooleanField(blank=True, null=True)
    rate_communication = models.PositiveIntegerField(
        validators=[MinValueValidator(1),
                    MaxValueValidator(5)],
        blank=True,
        null=True)
    pm_communication = models.NullBooleanField(blank=True, null=True)

    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 '{0} - {1}%'.format(self.event, self.percentage)

    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.event.project.is_participant(request)

    @staticmethod
    @allow_staff_or_superuser
    def has_write_permission(request):
        return request.user.is_developer or 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.user
Beispiel #28
0
class Company(models.Model):
    name = models.CharField(max_length=255, unique=True)
    slug = models.SlugField()
    legal_entity_name = models.CharField(max_length=255, blank=True, null=True)
    phone = models.CharField(max_length=255, blank=True, null=True)
    email = models.CharField(max_length=255, blank=True, null=True)
    stripe = models.CharField(max_length=255, blank=True, null=True)
    address = models.CharField(max_length=255, blank=True, null=True)
    address2 = models.CharField(max_length=255, blank=True, null=True)
    city = models.CharField(max_length=255, blank=True, null=True)
    state = models.CharField(max_length=255, blank=True, null=True)
    zipcode = models.CharField(max_length=15, blank=True, null=True)
    country = models.CharField(max_length=255, blank=True, null=True)
    ein = models.CharField(max_length=50,
                           verbose_name='EIN',
                           blank=True,
                           null=True)
    logo = models.ImageField(blank=True, null=True, upload_to='provider/logo')
    description = models.TextField(blank=True, null=True)
    long_description = models.TextField(blank=True, null=True)
    type = models.CharField(max_length=100,
                            choices=COMPANY_TYPES,
                            blank=True,
                            null=True)
    filing_location = models.CharField(max_length=100, blank=True, null=True)
    incorporation_date = models.DateField(blank=True, null=True)

    @property
    def get_logo(self):
        if self.logo:
            return '{0}{1}'.format(settings.MEDIA_URL, self.logo)
        else:
            return '{0}{1}'.format(settings.STATIC_URL,
                                   'images/home-hero-2g.jpg')

    @property
    def primary_contact(self):
        return Employee.objects.get(company=self, primary=True)

    @property
    def employees(self):
        return Employee.objects.filter(company=self)

    @property
    def tags(self):
        projects = Project.objects.filter(company=self)
        tags = []
        for project in projects:
            # TODO List comprehension here bro
            if project.type not in tags:
                tags.append(project.type)
        return tags

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super(Company, self).save(*args, **kwargs)

    def __str__(self):
        return self.name

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name_plural = 'companies'