Browse Source

Add opc de criar protoc na incorp de proposições

pull/752/head
LeandroRoberto 8 years ago
parent
commit
a30684f3ba
  1. 133
      sapl/base/apps.py
  2. 95
      sapl/base/models.py
  3. 102
      sapl/materia/forms.py
  4. 14
      sapl/materia/migrations/0054_auto_20161009_1222.py
  5. 20
      sapl/materia/migrations/0056_remove_tipo_proposicao.py
  6. 11
      sapl/materia/migrations/0057_auto_20161016_0156.py
  7. 23
      sapl/materia/views.py
  8. 14
      sapl/protocoloadm/migrations/0003_auto_20161009_1222.py
  9. 21
      sapl/protocoloadm/migrations/0004_auto_20161023_1444.py
  10. 1
      sapl/protocoloadm/models.py
  11. 9
      sapl/protocoloadm/urls.py
  12. 3
      sapl/relatorios/views.py

133
sapl/base/apps.py

@ -1,8 +1,137 @@
from django import apps
from builtins import LookupError
from django.apps import apps
from django.contrib.auth.management import _get_all_permissions
from django.core import exceptions
from django.db import router
from django.db.models.signals import pre_migrate, post_migrate
from django.db.utils import DEFAULT_DB_ALIAS
from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _
import django
def create_proxy_permissions(
app_config, verbosity=2, interactive=True,
using=DEFAULT_DB_ALIAS, **kwargs):
if not app_config.models_module:
return
# print(app_config)
try:
Permission = apps.get_model('auth', 'Permission')
except LookupError:
return
if not router.allow_migrate_model(using, Permission):
return
from django.contrib.contenttypes.models import ContentType
permission_name_max_length = Permission._meta.get_field('name').max_length
# This will hold the permissions we're looking for as
# (content_type, (codename, name))
searched_perms = list()
# The codenames and ctypes that should exist.
ctypes = set()
for klass in list(app_config.get_models()):
opts = klass._meta
permissions = (
("list_" + opts.model_name,
string_concat(
_('Visualizaçao da lista de'), ' ',
opts.verbose_name_plural)),
("detail_" + opts.model_name,
string_concat(
_('Visualização dos detalhes de'), ' ',
opts.verbose_name_plural)),
)
opts.permissions = tuple(
set(list(permissions) + list(opts.permissions)))
if opts.proxy:
# Force looking up the content types in the current database
# before creating foreign keys to them.
app_label, model = opts.app_label, opts.model_name
try:
ctype = ContentType.objects.db_manager(
using).get_by_natural_key(app_label, model)
except:
ctype = ContentType.objects.db_manager(
using).create(app_label=app_label, model=model)
else:
ctype = ContentType.objects.db_manager(using).get_for_model(klass)
ctypes.add(ctype)
for perm in _get_all_permissions(klass._meta, ctype):
searched_perms.append((ctype, perm))
class AppConfig(apps.AppConfig):
# Find all the Permissions that have a content_type for a model we're
# looking for. We don't need to check for codenames since we already have
# a list of the ones we're going to create.
all_perms = set(Permission.objects.using(using).filter(
content_type__in=ctypes,
).values_list(
"content_type", "codename"
))
perms = [
Permission(codename=codename, name=name, content_type=ct)
for ct, (codename, name) in searched_perms
if (ct.pk, codename) not in all_perms
]
# Validate the permissions before bulk_creation to avoid cryptic database
# error when the name is longer than 255 characters
for perm in perms:
if len(perm.name) > permission_name_max_length:
raise exceptions.ValidationError(
'The permission name %s of %s.%s '
'is longer than %s characters' % (
perm.name,
perm.content_type.app_label,
perm.content_type.model,
permission_name_max_length,
)
)
Permission.objects.using(using).bulk_create(perms)
if verbosity >= 2:
for perm in perms:
print("Adding permission '%s'" % perm)
def run_sql_organizers(
app_config, verbosity=2, interactive=True,
using=DEFAULT_DB_ALIAS, **kwargs):
"""with connection.cursor() as cursor:
for line in lines:
line = line.strip()
if not line or line.startswith('#'):
continue
try:
cursor.execute(line)"""
print('aqui run_sql_organizer', app_config)
""" update protocoloadm_protocolo set autor_id = null;
delete from materia_autoria;
delete from materia_proposicao;
delete from materia_tipoproposicao;
"""
class AppConfig(django.apps.AppConfig):
name = 'sapl.base'
label = 'base'
verbose_name = _('Dados Básicos')
def ready(self):
pre_migrate.connect(run_sql_organizers, self)
post_migrate.connect(
receiver=create_proxy_permissions,
dispatch_uid="django.contrib.auth.management.create_permissions")

