Beispiel #1
0
class RegistroVotacao(models.Model):
    tipo_resultado_votacao = models.ForeignKey(
        TipoResultadoVotacao,
        on_delete=models.PROTECT,
        verbose_name=_('Resultado da Votação'))
    materia = models.ForeignKey(MateriaLegislativa, on_delete=models.CASCADE)
    ordem = models.ForeignKey(OrdemDia,
                              blank=True,
                              null=True,
                              related_name="registrovotacao_set",
                              on_delete=models.CASCADE)
    expediente = models.ForeignKey(ExpedienteMateria,
                                   blank=True,
                                   null=True,
                                   on_delete=models.CASCADE)
    numero_votos_sim = models.PositiveIntegerField(verbose_name=_('Sim'))
    numero_votos_nao = models.PositiveIntegerField(verbose_name=_('Não'))
    numero_abstencoes = models.PositiveIntegerField(
        verbose_name=_('Abstenções'))
    observacao = models.TextField(blank=True, verbose_name=_('Observações'))

    subscricoes = ManyToManyField(Parlamentar, related_name='subscricoes')

    user = models.ForeignKey(get_settings_auth_user_model(),
                             on_delete=models.PROTECT,
                             null=True,
                             blank=True)
    ip = models.CharField(verbose_name=_('IP'),
                          max_length=30,
                          blank=True,
                          default='')
    data_hora = models.DateTimeField(verbose_name=_('Data/Hora'),
                                     auto_now_add=True,
                                     blank=True,
                                     null=True)

    class Meta:
        verbose_name = _('Votação')
        verbose_name_plural = _('Votações')
        ordering = ('id', )

    def __str__(self):
        return _('Ordem: %(ordem)s - Votação: %(votacao)s - '
                 'Matéria: %(materia)s') % {
                     'ordem': self.ordem,
                     'votacao': self.tipo_resultado_votacao,
                     'materia': self.materia
                 }

    def clean(self):
        """Exatamente um dos campos ordem ou expediente deve estar preenchido.
        """
        # TODO remover esse método quando OrdemDia e ExpedienteMateria
        # forem reestruturados e os campos ordem e expediente forem unificados
        if not xor(bool(self.ordem), bool(self.expediente)):
            raise ValidationError(
                'RegistroVotacao deve ter exatamente um dos campos '
                'ordem ou expediente preenchido. Ambos estão preenchidos: '
                '{}, {}'.format(self.ordem, self.expediente))
Beispiel #2
0
class TramitacaoAdministrativo(models.Model):
    status = models.ForeignKey(
        StatusTramitacaoAdministrativo,
        on_delete=models.PROTECT,
        verbose_name=_('Status'))
    documento = models.ForeignKey(DocumentoAdministrativo,
                                  on_delete=models.PROTECT)
    timestamp = models.DateTimeField(default=timezone.now)
    data_tramitacao = models.DateField(
        verbose_name=_('Data Tramitação'))
    unidade_tramitacao_local = models.ForeignKey(
        UnidadeTramitacao,
        related_name='adm_tramitacoes_origem',
        on_delete=models.PROTECT,
        verbose_name=_('Unidade Local'))
    data_encaminhamento = models.DateField(
        blank=True, null=True, verbose_name=_('Data Encaminhamento'))
    unidade_tramitacao_destino = models.ForeignKey(
        UnidadeTramitacao,
        related_name='adm_tramitacoes_destino',
        on_delete=models.PROTECT,
        verbose_name=_('Unidade Destino'))
    urgente = models.BooleanField(verbose_name=_('Urgente ?'),
                                  choices=YES_NO_CHOICES,
                                  default=False)
    texto = models.TextField(verbose_name=_('Texto da Ação'))
    data_fim_prazo = models.DateField(
        blank=True, null=True, verbose_name=_('Data Fim do Prazo'))
    user = models.ForeignKey(get_settings_auth_user_model(),
                             verbose_name=_('Usuário'),
                             on_delete=models.PROTECT,
                             null=True,
                             blank=True)
    ip = models.CharField(verbose_name=_('IP'),
                          max_length=30,
                          blank=True,
                          default='')
    ultima_edicao = models.DateTimeField(
        verbose_name=_('Data e Hora da Edição'),
        blank=True, null=True
    )

    class Meta:
        verbose_name = _('Tramitação de Documento Administrativo')
        verbose_name_plural = _('Tramitações de Documento Administrativo')

    def __str__(self):
        return _('%(documento)s - %(status)s') % {
            'documento': self.documento, 'status': self.status
        }
Beispiel #3
0
class AutorUser(models.Model):
    autor = models.ForeignKey(Autor,
                              verbose_name=_('Autor'),
                              on_delete=models.PROTECT)
    user = models.OneToOneField(
        get_settings_auth_user_model(),
        verbose_name=_('Usuário'),
        on_delete=models.PROTECT,
    )

    class Meta:
        verbose_name = _('Autor - Usuário')
        verbose_name_plural = _('Autores - Usuários')
        ordering = ('autor__nome', )

    def __str__(self):
        return "%s - %s" % (self.autor, self.user)
Beispiel #4
0
class VotoParlamentar(models.Model):  # RegistroVotacaoParlamentar
    '''
    As colunas ordem e expediente são redundantes, levando em consideração
    que RegistroVotacao já possui ordem/expediente. Entretanto, para
    viabilizar a votação interativa, uma vez que ela é feita antes de haver
    um RegistroVotacao, é preciso identificar o voto por ordem/expediente.
    '''
    votacao = models.ForeignKey(RegistroVotacao,
                                blank=True,
                                null=True,
                                on_delete=models.CASCADE)
    parlamentar = models.ForeignKey(Parlamentar, on_delete=models.PROTECT)
    voto = models.CharField(max_length=10)

    user = models.ForeignKey(get_settings_auth_user_model(),
                             on_delete=models.PROTECT,
                             null=True,
                             blank=True)
    ip = models.CharField(verbose_name=_('IP'),
                          max_length=30,
                          blank=True,
                          default='')
    data_hora = models.DateTimeField(verbose_name=_('Data/Hora'),
                                     auto_now=True,
                                     blank=True,
                                     null=True)

    ordem = models.ForeignKey(OrdemDia,
                              blank=True,
                              null=True,
                              on_delete=models.CASCADE)
    expediente = models.ForeignKey(ExpedienteMateria,
                                   blank=True,
                                   null=True,
                                   on_delete=models.CASCADE)

    class Meta:
        verbose_name = _('Registro de Votação de Parlamentar')
        verbose_name_plural = _('Registros de Votações de Parlamentares')

    def __str__(self):
        return _('Votação: %(votacao)s - Parlamentar: %(parlamentar)s') % {
            'votacao': self.votacao,
            'parlamentar': self.parlamentar
        }
