Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impressao materia tramitacao- fix de erros #3628

Draft
wants to merge 3 commits into
base: 3.1.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docker/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ if [ $lack_pwd -eq 0 ]; then
# return -1
fi

# Backfilling AuditLog's JSON field
time ./manage.py backfill_auditlog &

echo "-------------------------------------"
echo "| ███████╗ █████╗ ██████╗ ██╗ |"
echo "| ██╔════╝██╔══██╗██╔══██╗██║ |"
Expand Down
44 changes: 43 additions & 1 deletion sapl/base/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from haystack.forms import ModelSearchForm

from sapl.audiencia.models import AudienciaPublica
from sapl.base.models import Autor, TipoAutor, OperadorAutor
from sapl.base.models import Autor, AuditLog, TipoAutor, OperadorAutor
from sapl.comissoes.models import Reuniao
from sapl.crispy_layout_mixin import (form_actions, to_column, to_row,
SaplFormHelper, SaplFormLayout)
Expand Down Expand Up @@ -741,6 +741,48 @@ def __init__(self, *args, **kwargs):
form_actions(label='Pesquisar')))


def get_username():
return [(u, u) for u in get_user_model().objects.all().order_by('username').values_list('username', flat=True)]


def get_models():
return [(m, m) for m in AuditLog.objects.distinct('model_name').order_by('model_name').values_list('model_name', flat=True)]


class AuditLogFilterSet(django_filters.FilterSet):
OPERATION_CHOICES = (
('U', 'Atualizado'),
('C', 'Criado'),
('D', 'Excluído'),
)

username = django_filters.ChoiceFilter(choices=get_username(), label=_('Usuário'))
object_id = django_filters.NumberFilter(label=_('Id'))
operation = django_filters.ChoiceFilter(choices=OPERATION_CHOICES, label=_('Operação'))
model_name = django_filters.ChoiceFilter(choices=get_models, label=_('Tipo de Registro'))
timestamp = django_filters.DateRangeFilter(label=_('Período'))

class Meta:
model = AuditLog
fields = ['username', 'operation', 'model_name', 'timestamp', 'object_id']

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

row0 = to_row([('username', 2),
('operation', 2),
('model_name', 4),
('object_id', 2),
('timestamp', 2)])

self.form.helper = SaplFormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Filtros'),
row0,
form_actions(label='Aplicar Filtro')))


class OperadorAutorForm(ModelForm):

class Meta:
Expand Down
38 changes: 38 additions & 0 deletions sapl/base/management/commands/backfill_auditlog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import json
import logging

from django.core.management.base import BaseCommand
from sapl.base.models import AuditLog

logger = logging.getLogger(__name__)


class Command(BaseCommand):
def handle(self, **options):
print("Backfilling AuditLog JSON Field...")
logs = AuditLog.objects.filter(data__isnull=True)
error_counter = 0
if logs:
update_list = []
for log in logs:
try:
obj = log.object[1:-1] \
if log.object.startswith('[') else log.object
data = json.loads(obj)
log.data = data
except Exception as e:
error_counter += 1
logging.error(e)
log.data = None
else:
update_list.append(log)
if len(update_list) == 1000:
AuditLog.objects.bulk_update(update_list, ['data'])
update_list = []
if update_list:
AuditLog.objects.bulk_update(update_list, ['data'])
print(f"Logs backfilled: {len(logs) - error_counter}")
print(f"Logs with errors: {error_counter}")
print("Finished backfilling")


23 changes: 23 additions & 0 deletions sapl/base/migrations/0056_auto_20221118_1330.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 2.2.28 on 2022-11-18 16:30

import django.contrib.postgres.fields.jsonb
from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('base', '0055_appconfig_mostrar_voto'),
]