95
sapl/base/models.py

@ -203,98 +203,3 @@ class Autor(models.Model):
return str(self.partido)
else:
"""
def create_proxy_permissions(
app_config, verbosity=2, interactive=True,
using=DEFAULT_DB_ALIAS, **kwargs):
if not app_config.models_module:
return
# print(app_config)
try:
Permission = apps.get_model('auth', 'Permission')
except LookupError:
return
if not router.allow_migrate_model(using, Permission):
return
from django.contrib.contenttypes.models import ContentType
permission_name_max_length = Permission._meta.get_field('name').max_length
# This will hold the permissions we're looking for as
# (content_type, (codename, name))
searched_perms = list()
# The codenames and ctypes that should exist.
ctypes = set()
for klass in list(app_config.get_models()):
opts = klass._meta
permissions = (
("list_" + opts.model_name,
string_concat(
_('Visualizaçao da lista de'), ' ',
opts.verbose_name_plural)),
("detail_" + opts.model_name,
string_concat(
_('Visualização dos detalhes de'), ' ',
opts.verbose_name_plural)),
)
opts.permissions = tuple(
set(list(permissions) + list(opts.permissions)))
if opts.proxy:
# Force looking up the content types in the current database
# before creating foreign keys to them.
app_label, model = opts.app_label, opts.model_name
try:
ctype = ContentType.objects.db_manager(
using).get_by_natural_key(app_label, model)
except:
ctype = ContentType.objects.db_manager(
using).create(app_label=app_label, model=model)
else:
ctype = ContentType.objects.db_manager(using).get_for_model(klass)
ctypes.add(ctype)
for perm in _get_all_permissions(klass._meta, ctype):
searched_perms.append((ctype, perm))
# Find all the Permissions that have a content_type for a model we're
# looking for. We don't need to check for codenames since we already have
# a list of the ones we're going to create.
all_perms = set(Permission.objects.using(using).filter(
content_type__in=ctypes,
).values_list(
"content_type", "codename"
))
perms = [
Permission(codename=codename, name=name, content_type=ct)
for ct, (codename, name) in searched_perms
if (ct.pk, codename) not in all_perms
]
# Validate the permissions before bulk_creation to avoid cryptic database
# error when the name is longer than 255 characters
for perm in perms:
if len(perm.name) > permission_name_max_length:
raise exceptions.ValidationError(
'The permission name %s of %s.%s '
'is longer than %s characters' % (
perm.name,
perm.content_type.app_label,
perm.content_type.model,
permission_name_max_length,
)
)
Permission.objects.using(using).bulk_create(perms)
if verbosity >= 2:
for perm in perms:
print("Adding permission '%s'" % perm)
models.signals.post_migrate.connect(
receiver=create_proxy_permissions,
dispatch_uid="django.contrib.auth.management.create_permissions")

102
sapl/materia/forms.py

@ -1,10 +1,9 @@
from datetime import datetime
from datetime import datetime, date
import os
from crispy_forms.bootstrap import Alert, InlineCheckboxes, FormActions,\
InlineRadios
import django_filters
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout, Row,\
Field, Submit
@ -12,11 +11,13 @@ from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.files.base import File
from django.core.urlresolvers import reverse
from django.db import models, transaction
from django.db.models import Max
from django.forms import ModelForm, widgets
from django.forms.forms import Form
from django.utils.translation import ugettext_lazy as _
import django_filters
from sapl.base.models import Autor
from sapl.comissoes.models import Comissao
@ -1172,6 +1173,13 @@ class ConfirmarProposicaoForm(ProposicaoForm):
self.instance.data_recebimento = None
self.instance.data_envio = None
self.instance.save()
self.instance.results = {
'messages': {
'success': [_('Devolução efetuada com sucesso.'), ]
},
'url': reverse('sapl.materia:receber-proposicao')
}
return self.instance
elif 'incorporar' in self.data:
@ -1194,7 +1202,12 @@ class ConfirmarProposicaoForm(ProposicaoForm):
deverá contar também com uma implementação particular aqui no código
abaixo.
"""
self.instance.results = {
'messages': {
'success': [_('Proposição incorporada com sucesso'), ]
},
'url': reverse('sapl.materia:receber-proposicao')
}
proposicao = self.instance
conteudo_gerado = None
@ -1220,6 +1233,10 @@ class ConfirmarProposicaoForm(ProposicaoForm):
materia.save()
conteudo_gerado = materia
self.instance.results['messages']['success'].append(_(
'Matéria Legislativa registrada com sucesso (%s)'
) % str(materia))
# autoria
autoria = Autoria()
autoria.autor = proposicao.autor
@ -1227,6 +1244,10 @@ class ConfirmarProposicaoForm(ProposicaoForm):
autoria.primeiro_autor = True
autoria.save()
self.instance.results['messages']['success'].append(_(
'Autoria registrada para (%s)'
) % str(autoria.autor))
# Matéria de vinlculo
if proposicao.materia_de_vinculo:
anexada = Anexada()
@ -1235,20 +1256,19 @@ class ConfirmarProposicaoForm(ProposicaoForm):
anexada.data_anexacao = datetime.now()
anexada.save()
self.instance.results['messages']['success'].append(_(
'Matéria anexada a (%s)'
) % str(anexada.materia_principal))
self.instance.results['url'] = reverse(
'sapl.materia:materialegislativa_detail',
kwargs={'pk': materia.pk})
elif self.instance.tipo.conteudo.model_class() == TipoDocumento:
# dados básicos
doc = DocumentoAcessorio()
doc.materia = proposicao.materia_de_vinculo
"""
FIXME Esta forma de registrar autoria é falha.
Dificilmente o usuário que possui perfil de Autor será o autor
de um Documento Acessório.
Solução pode passar pela parametrização em TipoProposicao que
possibilite abrir ou não espaço, dado o Tipo, para quem está
incorporando a proposição rediga o nome do Autor do Doc Acessório.
"""
doc.autor = str(proposicao.autor)
doc.tipo = proposicao.tipo.tipo_conteudo_related
@ -1266,6 +1286,14 @@ class ConfirmarProposicaoForm(ProposicaoForm):
doc.save()
conteudo_gerado = doc
self.instance.results['messages']['success'].append(_(
'Documento Acessório registrado com sucesso e anexado (%s)'
) % str(doc.materia))
self.instance.results['url'] = reverse(
'sapl.materia:documentoacessorio_detail',
kwargs={'pk': doc.pk})
proposicao.conteudo_gerado_related = conteudo_gerado
proposicao.save()
@ -1275,7 +1303,7 @@ class ConfirmarProposicaoForm(ProposicaoForm):
# ocorre se proposicao_incorporacao_obrigatoria == 'C' (condicional)
# and gerar_protocolo == False
if 'gerar_protocolo' in cd or not cd['gerar_protocolo']:
if 'gerar_protocolo' not in cd or cd['gerar_protocolo'] == 'False':
return self.instance
# resta a opção proposicao_incorporacao_obrigatoria == 'C'
@ -1291,8 +1319,50 @@ class ConfirmarProposicaoForm(ProposicaoForm):
GenericForeignKey
"""
# FIXME - Implementar protocolo
# protocolo = Protocolo()
# protocolo.ano =
numeracao = sapl.base.models.AppConfig.attr('sequencia_numeracao')
if numeracao == 'A':
nm = Protocolo.objects.filter(
ano=date.today().year).aggregate(Max('numero'))
elif numeracao == 'U':
nm = Protocolo.objects.all().aggregate(Max('numero'))
protocolo = Protocolo()
protocolo.numero = (nm['numero__max'] + 1) if nm['numero__max'] else 1
protocolo.ano = date.today().year
protocolo.data = date.today()
protocolo.hora = datetime.now().time()
# TODO transformar campo timestamp em auto_now_add
protocolo.timestamp = datetime.now()
protocolo.tipo_protocolo = '1'
# 1 Processo Legislativo
# 0 Processo Administrativo
protocolo.tipo_processo = '1'
protocolo.interessado = str(proposicao.autor)
protocolo.autor = proposicao.autor
protocolo.numero_paginas = cd['numero_de_paginas']
protocolo.anulado = False
if self.instance.tipo.conteudo.model_class() == TipoMateriaLegislativa:
protocolo.tipo_materia = proposicao.tipo.tipo_conteudo_related
elif self.instance.tipo.conteudo.model_class() == TipoDocumento:
protocolo.tipo_documento = proposicao.tipo.tipo_conteudo_related
protocolo.save()
self.instance.results['messages']['success'].append(_(
'Protocolo realizado com sucesso'))
# FIXME qdo protocoloadm estiver homologado, verifique a necessidade
# de redirecionamento para o protocolo.
"""
self.instance.results['url'] = reverse(
'sapl.protocoloadm:...',
kwargs={'pk': protocolo.pk})
"""
conteudo_gerado.numero_protocolo = protocolo.numero
conteudo_gerado.save()
return self.instance

14
sapl/materia/migrations/0054_auto_20161009_1222.py

@ -6,6 +6,13 @@ from django.db import migrations, models
import django.db.models.deletion
def clear_model_autoria(apps, schema_editor):
Autoria = apps.get_model("materia", "Autoria")
Autoria.objects.all().delete()
Proposicao = apps.get_model("materia", "Proposicao")
Proposicao.objects.all().delete()
class Migration(migrations.Migration):
dependencies = [
@ -14,6 +21,7 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RunPython(clear_model_autoria),
migrations.RemoveField(
model_name='autor',
name='comissao',
@ -37,12 +45,14 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='autoria',
name='autor',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='base.Autor', verbose_name='Autor'),
field=models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE, to='base.Autor', verbose_name='Autor'),
),
migrations.AlterField(
model_name='proposicao',
name='autor',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='base.Autor'),
field=models.ForeignKey(
blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='base.Autor'),
),
migrations.DeleteModel(
name='Autor',

20
sapl/materia/migrations/0056_remove_tipo_proposicao.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-10-11 19:45
from __future__ import unicode_literals
from django.db import migrations
def clear_model_tipo_proposicao(apps, schema_editor):
TipoProposicao = apps.get_model("materia", "TipoProposicao")
TipoProposicao.objects.all().delete()
class Migration(migrations.Migration):
dependencies = [
('materia', '0056_merge'),
]
operations = [
migrations.RunPython(clear_model_tipo_proposicao), ]

11
sapl/materia/migrations/0057_auto_20161016_0156.py

@ -6,14 +6,20 @@ from django.db import migrations, models
import django.db.models.deletion
def clear_model_tipo_proposicao(apps, schema_editor):
TipoProposicao = apps.get_model("materia", "TipoProposicao")
TipoProposicao.objects.all().delete()
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('materia', '0056_merge'),
('materia', '0056_remove_tipo_proposicao'),
]
operations = [
migrations.RunPython(clear_model_tipo_proposicao),
migrations.RemoveField(
model_name='tipoproposicao',
name='materia_ou_documento',
@ -33,6 +39,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='tipoproposicao',
name='conteudo',
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='Conteúdo'),
field=models.ForeignKey(
default=None, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='Conteúdo'),
),
]

23
sapl/materia/views.py

@ -306,9 +306,13 @@ class ConfirmarProposicao(PermissionRequiredForAppCrudMixin, UpdateView):
# FIXME redirecionamento trival,
# ainda por implementar se será para protocolo ou para doc resultante
messages.success(self.request, _('Devolução efetuada com sucesso.'))
msgs = self.object.results['messages']
return reverse('sapl.materia:receber-proposicao')
for key, value in msgs.items():
for item in value:
getattr(messages, key)(self.request, item)
return self.object.results['url']
def get_object(self, queryset=None):
try:
@ -580,6 +584,21 @@ class ReciboProposicaoView(TemplateView):
self.kwargs['pk'])})
return context
def get(self, request, *args, **kwargs):
proposicao = Proposicao.objects.get(pk=self.kwargs['pk'])
if proposicao.data_envio:
return TemplateView.get(self, request, *args, **kwargs)
if not proposicao.data_envio and not proposicao.data_devolucao:
messages.error(request, _('Não é possível gerar recebo para uma '
'Proposição ainda não enviada.'))
elif proposicao.data_devolucao:
messages.error(request, _('Não é possível gerar recibo.'))
return redirect(reverse('sapl.materia:proposicao_detail',
kwargs={'pk': proposicao.pk}))
class RelatoriaCrud(MasterDetailCrud):
model = Relatoria

14
sapl/protocoloadm/migrations/0003_auto_20161009_1222.py

@ -6,6 +6,13 @@ from django.db import migrations, models
import django.db.models.deletion
def clear_field_autor_in_protocolo(apps, schema_editor):
Protocolo = apps.get_model("protocoloadm", "Protocolo")
for p in Protocolo.objects.all():
p.autor = None
p.save()
class Migration(migrations.Migration):
dependencies = [
@ -13,14 +20,17 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RunPython(clear_field_autor_in_protocolo),
migrations.AlterField(
model_name='documentoadministrativo',
name='autor',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='base.Autor'),
field=models.ForeignKey(
blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='base.Autor'),
),
migrations.AlterField(
model_name='protocolo',
name='autor',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='base.Autor'),
field=models.ForeignKey(
blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='base.Autor'),
),
]

21
sapl/protocoloadm/migrations/0004_auto_20161023_1444.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-10-23 14:44
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('protocoloadm', '0003_auto_20161009_1222'),
]
operations = [
migrations.AlterField(
model_name='tramitacaoadministrativo',
name='unidade_tramitacao_destino',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='adm_tramitacoes_destino', to='materia.UnidadeTramitacao', verbose_name='Unidade Destino'),
),
]

1
sapl/protocoloadm/models.py

@ -120,6 +120,7 @@ class Protocolo(models.Model):
verbose_name=_('Ano do Protocolo'))
data = models.DateField()
hora = models.TimeField()
# TODO transformar campo timestamp em auto_now_add
timestamp = models.DateTimeField()
tipo_protocolo = models.PositiveIntegerField(
verbose_name=_('Tipo de Protocolo'))

9
sapl/protocoloadm/urls.py

@ -50,14 +50,19 @@ urlpatterns_protocolo = [
ProtocoloPesquisaView.as_view(), name='protocolo'),
url(r'^protocoloadm/protocolo-list$',
ProtocoloListView.as_view(), name='protocolo_list'),
url(r'^protocoloadm/(?P<pk>\d+)/(?P<ano>\d+)/protocolo-mostrar$',
ProtocoloMostrarView.as_view(), name='protocolo_mostrar'),
url(r'^protocoloadm/anular-protocolo',
AnularProtocoloAdmView.as_view(), name='anular_protocolo'),
url(r'^protocoloadm/protocolar-doc',
ProtocoloDocumentoView.as_view(), name='protocolar_doc'),
url(r'^protocoloadm/protocolar-mat',
ProtocoloMateriaView.as_view(), name='protocolar_mat'),
# FIXME estas urls com pk e ano não fazem sentido
# se vai buscar por pk não precisa de nenhuma outra informação
# mas veja, apesar de chamar de pk aqui nas urls
# usou-se dentro da view como paramentro para ano.
url(r'^protocoloadm/(?P<pk>\d+)/(?P<ano>\d+)/protocolo-mostrar$',
ProtocoloMostrarView.as_view(), name='protocolo_mostrar'),
url(r'^protocoloadm/(?P<pk>\d+)/(?P<ano>\d+)/comprovante$',
ComprovanteProtocoloView.as_view(), name='comprovante_protocolo'),
url(r'^protocoloadm/(?P<pk>\d+)/(?P<ano>\d+)/criar-documento$',

3
sapl/relatorios/views.py

@ -1,7 +1,6 @@
from datetime import datetime
from bs4 import BeautifulSoup
from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404, HttpResponse
from django.utils.translation import ugettext_lazy as _
@ -20,6 +19,7 @@ from sapl.sessao.models import (ExpedienteMateria, ExpedienteSessao, Orador,
SessaoPlenariaPresenca, TipoExpediente)
from sapl.settings import STATIC_ROOT
from sapl.utils import UF
import sapl
from .templates import (pdf_capa_processo_gerar,
pdf_documento_administrativo_gerar, pdf_espelho_gerar,
@ -27,6 +27,7 @@ from .templates import (pdf_capa_processo_gerar,
pdf_ordem_dia_gerar, pdf_pauta_sessao_gerar,
pdf_protocolo_gerar, pdf_sessao_plenaria_gerar)
uf_dic = dict(UF)

Loading…
Cancel
Save