Example #1
0
class Usuario(AbstractBaseUser, PermissionsMixin):
	username 						= models.CharField(
														verbose_name='Nombre de usuario',
														max_length=50,
														unique=True,
														db_index=True,
														validators=[
															        MinLengthValidator(2),
															        MaxLengthValidator(50),
															    ]
													  )
	email    						= models.EmailField(
														max_length=100,
														unique=True,
														db_index=True,
														validators=[
															EmailValidator(),
														]
													   )
	numero_tarjeta_magnetica 		= models.PositiveIntegerField(verbose_name='Número de tarjeta mágnetica', default=0)
	numero_acceso_biometrico		= models.PositiveIntegerField(verbose_name='Número de acceso biométrico', default=0)
	slug							= models.SlugField(editable=False, max_length=255 ,unique=True, db_index=True, )
	fecha_registro 			   		= models.DateTimeField(auto_now_add=True, auto_now=False)
	usuario_creador          	 	= models.ForeignKey('self', null=True, default=None)
	nombre_host				    	= models.CharField(max_length=255)
	direccion_ip			    	= models.GenericIPAddressField(validators=[validate_ipv46_address])
	fecha_ultima_actualizacion 		= models.DateTimeField(auto_now_add=False, auto_now=True)
	ultimo_usuario_editor			= models.ForeignKey('self', null=True, default=None, related_name='ultimo_usuario_editor_usuarios_related')
	ultimo_nombre_host 				= models.CharField(max_length=255)
	ultimo_direccion_ip				= models.GenericIPAddressField(validators=[validate_ipv46_address])

	objects = UserManager()

	is_active = models.BooleanField(default=True)
	is_staff  = models.BooleanField(default=True)

	USERNAME_FIELD  = 'username'
	REQUIRED_FIELDS = ['email',]

	def save(self, *args, **kwargs):
		if not self.pk:
			self.slug = slugify(self.username)
		else:
			slug = slugify(self.username)
			if self.slug != slug:
				self.slug = slug
		super(Usuario, self).save(*args, **kwargs)

	def get_short_name(self):
		return self.username

	#Opciones
	class Meta:
		#Nombre para la tabla del gestor de base de datos
		db_table = 'Usuarios'
		#Ordenar los registros por un campo especifico
		ordering = ('username',)
		#Nombre para el Conjunto de Objetos en el Panel de Administración
		verbose_name = 'Usuario'
		#Nombre en Plural en la lista de módulos en el Panel de Administración
		verbose_name_plural = 'Usuarios'
Example #2
0
class Node(models.Model):
    type = "node"

    remote_server_url = models.URLField(max_length=200, primary_key=True, unique=True)
    remote_server_username = models.CharField(max_length=200, default='', blank=True)
    remote_server_password = models.CharField(max_length=200, default='', blank=True, validators=[MinLengthValidator(8)])
    adminApproval = models.BooleanField(default=False)

    konnection_username = models.CharField(max_length=200, default='', blank=True)
    konnection_password = models.CharField(max_length=200, default='', blank=True)

    # create author of type 'node' if node is admin approved and remote_server_* are provided
    def save(self, *args, **kwargs):
        # set username to hostname if blank
        if not self.remote_server_username:
            self.remote_server_username = self.hostname()
        self.remote_server_username = re.sub(r'\W+', '', self.remote_server_username)
        super(Node, self).save(*args, **kwargs)

        user_model = get_user_model()
        if self.adminApproval and self.remote_server_url and self.remote_server_username and self.remote_server_password:
            try:
                server_user = user_model.objects.get(username=self.remote_server_username)
                # update server_user
                server_user.username = self.remote_server_username
                server_user.password = self.remote_server_password
                server_user.url = self.remote_server_url
                server_user.adminApproval = self.adminApproval
                server_user.save()
            except user_model.DoesNotExist:
                # create server_user
                user_model.objects.create_author(
                    self.remote_server_username,
                    self.remote_server_password,
                    url=self.remote_server_url,
                    adminApproval=self.adminApproval,
                    type=self.type
                )
        else:
            # change adminApproval in server_user to False if it exists already
            try:
                server_user = user_model.objects.get(username=self.remote_server_username)
                if server_user:
                    server_user.adminApproval = False
                    server_user.save()
            except user_model.DoesNotExist:
                pass
    
    # delete corresponding author if exists
    def delete(self):
        try:
            server_user = get_user_model().objects.get(username=self.remote_server_username)
            if server_user:
                server_user.delete()
        except get_user_model().DoesNotExist:
            pass
        super(Node, self).delete()

    def hostname(self):
        parsed_url = urlparse(self.remote_server_url)
        return parsed_url.hostname
