mirror of https://github.com/interlegis/sapl.git
committed by
GitHub
328 changed files with 9461 additions and 5803 deletions
@ -1,231 +1,65 @@ |
|||
import logging |
|||
|
|||
from django.db.models import Q |
|||
from django.forms.fields import CharField, MultiValueField |
|||
from django.forms.widgets import MultiWidget, TextInput |
|||
from django.utils import timezone |
|||
from django.utils.translation import ugettext_lazy as _ |
|||
from django_filters.filters import CharFilter, ModelChoiceFilter, DateFilter |
|||
from django.db.models.fields.files import FileField |
|||
from django.template.defaultfilters import capfirst |
|||
import django_filters |
|||
from django_filters.filters import CharFilter, NumberFilter |
|||
from django_filters.rest_framework.filterset import FilterSet |
|||
from rest_framework import serializers |
|||
|
|||
from sapl.base.models import Autor, TipoAutor |
|||
from sapl.parlamentares.models import Legislatura |
|||
from sapl.utils import generic_relations_for_model |
|||
|
|||
|
|||
class SaplGenericRelationSearchFilterSet(FilterSet): |
|||
q = CharFilter(method='filter_q') |
|||
|
|||
def filter_q(self, queryset, name, value): |
|||
|
|||
query = value.split(' ') |
|||
if query: |
|||
q = Q() |
|||
for qtext in query: |
|||
if not qtext: |
|||
continue |
|||
q_fs = Q(nome__icontains=qtext) |
|||
|
|||
order_by = [] |
|||
|
|||
for gr in generic_relations_for_model(self._meta.model): |
|||
sgr = gr[1] |
|||
for item in sgr: |
|||
if item.related_model != self._meta.model: |
|||
|
|||
continue |
|||
flag_order_by = True |
|||
for field in item.fields_search: |
|||
if flag_order_by: |
|||
flag_order_by = False |
|||
order_by.append('%s__%s' % ( |
|||
item.related_query_name(), |
|||
field[0]) |
|||
) |
|||
# if len(field) == 3 and field[2](qtext) is not |
|||
# None: |
|||
q_fs = q_fs | Q(**{'%s__%s%s' % ( |
|||
item.related_query_name(), |
|||
field[0], |
|||
field[1]): qtext if len(field) == 2 |
|||
else field[2](qtext)}) |
|||
|
|||
q = q & q_fs |
|||
|
|||
if q: |
|||
queryset = queryset.filter(q).order_by(*order_by) |
|||
|
|||
return queryset |
|||
|
|||
|
|||
class SearchForFieldWidget(MultiWidget): |
|||
from django_filters.utils import resolve_field |
|||
from sapl.sessao.models import SessaoPlenaria |
|||
|
|||
def decompress(self, value): |
|||
if value is None: |
|||
return [None, None] |
|||
return value |
|||
|
|||
def __init__(self, attrs=None): |
|||
widgets = (TextInput, TextInput) |
|||
MultiWidget.__init__(self, widgets, attrs) |
|||
class SaplFilterSetMixin(FilterSet): |
|||
|
|||
|
|||
class SearchForFieldField(MultiValueField): |
|||
widget = SearchForFieldWidget |
|||
|
|||
def __init__(self, *args, **kwargs): |
|||
fields = ( |
|||
CharField(), |
|||
CharField()) |
|||
super(SearchForFieldField, self).__init__(fields, *args, **kwargs) |
|||
|
|||
def compress(self, parameters): |
|||
if parameters: |
|||
return parameters |
|||
return None |
|||
|
|||
|
|||
class SearchForFieldFilter(CharFilter): |
|||
field_class = SearchForFieldField |
|||
|
|||
|
|||
class AutorChoiceFilterSet(SaplGenericRelationSearchFilterSet): |
|||
q = CharFilter(method='filter_q') |
|||
tipo = ModelChoiceFilter(queryset=TipoAutor.objects.all()) |
|||
o = CharFilter(method='filter_o') |
|||
|
|||
class Meta: |
|||
model = Autor |
|||
fields = ['q', |
|||
'tipo', |
|||
'nome', ] |
|||
|
|||
def filter_q(self, queryset, name, value): |
|||
return super().filter_q( |
|||
queryset, name, value).distinct('nome').order_by('nome') |
|||
|
|||
|
|||
class AutorSearchForFieldFilterSet(AutorChoiceFilterSet): |
|||
q = SearchForFieldFilter(method='filter_q') |
|||
|
|||
class Meta(AutorChoiceFilterSet.Meta): |
|||
pass |
|||
|
|||
def filter_q(self, queryset, name, value): |
|||
|
|||
value[0] = value[0].split(',') |
|||
value[1] = value[1].split(',') |
|||
|
|||
params = {} |
|||
for key, v in list(zip(value[0], value[1])): |
|||
if v in ['True', 'False']: |
|||
v = '1' if v == 'True' else '0' |
|||
params[key] = v |
|||
return queryset.filter(**params).distinct('nome').order_by('nome') |
|||
|
|||
|
|||
class AutoresPossiveisFilterSet(FilterSet): |
|||
logger = logging.getLogger(__name__) |
|||
data_relativa = DateFilter(method='filter_data_relativa') |
|||
tipo = CharFilter(method='filter_tipo') |
|||
|
|||
class Meta: |
|||
model = Autor |
|||
fields = ['data_relativa', 'tipo', ] |
|||
|
|||
def filter_data_relativa(self, queryset, name, value): |
|||
return queryset |
|||
|
|||
def filter_tipo(self, queryset, name, value): |
|||
|
|||
fields = '__all__' |
|||
filter_overrides = { |
|||
FileField: { |
|||
'filter_class': django_filters.CharFilter, |
|||
'extra': lambda f: { |
|||
'lookup_expr': 'exact', |
|||
}, |
|||
}, |
|||
} |
|||
|
|||
def filter_o(self, queryset, name, value): |
|||
try: |
|||
self.logger.debug( |
|||
"Tentando obter TipoAutor correspondente à pk {}.".format(value)) |
|||
tipo = TipoAutor.objects.get(pk=value) |
|||
return queryset.order_by( |
|||
*map(str.strip, value.split(','))) |
|||
except: |
|||
self.logger.error("TipoAutor(pk={}) inexistente.".format(value)) |
|||
raise serializers.ValidationError(_('Tipo de Autor inexistente.')) |
|||
|
|||
qs = queryset.filter(tipo=tipo) |
|||
|
|||
return qs |
|||
|
|||
@property |
|||
def qs(self): |
|||
qs = super().qs |
|||
|
|||
data_relativa = self.form.cleaned_data['data_relativa'] \ |
|||
if 'data_relativa' in self.form.cleaned_data else None |
|||
|
|||
tipo = self.form.cleaned_data['tipo'] \ |
|||
if 'tipo' in self.form.cleaned_data else None |
|||
|
|||
if not tipo: |
|||
return qs |
|||
|
|||
tipo = TipoAutor.objects.get(pk=tipo) |
|||
if not tipo.content_type: |
|||
return qs |
|||
|
|||
filter_for_model = 'filter_%s' % tipo.content_type.model |
|||
|
|||
if not hasattr(self, filter_for_model): |
|||
return qs |
|||
|
|||
if not data_relativa: |
|||
data_relativa = timezone.now() |
|||
|
|||
return getattr(self, filter_for_model)(qs, data_relativa).distinct() |
|||
|
|||
def filter_parlamentar(self, queryset, data_relativa): |
|||
# não leva em conta afastamentos |
|||
legislatura_relativa = Legislatura.objects.filter( |
|||
data_inicio__lte=data_relativa, |
|||
data_fim__gte=data_relativa).first() |
|||
|
|||
q = Q( |
|||
parlamentar_set__mandato__data_inicio_mandato__lte=data_relativa, |
|||
parlamentar_set__mandato__data_fim_mandato__isnull=True) | Q( |
|||
parlamentar_set__mandato__data_inicio_mandato__lte=data_relativa, |
|||
parlamentar_set__mandato__data_fim_mandato__gte=data_relativa) |
|||
|
|||
if legislatura_relativa.atual(): |
|||
q = q & Q(parlamentar_set__ativo=True) |
|||
|
|||
return queryset.filter(q) |
|||
return queryset |
|||
|
|||
@classmethod |
|||
def filter_for_field(cls, f, name, lookup_expr='exact'): |
|||
# Redefine método estático para ignorar filtro para |
|||
# fields que não possuam lookup_expr informado |
|||
f, lookup_type = resolve_field(f, lookup_expr) |
|||
|
|||
default = { |
|||
'field_name': name, |
|||
'label': capfirst(f.verbose_name), |
|||
'lookup_expr': lookup_expr |
|||
} |
|||
|
|||
filter_class, params = cls.filter_for_lookup( |
|||
f, lookup_type) |
|||
default.update(params) |
|||
if filter_class is not None: |
|||
return filter_class(**default) |
|||
return None |
|||
|
|||
def filter_comissao(self, queryset, data_relativa): |
|||
return queryset.filter( |
|||
Q(comissao_set__data_extincao__isnull=True, |
|||
comissao_set__data_fim_comissao__isnull=True) | |
|||
Q(comissao_set__data_extincao__gte=data_relativa, |
|||
comissao_set__data_fim_comissao__isnull=True) | |
|||
Q(comissao_set__data_extincao__gte=data_relativa, |
|||
comissao_set__data_fim_comissao__isnull=True) | |
|||
Q(comissao_set__data_extincao__isnull=True, |
|||
comissao_set__data_fim_comissao__gte=data_relativa) | |
|||
Q(comissao_set__data_extincao__gte=data_relativa, |
|||
comissao_set__data_fim_comissao__gte=data_relativa), |
|||
comissao_set__data_criacao__lte=data_relativa) |
|||
|
|||
def filter_frente(self, queryset, data_relativa): |
|||
return queryset.filter( |
|||
Q(frente_set__data_extincao__isnull=True) | |
|||
Q(frente_set__data_extincao__gte=data_relativa), |
|||
frente_set__data_criacao__lte=data_relativa) |
|||
class SessaoPlenariaFilterSet(SaplFilterSetMixin): |
|||
year = NumberFilter(method='filter_year') |
|||
month = NumberFilter(method='filter_month') |
|||
|
|||
def filter_bancada(self, queryset, data_relativa): |
|||
return queryset.filter( |
|||
Q(bancada_set__data_extincao__isnull=True) | |
|||
Q(bancada_set__data_extincao__gte=data_relativa), |
|||
bancada_set__data_criacao__lte=data_relativa) |
|||
class Meta(SaplFilterSetMixin.Meta): |
|||
model = SessaoPlenaria |
|||
|
|||
def filter_bloco(self, queryset, data_relativa): |
|||
return queryset.filter( |
|||
Q(bloco_set__data_extincao__isnull=True) | |
|||
Q(bloco_set__data_extincao__gte=data_relativa), |
|||
bloco_set__data_criacao__lte=data_relativa) |
|||
def filter_year(self, queryset, name, value): |
|||
qs = queryset.filter(data_inicio__year=value) |
|||
return qs |
|||
|
|||
def filter_orgao(self, queryset, data_relativa): |
|||
# na implementação, não havia regras a implementar para orgao |
|||
return queryset |
|||
def filter_month(self, queryset, name, value): |
|||
qs = queryset.filter(data_inicio__month=value) |
|||
return qs |
|||
|
|||
@ -0,0 +1,34 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-02-19 18:11 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.utils.timezone |
|||
import sapl.utils |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('audiencia', '0009_remove_anexoaudienciapublica_indexacao'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='anexoaudienciapublica', |
|||
name='arquivo', |
|||
field=models.FileField(default='Assunto não existente.', upload_to=sapl.utils.texto_upload_path, verbose_name='Arquivo'), |
|||
preserve_default=False, |
|||
), |
|||
migrations.AlterField( |
|||
model_name='anexoaudienciapublica', |
|||
name='assunto', |
|||
field=models.TextField(verbose_name='Assunto'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='anexoaudienciapublica', |
|||
name='data', |
|||
field=models.DateField(auto_now=True, default=django.utils.timezone.now), |
|||
preserve_default=False, |
|||
), |
|||
] |
|||
@ -1,11 +1,10 @@ |
|||
from django.conf.urls import include, url |
|||
from sapl.audiencia.views import (index, AudienciaCrud,AnexoAudienciaPublicaCrud) |
|||
from sapl.audiencia.views import (index, AudienciaCrud, AnexoAudienciaPublicaCrud) |
|||
|
|||
from .apps import AppConfig |
|||
|
|||
app_name = AppConfig.name |
|||
|
|||
urlpatterns = [ |
|||
url(r'^audiencia/', include(AudienciaCrud.get_urls() + |
|||
AnexoAudienciaPublicaCrud.get_urls())), |
|||
url(r'^audiencia/', include(AudienciaCrud.get_urls() + AnexoAudienciaPublicaCrud.get_urls())), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-02-19 11:14 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('base', '0029_remove_appconfig_relatorios_atos'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='appconfig', |
|||
name='escolher_numero_materia_proposicao', |
|||
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Indicar número da matéria a ser gerada na proposição?'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-02-15 18:25 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('base', '0029_remove_appconfig_relatorios_atos'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='appconfig', |
|||
name='protocolo_manual', |
|||
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Protocolar proposição somente com recibo?'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-02-18 14:09 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('base', '0030_appconfig_protocolo_manual'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='appconfig', |
|||
name='protocolo_manual', |
|||
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Informar data e hora de protocolo?'), |
|||
), |
|||
] |
|||
@ -0,0 +1,16 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-02-19 12:41 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('base', '0031_auto_20190218_1109'), |
|||
('base', '0030_appconfig_escolher_numero_materia_proposicao'), |
|||
] |
|||
|
|||
operations = [ |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-15 13:50 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('base', '0032_merge_20190219_0941'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='appconfig', |
|||
name='sequencia_numeracao', |
|||
field=models.CharField(choices=[('A', 'Sequencial por ano para cada autor'), ('B', 'Sequencial por ano indepententemente do autor'), ('L', 'Sequencial por legislatura'), ('U', 'Sequencial único')], default='A', max_length=1, verbose_name='Sequência de numeração'), |
|||
), |
|||
] |
|||
@ -0,0 +1,29 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-17 12:41 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('base', '0033_auto_20190415_1050'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.RemoveField( |
|||
model_name='appconfig', |
|||
name='sequencia_numeracao', |
|||
), |
|||
migrations.AddField( |
|||
model_name='appconfig', |
|||
name='sequencia_numeracao_proposicao', |
|||
field=models.CharField(choices=[('A', 'Sequencial por ano para cada autor'), ('B', 'Sequencial por ano indepententemente do autor'), ('L', 'Sequencial por legislatura'), ('U', 'Sequencial único')], default='A', max_length=1, verbose_name='Sequência de numeração de proposições'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='appconfig', |
|||
name='sequencia_numeracao_protocolo', |
|||
field=models.CharField(choices=[('A', 'Sequencial por ano para cada autor'), ('L', 'Sequencial por legislatura'), ('U', 'Sequencial único')], default='A', max_length=1, verbose_name='Sequência de numeração de protocolos'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-17 13:09 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('base', '0034_auto_20190417_0941'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='appconfig', |
|||
name='sequencia_numeracao_proposicao', |
|||
field=models.CharField(choices=[('A', 'Sequencial por ano para cada autor'), ('B', 'Sequencial por ano indepententemente do autor')], default='A', max_length=1, verbose_name='Sequência de numeração de proposições'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-17 17:32 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('base', '0035_auto_20190417_1009'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='appconfig', |
|||
name='sequencia_numeracao_protocolo', |
|||
field=models.CharField(choices=[('A', 'Sequencial por ano'), ('L', 'Sequencial por legislatura'), ('U', 'Sequencial único')], default='A', max_length=1, verbose_name='Sequência de numeração de protocolos'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-03-26 18:59 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0010_auto_20181004_1939'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='tipotextoarticulado', |
|||
name='rodape_global', |
|||
field=models.TextField(default='', help_text='A cada Tipo de Texto Articulado pode ser adicionado uma nota global de rodapé!', verbose_name='Rodapé Global'), |
|||
), |
|||
] |
|||
@ -0,0 +1,27 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.13 on 2018-03-19 13:41 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
def adjust_bug_auto_inserido(apps, schema_editor): |
|||
Dispositivo = apps.get_model('compilacao', 'Dispositivo') |
|||
|
|||
Dispositivo.objects.filter( |
|||
tipo_dispositivo__class_css__startswith='caput', |
|||
dispositivo_pai__tipo_dispositivo__class_css__startswith='artigo', |
|||
auto_inserido=False |
|||
).update(auto_inserido=True) |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0011_tipotextoarticulado_rodape_global'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.RunPython(adjust_bug_auto_inserido), |
|||
] |
|||
@ -0,0 +1,315 @@ |
|||
import unicodedata |
|||
from datetime import datetime |
|||
|
|||
import oaipmh |
|||
import oaipmh.error |
|||
import oaipmh.metadata |
|||
import oaipmh.server |
|||
from django.urls import reverse |
|||
from lxml import etree |
|||
from lxml.builder import ElementMaker |
|||
|
|||
from sapl.base.models import AppConfig, CasaLegislativa |
|||
from sapl.lexml.models import LexmlPublicador, LexmlProvedor |
|||
from sapl.norma.models import NormaJuridica |
|||
from sapl.utils import LISTA_DE_UFS |
|||
|
|||
|
|||
class OAILEXML: |
|||
""" |
|||
Padrao OAI do LeXML |
|||
Esta registrado sobre o nome 'oai_lexml' |
|||
""" |
|||
|
|||
def __init__(self, prefix): |
|||
self.prefix = prefix |
|||
self.ns = {'oai_lexml': 'http://www.lexml.gov.br/oai_lexml', } |
|||
self.schemas = {'oai_lexml': 'http://projeto.lexml.gov.br/esquemas/oai_lexml.xsd'} |
|||
|
|||
def __call__(self, element, metadata): |
|||
data = metadata.record |
|||
if data.get('metadata'): |
|||
value = etree.XML(data['metadata']) |
|||
element.append(value) |
|||
|
|||
|
|||
class OAIServer: |
|||
""" |
|||
An OAI-2.0 compliant oai server. |
|||
Underlying code is based on pyoai's oaipmh.server' |
|||
""" |
|||
|
|||
XSI_NS = 'http://www.w3.org/2001/XMLSchema-instance' |
|||
ns = {'lexml': 'http://www.lexml.gov.br/oai_lexml'} |
|||
schema = {'oai_lexml': 'http://projeto.lexml.gov.br/esquemas/oai_lexml.xsd'} |
|||
|
|||
def __init__(self, config={}): |
|||
self.config = config |
|||
|
|||
def identify(self): |
|||
result = oaipmh.common.Identify( |
|||
repositoryName=self.config['titulo'], |
|||
baseURL=self.config['base_url'], |
|||
protocolVersion='2.0', |
|||
adminEmails=self.config['email'], |
|||
earliestDatestamp=datetime(2001, 1, 1, 10, 00), |
|||
deletedRecord='transient', |
|||
granularity='YYYY-MM-DDThh:mm:ssZ', |
|||
compression=['identity'], |
|||
toolkit_description=False) |
|||
if self.config.get('descricao'): |
|||
result.add_description(self.config['descricao']) |
|||
return result |
|||
|
|||
def create_header_and_metadata(self, record): |
|||
header = self.create_header(record) |
|||
metadata = oaipmh.common.Metadata(None, record['metadata']) |
|||
metadata.record = record |
|||
return header, metadata |
|||
|
|||
def list_query(self, from_=None, until=None, offset=0, batch_size=10, identifier=None): |
|||
if identifier: |
|||
identifier = int(identifier.split('/')[-1]) # Get internal id |
|||
else: |
|||
identifier = '' |
|||
until = datetime.now() if not until or until > datetime.now() else until |
|||
return self.oai_query(offset=offset, batch_size=batch_size, from_=from_, until=until, |
|||
identifier=identifier) |
|||
|
|||
def check_metadata_prefix(self, metadata_prefix): |
|||
if not metadata_prefix in self.config['metadata_prefixes']: |
|||
raise oaipmh.error.CannotDisseminateFormatError |
|||
|
|||
def listRecords(self, metadataPrefix, from_=None, until=None, cursor=0, batch_size=10): |
|||
self.check_metadata_prefix(metadataPrefix) |
|||
for record in self.list_query(from_, until, cursor, batch_size): |
|||
header, metadata = self.create_header_and_metadata(record) |
|||
yield header, metadata, None # None? |
|||
|
|||
def get_oai_id(self, internal_id): |
|||
return "oai:{}".format(internal_id) |
|||
|
|||
def create_header(self, record): |
|||
oai_id = self.get_oai_id(record['record']['id']) |
|||
timestamp = record['record']['when_modified'] if record['record']['when_modified'] else datetime.now() |
|||
timestamp = timestamp.replace(tzinfo=None) |
|||
sets = [] |
|||
deleted = record['record']['deleted'] |
|||
return oaipmh.common.Header(None, oai_id, timestamp, sets, deleted) |
|||
|
|||
def get_esfera_federacao(self): |
|||
appconfig = AppConfig.objects.first() |
|||
return appconfig.esfera_federacao |
|||
|
|||
def recupera_norma(self, offset, batch_size, from_, until, identifier, esfera): |
|||
kwargs = {'data__lte': until} |
|||
if from_: |
|||
kwargs['data__gte'] = from_ |
|||
if identifier: |
|||
kwargs['numero'] = identifier |
|||
if esfera: |
|||
kwargs['esfera_federacao'] = esfera |
|||
return NormaJuridica.objects.select_related('tipo').filter(**kwargs)[offset:offset + batch_size] |
|||
|
|||
def monta_id(self, norma): |
|||
if norma: |
|||
num = len(casa.endereco_web.split('.')) |
|||
dominio = '.'.join(casa.endereco_web.split('.')[1:num]) |
|||
prefixo_oai = '{}.{}:sapl/'.format(casa.sigla.lower(), dominio) |
|||
numero_interno = norma.numero |
|||
tipo_norma = norma.tipo.equivalente_lexml |
|||
ano_norma = norma.ano |
|||
identificador = '{}{};{};{}'.format(prefixo_oai, tipo_norma, ano_norma, numero_interno) |
|||
return identificador |
|||
else: |
|||
return None |
|||
|
|||
@staticmethod |
|||
def remove_acentos(linha): |
|||
res = unicodedata.normalize('NFKD', linha).encode('ASCII', 'ignore') |
|||
res = res.decode("UTF-8") |
|||
remove_list = ["\'", "\"", "-"] |
|||
for i in remove_list: |
|||
res = res.replace(i, "") |
|||
return res |
|||
|
|||
def monta_urn(self, norma, esfera): |
|||
if norma: |
|||
urn = 'urn:lex:br;' |
|||
esferas = {'M': 'municipal', 'E': 'estadual'} |
|||
municipio = self.remove_acentos(casa.municipio.lower()) |
|||
uf_map = dict(LISTA_DE_UFS) |
|||
uf_desc = uf_map.get(casa.uf.upper(), '').lower() |
|||
uf_desc = self.remove_acentos(uf_desc) |
|||
for x in [' ', '.de.', '.da.', '.das.', '.do.', '.dos.']: |
|||
municipio = municipio.replace(x, '.') |
|||
uf_desc = uf_desc.replace(x, '.') |
|||
if esfera == 'M': |
|||
urn += '{};{}:'.format(uf_desc, municipio) |
|||
if norma.tipo.equivalente_lexml == 'regimento.interno' or norma.tipo.equivalente_lexml == 'resolucao': |
|||
urn += 'camara.' |
|||
urn += esferas[esfera] + ':' |
|||
elif esfera == 'E': |
|||
urn += '{}:{}:'.format(uf_desc, esferas[esfera]) |
|||
else: |
|||
urn += ':' |
|||
if norma.tipo.equivalente_lexml: |
|||
urn += '{}:{};'.format(norma.tipo.equivalente_lexml, norma.data.isoformat()) |
|||
else: |
|||
urn += '{};'.format(norma.data.isoformat()) |
|||
if norma.tipo.equivalente_lexml == 'lei.organica' or norma.tipo.equivalente_lexml == 'constituicao': |
|||
urn += str(norma.ano) |
|||
else: |
|||
urn += str(norma.numero) |
|||
if norma.data_vigencia and norma.data_publicacao: |
|||
urn += '@{};publicacao;{}'.format(norma.data_vigencia.isoformat(), norma.data_publicacao.isoformat()) |
|||
elif norma.data_publicacao: |
|||
urn += '@inicio.vigencia;publicacao;{}'.format(norma.data_publicacao.isoformat()) |
|||
return urn |
|||
else: |
|||
return None |
|||
|
|||
def data_por_extenso(self, data): |
|||
data = data.strftime('%d-%m-%Y') |
|||
if data != '': |
|||
meses = {1: 'Janeiro', 2: 'Fevereiro', 3: 'Março', 4: 'Abril', 5: 'Maio', 6: 'Junho', 7: 'Julho', |
|||
8: 'Agosto', 9: 'Setembro', 10: 'Outubro', 11: 'Novembro', 12: 'Dezembro'} |
|||
return '{} de {} de {}'.format(data[0:2], meses[int(data[3:5])], data[6:]) |
|||
else: |
|||
return '' |
|||
|
|||
def monta_xml(self, urn, norma): |
|||
BASE_URL_SAPL = self.config['base_url'] |
|||
BASE_URL_SAPL = BASE_URL_SAPL[:BASE_URL_SAPL.find('/', 8)] |
|||
|
|||
publicador = LexmlPublicador.objects.first() |
|||
if norma and publicador: |
|||
LEXML = ElementMaker(namespace=self.ns['lexml'], nsmap=self.ns) |
|||
oai_lexml = LEXML.LexML() |
|||
oai_lexml.attrib['{{{pre}}}schemaLocation'.format(pre=self.XSI_NS)] = '{} {}'.format( |
|||
'http://www.lexml.gov.br/oai_lexml', 'http://projeto.lexml.gov.br/esquemas/oai_lexml.xsd') |
|||
texto_integral = norma.texto_integral |
|||
mime_types = {'doc': 'application/msword', |
|||
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', |
|||
'odt': 'application/vnd.oasis.opendocument.text', |
|||
'pdf': 'application/pdf', |
|||
'rtf': 'application/rtf'} |
|||
|
|||
if texto_integral: |
|||
url_conteudo = BASE_URL_SAPL + texto_integral.url |
|||
extensao = texto_integral.url.split('.')[-1] |
|||
formato = mime_types.get(extensao, 'application/octet-stream') |
|||
else: |
|||
formato = 'text/html' |
|||
url_conteudo = BASE_URL_SAPL + reverse('sapl.norma:normajuridica_detail', |
|||
kwargs={'pk': norma.pk}) |
|||
element_maker = ElementMaker() |
|||
id_publicador = str(publicador.id_publicador) |
|||
item_conteudo = element_maker.Item(url_conteudo, formato=formato, idPublicador=id_publicador, |
|||
tipo='conteudo') |
|||
oai_lexml.append(item_conteudo) |
|||
url = BASE_URL_SAPL + reverse('sapl.norma:normajuridica_detail', kwargs={'pk': norma.pk}) |
|||
item_metadado = element_maker.Item(url, formato='text/html', idPublicador=id_publicador, tipo='metadado') |
|||
oai_lexml.append(item_metadado) |
|||
documento_individual = element_maker.DocumentoIndividual(urn) |
|||
oai_lexml.append(documento_individual) |
|||
if norma.tipo.equivalente_lexml == 'lei.organica': |
|||
epigrafe = '{} de {} - {}, de {}'.format(norma.tipo.descricao, casa.municipio, |
|||
casa.uf, norma.ano) |
|||
elif norma.tipo.equivalente_lexml == 'constituicao': |
|||
epigrafe = '{} do Estado de {}, de {}'.format(norma.tipo.descricao, casa.municipio, |
|||
norma.ano) |
|||
else: |
|||
epigrafe = '{} n° {}, de {}'.format(norma.tipo.descricao, norma.numero, |
|||
self.data_por_extenso(norma.data)) |
|||
oai_lexml.append(element_maker.Epigrafe(epigrafe)) |
|||
oai_lexml.append(element_maker.Ementa(norma.ementa)) |
|||
indexacao = norma.indexacao |
|||
if indexacao: |
|||
oai_lexml.append(element_maker.Indexacao(indexacao)) |
|||
return etree.tostring(oai_lexml) |
|||
else: |
|||
return None |
|||
|
|||
def oai_query(self, offset=0, batch_size=10, from_=None, until=None, identifier=None): |
|||
esfera = self.get_esfera_federacao() |
|||
offset = 0 if offset < 0 else offset |
|||
batch_size = 10 if batch_size < 0 else batch_size |
|||
until = datetime.now() if not until or until > datetime.now() else until |
|||
normas = self.recupera_norma(offset, batch_size, from_, until, identifier, esfera) |
|||
for norma in normas: |
|||
resultado = {} |
|||
identificador = self.monta_id(norma) |
|||
urn = self.monta_urn(norma, esfera) |
|||
xml_lexml = self.monta_xml(urn, norma) |
|||
resultado['tx_metadado_xml'] = xml_lexml |
|||
resultado['cd_status'] = 'N' |
|||
resultado['id'] = identificador |
|||
resultado['when_modified'] = norma.timestamp |
|||
resultado['deleted'] = 0 |
|||
yield {'record': resultado, |
|||
'metadata': resultado['tx_metadado_xml']} |
|||
|
|||
|
|||
def OAIServerFactory(config={}): |
|||
""" |
|||
Create a new OAI batching OAI Server given a config and a database |
|||
""" |
|||
for prefix in config['metadata_prefixes']: |
|||
metadata_registry = oaipmh.metadata.MetadataRegistry() |
|||
metadata_registry.registerWriter(prefix, OAILEXML(prefix)) |
|||
return oaipmh.server.BatchingServer( |
|||
OAIServer(config), |
|||
metadata_registry=metadata_registry, |
|||
resumption_batch_size=config['batch_size'] |
|||
) |
|||
|
|||
|
|||
casa = None |
|||
|
|||
|
|||
def casa_legislativa(): |
|||
global casa |
|||
if not casa: |
|||
casa = CasaLegislativa.objects.first() |
|||
return casa if casa else CasaLegislativa() # retorna objeto dummy |
|||
|
|||
|
|||
def get_xml_provedor(): |
|||
""" antigo get_descricao_casa() """ |
|||
descricao = '' |
|||
provedor = LexmlProvedor.objects.first() |
|||
if provedor: |
|||
descricao = provedor.xml |
|||
if descricao: |
|||
descricao = descricao.encode('utf-8') |
|||
return descricao |
|||
|
|||
|
|||
def get_config(url, batch_size): |
|||
config = {'content_type': None, |
|||
'delay': 0, |
|||
'base_asset_path': None, |
|||
'metadata_prefixes': ['oai_lexml'], |
|||
'titulo': casa_legislativa().nome, # Inicializa variável global casa |
|||
'email': [casa.email], # lista de e-mails, antigo `def get_email()` |
|||
'base_url': url[:url.find('/', 8)] + reverse('sapl.lexml:lexml_endpoint')[:-4], # remove '/oai' suffix |
|||
'descricao': get_xml_provedor(), |
|||
'batch_size': batch_size |
|||
} |
|||
return config |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
""" |
|||
Para executar localmente (estando no diretório raiz): |
|||
|
|||
$ ./manage.py shell_plus |
|||
|
|||
Executar comando |
|||
%run sapl/lexml/OAIServer.py |
|||
""" |
|||
oai_server = OAIServerFactory(get_config('http://127.0.0.1:8000/', 10)) |
|||
r = oai_server.handleRequest({'verb': 'ListRecords', |
|||
'metadataPrefix': 'oai_lexml'}) |
|||
print(r.decode('UTF-8')) |
|||
@ -1,6 +1,35 @@ |
|||
from sapl.crud.base import CrudAux |
|||
from django.http import HttpResponse |
|||
from django.shortcuts import render |
|||
|
|||
from sapl.crud.base import CrudAux, Crud |
|||
from sapl.lexml.OAIServer import OAIServerFactory, get_config |
|||
from sapl.rules import RP_DETAIL, RP_LIST |
|||
|
|||
from .models import LexmlProvedor, LexmlPublicador |
|||
|
|||
LexmlProvedorCrud = CrudAux.build(LexmlProvedor, 'lexml_provedor') |
|||
LexmlPublicadorCrud = CrudAux.build(LexmlPublicador, 'lexml_publicador') |
|||
|
|||
|
|||
class LexmlProvedorCrud(Crud): |
|||
model = LexmlProvedor |
|||
help_topic = 'lexml_provedor' |
|||
public = [RP_LIST, RP_DETAIL] |
|||
|
|||
class DetailView(Crud.DetailView): |
|||
layout_key = 'LexmlProvedorDetail' |
|||
|
|||
|
|||
def lexml_request(request): |
|||
request_dict = request.GET.copy() |
|||
if request_dict.get('batch_size'): |
|||
del request_dict['batch_size'] |
|||
|
|||
config = get_config(request.get_raw_uri(), int(request.GET.get('batch_size', '10'))) |
|||
oai_server = OAIServerFactory(config) |
|||
r = oai_server.handleRequest(request_dict) |
|||
response = r.decode('UTF-8') |
|||
return HttpResponse(response, content_type='text/xml') |
|||
|
|||
|
|||
def request_search(request, keyword): |
|||
return render(request, "lexml/resultado-pesquisa.html", {"keyword": keyword}) |
|||
|
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-02-15 11:10 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('materia', '0040_auto_20190211_1602'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='proposicao', |
|||
name='numero_materia_futuro', |
|||
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Número Matéria'), |
|||
), |
|||
] |
|||
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-03-20 11:26 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('materia', '0041_proposicao_numero_materia_futuro'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='tipomaterialegislativa', |
|||
name='sequencia_regimental', |
|||
field=models.PositiveIntegerField( |
|||
default=0, help_text='A sequência regimental diz respeito ao que define o regimento da Casa Legislativa sobre qual a ordem de entrada das proposições nas Sessões Plenárias.', verbose_name='Sequência Regimental'), |
|||
), |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-03-20 20:49 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('materia', '0042_tipomaterialegislativa_sequencia_regimental'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='tipomaterialegislativa', |
|||
options={'ordering': ['sequencia_regimental', 'descricao'], 'verbose_name': 'Tipo de Matéria Legislativa', 'verbose_name_plural': 'Tipos de Matérias Legislativas'}, |
|||
), |
|||
] |
|||
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-03-27 17:09 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import sapl.materia.models |
|||
import sapl.utils |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('materia', '0043_auto_20190320_1749'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='documentoacessorio', |
|||
name='arquivo', |
|||
field=models.FileField(blank=True, max_length=255, null=True, upload_to=sapl.materia.models.anexo_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], verbose_name='Texto Integral'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-15 13:50 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('materia', '0044_auto_20190327_1409'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='tipomaterialegislativa', |
|||
name='sequencia_numeracao', |
|||
field=models.CharField(blank=True, choices=[('A', 'Sequencial por ano para cada autor'), ('B', 'Sequencial por ano indepententemente do autor'), ('L', 'Sequencial por legislatura'), ('U', 'Sequencial único')], max_length=1, verbose_name='Sequência de numeração'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-17 12:41 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('materia', '0045_auto_20190415_1050'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='tipomaterialegislativa', |
|||
name='sequencia_numeracao', |
|||
field=models.CharField(blank=True, choices=[('A', 'Sequencial por ano para cada autor'), ('L', 'Sequencial por legislatura'), ('U', 'Sequencial único')], max_length=1, verbose_name='Sequência de numeração'), |
|||
), |
|||
] |
|||
@ -0,0 +1,28 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-17 15:12 |
|||
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), |
|||
('materia', '0045_auto_20190415_1050'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='tramitacao', |
|||
name='ip', |
|||
field=models.CharField(blank=True, default='', max_length=30, verbose_name='IP'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='tramitacao', |
|||
name='user', |
|||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Usuário'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-17 17:32 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('materia', '0046_auto_20190417_0941'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='tipomaterialegislativa', |
|||
name='sequencia_numeracao', |
|||
field=models.CharField(blank=True, choices=[('A', 'Sequencial por ano'), ('L', 'Sequencial por legislatura'), ('U', 'Sequencial único')], max_length=1, verbose_name='Sequência de numeração'), |
|||
), |
|||
] |
|||
@ -0,0 +1,16 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-26 11:28 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('materia', '0046_auto_20190417_1212'), |
|||
('materia', '0047_auto_20190417_1432'), |
|||
] |
|||
|
|||
operations = [ |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-02-19 18:35 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('norma', '0022_auto_20190108_1606'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='normarelacionada', |
|||
options={'ordering': ('norma_principal__ano', 'norma_relacionada__ano'), 'verbose_name': 'Norma Relacionada', 'verbose_name_plural': 'Normas Relacionadas'}, |
|||
), |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-25 12:17 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('norma', '0023_auto_20190219_1535'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='normarelacionada', |
|||
options={'ordering': ('norma_principal__data', 'norma_relacionada__data'), 'verbose_name': 'Norma Relacionada', 'verbose_name_plural': 'Normas Relacionadas'}, |
|||
), |
|||
] |
|||
@ -0,0 +1,37 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-30 11:28 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('parlamentares', '0025_auto_20180924_1724'), |
|||
('sessao', '0039_auto_20190430_0825') |
|||
] |
|||
|
|||
state_operations = [ |
|||
migrations.CreateModel( |
|||
name='Bloco', |
|||
fields=[ |
|||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|||
('nome', models.CharField(max_length=80, verbose_name='Nome do Bloco')), |
|||
('data_criacao', models.DateField(null=True, verbose_name='Data Criação')), |
|||
('data_extincao', models.DateField(blank=True, null=True, verbose_name='Data Dissolução')), |
|||
('descricao', models.TextField(blank=True, verbose_name='Descrição')), |
|||
('partidos', models.ManyToManyField(blank=True, to='parlamentares.Partido', verbose_name='Partidos')), |
|||
], |
|||
options={ |
|||
'db_table': 'parlamentares_bloco', |
|||
'verbose_name': 'Bloco Parlamentar', |
|||
'verbose_name_plural': 'Blocos Parlamentares', |
|||
}, |
|||
bases=(models.Model,), |
|||
), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.SeparateDatabaseAndState(state_operations=state_operations) |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-30 11:39 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('parlamentares', '0026_bloco'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelTable( |
|||
name='bloco', |
|||
table=None, |
|||
), |
|||
] |
|||
@ -0,0 +1,35 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-03-14 18:32 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('protocoloadm', '0017_merge_20190121_1552'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.CreateModel( |
|||
name='Anexado', |
|||
fields=[ |
|||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|||
('data_anexacao', models.DateField(verbose_name='Data Anexação')), |
|||
('data_desanexacao', models.DateField(blank=True, null=True, verbose_name='Data Desanexação')), |
|||
('documento_anexado', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documento_anexado_set', to='protocoloadm.DocumentoAdministrativo', verbose_name='Documento Anexado')), |
|||
('documento_principal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documento_principal_set', to='protocoloadm.DocumentoAdministrativo', verbose_name='Documento Principal')), |
|||
], |
|||
options={ |
|||
'verbose_name': 'Anexado', |
|||
'verbose_name_plural': 'Anexados', |
|||
}, |
|||
), |
|||
migrations.AddField( |
|||
model_name='documentoadministrativo', |
|||
name='anexados', |
|||
field=models.ManyToManyField(blank=True, related_name='anexo_de', through='protocoloadm.Anexado', to='protocoloadm.DocumentoAdministrativo'), |
|||
), |
|||
] |
|||
@ -0,0 +1,28 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-26 11:33 |
|||
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), |
|||
('protocoloadm', '0018_auto_20190314_1532'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='tramitacaoadministrativo', |
|||
name='ip', |
|||
field=models.CharField(blank=True, default='', max_length=30, verbose_name='IP'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='tramitacaoadministrativo', |
|||
name='user', |
|||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Usuário'), |
|||
), |
|||
] |
|||
@ -0,0 +1,25 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-29 11:28 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('protocoloadm', '0018_auto_20190314_1532'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='tramitacaoadministrativo', |
|||
name='urgente', |
|||
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Urgente ?'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='tramitacaoadministrativo', |
|||
name='texto', |
|||
field=models.TextField(verbose_name='Texto da Ação'), |
|||
), |
|||
] |
|||
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-29 12:15 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.utils.timezone |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('protocoloadm', '0019_auto_20190429_0828'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='tramitacaoadministrativo', |
|||
name='timestamp', |
|||
field=models.DateTimeField(default=django.utils.timezone.now), |
|||
), |
|||
] |
|||
@ -0,0 +1,16 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-29 18:31 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('protocoloadm', '0020_tramitacaoadministrativo_timestamp'), |
|||
('protocoloadm', '0019_auto_20190426_0833'), |
|||
] |
|||
|
|||
operations = [ |
|||
] |
|||
@ -0,0 +1,25 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-02-28 21:03 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('sessao', '0032_merge_20181122_1527'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='resumoordenacao', |
|||
name='decimo_segundo', |
|||
field=models.CharField(default='Votos Nominais Mat Expediente', max_length=30), |
|||
), |
|||
migrations.AddField( |
|||
model_name='resumoordenacao', |
|||
name='decimo_terceiro', |
|||
field=models.CharField(default='Votos Nominais Mat Ordem Dia', max_length=30), |
|||
), |
|||
] |
|||
@ -0,0 +1,34 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-03-26 16:14 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
import sapl.sessao.models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('parlamentares', '0025_auto_20180924_1724'), |
|||
('sessao', '0033_auto_20190228_1803'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.CreateModel( |
|||
name='OradorOrdemDia', |
|||
fields=[ |
|||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|||
('numero_ordem', models.PositiveIntegerField(verbose_name='Ordem de pronunciamento')), |
|||
('url_discurso', models.URLField(blank=True, max_length=150, verbose_name='URL Vídeo')), |
|||
('observacao', models.CharField(blank=True, max_length=150, verbose_name='Observação')), |
|||
('upload_anexo', models.FileField(blank=True, null=True, upload_to=sapl.sessao.models.anexo_upload_path, verbose_name='Anexo do Orador')), |
|||
('parlamentar', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='parlamentares.Parlamentar', verbose_name='Parlamentar')), |
|||
('sessao_plenaria', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sessao.SessaoPlenaria')), |
|||
], |
|||
options={ |
|||
'verbose_name_plural': 'Oradores da Ordem do Dia', |
|||
'verbose_name': 'Orador da Ordem do Dia', |
|||
}, |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-03-26 18:14 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('sessao', '0034_oradorordemdia'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='resumoordenacao', |
|||
name='decimo_quarto', |
|||
field=models.CharField(default='Oradores da Ordem do Dia', max_length=30), |
|||
), |
|||
] |
|||
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11.20 on 2019-04-12 14:06 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('sessao', '0035_resumoordenacao_decimo_quarto'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='expedientesessao', |
|||
name='sessao_plenaria', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='expedientesessao_set', to='sessao.SessaoPlenaria'), |
|||
), |
|||
] |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue