Browse Source

Fix #2877 - Possibilidade de múltiplos usuários por autor

pull/2962/head
Cesar Carvalho 6 years ago
parent
commit
17249954aa
  1. 65
      sapl/base/forms.py
  2. 35
      sapl/base/migrations/0039_auto_20190910_1109.py
  3. 24
      sapl/base/migrations/0040_auto_20190910_1113.py
  4. 25
      sapl/base/models.py
  5. 5
      sapl/base/urls.py
  6. 36
      sapl/base/views.py
  7. 1
      sapl/rules/map_rules.py
  8. 2
      sapl/templates/base.html
  9. 41
      sapl/templates/base/autor_detail.html
  10. 13
      sapl/templates/base/autoruser_form.html
  11. 7
      sapl/templates/base/layouts.yaml

65
sapl/base/forms.py

@ -10,10 +10,10 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm, from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm,
SetPasswordForm) SetPasswordForm)
from django.contrib.auth.models import Group, User from django.contrib.auth.models import Group, User
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.db import models, transaction from django.db import models, transaction
from django.db.models import Q from django.db.models import Q
from django.forms import Form, ModelForm from django.forms import Form, ModelForm, widgets
from django.utils import timezone from django.utils import timezone
from django.utils.translation import string_concat from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -38,7 +38,7 @@ from sapl.utils import (autor_label, autor_modal, ChoiceWithoutValidationField,
ImageThumbnailFileInput, models_with_gr_for_model, ImageThumbnailFileInput, models_with_gr_for_model,
qs_override_django_filter, RangeWidgetOverride, qs_override_django_filter, RangeWidgetOverride,
RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter) RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter)
from .models import AppConfig, CasaLegislativa from .models import AppConfig, CasaLegislativa, AutorUser
from operator import xor from operator import xor
@ -1883,3 +1883,62 @@ class RelatorioNormasPorAutorFilterSet(django_filters.FilterSet):
row3, row3,
form_actions(label='Pesquisar')) form_actions(label='Pesquisar'))
) )
class AutorUserForm(ModelForm):
username = forms.CharField(label=get_user_model()._meta.get_field(
get_user_model().USERNAME_FIELD).verbose_name.capitalize(),
required=True,
max_length=50)
nome_autor = forms.CharField(
label='Autor',
widget=widgets.TextInput(attrs={'readonly': 'readonly'})
)
class Meta:
model = AutorUser
exclude = ['user']
widgets = {
'autor': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
row1 = to_row(
[('nome_autor', 6),('username', 6),])
row2 = to_row(
[('autor', 6)]
)
actions = [HTML('<a href="{{ view.cancel_url }}"'
' class="btn btn-dark">Cancelar</a>')]
self.helper = SaplFormHelper()
self.helper.layout = Layout(
Fieldset(_('Vincular Usuário ao Autor'),
row1, row2,
HTML("&nbsp;"),
form_actions(more=actions)
)
)
def clean(self):
cd = super().clean()
if not self.is_valid():
return cd
username = cd['username']
try:
user = User.objects.get(username=username)
except ObjectDoesNotExist as e:
raise ValidationError("Este usuário não existe.")
if AutorUser.objects.filter(user=user).exists():
raise ValidationError("Este usuário ({}) já está vinculado a um Autor ({}).".format(
username, AutorUser.objects.get(user=user).autor))

35
sapl/base/migrations/0039_auto_20190910_1109.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-09-10 14:09
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('base', '0038_auto_20190604_1109'),
]
operations = [
migrations.CreateModel(
name='AutorUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('autor', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='base.Autor', verbose_name='Autor')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Usuário')),
],
options={
'verbose_name': 'Autor - Usuário',
'verbose_name_plural': 'Autores - Usuários',
'ordering': ('autor__nome',),
},
),
migrations.AlterUniqueTogether(
name='autoruser',
unique_together=set([('autor', 'user')]),
),
]

24
sapl/base/migrations/0040_auto_20190910_1113.py

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-09-10 14:13
from __future__ import unicode_literals
from django.db import migrations
from sapl.utils import get_settings_auth_user_model
def migra_autores_usuarios(apps, schema_editor):
Autor = apps.get_model('base', 'Autor')
AutorUser = apps.get_model('base', 'AutorUser')
for a in Autor.objects.filter(user__isnull=False):
AutorUser.objects.create(autor=a, user=a.user)
class Migration(migrations.Migration):
dependencies = [
('base', '0039_auto_20190910_1109'),
]
operations = [
migrations.RunPython(migra_autores_usuarios)
]

