diff --git a/compilacao/forms.py b/compilacao/forms.py index 3d81a1622..8b52a4d81 100644 --- a/compilacao/forms.py +++ b/compilacao/forms.py @@ -1,12 +1,16 @@ +from datetime import datetime + from crispy_forms.bootstrap import FieldWithButtons, FormActions, StrictButton,\ InlineRadios, Alert from crispy_forms.helper import FormHelper from crispy_forms.layout import (HTML, Button, Column, Div, Field, Fieldset, Layout, Row) from django import forms -from django.core.exceptions import NON_FIELD_ERRORS +from django.core.exceptions import NON_FIELD_ERRORS, ValidationError +from django.forms.forms import Form from django.forms.models import ModelForm from django.template import defaultfilters +from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ from compilacao.models import (NOTAS_PUBLICIDADE_CHOICES, @@ -599,13 +603,78 @@ class DispositivoEdicaoBasicaForm(ModelForm): super(DispositivoEdicaoBasicaForm, self).__init__(*args, **kwargs) -FIELD_NAME_MAPPING = { - 'dispositivo_vigencia': 'dispositivo_ref', -} +class DispositivoSearchModalForm(Form): + + tipo_ta = forms.ModelChoiceField( + label=_('Tipo do Texto Articulado'), + queryset=TipoTextoArticulado.objects.all(), + required=False) + + tipo_model = forms.ChoiceField( + choices=[], + label=_('Tipos de...'), required=False) + + num_ta = forms.IntegerField( + label=_('Número do Documento'), required=False) + ano_ta = forms.IntegerField( + label=_('Ano do Documento'), required=False) + + dispositivos_internos = forms.ChoiceField( + label=_('Incluir Dispositivos Internos?'), + choices=utils.YES_NO_CHOICES, + widget=forms.RadioSelect(), + required=False) + + rotulo_dispositivo = forms.CharField( + label=_('Rótulo'), + required=False) + + texto_dispositivo = forms.CharField( + label=_('Pesquisa Textual'), + required=False) + + def __init__(self, *args, **kwargs): + + fields_search = Fieldset( + _('Busca por um Dispositivo'), + Row( + to_column(('num_ta', 4)), + to_column(('ano_ta', 4)), + to_column((InlineRadios('dispositivos_internos'), 4))), + Row( + to_column(('tipo_ta', 6)), + to_column(('tipo_model', 6))), + Row(to_column(('rotulo_dispositivo', 3)), + to_column((FieldWithButtons( + Field( + 'texto_dispositivo', + placeholder=_('Digite palavras, letras, ' + 'números ou algo' + ' que estejam no texto.')), + StrictButton(_('Buscar'), css_class='btn-busca')), 9))) + ) -class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): + self.helper = FormHelper() + self.helper.layout = Layout( + fields_search, + Row(to_column((Div(css_class='result-busca-dispositivo'), 12)))) + if 'choice_model_type_foreignkey_in_extenal_views' in kwargs: + ch = kwargs.pop('choice_model_type_foreignkey_in_extenal_views') + if 'data' in kwargs: + choice = ch(kwargs['data']['tipo_ta']) + self.base_fields['tipo_model'].choices = choice + elif 'instance' in kwargs and\ + isinstance(kwargs['instance'], Dispositivo): + choice = ch(kwargs['instance'].ta.tipo_ta_id) + self.base_fields['tipo_model'].choices = choice + + kwargs['initial'].update({'dispositivos_internos': False}) + super(DispositivoSearchModalForm, self).__init__(*args, **kwargs) + + +class DispositivoEdicaoVigenciaForm(ModelForm): inconstitucionalidade = forms.ChoiceField( label=Dispositivo._meta.get_field( 'inconstitucionalidade').verbose_name, @@ -613,9 +682,18 @@ class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): widget=forms.RadioSelect()) dispositivo_vigencia = forms.ModelChoiceField( + label=Dispositivo._meta.get_field( + 'dispositivo_vigencia').verbose_name, required=False, - queryset=Dispositivo.objects.all(), - widget=forms.HiddenInput()) + queryset=Dispositivo.objects.all()) + + extensao = forms.ChoiceField( + label=_('Extender a seleção abaixo como Dispositivo de Vigência ' + 'para todos dependentes originais ' + 'deste Dispositivo em edição?'), + choices=utils.YES_NO_CHOICES, + widget=forms.RadioSelect(), + required=False) class Meta: model = Dispositivo @@ -628,11 +706,6 @@ class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): 'dispositivo_vigencia' ] - def add_prefix(self, field_name): - # look up field name; return original if not found - field_name = FIELD_NAME_MAPPING.get(field_name, field_name) - return super(DispositivoEdicaoVigenciaForm, self).add_prefix(field_name) - def __init__(self, *args, **kwargs): layout = [] @@ -646,7 +719,6 @@ class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): content='%s %s' % ( _('Dica!'), _('Inclua uma Nota de Dispositivo informando ' 'sobre a Inconstitucionalidade.')))) - layout.append( Fieldset(_('Registro de Publicação e Validade'), row_publicacao, @@ -657,24 +729,28 @@ class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): ('fim_vigencia', 3), ('inicio_eficacia', 3), ('fim_eficacia', 3), ]) - layout.append( Fieldset(_('Datas de Controle de Vigência'), row_datas, css_class="col-md-12")) + row_vigencia = Field( + 'dispositivo_vigencia', + data_sapl_ta='DispositivoSearch', + data_field='dispositivo_vigencia', + data_type_selection='radio', + template="compilacao/layout/dispositivo_radio.html") + layout.append( + Fieldset(_('Dispositivo de Vigência'), + to_row([(InlineRadios('extensao'), 12)]), + row_vigencia, + css_class="col-md-12")) + self.helper = FormHelper() self.helper.layout = SaplFormLayout( + *layout, label_cancel=_('Retornar para o Editor Sequencial')) - self.helper.layout.fields += layout - - kwargs['fields_search'] = fields_search = Div() - self.helper.layout.fields.append( - Fieldset(_('Dispositivo de Vigência'), - fields_search, - css_class="col-md-12 dispositivo_vigencia_busca")) - super(DispositivoEdicaoVigenciaForm, self).__init__(*args, **kwargs) pubs = Publicacao.objects.order_by( @@ -684,3 +760,112 @@ class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): p.tipo_publicacao, defaultfilters.date( p.data, "d \d\e F \d\e Y"))) for p in pubs] + + dvs = Dispositivo.objects.order_by('ordem').filter( + pk=self.instance.dispositivo_vigencia_id) + self.fields['dispositivo_vigencia'].choices = [(d.pk, d) for d in dvs] + + def save(self): + super(DispositivoEdicaoVigenciaForm, self).save() + + data = self.cleaned_data + + extensao = 'extensao' in data and data['extensao'] == 'True' + + if extensao: + dv = data['dispositivo_vigencia'] + dv_pk = dv.pk if dv else None + instance = self.instance + + def extenderPara(dpt_pk): + + Dispositivo.objects.filter( + dispositivo_pai_id=dpt_pk, + ta_publicado__isnull=True).update( + dispositivo_vigencia_id=dv_pk) + + filhos = Dispositivo.objects.filter( + dispositivo_pai_id=dpt_pk).values_list('pk', flat=True) + + for d in filhos: + extenderPara(d) + + extenderPara(instance.pk) + + +class MultipleChoiceWithoutValidationField(forms.MultipleChoiceField): + + def validate(self, value): + if self.required and not value: + raise ValidationError( + self.error_messages['required'], code='required') + + +class DispositivoDefinidorVigenciaForm(Form): + + dispositivo_vigencia = MultipleChoiceWithoutValidationField( + label=Dispositivo._meta.get_field( + 'dispositivo_vigencia').verbose_name, + required=False) + + def __init__(self, *args, **kwargs): + + layout = [] + + row_vigencia = Field( + 'dispositivo_vigencia', + data_sapl_ta='DispositivoSearch', + data_field='dispositivo_vigencia', + data_type_selection='checkbox', + template="compilacao/layout/dispositivo_checkbox.html") + layout.append( + Fieldset(_('Definidor de Vigência dos Dispositívos abaixo'), + row_vigencia, + css_class="col-md-12")) + + self.helper = FormHelper() + self.helper.layout = SaplFormLayout( + *layout, + label_cancel=_('Retornar para o Editor Sequencial')) + + pk = kwargs.pop('pk') + super(DispositivoDefinidorVigenciaForm, self).__init__(*args, **kwargs) + + dvs = Dispositivo.objects.order_by('ta', 'ordem').filter( + dispositivo_vigencia_id=pk).select_related( + 'tipo_dispositivo', + 'ta_publicado', + 'ta', + 'dispositivo_atualizador', + 'dispositivo_atualizador__dispositivo_pai', + 'dispositivo_atualizador__dispositivo_pai__ta', + 'dispositivo_atualizador__dispositivo_pai__ta__tipo_ta', + 'dispositivo_pai', + 'dispositivo_pai__tipo_dispositivo', + 'ta_publicado', + 'ta',) + self.initial['dispositivo_vigencia'] = [d.pk for d in dvs] + + tas = Dispositivo.objects.filter( + dispositivo_vigencia_id=pk).values_list('ta', 'ta_publicado') + + tas = list(set().union(*list(map(list, zip(*tas))))) + + if not tas: + tas = Dispositivo.objects.filter(pk=pk).values_list('ta_id') + + dvs = Dispositivo.objects.order_by('-ta__data', '-ta__ano', '-ta__numero', 'ta', 'ordem').filter( + ta__in=tas).select_related( + 'tipo_dispositivo', + 'ta_publicado', + 'ta', + 'dispositivo_atualizador', + 'dispositivo_atualizador__dispositivo_pai', + 'dispositivo_atualizador__dispositivo_pai__ta', + 'dispositivo_atualizador__dispositivo_pai__ta__tipo_ta', + 'dispositivo_pai', + 'dispositivo_pai__tipo_dispositivo', + 'ta_publicado', + 'ta',) + self.fields['dispositivo_vigencia'].choices = [ + (d.pk, d) for d in dvs] diff --git a/compilacao/models.py b/compilacao/models.py index 847e2f7ff..96961f673 100644 --- a/compilacao/models.py +++ b/compilacao/models.py @@ -627,7 +627,7 @@ class Dispositivo(BaseModel, TimestampedMixin): dispositivo_vigencia = models.ForeignKey( 'self', blank=True, null=True, default=None, - related_name='+', + related_name='dispositivos_vigencias_set', verbose_name=_('Dispositivo de Vigência')) dispositivo_atualizador = models.ForeignKey( 'self', @@ -752,6 +752,8 @@ class Dispositivo(BaseModel, TimestampedMixin): r += prefixo[0] r += self.get_nomenclatura_completa() else: + if self.dispositivo0 == 0: + self.dispositivo0 = 1 r += prefixo[0] r += self.get_nomenclatura_completa() @@ -1150,10 +1152,20 @@ class Dispositivo(BaseModel, TimestampedMixin): dp.texto = '' dp.ta = dispositivo_base.ta dp.dispositivo_pai = dispositivo_base.dispositivo_pai - dp.inicio_eficacia = dispositivo_base.inicio_eficacia - dp.inicio_vigencia = dispositivo_base.inicio_vigencia dp.publicacao = dispositivo_base.publicacao - dp.timestamp = datetime.now() + + dp.dispositivo_vigencia = dispositivo_base.dispositivo_vigencia + if dp.dispositivo_vigencia: + dp.inicio_eficacia = dp.dispositivo_vigencia.inicio_eficacia + dp.inicio_vigencia = dp.dispositivo_vigencia.inicio_vigencia + dp.fim_eficacia = dp.dispositivo_vigencia.fim_eficacia + dp.fim_vigencia = dp.dispositivo_vigencia.fim_vigencia + else: + dp.inicio_eficacia = dispositivo_base.inicio_eficacia + dp.inicio_vigencia = dispositivo_base.inicio_vigencia + dp.fim_eficacia = dispositivo_base.inicio_eficacia + dp.fim_vigencia = dispositivo_base.fim_vigencia + dp.ordem = dispositivo_base.ordem return dp diff --git a/compilacao/templatetags/compilacao_filters.py b/compilacao/templatetags/compilacao_filters.py index 6aab329a5..2ee09593b 100644 --- a/compilacao/templatetags/compilacao_filters.py +++ b/compilacao/templatetags/compilacao_filters.py @@ -16,13 +16,6 @@ def get_bloco_atualizador(pk_atualizador): Q(dispositivo_atualizador_id=pk_atualizador)).select_related() -@register.filter -def get_tipos_dispositivo(pk_atual): - - return TipoDispositivo.objects.filter( - id__gte=pk_atual) - - @register.simple_tag def dispositivo_desativado(dispositivo, inicio_vigencia, fim_vigencia): if inicio_vigencia and fim_vigencia: @@ -39,17 +32,23 @@ def dispositivo_desativado(dispositivo, inicio_vigencia, fim_vigencia): @register.simple_tag def nota_automatica(dispositivo, ta_pub_list): + if dispositivo.ta_publicado is not None: d = dispositivo.dispositivo_atualizador.dispositivo_pai + + ta_publicado = ta_pub_list[dispositivo.ta_publicado_id] if\ + ta_pub_list else dispositivo.ta_publicado + if dispositivo.texto == Dispositivo.TEXTO_PADRAO_DISPOSITIVO_REVOGADO: return _('Revogado pelo %s - %s.') % ( - d, ta_pub_list[dispositivo.ta_publicado_id]) + d, ta_publicado) elif not dispositivo.dispositivo_substituido_id: return _('Inclusão feita pelo %s - %s.') % ( - d, ta_pub_list[dispositivo.ta_publicado_id]) + d, ta_publicado) else: return _('Alteração feita pelo %s - %s.') % ( - d, ta_pub_list[dispositivo.ta_publicado_id]) + d, ta_publicado) + return '' @@ -125,8 +124,10 @@ def nomenclatura(d): result = '(' + d.tipo_dispositivo.nome + ' ' + \ d.rotulo + ')' else: - result = '(' + d.tipo_dispositivo.nome + ' ' + \ - d.rotulo_padrao() + ')' + r = d.rotulo_padrao() + if r: + r += ' ' + result = '(' + d.tipo_dispositivo.nome + r + ')' return result @@ -159,3 +160,8 @@ def nomenclatura_heranca(d, ignore_ultimo=0, ignore_primeiro=0): @register.filter def urldetail_content_type(obj): return '%s:detail' % obj.content_type.model + + +@register.filter +def list(obj): + return [obj, ] diff --git a/compilacao/urls.py b/compilacao/urls.py index bc5d22754..1a2262c02 100644 --- a/compilacao/urls.py +++ b/compilacao/urls.py @@ -40,13 +40,13 @@ urlpatterns_compilacao = [ views.DispositivoEdicaoVigenciaView.as_view(), name='dispositivo_edit_vigencia'), - + url(r'^(?P[0-9]+)/text/(?P[0-9]+)/edit/definidor_vigencia', + views.DispositivoDefinidorVigenciaView.as_view(), + name='dispositivo_edit_definidor_vigencia'), url(r'^(?P[0-9]+)/text/(?P[0-9]+)/actions', views.ActionsEditView.as_view(), name='dispositivo_actions'), - - url(r'^(?P[0-9]+)/text/' '(?P[0-9]+)/nota/create$', views.NotasCreateView.as_view(), name='nota_create'), @@ -75,6 +75,10 @@ urlpatterns_compilacao = [ views.DispositivoSearchFragmentFormView.as_view(), name='dispositivo_fragment_form'), + url(r'^search_form$', + views.DispositivoSearchModalView.as_view(), + name='dispositivo_search_form'), + url(r'^(?P[0-9]+)/publicacao$', views.PublicacaoListView.as_view(), name='ta_pub_list'), diff --git a/compilacao/views.py b/compilacao/views.py index 82dceebbf..1e6c901f4 100644 --- a/compilacao/views.py +++ b/compilacao/views.py @@ -19,12 +19,15 @@ from django.utils.decorators import method_decorator from django.utils.translation import ugettext_lazy as _ from django.views.generic.base import TemplateView from django.views.generic.detail import DetailView -from django.views.generic.edit import CreateView, DeleteView, UpdateView +from django.views.generic.edit import CreateView, DeleteView, UpdateView,\ + FormView from django.views.generic.list import ListView from compilacao.forms import (DispositivoEdicaoBasicaForm, NotaForm, PublicacaoForm, TaForm, TipoTaForm, VideForm, - DispositivoEdicaoVigenciaForm) + DispositivoEdicaoVigenciaForm, + DispositivoSearchModalForm, + DispositivoDefinidorVigenciaForm) from compilacao.models import (Dispositivo, Nota, PerfilEstruturalTextoArticulado, Publicacao, TextoArticulado, TipoDispositivo, TipoNota, @@ -317,6 +320,266 @@ class TaDeleteView(CompMixin, DeleteView): return reverse_lazy('compilacao:ta_list') +class DispositivoSuccessUrlMixin: + + def get_success_url(self): + return reverse_lazy( + 'compilacao:dispositivo', kwargs={ + 'ta_id': self.kwargs[ + 'ta_id'], + 'dispositivo_id': self.kwargs[ + 'dispositivo_id']}) + + +class NotaMixin(DispositivoSuccessUrlMixin): + + def get_modelo_nota(self, request): + if 'action' in request.GET and request.GET['action'] == 'modelo_nota': + tn = TipoNota.objects.get(pk=request.GET['id_tipo']) + return True, tn.modelo + return False, '' + + def get_initial(self): + dispositivo = get_object_or_404( + Dispositivo, pk=self.kwargs.get('dispositivo_id')) + initial = {'dispositivo': dispositivo} + + if 'pk' in self.kwargs: + initial['pk'] = self.kwargs.get('pk') + + return initial + + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super(NotaMixin, self).dispatch(*args, **kwargs) + + +class NotasCreateView(NotaMixin, CreateView): + template_name = 'compilacao/ajax_form.html' + form_class = NotaForm + + def get(self, request, *args, **kwargs): + flag_action, modelo_nota = self.get_modelo_nota(request) + if flag_action: + return HttpResponse(modelo_nota) + + return super(NotasCreateView, self).get(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + self.object = None + try: + ta_id = kwargs.pop('ta_id') + dispositivo_id = kwargs.pop('dispositivo_id') + form = NotaForm(request.POST, request.FILES, **kwargs) + kwargs['ta_id'] = ta_id + kwargs['dispositivo_id'] = dispositivo_id + + if form.is_valid(): + nt = form.save(commit=False) + nt.owner_id = request.user.pk + nt.save() + self.kwargs['pk'] = nt.pk + return self.form_valid(form) + else: + return self.form_invalid(form) + except Exception as e: + print(e) + return HttpResponse("error post") + + +class NotasEditView(NotaMixin, UpdateView): + model = Nota + template_name = 'compilacao/ajax_form.html' + form_class = NotaForm + + def get(self, request, *args, **kwargs): + flag_action, modelo_nota = self.get_modelo_nota(request) + if flag_action: + return HttpResponse(modelo_nota) + + return super(NotasEditView, self).get(request, *args, **kwargs) + + +class NotasDeleteView(NotaMixin, TemplateView): + + def get(self, request, *args, **kwargs): + nt = Nota.objects.get(pk=self.kwargs['pk']) + nt.delete() + return HttpResponseRedirect(self.get_success_url()) + + +class VideMixin(DispositivoSuccessUrlMixin): + + def get_initial(self): + dispositivo_base = get_object_or_404( + Dispositivo, pk=self.kwargs.get('dispositivo_id')) + + initial = {'dispositivo_base': dispositivo_base} + + if 'pk' in self.kwargs: + initial['pk'] = self.kwargs.get('pk') + + return initial + + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super(VideMixin, self).dispatch(*args, **kwargs) + + +def choice_model_type_foreignkey_in_extenal_views(id_tipo_ta=None): + yield None, '-------------' + + if not id_tipo_ta: + return + + tipo_ta = TipoTextoArticulado.objects.get(pk=id_tipo_ta) + + integrations_view_names = get_integrations_view_names() + for item in integrations_view_names: + if hasattr(item, 'model_type_foreignkey'): + if (tipo_ta.content_type.model == item.model.__name__.lower() and + tipo_ta.content_type.app_label == + item.model._meta.app_label): + for i in item.model_type_foreignkey.objects.all(): + yield i.pk, i + + +class VideCreateView(VideMixin, CreateView): + model = Vide + template_name = 'compilacao/ajax_form.html' + form_class = VideForm + + def get(self, request, *args, **kwargs): + self.object = None + form = self.get_form() + return self.render_to_response(self.get_context_data(form=form)) + + def get_form_kwargs(self): + + kwargs = super(VideCreateView, self).get_form_kwargs() + + if 'choice_model_type_foreignkey_in_extenal_views' not in kwargs: + kwargs.update({ + 'choice_model_type_foreignkey_in_extenal_views': + choice_model_type_foreignkey_in_extenal_views + }) + + return kwargs + + +class VideEditView(VideMixin, UpdateView): + model = Vide + template_name = 'compilacao/ajax_form.html' + form_class = VideForm + + +class VideDeleteView(VideMixin, TemplateView): + + def get(self, request, *args, **kwargs): + vd = Vide.objects.get(pk=self.kwargs['pk']) + vd.delete() + return HttpResponseRedirect(self.get_success_url()) + + +class PublicacaoListView(ListView): + model = Publicacao + verbose_name = model._meta.verbose_name + + @property + def title(self): + return _('%s de %s' % ( + self.model._meta.verbose_name_plural, + self.ta)) + + @property + def ta(self): + ta = TextoArticulado.objects.get(pk=self.kwargs['ta_id']) + return ta + + @property + def create_url(self): + return reverse_lazy( + 'compilacao:ta_pub_create', + kwargs={'ta_id': self.kwargs['ta_id']}) + + def get_queryset(self): + pubs = Publicacao.objects.filter(ta_id=self.kwargs['ta_id']) + return pubs + + def get_context_data(self, **kwargs): + context = super(PublicacaoListView, self).get_context_data(**kwargs) + context['NO_ENTRIES_MSG'] = CrudListView.no_entries_msg + return context + + +class PublicacaoCreateView(FormMessagesMixin, CreateView): + model = Publicacao + form_class = PublicacaoForm + template_name = "crud/form.html" + form_valid_message = _('Registro criado com sucesso!') + form_invalid_message = _('O registro não foi criado.') + + def get_success_url(self): + return reverse_lazy( + 'compilacao:ta_pub_detail', + kwargs={ + 'pk': self.object.id, + 'ta_id': self.kwargs['ta_id']}) + + @property + def cancel_url(self): + return reverse_lazy( + 'compilacao:ta_pub_list', + kwargs={'ta_id': self.kwargs['ta_id']}) + + def get_initial(self): + return {'ta': self.kwargs['ta_id']} + + +class PublicacaoDetailView(CompMixin, DetailView): + model = Publicacao + + +class PublicacaoUpdateView(CompMixin, UpdateView): + model = Publicacao + form_class = PublicacaoForm + template_name = "crud/form.html" + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + form = self.get_form() + # if self.object and self.object.content_object: + # form.fields['tipo_ta'].required = False + # form.fields['tipo_ta'].widget.attrs['disabled'] = 'disabled' + return self.render_to_response(self.get_context_data(form=form)) + + def get_success_url(self): + return reverse_lazy('compilacao:ta_pub_detail', + kwargs={ + 'pk': self.object.id, + 'ta_id': self.kwargs['ta_id']}) + + @property + def cancel_url(self): + return self.get_success_url() + + +class PublicacaoDeleteView(CompMixin, DeleteView): + model = Publicacao + template_name = "crud/confirm_delete.html" + + @property + def detail_url(self): + return reverse_lazy('compilacao:ta_pub_detail', + kwargs={ + 'pk': self.object.id, + 'ta_id': self.kwargs['ta_id']}) + + def get_success_url(self): + return reverse_lazy('compilacao:ta_pub_list', + kwargs={'ta_id': self.kwargs['ta_id']}) + + class TextView(ListView, CompMixin): template_name = 'compilacao/text_list.html' @@ -617,7 +880,6 @@ class TextEditView(ListView, CompMixin): a.tipo_dispositivo = td a.inicio_vigencia = ta.data a.inicio_eficacia = ta.data - a.timestamp = datetime.now() a.save() td = TipoDispositivo.objects.filter(class_css='ementa')[0] @@ -630,7 +892,6 @@ class TextEditView(ListView, CompMixin): e.tipo_dispositivo = td e.inicio_vigencia = ta.data e.inicio_eficacia = ta.data - e.timestamp = datetime.now() e.texto = ta.ementa e.dispositivo_pai = a e.save() @@ -640,7 +901,6 @@ class TextEditView(ListView, CompMixin): a.ordem = e.ordem + Dispositivo.INTERVALO_ORDEM a.ordem_bloco_atualizador = 0 a.set_numero_completo([2, 0, 0, 0, 0, 0, ]) - a.timestamp = datetime.now() a.save() result = Dispositivo.objects.filter( @@ -1018,6 +1278,7 @@ class ActionsEditMixin: return JsonResponse(action(context), safe=False) def set_dvt(self, context): + # Dispositivo de Vigência do Texto Original e de Dpts Alterados dvt = Dispositivo.objects.get(pk=context['dispositivo_id']) if dvt.is_relative_auto_insert(): @@ -1025,15 +1286,28 @@ class ActionsEditMixin: try: Dispositivo.objects.filter( - ta=dvt.ta, - ta_publicado__isnull=True).update( - dispositivo_vigencia=dvt, - inicio_vigencia=dvt.inicio_vigencia) - - Dispositivo.objects.filter( - ta_publicado=dvt.ta).update( + (Q(ta=dvt.ta) & Q(ta_publicado__isnull=True)) | + Q(ta_publicado=dvt.ta) + ).update( dispositivo_vigencia=dvt, - inicio_vigencia=dvt.inicio_vigencia) + inicio_vigencia=dvt.inicio_vigencia, + inicio_eficacia=dvt.inicio_eficacia) + + dps = Dispositivo.objects.filter(dispositivo_vigencia_id=dvt.pk, + ta_publicado_id=dvt.ta_id) + + for d in dps: + if d.dispositivo_substituido: + ds = d.dispositivo_substituido + ds.fim_vigencia = d.inicio_vigencia - timedelta(days=1) + ds.fim_eficacia = d.inicio_eficacia - timedelta(days=1) + ds.save() + + if d.dispositivo_subsequente: + ds = d.dispositivo_subsequente + d.fim_vigencia = ds.inicio_vigencia - timedelta(days=1) + d.fim_eficacia = ds.inicio_eficacia - timedelta(days=1) + d.save() return {'message': str(_('Dispositivo de Vigência atualizado ' 'com sucesso!!!'))} @@ -1723,172 +1997,80 @@ class ActionsEditView(ActionsEditMixin, TemplateView): return self.render_to_json_response(context, **response_kwargs) -class DispositivoSuccessUrlMixin: +class DispositivoEdicaoBasicaView(FormMessagesMixin, UpdateView): + model = Dispositivo + template_name = 'compilacao/dispositivo_form_edicao_basica.html' + form_class = DispositivoEdicaoBasicaForm + form_valid_message = _('Alterações no Dispositivo realizadas com sucesso!') + form_invalid_message = _('Houve erro em registrar ' + 'as alterações no Dispositivo') - def get_success_url(self): + @property + def cancel_url(self): return reverse_lazy( - 'compilacao:dispositivo', kwargs={ - 'ta_id': self.kwargs[ - 'ta_id'], - 'dispositivo_id': self.kwargs[ - 'dispositivo_id']}) - - -class NotaMixin(DispositivoSuccessUrlMixin): - - def get_modelo_nota(self, request): - if 'action' in request.GET and request.GET['action'] == 'modelo_nota': - tn = TipoNota.objects.get(pk=request.GET['id_tipo']) - return True, tn.modelo - return False, '' - - def get_initial(self): - dispositivo = get_object_or_404( - Dispositivo, pk=self.kwargs.get('dispositivo_id')) - initial = {'dispositivo': dispositivo} - - if 'pk' in self.kwargs: - initial['pk'] = self.kwargs.get('pk') - - return initial - - @method_decorator(login_required) - def dispatch(self, *args, **kwargs): - return super(NotaMixin, self).dispatch(*args, **kwargs) - - -class NotasCreateView(NotaMixin, CreateView): - template_name = 'compilacao/ajax_form.html' - form_class = NotaForm - - def get(self, request, *args, **kwargs): - flag_action, modelo_nota = self.get_modelo_nota(request) - if flag_action: - return HttpResponse(modelo_nota) - - return super(NotasCreateView, self).get(request, *args, **kwargs) - - def post(self, request, *args, **kwargs): - self.object = None - try: - ta_id = kwargs.pop('ta_id') - dispositivo_id = kwargs.pop('dispositivo_id') - form = NotaForm(request.POST, request.FILES, **kwargs) - kwargs['ta_id'] = ta_id - kwargs['dispositivo_id'] = dispositivo_id - - if form.is_valid(): - nt = form.save(commit=False) - nt.owner_id = request.user.pk - nt.save() - self.kwargs['pk'] = nt.pk - return self.form_valid(form) - else: - return self.form_invalid(form) - except Exception as e: - print(e) - return HttpResponse("error post") - - -class NotasEditView(NotaMixin, UpdateView): - model = Nota - template_name = 'compilacao/ajax_form.html' - form_class = NotaForm - - def get(self, request, *args, **kwargs): - flag_action, modelo_nota = self.get_modelo_nota(request) - if flag_action: - return HttpResponse(modelo_nota) - - return super(NotasEditView, self).get(request, *args, **kwargs) - - -class NotasDeleteView(NotaMixin, TemplateView): - - def get(self, request, *args, **kwargs): - nt = Nota.objects.get(pk=self.kwargs['pk']) - nt.delete() - return HttpResponseRedirect(self.get_success_url()) - - -class VideMixin(DispositivoSuccessUrlMixin): - - def get_initial(self): - dispositivo_base = get_object_or_404( - Dispositivo, pk=self.kwargs.get('dispositivo_id')) - - initial = {'dispositivo_base': dispositivo_base} - - if 'pk' in self.kwargs: - initial['pk'] = self.kwargs.get('pk') - - return initial - - @method_decorator(login_required) - def dispatch(self, *args, **kwargs): - return super(VideMixin, self).dispatch(*args, **kwargs) - - -def choice_model_type_foreignkey_in_extenal_views(id_tipo_ta=None): - yield None, '-------------' - - if not id_tipo_ta: - return - - tipo_ta = TipoTextoArticulado.objects.get(pk=id_tipo_ta) - - integrations_view_names = get_integrations_view_names() - for item in integrations_view_names: - if hasattr(item, 'model_type_foreignkey'): - if (tipo_ta.content_type.model == item.model.__name__.lower() and - tipo_ta.content_type.app_label == - item.model._meta.app_label): - for i in item.model_type_foreignkey.objects.all(): - yield i.pk, i - - -class DispositivoSearchMixin: + 'compilacao:ta_text_edit', + kwargs={'ta_id': self.kwargs['ta_id']}) + '#' + str(self.object.pk) - def get_form_kwargs(self): + def get_success_url(self): + return reverse_lazy( + 'compilacao:dispositivo_edit', + kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']}) - kwargs = super(DispositivoSearchMixin, self).get_form_kwargs() + def get_url_this_view(self): + return 'compilacao:dispositivo_edit' - if 'choice_model_type_foreignkey_in_extenal_views' not in kwargs: - kwargs.update({ - 'choice_model_type_foreignkey_in_extenal_views': - choice_model_type_foreignkey_in_extenal_views - }) + def run_actions(self, request): + if 'action' in request.GET and\ + request.GET['action'] == 'atualiza_rotulo': + try: + d = Dispositivo.objects.get(pk=self.kwargs['pk']) + d.dispositivo0 = int(request.GET['dispositivo0']) + d.dispositivo1 = int(request.GET['dispositivo1']) + d.dispositivo2 = int(request.GET['dispositivo2']) + d.dispositivo3 = int(request.GET['dispositivo3']) + d.dispositivo4 = int(request.GET['dispositivo4']) + d.dispositivo5 = int(request.GET['dispositivo5']) + d.rotulo = d.rotulo_padrao() - return kwargs + numero = d.get_numero_completo()[1:] + zerar = False + for i in range(len(numero)): + if not numero[i]: + zerar = True -class VideCreateView(VideMixin, DispositivoSearchMixin, CreateView): - model = Vide - template_name = 'compilacao/ajax_form.html' - form_class = VideForm + if zerar: + numero[i] = 0 - def get(self, request, *args, **kwargs): - self.object = None - form = self.get_form() - return self.render_to_response(self.get_context_data(form=form)) + if zerar: + d.set_numero_completo([d.dispositivo0, ] + numero) + d.rotulo = d.rotulo_padrao() + except: + return True, JsonResponse({'message': str( + _('Ocorreu erro na atualização do rótulo'))}, safe=False) + return True, JsonResponse({ + 'rotulo': d.rotulo, + 'dispositivo0': d.dispositivo0, + 'dispositivo1': d.dispositivo1, + 'dispositivo2': d.dispositivo2, + 'dispositivo3': d.dispositivo3, + 'dispositivo4': d.dispositivo4, + 'dispositivo5': d.dispositivo5}, safe=False) -class VideEditView(VideMixin, UpdateView): - model = Vide - template_name = 'compilacao/ajax_form.html' - form_class = VideForm + return False, '' + def get(self, request, *args, **kwargs): -class VideDeleteView(VideMixin, TemplateView): + flag_action, render_json_response = self.run_actions(request) + if flag_action: + return render_json_response - def get(self, request, *args, **kwargs): - vd = Vide.objects.get(pk=self.kwargs['pk']) - vd.delete() - return HttpResponseRedirect(self.get_success_url()) + return UpdateView.get(self, request, *args, **kwargs) class DispositivoSearchFragmentFormView(ListView): - template_name = 'compilacao/dispositivo_search_fragment_form.html' + template_name = 'compilacao/dispositivo_form_search_fragment.html' def get(self, request, *args, **kwargs): @@ -1908,16 +2090,18 @@ class DispositivoSearchFragmentFormView(ListView): def get_queryset(self): try: + n = 10 + q = Q(nivel__gt=0) if 'initial_ref' in self.request.GET: initial_ref = self.request.GET['initial_ref'] if initial_ref: - q = Q(pk=initial_ref) + q = q & Q(pk=initial_ref) result = Dispositivo.objects.filter(q).select_related( 'ta').exclude( tipo_dispositivo__dispositivo_de_alteracao=True) - return result + return result[:n] texto = '' rotulo = '' @@ -1925,9 +2109,7 @@ class DispositivoSearchFragmentFormView(ListView): if 'texto' in self.request.GET: texto = self.request.GET['texto'] - q = Q(nivel__gt=0) texto = texto.split(' ') - n = 10 if 'rotulo' in self.request.GET: rotulo = self.request.GET['rotulo'] @@ -2023,220 +2205,84 @@ class DispositivoSearchFragmentFormView(ListView): print(e) -class PublicacaoListView(ListView): - model = Publicacao - verbose_name = model._meta.verbose_name - - @property - def title(self): - return _('%s de %s' % ( - self.model._meta.verbose_name_plural, - self.ta)) - - @property - def ta(self): - ta = TextoArticulado.objects.get(pk=self.kwargs['ta_id']) - return ta - - @property - def create_url(self): - return reverse_lazy( - 'compilacao:ta_pub_create', - kwargs={'ta_id': self.kwargs['ta_id']}) - - def get_queryset(self): - pubs = Publicacao.objects.filter(ta_id=self.kwargs['ta_id']) - return pubs - - def get_context_data(self, **kwargs): - context = super(PublicacaoListView, self).get_context_data(**kwargs) - context['NO_ENTRIES_MSG'] = CrudListView.no_entries_msg - return context - +class DispositivoSearchModalView(FormView): + template_name = 'compilacao/dispositivo_form_search.html' + form_class = DispositivoSearchModalForm -class PublicacaoCreateView(FormMessagesMixin, CreateView): - model = Publicacao - form_class = PublicacaoForm - template_name = "crud/form.html" - form_valid_message = _('Registro criado com sucesso!') - form_invalid_message = _('O registro não foi criado.') - def get_success_url(self): - return reverse_lazy( - 'compilacao:ta_pub_detail', - kwargs={ - 'pk': self.object.id, - 'ta_id': self.kwargs['ta_id']}) +class DispositivoEdicaoVigenciaView(FormMessagesMixin, UpdateView): + model = Dispositivo + template_name = 'compilacao/dispositivo_form_vigencia.html' + form_class = DispositivoEdicaoVigenciaForm + form_valid_message = _('Alterações no Dispositivo realizadas com sucesso!') + form_invalid_message = _('Houve erro em registrar ' + 'as alterações no Dispositivo') @property def cancel_url(self): return reverse_lazy( - 'compilacao:ta_pub_list', - kwargs={'ta_id': self.kwargs['ta_id']}) - - def get_initial(self): - return {'ta': self.kwargs['ta_id']} - - -class PublicacaoDetailView(CompMixin, DetailView): - model = Publicacao - - -class PublicacaoUpdateView(CompMixin, UpdateView): - model = Publicacao - form_class = PublicacaoForm - template_name = "crud/form.html" - - def get(self, request, *args, **kwargs): - self.object = self.get_object() - form = self.get_form() - # if self.object and self.object.content_object: - # form.fields['tipo_ta'].required = False - # form.fields['tipo_ta'].widget.attrs['disabled'] = 'disabled' - return self.render_to_response(self.get_context_data(form=form)) - - def get_success_url(self): - return reverse_lazy('compilacao:ta_pub_detail', - kwargs={ - 'pk': self.object.id, - 'ta_id': self.kwargs['ta_id']}) - - @property - def cancel_url(self): - return self.get_success_url() - - -class PublicacaoDeleteView(CompMixin, DeleteView): - model = Publicacao - template_name = "crud/confirm_delete.html" + 'compilacao:ta_text_edit', + kwargs={'ta_id': self.kwargs['ta_id']}) + '#' + str(self.object.pk) - @property - def detail_url(self): - return reverse_lazy('compilacao:ta_pub_detail', - kwargs={ - 'pk': self.object.id, - 'ta_id': self.kwargs['ta_id']}) + def get_url_this_view(self): + return 'compilacao:dispositivo_edit_vigencia' def get_success_url(self): - return reverse_lazy('compilacao:ta_pub_list', - kwargs={'ta_id': self.kwargs['ta_id']}) + return reverse_lazy( + 'compilacao:dispositivo_edit_vigencia', + kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']}) -class DispositivoEdicaoBasicaView(FormMessagesMixin, UpdateView): +class DispositivoDefinidorVigenciaView(FormMessagesMixin, FormView): model = Dispositivo - form_class = DispositivoEdicaoBasicaForm + template_name = 'compilacao/dispositivo_form_definidor_vigencia.html' + form_class = DispositivoDefinidorVigenciaForm form_valid_message = _('Alterações no Dispositivo realizadas com sucesso!') form_invalid_message = _('Houve erro em registrar ' 'as alterações no Dispositivo') + def get_form_kwargs(self): + kwargs = FormView.get_form_kwargs(self) + kwargs.update({ + 'pk': self.kwargs['pk'], + }) + return kwargs + @property def cancel_url(self): return reverse_lazy( 'compilacao:ta_text_edit', kwargs={'ta_id': self.kwargs['ta_id']}) + '#' + str(self.object.pk) - def get_success_url(self): - return reverse_lazy( - 'compilacao:dispositivo_edit', - kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']}) - - def get_url_this_view(self): - return 'compilacao:dispositivo_edit' - - def run_actions(self, request): - if 'action' in request.GET and\ - request.GET['action'] == 'atualiza_rotulo': - try: - d = Dispositivo.objects.get(pk=self.kwargs['pk']) - d.dispositivo0 = int(request.GET['dispositivo0']) - d.dispositivo1 = int(request.GET['dispositivo1']) - d.dispositivo2 = int(request.GET['dispositivo2']) - d.dispositivo3 = int(request.GET['dispositivo3']) - d.dispositivo4 = int(request.GET['dispositivo4']) - d.dispositivo5 = int(request.GET['dispositivo5']) - d.rotulo = d.rotulo_padrao() - - numero = d.get_numero_completo()[1:] - - zerar = False - for i in range(len(numero)): - if not numero[i]: - zerar = True - - if zerar: - numero[i] = 0 - - if zerar: - d.set_numero_completo([d.dispositivo0, ] + numero) - d.rotulo = d.rotulo_padrao() - - except: - return True, JsonResponse({'message': str( - _('Ocorreu erro na atualização do rótulo'))}, safe=False) - return True, JsonResponse({ - 'rotulo': d.rotulo, - 'dispositivo0': d.dispositivo0, - 'dispositivo1': d.dispositivo1, - 'dispositivo2': d.dispositivo2, - 'dispositivo3': d.dispositivo3, - 'dispositivo4': d.dispositivo4, - 'dispositivo5': d.dispositivo5}, safe=False) - - return False, '' - - def get(self, request, *args, **kwargs): - - flag_action, render_json_response = self.run_actions(request) - if flag_action: - return render_json_response - - return UpdateView.get(self, request, *args, **kwargs) - - -class DispositivoEdicaoVigenciaView( - DispositivoSearchMixin, DispositivoEdicaoBasicaView): - model = Dispositivo - form_class = DispositivoEdicaoVigenciaForm - def get_url_this_view(self): - return 'compilacao:dispositivo_edit_vigencia' + return 'compilacao:dispositivo_edit_definidor_vigencia' def get_success_url(self): return reverse_lazy( - 'compilacao:dispositivo_edit_vigencia', + 'compilacao:dispositivo_edit_definidor_vigencia', kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']}) - def run_actions(self, request): - if 'action' in request.GET and\ - request.GET['action'] == 'atualiza_rotulo': - try: - pass - except: - return True, JsonResponse({'message': str( - _('Ocorreu erro na atualização do rótulo'))}, safe=False) - return True, JsonResponse({}, safe=False) - return False, '' - - def get_initial(self): - - ta = self.object.ta_publicado if self.object.ta_publicado else\ - self.object.ta + def get(self, request, *args, **kwargs): + self.object = get_object_or_404(Dispositivo, pk=kwargs['pk']) + return FormView.get(self, request, *args, **kwargs) - initial = { - 'ano_ta': ta.ano, - 'num_ta': ta.numero, - 'tipo_ta': ta.tipo_ta, - } - if hasattr(ta, 'content_object') and\ - ta.content_object: - lista_tipos = list(choice_model_type_foreignkey_in_extenal_views( - id_tipo_ta=ta.tipo_ta_id)) + def get_context_data(self, **kwargs): + context = FormView.get_context_data(self, **kwargs) + context.update({'object': self.object}) + return context - content_object = model_to_dict(ta.content_object) + def post(self, request, *args, **kwargs): + self.object = get_object_or_404(Dispositivo, pk=kwargs['pk']) - for key, value in content_object.items(): - for item in lista_tipos: - if getattr(ta.content_object, key) == item[1]: - initial['tipo_model'] = item[0] + form = self.get_form() + if form.is_valid(): + dvs = form.cleaned_data['dispositivo_vigencia'] + with transaction.atomic(): + self.object.dispositivos_vigencias_set.clear() + for item in dvs: + d = Dispositivo.objects.get(pk=item) + self.object.dispositivos_vigencias_set.add(d) - return initial + return self.form_valid(form) + else: + return self.form_invalid(form) diff --git a/static/js/compilacao.js b/static/js/compilacao.js index b6d2242f4..0a7f2aa3a 100644 --- a/static/js/compilacao.js +++ b/static/js/compilacao.js @@ -34,18 +34,14 @@ var configFormSearchTA = function(container, _tipo_form, _tipo_select) { $(container+" select[name='tipo_ta']").change(function(event) { var url = ''; url = '/ta/search_fragment_form?action=get_tipos&tipo_ta='+this.value; - $(container+" label[for='id_tipo_model']").html('Tipos de ' + this.children[this.selectedIndex].innerHTML); - var select = $(container+" select[name='tipo_model']"); select.empty(); $('').appendTo(select); $.get(url).done(function( data ) { select.empty(); - - for(var item in data) { for (var i in data[item]) select.append($("