Example #3
0
class User(AbstractBaseUser, PermissionsMixin):
    """Custom user model that support using phone number instead of username"""

    EDUCATION_CHOICES = [
        ('High school', 'High school'),
        ('College', 'College'),
        ('University', 'University')
    ]
    EMPLOYMENT_CHOICES = [
        ('Student', 'Student'),
        ('Full time', 'Full time'),
        ('Part time', 'Part time')
    ]
    phone_regex = RegexValidator(
        regex=r'^\+?1?\d{9,15}$',
        message="Phone number must be entered in the format: '+999999999'. \
            Up to 15 digits allowed."
    )

    # INFO
    phone_number = models.CharField(_('phone number'), max_length=17,
                                    unique=True)
    email = models.EmailField(_('email address'), blank=True, null=True)
    name = models.CharField(max_length=255)
    first_name = models.CharField(_('first name'), max_length=30,
                                  blank=True, null=True)
    last_name = models.CharField(_('last name'), max_length=30,
                                 blank=True, null=True)
    age = models.PositiveSmallIntegerField(_('age'),
                                           validators=[
                                                MinValueValidator(18),
                                                MaxValueValidator(150)
                                           ],
                                           blank=True, null=True)
    zipcode = models.PositiveSmallIntegerField(_('zipcode'),
                                               validators=[
                                                    MinLengthValidator(5),
                                                    MaxLengthValidator(5)
                                               ],
                                               blank=True, null=True)
    income = models.DecimalField(_('income'), max_digits=10, decimal_places=2,
                                 validators=[DecimalValidator], blank=True,
                                 null=True)
    education = models.CharField(_('education'), max_length=50,
                                 choices=EDUCATION_CHOICES, blank=True,
                                 null=True)
    employment = models.CharField(_('employment'), max_length=50,
                                  choices=EMPLOYMENT_CHOICES, blank=True,
                                  null=True)

    # SCORES
    scores_initial = models.ForeignKey('Score', on_delete=models.CASCADE,
                                       null=True, blank=True,
                                       related_name="score_initial_owner")
    scores_final = models.ForeignKey('Score', on_delete=models.CASCADE,
                                     null=True, blank=True,
                                     related_name="score_final_owner")

    date_joined = models.DateTimeField(_('registered'), auto_now_add=True,
                                       null=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'phone_number'

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    def get_full_name(self):
        """Returns the firstname plus the last_name, and a space in between."""
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        """Returns the short name for the user."""
        return self.first_name
Example #4
0
class Empresas(models.Model):
    email = models.EmailField(unique=True)
    razao_social = models.CharField(max_length=255)
    endereco = models.CharField(max_length=255)
    ramo = models.CharField(max_length=255)
    numero = models.IntegerField()
    senha = models.TextField(validators=[MinLengthValidator(6)])

    def login_empresa(self, request=None, email=None, senha=None):
        if not request.session.get('email_empresa', None):
            self.email = email
            self.senha = HashPassword(senha)
            try:
                self.empresa = Empresas.objects.get(email=self.email,
                                                    senha=self.senha)

                if request.session.get('email', False):
                    del request.session['email']
                if request.session.get('id', False):
                    del request.session['id']
                if request.session.get('candidato'):
                    del request.session['candidato']

                request.session['email_empresa'] = self.empresa.email
                request.session['id_empresa'] = self.empresa.id
                request.session['empresa'] = True
                return self.empresa
            except Empresas.DoesNotExist:
                return False
        else:
            return False

    def empresa_update(self,
                       id=None,
                       email=None,
                       razao_social=None,
                       endereco=None,
                       ramo=None,
                       numero=None,
                       senha=None):
        if id:
            self.empresa = self.get_empresa_by_id(id=id)
            if self.empresa:
                if senha:
                    self.empresa.senha = HashPassword(senha)
                self.empresa.email = email
                self.empresa.razao_social = razao_social
                self.empresa.endereco = endereco
                self.empresa.ramo = ramo
                self.empresa.numero = numero
                self.empresa.save()
                return True
        else:
            return False

    def get_empresa_by_id(self, id=id):
        if id:
            self.id = id
            try:
                self.empresa = Empresas.objects.get(pk=self.id)
                return self.empresa
            except Empresas.DoesNotExist:
                return False
        else:
            return False
Example #5
0
class Article(models.Model):

    """
    A simple model.
    Use Article.get_articles(CATEGORY=None, TAG=None, NUM=100) to
        get available articles list.
    Use Article.get_recently_articles(RECENTLY_ARTICLES_NUM) to get
        recently(RECENTLY_ARTICLES_NUM) articles.
    Use Article.get_hots_articles(HOT_ARTICLES_NUM) to
        get hot(HOT_ARTICLES_NUM) articles.
    Use article_object.related_articles(REALITVE_ARTICLES_NUM) to
        get related_articles of an object.
    """
    author = models.ForeignKey(User, verbose_name=_(u"Author"))
    category = models.ForeignKey(Category, verbose_name=_(u'Category'))

    title = models.CharField(max_length=100, verbose_name=_(u'Title'))
    tags = models.CharField(max_length=100,
                            null=True,
                            blank=True,
                            verbose_name=_(u'Tags'),
                            help_text=_(u"Use the comma(',') separated")
                            )

    summary = models.TextField(
        verbose_name=_(u'Summary'),
        validators=[MinLengthValidator(30)],
        error_messages={"min_length":
                        _("At least %(limit_value)d word,please!(it has %(show_value)d).")
                        }
    )
    content = wmd_models.MarkDownField(verbose_name=_(u'Content'))

    title_image = ProcessedImageField(upload_to='thumbnail',
                                      processors=[ResizeToFill(70, 70)],
                                      format='JPEG',
                                      options={'quality': 60}
                                      )

    status = models.IntegerField(
        default=0, choices=STATUS.items(), verbose_name=_(u'Status'))
    view_times = models.IntegerField(default=1)
    like_times = models.IntegerField(default=1)

    liked_ip = models.TextField(verbose_name=_(u'liked_ip'))
    disliked_ip = models.TextField(verbose_name=_(u'disliked_ip'))

    is_top = models.BooleanField(default=False, verbose_name=_(u'Top'))

    create_time = models.DateTimeField(
        _(u'Create Time'), auto_now_add=True, editable=True)
    update_time = models.DateTimeField(_(u'Update Time'), auto_now=True)

    def __unicode__(self):
        return self.title

    def tags_list(self):
        """
        Use article_object.tags_list() to split and get article_object's tags.
        """
        return [tag.strip() for tag in self.tags.split(',')]

    def related_articles(self, num):
        """
        A simple method.
        Use article_object.related_articles(REALITVE_ARTICLES_NUM) to
            get related_articles of an object.
        """
        related_articles = None
        try:
            related_articles = Article.objects.values('id', 'title', 'view_times', 'update_time', 'author').\
                filter(tags__icontains=self.tags_list()[0]).\
                exclude(id=self.id)[:num]
        except IndexError:
            pass

        if not related_articles:
            related_articles = Article.objects.values('id', 'title', 'view_times', 'update_time', 'author').\
                filter(category=self.category).\
                exclude(id=self.id)[:num]

        return related_articles

    @classmethod
    def get_articles(cls, CATEGORY=None, TAG=None, NUM=100):
        """
        A simple classmethod.
        Use Article.get_articles(CATEGORY=None, TAG=None, NUM=100) to
            get articles list.
        """
        if CATEGORY:
            article_list = cls.objects.filter(
                Q(status=0) & Q(category__name__icontains=CATEGORY))[:NUM]
            return article_list
        if TAG:
            article_list = cls.objects.filter(
                Q(status=0) & Q(tags__icontains=TAG))[:NUM]
            return article_list
        return cls.objects.filter(status=0)[:NUM]

    @classmethod
    def get_all_tags_list(cls):
        """
        A simple classmethod.
        Use Article.get_all_tags_list() to get all articles' tags list.
        """
        all_tags_list = []
        # obj_list = cls.objects.filter(status=0).order_by('-update_time')
        obj_list = Article.objects.all()
        for obj in obj_list:
            all_tags_list = all_tags_list + obj.tags_list()
            # for tag in obj.tags.split(','):
            #     all_tags_list.append(tag)
        return all_tags_list

    @classmethod
    def get_recently_articles(cls, num):
        """
        A simple classmethod.
        Use Article.get_recently_articles(RECENTLY_ARTICLES_NUM) to
            get recently(RECENTLY_ARTICLES_NUM) articles.
        """
        return cls.objects.values('title', 'view_times', 'update_time', 'author')\
            .filter(status=0).order_by('-update_time')[:num]

    @classmethod
    def get_hots_articles(cls, num):
        """
        A simple classmethod.
        Use Article.get_hots_articles(HOT_ARTICLES_NUM) to
            get hot(HOT_ARTICLES_NUM) articles.
        """
        return cls.objects.values('id', 'title', 'view_times', 'update_time', 'author').\
            filter(status=0).order_by('-view_times'
                                      )[:num]

    class Meta:
        ordering = ['-is_top', '-update_time', '-create_time']
        verbose_name_plural = verbose_name = _(u"Article")
Example #6
0
class Project(ProjectMixin, models.Model):
    """
    """
    objects = ProjectManager()
    __original_label_config = None

    title = models.CharField(
        _('title'),
        null=True,
        blank=True,
        default='',
        max_length=settings.PROJECT_TITLE_MAX_LEN,
        help_text=
        f'Project name. Must be between {settings.PROJECT_TITLE_MIN_LEN} and {settings.PROJECT_TITLE_MAX_LEN} characters long.',
        validators=[
            MinLengthValidator(settings.PROJECT_TITLE_MIN_LEN),
            MaxLengthValidator(settings.PROJECT_TITLE_MAX_LEN)
        ])
    description = models.TextField(_('description'),
                                   blank=True,
                                   null=True,
                                   default='',
                                   help_text='Project description')

    organization = models.ForeignKey('organizations.Organization',
                                     on_delete=models.CASCADE,
                                     related_name='projects',
                                     null=True)
    label_config = models.TextField(
        _('label config'),
        blank=True,
        null=True,
        default='<View></View>',
        help_text=
        'Label config in XML format. See more about it in documentation')
    expert_instruction = models.TextField(
        _('expert instruction'),
        blank=True,
        null=True,
        default='',
        help_text='Labeling instructions in HTML format')
    show_instruction = models.BooleanField(
        _('show instruction'),
        default=False,
        help_text='Show instructions to the annotator before they start')

    show_skip_button = models.BooleanField(
        _('show skip button'),
        default=True,
        help_text=
        'Show a skip button in interface and allow annotators to skip the task'
    )
    enable_empty_annotation = models.BooleanField(
        _('enable empty annotation'),
        default=True,
        help_text='Allow annotators to submit empty annotations')

    show_annotation_history = models.BooleanField(
        _('show annotation history'),
        default=False,
        help_text='Show annotation history to annotator')
    show_collab_predictions = models.BooleanField(
        _('show predictions to annotator'),
        default=True,
        help_text='If set, the annotator can view model predictions')
    evaluate_predictions_automatically = models.BooleanField(
        _('evaluate predictions automatically'),
        default=False,
        help_text='Retrieve and display predictions when loading a task')
    token = models.CharField(_('token'),
                             max_length=256,
                             default=create_hash,
                             null=True,
                             blank=True)
    result_count = models.IntegerField(
        _('result count'),
        default=0,
        help_text='Total results inside of annotations counter')
    color = models.CharField(_('color'),
                             max_length=16,
                             default='#FFFFFF',
                             null=True,
                             blank=True)

    created_by = models.ForeignKey(settings.AUTH_USER_MODEL,
                                   related_name='created_projects',
                                   on_delete=models.SET_NULL,
                                   null=True,
                                   verbose_name=_('created by'))
    maximum_annotations = models.IntegerField(
        _('maximum annotation number'),
        default=1,
        help_text='Maximum number of annotations for one task. '
        'If the number of annotations per task is equal or greater '
        'to this value, the task is completed (is_labeled=True)')
    min_annotations_to_start_training = models.IntegerField(
        _('min_annotations_to_start_training'),
        default=10,
        help_text=
        'Minimum number of completed tasks after which model training is started'
    )

    control_weights = JSONField(_('control weights'),
                                null=True,
                                default=dict,
                                help_text='Weights for control tags')
    model_version = models.TextField(
        _('model version'),
        blank=True,
        null=True,
        default='',
        help_text='Machine learning model version')
    data_types = JSONField(_('data_types'), default=dict, null=True)

    is_draft = models.BooleanField(
        _('is draft'),
        default=False,
        help_text='Whether or not the project is in the middle of being created'
    )
    is_published = models.BooleanField(
        _('published'),
        default=False,
        help_text='Whether or not the project is published to annotators')
    created_at = models.DateTimeField(_('created at'), auto_now_add=True)
    updated_at = models.DateTimeField(_('updated at'), auto_now=True)

    SEQUENCE = 'Sequential sampling'
    UNIFORM = 'Uniform sampling'
    UNCERTAINTY = 'Uncertainty sampling'

    SAMPLING_CHOICES = ((
        SEQUENCE, 'Tasks are ordered by Data manager ordering'
    ), (UNIFORM, 'Tasks are chosen randomly'), (
        UNCERTAINTY,
        'Tasks are chosen according to model uncertainty scores (active learning mode)'
    ))

    sampling = models.CharField(max_length=100,
                                choices=SAMPLING_CHOICES,
                                null=True,
                                default=SEQUENCE)
    show_ground_truth_first = models.BooleanField(_('show ground truth first'),
                                                  default=True)
    show_overlap_first = models.BooleanField(_('show overlap first'),
                                             default=True)
    overlap_cohort_percentage = models.IntegerField(
        _('overlap_cohort_percentage'), default=100)

    task_data_login = models.CharField(
        _('task_data_login'),
        max_length=256,
        blank=True,
        null=True,
        help_text='Task data credentials: login')
    task_data_password = models.CharField(
        _('task_data_password'),
        max_length=256,
        blank=True,
        null=True,
        help_text='Task data credentials: password')

    def __init__(self, *args, **kwargs):
        super(Project, self).__init__(*args, **kwargs)
        self.__original_label_config = self.label_config
        self.__maximum_annotations = self.maximum_annotations
        self.__overlap_cohort_percentage = self.overlap_cohort_percentage

        # TODO: once bugfix with incorrect data types in List
        # logging.warning('! Please, remove code below after patching of all projects (extract_data_types)')
        if self.label_config is not None:
            if self.data_types != extract_data_types(self.label_config):
                self.data_types = extract_data_types(self.label_config)

    @property
    def num_tasks(self):
        return self.tasks.count()

    def get_current_predictions(self):
        return Prediction.objects.filter(
            Q(task__project=self.id) & Q(model_version=self.model_version))

    @property
    def num_predictions(self):
        return self.get_current_predictions().count()

    @property
    def num_annotations(self):
        return Annotation.objects.filter(
            Q(task__project=self) & Q_finished_annotations
            & Q(ground_truth=False)).count()

    @property
    def has_predictions(self):
        return self.get_current_predictions().exists()

    @property
    def has_any_predictions(self):
        return Prediction.objects.filter(Q(task__project=self.id)).exists()

    @property
    def business(self):
        return self.created_by.business

    @property
    def is_private(self):
        return None

    @property
    def has_storages(self):
        return hasattr(
            self, 'storages'
        ) and self.storages is not None and self.storages.count() > 0

    @property
    def secure_mode(self):
        return False

    @property
    def one_object_in_label_config(self):
        return len(self.data_types) <= 1

    @property
    def only_undefined_field(self):
        return self.one_object_in_label_config and self.summary.common_data_columns and self.summary.common_data_columns[
            0] == settings.DATA_UNDEFINED_NAME

    @property
    def get_labeled_count(self):
        return self.tasks.filter(is_labeled=True).count()

    @property
    def get_collected_count(self):
        return self.tasks.count()

    @property
    def get_total_possible_count(self):
        """
            Tasks has overlap - how many tc should be accepted
            possible count = sum [ t.overlap for t in tasks]

        :return: N int total amount of Annotations that should be submitted
        """
        if self.tasks.count() == 0:
            return 0
        return self.tasks.aggregate(Sum('overlap'))['overlap__sum']

    @property
    def get_available_for_labeling(self):
        return self.get_collected_count - self.get_labeled_count

    @property
    def need_annotators(self):
        return self.maximum_annotations - self.num_annotators

    @classmethod
    def find_by_invite_url(cls, url):
        token = url.strip('/').split('/')[-1]
        if len(token):
            return Project.objects.get(token=token)
        else:
            raise KeyError(f'Can\'t find Project by invite URL: {url}')

    def reset_token(self):
        self.token = create_hash()
        self.save()

    def add_collaborator(self, user):
        created = False
        with transaction.atomic():
            try:
                ProjectMember.objects.get(user=user, project=self)
            except ProjectMember.DoesNotExist:
                ProjectMember.objects.create(user=user, project=self)
                created = True
            else:
                logger.debug(
                    f'Project membership {self} for user {user} already exists'
                )
        return created

    def has_collaborator(self, user):
        return ProjectMember.objects.filter(user=user, project=self).exists()

    def has_collaborator_enabled(self, user):
        membership = ProjectMember.objects.filter(user=user, project=self)
        return membership.exists() and membership.first().enabled

    def update_tasks_states(self, maximum_annotations_changed,
                            overlap_cohort_percentage_changed,
                            tasks_number_changed):

        # if only maximum annotations parameter is tweaked
        if maximum_annotations_changed and not overlap_cohort_percentage_changed:
            tasks_with_overlap = self.tasks.filter(overlap__gt=1)
            if tasks_with_overlap.exists():
                # if there is a part with overlaped tasks, affect only them
                tasks_with_overlap.update(overlap=self.maximum_annotations)
            else:
                # otherwise affect all tasks
                self.tasks.update(overlap=self.maximum_annotations)

        # if cohort slider is tweaked
        elif overlap_cohort_percentage_changed and self.maximum_annotations > 1:
            self._rearrange_overlap_cohort()

        # if adding/deleting tasks and cohort settings are applied
        elif tasks_number_changed and self.overlap_cohort_percentage < 100 and self.maximum_annotations > 1:
            self._rearrange_overlap_cohort()

        if maximum_annotations_changed or overlap_cohort_percentage_changed:
            bulk_update_stats_project_tasks(
                self.tasks.filter(
                    Q(annotations__isnull=False)
                    & Q(annotations__ground_truth=False)))

    def _rearrange_overlap_cohort(self):
        tasks_with_overlap = self.tasks.filter(overlap__gt=1)
        tasks_with_overlap_count = tasks_with_overlap.count()
        total_tasks = self.tasks.count()

        new_tasks_with_overlap_count = int(self.overlap_cohort_percentage /
                                           100 * total_tasks + 0.5)
        if tasks_with_overlap_count > new_tasks_with_overlap_count:
            # TODO: warn if we try to reduce current cohort that is already labeled with overlap
            reduce_by = tasks_with_overlap_count - new_tasks_with_overlap_count
            reduce_tasks = sample_query(tasks_with_overlap, reduce_by)
            reduce_tasks.update(overlap=1)
            reduced_tasks_ids = reduce_tasks.values_list('id', flat=True)
            tasks_with_overlap.exclude(id__in=reduced_tasks_ids).update(
                overlap=self.maximum_annotations)

        elif tasks_with_overlap_count < new_tasks_with_overlap_count:
            increase_by = new_tasks_with_overlap_count - tasks_with_overlap_count
            tasks_without_overlap = self.tasks.filter(overlap=1)
            increase_tasks = sample_query(tasks_without_overlap, increase_by)
            increase_tasks.update(overlap=self.maximum_annotations)
            tasks_with_overlap.update(overlap=self.maximum_annotations)

    def remove_tasks_by_file_uploads(self, file_upload_ids):
        self.tasks.filter(file_upload_id__in=file_upload_ids).delete()

    def advance_onboarding(self):
        """ Move project to next onboarding step
        """
        po_qs = self.steps_left.order_by('step__order')
        count = po_qs.count()

        if count:
            po = po_qs.first()
            po.finished = True
            po.save()

            return count != 1

    def created_at_prettify(self):
        return self.created_at.strftime("%d %b %Y %H:%M:%S")

    def onboarding_step_finished(self, step):
        """ Mark specific step as finished
        """
        pos = ProjectOnboardingSteps.objects.get(code=step)
        po = ProjectOnboarding.objects.get(project=self, step=pos)
        po.finished = True
        po.save()

        return po

    def data_types_json(self):
        return json.dumps(self.data_types)

    def available_data_keys(self):
        return sorted(list(self.data_types.keys()))

    @classmethod
    def validate_label_config(cls, config_string):
        validate_label_config(config_string)

    def validate_config(self, config_string):
        self.validate_label_config(config_string)
        if not hasattr(self, 'summary'):
            return

        # validate data columns consistency
        fields_from_config = get_all_object_tag_names(config_string)
        if not fields_from_config:
            logger.debug(f'Data fields not found in labeling config')
            return
        fields_from_data = set(self.summary.common_data_columns)
        fields_from_data.discard(settings.DATA_UNDEFINED_NAME)
        if fields_from_data and not fields_from_config.issubset(
                fields_from_data):
            different_fields = list(
                fields_from_config.difference(fields_from_data))
            raise ValidationError(
                f'These fields are not present in the data: {",".join(different_fields)}'
            )

        # validate annotations consistency
        annotations_from_config = set(
            get_all_control_tag_tuples(config_string))
        if not annotations_from_config:
            logger.debug(f'Annotation schema is not found in config')
            return
        annotations_from_data = set(self.summary.created_annotations)
        if annotations_from_data and not annotations_from_data.issubset(
                annotations_from_config):
            different_annotations = list(
                annotations_from_data.difference(annotations_from_config))
            diff_str = []
            for ann_tuple in different_annotations:
                from_name, to_name, t = ann_tuple.split('|')
                diff_str.append(
                    f'{self.summary.created_annotations[ann_tuple]} '
                    f'with from_name={from_name}, to_name={to_name}, type={t}')
            diff_str = '\n'.join(diff_str)
            raise ValidationError(
                f'Created annotations are incompatible with provided labeling schema, '
                f'we found:\n{diff_str}')

        # validate labels consistency
        labels_from_config = get_all_labels(config_string)
        created_labels = self.summary.created_labels
        for control_tag_from_data, labels_from_data in created_labels.items():
            # Check if labels created in annotations, and their control tag has been removed
            if labels_from_data and control_tag_from_data not in labels_from_config:
                raise ValidationError(
                    f'There are {sum(labels_from_data.values(), 0)} annotation(s) created with tag '
                    f'"{control_tag_from_data}", you can\'t remove it')
            labels_from_config_by_tag = set(
                labels_from_config[control_tag_from_data])
            if not set(labels_from_data).issubset(
                    set(labels_from_config_by_tag)):
                different_labels = list(
                    set(labels_from_data).difference(
                        labels_from_config_by_tag))
                diff_str = '\n'.join(f'{l} ({labels_from_data[l]} annotations)'
                                     for l in different_labels)
                raise ValidationError(
                    f'These labels still exist in annotations:\n{diff_str}')

    def _label_config_has_changed(self):
        return self.label_config != self.__original_label_config

    def delete_predictions(self):
        predictions = Prediction.objects.filter(task__project=self)
        count = predictions.count()
        predictions.delete()
        return {'deleted_predictions': count}

    def get_updated_weights(self):
        outputs = parse_config(self.label_config)
        control_weights = {}
        exclude_control_types = ('Filter', )
        for control_name in outputs:
            control_type = outputs[control_name]['type']
            if control_type in exclude_control_types:
                continue
            control_weights[control_name] = {
                'overall': 1.0,
                'type': control_type,
                'labels': {
                    label: 1.0
                    for label in outputs[control_name].get('labels', [])
                }
            }
        return control_weights

    def save(self, *args, recalc=True, **kwargs):
        exists = True if self.pk else False

        if self.label_config and (self._label_config_has_changed()
                                  or not exists or not self.control_weights):
            self.control_weights = self.get_updated_weights()
        super(Project, self).save(*args, **kwargs)
        project_with_config_just_created = not exists and self.pk and self.label_config
        if self._label_config_has_changed(
        ) or project_with_config_just_created:
            self.data_types = extract_data_types(self.label_config)

        if self._label_config_has_changed():
            self.__original_label_config = self.label_config

        if not exists:
            steps = ProjectOnboardingSteps.objects.all()
            objs = [
                ProjectOnboarding(project=self, step=step) for step in steps
            ]
            ProjectOnboarding.objects.bulk_create(objs)

        # argument for recalculate project task stats
        if recalc:
            self.update_tasks_states(
                maximum_annotations_changed=self.__maximum_annotations !=
                self.maximum_annotations,
                overlap_cohort_percentage_changed=self.
                __overlap_cohort_percentage != self.overlap_cohort_percentage,
                tasks_number_changed=False)
            self.__maximum_annotations = self.maximum_annotations
            self.__overlap_cohort_percentage = self.overlap_cohort_percentage

    def get_member_ids(self):
        if hasattr(self, 'team_link'):
            # project has defined team scope
            # TODO: avoid checking team but rather add all project members when creating a project
            return self.team_link.team.members.values_list('user', flat=True)
        else:
            from users.models import User
            # TODO: may want to return all users from organization
            return User.objects.none()

    def has_team_user(self, user):
        return hasattr(self,
                       'team_link') and self.team_link.team.has_user(user)

    def annotators(self):
        """ Annotators connected to this project including team members
        """
        from users.models import User
        member_ids = self.get_member_ids()
        team_members = User.objects.filter(id__in=member_ids).order_by('email')

        # add members from invited projects
        project_member_ids = self.members.values_list('user__id', flat=True)
        project_members = User.objects.filter(id__in=project_member_ids)

        annotators = team_members | project_members

        # set annotator.team_member=True if annotator is not an invited user
        annotators = annotators.annotate(team_member=Case(
            When(id__in=project_member_ids, then=Value(False)),
            default=Value(True),
            output_field=BooleanField(),
        ))
        return annotators

    def annotators_with_annotations(self, min_count=500):
        """ Annotators with annotation number > min_number

        :param min_count: minimal annotation number to leave an annotators
        :return: filtered annotators
        """
        annotators = self.annotators()
        q = Q(
            annotations__task__project=self) & Q_task_finished_annotations & Q(
                annotations__ground_truth=False)
        annotators = annotators.annotate(
            annotation_count=Count('annotations', filter=q, distinct=True))
        return annotators.filter(annotation_count__gte=min_count)

    def labeled_tasks(self):
        return self.tasks.filter(is_labeled=True)

    def has_annotations(self):
        from tasks.models import Annotation  # prevent cycling imports
        return Annotation.objects.filter(
            Q(task__project=self) & Q(ground_truth=False)).count() > 0

    # [TODO] this should be a template tag or something like this
    @property
    def label_config_line(self):
        c = self.label_config
        return config_line_stipped(c)

    def get_sample_task(self, label_config=None):
        config = label_config or self.label_config
        task, _, _ = get_sample_task(config)
        return task

    def eta(self):
        """
            Show eta for project to be finished
            eta = avg task annotations finish time * remain annotations

            task has overlap = amount of task annotations to consider as finished (is_labeled)
            remain annotations = sum ( task annotations to be done to fulfill each unfinished task overlap)

        :return: time in seconds
        """
        # finished tasks * overlap
        finished_tasks = Task.objects.filter(project=self.id, is_labeled=True)
        # one could make more than need to overlap
        min_n_finished_annotations = sum([ft.overlap for ft in finished_tasks])

        annotations_unfinished_tasks = Annotation.objects.filter(
            task__project=self.id,
            task__is_labeled=False,
            ground_truth=False,
            result__isnull=False).count()

        # get minimum remain annotations
        total_annotations_needed = self.get_total_possible_count
        annotations_remain = total_annotations_needed - min_n_finished_annotations - annotations_unfinished_tasks

        # get average time of all finished TC
        finished_annotations = Annotation.objects.filter(
            Q(task__project=self.id) & Q(ground_truth=False),
            result__isnull=False).values('lead_time')
        avg_lead_time = finished_annotations.aggregate(
            avg_lead_time=Avg('lead_time'))['avg_lead_time']

        if avg_lead_time is None:
            return None
        return avg_lead_time * annotations_remain

    def finished(self):
        return not self.tasks.filter(is_labeled=False).exists()

    def annotations_lead_time(self):
        annotations = Annotation.objects.filter(
            Q(task__project=self.id) & Q(ground_truth=False))
        return annotations.aggregate(
            avg_lead_time=Avg('lead_time'))['avg_lead_time']

    @staticmethod
    def django_settings():
        return settings

    @staticmethod
    def max_tasks_file_size():
        return settings.TASKS_MAX_FILE_SIZE

    def get_control_tags_from_config(self):
        return parse_config(self.label_config)

    def get_parsed_config(self):
        return parse_config(self.label_config)

    def __str__(self):
        return f'{self.title} (id={self.id})' or _(
            "Business number %d") % self.pk

    class Meta:
        db_table = 'project'
Example #7
0
class UserForm(AbstractParticipantForm):
    """
    Form for user profiles
    """
    is_active = forms.BooleanField(
        label=_("Active"),
        required=False,
        help_text=_("Whether this user is active, disable to remove access."))

    email = forms.CharField(max_length=256,
                            label=_("Email"),
                            help_text=_("Email address and login."))

    password = forms.CharField(
        widget=forms.PasswordInput,
        validators=[MinLengthValidator(8)],
        label=_("Password"),
        help_text=_("Password used to log in (minimum of 8 characters)."))

    new_password = forms.CharField(
        widget=forms.PasswordInput,
        validators=[MinLengthValidator(8)],
        required=False,
        label=_("New password"),
        help_text=_(
            "Password used to login (minimum of 8 characters, optional)."))

    confirm_password = forms.CharField(widget=forms.PasswordInput,
                                       required=False,
                                       label=_("Confirm password"))

    change_password = forms.BooleanField(
        label=_("Require change"),
        required=False,
        help_text=_("Whether user must change password on next login."))

    rooms = forms.ModelMultipleChoiceField(
        label=_("Rooms (chatting)"),
        queryset=Room.objects.all(),
        required=False,
        help_text=_("Chat rooms which this user can chat in."))

    manage_rooms = forms.ModelMultipleChoiceField(
        label=_("Rooms (manage)"),
        queryset=Room.objects.all(),
        required=False,
        help_text=_("Chat rooms which this user can manage."))

    def __init__(self, *args, **kwargs):
        super(UserForm, self).__init__(*args, **kwargs)

        if self.user.get_org():
            org_rooms = Room.get_all(self.user.get_org()).order_by('name')
            self.fields['rooms'].queryset = org_rooms
            self.fields['manage_rooms'].queryset = org_rooms

    def clean(self):
        cleaned_data = super(UserForm, self).clean()

        password = cleaned_data.get('password', None) or cleaned_data.get(
            'new_password', None)
        if password:
            confirm_password = cleaned_data.get('confirm_password', '')
            if password != confirm_password:
                self.add_error('confirm_password', _("Passwords don't match."))

    class Meta:
        model = User
        exclude = ()
Example #8
0
class AgencyProfile(TimeStampedModel):
    NUMBER_OF_SPECIALISTS = ((1, '<5'), (2, '5-10'), (3, '10-20'), (4, '>20'))

    user = models.OneToOneField(User,
                                related_name='agency_profile',
                                on_delete=models.CASCADE)
    company_logo = models.ImageField(_('Logo'),
                                     upload_to='company_logos',
                                     blank=True,
                                     null=True)
    company_name = models.CharField(_('Company name'),
                                    max_length=255,
                                    blank=False)
    number_of_specialists = models.IntegerField(
        _('Number of available specialists'),
        choices=NUMBER_OF_SPECIALISTS,
        null=True)
    communication_languages = MultiSelectField(_('Communication languages'),
                                               choices=LANGUAGES,
                                               blank=False)
    company_description = models.TextField(
        _('Description'),
        blank=True,
        validators=[
            MinLengthValidator(100,
                               message=_("Please enter minimum 100 symbols")),
            MaxLengthValidator(2000,
                               message=_("Please enter maximun 2000 symbols"))
        ])
    founded = models.DateField(_('Founded'), blank=False)
    company_type = models.CharField(_('Company type'),
                                    max_length=255,
                                    blank=False)
    average_hourly_rate = models.OneToOneField(
        'AverageHourlyRate',
        related_name='average_hourly_rate',
        on_delete=models.CASCADE,
        blank=True,
        null=True)
    specialization = models.ManyToManyField(
        'Specialization', related_name='agency_specilaizations', blank=False)
    technologies = models.ManyToManyField('Technology',
                                          related_name='agency_technologies',
                                          blank=False)
    company_adress = models.CharField(_('Adress'), max_length=255, blank=False)
    postal_code = models.CharField(_('Postal Code'),
                                   max_length=255,
                                   blank=False)
    city = models.CharField(_('City'), max_length=255, blank=False)
    country = models.CharField(_('Country'),
                               choices=COUNTRY_CHOICES,
                               max_length=255,
                               blank=False,
                               db_index=True)
    company_website = models.CharField(_('Website'), max_length=255)
    phone_number = models.CharField(_('Phone number'),
                                    max_length=16,
                                    blank=False)

    objects = AgencyManager()

    class Meta:
        verbose_name = 'agency profile'
        verbose_name_plural = 'agency profiles'

    def __str__(self):
        return self.company_name

    def get_contact_persons_email(self):
        contact_persons = self.contact_persons.all()
        return [cp.email for cp in contact_persons]

    def activate_membership(self):
        self.user.activate_membership()
Example #9
0
class Ingredient(AbstractSubmissionModel, AbstractLicenseModel, models.Model):
    """
    An ingredient, with some approximate nutrition values
    """
    objects = SubmissionManager()
    """Custom manager"""

    ENERGY_APPROXIMATION = 15
    """
    How much the calculated energy from protein, etc. can deviate from the
    energy amount given (in percent).
    """

    # Metaclass to set some other properties
    class Meta:
        ordering = [
            "name",
        ]

    # Meta data
    language = models.ForeignKey(Language,
                                 verbose_name=_('Language'),
                                 editable=False,
                                 on_delete=models.CASCADE)

    creation_date = models.DateField(_('Date'), auto_now_add=True)
    update_date = models.DateField(_('Date'),
                                   auto_now=True,
                                   blank=True,
                                   editable=False)

    # Product infos
    name = models.CharField(max_length=200,
                            verbose_name=_('Name'),
                            validators=[MinLengthValidator(3)])

    energy = models.IntegerField(verbose_name=_('Energy'),
                                 help_text=_('In kcal per 100g'))

    protein = models.DecimalField(
        decimal_places=3,
        max_digits=6,
        verbose_name=_('Protein'),
        help_text=_('In g per 100g of product'),
        validators=[MinValueValidator(0),
                    MaxValueValidator(100)])

    carbohydrates = models.DecimalField(
        decimal_places=3,
        max_digits=6,
        verbose_name=_('Carbohydrates'),
        help_text=_('In g per 100g of product'),
        validators=[MinValueValidator(0),
                    MaxValueValidator(100)])

    carbohydrates_sugar = models.DecimalField(
        decimal_places=3,
        max_digits=6,
        blank=True,
        null=True,
        verbose_name=_('Sugar content in carbohydrates'),
        help_text=_('In g per 100g of product'),
        validators=[MinValueValidator(0),
                    MaxValueValidator(100)])

    fat = models.DecimalField(
        decimal_places=3,
        max_digits=6,
        verbose_name=_('Fat'),
        help_text=_('In g per 100g of product'),
        validators=[MinValueValidator(0),
                    MaxValueValidator(100)])

    fat_saturated = models.DecimalField(
        decimal_places=3,
        max_digits=6,
        blank=True,
        null=True,
        verbose_name=_('Saturated fat content in fats'),
        help_text=_('In g per 100g of product'),
        validators=[MinValueValidator(0),
                    MaxValueValidator(100)])

    fibres = models.DecimalField(
        decimal_places=3,
        max_digits=6,
        blank=True,
        null=True,
        verbose_name=_('Fibres'),
        help_text=_('In g per 100g of product'),
        validators=[MinValueValidator(0),
                    MaxValueValidator(100)])

    sodium = models.DecimalField(
        decimal_places=3,
        max_digits=6,
        blank=True,
        null=True,
        verbose_name=_('Sodium'),
        help_text=_('In g per 100g of product'),
        validators=[MinValueValidator(0),
                    MaxValueValidator(100)])

    code = models.CharField(max_length=200,
                            null=True,
                            blank=True,
                            db_index=True)
    """Internal ID of the source database, e.g. a barcode or similar"""

    source_name = models.CharField(max_length=200, null=True, blank=True)
    """Name of the source, such as Open Food Facts"""

    source_url = models.URLField(verbose_name=_('Link'),
                                 help_text=_('Link to product'),
                                 blank=True,
                                 null=True)
    """URL of the product at the source"""

    last_imported = models.DateTimeField(_('Date'),
                                         auto_now_add=True,
                                         null=True,
                                         blank=True)

    common_name = models.CharField(max_length=200, null=True, blank=True)

    category = models.ForeignKey(IngredientCategory,
                                 verbose_name=_('Category'),
                                 on_delete=models.CASCADE,
                                 null=True,
                                 blank=True)

    brand = models.CharField(max_length=200,
                             verbose_name=_('Brand name of product'),
                             null=True,
                             blank=True)

    #
    # Django methods
    #

    def get_absolute_url(self):
        """
        Returns the canonical URL to view this object.

        Since some names consist of only non-ascii characters (e.g. 감자깡), the
        resulting slug would be empty and no URL would match. In that case, use
        the regular URL with only the ID.
        """
        slug = slugify(self.name)
        if not slug:
            return reverse('nutrition:ingredient:view', kwargs={'id': self.id})
        else:
            return reverse('nutrition:ingredient:view',
                           kwargs={
                               'id': self.id,
                               'slug': slug
                           })

    def clean(self):
        """
        Do a very broad sanity check on the nutritional values according to
        the following rules:
        - 1g of protein: 4kcal
        - 1g of carbohydrates: 4kcal
        - 1g of fat: 9kcal

        The sum is then compared to the given total energy, with ENERGY_APPROXIMATION
        percent tolerance.
        """

        # Note: calculations in 100 grams, to save us the '/100' everywhere
        energy_protein = 0
        if self.protein:
            energy_protein = self.protein * ENERGY_FACTOR['protein']['kg']

        energy_carbohydrates = 0
        if self.carbohydrates:
            energy_carbohydrates = self.carbohydrates * ENERGY_FACTOR[
                'carbohydrates']['kg']

        energy_fat = 0
        if self.fat:
            # TODO: for some reason, during the tests the fat value is not
            #       converted to decimal (django 1.9)
            energy_fat = Decimal(self.fat * ENERGY_FACTOR['fat']['kg'])

        energy_calculated = energy_protein + energy_carbohydrates + energy_fat

        # Compare the values, but be generous
        if self.energy:
            energy_upper = self.energy * (
                1 + (self.ENERGY_APPROXIMATION / Decimal(100.0)))
            energy_lower = self.energy * (
                1 - (self.ENERGY_APPROXIMATION / Decimal(100.0)))

            if not ((energy_upper > energy_calculated) and
                    (energy_calculated > energy_lower)):
                raise ValidationError(
                    _('The total energy ({energy}kcal) is not the approximate sum of the '
                      'energy provided by protein, carbohydrates and fat ({energy_calculated}kcal '
                      '+/-{energy_approx}%)'.format(
                          energy=self.energy,
                          energy_calculated=energy_calculated,
                          energy_approx=self.ENERGY_APPROXIMATION)))

    def save(self, *args, **kwargs):
        """
        Reset the cache
        """

        super(Ingredient, self).save(*args, **kwargs)
        cache.delete(cache_mapper.get_ingredient_key(self.id))

    def __str__(self):
        """
        Return a more human-readable representation
        """
        return self.name

    def __eq__(self, other):
        """
        Compare ingredients based on their values, not like django on their PKs
        """

        logger.debug(
            'Overwritten behaviour: comparing ingredients on values, not PK.')
        equal = True
        if isinstance(other, self.__class__):
            for i in self._meta.fields:
                if (hasattr(self, i.name) and hasattr(other, i.name)
                        and (getattr(self, i.name, None) != getattr(
                            other, i.name, None))):
                    equal = False
        else:
            equal = False
        return equal

    def __hash__(self):
        """
        Define a hash function

        This is rather unnecessary, but it seems that newer versions of django
        have a problem when the __eq__ function is implemented, but not the
        __hash__ one. Returning hash(pk) is also django's default.

        :return: hash(pk)
        """
        return hash(self.pk)

    #
    # Own methods
    #
    def compare_with_database(self):
        """
        Compares the current ingredient with the version saved in the database.

        If the current object has no PK, returns false
        """
        if not self.pk:
            return False

        ingredient = Ingredient.objects.get(pk=self.pk)
        if self != ingredient:
            return False
        else:
            return True

    def send_email(self, request):
        """
        Sends an email after being successfully added to the database (for user
        submitted ingredients only)
        """
        try:
            user = User.objects.get(username=self.license_author)
        except User.DoesNotExist:
            return

        if self.license_author and user.email:
            translation.activate(
                user.userprofile.notification_language.short_name)
            url = request.build_absolute_uri(self.get_absolute_url())
            subject = _(
                'Ingredient was successfully added to the general database')
            context = {
                'ingredient': self.name,
                'url': url,
                'site': Site.objects.get_current().domain
            }
            message = render_to_string('ingredient/email_new.tpl', context)
            mail.send_mail(subject,
                           message,
                           settings.WGER_SETTINGS['EMAIL_FROM'], [user.email],
                           fail_silently=True)

    def set_author(self, request):
        if request.user.has_perm('nutrition.add_ingredient'):
            self.status = Ingredient.STATUS_ACCEPTED
            if not self.license_author:
                self.license_author = request.get_host().split(':')[0]
        else:
            if not self.license_author:
                self.license_author = request.user.username

            # Send email to administrator
            subject = _('New user submitted ingredient')
            message = _(
                """The user {0} submitted a new ingredient "{1}".""".format(
                    request.user.username, self.name))
            mail.mail_admins(subject, message, fail_silently=True)

    def get_owner_object(self):
        """
        Ingredient has no owner information
        """
        return False

    @property
    def energy_kilojoule(self):
        """
        returns kilojoules for current ingredient, 0 if energy is uninitialized
        """
        if self.energy:
            return Decimal(self.energy * 4.184).quantize(TWOPLACES)
        else:
            return 0
class DomesticComplaint(models.Model):

    doc_id = models.UUIDField(primary_key=True,
                              default=uuid.uuid4,
                              editable=False,
                              verbose_name='Complaint ID')  #pk

    # own info of customer
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.CASCADE,
                             null=True)
    o_name = models.CharField(
        max_length=128, verbose_name='Complainant Name')  #complainant name
    o_email = models.EmailField(
        max_length=64, verbose_name='Complainant Email')  #complainant email
    o_no = PhoneNumberField(verbose_name='Complainant No')  #complainant no
    o_state = models.CharField(
        max_length=32, verbose_name='Complainant Name')  #complainant state
    o_city = models.CharField(
        max_length=32, verbose_name='Complainant City')  #complainant city
    o_adds = models.TextField(
        max_length=256,
        verbose_name='Complainant Address')  #complainant address
    gender = models.CharField(max_length=8,
                              choices=GENDER_CHOICES,
                              default='MALE',
                              verbose_name='Gender')  #complainant gender

    acc_name = models.CharField(max_length=128,
                                verbose_name='Accused Name')  #accused name
    acc_adds = models.TextField(
        max_length=256, blank=True, null=True,
        verbose_name='Accused address')  #accused address
    acc_state = models.CharField(max_length=32,
                                 verbose_name='Accused state')  #accused state
    acc_city = models.CharField(max_length=32,
                                verbose_name='Accused city')  #accused city
    acc_email = models.EmailField(blank=True,
                                  null=True,
                                  verbose_name='Accused Email')  #accused email
    acc_no = PhoneNumberField(blank=True,
                              null=True,
                              verbose_name='Accused contact No')  #accused no
    acc_gender = models.CharField(
        max_length=8,
        choices=GENDER_CHOICES,
        default='MALE',
        verbose_name='Accused gender')  #accused gender
    case_pending_a = models.CharField(
        max_length=4,
        choices=ICC_CHOICES,
        default='YES',
        verbose_name='case pending at any other court'
    )  #case pending at any other court
    case_pending_w = models.CharField(
        max_length=4,
        choices=ICC_CHOICES,
        default='YES',
        verbose_name='case pending at any women association court'
    )  #case pending at any women association court
    c_description = models.TextField(max_length=4056,
                                     verbose_name='Complainant Description',
                                     validators=[MinLengthValidator(30)
                                                 ])  #complaint discription
    c_document = models.FileField(upload_to='domestic/',
                                  null=True,
                                  blank=True,
                                  verbose_name='Complaint related documents')
    c_filed = models.DateField(auto_now_add=True,
                               verbose_name='Complaint filed date')

    c_amt = models.DecimalField(decimal_places=2,
                                max_digits=10,
                                verbose_name='Complaint Amount',
                                null=True,
                                blank=True)
    p_date = models.DateTimeField(null=True,
                                  verbose_name='Payment Date',
                                  blank=True)
    p_status = models.BooleanField(verbose_name='Payment Status', default=0)
    new_cid = models.CharField(max_length=128,
                               null=True,
                               blank=True,
                               verbose_name='Order ID')
    txn_id = models.CharField(max_length=128,
                              null=True,
                              blank=True,
                              verbose_name='Transaction ID')

    update_flag = models.BooleanField(verbose_name='Information Updated',
                                      default=0)

    admin_reply = models.TextField(max_length=4056,
                                   verbose_name='Update Complaint Status',
                                   null=True,
                                   blank=True)
    admin_document = models.FileField(upload_to='admin/domestic/',
                                      null=True,
                                      blank=True,
                                      verbose_name='Attach documents')

    def __str__(self):
        return self.o_name
Example #11
0
class CandidateProfile(TimeStampedModel):
    user = models.OneToOneField(User,
                                related_name='candidate_profile',
                                on_delete=models.CASCADE)
    first_name = models.CharField(
        _('First name'),
        max_length=255,
        blank=False,
        error_messages={"max_length": _("Please enter maximum 255 symbols")})
    last_name = models.CharField(
        _('Last name'),
        max_length=255,
        blank=False,
        error_messages={"max_length": _("Please enter maximum 255 symbols")})
    nationality = models.CharField(_('Nationality'),
                                   max_length=255,
                                   blank=False)
    image = models.ImageField(_('Profile image'),
                              upload_to='candidate_images',
                              blank=True,
                              null=True)
    job_position = models.CharField(_('Job position'),
                                    max_length=255,
                                    blank=False)
    cover_letter = models.TextField(
        _('Cover letter'),
        validators=[
            MinLengthValidator(
                255, message=_("Please enter between 255 and 1000 symbols")),
            MaxLengthValidator(
                1000, message=_("Please enter between 255 and 1000 symbols")),
        ],
        blank=True,
        null=True)
    hourly_rate = models.OneToOneField(HourlyRate,
                                       related_name='hourly_rate',
                                       on_delete=models.CASCADE,
                                       blank=True,
                                       null=True)
    monthly_rate = models.OneToOneField(MonthlyRate,
                                        related_name='monthly_rate',
                                        on_delete=models.CASCADE,
                                        blank=True,
                                        null=True)
    adress = models.CharField(_('Adress'), max_length=255, blank=False)
    postal_code = models.CharField(_('Postal Code'),
                                   max_length=255,
                                   blank=False)
    city = models.CharField(_('City'), max_length=255, blank=False)
    country = models.CharField(_('Country'),
                               choices=COUNTRY_CHOICES,
                               max_length=255,
                               blank=False,
                               db_index=True)
    date_of_birth = models.DateField(_('Date of birth'), blank=False)
    experience = models.IntegerField(_('Experience'),
                                     choices=EXPERIENCE,
                                     blank=False,
                                     db_index=True)
    experience_level = models.IntegerField(
        _('Experience level'),
        choices=EXPERIENCE_LVL,
        blank=False,
        db_index=True,
    )
    job_type = MultiSelectField(_('Job type'),
                                choices=JOB_TYPE,
                                blank=False,
                                db_index=True)
    specialization = models.ManyToManyField(
        'Specialization',
        related_name='candidate_specilaizations',
        blank=False)
    technologies = models.ManyToManyField('Technology',
                                          related_name='technologies',
                                          blank=False,
                                          db_index=True)
    communication_languages = MultiSelectField(_('Communication Language'),
                                               choices=LANGUAGES,
                                               blank=False)
    phone_number = models.CharField(_('Phone number'),
                                    max_length=16,
                                    blank=False)
    email = models.EmailField(_('Email address'), blank=False)
    linkedin_url = models.URLField(_('LinkedIn Profile'),
                                   blank=True,
                                   null=True)
    is_identified = models.BooleanField(_('Is identified'), default=False)

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

    @cached_property
    def full_name(self):
        return "{} {}".format(self.first_name, self.last_name)