25
sapl/base/models.py

@ -229,7 +229,7 @@ class Autor(models.Model):
nome = models.CharField( nome = models.CharField(
max_length=120, blank=True, verbose_name=_('Nome do Autor')) max_length=120, blank=True, verbose_name=_('Nome do Autor'))
cargo = models.CharField(max_length=50, blank=True) cargo = models.CharField(max_length=50, blank=True, verbose_name=_('Cargo'))
class Meta: class Meta:
verbose_name = _('Autor') verbose_name = _('Autor')
@ -249,3 +249,26 @@ class Autor(models.Model):
if self.user: if self.user:
return str(self.user.username) return str(self.user.username)
return '?' return '?'
@reversion.register()
class AutorUser(models.Model):
autor = models.ForeignKey(
Autor,
verbose_name=_('Autor'),
on_delete=models.PROTECT
)
user = models.ForeignKey(
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')
unique_together = (('autor', 'user'), )
ordering = ('autor__nome',)
def __str__(self):
return str(self.autor) + ' - ' + str(self.user)

5
sapl/base/urls.py

@ -39,7 +39,7 @@ from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud,
ListarLegislaturaInfindavelView, ListarAnexadasCiclicasView, ListarLegislaturaInfindavelView, ListarAnexadasCiclicasView,
ListarAnexadosCiclicosView, pesquisa_textual, ListarAnexadosCiclicosView, pesquisa_textual,
RelatorioHistoricoTramitacaoAdmView, RelatorioDocumentosAcessoriosView, RelatorioHistoricoTramitacaoAdmView, RelatorioDocumentosAcessoriosView,
RelatorioNormasPorAutorView) RelatorioNormasPorAutorView, AutorUserCrud, AutorUserFormView)
app_name = AppConfig.name app_name = AppConfig.name
@ -233,5 +233,8 @@ urlpatterns = [
url(r'^(sapl/)?sapl_documentos/props_sapl/logo_casa', url(r'^(sapl/)?sapl_documentos/props_sapl/logo_casa',
LogotipoView.as_view(), name='logotipo'), LogotipoView.as_view(), name='logotipo'),
url(r'^sistema/autor/(?P<autor_pk>\d+)/vincular-usuario/create$',
AutorUserFormView.as_view(), name='vincular-usuario-autor'),
] + recuperar_senha + alterar_senha + admin_user + channels_url ] + recuperar_senha + alterar_senha + admin_user + channels_url

36
sapl/base/views.py

@ -76,8 +76,8 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm,
EstatisticasAcessoNormasForm, UsuarioFilterSet, EstatisticasAcessoNormasForm, UsuarioFilterSet,
RelatorioHistoricoTramitacaoAdmFilterSet, RelatorioHistoricoTramitacaoAdmFilterSet,
RelatorioDocumentosAcessoriosFilterSet, RelatorioDocumentosAcessoriosFilterSet,
RelatorioNormasPorAutorFilterSet) RelatorioNormasPorAutorFilterSet, AutorUserForm)
from .models import AppConfig, CasaLegislativa from .models import AppConfig, CasaLegislativa, AutorUser
def chanel_index(request): def chanel_index(request):
@ -116,6 +116,9 @@ def get_casalegislativa():
return CasaLegislativa.objects.first() return CasaLegislativa.objects.first()
AutorUserCrud = CrudAux.build(AutorUser, 'autor_user')
class ConfirmarEmailView(TemplateView): class ConfirmarEmailView(TemplateView):
template_name = "email/confirma.html" template_name = "email/confirma.html"
@ -326,6 +329,13 @@ class AutorCrud(CrudAux):
return url_reverse return url_reverse
class DetailView(CrudAux.DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['autor_user'] = AutorUser.objects.filter(autor=context['object'])
return context
class RelatoriosListView(TemplateView): class RelatoriosListView(TemplateView):
template_name = 'base/relatorios_list.html' template_name = 'base/relatorios_list.html'
@ -2266,3 +2276,25 @@ class RelatorioNormasPorAutorView(RelatorioMixin, FilterView):
' - ' + self.request.GET['data_1']) ' - ' + self.request.GET['data_1'])
return context return context
class AutorUserFormView(FormView):
form_class = AutorUserForm
template_name = 'base/autoruser_form.html'
success_url = '/'
def get_initial(self):
initial = super().get_initial()
autor_pk = self.kwargs['autor_pk']
autor = Autor.objects.get(id=autor_pk)
initial['nome_autor'] = autor.nome
initial['autor'] = autor
return initial
def form_valid(self, form):
super().form_valid(form)
@property
def cancel_url(self):
return reverse('sapl.base:autor_detail',
kwargs={'pk': self.kwargs['autor_pk']})