Beispiel #5
0
class RegistroLeitura(models.Model):
    materia = models.ForeignKey(MateriaLegislativa, on_delete=models.CASCADE)
    ordem = models.ForeignKey(OrdemDia,
                              blank=True,
                              null=True,
                              on_delete=models.CASCADE)
    expediente = models.ForeignKey(ExpedienteMateria,
                                   blank=True,
                                   null=True,
                                   on_delete=models.CASCADE)
    observacao = models.TextField(
        blank=True, verbose_name=_('Observações'))
    user = models.ForeignKey(get_settings_auth_user_model(),
                             on_delete=models.PROTECT,
                             null=True,
                             blank=True)
    ip = models.CharField(verbose_name=_('IP'),
                          max_length=60,
                          blank=True,
                          default='')
    data_hora = models.DateTimeField(
        verbose_name=_('Data/Hora'),
        auto_now=True,
        blank=True,
        null=True)

    class Meta:
        verbose_name = _('Leitura')
        verbose_name_plural = _('Leituras')

    def __str__(self):
        return _('Leitura - '
                 'Matéria: %(materia)s') % {
            'materia': self.materia}

    def clean(self):
        """Exatamente um dos campos ordem ou expediente deve estar preenchido.
        """
        # TODO remover esse método quando OrdemDia e ExpedienteMateria
        # forem reestruturados e os campos ordem e expediente forem unificados
        if not xor(bool(self.ordem), bool(self.expediente)):
            raise ValidationError(
                'RegistroLeitura deve ter exatamente um dos campos '
                'ordem ou expediente preenchido. Ambos estão preenchidos: '
                '{}, {}'. format(self.ordem, self.expediente))
Beispiel #6
0
class Autor(models.Model):

    user = models.OneToOneField(get_settings_auth_user_model(),
                                on_delete=models.SET_NULL,
                                null=True)

    tipo = models.ForeignKey(TipoAutor,
                             verbose_name=_('Tipo do Autor'),
                             on_delete=models.PROTECT)

    content_type = models.ForeignKey(ContentType,
                                     blank=True,
                                     null=True,
                                     default=None)
    object_id = models.PositiveIntegerField(blank=True,
                                            null=True,
                                            default=None)
    autor_related = GenericForeignKey('content_type', 'object_id')

    nome = models.CharField(max_length=120,
                            blank=True,
                            verbose_name=_('Nome do Autor'))

    cargo = models.CharField(max_length=50, blank=True)

    class Meta:
        verbose_name = _('Autor')
        verbose_name_plural = _('Autores')
        unique_together = (('content_type', 'object_id'), )
        ordering = ('nome', )

    def __str__(self):
        if self.autor_related:
            return str(self.autor_related)
        else:
            if self.nome:
                if self.cargo:
                    return '{} - {}'.format(self.nome, self.cargo)
                else:
                    return str(self.nome)
        if self.user:
            return str(self.user.username)
        return '?'
Beispiel #7
0
class VotoNominal(models.Model):
    parlamentar = models.ForeignKey(Parlamentar, on_delete=models.PROTECT)
    voto = models.CharField(verbose_name=_('Voto'), max_length=10)

    sessao = models.ForeignKey(SessaoPlenaria, on_delete=models.PROTECT)
    materia = models.ForeignKey(MateriaLegislativa, on_delete=models.PROTECT)

    user = models.ForeignKey(get_settings_auth_user_model(),
                             on_delete=models.PROTECT)
    ip = models.CharField(verbose_name=_('IP'), max_length=30)
    data_hora = models.DateTimeField(verbose_name=_('Data/Hora'),
                                     auto_now_add=True)

    class Meta:
        verbose_name = _('Registro do Voto do Parlamentar')
        verbose_name_plural = _('Registros dos Votos dos Parlamentares')

    def __str__(self):
        return '%s - %s' % (self.parlamentar.nome_parlamentar, self.voto)