operations = [
migrations.AlterModelOptions(
name='auditlog',
options={'ordering': ('-id', '-timestamp'), 'verbose_name': 'AuditLog', 'verbose_name_plural': 'AuditLogs'},
),
migrations.AddField(
model_name='auditlog',
name='data',
field=django.contrib.postgres.fields.jsonb.JSONField(null=True, verbose_name='data'),
),
]
7 changes: 5 additions & 2 deletions sapl/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,12 +419,15 @@ class AuditLog(models.Model):
db_index=True)
timestamp = models.DateTimeField(verbose_name=_('timestamp'),
db_index=True)
# DEPRECATED FIELD! TO BE REMOVED (EVENTUALLY)
object = models.CharField(max_length=MAX_DATA_LENGTH,
blank=True,
verbose_name=_('object'))
data = JSONField(null=True, verbose_name=_('data'))
object_id = models.PositiveIntegerField(verbose_name=_('object_id'),
db_index=True)
model_name = models.CharField(max_length=100, verbose_name=_('model'),
model_name = models.CharField(max_length=100,
verbose_name=_('model'),
db_index=True)
app_name = models.CharField(max_length=100,
verbose_name=_('app'),
Expand All @@ -433,7 +436,7 @@ class AuditLog(models.Model):
class Meta:
verbose_name = _('AuditLog')
verbose_name_plural = _('AuditLogs')
ordering = ('-id',)
ordering = ('-id', '-timestamp')

def __str__(self):
return "[%s] %s %s.%s %s" % (self.timestamp,
Expand Down
16 changes: 11 additions & 5 deletions sapl/base/receivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,15 @@ def audit_log_function(sender, **kwargs):
model_name = instance.__class__.__name__
app_name = instance._meta.app_label
object_id = instance.id
data = serializers.serialize('json', [instance])

if len(data) > AuditLog.MAX_DATA_LENGTH:
data = data[:AuditLog.MAX_DATA_LENGTH]
try:
import json
# [1:-1] below removes the surrounding square brackets
str_data = serializers.serialize('json', [instance])[1:-1]
data = json.loads(str_data)
except:
# old version capped string at AuditLog.MAX_DATA_LENGTH
# so there can be invalid json fields in Prod.
data = None

if user:
username = user.username
Expand All @@ -136,7 +141,8 @@ def audit_log_function(sender, **kwargs):
app_name=app_name,
timestamp=timezone.now(),
object_id=object_id,
object=data)
object='',
data=data)
except Exception as e:
logger.error('Error saving auditing log object')
logger.error(e)
Expand Down
30 changes: 30 additions & 0 deletions sapl/base/templatetags/common_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ def define(arg):
return arg


@register.simple_tag
def describe_operation(value):
if value == "C":
return "Criar"
elif value == "D":
return "Apagar"
elif value == "U":
return "Atualizar"
return ""


@register.simple_tag
def field_verbose_name(instance, field_name):
return instance._meta.get_field(field_name).verbose_name
Expand All @@ -51,6 +62,25 @@ def model_verbose_name_plural(class_name):
model = get_class(class_name)
return model._meta.verbose_name_plural


@register.filter
def obfuscate_value(value, key):
if key in ["hash", "google_recaptcha_secret_key", "password", "google_recaptcha_site_key", "hash_code"]:
return "***************"
return value


@register.filter
def desc_operation(value):
if value == "C":
return "Criado"
elif value == "D":
return "Excluido"
elif value == "U":
return "Atualizado"
return ""


@register.filter
def format_user(user):
if user.first_name:
Expand Down
4 changes: 3 additions & 1 deletion sapl/base/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from .apps import AppConfig
from .forms import LoginForm
from .views import (LoginSapl, AlterarSenha, AppConfigCrud, CasaLegislativaCrud,
HelpTopicView, LogotipoView, RelatorioAtasView,
HelpTopicView, LogotipoView, RelatorioAtasView, PesquisarAuditLogView,
RelatorioAudienciaView, RelatorioDataFimPrazoTramitacaoView, RelatorioHistoricoTramitacaoView,
RelatorioMateriasPorAnoAutorTipoView, RelatorioMateriasPorAutorView,
RelatorioMateriasTramitacaoView, RelatorioPresencaSessaoView, RelatorioReuniaoView, SaplSearchView,
Expand Down Expand Up @@ -179,6 +179,8 @@

url(r'^sistema/search/', SaplSearchView(), name='haystack_search'),

url(r'^sistema/auditlog/$', PesquisarAuditLogView.as_view(), name='pesquisar_auditlog'),

# Folhas XSLT e extras referenciadas por documentos migrados do sapl 2.5
url(r'^(sapl/)?XSLT/HTML/(?P<path>.*)$', RedirectView.as_view(
url=os.path.join(MEDIA_URL, 'sapl/public/XSLT/HTML/%(path)s'),
Expand Down
75 changes: 73 additions & 2 deletions sapl/base/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
from sapl import settings
from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica
from sapl.base.forms import (AutorForm, TipoAutorForm, AutorFilterSet, RecuperarSenhaForm,
NovaSenhaForm, UserAdminForm,
NovaSenhaForm, UserAdminForm, AuditLogFilterSet,
OperadorAutorForm, LoginForm, SaplSearchForm)
from sapl.base.models import Autor, TipoAutor, OperadorAutor
from sapl.base.models import AuditLog, Autor, TipoAutor, OperadorAutor
from sapl.comissoes.models import Comissao, Reuniao
from sapl.crud.base import CrudAux, make_pagination, Crud,\
ListWithSearchForm, MasterDetailCrud
Expand Down Expand Up @@ -2256,6 +2256,77 @@ def get_context(self):
return context


class PesquisarAuditLogView(FilterView):
model = AuditLog
filterset_class = AuditLogFilterSet
paginate_by = 20

permission_required = ('base.list_appconfig',)

def get_filterset_kwargs(self, filterset_class):
super(PesquisarAuditLogView, self).get_filterset_kwargs(
filterset_class
)

return ({
"data": self.request.GET or None,
"queryset": self.get_queryset().order_by("-id")
})

def get_context_data(self, **kwargs):
context = super(PesquisarAuditLogView, self).get_context_data(
**kwargs
)

paginator = context["paginator"]
page_obj = context["page_obj"]

qr = self.request.GET.copy()
if 'page' in qr:
del qr['page']
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr)

context.update({
"page_range": make_pagination(
page_obj.number, paginator.num_pages
),
"NO_ENTRIES_MSG": "Nenhum registro de log encontrado!",
"title": _("Pesquisar Logs de Auditoria")
})

return context

def get(self, request, *args, **kwargs):
super(PesquisarAuditLogView, self).get(request)

data = self.filterset.data

url = ''

if data:
url = '&' + str(self.request.META["QUERY_STRING"])
if url.startswith("&page"):
url = ''

resultados = self.object_list
# if 'page' in self.request.META['QUERY_STRING']:
# resultados = self.object_list
# else:
# resultados = []

context = self.get_context_data(filter=self.filterset,
object_list=resultados,
filter_url=url,
numero_res=len(resultados)
)

context['show_results'] = show_results_filter_set(
self.request.GET.copy())

return self.render_to_response(context)


class AlterarSenha(FormView):
from sapl.settings import LOGIN_URL

Expand Down
6 changes: 5 additions & 1 deletion sapl/relatorios/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
relatorio_etiqueta_protocolo, relatorio_materia,
relatorio_ordem_dia, relatorio_pauta_sessao,
relatorio_protocolo, relatorio_sessao_plenaria,
resumo_ata_pdf, relatorio_sessao_plenaria_pdf, etiqueta_materia_legislativa)
resumo_ata_pdf, relatorio_sessao_plenaria_pdf, etiqueta_materia_legislativa,
relatorio_materia_tramitacao)

app_name = AppConfig.name

Expand Down Expand Up @@ -41,4 +42,7 @@
relatorio_sessao_plenaria_pdf, name='relatorio_sessao_plenaria_pdf'),
url(r'^relatorios/(?P<pk>\d+)/etiqueta-materia-legislativa$',
etiqueta_materia_legislativa, name='etiqueta_materia_legislativa'),

url(r'^relatorios/(?P<pk>\d+)/materia-tramitacao$',
relatorio_materia_tramitacao, name='relatorio_materia_tramitacao'),
]
Loading