We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Link de Matéria Legislative em Audiência
## Comportamento Atual
<!--- Se está descrevendo um bug, conte-nos o que acontece em vez do comportamento esperado. -->
<!--- Se está sugerindo uma mudança/melhoria, explique a diferença com o comportamento atual. -->
Quando clica-se no link da Matéria Legislativa, é redirecionado para outra Matéria Legislativa e não a com o título no link

## Possível Solução
<!--- Não é obrigatório, mas sugira uma possível correção/razão para o bug -->
<!--- ou ideias de como implementar a adição/mudança. -->
Número das audiências estão repetidos. Talvez isso tá causando o bug.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sapl/audiencia/views.py`
Content:
```
1 import sapl
2 
3 from django.http import HttpResponse
4 from django.urls import reverse
5 from django.views.decorators.clickjacking import xframe_options_exempt
6 from django.views.generic import UpdateView
7 from sapl.crud.base import RP_DETAIL, RP_LIST, Crud, MasterDetailCrud
8 
9 from .forms import AudienciaForm, AnexoAudienciaPublicaForm
10 from .models import AudienciaPublica, AnexoAudienciaPublica
11 
12 
13 def index(request):
14     return HttpResponse("Audiência  Pública")
15 
16 
17 class AudienciaCrud(Crud):
18     model = AudienciaPublica
19     public = [RP_LIST, RP_DETAIL, ]
20 
21     class BaseMixin(Crud.BaseMixin):
22         list_field_names = ['numero', 'nome', 'tipo', 'materia',
23                             'data'] 
24         ordering = '-data', 'nome', 'numero', 'tipo'
25 
26     class ListView(Crud.ListView):
27         paginate_by = 10
28 
29         def get_context_data(self, **kwargs):
30             context = super().get_context_data(**kwargs)
31 
32             audiencia_materia = {}
33             for o in context['object_list']:
34                 # indexado pelo numero da audiencia
35                 audiencia_materia[str(o.numero)] = o.materia
36 
37             for row in context['rows']:
38                 coluna_materia = row[3] # se mudar a ordem de listagem mudar aqui
39                 if coluna_materia[0]:
40                     materia = audiencia_materia[row[0][0]]
41                     if materia:
42                         url_materia = reverse('sapl.materia:materialegislativa_detail',
43                                               kwargs={'pk': materia.id})
44                     else:
45                         url_materia = None
46                     row[3] = (coluna_materia[0], url_materia)
47             return context
48 
49     class CreateView(Crud.CreateView):
50         form_class = AudienciaForm
51 
52         def form_valid(self, form):
53             return super(Crud.CreateView, self).form_valid(form)
54 
55     class UpdateView(Crud.UpdateView):
56         form_class = AudienciaForm
57 
58         def get_initial(self):
59             initial = super(UpdateView, self).get_initial()
60             if self.object.materia:
61                 initial['tipo_materia'] = self.object.materia.tipo.id
62                 initial['numero_materia'] = self.object.materia.numero
63                 initial['ano_materia'] = self.object.materia.ano
64             return initial
65      
66     class DeleteView(Crud.DeleteView):
67         pass
68 
69     class DetailView(Crud.DetailView):
70 
71         layout_key = 'AudienciaPublicaDetail'
72 
73         @xframe_options_exempt
74         def get(self, request, *args, **kwargs):
75             return super().get(request, *args, **kwargs)
76 
77 
78 class AudienciaPublicaMixin:
79 
80     def has_permission(self):
81         app_config = sapl.base.models.AppConfig.objects.last()
82         if app_config and app_config.documentos_administrativos == 'O':
83             return True
84 
85         return super().has_permission()
86 
87 
88 class AnexoAudienciaPublicaCrud(MasterDetailCrud):
89     model = AnexoAudienciaPublica
90     parent_field = 'audiencia'
91     help_topic = 'numeracao_docsacess'
92     public = [RP_LIST, RP_DETAIL, ]
93 
94     class BaseMixin(MasterDetailCrud.BaseMixin):
95         list_field_names = ['assunto']
96 
97     class CreateView(MasterDetailCrud.CreateView):
98         form_class = AnexoAudienciaPublicaForm
99         layout_key = None
100 
101     class UpdateView(MasterDetailCrud.UpdateView):
102         form_class = AnexoAudienciaPublicaForm
103 
104     class ListView(AudienciaPublicaMixin, MasterDetailCrud.ListView):
105 
106         def get_queryset(self):
107             qs = super(MasterDetailCrud.ListView, self).get_queryset()
108             kwargs = {self.crud.parent_field: self.kwargs['pk']}
109             return qs.filter(**kwargs).order_by('-data', '-id')
110 
111     class DetailView(AudienciaPublicaMixin, MasterDetailCrud.DetailView):
112         pass
113
```

Path: `sapl/audiencia/forms.py`
Content:
```
1 import logging
2 
3 from django import forms
4 from django.core.exceptions import ObjectDoesNotExist, ValidationError
5 from django.db import transaction
6 from django.utils.translation import ugettext_lazy as _
7 
8 from crispy_forms.layout import Button, Column, Fieldset, HTML, Layout
9 
10 from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica, AnexoAudienciaPublica
11 from sapl.crispy_layout_mixin import form_actions, SaplFormHelper, SaplFormLayout, to_row
12 from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa
13 from sapl.parlamentares.models import Parlamentar
14 from sapl.utils import timezone, FileFieldCheckMixin, validar_arquivo
15 
16 class AudienciaForm(FileFieldCheckMixin, forms.ModelForm):
17     logger = logging.getLogger(__name__)
18     data_atual = timezone.now()
19 
20     tipo = forms.ModelChoiceField(
21         required=True,
22         label=_('Tipo de Audiência Pública'),
23         queryset=TipoAudienciaPublica.objects.all().order_by('nome'))
24 
25     tipo_materia = forms.ModelChoiceField(
26         label=_('Tipo Matéria'),
27         required=False,
28         queryset=TipoMateriaLegislativa.objects.all(),
29         empty_label=_('Selecione'))
30 
31     numero_materia = forms.CharField(
32         label=_('Número Matéria'),
33         required=False)
34 
35     ano_materia = forms.CharField(
36         label=_('Ano Matéria'),
37         required=False)
38 
39     materia = forms.ModelChoiceField(
40         required=False,
41         widget=forms.HiddenInput(),
42         queryset=MateriaLegislativa.objects.all())
43 
44     parlamentar_autor = forms.ModelChoiceField(
45         label=_("Parlamentar Autor"),
46         required=False,
47         queryset=Parlamentar.objects.all())
48 
49     requerimento = forms.ModelChoiceField(
50         label=_("Requerimento"),
51         required=False,
52         queryset=MateriaLegislativa.objects.select_related("tipo").filter(tipo__descricao="Requerimento"))
53 
54     class Meta:
55         model = AudienciaPublica
56         fields = ['tipo', 'numero', 'nome',
57                   'tema', 'data', 'hora_inicio', 'hora_fim',
58                   'observacao', 'audiencia_cancelada', 'parlamentar_autor', 'requerimento', 'url_audio',
59                   'url_video', 'upload_pauta', 'upload_ata',
60                   'upload_anexo', 'tipo_materia', 'numero_materia',
61                   'ano_materia', 'materia']
62 
63     def __init__(self, **kwargs):
64         super(AudienciaForm, self).__init__(**kwargs)
65 
66         tipos = []
67 
68         if not self.fields['tipo'].queryset:
69             tipos.append(TipoAudienciaPublica.objects.create(nome='Audiência Pública', tipo='A'))
70             tipos.append(TipoAudienciaPublica.objects.create(nome='Plebiscito', tipo='P'))
71             tipos.append(TipoAudienciaPublica.objects.create(nome='Referendo', tipo='R'))
72             tipos.append(TipoAudienciaPublica.objects.create(nome='Iniciativa Popular', tipo='I'))
73 
74             for t in tipos:
75                 t.save()
76 
77     def clean(self):
78         cleaned_data = super(AudienciaForm, self).clean()
79         if not self.is_valid():
80             return cleaned_data
81 
82         materia = cleaned_data['numero_materia']
83         ano_materia = cleaned_data['ano_materia']
84         tipo_materia = cleaned_data['tipo_materia']
85         parlamentar_autor = cleaned_data["parlamentar_autor"]
86         requerimento = cleaned_data["requerimento"]
87 
88         if materia and ano_materia and tipo_materia:
89             try:
90                 self.logger.debug("Tentando obter MateriaLegislativa %s nº %s/%s." % (tipo_materia, materia, ano_materia))
91                 materia = MateriaLegislativa.objects.get(
92                     numero=materia,
93                     ano=ano_materia,
94                     tipo=tipo_materia)
95             except ObjectDoesNotExist:
96                 msg = _('A matéria %s nº %s/%s não existe no cadastro'
97                         ' de matérias legislativas.' % (tipo_materia, materia, ano_materia))
98                 self.logger.warning(
99                     'A MateriaLegislativa %s nº %s/%s não existe no cadastro'
100                     ' de matérias legislativas.' % (tipo_materia, materia, ano_materia)
101                 )
102                 raise ValidationError(msg)
103             else:
104                 self.logger.info("MateriaLegislativa %s nº %s/%s obtida com sucesso." % (tipo_materia, materia, ano_materia))
105                 cleaned_data['materia'] = materia
106 
107         else:
108             campos = [materia, tipo_materia, ano_materia]
109             if campos.count(None) + campos.count('') < len(campos):
110                 msg = _('Preencha todos os campos relacionados à Matéria Legislativa')
111                 self.logger.warning(
112                     'Algum campo relacionado à MatériaLegislativa %s nº %s/%s \
113                     não foi preenchido.' % (tipo_materia, materia, ano_materia)
114                 )
115                 raise ValidationError(msg)
116 
117         if not cleaned_data['numero']:
118 
119             ultima_audiencia = AudienciaPublica.objects.all().order_by('numero').last()
120             if ultima_audiencia:
121                 cleaned_data['numero'] = ultima_audiencia.numero + 1
122             else:
123                 cleaned_data['numero'] = 1
124 
125         if self.cleaned_data['hora_inicio'] and self.cleaned_data['hora_fim']:
126             if self.cleaned_data['hora_fim'] < self.cleaned_data['hora_inicio']:
127                 msg = _('A hora de fim ({}) não pode ser anterior a hora de início({})'
128                         .format(self.cleaned_data['hora_fim'], self.cleaned_data['hora_inicio']))
129                 self.logger.warning(
130                     'Hora de fim anterior à hora de início.'
131                 )
132                 raise ValidationError(msg)
133 
134         # requerimento é optativo
135         if parlamentar_autor and requerimento:
136             if parlamentar_autor.autor.first() not in requerimento.autores.all():
137                 raise ValidationError("Parlamentar Autor selecionado não faz"
138                                       " parte da autoria do Requerimento "
139                                       "selecionado.")
140         elif parlamentar_autor:
141             raise ValidationError("Para informar um autor deve-se informar um requerimento.")
142         elif requerimento:
143             raise ValidationError("Para informar um requerimento deve-se informar um autor.")
144 
145 
146         upload_pauta = self.cleaned_data.get('upload_pauta', False)
147         upload_ata = self.cleaned_data.get('upload_ata', False)
148         upload_anexo = self.cleaned_data.get('upload_anexo', False)
149 
150         if upload_pauta:
151             validar_arquivo(upload_pauta, "Pauta da Audiência Pública")
152 
153         if upload_ata:
154             validar_arquivo(upload_ata, "Ata da Audiência Pública")
155 
156         if upload_anexo:
157             validar_arquivo(upload_anexo, "Anexo da Audiência Pública")
158 
159         return cleaned_data
160 
161 
162 class AnexoAudienciaPublicaForm(forms.ModelForm):
163 
164     class Meta:
165         model = AnexoAudienciaPublica
166         fields = ['arquivo',
167                   'assunto']
168 
169     def __init__(self, *args, **kwargs):
170 
171         row1 = to_row(
172             [('arquivo', 4)])
173 
174         row2 = to_row(
175             [('assunto', 12)])
176 
177         self.helper = SaplFormHelper()
178         self.helper.layout = SaplFormLayout(
179             Fieldset(_('Identificação Básica'),
180                      row1, row2))
181         super(AnexoAudienciaPublicaForm, self).__init__(
182             *args, **kwargs)
183 
184     def clean(self):
185         super(AnexoAudienciaPublicaForm, self).clean()
186 
187         if not self.is_valid():
188             return self.cleaned_data
189 
190         arquivo = self.cleaned_data.get('arquivo', False)
191 
192         if arquivo:
193             validar_arquivo(arquivo, "Arquivo")
194 
195         return self.cleaned_data
196
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sapl/audiencia/forms.py b/sapl/audiencia/forms.py
--- a/sapl/audiencia/forms.py
+++ b/sapl/audiencia/forms.py
@@ -115,12 +115,14 @@
                 raise ValidationError(msg)
 
         if not cleaned_data['numero']:
-
             ultima_audiencia = AudienciaPublica.objects.all().order_by('numero').last()
             if ultima_audiencia:
                 cleaned_data['numero'] = ultima_audiencia.numero + 1
             else:
                 cleaned_data['numero'] = 1
+        else:
+            if AudienciaPublica.objects.filter(numero=cleaned_data['numero']).exclude(pk=self.instance.pk).exists():
+                raise ValidationError(f"Já existe uma audiência com a numeração {cleaned_data['numero']}.")
 
         if self.cleaned_data['hora_inicio'] and self.cleaned_data['hora_fim']:
             if self.cleaned_data['hora_fim'] < self.cleaned_data['hora_inicio']:
diff --git a/sapl/audiencia/views.py b/sapl/audiencia/views.py
--- a/sapl/audiencia/views.py
+++ b/sapl/audiencia/views.py
@@ -29,15 +29,13 @@
         def get_context_data(self, **kwargs):
             context = super().get_context_data(**kwargs)
 
-            audiencia_materia = {}
-            for o in context['object_list']:
-                # indexado pelo numero da audiencia
-                audiencia_materia[str(o.numero)] = o.materia
+            audiencia_materia = {str(a.id): a.materia for a in context['object_list']}
 
             for row in context['rows']:
-                coluna_materia = row[3] # se mudar a ordem de listagem mudar aqui
+                coluna_materia = row[3]  # se mudar a ordem de listagem mudar aqui
                 if coluna_materia[0]:
-                    materia = audiencia_materia[row[0][0]]
+                    audiencia_id = row[0][1].split('/')[-1]
+                    materia = audiencia_materia[audiencia_id]
                     if materia:
                         url_materia = reverse('sapl.materia:materialegislativa_detail',
                                               kwargs={'pk': materia.id})

{"golden_diff": "diff --git a/sapl/audiencia/forms.py b/sapl/audiencia/forms.py\n--- a/sapl/audiencia/forms.py\n+++ b/sapl/audiencia/forms.py\n@@ -115,12 +115,14 @@\n                 raise ValidationError(msg)\n \n         if not cleaned_data['numero']:\n-\n             ultima_audiencia = AudienciaPublica.objects.all().order_by('numero').last()\n             if ultima_audiencia:\n                 cleaned_data['numero'] = ultima_audiencia.numero + 1\n             else:\n                 cleaned_data['numero'] = 1\n+        else:\n+            if AudienciaPublica.objects.filter(numero=cleaned_data['numero']).exclude(pk=self.instance.pk).exists():\n+                raise ValidationError(f\"J\u00e1 existe uma audi\u00eancia com a numera\u00e7\u00e3o {cleaned_data['numero']}.\")\n \n         if self.cleaned_data['hora_inicio'] and self.cleaned_data['hora_fim']:\n             if self.cleaned_data['hora_fim'] < self.cleaned_data['hora_inicio']:\ndiff --git a/sapl/audiencia/views.py b/sapl/audiencia/views.py\n--- a/sapl/audiencia/views.py\n+++ b/sapl/audiencia/views.py\n@@ -29,15 +29,13 @@\n         def get_context_data(self, **kwargs):\n             context = super().get_context_data(**kwargs)\n \n-            audiencia_materia = {}\n-            for o in context['object_list']:\n-                # indexado pelo numero da audiencia\n-                audiencia_materia[str(o.numero)] = o.materia\n+            audiencia_materia = {str(a.id): a.materia for a in context['object_list']}\n \n             for row in context['rows']:\n-                coluna_materia = row[3] # se mudar a ordem de listagem mudar aqui\n+                coluna_materia = row[3]  # se mudar a ordem de listagem mudar aqui\n                 if coluna_materia[0]:\n-                    materia = audiencia_materia[row[0][0]]\n+                    audiencia_id = row[0][1].split('/')[-1]\n+                    materia = audiencia_materia[audiencia_id]\n                     if materia:\n                         url_materia = reverse('sapl.materia:materialegislativa_detail',\n                                               kwargs={'pk': materia.id})\n", "issue": "Link de Mat\u00e9ria Legislative em Audi\u00eancia\n## Comportamento Atual\r\n<!--- Se est\u00e1 descrevendo um bug, conte-nos o que acontece em vez do comportamento esperado. -->\r\n<!--- Se est\u00e1 sugerindo uma mudan\u00e7a/melhoria, explique a diferen\u00e7a com o comportamento atual. -->\r\nQuando clica-se no link da Mat\u00e9ria Legislativa, \u00e9 redirecionado para outra Mat\u00e9ria Legislativa e n\u00e3o a com o t\u00edtulo no link\r\n\r\n## Poss\u00edvel Solu\u00e7\u00e3o\r\n<!--- N\u00e3o \u00e9 obrigat\u00f3rio, mas sugira uma poss\u00edvel corre\u00e7\u00e3o/raz\u00e3o para o bug -->\r\n<!--- ou ideias de como implementar a adi\u00e7\u00e3o/mudan\u00e7a. -->\r\nN\u00famero das audi\u00eancias est\u00e3o repetidos. Talvez isso t\u00e1 causando o bug.\n", "before_files": [{"content": "import sapl\n\nfrom django.http import HttpResponse\nfrom django.urls import reverse\nfrom django.views.decorators.clickjacking import xframe_options_exempt\nfrom django.views.generic import UpdateView\nfrom sapl.crud.base import RP_DETAIL, RP_LIST, Crud, MasterDetailCrud\n\nfrom .forms import AudienciaForm, AnexoAudienciaPublicaForm\nfrom .models import AudienciaPublica, AnexoAudienciaPublica\n\n\ndef index(request):\n    return HttpResponse(\"Audi\u00eancia  P\u00fablica\")\n\n\nclass AudienciaCrud(Crud):\n    model = AudienciaPublica\n    public = [RP_LIST, RP_DETAIL, ]\n\n    class BaseMixin(Crud.BaseMixin):\n        list_field_names = ['numero', 'nome', 'tipo', 'materia',\n                            'data'] \n        ordering = '-data', 'nome', 'numero', 'tipo'\n\n    class ListView(Crud.ListView):\n        paginate_by = 10\n\n        def get_context_data(self, **kwargs):\n            context = super().get_context_data(**kwargs)\n\n            audiencia_materia = {}\n            for o in context['object_list']:\n                # indexado pelo numero da audiencia\n                audiencia_materia[str(o.numero)] = o.materia\n\n            for row in context['rows']:\n                coluna_materia = row[3] # se mudar a ordem de listagem mudar aqui\n                if coluna_materia[0]:\n                    materia = audiencia_materia[row[0][0]]\n                    if materia:\n                        url_materia = reverse('sapl.materia:materialegislativa_detail',\n                                              kwargs={'pk': materia.id})\n                    else:\n                        url_materia = None\n                    row[3] = (coluna_materia[0], url_materia)\n            return context\n\n    class CreateView(Crud.CreateView):\n        form_class = AudienciaForm\n\n        def form_valid(self, form):\n            return super(Crud.CreateView, self).form_valid(form)\n\n    class UpdateView(Crud.UpdateView):\n        form_class = AudienciaForm\n\n        def get_initial(self):\n            initial = super(UpdateView, self).get_initial()\n            if self.object.materia:\n                initial['tipo_materia'] = self.object.materia.tipo.id\n                initial['numero_materia'] = self.object.materia.numero\n                initial['ano_materia'] = self.object.materia.ano\n            return initial\n     \n    class DeleteView(Crud.DeleteView):\n        pass\n\n    class DetailView(Crud.DetailView):\n\n        layout_key = 'AudienciaPublicaDetail'\n\n        @xframe_options_exempt\n        def get(self, request, *args, **kwargs):\n            return super().get(request, *args, **kwargs)\n\n\nclass AudienciaPublicaMixin:\n\n    def has_permission(self):\n        app_config = sapl.base.models.AppConfig.objects.last()\n        if app_config and app_config.documentos_administrativos == 'O':\n            return True\n\n        return super().has_permission()\n\n\nclass AnexoAudienciaPublicaCrud(MasterDetailCrud):\n    model = AnexoAudienciaPublica\n    parent_field = 'audiencia'\n    help_topic = 'numeracao_docsacess'\n    public = [RP_LIST, RP_DETAIL, ]\n\n    class BaseMixin(MasterDetailCrud.BaseMixin):\n        list_field_names = ['assunto']\n\n    class CreateView(MasterDetailCrud.CreateView):\n        form_class = AnexoAudienciaPublicaForm\n        layout_key = None\n\n    class UpdateView(MasterDetailCrud.UpdateView):\n        form_class = AnexoAudienciaPublicaForm\n\n    class ListView(AudienciaPublicaMixin, MasterDetailCrud.ListView):\n\n        def get_queryset(self):\n            qs = super(MasterDetailCrud.ListView, self).get_queryset()\n            kwargs = {self.crud.parent_field: self.kwargs['pk']}\n            return qs.filter(**kwargs).order_by('-data', '-id')\n\n    class DetailView(AudienciaPublicaMixin, MasterDetailCrud.DetailView):\n        pass\n", "path": "sapl/audiencia/views.py"}, {"content": "import logging\n\nfrom django import forms\nfrom django.core.exceptions import ObjectDoesNotExist, ValidationError\nfrom django.db import transaction\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom crispy_forms.layout import Button, Column, Fieldset, HTML, Layout\n\nfrom sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica, AnexoAudienciaPublica\nfrom sapl.crispy_layout_mixin import form_actions, SaplFormHelper, SaplFormLayout, to_row\nfrom sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa\nfrom sapl.parlamentares.models import Parlamentar\nfrom sapl.utils import timezone, FileFieldCheckMixin, validar_arquivo\n\nclass AudienciaForm(FileFieldCheckMixin, forms.ModelForm):\n    logger = logging.getLogger(__name__)\n    data_atual = timezone.now()\n\n    tipo = forms.ModelChoiceField(\n        required=True,\n        label=_('Tipo de Audi\u00eancia P\u00fablica'),\n        queryset=TipoAudienciaPublica.objects.all().order_by('nome'))\n\n    tipo_materia = forms.ModelChoiceField(\n        label=_('Tipo Mat\u00e9ria'),\n        required=False,\n        queryset=TipoMateriaLegislativa.objects.all(),\n        empty_label=_('Selecione'))\n\n    numero_materia = forms.CharField(\n        label=_('N\u00famero Mat\u00e9ria'),\n        required=False)\n\n    ano_materia = forms.CharField(\n        label=_('Ano Mat\u00e9ria'),\n        required=False)\n\n    materia = forms.ModelChoiceField(\n        required=False,\n        widget=forms.HiddenInput(),\n        queryset=MateriaLegislativa.objects.all())\n\n    parlamentar_autor = forms.ModelChoiceField(\n        label=_(\"Parlamentar Autor\"),\n        required=False,\n        queryset=Parlamentar.objects.all())\n\n    requerimento = forms.ModelChoiceField(\n        label=_(\"Requerimento\"),\n        required=False,\n        queryset=MateriaLegislativa.objects.select_related(\"tipo\").filter(tipo__descricao=\"Requerimento\"))\n\n    class Meta:\n        model = AudienciaPublica\n        fields = ['tipo', 'numero', 'nome',\n                  'tema', 'data', 'hora_inicio', 'hora_fim',\n                  'observacao', 'audiencia_cancelada', 'parlamentar_autor', 'requerimento', 'url_audio',\n                  'url_video', 'upload_pauta', 'upload_ata',\n                  'upload_anexo', 'tipo_materia', 'numero_materia',\n                  'ano_materia', 'materia']\n\n    def __init__(self, **kwargs):\n        super(AudienciaForm, self).__init__(**kwargs)\n\n        tipos = []\n\n        if not self.fields['tipo'].queryset:\n            tipos.append(TipoAudienciaPublica.objects.create(nome='Audi\u00eancia P\u00fablica', tipo='A'))\n            tipos.append(TipoAudienciaPublica.objects.create(nome='Plebiscito', tipo='P'))\n            tipos.append(TipoAudienciaPublica.objects.create(nome='Referendo', tipo='R'))\n            tipos.append(TipoAudienciaPublica.objects.create(nome='Iniciativa Popular', tipo='I'))\n\n            for t in tipos:\n                t.save()\n\n    def clean(self):\n        cleaned_data = super(AudienciaForm, self).clean()\n        if not self.is_valid():\n            return cleaned_data\n\n        materia = cleaned_data['numero_materia']\n        ano_materia = cleaned_data['ano_materia']\n        tipo_materia = cleaned_data['tipo_materia']\n        parlamentar_autor = cleaned_data[\"parlamentar_autor\"]\n        requerimento = cleaned_data[\"requerimento\"]\n\n        if materia and ano_materia and tipo_materia:\n            try:\n                self.logger.debug(\"Tentando obter MateriaLegislativa %s n\u00ba %s/%s.\" % (tipo_materia, materia, ano_materia))\n                materia = MateriaLegislativa.objects.get(\n                    numero=materia,\n                    ano=ano_materia,\n                    tipo=tipo_materia)\n            except ObjectDoesNotExist:\n                msg = _('A mat\u00e9ria %s n\u00ba %s/%s n\u00e3o existe no cadastro'\n                        ' de mat\u00e9rias legislativas.' % (tipo_materia, materia, ano_materia))\n                self.logger.warning(\n                    'A MateriaLegislativa %s n\u00ba %s/%s n\u00e3o existe no cadastro'\n                    ' de mat\u00e9rias legislativas.' % (tipo_materia, materia, ano_materia)\n                )\n                raise ValidationError(msg)\n            else:\n                self.logger.info(\"MateriaLegislativa %s n\u00ba %s/%s obtida com sucesso.\" % (tipo_materia, materia, ano_materia))\n                cleaned_data['materia'] = materia\n\n        else:\n            campos = [materia, tipo_materia, ano_materia]\n            if campos.count(None) + campos.count('') < len(campos):\n                msg = _('Preencha todos os campos relacionados \u00e0 Mat\u00e9ria Legislativa')\n                self.logger.warning(\n                    'Algum campo relacionado \u00e0 Mat\u00e9riaLegislativa %s n\u00ba %s/%s \\\n                    n\u00e3o foi preenchido.' % (tipo_materia, materia, ano_materia)\n                )\n                raise ValidationError(msg)\n\n        if not cleaned_data['numero']:\n\n            ultima_audiencia = AudienciaPublica.objects.all().order_by('numero').last()\n            if ultima_audiencia:\n                cleaned_data['numero'] = ultima_audiencia.numero + 1\n            else:\n                cleaned_data['numero'] = 1\n\n        if self.cleaned_data['hora_inicio'] and self.cleaned_data['hora_fim']:\n            if self.cleaned_data['hora_fim'] < self.cleaned_data['hora_inicio']:\n                msg = _('A hora de fim ({}) n\u00e3o pode ser anterior a hora de in\u00edcio({})'\n                        .format(self.cleaned_data['hora_fim'], self.cleaned_data['hora_inicio']))\n                self.logger.warning(\n                    'Hora de fim anterior \u00e0 hora de in\u00edcio.'\n                )\n                raise ValidationError(msg)\n\n        # requerimento \u00e9 optativo\n        if parlamentar_autor and requerimento:\n            if parlamentar_autor.autor.first() not in requerimento.autores.all():\n                raise ValidationError(\"Parlamentar Autor selecionado n\u00e3o faz\"\n                                      \" parte da autoria do Requerimento \"\n                                      \"selecionado.\")\n        elif parlamentar_autor:\n            raise ValidationError(\"Para informar um autor deve-se informar um requerimento.\")\n        elif requerimento:\n            raise ValidationError(\"Para informar um requerimento deve-se informar um autor.\")\n\n\n        upload_pauta = self.cleaned_data.get('upload_pauta', False)\n        upload_ata = self.cleaned_data.get('upload_ata', False)\n        upload_anexo = self.cleaned_data.get('upload_anexo', False)\n\n        if upload_pauta:\n            validar_arquivo(upload_pauta, \"Pauta da Audi\u00eancia P\u00fablica\")\n\n        if upload_ata:\n            validar_arquivo(upload_ata, \"Ata da Audi\u00eancia P\u00fablica\")\n\n        if upload_anexo:\n            validar_arquivo(upload_anexo, \"Anexo da Audi\u00eancia P\u00fablica\")\n\n        return cleaned_data\n\n\nclass AnexoAudienciaPublicaForm(forms.ModelForm):\n\n    class Meta:\n        model = AnexoAudienciaPublica\n        fields = ['arquivo',\n                  'assunto']\n\n    def __init__(self, *args, **kwargs):\n\n        row1 = to_row(\n            [('arquivo', 4)])\n\n        row2 = to_row(\n            [('assunto', 12)])\n\n        self.helper = SaplFormHelper()\n        self.helper.layout = SaplFormLayout(\n            Fieldset(_('Identifica\u00e7\u00e3o B\u00e1sica'),\n                     row1, row2))\n        super(AnexoAudienciaPublicaForm, self).__init__(\n            *args, **kwargs)\n\n    def clean(self):\n        super(AnexoAudienciaPublicaForm, self).clean()\n\n        if not self.is_valid():\n            return self.cleaned_data\n\n        arquivo = self.cleaned_data.get('arquivo', False)\n\n        if arquivo:\n            validar_arquivo(arquivo, \"Arquivo\")\n\n        return self.cleaned_data\n", "path": "sapl/audiencia/forms.py"}], "after_files": [{"content": "import sapl\n\nfrom django.http import HttpResponse\nfrom django.urls import reverse\nfrom django.views.decorators.clickjacking import xframe_options_exempt\nfrom django.views.generic import UpdateView\nfrom sapl.crud.base import RP_DETAIL, RP_LIST, Crud, MasterDetailCrud\n\nfrom .forms import AudienciaForm, AnexoAudienciaPublicaForm\nfrom .models import AudienciaPublica, AnexoAudienciaPublica\n\n\ndef index(request):\n    return HttpResponse(\"Audi\u00eancia  P\u00fablica\")\n\n\nclass AudienciaCrud(Crud):\n    model = AudienciaPublica\n    public = [RP_LIST, RP_DETAIL, ]\n\n    class BaseMixin(Crud.BaseMixin):\n        list_field_names = ['numero', 'nome', 'tipo', 'materia',\n                            'data'] \n        ordering = '-data', 'nome', 'numero', 'tipo'\n\n    class ListView(Crud.ListView):\n        paginate_by = 10\n\n        def get_context_data(self, **kwargs):\n            context = super().get_context_data(**kwargs)\n\n            audiencia_materia = {str(a.id): a.materia for a in context['object_list']}\n\n            for row in context['rows']:\n                coluna_materia = row[3]  # se mudar a ordem de listagem mudar aqui\n                if coluna_materia[0]:\n                    audiencia_id = row[0][1].split('/')[-1]\n                    materia = audiencia_materia[audiencia_id]\n                    if materia:\n                        url_materia = reverse('sapl.materia:materialegislativa_detail',\n                                              kwargs={'pk': materia.id})\n                    else:\n                        url_materia = None\n                    row[3] = (coluna_materia[0], url_materia)\n            return context\n\n    class CreateView(Crud.CreateView):\n        form_class = AudienciaForm\n\n        def form_valid(self, form):\n            return super(Crud.CreateView, self).form_valid(form)\n\n    class UpdateView(Crud.UpdateView):\n        form_class = AudienciaForm\n\n        def get_initial(self):\n            initial = super(UpdateView, self).get_initial()\n            if self.object.materia:\n                initial['tipo_materia'] = self.object.materia.tipo.id\n                initial['numero_materia'] = self.object.materia.numero\n                initial['ano_materia'] = self.object.materia.ano\n            return initial\n     \n    class DeleteView(Crud.DeleteView):\n        pass\n\n    class DetailView(Crud.DetailView):\n\n        layout_key = 'AudienciaPublicaDetail'\n\n        @xframe_options_exempt\n        def get(self, request, *args, **kwargs):\n            return super().get(request, *args, **kwargs)\n\n\nclass AudienciaPublicaMixin:\n\n    def has_permission(self):\n        app_config = sapl.base.models.AppConfig.objects.last()\n        if app_config and app_config.documentos_administrativos == 'O':\n            return True\n\n        return super().has_permission()\n\n\nclass AnexoAudienciaPublicaCrud(MasterDetailCrud):\n    model = AnexoAudienciaPublica\n    parent_field = 'audiencia'\n    help_topic = 'numeracao_docsacess'\n    public = [RP_LIST, RP_DETAIL, ]\n\n    class BaseMixin(MasterDetailCrud.BaseMixin):\n        list_field_names = ['assunto']\n\n    class CreateView(MasterDetailCrud.CreateView):\n        form_class = AnexoAudienciaPublicaForm\n        layout_key = None\n\n    class UpdateView(MasterDetailCrud.UpdateView):\n        form_class = AnexoAudienciaPublicaForm\n\n    class ListView(AudienciaPublicaMixin, MasterDetailCrud.ListView):\n\n        def get_queryset(self):\n            qs = super(MasterDetailCrud.ListView, self).get_queryset()\n            kwargs = {self.crud.parent_field: self.kwargs['pk']}\n            return qs.filter(**kwargs).order_by('-data', '-id')\n\n    class DetailView(AudienciaPublicaMixin, MasterDetailCrud.DetailView):\n        pass\n", "path": "sapl/audiencia/views.py"}, {"content": "import logging\n\nfrom django import forms\nfrom django.core.exceptions import ObjectDoesNotExist, ValidationError\nfrom django.db import transaction\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom crispy_forms.layout import Button, Column, Fieldset, HTML, Layout\n\nfrom sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica, AnexoAudienciaPublica\nfrom sapl.crispy_layout_mixin import form_actions, SaplFormHelper, SaplFormLayout, to_row\nfrom sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa\nfrom sapl.parlamentares.models import Parlamentar\nfrom sapl.utils import timezone, FileFieldCheckMixin, validar_arquivo\n\nclass AudienciaForm(FileFieldCheckMixin, forms.ModelForm):\n    logger = logging.getLogger(__name__)\n    data_atual = timezone.now()\n\n    tipo = forms.ModelChoiceField(\n        required=True,\n        label=_('Tipo de Audi\u00eancia P\u00fablica'),\n        queryset=TipoAudienciaPublica.objects.all().order_by('nome'))\n\n    tipo_materia = forms.ModelChoiceField(\n        label=_('Tipo Mat\u00e9ria'),\n        required=False,\n        queryset=TipoMateriaLegislativa.objects.all(),\n        empty_label=_('Selecione'))\n\n    numero_materia = forms.CharField(\n        label=_('N\u00famero Mat\u00e9ria'),\n        required=False)\n\n    ano_materia = forms.CharField(\n        label=_('Ano Mat\u00e9ria'),\n        required=False)\n\n    materia = forms.ModelChoiceField(\n        required=False,\n        widget=forms.HiddenInput(),\n        queryset=MateriaLegislativa.objects.all())\n\n    parlamentar_autor = forms.ModelChoiceField(\n        label=_(\"Parlamentar Autor\"),\n        required=False,\n        queryset=Parlamentar.objects.all())\n\n    requerimento = forms.ModelChoiceField(\n        label=_(\"Requerimento\"),\n        required=False,\n        queryset=MateriaLegislativa.objects.select_related(\"tipo\").filter(tipo__descricao=\"Requerimento\"))\n\n    class Meta:\n        model = AudienciaPublica\n        fields = ['tipo', 'numero', 'nome',\n                  'tema', 'data', 'hora_inicio', 'hora_fim',\n                  'observacao', 'audiencia_cancelada', 'parlamentar_autor', 'requerimento', 'url_audio',\n                  'url_video', 'upload_pauta', 'upload_ata',\n                  'upload_anexo', 'tipo_materia', 'numero_materia',\n                  'ano_materia', 'materia']\n\n    def __init__(self, **kwargs):\n        super(AudienciaForm, self).__init__(**kwargs)\n\n        tipos = []\n\n        if not self.fields['tipo'].queryset:\n            tipos.append(TipoAudienciaPublica.objects.create(nome='Audi\u00eancia P\u00fablica', tipo='A'))\n            tipos.append(TipoAudienciaPublica.objects.create(nome='Plebiscito', tipo='P'))\n            tipos.append(TipoAudienciaPublica.objects.create(nome='Referendo', tipo='R'))\n            tipos.append(TipoAudienciaPublica.objects.create(nome='Iniciativa Popular', tipo='I'))\n\n            for t in tipos:\n                t.save()\n\n    def clean(self):\n        cleaned_data = super(AudienciaForm, self).clean()\n        if not self.is_valid():\n            return cleaned_data\n\n        materia = cleaned_data['numero_materia']\n        ano_materia = cleaned_data['ano_materia']\n        tipo_materia = cleaned_data['tipo_materia']\n        parlamentar_autor = cleaned_data[\"parlamentar_autor\"]\n        requerimento = cleaned_data[\"requerimento\"]\n\n        if materia and ano_materia and tipo_materia:\n            try:\n                self.logger.debug(\"Tentando obter MateriaLegislativa %s n\u00ba %s/%s.\" % (tipo_materia, materia, ano_materia))\n                materia = MateriaLegislativa.objects.get(\n                    numero=materia,\n                    ano=ano_materia,\n                    tipo=tipo_materia)\n            except ObjectDoesNotExist:\n                msg = _('A mat\u00e9ria %s n\u00ba %s/%s n\u00e3o existe no cadastro'\n                        ' de mat\u00e9rias legislativas.' % (tipo_materia, materia, ano_materia))\n                self.logger.warning(\n                    'A MateriaLegislativa %s n\u00ba %s/%s n\u00e3o existe no cadastro'\n                    ' de mat\u00e9rias legislativas.' % (tipo_materia, materia, ano_materia)\n                )\n                raise ValidationError(msg)\n            else:\n                self.logger.info(\"MateriaLegislativa %s n\u00ba %s/%s obtida com sucesso.\" % (tipo_materia, materia, ano_materia))\n                cleaned_data['materia'] = materia\n\n        else:\n            campos = [materia, tipo_materia, ano_materia]\n            if campos.count(None) + campos.count('') < len(campos):\n                msg = _('Preencha todos os campos relacionados \u00e0 Mat\u00e9ria Legislativa')\n                self.logger.warning(\n                    'Algum campo relacionado \u00e0 Mat\u00e9riaLegislativa %s n\u00ba %s/%s \\\n                    n\u00e3o foi preenchido.' % (tipo_materia, materia, ano_materia)\n                )\n                raise ValidationError(msg)\n\n        if not cleaned_data['numero']:\n            ultima_audiencia = AudienciaPublica.objects.all().order_by('numero').last()\n            if ultima_audiencia:\n                cleaned_data['numero'] = ultima_audiencia.numero + 1\n            else:\n                cleaned_data['numero'] = 1\n        else:\n            if AudienciaPublica.objects.filter(numero=cleaned_data['numero']).exclude(pk=self.instance.pk).exists():\n                raise ValidationError(f\"J\u00e1 existe uma audi\u00eancia com a numera\u00e7\u00e3o {cleaned_data['numero']}.\")\n\n        if self.cleaned_data['hora_inicio'] and self.cleaned_data['hora_fim']:\n            if self.cleaned_data['hora_fim'] < self.cleaned_data['hora_inicio']:\n                msg = _('A hora de fim ({}) n\u00e3o pode ser anterior a hora de in\u00edcio({})'\n                        .format(self.cleaned_data['hora_fim'], self.cleaned_data['hora_inicio']))\n                self.logger.warning(\n                    'Hora de fim anterior \u00e0 hora de in\u00edcio.'\n                )\n                raise ValidationError(msg)\n\n        # requerimento \u00e9 optativo\n        if parlamentar_autor and requerimento:\n            if parlamentar_autor.autor.first() not in requerimento.autores.all():\n                raise ValidationError(\"Parlamentar Autor selecionado n\u00e3o faz\"\n                                      \" parte da autoria do Requerimento \"\n                                      \"selecionado.\")\n        elif parlamentar_autor:\n            raise ValidationError(\"Para informar um autor deve-se informar um requerimento.\")\n        elif requerimento:\n            raise ValidationError(\"Para informar um requerimento deve-se informar um autor.\")\n\n\n        upload_pauta = self.cleaned_data.get('upload_pauta', False)\n        upload_ata = self.cleaned_data.get('upload_ata', False)\n        upload_anexo = self.cleaned_data.get('upload_anexo', False)\n\n        if upload_pauta:\n            validar_arquivo(upload_pauta, \"Pauta da Audi\u00eancia P\u00fablica\")\n\n        if upload_ata:\n            validar_arquivo(upload_ata, \"Ata da Audi\u00eancia P\u00fablica\")\n\n        if upload_anexo:\n            validar_arquivo(upload_anexo, \"Anexo da Audi\u00eancia P\u00fablica\")\n\n        return cleaned_data\n\n\nclass AnexoAudienciaPublicaForm(forms.ModelForm):\n\n    class Meta:\n        model = AnexoAudienciaPublica\n        fields = ['arquivo',\n                  'assunto']\n\n    def __init__(self, *args, **kwargs):\n\n        row1 = to_row(\n            [('arquivo', 4)])\n\n        row2 = to_row(\n            [('assunto', 12)])\n\n        self.helper = SaplFormHelper()\n        self.helper.layout = SaplFormLayout(\n            Fieldset(_('Identifica\u00e7\u00e3o B\u00e1sica'),\n                     row1, row2))\n        super(AnexoAudienciaPublicaForm, self).__init__(\n            *args, **kwargs)\n\n    def clean(self):\n        super(AnexoAudienciaPublicaForm, self).clean()\n\n        if not self.is_valid():\n            return self.cleaned_data\n\n        arquivo = self.cleaned_data.get('arquivo', False)\n\n        if arquivo:\n            validar_arquivo(arquivo, \"Arquivo\")\n\n        return self.cleaned_data\n", "path": "sapl/audiencia/forms.py"}]}