Example #12
0
class User(AbstractBaseUser, PermissionsMixin, TimeStampedModel):
    class Meta:
        verbose_name = _("User")
        verbose_name_plural = _("Users")

    email = models.EmailField(_('Email address'),
                              default="",
                              unique=True,
                              blank=True)
    pin = models.PositiveIntegerField(
        _("PIN"),
        default=get_random_pin,
        validators=[MinLengthValidator(6)],
    )
    first_name = models.CharField(_('First name'),
                                  max_length=30,
                                  default="",
                                  blank=True)
    last_name = models.CharField(_('Last name'),
                                 max_length=30,
                                 default="",
                                 blank=True)
    birthdate = models.DateField(verbose_name=_("Birth Date"), null=True)
    is_staff = models.BooleanField(_('Is Staff'), default=False)
    is_active = models.BooleanField(_('Is Active'), default=False)
    is_verified = models.BooleanField(_('Is Verified'), default=False)
    is_email = models.BooleanField(
        _('Is Email Verified'),
        default=False,
        help_text=_(
            "Email verification is important to keep email address verified"))
    img = models.ImageField(verbose_name=_("Avatar"),
                            upload_to=settings.DEFAULT_USER_FOLDER,
                            blank=True,
                            default=settings.DEFAULT_USER_AVATAR)

    address = models.TextField(
        verbose_name=_("Address"),
        blank=True,
    )
    mobile = models.CharField(verbose_name=_("Mobile"),
                              max_length=15,
                              blank=True,
                              validators=[_PHONE_REGEX])
    telephone = models.CharField(verbose_name=_("Telephone"),
                                 max_length=15,
                                 blank=True,
                                 validators=[_PHONE_REGEX])
    fax = models.CharField(verbose_name=_("Fax"),
                           max_length=15,
                           blank=True,
                           validators=[_PHONE_REGEX])

    username_validator = ASCIIUsernameValidator()
    username = models.CharField(
        _('Username'),
        max_length=150,
        unique=True,
        help_text=
        _('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'
          ),
        validators=[username_validator],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )

    objects = UserManager()
    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    @property
    def date_joined(self):
        return self.created

    def get_full_name(self):
        """
        Returns the first_name plus the last_name, with a space in between.
        """
        full_name = f'{self.first_name} {self.last_name}' if self.first_name and self.last_name else self.username
        return full_name.strip()

    get_full_name.short_description = _("Full Name")

    def get_full_name_slug(self):
        return "{}-{}".format(self.get_full_name().replace(' ', '-'), self.pin)

    @property
    def full_name(self):
        return self.get_full_name()

    def get_short_name(self):
        """Returns the short name for the user."""
        return f"{self.first_name} {self.last_name[:1]}" if self.first_name else self.username

    get_short_name.short_description = _("Short Name")

    def save(self, *args, **kwargs):
        super(User, self).save(*args, **kwargs)

    def __str__(self):
        return self.get_full_name()

    def get_dict(self):
        return {
            "img": self.img if self.img else settings.DEFAULT_USER_AVATAR,
            "username": self.username,
            "first_name": self.first_name,
            "last_name": self.last_name,
            "full_name": self.get_full_name(),
            "email": self.email,
            "created": self.created.isoformat() if self.created else None,
        }
