Repository: interlegis/sapl

Issue:
Registro de tramitações em matérias anexadas
## Comportamento Esperado
As matérias, depois de anexadas, devem passar a receber as tramitações das matérias anexadoras, pelo menos as de fim de tramitação.

## Comportamento Atual
Isso não ocorre, deve-se dar tramitação em ambas.

## Contexto
Registro de tramitações.

## Imagens do Ocorrido
![captura de tela de 2018-12-11 10-34-58](https://user-images.githubusercontent.com/19169882/49801190-a5fed900-fd30-11e8-8db3-7261bd79d14e.png)
![captura de tela de 2018-12-11 10-35-35](https://user-images.githubusercontent.com/19169882/49801207-b1520480-fd30-11e8-9531-cc923a13b7b6.png)

## Seu Ambiente
Versão usada (Release): 3.1.137
Nome e versão do navegador: Versão 70.0.3538.77 (Versão oficial)
Nome e versão do Sistema Operacional (desktop ou mobile): Ubuntu 16.04 64 bits



Discussion:

Resolving patch:
diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py
--- a/sapl/materia/forms.py
+++ b/sapl/materia/forms.py
@@ -495,6 +495,20 @@ def clean(self):
 
         return cleaned_data
 
+    @transaction.atomic
+    def save(self, commit=True):
+        tramitacao = super(TramitacaoForm, self).save(commit)
+        materia = tramitacao.materia
+        for ma in materia.anexadas.all():
+            if not ma.tramitacao_set.all() \
+                    or ma.tramitacao_set.last().unidade_tramitacao_destino == tramitacao.unidade_tramitacao_local:
+                tramitacao_nova = tramitacao
+                tramitacao_nova.pk = None
+                tramitacao_nova.materia = ma
+                tramitacao_nova.save()
+
+        return tramitacao
+
 
 class TramitacaoUpdateForm(TramitacaoForm):
     unidade_tramitacao_local = forms.ModelChoiceField(
@@ -1123,6 +1137,29 @@ def __init__(self, *args, **kwargs):
             Fieldset(_('Documentos Acessórios em Lote'),
                      row1, row2, form_actions(label='Pesquisar')))
 
+class AnexadaEmLoteFilterSet(django_filters.FilterSet):
+
+    class Meta(FilterOverridesMetaMixin):
+        model = MateriaLegislativa
+        fields = ['tipo', 'data_apresentacao']
+
+    def __init__(self, *args, **kwargs):
+        super(AnexadaEmLoteFilterSet, self).__init__(*args, **kwargs)
+
+        self.filters['tipo'].label = 'Tipo de Matéria'
+        self.filters['data_apresentacao'].label = 'Data (Inicial - Final)'
+        self.form.fields['tipo'].required = True
+        self.form.fields['data_apresentacao'].required = True
+
+        row1 = to_row([('tipo', 12)])
+        row2 = to_row([('data_apresentacao', 12)])
+
+        self.form.helper = SaplFormHelper()
+        self.form.helper.form_method = 'GET'
+        self.form.helper.layout = Layout(
+            Fieldset(_('Matéria Anexada em Lote'),
+                     row1, row2, form_actions(label='Pesquisar')))
+
 
 class PrimeiraTramitacaoEmLoteFilterSet(django_filters.FilterSet):
 
diff --git a/sapl/materia/urls.py b/sapl/materia/urls.py
--- a/sapl/materia/urls.py
+++ b/sapl/materia/urls.py
@@ -8,6 +8,7 @@
                                 CriarProtocoloMateriaView, DespachoInicialCrud,
                                 DocumentoAcessorioCrud,
                                 DocumentoAcessorioEmLoteView,
+                                MateriaAnexadaEmLoteView,
                                 EtiquetaPesquisaView, FichaPesquisaView,
                                 FichaSelecionaView, ImpressosView,
                                 LegislacaoCitadaCrud, MateriaAssuntoCrud,
@@ -93,6 +94,8 @@
 
     url(r'^materia/acessorio-em-lote', DocumentoAcessorioEmLoteView.as_view(),
         name='acessorio_em_lote'),
+    url(r'^materia/(?P<pk>\d+)/anexada-em-lote', MateriaAnexadaEmLoteView.as_view(),
+        name='anexada_em_lote'),
     url(r'^materia/primeira-tramitacao-em-lote',
         PrimeiraTramitacaoEmLoteView.as_view(),
         name='primeira_tramitacao_em_lote'),
diff --git a/sapl/materia/views.py b/sapl/materia/views.py
--- a/sapl/materia/views.py
+++ b/sapl/materia/views.py
@@ -51,6 +51,7 @@
                         show_results_filter_set, mail_service_configured)
 
 from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm,
+                    AnexadaEmLoteFilterSet,
                     AdicionarVariasAutoriasFilterSet, DespachoInicialForm,
                     DocumentoAcessorioForm, EtiquetaPesquisaForm,
                     FichaPesquisaForm, FichaSelecionaForm, MateriaAssuntoForm,
@@ -1996,6 +1997,64 @@ def post(self, request, *args, **kwargs):
         messages.add_message(request, messages.SUCCESS, msg)
         return self.get(request, self.kwargs)
 
+class MateriaAnexadaEmLoteView(PermissionRequiredMixin, FilterView):
+    filterset_class = AnexadaEmLoteFilterSet
+    template_name = 'materia/em_lote/anexada.html'
+    permission_required = ('materia.add_documentoacessorio',)
+
+    def get_context_data(self, **kwargs):
+        context = super(MateriaAnexadaEmLoteView,
+                        self).get_context_data(**kwargs)
+
+        context['root_pk'] = self.kwargs['pk']
+
+        context['subnav_template_name'] = 'materia/subnav.yaml'
+
+
+        context['title'] = _('Matérias Anexadas em Lote')
+        # Verifica se os campos foram preenchidos
+        if not self.filterset.form.is_valid():
+            return context
+
+        qr = self.request.GET.copy()
+        context['object_list'] = context['object_list'].order_by(
+            'ano', 'numero')
+        context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
+
+        context['show_results'] = show_results_filter_set(qr)
+
+        return context
+
+    def post(self, request, *args, **kwargs):
+        marcadas = request.POST.getlist('materia_id')
+
+        if len(marcadas) == 0:
+            msg = _('Nenhuma máteria foi selecionada.')
+            messages.add_message(request, messages.ERROR, msg)
+            return self.get(request, self.kwargs)
+
+        data_anexacao = datetime.strptime(
+            request.POST['data_anexacao'], "%d/%m/%Y").date()
+
+        if request.POST['data_desanexacao'] == '':
+            data_desanexacao = None
+        else:
+            data_desanexacao = datetime.strptime(
+            request.POST['data_desanexacao'], "%d/%m/%Y").date()
+
+        for materia_id in marcadas:
+
+            anexada = Anexada()
+            anexada.materia_principal = MateriaLegislativa.objects.get(pk = kwargs['pk'])
+            anexada.materia_anexada = MateriaLegislativa.objects.get(pk = materia_id)
+            anexada.data_anexacao = data_anexacao
+            anexada.data_desanexacao = data_desanexacao
+            anexada.save()
+
+        msg = _('Materia(s) anexada(s).')
+        messages.add_message(request, messages.SUCCESS, msg)
+        return self.get(request, self.kwargs)
+
 
 class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView):
     filterset_class = PrimeiraTramitacaoEmLoteFilterSet


Test patch: