From 52806f96d84a6207c829251cfd2c47da783f2880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Cantu=C3=A1ria?= Date: Mon, 13 May 2019 09:40:42 -0300 Subject: [PATCH] Adiciona script para remover multiplos parlamentares (#2713) Co-authored-by: Edward Ribeiro --- sapl/parlamentares/forms.py | 15 +++++ scripts/deduplica_parlamentares.py | 105 +++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 scripts/deduplica_parlamentares.py diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 90d6e150c..2003a4679 100755 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -243,6 +243,21 @@ class ParlamentarCreateForm(ParlamentarForm): attrs={'id': 'texto-rico'}) } + def clean(self): + super().clean() + + if not self.is_valid(): + return self.cleaned_data + + cleaned_data = self.cleaned_data + parlamentar = Parlamentar.objects.filter(nome_parlamentar=cleaned_data['nome_parlamentar']).exists() + + if parlamentar: + self.logger.error('Parlamentar já cadastrado.') + raise ValidationError('Parlamentar já cadastrado.') + + return cleaned_data + @transaction.atomic def save(self, commit=True): parlamentar = super(ParlamentarCreateForm, self).save(commit) diff --git a/scripts/deduplica_parlamentares.py b/scripts/deduplica_parlamentares.py new file mode 100644 index 000000000..8432b4302 --- /dev/null +++ b/scripts/deduplica_parlamentares.py @@ -0,0 +1,105 @@ +from django.db.models import Count + +from sapl.base.models import Autor +from sapl.comissoes.models import Participacao +from sapl.materia.models import Relatoria, UnidadeTramitacao, Autoria, Proposicao +from sapl.norma.models import AutoriaNorma +from sapl.parlamentares.models import Parlamentar, ComposicaoMesa, Dependente, Filiacao, Mandato, Frente, Votante +from sapl.protocoloadm.models import Protocolo, DocumentoAdministrativo +from sapl.sessao.models import IntegranteMesa, JustificativaAusencia, OradorExpediente, PresencaOrdemDia, \ + RetiradaPauta, SessaoPlenariaPresenca, VotoParlamentar, OradorOrdemDia + + +models = [ComposicaoMesa, Dependente, Filiacao, IntegranteMesa, JustificativaAusencia, Mandato, OradorOrdemDia, + OradorExpediente, Participacao, PresencaOrdemDia, Relatoria, RetiradaPauta, SessaoPlenariaPresenca, + UnidadeTramitacao, VotoParlamentar, Votante] + +# Tratar FRENTE pois ela é 1-to-many (campo parlamentares) com Parlamentar + +models_autor = [AutoriaNorma, Autoria, Proposicao, Protocolo, DocumentoAdministrativo] + +## Verificar se TipoAutor é sempre 1 para parlamentar e ContentType é sempre 26 para parlamentar. +TIPO_PARLAMENTAR = 1 +CONTENT_TYPE_PARLAMENTAR = 26 + + +def recupera_parlamentares(): + return [[parlamentar for parlamentar in Parlamentar.objects.filter(nome_parlamentar=nome_parlamentar).order_by('id')] + for nome_parlamentar in Parlamentar.objects.values_list('nome_parlamentar', flat=True) + .annotate(qntd=Count('nome_parlamentar')).filter(qntd__gt=1)] + + +def deduplica_parlamentares(parlamentares): + for parlamentar in parlamentares: + parlamentar_principal = parlamentar[0] + print('Corrigindo parlamentar {}'.format(parlamentar_principal)) + for clone in parlamentar[1:]: + if parlamentar_principal.biografia and clone.biografia: + parlamentar_principal.biografia += f'\n\n------------------------\n\n{clone.biografia}' + parlamentar_principal.save() + elif clone.biografia: + parlamentar_principal.biografia = clone.biografia + + autor_principal = Autor.objects.filter(tipo_id=TIPO_PARLAMENTAR, + content_type_id=CONTENT_TYPE_PARLAMENTAR, + object_id=parlamentar_principal.id) + + for a in Autor.objects.filter(tipo_id=TIPO_PARLAMENTAR, content_type_id=CONTENT_TYPE_PARLAMENTAR, object_id=clone.id): + print(a) + if not autor_principal: + print('Ajustando autor de %s' % parlamentar) + a.object_id = parlamentar_principal.id + a.save() + else: + print('Movendo referencias de autor') + for ma in models_autor: + for ra in ma.objects.filter(autor=a): + ra.autor = autor_principal[0] + ra.save() + a.delete() + + # Muda apontamento de models que referenciam parlamentar + for model in models: + for obj in model.objects.filter(parlamentar_id=clone.id): + obj.parlamentar = parlamentar_principal + obj.save() + + frentes = Frente.objects.filter(parlamentares=parlamentar_principal) + for frente in Frente.objects.select_related.filter(parlamentares=clone): + if frente not in frentes: + frente.parlamentares.add(parlamentar_principal) + + frente.parlamentares.remove(clone) + + clone.delete() + + +def estatisticas(parlamentares): + stats = [] + for ps in parlamentares: + for p in ps: + d = { + 'id': p.id, + 'nome': p.nome_parlamentar, + 'stats': {m.__name__: m.objects.filter(parlamentar=p).count() for m in models} + } + for m in models_autor: + d['stats'].update({m.__name__:m.objects.filter(autor__object_id=p.id, + autor__content_type=CONTENT_TYPE_PARLAMENTAR, + autor__tipo_id=TIPO_PARLAMENTAR).count()}) + stats.append(d) + for s in stats: + print('---------------------------------------------------') + print(s['id'], s['nome']) + print(s['stats']) + + +def main(): + parlamentares = recupera_parlamentares() + estatisticas(parlamentares) + deduplica_parlamentares(parlamentares) + estatisticas(parlamentares) + + +if __name__ == '__main__': + main()