Example #13
0
class User(AbstractBaseUser, PermissionsMixin):
    """Custom user model that support using phone number instead of username"""

    EDUCATION_CHOICES = [
        ("Associate degree", "Associate degree"),
        ("Bachelor's degree", "Bachelor's degree"),
        ("Master's degree", "Master's degree"),
        ("Doctoral degree", "Doctoral degree"),
    ]
    EMPLOYMENT_CHOICES = [
        ("Employed", "Employed"),
        ("Unemployed", "Unemployed"),
        ("Contractor", "Contractor"),
        ("Student", "Student"),
    ]
    COVERAGE_CHOICES = [("Yes", "Yes"), ("No", "No"),
                        ("Don't know", "Don't know")]
    phone_regex = RegexValidator(
        regex=r"^\+?1?\d{9,15}$",
        message="Phone number must be entered in the format: '+999999999'. \
            Up to 15 digits allowed.",
    )

    # PERSONAL INFO
    phone_number = models.CharField(_("phone number"),
                                    max_length=17,
                                    unique=True)
    email = models.EmailField(_("email address"), blank=True)
    name = models.CharField(max_length=255)
    first_name = models.CharField(_("first name"), max_length=30, blank=True)
    last_name = models.CharField(_("last name"), max_length=30, blank=True)
    age = models.PositiveSmallIntegerField(
        _("age"),
        validators=[MinValueValidator(18),
                    MaxValueValidator(150)],
        blank=True,
        null=True,
    )
    zipcode = models.CharField(_("zipcode"),
                               max_length=5,
                               validators=[MinLengthValidator(5)],
                               blank=True)
    income = models.DecimalField(_("income"),
                                 max_digits=10,
                                 decimal_places=2,
                                 blank=True,
                                 null=True)
    savings = models.DecimalField(_("savings"),
                                  max_digits=10,
                                  decimal_places=2,
                                  blank=True,
                                  null=True)
    debt = models.DecimalField(_("debt"),
                               max_digits=10,
                               decimal_places=2,
                               blank=True,
                               null=True)
    education = models.CharField(_("education"),
                                 max_length=50,
                                 choices=EDUCATION_CHOICES,
                                 blank=True)
    employment = models.CharField(_("employment"),
                                  max_length=50,
                                  choices=EMPLOYMENT_CHOICES,
                                  blank=True)

    # SCORES
    score = models.ForeignKey("Score",
                              on_delete=models.CASCADE,
                              blank=True,
                              null=True)

    # STUFF
    own_vehicle = models.BooleanField(default=False)
    own_pet = models.BooleanField(default=False)
    own_rent_house = models.BooleanField(default=False)

    # COVERAGES
    have_health_cover = models.CharField(_("health"),
                                         max_length=50,
                                         choices=COVERAGE_CHOICES,
                                         blank=True)
    have_vision_cover = models.CharField(_("vision"),
                                         max_length=50,
                                         choices=COVERAGE_CHOICES,
                                         blank=True)
    have_dental_cover = models.CharField(_("dental"),
                                         max_length=50,
                                         choices=COVERAGE_CHOICES,
                                         blank=True)
    have_life_cover = models.CharField(_("life"),
                                       max_length=50,
                                       choices=COVERAGE_CHOICES,
                                       blank=True)
    have_longtermdisability_cover = models.CharField(_("long term disability"),
                                                     max_length=50,
                                                     choices=COVERAGE_CHOICES,
                                                     blank=True)
    have_shorttermdisability_cover = models.CharField(
        _("short term disability"),
        max_length=50,
        choices=COVERAGE_CHOICES,
        blank=True)
    have_accident_cover = models.CharField(_("accident"),
                                           max_length=50,
                                           choices=COVERAGE_CHOICES,
                                           blank=True)
    have_criticalillness_cover = models.CharField(_("critical illness"),
                                                  max_length=50,
                                                  choices=COVERAGE_CHOICES,
                                                  blank=True)
    have_auto_cover = models.CharField(_("auto"),
                                       max_length=50,
                                       choices=COVERAGE_CHOICES,
                                       blank=True)
    have_homeowner_cover = models.CharField(_("homeowner"),
                                            max_length=50,
                                            choices=COVERAGE_CHOICES,
                                            blank=True)
    have_renters_cover = models.CharField(_("renters"),
                                          max_length=50,
                                          choices=COVERAGE_CHOICES,
                                          blank=True)
    have_pet_cover = models.CharField(_("pet"),
                                      max_length=50,
                                      choices=COVERAGE_CHOICES,
                                      blank=True)

    date_joined = models.DateTimeField(_("registered"),
                                       auto_now_add=True,
                                       null=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = "phone_number"

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    def get_full_name(self):
        """Returns the firstname plus the last_name, and a space in between."""
        full_name = "%s %s" % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        """Returns the short name for the user."""
        return self.first_name

    def calculate_score(self):
        """Initializes dummy score object for now."""

        # TODO: Call make_user_score_metrics(user, products) to get score metrics

        overall_score = randint(0, 100)
        return Score(
            score_overall=overall_score,
            score_medical=randint(0, 100),
            score_income=randint(0, 100),
            score_stuff=randint(0, 100),
            score_liability=randint(0, 100),
            score_digital=randint(0, 100),
            content_overall="Your overall score of {} shows you're doing good."
            .format(overall_score),
            content_medical="You are underprotected in your medical category.",
            content_income=
            "We also think you're overprotected in your income category.",
            content_stuff="",
            content_liability="",
            content_digital="",
        )
Example #14
0
class User(AbstractBaseUser, PermissionsMixin):
    """
    User model. It inherits the basic structure of the Django
    user model. The username field is overwiritten with the
    email value. This model manage basic user iformation and
    legal items status.
    """
    USERNAME_FIELD = 'email'

    avatar = models.ImageField(
        verbose_name=_('profile image'),
        max_length=255,
        blank=True,
        validators=[FileSizeValidator(4000)],
    )

    first_name = models.CharField(
        verbose_name=_('name'),
        max_length=128,
        blank=False,
        validators=[
            MinLengthValidator(3),
        ],
        error_messages={
            'min_length':
            'El campo "Nombre" debe tener al menos %(limit_value)d '
            'caracteres (actualmente tiene %(show_value)d).'
        })

    last_name = models.CharField(
        verbose_name=_('last name'),
        max_length=128,
        blank=False,
        validators=[
            MinLengthValidator(3),
        ],
        error_messages={
            'min_length':
            'El campo "Apellidos" debe tener al menos %(limit_value)d '
            'caracteres (actualmente tiene %(show_value)d).'
        })

    email = models.EmailField(
        verbose_name=_('email'),
        unique=True,
        blank=False,
    )

    is_staff = models.BooleanField(
        'staff status',
        default=False,
    )

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

    country = models.ForeignKey(
        'place.Country',
        null=True,
        verbose_name=_('country'),
    )

    state = models.ForeignKey(
        'place.State',
        null=True,
        verbose_name=_('state'),
    )

    city = models.ForeignKey(
        'place.City',
        null=True,
        verbose_name=_('city'),
    )

    address = models.CharField(
        verbose_name=_('address'),
        max_length=80,
        null=True,
        blank=True,
    )

    date_joined = models.DateTimeField(
        verbose_name=_('created at'),
        default=timezone.now,
    )

    accepted_terms = models.BooleanField(
        verbose_name=_('accepted user agreement'),
        default=True,
    )

    accepted_terms_date = models.DateField(
        verbose_name=_('accepted user agreement date'),
        null=True,
        blank=True,
    )

    accepted_privacy_policy = models.BooleanField(
        verbose_name=_('accepted privacy policy'),
        default=True,
    )

    accepted_privacy_policy_date = models.DateField(
        verbose_name=_('accepted privacy policy date'),
        null=True,
        blank=True,
    )

    objects = UserManager()

    def get_short_name(self):
        return self.first_name if self.first_name else self.email.split('@')[0]

    @property
    def get_avatar(self):
        avatar = '/static/img/profile_default_avatar.svg'
        if self.avatar:
            avatar = self.avatar.url

        return avatar

    @property
    def get_country(self):
        country = None

        if self.country:
            country = self.country.country

        return country

    @property
    def get_full_name(self):
        full_name = '{0} {1}'.format(self.first_name, self.last_name)
        return full_name.strip()

    def __str__(self):
        return self.get_full_name

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')
        ordering = ('email', )
    def __init__(
        self,
        name="",
        default=dict,
        required=False,
        prefix="",
        call_default=True,
        transform_default=False,
        validators=(),
        key_type=None,
        value_type=None,
        outer_delimiter=None,
        inner_delimiter="=",
        min_length=None,
        max_length=None,
        empty=None,
    ):
        """
        Initialization method.

        Args:
            name (str): the name of the setting.
            default (dict): default value given to the setting.
            required (bool): whether the setting is required or not.
            prefix (str):
                the setting's prefix (overrides ``AppSettings.Meta`` prefix).
            call_default (bool): whether to call the default (if callable).
            transform_default (bool): whether to transform the default value.
            validators (list of callables): list of additional validators to use.
            key_type: the type of the dict keys.
            value_type (type): the type of dict values.
            outer_delimiter (str): value used to split environ string into separated parts
            inner_delimiter (str): value used to split environ string parts
            min_length (int): Noop. Deprecated.
            max_length (int): Noop. Deprecated.
            empty (bool): whether empty iterable is allowed. Deprecated in favor of MinLengthValidator.
        """
        super().__init__(
            name=name,
            default=default,
            required=required,
            prefix=prefix,
            call_default=call_default,
            transform_default=transform_default,
            validators=validators,
        )
        self.key_type = key_type
        self.value_type = value_type
        self.outer_delimiter = outer_delimiter
        self.inner_delimiter = inner_delimiter
        if key_type is not None:
            self.validators.append(DictKeysTypeValidator(key_type))
        if value_type is not None:
            self.validators.append(DictValuesTypeValidator(value_type))
        if empty is not None:
            warnings.warn(
                "Empty argument is deprecated, use MinLengthValidator instead.",
                DeprecationWarning)
            self.validators.append(MinLengthValidator(1))
        if min_length is not None:
            warnings.warn(
                "Argument min_length does nothing and is deprecated.",
                DeprecationWarning)
        if max_length is not None:
            warnings.warn(
                "Argument max_length does nothing and is deprecated.",
                DeprecationWarning)
Example #16
0
class Post(models.Model):
    STATUS = ((0, 'Draft'), (1, 'Publish'))
    title = models.CharField(
        max_length=60,
        validators=[MinLengthValidator(40)],
        help_text='The length of the post must be between 40 and 60 characters'
    )
    slug = models.SlugField(max_length=60, unique=True)
    content = HTMLField()
    reference_url = models.URLField(blank=True)
    publish_date = models.DateTimeField(db_index=True,
                                        auto_now_add=True,
                                        editable=False)
    updated_date = models.DateTimeField(db_index=True, auto_now=True)
    image = models.ImageField(
        default='post_images/algorithm1.jpeg',
        upload_to='post_images',
        max_length=200,
        help_text=
        'For bests results, use an image that is 1,200px wide x 600px high',
    )
    status = models.IntegerField(db_index=True, choices=STATUS, default=0)
    author = models.ForeignKey(get_user_model(),
                               related_name='author',
                               on_delete=models.CASCADE)
    categories = models.ManyToManyField(
        Category,
        related_name='posts',
        help_text=
        'Select more than one category by holding down Ctrl or Cmd key')

    # Model Managers
    objects = models.Manager()
    published = PublishedManager()

    class Meta:
        ordering = ['-updated_date', '-publish_date']
        default_manager_name = 'objects'

    def __str__(self):
        return str(self.title)

    @property
    def word_count(self) -> int:
        return len(self.content.split())

    @property
    def reading_time(self) -> int:
        return int(math.ceil(self.word_count / 75))

    @property
    def publish_year(self) -> int:
        return self.publish_date.year

    @staticmethod
    def num_draft_posts() -> int:
        return Post.objects.filter(status=0).count()

    def save(self):
        if not self.slug.strip():  # pragma: no cover
            self.slug = slugify(self.title)

        _slug = self.slug
        _count = 1

        while True:
            try:
                Post.objects.all().exclude(pk=self.pk).get(slug=_slug)
            except ObjectDoesNotExist:
                break
            _slug = f"{self.slug}{_count}"
            _count += 1

        self.slug = _slug

        super(Post, self).save()

    def get_absolute_url(self):
        return reverse('blog:post_detail', kwargs={'slug': self.slug})

    def get_excerpt(self, char):
        return self.content[:char]
Example #17
0
 (MaxValueValidator(10), 0, None),
 (MaxValueValidator(NOW), NOW, None),
 (MaxValueValidator(NOW), NOW - timedelta(days=1), None),
 (MaxValueValidator(0), 1, ValidationError),
 (MaxValueValidator(NOW), NOW + timedelta(days=1), ValidationError),
 (MinValueValidator(-10), -10, None),
 (MinValueValidator(-10), 10, None),
 (MinValueValidator(-10), 0, None),
 (MinValueValidator(NOW), NOW, None),
 (MinValueValidator(NOW), NOW + timedelta(days=1), None),
 (MinValueValidator(0), -1, ValidationError),
 (MinValueValidator(NOW), NOW - timedelta(days=1), ValidationError),
 (MaxLengthValidator(10), '', None),
 (MaxLengthValidator(10), 10 * 'x', None),
 (MaxLengthValidator(10), 15 * 'x', ValidationError),
 (MinLengthValidator(10), 15 * 'x', None),
 (MinLengthValidator(10), 10 * 'x', None),
 (MinLengthValidator(10), '', ValidationError),
 (URLValidator(EXTENDED_SCHEMES), 'file://localhost/path', None),
 (URLValidator(EXTENDED_SCHEMES), 'git://example.com/', None),
 (URLValidator(EXTENDED_SCHEMES), 'git://-invalid.com', ValidationError),
 (BaseValidator(True), True, None),
 (BaseValidator(True), False, ValidationError),
 (RegexValidator(), '', None),
 (RegexValidator(), 'x1x2', None),
 (RegexValidator('[0-9]+'), 'xxxxxx', ValidationError),
 (RegexValidator('[0-9]+'), '1234', None),
 (RegexValidator(re.compile('[0-9]+')), '1234', None),
 (RegexValidator('.*'), '', None),
 (RegexValidator(re.compile('.*')), '', None),
 (RegexValidator('.*'), 'xxxxx', None),
Example #18
0
class Simple(models.Model):
    sentence_text = models.CharField(max_length=200,
                                     unique=True,
                                     null=False,
                                     validators=[MinLengthValidator(1)])
    preprocess_sen = models.CharField(max_length=200, null=True)
    pos_tagging = models.CharField(max_length=200, null=True)
    lexical_tree = models.TextField('lexical tree', null=True)
    request_date = models.DateTimeField('date requested', default=timezone.now)
    request_count = models.PositiveIntegerField('count', default=0)
    pv_word = models.TextField("pv word", null=True)
    pv_modifier_word = models.TextField("pv modifier word", null=True)
    keywords = models.TextField("keywords", null=True)
    emotion = models.IntegerField('emotion', default=-1)

    def __str__(self):
        return self.sentence_text

    def __unicode__(self):
        return u'%s' % self.sentence_text

    def get_washed_text(self, refresh=False):
        """
        获取预处理后的数据
        :param refresh: 如果refresh设置为True,则强制进行依次预处理,再返回结果
        :return: 第一次调用会进行一次预处理,并把结果存入数据库,之后调用将直接从数据库读取结果
        """
        if self.preprocess_sen is None or refresh:
            self.preprocess_sen = wash_data(self.sentence_text)
            self.save()
        print "washed text :%s" % self.preprocess_sen
        return self.preprocess_sen

    def get_seg_json(self, refresh=False):
        """
        获取jieba分词结果的json格式
        :param refresh: 是否强制重新分词,并刷新分词结果
        :return: jieba分词
        """
        if self.pos_tagging is None or refresh:
            words = pseg.cut(self.get_washed_text())
            self.pos_tagging = ''
            for word, flag in words:
                self.pos_tagging += (word + flag[0] + ',')
            self.pos_tagging = self.pos_tagging[:-1]
            self.save()
        return self.pos_tagging

    def get_lexical_tree(self, refresh=False):
        """
        获取词法分析树的数据(调用哈工大云的API)
        :param refresh: 是否强制刷新数据,是则重新调用哈工大云API
        :return: 词法分析树的json格式数据
        """
        if self.lexical_tree is None or len(self.lexical_tree) == 0 or refresh:
            text = self.get_washed_text()
            params = {
                'api_key': 'N5G9s2d6TVoT7mptglCmWagXJqWWKAfBMBlDxJBR',
                'text': text.encode('utf8'),
                'format': 'json',
                'pattern': 'all'
            }

            params = urlencode(params)
            url = "http://api.ltp-cloud.com/analysis/?" + params
            result = urllib2.urlopen(url)
            content = result.read().strip()
            content = re.sub('\n', ' ', content.decode('utf8')).encode('utf8')

            self.lexical_tree = content
            self.save()

        print self.lexical_tree
        return self.lexical_tree

    def get_lexical_tree_strip(self):
        content = self.get_lexical_tree()
        content = json.loads(content)[0][0]
        content = json.dumps(content)
        return content

    def syntactic(self):
        """
        call API from algorithm to tell the syntactic of this sentence
        :return: Negative, Declarative or Question
        """

        if self.emotion < 0:
            washed = self.get_washed_text()
            segs = self.get_seg_json()
            ltp = self.get_lexical_tree_strip()
            ltp_list = []
            ltp_list.append(ltp.encode('utf8'))
            washed_list = []
            washed_list.append(washed.encode('utf8'))
            segs_list = []
            segs_list.append(segs.encode('utf8'))
            id_list = []
            id_list.append(self.id)

            # hgd_file 是指经过哈工大预处理后的句子
            # test_numark_file 是指没有处理过的句子
            # test_file 是指分词后句子

            result = judge.test(washed_list, segs_list, ltp_list, id_list)
            if result is None:
                self.emotion = -1
            else:
                self.emotion = result
            self.save()
        if self.emotion == 0:
            return '疑问句'
        if self.emotion == 1:
            return '否定句'
        if self.emotion == 2:
            return '陈述句'
        return self.emotion
Example #19
0
class PDAInstance(models.Model):
    # record contains teacher, school-year and summary
    pda_record = models.ForeignKey(PDARecord,
                                   on_delete=models.PROTECT,
                                   null=False,
                                   blank=False)
    pda_type = models.ForeignKey(PDAType,
                                 on_delete=models.PROTECT,
                                 null=False,
                                 blank=False)
    date_completed = models.DateField(null=False)
    description = models.CharField(validators=[MinLengthValidator(1)],
                                   max_length=3000,
                                   blank=False,
                                   null=False)

    # OR between those three
    ceu = models.DecimalField(max_digits=5,
                              decimal_places=2,
                              null=True,
                              blank=True)
    clock_hours = models.DecimalField(max_digits=3,
                                      decimal_places=1,
                                      null=True,
                                      blank=True)
    pages = models.DecimalField(max_digits=3,
                                decimal_places=0,
                                null=True,
                                blank=True)

    file = models.FileField(upload_to='documents/Supporting_Files/',
                            null=True,
                            blank=True)
    date_submitted = models.DateField(null=True, blank=True)

    submitted = models.BooleanField(null=False, default=False, blank=True)
    principal_signed = models.BooleanField(null=False,
                                           default=False,
                                           blank=True)
    isei_reviewed = models.BooleanField(null=False, default=False, blank=True)
    approved = models.BooleanField(null=False, default=False, blank=True)

    approved_ceu = models.DecimalField(max_digits=5,
                                       decimal_places=2,
                                       null=True,
                                       blank=True)
    approval_comment = models.CharField(max_length=300, null=True, blank=True)

    class Meta:
        ordering = ['pda_record']

    @property
    def status(self):
        return int(
            self.submitted == True
        ) + int(self.principal_signed == True) * 2 + int(
            self.isei_reviewed == True) * 4 + int(self.approved == True) * 8

    # 0 - New instance
    # 1 - Submitted instance
    # 2 - Denied by the principal (submitted=0, principal_signed = 1)
    # 3 - Signed by the principal
    # 4 - Summary denied, whole record returned (isei_reviewed = 1, submitted = 0, principal_signed = 0)
    # 5 - Resubmitted to principal (isei_reviewed = 1, submitted = 1, principal_signed = 0)
    # 6 - Record approved, individual instance denied ( isei_reviewed = 1, principal_signed = 1, submitted = 0)
    # 15 - Approved by ISEI

    def suggested_ceu(self):
        if self.approved:
            if self.ceu is not None:
                return self.ceu
            elif self.pages is not None:
                return round(self.pages / 100, 2)
            elif self.clock_hours is not None:
                return round(self.clock_hours / 10, 2)

    def __str__(self):
        return self.description
Example #20
0
class Shop(models.Model):
    name = models.CharField(max_length=100, validators=[MinLengthValidator(5)])
    desc = models.TextField(blank=True)
    address = models.CharField(max_length=100, blank=True)
Example #21
0
class Candidatos(models.Model):
    email = models.EmailField(unique=True)
    escolaridade = models.IntegerField(choices=ESCOLARIDADE_CHOICES,
                                       blank=True,
                                       null=True)
    experiencia = models.IntegerField(blank=True, null=True)
    distancia = models.DecimalField(max_digits=10,
                                    decimal_places=2,
                                    blank=True,
                                    null=True)
    faixa_salarial = models.DecimalField(max_digits=10,
                                         decimal_places=2,
                                         blank=True,
                                         null=True)
    senha = models.TextField(validators=[MinLengthValidator(6)])

    def login(self, request, email=None, senha=None):
        self.email = email
        self.senha = HashPassword(senha)

        if not request.session.get('email', False):
            try:
                self.candidato = Candidatos.objects.get(email=self.email,
                                                        senha=self.senha)
                if request.session.get('email_empresa', False):
                    del request.session['email_empresa']
                if request.session.get('id_empresa', False):
                    del request.session['id_empresa']
                if request.session.get('empresa', False):
                    del request.session['empresa']

                request.session['email'] = self.candidato.email
                request.session['id'] = self.candidato.id
                request.session['candidato'] = True
                return self.candidato
            except Candidatos.DoesNotExist:
                return False
        else:
            return True

    def candidato_update(self,
                         id=None,
                         email=None,
                         escolaridade=None,
                         experiencia=None,
                         distancia=None,
                         faixa_salarial=None,
                         senha=None):
        if id:
            self.id = id
            self.distancia = distancia
            self.faixa_salarial = faixa_salarial
            self.candidato = self.getcandidato_by_id(id=id)
            if self.candidato:
                if senha:
                    self.candidato.senha = HashPassword(senha)
                if email:
                    self.candidato.email = email
                self.candidato.escolaridade = escolaridade
                self.candidato.experiencia = experiencia
                self.candidato.faixa_salarial = faixa_salarial
                self.candidato.save()
                return True
            else:
                return False
        else:
            return False

    def getcandidato_by_id(self, id=None):
        if id:
            self.id = id
            try:
                self.candidato = Candidatos.objects.get(pk=id)
                return self.candidato
            except Candidatos.DoesNotExist:
                return False
        else:
            return False
Example #22
0
class Headquarters(models.Model):
    '''   
        This Class: <Headquarters> contains the information of an headquarters.
        Esta Clase: <Sede> contiene la información de una sede.
    '''
    entity = models.ForeignKey(
        Entity, 
        db_index=True,
        on_delete=models.CASCADE, 
        help_text='Entity | Entidad'
    )
    name = models.CharField(
        max_length=100,
        unique=True,
        db_index=True,
        validators=[
            MinLengthValidator(1),
            MaxLengthValidator(100),
        ], 
        help_text= 'Name | Nombre'
    )
    contact_information = models.ManyToManyField(
        ContactInformation,
        blank=True, 
        help_text='Contact information | Informarción de contacto'
    )
    extra_information = models.ManyToManyField(
        ExtraInformation,
        blank=True, 
        help_text='Extra information | Informarción extra'
    )
    active = models.BooleanField(
        default=True, 
        help_text='Active | Activo'
    )
    slug = models.SlugField(
        editable=False, 
        max_length=255,
        unique=True, 
        db_index=True 
    )

    def __str__(self):
        return self.get_name()

    def save(self, *args, **kwargs):
        if not self.pk:
            self.slug = slugify(self.get_name())
        else:
            slug = slugify(self.get_name())
            if self.slug != slug:
                self.slug = slug
        super(Headquarters, self).save(*args, **kwargs)

    #Setter
    def set_entity(self, entity):
        self.entity = entity 

    def set_name(self, name):
        self.name = name 
    
    def set_contact_information(self, contact_information):
        self.contact_information = contact_information
    
    def set_extra_information(self, extra_information):
        self.extra_information = extra_information
    
    def set_active(self, active):
        self.active = active 

    #Getter
    def get_entity(self):
        return self.entity 
    
    def get_name(self):
        return self.name 
    
    def get_contact_information(self):
        return self.contact_information
    
    def get_extra_information(self):
        return self.extra_information
    
    def is_active(self):
        return self.active

    def get_full_name(self):
        return '%s - %s'%(self.get_entity(), self.get_name())

    class Meta:
        db_table = 'headquarters'
        ordering = ['entity', 'name']
        verbose_name = 'Entity'
        verbose_name_plural = 'Headquarters'
Example #23
0
def validate_tag_embed(embed: Any) -> None:
    """
    Validate a JSON document containing an embed as possible to send on Discord.

    This attempts to rebuild the validation used by Discord
    as well as possible by checking for various embed limits so we can
    ensure that any embed we store here will also be accepted as a
    valid embed by the Discord API.

    Using this directly is possible, although not intended - you usually
    stick this onto the `validators` keyword argument of model fields.

    Example:

        >>> from django.contrib.postgres import fields as pgfields
        >>> from django.db import models
        >>> from pydis_site.apps.api.models.bot.tag import validate_tag_embed
        >>> class MyMessage(models.Model):
        ...     embed = pgfields.JSONField(
        ...         validators=(
        ...             validate_tag_embed,
        ...         )
        ...     )
        ...     # ...
        ...

    Args:
        embed (Any):
            A dictionary describing the contents of this embed.
            See the official documentation for a full reference
            of accepted keys by this dictionary:
                https://discordapp.com/developers/docs/resources/channel#embed-object

    Raises:
        ValidationError:
            In case the given embed is deemed invalid, a `ValidationError`
            is raised which in turn will allow Django to display errors
            as appropriate.
    """
    all_keys = {
        'title', 'type', 'description', 'url', 'timestamp', 'color', 'footer',
        'image', 'thumbnail', 'video', 'provider', 'author', 'fields'
    }
    one_required_of = {'description', 'fields', 'image', 'title', 'video'}
    field_validators = {
        'title': (MinLengthValidator(limit_value=1,
                                     message="Embed title must not be empty."),
                  MaxLengthValidator(limit_value=256)),
        'description': (MaxLengthValidator(limit_value=2048), ),
        'fields':
        (MaxLengthValidator(limit_value=25), validate_tag_embed_fields),
        'footer': (validate_tag_embed_footer, ),
        'author': (validate_tag_embed_author, )
    }

    if not embed:
        raise ValidationError("Tag embed must not be empty.")

    elif not isinstance(embed, Mapping):
        raise ValidationError("Tag embed must be a mapping.")

    elif not any(field in embed for field in one_required_of):
        raise ValidationError(
            f"Tag embed must contain one of the fields {one_required_of}.")

    for required_key in one_required_of:
        if required_key in embed and not embed[required_key]:
            raise ValidationError(f"Key {required_key!r} must not be empty.")

    for field_name, value in embed.items():
        if field_name not in all_keys:
            raise ValidationError(f"Unknown field name: {field_name!r}")

        if field_name in field_validators:
            for validator in field_validators[field_name]:
                validator(value)
class Analysis(models.Model):
    name = models.CharField(max_length=30, unique=True, validators=[MinLengthValidator(3)])
    date_create = models.DateField(auto_now_add=True)
    date_modification = models.DateField(auto_now=True)
    data_set = models.FileField(upload_to="data_sets/")
    signal_speed = models.IntegerField(validators=[MaxValueValidator(4), MinValueValidator(1)])
    signal_direction = models.IntegerField(validators=[MaxValueValidator(4), MinValueValidator(1)])
    step_group = models.IntegerField(validators=[greater_zero])
    start_sector_direction = models.IntegerField(
        validators=[MaxValueValidator(360), MinValueValidator(0)]
    )
    end_sector_direction = models.IntegerField(
        validators=[MaxValueValidator(360), MinValueValidator(0)]
    )
    start_sector_speed = models.IntegerField(validators=[MinValueValidator(0)])
    end_sector_speed = models.IntegerField(validators=[MinValueValidator(0)])
    result_analysis = models.FilePathField(blank=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ["date_modification"]

    def delete(self, using=None, keep_parents=False):
        shutil.rmtree(self.result_analysis)
        self.data_set.delete(save=False)
        super(Analysis, self).delete(using, keep_parents)

    def delete_results_analysis(self):
        if os.path.exists(self.result_analysis):
            for analysis_file in os.listdir(self.result_analysis):
                os.remove(os.path.join(self.result_analysis, analysis_file))
        logging.warning(f"Path does not exists {self.result_analysis}")

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        is_new = self.pk is None
        self.calculate_analysis()
        if is_new:
            self.result_analysis = os.path.join(settings.MEDIA_ROOT, self.name)
        super().save(force_insert, force_update, using, update_fields)

    def calculate_analysis(self):
        try:
            ApplicationManager().go(
                self,
                settings.MEDIA_ROOT,
            )
        except Exception as e:
            try:
                Analysis.objects.get(name=self.name)
            except ObjectDoesNotExist:
                shutil.rmtree(os.path.join(settings.MEDIA_ROOT, self.name))
                raise ValidationError(e)

    def create_archive(self):
        file_name = "{}_{}.zip".format(self.name, self.date_modification)
        base_name_dir = "zip_files"
        abs_path_dir = os.path.join(settings.MEDIA_ROOT, base_name_dir)
        if not os.path.exists(abs_path_dir):
            os.mkdir(abs_path_dir)
        compress_zip(os.path.join(abs_path_dir, file_name), get_all_abs_paths(self.result_analysis))
        archive = ZipArchive()
        archive.name = self.name
        archive.zip_file = os.path.join(base_name_dir, file_name)
        archive.analysis = self
        archive.save()
        return archive

    def delete_archive(self):
        try:
            ZipArchive.objects.get(name=self.name).delete()
        except Exception:
            pass
Example #25
0
class Project(SearchableMixin, CustomModel):
    name = models.CharField(
        _("Name"),
        max_length=30,
        validators=[
            MinLengthValidator(
                4, _("A Projectname should be at least 4 chars long"))
        ],
    )

    activity = models.TextField(default="[]")

    name_short = models.CharField(
        _("Short Name"),
        max_length=4,
        unique=True,
        validators=[
            RegexValidator(r'^[0-9a-zA-Z]*$',
                           _("Only alphanumeric characters are valid"))
        ],
    )
    description = models.TextField(_("Description"), blank=True)
    creator = models.ForeignKey(
        AUTH_USER_MODEL,
        # TODO BUG the project should not be deleted when the creator is deleted
        on_delete=models.CASCADE,
        verbose_name=_("creator"),
        related_name="creator")
    created_at = models.DateTimeField(_("Creation Date"), auto_now_add=True)
    updated_at = models.DateTimeField(_("Last updated:"), auto_now=True)
    manager = models.ManyToManyField(AUTH_USER_MODEL,
                                     verbose_name=_("project manager"),
                                     related_name="manager")
    developer = models.ManyToManyField(AUTH_USER_MODEL,
                                       verbose_name=_("developer"),
                                       related_name="dev_projects",
                                       blank=True)
    # TODO BUG projectWhereWctive? is that a typo what is meant with Wctive? (=active?)
    currentsprint = models.ForeignKey('sprint.Sprint',
                                      models.CASCADE,
                                      verbose_name=_("sprint"),
                                      related_name="projectWhereWctive",
                                      default=None,
                                      blank=True,
                                      null=True)

    nextTicketId = models.IntegerField(_("Next ticket ID"),
                                       editable=False,
                                       default=1)
    nextSprintId = models.IntegerField(_("Next sprint ID"),
                                       editable=False,
                                       default=1)

    activity_only_for_managers = models.BooleanField(
        _("Only managers can see timelog statistics for all developers"),
        default=True)

    objects = ProjectManager()

    class Meta:
        ordering = ['name']
        verbose_name = _("project")
        verbose_name_plural = _("projects")

    def get_absolute_url(self):
        return reverse('project:detail', kwargs={'project': self.name_short})

    def has_active_sprint(self):
        if (self.currentsprint is not None):
            return (self.currentsprint.is_active())
        else:
            return False

    def developer_allowed(self, user):
        if (len(self.manager.filter(pk=user.pk)) == 1
                or len(self.developer.filter(pk=user.pk)) == 1):
            return 1
        return 0

    def is_manager(self, user):
        if len(self.manager.filter(pk=user.pk)) == 1:
            return 1
        return 0

    def get_members(self):
        return (self.developer.all() | self.manager.all()).distinct()

    def __str__(self):
        return self.name

    # SearchableMixin functions
    def search_allowed_for_user(self, user):
        return self.developer_allowed(user)

    def get_relative_project(self):
        return self.name

    # permission functions
    def user_has_write_permissions(self, user):
        return self.is_manager(user)

    def user_has_read_permissions(self, user):
        return self.developer_allowed(user)

    # activity function
    def activity_stream_long_name(self):
        return self.description

    def increase_activity(self, date, issue=None, decrease=False):
        actor = CuserMiddleware.get_user()
        # handle user activity, if there is a current user
        if actor and not isinstance(actor, AnonymousUser):
            user_activity = json.loads(actor.activity)
            iss = 'None'
            if issue:
                iss = issue.get_ticket_identifier()
            if decrease:
                if self.name_short in user_activity:
                    user_activity[self.name_short].pop()
            else:
                if self.name_short in user_activity:
                    user_activity[self.name_short].append(
                        (date.isoformat(), iss))
                else:
                    user_activity[self.name_short] = []
                    user_activity[self.name_short].append(
                        (date.isoformat(), iss))
            actor.activity = json.dumps(user_activity)
            actor.save()
            # delete cache
            cache.delete('action_data_' + actor.username)
            cache.delete('action_data_' + actor.username + '_' +
                         self.name_short)

        # handle project activity
        activity_dict = json.loads(self.activity)
        if isinstance(activity_dict, dict):
            activity_dict = []
        if decrease:
            activity_dict.pop()
        else:
            activity_dict.append(date.isoformat())
        self.activity = json.dumps(activity_dict)
        self.save()
        return

    searchable_fields = [
        'creator', 'created_at', 'description', 'name', 'name_short',
        'updated_at', 'issue'
    ]
Example #26
0
class Exercise(AbstractSubmissionModel, AbstractLicenseModel, models.Model):
    """
    Model for an exercise
    """

    objects = SubmissionManager()
    """Custom manager"""

    description = models.TextField(max_length=2000,
                                   verbose_name=_('Description'),
                                   validators=[MinLengthValidator(40)])
    """Description on how to perform the exercise"""

    name = models.CharField(max_length=200, verbose_name=_('Name'))
    """The exercise's name, with correct uppercase"""

    name_original = models.CharField(max_length=200,
                                     verbose_name=_('Name'),
                                     default='')
    """The exercise's name, as entered by the user"""

    creation_date = models.DateField(_('Date'),
                                     auto_now_add=True,
                                     null=True,
                                     blank=True)
    """The submission date"""

    language = models.ForeignKey(Language,
                                 verbose_name=_('Language'),
                                 on_delete=models.CASCADE)
    """The exercise's language"""

    uuid = models.UUIDField(default=uuid.uuid4,
                            editable=False,
                            verbose_name='UUID')
    """Globally unique ID, to identify the exercise across installations"""

    exercise_base = models.ForeignKey(ExerciseBase,
                                      verbose_name='ExerciseBase',
                                      on_delete=models.CASCADE,
                                      default=None,
                                      null=True,
                                      related_name='exercises')
    """ Refers to the base exercise with non translated information """

    #
    # Django methods
    #
    class Meta:
        base_manager_name = 'objects'
        ordering = [
            "name",
        ]

    def get_absolute_url(self):
        """
        Returns the canonical URL to view an exercise
        """
        return reverse('exercise:exercise:view',
                       kwargs={
                           'id': self.id,
                           'slug': slugify(self.name)
                       })

    def save(self, *args, **kwargs):
        """
        Reset all cached infos
        """
        self.name = smart_capitalize(self.name_original)
        super(Exercise, self).save(*args, **kwargs)

        # Cached template fragments
        for language in Language.objects.all():
            delete_template_fragment_cache('muscle-overview', language.id)
            delete_template_fragment_cache('exercise-overview', language.id)
            delete_template_fragment_cache('equipment-overview', language.id)

        # Cached workouts
        for setting in self.setting_set.all():
            reset_workout_canonical_form(setting.set.exerciseday.training_id)

    def delete(self, *args, **kwargs):
        """
        Reset all cached infos
        """

        # Cached template fragments
        for language in Language.objects.all():
            delete_template_fragment_cache('muscle-overview', language.id)
            delete_template_fragment_cache('exercise-overview', language.id)
            delete_template_fragment_cache('equipment-overview', language.id)

        # Cached workouts
        for setting in self.setting_set.all():
            reset_workout_canonical_form(setting.set.exerciseday.training.pk)

        super(Exercise, self).delete(*args, **kwargs)

    def __str__(self):
        """
        Return a more human-readable representation
        """
        return self.name

    #
    # Properties to expose the info from the exercise base
    #
    @property
    def category(self):
        return self.exercise_base.category

    @property
    def muscles(self):
        return self.exercise_base.muscles

    @property
    def muscles_secondary(self):
        return self.exercise_base.muscles_secondary

    @property
    def equipment(self):
        return self.exercise_base.equipment

    @property
    def images(self):
        return self.exercise_base.exerciseimage_set

    @property
    def variations(self):
        """
        Returns the variations for this exercise in the same language
        """
        out = []
        if self.exercise_base.variations:
            for variation in self.exercise_base.variations.exercisebase_set.all(
            ):
                for exercise in variation.exercises.filter(
                        language=self.language).accepted():
                    out.append(exercise)
        return out

    #
    # Own methods
    #
    @property
    def main_image(self):
        """
        Return the main image for the exercise or None if nothing is found
        """
        return self.images.accepted().filter(is_main=True).first()

    @property
    def description_clean(self):
        """
        Return the exercise description with all markup removed
        """
        return bleach.clean(self.description, strip=True)

    def get_owner_object(self):
        """
        Exercise has no owner information
        """
        return False

    def send_email(self, request):
        """
        Sends an email after being successfully added to the database (for user
        submitted exercises only)
        """
        try:
            user = User.objects.get(username=self.license_author)
        except User.DoesNotExist:
            return
        if self.license_author and user.email:
            translation.activate(
                user.userprofile.notification_language.short_name)
            url = request.build_absolute_uri(self.get_absolute_url())
            subject = _(
                'Exercise was successfully added to the general database')
            context = {
                'exercise': self.name,
                'url': url,
                'site': Site.objects.get_current().domain
            }
            message = render_to_string('exercise/email_new.tpl', context)
            mail.send_mail(subject,
                           message,
                           settings.WGER_SETTINGS['EMAIL_FROM'], [user.email],
                           fail_silently=True)

    def set_author(self, request):
        """
        Set author and status
        This is only used when creating exercises (via web or API)
        """
        if request.user.has_perm('exercises.add_exercise'):
            self.status = self.STATUS_ACCEPTED
            if not self.license_author:
                self.license_author = request.get_host().split(':')[0]
        else:
            if not self.license_author:
                self.license_author = request.user.username

            subject = _('New user submitted exercise')
            message = _('The user {0} submitted a new exercise "{1}".').format(
                request.user.username, self.name)
            mail.mail_admins(str(subject), str(message), fail_silently=True)
Example #27
0
class Person(models.Model):
    '''
        This Class:<Person> is abstract and contains basic personal information.
        Esta Clase:<Persona> es abstracto y contiene la información personal básica.
    '''
    GENDER_CHOICES = [(gender.value, gender.value) for gender in Gender]
    MARITAL_STATUS_CHOICES = [(marital_status.value, marital_status.value) for marital_status in MaritalStatus]
    GROUP_CHOICES_BLOOD = [(blood_group.value, blood_group.value) for blood_group in BloodGroup]
    
    name = models.CharField(
        max_length=100,
        unique=True,
        db_index=True,
        validators=[
            MinLengthValidator(1),
            MaxLengthValidator(100),
        ],
        help_text='Name | Nombre'
    )
    last_name = models.CharField(
        max_length=100,
        unique=True,
        db_index=True,
        validators=[
            MinLengthValidator(1),
            MaxLengthValidator(100),
        ],
        help_text='Last name | Apellido paterno'
    )
    mother_last_name = models.CharField(
        max_length=100,
        unique=True,
        db_index=True,
        validators=[
            MinLengthValidator(1),
            MaxLengthValidator(100),
        ], 
        help_text='Mother last name | Apellido materno'
    )   
    birthday = models.DateField(
        help_text='birthday | Fecha nacimiento'
    )
    gender = models.CharField(
        choices = GENDER_CHOICES,
        max_length=9,
        help_text='Gender | Género'
    )
    marital_status = models.CharField(
        choices = MARITAL_STATUS_CHOICES,
        max_length=9,
        help_text='Marital status | Estado marital o civil'
    )
    blood_group = models.CharField(
        choices = GROUP_CHOICES_BLOOD,
        max_length=9,
        null=True,
        blank=True,
        help_text='Blood group | Grupo sanguíneo'
    )  
    photography = models.ImageField(
        upload_to='image/persons/', 
        null=True, 
        blank=True,
        default=None, 
        help_text='Photography | Fotografía'
    ) 
    slug = models.SlugField(
        editable=False, 
        max_length=255,
        unique=True, 
        db_index=True 
    )
    
    def __str__(self):
        return self.get_full_name()

    def save(self, *args, **kwargs):
        if not self.pk:
            self.slug = slugify(self.get_full_name())
        else:
            slug = slugify(self.get_full_name())
            if self.slug != slug:
                self.slug = slug
        super(Person, self).save(*args, **kwargs)

    def get_full_name(self):
        return '%s %s, %s' % (self.get_last_name(), self.get_mother_last_name(), self.get_name())

    #Setter
    def set_name(self, name):
        self.name = name

    def set_last_name(self, last_name):
        self.last_name = last_name

    def set_mother_last_name(self, mother_last_name):
        self.mother_last_name = mother_last_name

    def set_birthday(self, birthday):
        self.birthday = birthday

    def set_gender(self, gender):
        self.gender = gender

    def set_marital_status(self, marital_status):
        self.marital_status = marital_status

    def set_blood_group(self, blood_group):
        self.blood_group = blood_group

    #Getter 
    def get_name(self):
        return self.name

    def get_last_name(self):
        return self.last_name

    def get_mother_last_name(self):
        return self.mother_last_name

    def get_birthday(self):
        return self.birthday 

    def get_gender(self):
        return self.gender

    def get_marital_status(self):
        return self.marital_status 

    def get_blood_group(self):
        return self.blood_group 

    class Meta:
        abstract = True
Example #28
0
class Terceirizada(ExportModelOperationsMixin('terceirizada'), TemChaveExterna,
                   Ativavel, TemIdentificadorExternoAmigavel, TemVinculos):
    nome_fantasia = models.CharField('Nome fantasia',
                                     max_length=160,
                                     blank=True)
    razao_social = models.CharField('Razao social', max_length=160, blank=True)
    cnpj = models.CharField('CNPJ',
                            validators=[MinLengthValidator(14)],
                            max_length=14)
    representante_legal = models.CharField('Representante legal',
                                           max_length=160,
                                           blank=True)
    representante_telefone = models.CharField(
        'Representante contato (telefone)', max_length=160, blank=True)
    representante_email = models.CharField('Representante contato (email)',
                                           max_length=160,
                                           blank=True)
    endereco = models.CharField('Endereco', max_length=160, blank=True)
    cep = models.CharField('CEP', max_length=8, blank=True)
    bairro = models.CharField('Bairro', max_length=150, blank=True)
    cidade = models.CharField('Cidade', max_length=150, blank=True)
    estado = models.CharField('Estado', max_length=150, blank=True)
    numero = models.CharField('Número', max_length=10, blank=True)
    complemento = models.CharField('Complemento', max_length=50, blank=True)
    eh_distribuidor = models.BooleanField('É distribuidor?', default=False)
    responsavel_nome = models.CharField('Responsável',
                                        max_length=160,
                                        blank=True)
    responsavel_email = models.CharField('Responsável contato (email)',
                                         max_length=160,
                                         blank=True)
    responsavel_cpf = models.CharField(
        max_length=11,
        blank=True,
        null=True,
        unique=True,  # noqa DJ01
        validators=[MinLengthValidator(11)])
    responsavel_telefone = models.CharField('Responsável contato (telefone)',
                                            max_length=160,
                                            blank=True)
    responsavel_cargo = models.CharField('Responsável cargo',
                                         max_length=50,
                                         blank=True)

    # TODO: criar uma tabela central (Instituição) para agregar Escola, DRE, Terc e CODAE???
    # e a partir dai a instituição que tem contatos e endereço?
    # o mesmo para pessoa fisica talvez?
    contatos = models.ManyToManyField('dados_comuns.Contato', blank=True)

    @property
    def vinculos_que_podem_ser_finalizados(self):
        return self.vinculos.filter(
            Q(data_inicial=None, data_final=None, ativo=False)
            |  # noqa W504 esperando ativacao
            Q(data_inicial__isnull=False, data_final=None,
              ativo=True)  # noqa W504 ativo
        ).exclude(perfil__nome=NUTRI_ADMIN_RESPONSAVEL)

    def desvincular_lotes(self):
        for lote in self.lotes.all():
            self.lotes.remove(lote)
        self.save()

    @property
    def quantidade_alunos(self):
        quantidade_total = 0
        for lote in self.lotes.all():
            quantidade_total += lote.quantidade_alunos
        return quantidade_total

    @property
    def nome(self):
        return self.nome_fantasia

    @property
    def nutricionistas(self):
        return self.nutricionistas

    @property
    def super_admin(self):
        vinculo = self.vinculos.filter(
            usuario__super_admin_terceirizadas=True).last()
        if vinculo:
            return vinculo.usuario
        return None

    @property
    def inclusoes_continuas_autorizadas(self):
        return InclusaoAlimentacaoContinua.objects.filter(
            escola__lote__in=self.lotes.all(),
            status__in=[
                InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO,
                InclusaoAlimentacaoContinua.workflow_class.
                TERCEIRIZADA_TOMOU_CIENCIA
            ])

    @property
    def inclusoes_normais_autorizadas(self):
        return GrupoInclusaoAlimentacaoNormal.objects.filter(
            escola__lote__in=self.lotes.all(),
            status__in=[
                GrupoInclusaoAlimentacaoNormal.workflow_class.CODAE_AUTORIZADO,
                GrupoInclusaoAlimentacaoNormal.workflow_class.
                TERCEIRIZADA_TOMOU_CIENCIA
            ])

    @property
    def inclusoes_continuas_reprovadas(self):
        return InclusaoAlimentacaoContinua.objects.filter(
            escola__lote__in=self.lotes.all(),
            status=InclusaoAlimentacaoContinua.workflow_class.
            CODAE_NEGOU_PEDIDO)

    @property
    def solicitacao_kit_lanche_avulsa_autorizadas(self):
        return SolicitacaoKitLancheAvulsa.objects.filter(
            escola__lote__in=self.lotes.all(),
            status__in=[
                SolicitacaoKitLancheAvulsa.workflow_class.CODAE_AUTORIZADO,
                SolicitacaoKitLancheAvulsa.workflow_class.
                TERCEIRIZADA_TOMOU_CIENCIA
            ])

    @property
    def inclusoes_normais_reprovadas(self):
        return GrupoInclusaoAlimentacaoNormal.objects.filter(
            escola__lote__in=self.lotes.all(),
            status=GrupoInclusaoAlimentacaoNormal.workflow_class.
            CODAE_NEGOU_PEDIDO)

    # TODO: talvez fazer um manager genérico pra fazer esse filtro

    def inclusoes_continuas_das_minhas_escolas_no_prazo_vencendo(
            self, filtro_aplicado):
        if filtro_aplicado == 'hoje':
            # TODO: rever filtro hoje que nao é mais usado
            inclusoes_continuas = InclusaoAlimentacaoContinua.objects
        else:  # se o filtro nao for hoje, filtra o padrao
            inclusoes_continuas = InclusaoAlimentacaoContinua.vencidos
        return inclusoes_continuas.filter(
            status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def inclusoes_continuas_das_minhas_escolas_no_prazo_limite(
            self, filtro_aplicado):
        if filtro_aplicado == 'daqui_a_7_dias':
            inclusoes_continuas = InclusaoAlimentacaoContinua.desta_semana
        else:
            inclusoes_continuas = InclusaoAlimentacaoContinua.objects  # type: ignore
        return inclusoes_continuas.filter(
            status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def inclusoes_continuas_das_minhas_escolas_no_prazo_regular(
            self, filtro_aplicado):
        if filtro_aplicado == 'daqui_a_30_dias':
            inclusoes_continuas = InclusaoAlimentacaoContinua.deste_mes
        elif filtro_aplicado == 'daqui_a_7_dias':
            inclusoes_continuas = InclusaoAlimentacaoContinua.desta_semana  # type: ignore
        else:
            inclusoes_continuas = InclusaoAlimentacaoContinua.objects  # type: ignore
        return inclusoes_continuas.filter(
            status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def inclusoes_normais_das_minhas_escolas_no_prazo_vencendo(
            self, filtro_aplicado):
        if filtro_aplicado == 'hoje':
            # TODO: rever filtro hoje que nao é mais usado
            inclusoes_normais = GrupoInclusaoAlimentacaoNormal.objects
        else:
            inclusoes_normais = GrupoInclusaoAlimentacaoNormal.vencidos
        return inclusoes_normais.filter(
            status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def inclusoes_normais_das_minhas_escolas_no_prazo_limite(
            self, filtro_aplicado):
        if filtro_aplicado == 'daqui_a_7_dias':
            inclusoes_normais = GrupoInclusaoAlimentacaoNormal.desta_semana
        else:
            inclusoes_normais = GrupoInclusaoAlimentacaoNormal.objects  # type: ignore
        return inclusoes_normais.filter(
            status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def inclusoes_normais_das_minhas_escolas_no_prazo_regular(
            self, filtro_aplicado):
        if filtro_aplicado == 'daqui_a_30_dias':
            inclusoes_normais = GrupoInclusaoAlimentacaoNormal.deste_mes
        elif filtro_aplicado == 'daqui_a_7_dias':
            inclusoes_normais = GrupoInclusaoAlimentacaoNormal.desta_semana  # type: ignore
        else:
            inclusoes_normais = GrupoInclusaoAlimentacaoNormal.objects  # type: ignore
        return inclusoes_normais.filter(
            status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def alteracoes_cardapio_das_minhas_escolas_no_prazo_vencendo(
            self, filtro_aplicado):
        if filtro_aplicado == 'hoje':
            # TODO: rever filtro hoje que nao é mais usado
            alteracoes_cardapio = AlteracaoCardapio.objects
        else:
            alteracoes_cardapio = AlteracaoCardapio.vencidos
        return alteracoes_cardapio.filter(
            status=AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def alteracoes_cardapio_das_minhas_escolas_no_prazo_limite(
            self, filtro_aplicado):
        if filtro_aplicado == 'daqui_a_7_dias':
            alteracoes_cardapio = AlteracaoCardapio.desta_semana
        else:
            alteracoes_cardapio = AlteracaoCardapio.objects  # type: ignore
        return alteracoes_cardapio.filter(
            status=AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def alteracoes_cardapio_das_minhas_escolas_no_prazo_regular(
            self, filtro_aplicado):
        if filtro_aplicado == 'daqui_a_30_dias':
            alteracoes_cardapio = AlteracaoCardapio.deste_mes
        elif filtro_aplicado == 'daqui_a_7_dias':
            alteracoes_cardapio = AlteracaoCardapio.desta_semana  # type: ignore
        else:
            alteracoes_cardapio = AlteracaoCardapio.objects  # type: ignore
        return alteracoes_cardapio.filter(
            status=AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def alteracoes_cardapio_das_minhas(self, filtro_aplicado):
        queryset = queryset_por_data(filtro_aplicado, AlteracaoCardapio)
        return queryset.filter(status__in=[
            AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO,
            AlteracaoCardapio.workflow_class.CODAE_QUESTIONADO
        ],
                               escola__lote__in=self.lotes.all())

    def alteracoes_cardapio_cei_das_minhas(self, filtro_aplicado):
        queryset = queryset_por_data(filtro_aplicado, AlteracaoCardapioCEI)
        return queryset.filter(status__in=[
            AlteracaoCardapioCEI.workflow_class.CODAE_AUTORIZADO,
            AlteracaoCardapioCEI.workflow_class.CODAE_QUESTIONADO
        ],
                               escola__lote__in=self.lotes.all())

    def grupos_inclusoes_alimentacao_normal_das_minhas_escolas(
            self, filtro_aplicado):
        queryset = queryset_por_data(filtro_aplicado,
                                     GrupoInclusaoAlimentacaoNormal)
        return queryset.filter(
            status=AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def inclusoes_alimentacao_de_cei_das_minhas_escolas(self, filtro_aplicado):
        return self.filtra_solicitacoes_minhas_escolas_a_validar_por_data(
            filtro_aplicado, InclusaoAlimentacaoDaCEI)

    def inclusoes_alimentacao_continua_das_minhas_escolas(
            self, filtro_aplicado):
        queryset = queryset_por_data(filtro_aplicado,
                                     InclusaoAlimentacaoContinua)
        return queryset.filter(
            status=AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO,
            escola__lote__in=self.lotes.all())

    def suspensoes_alimentacao_das_minhas_escolas(self, filtro_aplicado):
        queryset = queryset_por_data(filtro_aplicado,
                                     GrupoSuspensaoAlimentacao)
        return queryset.filter(
            status=GrupoSuspensaoAlimentacao.workflow_class.INFORMADO,
            escola__lote__in=self.lotes.all())

    @property
    def alteracoes_cardapio_autorizadas(self):
        return AlteracaoCardapio.objects.filter(
            escola__lote__in=self.lotes.all(),
            status__in=[
                AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO,
                AlteracaoCardapio.workflow_class.TERCEIRIZADA_TOMOU_CIENCIA
            ])

    @property
    def alteracoes_cardapio_reprovadas(self):
        return AlteracaoCardapio.objects.filter(
            escola__lote__in=self.lotes.all(),
            status=AlteracaoCardapio.workflow_class.CODAE_NEGOU_PEDIDO)

    #
    # Inversão de dia de cardápio
    #

    def inversoes_cardapio_das_minhas_escolas(self, filtro_aplicado):
        if filtro_aplicado == 'daqui_a_7_dias':
            inversoes_cardapio = InversaoCardapio.desta_semana
        elif filtro_aplicado == 'daqui_a_30_dias':
            inversoes_cardapio = InversaoCardapio.deste_mes  # type: ignore
        else:
            inversoes_cardapio = InversaoCardapio.objects  # type: ignore
        return inversoes_cardapio.filter(
            escola__lote__in=self.lotes.all(),
            status=InversaoCardapio.workflow_class.CODAE_AUTORIZADO)

    @property
    def inversoes_cardapio_autorizadas(self):
        return InversaoCardapio.objects.filter(
            escola__lote__in=self.lotes.all(),
            status__in=[
                InversaoCardapio.workflow_class.CODAE_AUTORIZADO,
                InversaoCardapio.workflow_class.TERCEIRIZADA_TOMOU_CIENCIA
            ])

    #
    # Solicitação Unificada
    #

    def solicitacoes_unificadas_das_minhas_escolas(self, filtro_aplicado):
        if filtro_aplicado == 'daqui_a_7_dias':
            solicitacoes_unificadas = SolicitacaoKitLancheUnificada.desta_semana
        elif filtro_aplicado == 'daqui_a_30_dias':
            solicitacoes_unificadas = SolicitacaoKitLancheUnificada.deste_mes  # type: ignore
        else:
            solicitacoes_unificadas = SolicitacaoKitLancheUnificada.objects  # type: ignore
        return solicitacoes_unificadas.filter(
            escolas_quantidades__escola__lote__in=self.lotes.all(),
            status=SolicitacaoKitLancheUnificada.workflow_class.
            CODAE_AUTORIZADO).distinct()

    @property
    def solicitacoes_unificadas_autorizadas(self):
        return SolicitacaoKitLancheUnificada.objects.filter(
            escolas_quantidades__escola__lote__in=self.lotes.all(),
            status__in=[
                SolicitacaoKitLancheUnificada.workflow_class.CODAE_AUTORIZADO,
                SolicitacaoKitLancheUnificada.workflow_class.
                TERCEIRIZADA_TOMOU_CIENCIA
            ]).distinct()

    def solicitacoes_kit_lanche_das_minhas_escolas_a_validar(
            self, filtro_aplicado):
        if filtro_aplicado == 'daqui_a_7_dias':
            solicitacoes_kit_lanche = SolicitacaoKitLancheAvulsa.desta_semana
        elif filtro_aplicado == 'daqui_a_30_dias':
            solicitacoes_kit_lanche = SolicitacaoKitLancheAvulsa.deste_mes  # type: ignore
        else:
            solicitacoes_kit_lanche = SolicitacaoKitLancheAvulsa.objects  # type: ignore
        return solicitacoes_kit_lanche.filter(
            escola__lote__in=self.lotes.all(),
            status__in=[
                SolicitacaoKitLancheAvulsa.workflow_class.CODAE_AUTORIZADO,
                SolicitacaoKitLancheAvulsa.workflow_class.CODAE_QUESTIONADO
            ])

    def solicitacoes_kit_lanche_cei_das_minhas_escolas_a_validar(
            self, filtro_aplicado):
        if filtro_aplicado == 'daqui_a_7_dias':
            solicitacoes_kit_lanche = SolicitacaoKitLancheCEIAvulsa.desta_semana
        elif filtro_aplicado == 'daqui_a_30_dias':
            solicitacoes_kit_lanche = SolicitacaoKitLancheCEIAvulsa.deste_mes  # type: ignore
        else:
            solicitacoes_kit_lanche = SolicitacaoKitLancheCEIAvulsa.objects  # type: ignore
        return solicitacoes_kit_lanche.filter(
            escola__lote__in=self.lotes.all(),
            status__in=[
                SolicitacaoKitLancheCEIAvulsa.workflow_class.CODAE_AUTORIZADO,
                SolicitacaoKitLancheCEIAvulsa.workflow_class.CODAE_QUESTIONADO
            ])

    def __str__(self):
        return f'{self.nome_fantasia}'

    class Meta:
        verbose_name = 'Terceirizada'
        verbose_name_plural = 'Terceirizadas'
Example #29
0
class Contest(models.Model):
    title = models.CharField(max_length=200)

    author = models.ForeignKey(to=User, on_delete=models.PROTECT)

    short_description = models.TextField(
        verbose_name="Short Description",
        max_length=250,
        help_text="A short description whch describes your contest.",
        null=True,
    )

    description = RichTextUploadingField(
        help_text="Give a brief or detailed description for your contest")

    eligibility = models.TextField(
        null=True,
        help_text="What is the eligibility criteria for participants?",
    )

    rules = models.TextField(
        null=True,
        help_text="What are the rules that all participants must follow?",
    )

    prizes = models.TextField(
        null=True,
        help_text="Mention prizes for diff positions/winners (If any)",
        max_length=200)

    contacts = models.TextField(
        null=True,
        help_text=
        "Give your email, phone etc. so that people can contact you if they need to"
    )

    start_date = models.DateField(verbose_name="Start Date")

    start_time = models.TimeField(verbose_name="Start Time", null=True)

    end_date = models.DateField(verbose_name="End Date")

    end_time = models.TimeField(verbose_name="End Time", null=True)

    unique_code = models.CharField(
        verbose_name="Unique Code",
        max_length=15,
        validators=[MinLengthValidator(3), unique_code_validator],
        unique=True,
        db_index=True,
        help_text=
        "A unique code for your contest. between 3-15 characters. May contain only \
                                      lowercase characters and numbers. For example if the question name is 'Sorting Array', \
                                      you may name the code SORTARR")

    is_public = models.BooleanField(
        verbose_name="Is this Public?",
        default=True,
        help_text=
        "If you choose to make this non public, please enter a link below that participants will\
                                  click to register for the contest. It can lead to a form or a website etc. After they complete \
                                  registration, it is your responsibility to add them in the participants list via\
                                   the REST API call.")

    status = models.IntegerField(
        default=0,
        help_text="0-Yet to start, 1- live, 2- ended",
        validators=[MinValueValidator(0),
                    MaxValueValidator(2)])

    registration_link = models.URLField(verbose_name="Registration Link",
                                        blank=True)

    participants = models.ManyToManyField(
        to=User, related_name="participating_contests")

    def __str__(self):
        return self.unique_code
Example #30
0
class Team(UUIDClassicModel):
    organization: models.ForeignKey = models.ForeignKey(
        "posthog.Organization",
        on_delete=models.CASCADE,
        related_name="teams",
        related_query_name="team")
    api_token: models.CharField = models.CharField(
        max_length=200,
        unique=True,
        default=generate_random_token,
        validators=[
            MinLengthValidator(
                10, "Project's API token must be at least 10 characters long!")
        ],
    )
    app_urls: ArrayField = ArrayField(models.CharField(max_length=200,
                                                       null=True),
                                      default=list,
                                      blank=True)
    name: models.CharField = models.CharField(
        max_length=200,
        default="Default Project",
        validators=[MinLengthValidator(1, "Project must have a name!")],
    )
    slack_incoming_webhook: models.CharField = models.CharField(max_length=500,
                                                                null=True,
                                                                blank=True)
    created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True)
    updated_at: models.DateTimeField = models.DateTimeField(auto_now=True)
    anonymize_ips: models.BooleanField = models.BooleanField(default=False)
    completed_snippet_onboarding: models.BooleanField = models.BooleanField(
        default=False)
    ingested_event: models.BooleanField = models.BooleanField(default=False)
    session_recording_opt_in: models.BooleanField = models.BooleanField(
        default=False)
    session_recording_retention_period_days: models.IntegerField = models.IntegerField(
        null=True, default=None, blank=True)
    signup_token: models.CharField = models.CharField(max_length=200,
                                                      null=True,
                                                      blank=True)
    is_demo: models.BooleanField = models.BooleanField(default=False)
    test_account_filters: models.JSONField = models.JSONField(default=list)
    timezone: models.CharField = models.CharField(max_length=240,
                                                  choices=TIMEZONES,
                                                  default="UTC")
    data_attributes: models.JSONField = models.JSONField(
        default=get_default_data_attributes)

    # DEPRECATED, DISUSED: plugins are enabled for everyone now
    plugins_opt_in: models.BooleanField = models.BooleanField(default=False)
    # DEPRECATED, DISUSED: replaced with env variable OPT_OUT_CAPTURE and User.anonymized_data
    opt_out_capture: models.BooleanField = models.BooleanField(default=False)
    # DEPRECATED, DISUSED: now managing access in an Organization-centric way
    users: models.ManyToManyField = models.ManyToManyField(
        "User", blank=True, related_name="teams_deprecated_relationship")
    # DEPRECATED: in favor of `EventDefinition` model
    event_names: models.JSONField = models.JSONField(default=list)
    event_names_with_usage: models.JSONField = models.JSONField(default=list)
    # DEPRECATED: in favor of `PropertyDefinition` model
    event_properties: models.JSONField = models.JSONField(default=list)
    event_properties_with_usage: models.JSONField = models.JSONField(
        default=list)
    event_properties_numerical: models.JSONField = models.JSONField(
        default=list)

    objects: TeamManager = TeamManager()

    def __str__(self):
        if self.name:
            return self.name
        if self.app_urls and self.app_urls[0]:
            return ", ".join(self.app_urls)
        return str(self.pk)

    __repr__ = sane_repr("uuid", "name", "api_token")

    def get_latest_event_names_with_usage(self):
        """
        TODO: #4070 This has been deprecated in favor of `EventDefinition` and should be removed upon final migration.
        Fetches `event_names_with_usage` but adding any events that may have come in since the
        property was last computed. Ensures all events are included.
        """
        def get_key(event: str, type: str):
            return next((item.get(type) for item in self.event_names_with_usage
                         if item["event"] == event), None)

        return [{
            "event": event,
            "volume": get_key(event, "volume"),
            "usage_count": get_key(event, "usage_count")
        } for event in self.event_names]

    def get_latest_event_properties_with_usage(self):
        """
        TODO: #4070 This has been deprecated in favor of `EventDefinition` and should be removed upon final migration.
        Fetches `event_properties_with_usage` but adding any properties that may have appeared since the
        property was last computed. Ensures all properties are included.
        """
        def get_key(key: str, type: str):
            return next((item.get(type)
                         for item in self.event_properties_with_usage
                         if item["key"] == key), None)

        return [{
            "key": key,
            "volume": get_key(key, "volume"),
            "usage_count": get_key(key, "usage_count")
        } for key in self.event_properties]