Beispiel #8
0
class Autor(models.Model):

    user = models.OneToOneField(get_settings_auth_user_model(),
                                on_delete=models.SET_NULL,
                                null=True)

    tipo = models.ForeignKey(TipoAutor, verbose_name=_('Tipo do Autor'))

    content_type = models.ForeignKey(ContentType,
                                     blank=True,
                                     null=True,
                                     default=None)
    object_id = models.PositiveIntegerField(blank=True,
                                            null=True,
                                            default=None)
    autor_related = GenericForeignKey('content_type', 'object_id')

    nome = models.CharField(max_length=60,
                            blank=True,
                            verbose_name=_('Nome do Autor'))

    cargo = models.CharField(max_length=50, blank=True)

    class Meta:
        verbose_name = _('Autor')
        verbose_name_plural = _('Autores')
        unique_together = (('content_type', 'object_id'), )
        ordering = ('nome', )

    def __str__(self):

        if self.autor_related:
            return str(self.autor_related)
        else:
            if str(self.cargo):
                return _('%(nome)s - %(cargo)s') % {
                    'nome': self.nome,
                    'cargo': self.cargo
                }
            else:
                return str(self.nome)
        """if str(self.tipo) == 'Parlamentar' and self.parlamentar:
Beispiel #9
0
class Votante(models.Model):
    parlamentar = models.ForeignKey(
        Parlamentar, verbose_name=_('Parlamentar'),
        on_delete=models.PROTECT, related_name='parlamentar')
    user = models.ForeignKey(
        get_settings_auth_user_model(), on_delete=models.PROTECT,
        verbose_name=_('User'), related_name='user')
    data = models.DateTimeField(
        verbose_name=_('Data'), auto_now_add=True,
        max_length=30, null=True, blank=True)

    class Meta:
        verbose_name = _('Usuário')
        verbose_name_plural = _('Usuários')
        permissions = (
            ('can_vote', _('Can Vote')),
        )

    def __str__(self):
        return self.user.username
Beispiel #10
0
class NormaJuridica(models.Model):
    ESFERA_FEDERACAO_CHOICES = Choices(
        ('M', 'municipal', _('Municipal')),
        ('E', 'estadual', _('Estadual')),
        ('F', 'federal', _('Federal')),
    )

    texto_integral = models.FileField(
        blank=True,
        null=True,
        upload_to=norma_upload_path,
        verbose_name=_('Texto Integral'),
        storage=OverwriteStorage(),
        validators=[restringe_tipos_de_arquivo_txt])
    tipo = models.ForeignKey(TipoNormaJuridica,
                             on_delete=models.PROTECT,
                             verbose_name=_('Tipo da Norma Jurídica'))
    materia = models.ForeignKey(MateriaLegislativa,
                                blank=True,
                                null=True,
                                on_delete=models.PROTECT,
                                verbose_name=_('Matéria'))
    numero = models.CharField(max_length=8, verbose_name=_('Número'))
    ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'),
                                           choices=RANGE_ANOS)
    esfera_federacao = models.CharField(max_length=1,
                                        verbose_name=_('Esfera Federação'),
                                        choices=ESFERA_FEDERACAO_CHOICES)
    data = models.DateField(blank=False, null=True, verbose_name=_('Data'))
    data_publicacao = models.DateField(blank=True,
                                       null=True,
                                       verbose_name=_('Data de Publicação'))
    veiculo_publicacao = models.CharField(
        max_length=30, blank=True, verbose_name=_('Veículo de Publicação'))
    pagina_inicio_publicacao = models.PositiveIntegerField(
        blank=True, null=True, verbose_name=_('Pg. Início'))
    pagina_fim_publicacao = models.PositiveIntegerField(
        blank=True, null=True, verbose_name=_('Pg. Fim'))
    ementa = models.TextField(verbose_name=_('Ementa'))
    indexacao = models.TextField(blank=True, verbose_name=_('Indexação'))
    observacao = models.TextField(blank=True, verbose_name=_('Observação'))
    complemento = models.NullBooleanField(blank=True,
                                          verbose_name=_('Complementar ?'),
                                          choices=YES_NO_CHOICES)
    # XXX was a CharField (attention on migrate)
    assuntos = models.ManyToManyField(AssuntoNorma,
                                      blank=True,
                                      verbose_name=_('Assuntos'))
    data_vigencia = models.DateField(blank=True,
                                     null=True,
                                     verbose_name=_('Data Fim Vigência'))
    timestamp = models.DateTimeField(null=True)

    texto_articulado = GenericRelation(TextoArticulado,
                                       related_query_name='texto_articulado')

    data_ultima_atualizacao = models.DateTimeField(blank=True,
                                                   null=True,
                                                   auto_now=True,
                                                   verbose_name=_('Data'))

    autores = models.ManyToManyField(Autor,
                                     through='AutoriaNorma',
                                     through_fields=('norma', 'autor'),
                                     symmetrical=False)

    norma_de_destaque = models.BooleanField(
        verbose_name=_('Norma de Destaque ?'),
        choices=YES_NO_CHOICES,
        default=False)

    apelido = models.TextField(blank=True, verbose_name=_('Apelido'))

    user = models.ForeignKey(get_settings_auth_user_model(),
                             verbose_name=_('Usuário'),
                             on_delete=models.PROTECT,
                             null=True,
                             blank=True)
    ip = models.CharField(verbose_name=_('IP'),
                          max_length=30,
                          blank=True,
                          default='')

    class Meta:
        verbose_name = _('Norma Jurídica')
        verbose_name_plural = _('Normas Jurídicas')
        ordering = ['-data', '-numero']

    def get_normas_relacionadas(self):
        principais = NormaRelacionada.objects.filter(
            norma_principal=self.id).order_by('norma_principal__data',
                                              'norma_relacionada__data')
        relacionadas = NormaRelacionada.objects.filter(
            norma_relacionada=self.id).order_by('norma_principal__data',
                                                'norma_relacionada__data')
        return (principais, relacionadas)

    def get_anexos_norma_juridica(self):
        anexos = AnexoNormaJuridica.objects.filter(norma=self.id)
        return anexos

    def __str__(self):
        return _('%(tipo)s nº %(numero)s de %(data)s') % {
            'tipo': self.tipo,
            'numero': self.numero,
            'data': defaultfilters.date(self.data, "d \d\e F \d\e Y")
        }

    @property
    def epigrafe(self):
        return _('%(tipo)s nº %(numero)s de %(data)s') % {
            'tipo': self.tipo,
            'numero': self.numero,
            'data': defaultfilters.date(self.data, "d \d\e F \d\e Y")
        }

    def delete(self, using=None, keep_parents=False):
        if self.texto_integral:
            self.texto_integral.delete()

        return models.Model.delete(self,
                                   using=using,
                                   keep_parents=keep_parents)

    def save(self,
             force_insert=False,
             force_update=False,
             using=None,
             update_fields=None):

        if not self.pk and self.texto_integral:
            texto_integral = self.texto_integral
            self.texto_integral = None
            models.Model.save(self,
                              force_insert=force_insert,
                              force_update=force_update,
                              using=using,
                              update_fields=update_fields)
            self.texto_integral = texto_integral

        return models.Model.save(self,
                                 force_insert=force_insert,
                                 force_update=force_update,
                                 using=using,
                                 update_fields=update_fields)
Beispiel #11
0
class Proposicao(models.Model):
    autor = models.ForeignKey(Autor,
                              null=True,
                              blank=True,
                              on_delete=models.PROTECT)
    tipo = models.ForeignKey(TipoProposicao,
                             on_delete=models.PROTECT,
                             blank=False,
                             null=True,
                             verbose_name=_('Tipo'))

    # XXX data_envio was not null, but actual data said otherwise!!!
    data_envio = models.DateTimeField(blank=False,
                                      null=True,
                                      verbose_name=_('Data de Envio'))
    data_recebimento = models.DateTimeField(
        blank=True, null=True, verbose_name=_('Data de Recebimento'))
    data_devolucao = models.DateTimeField(blank=True,
                                          null=True,
                                          verbose_name=_('Data de Devolução'))

    descricao = models.TextField(verbose_name=_('Ementa'))
    justificativa_devolucao = models.CharField(
        max_length=200,
        blank=True,
        verbose_name=_('Justificativa da Devolução'))

    ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'),
                                           default=None,
                                           blank=True,
                                           null=True,
                                           choices=RANGE_ANOS)

    numero_proposicao = models.PositiveIntegerField(blank=True,
                                                    null=True,
                                                    verbose_name=_('Número'))

    numero_materia_futuro = models.PositiveIntegerField(
        blank=True, null=True, verbose_name=_('Número Matéria'))

    hash_code = models.CharField(verbose_name=_('Código do Documento'),
                                 max_length=200,
                                 blank=True)
    """
    FIXME Campo não é necessário na modelagem e implementação atual para o
    módulo de proposições.
    E - Enviada é tratado pela condição do campo data_envio - se None n enviado
        se possui uma data, enviada
    R - Recebida é uma condição do campo data_recebimento - se None não receb.
        se possui uma data, enviada, recebida e incorporada
    I - A incorporação é automática ao ser recebida

    e ainda possui a condição de Devolvida onde o campo data_devolucao é
    direfente de None, fornecedo a informação para o usuário da data que o
    responsável devolveu bem como a justificativa da devolução.
    Essa informação fica disponível para o Autor até que ele envie novamente
    sua proposição ou resolva excluir.
    """
    # ind_enviado and ind_devolvido collapsed as char field (status)
    status = models.CharField(blank=True,
                              max_length=1,
                              choices=(('E', 'Enviada'), ('R', 'Recebida'),
                                       ('I', 'Incorporada')),
                              verbose_name=_('Status Proposição'))
    texto_original = models.FileField(
        max_length=300,
        upload_to=materia_upload_path,
        blank=True,
        null=True,
        verbose_name=_('Texto Original'),
        storage=OverwriteStorage(),
        validators=[restringe_tipos_de_arquivo_txt])

    texto_articulado = GenericRelation(TextoArticulado,
                                       related_query_name='texto_articulado')

    materia_de_vinculo = models.ForeignKey(MateriaLegislativa,
                                           blank=True,
                                           null=True,
                                           on_delete=models.CASCADE,
                                           verbose_name=_('Matéria anexadora'),
                                           related_name=_('proposicao_set'))

    content_type = models.ForeignKey(ContentType,
                                     default=None,
                                     blank=True,
                                     null=True,
                                     verbose_name=_('Tipo de Material Gerado'))
    object_id = models.PositiveIntegerField(blank=True,
                                            null=True,
                                            default=None)
    conteudo_gerado_related = SaplGenericForeignKey(
        'content_type', 'object_id', verbose_name=_('Conteúdo Gerado'))
    observacao = models.TextField(blank=True, verbose_name=_('Observação'))
    cancelado = models.BooleanField(verbose_name=_('Cancelada ?'),
                                    choices=YES_NO_CHOICES,
                                    default=False)
    """# Ao ser recebida, irá gerar uma nova matéria ou um documento acessorio
    # de uma já existente
    materia_gerada = models.ForeignKey(
        MateriaLegislativa, blank=True, null=True,
        related_name=_('materia_gerada'))
    documento_gerado = models.ForeignKey(
        DocumentoAcessorio, blank=True, null=True)"""

    user = models.ForeignKey(get_settings_auth_user_model(),
                             verbose_name=_('Usuário'),
                             on_delete=models.PROTECT,
                             null=True,
                             blank=True)
    ip = models.CharField(verbose_name=_('IP'),
                          max_length=60,
                          blank=True,
                          default='')
    ultima_edicao = models.DateTimeField(
        verbose_name=_('Data e Hora da Edição'), blank=True, null=True)

    @property
    def perfis(self):
        return self.tipo.perfis.all()

    @property
    def title_type(self):
        return '%s nº _____ %s' % (self.tipo,
                                   formats.date_format(
                                       self.data_envio if self.data_envio else
                                       timezone.now(), "\d\e d \d\e F \d\e Y"))

    class Meta:
        ordering = ['-data_recebimento']
        verbose_name = _('Proposição')
        verbose_name_plural = _('Proposições')
        unique_together = (('content_type', 'object_id'), )
        permissions = (
            ('detail_proposicao_enviada',
             _('Pode acessar detalhes de uma proposição enviada.')),
            ('detail_proposicao_devolvida',
             _('Pode acessar detalhes de uma proposição devolvida.')),
            ('detail_proposicao_incorporada',
             _('Pode acessar detalhes de uma proposição incorporada.')),
        )

    def __str__(self):
        if self.ano and self.numero_proposicao:
            return '%s %s/%s' % (Proposicao._meta.verbose_name,
                                 self.numero_proposicao, self.ano)
        else:
            if len(self.descricao) < 30:
                descricao = self.descricao[:28] + ' ...'
            else:
                descricao = self.descricao

            return '%s %s/%s' % (Proposicao._meta.verbose_name, self.id,
                                 descricao)

    @property
    def epigrafe(self):
        return _('%(tipo)s nº %(numero)s de %(data)s') % {
            'tipo':
            self.tipo,
            'numero':
            self.numero_proposicao,
            'data':
            defaultfilters.date(
                self.data_envio if self.data_envio else timezone.now(),
                "d \d\e F \d\e Y")
        }

    def delete(self, using=None, keep_parents=False):
        texto_original = self.texto_original
        result = super().delete(using=using, keep_parents=keep_parents)

        if texto_original:
            texto_original.delete(save=False)

        return result

    def save(self,
             force_insert=False,
             force_update=False,
             using=None,
             update_fields=None):

        if not self.pk and self.texto_original:
            texto_original = self.texto_original
            self.texto_original = None
            models.Model.save(self,
                              force_insert=force_insert,
                              force_update=force_update,
                              using=using,
                              update_fields=update_fields)
            self.texto_original = texto_original

        return models.Model.save(self,
                                 force_insert=force_insert,
                                 force_update=force_update,
                                 using=using,
                                 update_fields=update_fields)
Beispiel #12
0
class MateriaLegislativa(models.Model):

    tipo = models.ForeignKey(
        TipoMateriaLegislativa,
        on_delete=models.PROTECT,
        verbose_name=TipoMateriaLegislativa._meta.verbose_name)
    numero = models.PositiveIntegerField(verbose_name=_('Número'))
    ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'),
                                           choices=RANGE_ANOS)
    numero_protocolo = models.PositiveIntegerField(
        blank=True, null=True, verbose_name=_('Número do Protocolo'))
    data_apresentacao = models.DateField(
        verbose_name=_('Data de Apresentação'))
    tipo_apresentacao = models.CharField(
        max_length=1,
        blank=True,
        verbose_name=_('Tipo de Apresentação'),
        choices=TIPO_APRESENTACAO_CHOICES)
    regime_tramitacao = models.ForeignKey(RegimeTramitacao,
                                          on_delete=models.PROTECT,
                                          verbose_name=_('Regime Tramitação'))
    data_publicacao = models.DateField(blank=True,
                                       null=True,
                                       verbose_name=_('Data de Publicação'))
    tipo_origem_externa = models.ForeignKey(
        TipoMateriaLegislativa,
        blank=True,
        null=True,
        related_name='tipo_origem_externa_set',
        on_delete=models.PROTECT,
        verbose_name=_('Tipo'))
    numero_origem_externa = models.CharField(max_length=10,
                                             blank=True,
                                             verbose_name=_('Número'))
    ano_origem_externa = models.PositiveSmallIntegerField(
        blank=True, null=True, verbose_name=_('Ano'), choices=RANGE_ANOS)
    data_origem_externa = models.DateField(blank=True,
                                           null=True,
                                           verbose_name=_('Data'))
    local_origem_externa = models.ForeignKey(Origem,
                                             blank=True,
                                             null=True,
                                             on_delete=models.PROTECT,
                                             verbose_name=_('Local de Origem'))
    apelido = models.CharField(max_length=50,
                               blank=True,
                               verbose_name=_('Apelido'))
    dias_prazo = models.PositiveIntegerField(blank=True,
                                             null=True,
                                             verbose_name=_('Dias Prazo'))
    data_fim_prazo = models.DateField(blank=True,
                                      null=True,
                                      verbose_name=_('Data Fim Prazo'))
    em_tramitacao = models.BooleanField(verbose_name=_('Em Tramitação?'),
                                        default=False,
                                        choices=YES_NO_CHOICES)
    polemica = models.NullBooleanField(blank=True,
                                       verbose_name=_('Matéria Polêmica?'))
    objeto = models.CharField(max_length=150,
                              blank=True,
                              verbose_name=_('Objeto'))
    complementar = models.NullBooleanField(blank=True,
                                           verbose_name=_('É Complementar?'))
    ementa = models.TextField(verbose_name=_('Ementa'))
    indexacao = models.TextField(blank=True, verbose_name=_('Indexação'))
    observacao = models.TextField(blank=True, verbose_name=_('Observação'))
    resultado = models.TextField(blank=True)
    # XXX novo
    anexadas = models.ManyToManyField('self',
                                      blank=True,
                                      through='Anexada',
                                      symmetrical=False,
                                      related_name='anexo_de',
                                      through_fields=('materia_principal',
                                                      'materia_anexada'))
    texto_original = models.FileField(
        max_length=300,
        blank=True,
        null=True,
        upload_to=materia_upload_path,
        verbose_name=_('Texto Original'),
        storage=OverwriteStorage(),
        validators=[restringe_tipos_de_arquivo_txt])

    texto_articulado = GenericRelation(TextoArticulado,
                                       related_query_name='texto_articulado')

    proposicao = GenericRelation('Proposicao', related_query_name='proposicao')

    autores = models.ManyToManyField(
        Autor,
        through='Autoria',
        through_fields=('materia', 'autor'),
        symmetrical=False,
    )

    data_ultima_atualizacao = models.DateTimeField(blank=True,
                                                   null=True,
                                                   auto_now=True,
                                                   verbose_name=_('Data'))

    user = models.ForeignKey(get_settings_auth_user_model(),
                             verbose_name=_('Usuário'),
                             on_delete=models.PROTECT,
                             null=True,
                             blank=True)
    ip = models.CharField(verbose_name=_('IP'),
                          max_length=60,
                          blank=True,
                          default='')
    ultima_edicao = models.DateTimeField(
        verbose_name=_('Data e Hora da Edição'), blank=True, null=True)

    class Meta:
        verbose_name = _('Matéria Legislativa')
        verbose_name_plural = _('Matérias Legislativas')
        unique_together = (("tipo", "numero", "ano"), )
        ordering = ['-id']
        permissions = (("can_access_impressos", "Can access impressos"), )

    def __str__(self):
        return _('%(tipo)s nº %(numero)s de %(ano)s') % {
            'tipo': self.tipo,
            'numero': self.numero,
            'ano': self.ano
        }

    @property
    def epigrafe(self):
        return _('%(tipo)s nº %(numero)s de %(data)s') % {
            'tipo': self.tipo,
            'numero': self.numero,
            'data': defaultfilters.date(self.data_apresentacao,
                                        "d \d\e F \d\e Y")
        }

    def data_entrada_protocolo(self):
        '''
           hack: recuperar a data de entrada do protocolo sem gerar
           dependência circular
        '''
        from sapl.protocoloadm.models import Protocolo
        if self.ano and self.numero_protocolo:
            protocolo = Protocolo.objects.filter(
                ano=self.ano, numero=self.numero_protocolo).first()
            if protocolo:
                if protocolo.timestamp:
                    return protocolo.timestamp.date()
                elif protocolo.timestamp_data_hora_manual:
                    return protocolo.timestamp_data_hora_manual.date()
                elif protocolo.data:
                    return protocolo.data

            return ''

    def delete(self, using=None, keep_parents=False):
        texto_original = self.texto_original
        result = super().delete(using=using, keep_parents=keep_parents)

        if texto_original:
            texto_original.delete(save=False)

        for p in self.proposicao.all():
            p.conteudo_gerado_related = None
            p.cancelado = True
            p.save()

        return result

    def save(self,
             force_insert=False,
             force_update=False,
             using=None,
             update_fields=None):

        if not self.pk and self.texto_original:
            texto_original = self.texto_original
            self.texto_original = None
            models.Model.save(self,
                              force_insert=force_insert,
                              force_update=force_update,
                              using=using,
                              update_fields=update_fields)
            self.texto_original = texto_original

        return models.Model.save(self,
                                 force_insert=force_insert,
                                 force_update=force_update,
                                 using=using,
                                 update_fields=update_fields)
Beispiel #13
0
class Tramitacao(models.Model):
    TURNO_CHOICES = Choices(
        ('P', 'primeiro', _('Primeiro')),
        ('S', 'segundo', _('Segundo')),
        ('U', 'unico', _('Único')),
        ('L', 'suplementar', _('Suplementar')),
        ('F', 'final', _('Final')),
        ('A', 'votacao_unica', _('Votação Única em Regime de Urgência')),
        ('B', 'primeira_votacao', _('1ª Votação')),
        ('C', 'segunda_terceira_votacao', _('2ª e 3ª Votações')),
        ('D', 'deliberacao', _('Deliberação')),
        ('G', 'primeria_segunda_votacoes', _('1ª e 2ª Votações')),
        ('E', 'primeira_segunda_votacao_urgencia',
         _('1ª e 2ª Votações em Regime de Urgência')),
    )

    status = models.ForeignKey(
        StatusTramitacao,
        on_delete=models.PROTECT,
        # TODO PÓS MIGRACAO INICIAL (vide #1381)
        # não nulo quando todas as
        # bases tiverem sido corrigidas
        null=True,
        verbose_name=_('Status'))
    materia = models.ForeignKey(MateriaLegislativa, on_delete=models.CASCADE)
    # TODO: Remover os campos de data
    # TODO: pois timestamp supre a necessidade
    timestamp = models.DateTimeField(default=timezone.now)
    data_tramitacao = models.DateField(verbose_name=_('Data Tramitação'))
    unidade_tramitacao_local = models.ForeignKey(
        UnidadeTramitacao,
        related_name='tramitacoes_origem',
        on_delete=models.PROTECT,
        verbose_name=_('Unidade Local'))
    data_encaminhamento = models.DateField(
        blank=True, null=True, verbose_name=_('Data Encaminhamento'))
    unidade_tramitacao_destino = models.ForeignKey(
        UnidadeTramitacao,
        # TODO PÓS MIGRACAO INICIAL (vide #1381)
        # não nulo quando todas as
        # bases tiverem sido corrigidas
        null=True,
        related_name='tramitacoes_destino',
        on_delete=models.PROTECT,
        verbose_name=_('Unidade Destino'))
    urgente = models.BooleanField(verbose_name=_('Urgente ?'),
                                  choices=YES_NO_CHOICES,
                                  default=False)
    tipo_turno = models.ForeignKey(TipoTurnoTramitacao,
                                   on_delete=models.PROTECT,
                                   blank=True,
                                   null=True,
                                   verbose_name=_('Turno'))
    texto = models.TextField(verbose_name=_('Texto da Ação'), blank=True)
    data_fim_prazo = models.DateField(blank=True,
                                      null=True,
                                      verbose_name=_('Data Fim Prazo'))
    user = models.ForeignKey(get_settings_auth_user_model(),
                             verbose_name=_('Usuário'),
                             on_delete=models.PROTECT,
                             null=True,
                             blank=True)
    ip = models.CharField(verbose_name=_('IP'),
                          max_length=60,
                          blank=True,
                          default='')
    ultima_edicao = models.DateTimeField(
        verbose_name=_('Data e Hora da Edição'), blank=True, null=True)

    class Meta:
        verbose_name = _('Tramitação')
        verbose_name_plural = _('Tramitações')

    def __str__(self):
        return _('%(materia)s | %(status)s | %(data)s') % {
            'materia': self.materia,
            'status': self.status,
            'data': self.data_tramitacao.strftime("%d/%m/%Y")
        }
Beispiel #14
0
class MateriaLegislativa(CommonMixin):

    objects = MateriaLegislativaManager()

    FIELDFILE_NAME = ('texto_original', )

    metadata = JSONField(verbose_name=_('Metadados'),
                         blank=True,
                         null=True,
                         default=None,
                         encoder=DjangoJSONEncoder)

    tipo = models.ForeignKey(
        TipoMateriaLegislativa,
        on_delete=models.PROTECT,
        verbose_name=TipoMateriaLegislativa._meta.verbose_name)
    numero = models.PositiveIntegerField(verbose_name=_('Número'))
    ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'),
                                           choices=RANGE_ANOS)
    numero_protocolo = models.PositiveIntegerField(
        blank=True, null=True, verbose_name=_('Número do Protocolo'))
    data_apresentacao = models.DateField(
        verbose_name=_('Data de Apresentação'))
    tipo_apresentacao = models.CharField(
        max_length=1,
        blank=True,
        verbose_name=_('Tipo de Apresentação'),
        choices=TIPO_APRESENTACAO_CHOICES)
    regime_tramitacao = models.ForeignKey(RegimeTramitacao,
                                          on_delete=models.PROTECT,
                                          verbose_name=_('Regime Tramitação'))
    data_publicacao = models.DateField(blank=True,
                                       null=True,
                                       verbose_name=_('Data de Publicação'))
    tipo_origem_externa = models.ForeignKey(
        TipoMateriaLegislativa,
        blank=True,
        null=True,
        related_name='tipo_origem_externa_set',
        on_delete=models.PROTECT,
        verbose_name=_('Tipo'))
    numero_origem_externa = models.CharField(max_length=10,
                                             blank=True,
                                             verbose_name=_('Número'))
    ano_origem_externa = models.PositiveSmallIntegerField(
        blank=True, null=True, verbose_name=_('Ano'), choices=RANGE_ANOS)
    data_origem_externa = models.DateField(blank=True,
                                           null=True,
                                           verbose_name=_('Data'))
    local_origem_externa = models.ForeignKey(Origem,
                                             blank=True,
                                             null=True,
                                             on_delete=models.PROTECT,
                                             verbose_name=_('Local de Origem'))
    apelido = models.CharField(max_length=50,
                               blank=True,
                               verbose_name=_('Apelido'))
    dias_prazo = models.PositiveIntegerField(blank=True,
                                             null=True,
                                             verbose_name=_('Dias Prazo'))
    data_fim_prazo = models.DateField(blank=True,
                                      null=True,
                                      verbose_name=_('Data Fim Prazo'))
    em_tramitacao = models.BooleanField(verbose_name=_('Em Tramitação?'),
                                        default=False,
                                        choices=YES_NO_CHOICES)
    polemica = models.NullBooleanField(blank=True,
                                       verbose_name=_('Matéria Polêmica?'))
    objeto = models.CharField(max_length=150,
                              blank=True,
                              verbose_name=_('Objeto'))
    complementar = models.NullBooleanField(blank=True,
                                           verbose_name=_('É Complementar?'))
    ementa = models.TextField(verbose_name=_('Ementa'))
    indexacao = models.TextField(blank=True, verbose_name=_('Indexação'))
    observacao = models.TextField(blank=True, verbose_name=_('Observação'))
    resultado = models.TextField(blank=True)
    # XXX novo
    anexadas = models.ManyToManyField('self',
                                      blank=True,
                                      through='Anexada',
                                      symmetrical=False,
                                      related_name='anexo_de',
                                      through_fields=('materia_principal',
                                                      'materia_anexada'))
    texto_original = PortalFileField(
        blank=True,
        null=True,
        upload_to=materia_upload_path,
        verbose_name=_('Texto Original'),
        storage=OverwriteStorage(),
        validators=[restringe_tipos_de_arquivo_txt],
        max_length=512)

    texto_articulado = GenericRelation(TextoArticulado,
                                       related_query_name='texto_articulado')

    proposicao = GenericRelation('Proposicao', related_query_name='proposicao')

    protocolo_gr = GenericRelation('protocoloadm.Protocolo',
                                   object_id_field='conteudo_object_id',
                                   content_type_field='conteudo_content_type',
                                   related_query_name='protocolo_gr')

    diariosoficiais = GenericRelation(VinculoDocDiarioOficial,
                                      related_query_name='diariosoficiais')

    autores = models.ManyToManyField(
        Autor,
        through='Autoria',
        through_fields=('materia', 'autor'),
        symmetrical=False,
    )

    data_ultima_atualizacao = models.DateTimeField(blank=True,
                                                   null=True,
                                                   auto_now=True,
                                                   verbose_name=_('Data'))

    user = models.ForeignKey(get_settings_auth_user_model(),
                             verbose_name=_('Usuário'),
                             on_delete=models.PROTECT,
                             null=True,
                             blank=True)
    ip = models.CharField(verbose_name=_('IP'),
                          max_length=30,
                          blank=True,
                          default='')

    arquivado = models.BooleanField(verbose_name=_('Arquivamento completo?'),
                                    default=False,
                                    choices=YES_NO_CHOICES)

    checkcheck = models.BooleanField(
        verbose_name=_('Processo Legislativo Auditado?'),
        default=False,
        choices=YES_NO_CHOICES)

    url_video = models.URLField(
        max_length=150,
        blank=True,
        verbose_name=_('URL Arquivo Vídeo (Formatos MP4 / FLV / WebM)'))

    _certidao = GenericRelation(CertidaoPublicacao,
                                related_query_name='materialegislativa_cert')

    _diario = GenericRelation(VinculoDocDiarioOficial,
                              related_query_name='materialegislativa_diario')

    class Meta:
        verbose_name = _('Matéria Legislativa')
        verbose_name_plural = _('Matérias Legislativas')
        unique_together = (("tipo", "numero", "ano"), )
        ordering = ['-id']
        permissions = (
            ("can_access_impressos", "Can access impressos"),
            ("can_check_complete", "Pode checar conclusão de processo"),
        )

    @property
    def __descr__(self):
        return str(self.ementa)

    @property
    def certidao(self):
        return self._certidao.all().first()

    @property
    def diariooficial(self):
        try:
            return self._diario.all().first().diario
        except:
            return None

    def __str__(self):
        return _('%(tipo)s nº %(numero)s de %(ano)s') % {
            'tipo': self.tipo,
            'numero': self.numero,
            'ano': self.ano
        }

    @property
    def is_signed(self):
        try:
            return self.metadata and self.metadata['signs'] and \
                self.metadata['signs']['texto_original'] and \
                self.metadata['signs']['texto_original']['signs']
        except:
            return False

    @property
    def epigrafe(self):
        return _('%(tipo)s nº %(numero)s de %(data)s') % {
            'tipo': self.tipo,
            'numero': self.numero,
            'data': defaultfilters.date(self.data_apresentacao,
                                        "d \d\e F \d\e Y")
        }

    @property
    def epigrafe_short(self):
        return '{} {:03d}/{}'.format(self.tipo.sigla, self.numero, self.ano)

    def data_entrada_protocolo(self):
        '''
           hack: recuperar a data de entrada do protocolo sem gerar
           dependência circular
        '''
        from sapl.protocoloadm.models import Protocolo
        if self.ano and self.numero_protocolo:
            protocolo = Protocolo.objects.filter(
                ano=self.ano, numero=self.numero_protocolo).first()
            if protocolo:
                if protocolo.timestamp:
                    return protocolo.timestamp.date()
                elif protocolo.timestamp_data_hora_manual:
                    return protocolo.timestamp_data_hora_manual.date()
                elif protocolo.data:
                    return protocolo.data

            return ''

    def delete(self, using=None, keep_parents=False):
        if self.texto_original:
            self.texto_original.delete()

        for p in self.proposicao.all():
            p.conteudo_gerado_related = None
            p.cancelado = True
            p.save()

        for p in self.protocolo_gr.all():
            p.conteudo_protocolado = None
            p.save()

        return models.Model.delete(self,
                                   using=using,
                                   keep_parents=keep_parents)

    def save(self,
             force_insert=False,
             force_update=False,
             using=None,
             update_fields=None):

        if not self.pk and self.texto_original:
            texto_original = self.texto_original
            self.texto_original = None
            models.Model.save(self,
                              force_insert=force_insert,
                              force_update=force_update,
                              using=using,
                              update_fields=update_fields)
            self.texto_original = texto_original

        return models.Model.save(self,
                                 force_insert=force_insert,
                                 force_update=force_update,
                                 using=using,
                                 update_fields=update_fields)

    def autografo(self):
        return self.normajuridica_set.filter(tipo_id=27).first()

    def normajuridica(self):
        return self.normajuridica_set.exclude(tipo_id=27).first()

    def autografovinculado_a_normajuridica(self):
        nr = self.normajuridica_set.exclude(
            tipo_id=27).first().norma_principal.filter(
                norma_relacionada__tipo_id=27).first()

        if nr:
            return nr.norma_relacionada
        return ''
Beispiel #15
0
class DocumentoAdministrativo(models.Model):
    tipo = models.ForeignKey(
        TipoDocumentoAdministrativo, on_delete=models.PROTECT,
        verbose_name=_('Tipo Documento'))
    numero = models.PositiveIntegerField(verbose_name=_('Número'))

    complemento = models.CharField(max_length=10, blank=True,
        verbose_name=_('Complemento'))

    ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'),
                                           choices=RANGE_ANOS)
    protocolo = models.ForeignKey(
        Protocolo,
        blank=True,
        null=True,
        on_delete=models.PROTECT,
        verbose_name=_('Protocolo'))
    data = models.DateField(verbose_name=_('Data'))

    interessado = models.CharField(
        max_length=50, blank=True, verbose_name=_('Interessado'))
    autor = models.ForeignKey(Autor, blank=True, null=True,
                              on_delete=models.PROTECT)
    dias_prazo = models.PositiveIntegerField(
        blank=True, null=True, verbose_name=_('Dias Prazo'))
    data_fim_prazo = models.DateField(
        blank=True, null=True, verbose_name=_('Data Fim Prazo'))
    tramitacao = models.BooleanField(
        verbose_name=_('Em Tramitação?'),
        choices=YES_NO_CHOICES,
        default=False)
    assunto = models.TextField(verbose_name=_('Assunto'))
    numero_externo = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name=_('Número Externo'))
    observacao = models.TextField(
        blank=True, verbose_name=_('Observação'))
    texto_integral = models.FileField(
        max_length=300,
        blank=True,
        null=True,
        storage=OverwriteStorage(),
        upload_to=texto_upload_path,
        verbose_name=_('Texto Integral'))
    restrito = models.BooleanField(default=False,
                                   verbose_name=_('Acesso Restrito'),
                                   blank=True)

    anexados = models.ManyToManyField(
        'self',
        blank=True,
        through='Anexado',
        symmetrical=False,
        related_name='anexo_de',
        through_fields=(
            'documento_principal',
            'documento_anexado'
        )
    )

    user = models.ForeignKey(
        get_settings_auth_user_model(),
        verbose_name=_('Usuário'),
        on_delete=models.PROTECT,
        null=True,
        blank=True
    )
    ip = models.CharField(
        verbose_name=_('IP'),
        max_length=30,
        blank=True,
        default=''
    )
    ultima_edicao = models.DateTimeField(
        verbose_name=_('Data e Hora da Edição'),
        blank=True, null=True
    )

    class Meta:
        verbose_name = _('Documento Administrativo')
        verbose_name_plural = _('Documentos Administrativos')

    def __str__(self):
        return _('%(tipo)s - %(assunto)s') % {
            'tipo': self.tipo, 'assunto': self.assunto
        }

    def delete(self, using=None, keep_parents=False):
        texto_integral = self.texto_integral
        result = super().delete(using=using, keep_parents=keep_parents)

        if texto_integral:
            texto_integral.delete(save=False)

        return result

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):

        if not self.pk and self.texto_integral:
            texto_integral = self.texto_integral
            self.texto_integral = None
            models.Model.save(self, force_insert=force_insert,
                              force_update=force_update,
                              using=using,
                              update_fields=update_fields)
            self.texto_integral = texto_integral

        return models.Model.save(self, force_insert=force_insert,
                                 force_update=force_update,
                                 using=using,
                                 update_fields=update_fields)
Beispiel #16
0
class NormaJuridica(CommonMixin):
    FIELDFILE_NAME = ('texto_integral', )

    ESFERA_FEDERACAO_CHOICES = Choices(
        ('M', 'municipal', _('Municipal')),
        ('E', 'estadual', _('Estadual')),
        ('F', 'federal', _('Federal')),
    )

    metadata = JSONField(
        verbose_name=_('Metadados'),
        blank=True, null=True, default=None, encoder=DjangoJSONEncoder)

    texto_integral = PortalFileField(
        blank=True,
        null=True,
        upload_to=norma_upload_path,
        verbose_name=_('Texto Integral'),
        storage=OverwriteStorage(),
        validators=[restringe_tipos_de_arquivo_txt],
        max_length=512)

    tipo = models.ForeignKey(
        TipoNormaJuridica,
        on_delete=models.PROTECT,
        verbose_name=_('Tipo da Norma Jurídica'))
    materia = models.ForeignKey(
        MateriaLegislativa, blank=True, null=True,
        on_delete=models.PROTECT, verbose_name=_('Matéria'))
    numero = models.CharField(
        max_length=8,
        verbose_name=_('Número'))
    ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'),
                                           choices=RANGE_ANOS)
    esfera_federacao = models.CharField(
        max_length=1,
        verbose_name=_('Esfera Federação'),
        choices=ESFERA_FEDERACAO_CHOICES)
    data = models.DateField(blank=False, null=True, verbose_name=_('Data'))
    data_publicacao = models.DateField(
        blank=True, null=True, verbose_name=_('Data de Publicação'))

    ementa = models.TextField(verbose_name=_('Ementa'))
    indexacao = models.TextField(
        blank=True, verbose_name=_('Indexação'))
    observacao = models.TextField(
        blank=True, verbose_name=_('Observação'))
    complemento = models.NullBooleanField(
        blank=True, verbose_name=_('Complementar ?'),
        choices=YES_NO_CHOICES)
    # XXX was a CharField (attention on migrate)
    assuntos = models.ManyToManyField(
        AssuntoNorma, blank=True,
        verbose_name=_('Assuntos'))
    data_vigencia = models.DateField(
        blank=True, null=True, verbose_name=_('Data Fim Vigência'))
    timestamp = models.DateTimeField(null=True)

    texto_articulado = GenericRelation(
        TextoArticulado, related_query_name='texto_articulado')

    diariosoficiais = GenericRelation(
        VinculoDocDiarioOficial,
        related_query_name='diariosoficiais')

    data_ultima_atualizacao = models.DateTimeField(
        blank=True, null=True,
        auto_now=True,
        verbose_name=_('Data'))

    autores = models.ManyToManyField(
        Autor,
        through='AutoriaNorma',
        through_fields=('norma', 'autor'),
        symmetrical=False)

    norma_de_destaque = models.BooleanField(verbose_name=_('Norma de Destaque ?'),
                                            choices=YES_NO_CHOICES,
                                            default=False)

    apelido = models.TextField(
        blank=True, verbose_name=_('Apelido'))

    user = models.ForeignKey(
        get_settings_auth_user_model(),
        verbose_name=_('Usuário'),
        on_delete=models.PROTECT,
        null=True,
        blank=True
    )
    ip = models.CharField(
        verbose_name=_('IP'),
        max_length=30,
        blank=True,
        default=''
    )

    checkcheck = models.BooleanField(
        verbose_name=_('Registro de Norma Jurídica Auditado?'),
        default=False,
        choices=YES_NO_CHOICES)

    _certidao = GenericRelation(
        CertidaoPublicacao, related_query_name='normajuridica_cert')

    _diario = GenericRelation(
        VinculoDocDiarioOficial, related_query_name='normajuridica_diario')

    class Meta:
        verbose_name = _('Norma Jurídica')
        verbose_name_plural = _('Normas Jurídicas')
        ordering = ['-data', '-numero']

    def get_normas_relacionadas(self):
        principais = NormaRelacionada.objects.filter(
            norma_principal=self.id).order_by('norma_principal__data',
                                              'norma_relacionada__data')
        relacionadas = NormaRelacionada.objects.filter(
            norma_relacionada=self.id).order_by('norma_principal__data',
                                                'norma_relacionada__data')
        return (principais, relacionadas)

    def get_anexos_norma_juridica(self):
        anexos = AnexoNormaJuridica.objects.filter(
            norma=self.id)
        return anexos

    @property
    def is_signed(self):
        try:
            return self.metadata and self.metadata['signs'] and \
                self.metadata['signs']['texto_integral'] and \
                self.metadata['signs']['texto_integral']['signs']
        except:
            return False

    @property
    def certidao(self):
        return self._certidao.all().first()

    @property
    def diariooficial(self):
        try:
            return self._diario.all().first().diario
        except:
            return None

    @property
    def __descr__(self):
        return self.ementa

    def __str__(self):
        return _('%(tipo)s nº %(numero)s de %(data)s') % {
            'tipo': self.tipo,
            'numero': self.numero,
            'data': defaultfilters.date(self.data, "d \d\e F \d\e Y")}

    @property
    def epigrafe(self):
        return _('%(tipo)s nº %(numero)s de %(data)s') % {
            'tipo': self.tipo,
            'numero': self.numero,
            'data': defaultfilters.date(self.data, "d \d\e F \d\e Y")}

    def delete(self, using=None, keep_parents=False):
        if self.texto_integral:
            self.texto_integral.delete()

        return models.Model.delete(
            self, using=using, keep_parents=keep_parents)

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):

        if not self.pk and self.texto_integral:
            texto_integral = self.texto_integral
            self.texto_integral = None
            models.Model.save(self, force_insert=force_insert,
                              force_update=force_update,
                              using=using,
                              update_fields=update_fields)
            self.texto_integral = texto_integral

        return models.Model.save(self, force_insert=force_insert,
                                 force_update=force_update,
                                 using=using,
                                 update_fields=update_fields)