Browse Source

Alocação das equipes em eventos

pull/159/head
Sesostris Vieira 3 years ago
parent
commit
65a7247597
  1. 83
      sigi/apps/eventos/templates/eventos/alocacao_equipe.html
  2. 73
      sigi/apps/eventos/templates/eventos/alocacao_equipe_pdf.html
  3. 17
      sigi/apps/eventos/templates/eventos/alocacao_equipe_snippet.html
  4. 44
      sigi/apps/eventos/templates/eventos/snippets/alocacao_equipe_snippet.html
  5. 3
      sigi/apps/eventos/urls.py
  6. 269
      sigi/apps/eventos/views.py
  7. 2
      sigi/menu_conf.yaml

83
sigi/apps/eventos/templates/eventos/alocacao_equipe.html

@ -1,16 +1,21 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static %}
{% load static from staticfiles %}
{% load thumbnail %}
{% load static i18n %}
{% block extrastyle %}
<style type="text/css">
th { vertical-align: bottom !important; text-align: center !important; background-color: #f1f1f1; }
td { width: 6%; vertical-align: bottom !important; }
td:first-child { width: 22%; font-weight: bolder; }
td:last-child { font-weight: bolder; }
</style>
{{ block.super }}
{{ block.super }}
<style type="text/css">
.table-responsive {
overflow: auto;
width: 100%;
}
table {
width: auto;
}
table.fixed {
table-layout: fixed;
}
</style>
<link rel="stylesheet" type="text/css" href="/static/css/calendario.css">
{% endblock %}
{% block extrahead %}
@ -19,20 +24,56 @@
{% block coltype %}colMS{% endblock %}
{% block content_title %}<h1>{% blocktrans %}Alocação de equipe em {{ ano_pesquisa }}{% endblocktrans %}</h1>{% endblock %}
{% block object-tools-items %}
{% if prev_button %}
<li><a href="?ano={{ prev_button.ano|safe }}">{% trans "Ano anterior" %}</a></li>
{% block content_title %}
{% if mes_pesquisa %}
{% for mes in meses %}
{% if forloop.counter == mes_pesquisa %}
<h5>{% blocktrans with ano=ano_pesquisa|safe mes=mes %}Alocação de equipe em {{ mes }} de {{ ano }}{% endblocktrans %}</h5>
{% endif %}
{% endfor %}
{% else %}
<h5>{% blocktrans with ano=ano_pesquisa|safe %}Alocação de equipe em {{ ano }}{% endblocktrans %}</h5>
{% endif %}
{% if next_button %}
<li><a href="?ano={{ next_button.ano|safe }}">{% trans "Próximo ano" %}</a></li>
{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs">
{% for ano in anos %}
<a class="btn-flat btn-small{% if ano == ano_pesquisa and not mes_pesquisa %} disabled{% endif %}" href="?ano={{ ano|safe }}">{{ ano|safe }}</a>
{% endfor %}
</div>
{% if mes_pesquisa %}
<div class="breadcrumbs">
{% for mes in meses %}
<a class="btn-flat btn-small" href="?ano={{ ano_pesquisa|safe }}&mes={{ forloop.counter|safe }}">{{ mes|safe }}</a>
{% endfor %}
</div>
{% endif %}
<li><a href="?ano={{ ano_pesquisa|safe }}&fmt=pdf" target="_blank">{% trans "Exportar para PDF" %}</a></li>
<li><a href="?ano={{ ano_pesquisa|safe }}&fmt=csv">{% trans "Exportar para CSV" %}</a></li>
<li><a href="?ano={{ ano_pesquisa|safe }}&fmt=json" target="_blank">{% trans "Exportar para Json" %}</a></li>
{% endblock %}
{% block content %}
{% include "eventos/alocacao_equipe_snippet.html" %}
<div class="fixed-action-btn">
<a class="btn-floating">
<i class="large material-icons">print</i>
</a>
<ul>
<li><a class="btn-floating" href="?ano={{ ano_pesquisa|safe }}{% if mes_pesquisa %}&mes={{ mes_pesquisa|safe }}{% endif %}{% if semana_pesquisa %}&semana={{ semana_pesquisa|safe }}{% endif %}&fmt=pdf" title="{% trans "Exportar para PDF" %}"><i class="material-icons">picture_as_pdf</i></a></li>
<li><a class="btn-floating" href="?ano={{ ano_pesquisa|safe }}{% if mes_pesquisa %}&mes={{ mes_pesquisa|safe }}{% endif %}{% if semana_pesquisa %}&semana={{ semana_pesquisa|safe }}{% endif %}&fmt=csv" title="{% trans "Exportar para CSV" %}"><i class="material-icons">file_download</i></a></li>
</ul>
</div>
{% include "eventos/snippets/alocacao_equipe_snippet.html" with mode="html" %}
{% if semana_pesquisa %}
{% include "eventos/snippets/calendario_modals.html" %}
{% endif %}
{% endblock %}
{% block footer %}
{{ block.super }}
<script>
$(document).ready(function(){
M.FloatingActionButton.init($('.fixed-action-btn'), {hoverEnabled: false});
M.Modal.init($(".modal"));
})
</script>
{% endblock %}

73
sigi/apps/eventos/templates/eventos/alocacao_equipe_pdf.html

@ -1,63 +1,22 @@
{% extends "base_report.html" %}
{% load static from staticfiles %}
{% extends "pdf/base_report.html" %}
{% load static %}
{% load i18n %}
{% block extra_head %}
<style>
@page {
size: A4 landscape;
margin: 1cm;
}
* { font-size: 10px;}
a {
color: black;
text-decoration: none;
}
dt {
font-weight: 700;
}
dd {
margin-left: 2mm;
}
table, th, td {
border: 1px solid #ddd;
}
table {
border-collapse: collapse;
{% block page_size %}A4 landscape{% endblock %}
{% block extra_style %}
{{ block.super }}
a {
color: black;
text-decoration: none;
}
th {
text-align: center;
vertical-align: bottom;
background-color: #f1f1f1;
}
td {
width: 6%;
}
td, th {
padding: 2px;
vertical-align: center;
}
td:first-child { width: 22%; font-weight: bolder; }
td:last-child { font-weight: bolder; }
</style>
<title>{% blocktrans %}Alocação de equipe em {{ ano_pesquisa }}{% endblocktrans %}</title>
{% endblock %}
{% block report %}
<h1>{% blocktrans %}Alocação de equipe em {{ ano_pesquisa }}{% endblocktrans %}</h1>
{% include "eventos/alocacao_equipe_snippet.html" %}
{% block main_content %}
<h4>
{% if mes_pesquisa %}
{% blocktrans with mes=mes_pesquisa|safe ano=ano_pesquisa|safe %}Alocação de equipe em {{ mes }}/{{ ano }}{% endblocktrans %}</h4>
{% else %}
{% blocktrans with ano=ano_pesquisa|safe %}Alocação de equipe em {{ ano }}{% endblocktrans %}</h4>
{% endif %}
{% include "eventos/snippets/alocacao_equipe_snippet.html" %}
{% endblock %}
</body>
</html>

17
sigi/apps/eventos/templates/eventos/alocacao_equipe_snippet.html

@ -1,17 +0,0 @@
<div class="table-responsive">
<table class="table table-condensed table-bordered" repeat="1">
{% for linha in linhas %}
<tr>
{% if forloop.first %}
{% for coluna in linha %}
<th>{{ coluna }}</th>
{% endfor %}
{% else %}
{% for coluna in linha %}
<td>{{ coluna }}</td>
{% endfor %}
{% endif %}
</tr>
{% endfor %}
</table>
</div>

44
sigi/apps/eventos/templates/eventos/snippets/alocacao_equipe_snippet.html

@ -0,0 +1,44 @@
<div class="table-responsive">
<table class="striped{% if semana_pesquisa %} fixed{% endif %}">
<thead>
<tr>
{% for coluna in cabecalho %}
<th>
{% if mode == "html" and not semana_pesquisa and forloop.counter0 >= 1 and forloop.counter0 <= cabecalho|length|add:-2 %}
<a href="?ano={{ ano_pesquisa|safe }}&mes={% if mes_pesquisa %}{{ mes_pesquisa|safe }}&semana={% endif %}{{ forloop.counter0 }}">{{ coluna }}</a>
{% else %}
{% if semana_pesquisa and forloop.counter0 >= 1 %}
{{ coluna|date:"SHORT_DATE_FORMAT" }}
{% else %}
{{ coluna }}
{% endif %}
{% endif %}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for linha in linhas %}
<tr>
{% for coluna in linha %}
{% if forloop.first %}
<th>{{ coluna }}</th>
{% elif forloop.last and not semana_pesquisa %}
<th>{{ coluna }}</th>
{% else %}
<td>
{% if semana_pesquisa %}
{% for evento in coluna %}
<p><a class="modal-trigger" href="#modal{{ evento.id }}">{{ evento.nome }}</a></p>
{% endfor %}
{% else %}
{{ coluna }}
{% endif %}
</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>

3
sigi/apps/eventos/urls.py

@ -3,6 +3,9 @@ from sigi.apps.eventos import views
urlpatterns = [
path("calendario/", views.calendario, name="eventos-calendario"),
path(
"alocacaoequipe/", views.alocacao_equipe, name="eventos-alocacao-equipe"
),
path("evento/<int:id>/", views.evento, name="eventos-evento"),
path(
"evento/<int:evento_id>/convite/<casa_id>/",

269
sigi/apps/eventos/views.py

@ -1,16 +1,24 @@
from datetime import datetime
import calendar
import csv
import locale
from datetime import datetime
from functools import reduce
from typing import OrderedDict
from django.contrib import messages
from django.contrib.admin.sites import site
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.http import HttpResponse, JsonResponse
from django.shortcuts import redirect, render, get_object_or_404
from django.template import Template, Context
from django.template.exceptions import TemplateSyntaxError
from django.utils import timezone
from django.utils.text import slugify
from django.utils.translation import to_locale, get_language, gettext as _
from django.utils.translation import (
to_locale,
get_language,
ngettext,
gettext as _,
)
from django.urls import reverse
from django_weasyprint.utils import django_url_fetcher
from django_weasyprint.views import WeasyTemplateResponse
@ -383,79 +391,188 @@ def gerar_anexo(casa, presidente, contato, path, modelo, nome, texto):
return anexo
# @login_required
# def alocacao_equipe(request):
# ano_pesquisa = int(request.GET.get('ano', timezone.localdate().year))
# formato = request.GET.get('fmt', 'html')
# data = {'ano_pesquisa': ano_pesquisa}
# if Evento.objects.filter(data_inicio__year=ano_pesquisa-1).exists():
# data['prev_button'] = {'ano': ano_pesquisa - 1 }
# if Evento.objects.filter(data_inicio__year=ano_pesquisa+1).exists():
# data['next_button'] = {'ano': ano_pesquisa + 1 }
# dados = []
# for evento in Evento.objects.filter(data_inicio__year=ano_pesquisa).exclude(status='C').prefetch_related('equipe_set'):
# for p in evento.equipe_set.all():
# registro = None
# for r in dados:
# if r[0] == p.membro.pk:
# registro = r
# break
# if not registro:
# registro = [p.membro.pk, p.membro.nome_completo, [{'dias': 0, 'eventos': 0} for x in range(1,13)]]
# dados.append(registro)
# registro[2][evento.data_inicio.month-1]['dias'] += (evento.data_termino - evento.data_inicio).days + 1
# registro[2][evento.data_inicio.month-1]['eventos'] += 1
# dados.sort(lambda x, y: cmp(x[1], y[1]))
# lang = (translation.to_locale(translation.get_language())+'.utf8').encode()
# locale.setlocale(locale.LC_ALL, lang)
# meses = [calendar.month_name[m] for m in range(1,13)]
# linhas = [[_("Servidor")] + meses + ['total']]
# for r in dados:
# r[2].append(reduce(lambda x,y:{'dias': x['dias'] + y['dias'],
# 'eventos': x['eventos'] + y['eventos']}, r[2]))
# linhas.append([r[1]] +
# [_(ungettext("%(dias)s dia", "%(dias)s dias", d['dias']) + " em " +
# ungettext("%(eventos)s evento", "%(eventos)s eventos", d['eventos'])
# ) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in r[2]])
# # for registro in Servidor.objects.filter(equipe_evento__evento__data_inicio__year=ano_pesquisa).exclude(equipe_evento__evento__status='C').distinct():
# # dados = [{'dias': 0, 'eventos': 0} for x in range(1,13)]
# # for part in registro.equipe_evento.filter(evento__data_inicio__year=ano_pesquisa).exclude(evento__status='C'):
# # dados[part.evento.data_inicio.month-1]['dias'] += (part.evento.data_termino -
# # part.evento.data_inicio).days + 1
# # dados[part.evento.data_inicio.month-1]['eventos'] += 1
# # dados.append([registro.nome_completo] + [_(ungettext("%(dias)s dia", "%(dias)s dias", d['dias']) + " em " + ungettext("%(eventos)s evento", "%(eventos)s eventos", d['eventos'])) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in dados])
# data['linhas'] = linhas
# if formato == 'pdf':
# return render_to_pdf('eventos/alocacao_equipe_pdf.html', data)
# elif formato == 'csv':
# response = HttpResponse(content_type='text/csv')
# response['Content-Disposition'] = 'attachment; filename="alocacao_equipe_%s.csv"' % (ano_pesquisa,)
# writer = csv.writer(response)
# asc_list = [[s.encode('utf-8') if isinstance(s, unicode) else s for s in l] for l in linhas]
# writer.writerows(asc_list)
# return response
# elif formato == 'json':
# result = {'ano': ano_pesquisa,
# 'equipe': [{'pk': d[0],
# 'nome_completo': d[1],
# 'meses': {m[0]: m[1] for m in zip(meses+['total'], d[2])}
# } for d in dados]}
# return JsonResponse(result)
# return render(request, 'eventos/alocacao_equipe.html', data)
@login_required
def alocacao_equipe(request):
ano_pesquisa = int(request.GET.get("ano", timezone.localdate().year))
mes_pesquisa = int(request.GET.get("mes", 0))
semana_pesquisa = int(request.GET.get("semana", 0))
formato = request.GET.get("fmt", "html")
lang = to_locale(get_language()) + ".UTF-8"
locale.setlocale(locale.LC_ALL, lang)
dados = []
eventos = Evento.objects.exclude(status="C").prefetch_related("equipe_set")
num_cols = 12
if mes_pesquisa > 0:
semanas = [
[s[0], s[-1]]
for s in calendar.Calendar().monthdatescalendar(
ano_pesquisa, mes_pesquisa
)
]
num_cols = len(semanas)
if semana_pesquisa > 0:
dias = calendar.Calendar().monthdatescalendar(
ano_pesquisa, mes_pesquisa
)[semana_pesquisa - 1]
num_cols = len(dias)
eventos = eventos.filter(
data_inicio__gte=dias[0], data_inicio__lte=dias[-1]
)
else:
eventos = eventos.filter(
data_inicio__gte=semanas[0][0], data_inicio__lte=semanas[-1][-1]
)
else:
eventos = eventos.filter(data_inicio__year=ano_pesquisa)
for evento in eventos:
for p in evento.equipe_set.all():
registro = None
for r in dados:
if r[0] == p.membro.pk:
registro = r
break
if not registro:
if semana_pesquisa > 0:
registro = [
p.membro.pk,
p.membro.nome_completo,
OrderedDict([(dia, []) for dia in dias]),
]
else:
registro = [
p.membro.pk,
p.membro.nome_completo,
[{"dias": 0, "eventos": 0} for __ in range(num_cols)],
]
dados.append(registro)
if mes_pesquisa > 0:
if semana_pesquisa > 0:
for dia in dias:
if (
evento.data_inicio.date()
<= dia
<= evento.data_termino.date()
):
registro[2][dia].append(evento)
else:
for idx, [inicio, fim] in enumerate(semanas):
if inicio <= evento.data_inicio.date() <= fim:
registro[2][idx]["dias"] += (
min(fim, evento.data_termino.date())
- evento.data_inicio.date()
).days + 1
registro[2][idx]["eventos"] += 1
elif inicio <= evento.data_termino.date() <= fim:
registro[2][idx]["dias"] += (
min(fim, evento.data_termino.date())
- evento.data_inicio.date()
).days + 1
registro[2][idx]["eventos"] += 1
else:
registro[2][evento.data_inicio.month - 1]["dias"] += (
evento.data_termino - evento.data_inicio
).days + 1
registro[2][evento.data_inicio.month - 1]["eventos"] += 1
dados.sort(key=lambda x: x[1])
meses = list(calendar.month_abbr)[1:]
linhas = []
if semana_pesquisa:
linhas = [
[registro[1]] + list(registro[2].values()) for registro in dados
]
else:
for r in dados:
r[2].append(
reduce(
lambda x, y: {
"dias": x["dias"] + y["dias"],
"eventos": x["eventos"] + y["eventos"],
},
r[2],
)
)
linhas.append(
[r[1]]
+ [
_(
ngettext("%(dias)s dia", "%(dias)s dias", d["dias"])
+ " em "
+ ngettext(
"%(eventos)s evento",
"%(eventos)s eventos",
d["eventos"],
)
)
% d
if d["dias"] > 0 or d["eventos"] > 0
else ""
for d in r[2]
]
)
context = site.each_context(request) or {}
context.update(
{
"anos": Evento.objects.exclude(data_inicio=None)
.order_by("data_inicio__year")
.distinct("data_inicio__year")
.values_list("data_inicio__year", flat=True),
"ano_pesquisa": ano_pesquisa,
"linhas": linhas,
}
)
if mes_pesquisa > 0:
context["mes_pesquisa"] = mes_pesquisa
context["meses"] = meses
if semana_pesquisa > 0:
cabecalho = [_("Servidor")] + dias
context["semana_pesquisa"] = semana_pesquisa
context["eventos"] = eventos
else:
cabecalho = (
[_("Servidor")]
+ [
_(f"de {inicio:%d/%m} a {fim:%d/%m}")
for inicio, fim in semanas
]
+ ["total"]
)
else:
cabecalho = [_("Servidor")] + meses + ["total"]
context["cabecalho"] = cabecalho
if formato == "pdf":
context["title"] = _("Alocação de equipe")
context["pdf"] = True
return WeasyTemplateResponse(
# filename="alocacao_equipe.pdf",
request=request,
template="eventos/alocacao_equipe_pdf.html",
context=context,
content_type="application/pdf",
)
elif formato == "csv":
response = HttpResponse(content_type="text/csv")
response[
"Content-Disposition"
] = 'attachment; filename="alocacao_equipe_%s.csv"' % (ano_pesquisa,)
writer = csv.writer(response)
writer.writerow(cabecalho)
writer.writerows(linhas)
return response
return render(request, "eventos/alocacao_equipe.html", context)
# # Views e functions para carrinho de exportação

2
sigi/menu_conf.yaml

@ -86,7 +86,7 @@ main_menu:
- title: Calendário mensal
view_name: eventos-calendario
- title: Alocação de equipe
view_name:
view_name: eventos-alocacao-equipe
- title: Servidores
icon: account_circle
children:

Loading…
Cancel
Save