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))
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 }
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)
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 }
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))
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 '?'
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)
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:
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
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)
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)
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)
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") }
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 ''
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)
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)