1
sapl/rules/map_rules.py

@ -234,6 +234,7 @@ rules_group_geral = {
[RP_ADD], __perms_publicas__), [RP_ADD], __perms_publicas__),
(base.TipoAutor, __base__, __perms_publicas__), (base.TipoAutor, __base__, __perms_publicas__),
(base.Autor, __base__, __perms_publicas__), (base.Autor, __base__, __perms_publicas__),
(base.AutorUser, __base__, __perms_publicas__),
(protocoloadm.StatusTramitacaoAdministrativo, __base__, set()), (protocoloadm.StatusTramitacaoAdministrativo, __base__, set()),
(protocoloadm.TipoDocumentoAdministrativo, __base__, set()), (protocoloadm.TipoDocumentoAdministrativo, __base__, set()),

2
sapl/templates/base.html

@ -63,7 +63,7 @@
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img height="30" width="30" src="{% webpack_static 'img/authenticated.png' %}"><span class="caret"></span></a> <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img height="30" width="30" src="{% webpack_static 'img/authenticated.png' %}"><span class="caret"></span></a>
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li class="dropdown-item"><a>{{user.username}}</a></li> <li class="dropdown-item"><a>{{user.username}} {% if user.autor %} ({{user.autor}}) {% endif %}</a></li>
{% if 'parlamentares.can_vote' in request.user.get_all_permissions %} {% if 'parlamentares.can_vote' in request.user.get_all_permissions %}
<li class="dropdown-item"><a href="" onclick="window.open('{% url 'sapl.painel:voto_individual' %}','Voto Individual','width=1000, height=800, scrollbars=yes')";> <li class="dropdown-item"><a href="" onclick="window.open('{% url 'sapl.painel:voto_individual' %}','Voto Individual','width=1000, height=800, scrollbars=yes')";>
Votar Matéria Votar Matéria

41
sapl/templates/base/autor_detail.html

@ -0,0 +1,41 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% block sub_actions %}
{{block.super}}
<div class="actions btn-group btn-group-sm" role="group">
<a href="{% url 'sapl.base:vincular-usuario-autor' object.pk %}" class="btn btn-outline-primary">Vincular Usuário</a>
</div>
{% endblock sub_actions %}
{% block detail_content %}
{{block.super}}
{% if autor_user %}
<h2 class="legend">Usuários vinculados</h2>
<table class="table table-striped table-hover table-link-ordering">
<thead>
<tr>
<th>Usuário</th>
</tr>
</thead>
<tbody>
{% for au in autor_user %}
<tr>
<td><a href="{% url 'sapl.base:user_edit' au.user.pk %}">{{au.user}}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endblock %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function(){
});
</script>
{% endblock %}

13
sapl/templates/base/autoruser_form.html

@ -0,0 +1,13 @@
{% extends "crud/form.html" %}
{% load i18n %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function(){
});
</script>
{% endblock %}

7
sapl/templates/base/layouts.yaml

@ -43,9 +43,12 @@ TipoAutor:
Autor: Autor:
{% trans 'Autor' %}: {% trans 'Autor' %}:
- tipo:3 nome - tipo:4 nome:4 cargo:4
- cargo
AutorCreate: AutorCreate:
{% trans 'Cadastro de Usuários Autores' %}: {% trans 'Cadastro de Usuários Autores' %}:
- tipo:3 search_autor - tipo:3 search_autor
AutorUser:
{% trans 'Autor - Usuário' %}:
- autor:6 user:6
Loading…
Cancel
Save