Browse Source

Adiciona relatório uso de espaços. Gertiq #160526

pull/169/head
Sesóstris Vieira 1 year ago
parent
commit
d0d8da2652
  1. 1
      sigi/apps/espacos/admin_urls.py
  2. 44
      sigi/apps/espacos/forms.py
  3. 2
      sigi/apps/espacos/templates/espacos/agenda_pdf.html
  4. 43
      sigi/apps/espacos/templates/espacos/snippets/uso_espaco_snippet.html
  5. 56
      sigi/apps/espacos/templates/espacos/uso_espaco.html
  6. 19
      sigi/apps/espacos/templates/espacos/uso_espaco_pdf.html
  7. 87
      sigi/apps/espacos/views.py
  8. 53
      sigi/apps/utils/mixins.py
  9. 2
      sigi/menu_conf.yaml
  10. 2
      sigi/templates/pdf/base.html

1
sigi/apps/espacos/admin_urls.py

@ -3,4 +3,5 @@ from sigi.apps.espacos import views
urlpatterns = [
path("agenda/", views.Agenda.as_view(), name="espacos_agenda"),
path("usoespacos/", views.UsoEspacos.as_view(), name="espacos_usoespaco"),
]

44
sigi/apps/espacos/forms.py

@ -0,0 +1,44 @@
import calendar
from django.utils import timezone
from django import forms
from material.admin.widgets import MaterialAdminDateWidget
from django.forms.widgets import CheckboxSelectMultiple
from django.utils.translation import gettext as _
from sigi.apps.espacos.models import Espaco
class UsoEspacoReportForm(forms.Form):
class Media:
css = {"all": ["css/change_form.css"]}
js = [
"/admin/js/vendor/select2/select2.full.js",
"/admin/js/change_form.js",
"/admin/js/vendor/select2/i18n/pt-BR.js",
"/material/admin/js/widgets/TimeInput.js",
"/admin/js/core.js",
]
def get_semana(self):
return [
{"first": s[0], "last": s[-1]}
for s in calendar.Calendar().monthdatescalendar(
timezone.localdate().year, timezone.localdate().month
)
if s[0] <= timezone.localdate() <= s[-1]
][0]
data_inicio = forms.DateField(
label=_("Data início"), required=True, widget=MaterialAdminDateWidget
)
data_fim = forms.DateField(
label=_("Data fim"), required=True, widget=MaterialAdminDateWidget
)
espaco = forms.ModelMultipleChoiceField(
label=_("Espaços"), required=True, queryset=Espaco.objects.all(), widget=CheckboxSelectMultiple
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
semana = self.get_semana()
self.fields["data_inicio"].initial = semana["first"]
self.fields["data_fim"].initial = semana["last"]

2
sigi/apps/espacos/templates/espacos/agenda_pdf.html

@ -1,8 +1,6 @@
{% extends 'pdf/base_report.html' %}
{% load static i18n sigi_tags %}
{% block page_size %}A4 landscape{% endblock page_size %}
{% block extra_style %}
{{ block.super }}
blockquote {

43
sigi/apps/espacos/templates/espacos/snippets/uso_espaco_snippet.html

@ -0,0 +1,43 @@
{% load i18n static sigi_tags dict_get %}
<table class="calendar-table" repeat="2">
<thead>
<tr>
<th rowspan="2">{% trans "Espaço" %}</th>
<th rowspan="2">{% trans "Data início" %}</th>
<th rowspan="2">{% trans "Data término" %}</th>
<th rowspan="2">{% trans "Propósito" %}</th>
<th rowspan="2">{% trans "Solicitante" %}</th>
<th colspan="2">{% trans "Contato" %}</th>
<th rowspan="2">{% trans "Informações adicionais" %}</th>
<th rowspan="2">{% trans "Recursos solicitados" %}</th>
</tr>
<tr>
<th>{% trans "Nome" %}</th>
<th>{% trans "Telefone" %}</th>
</tr>
</thead>
<tbody>
{% for reserva in reservas %}
<tr>
{% ifchanged reserva.espaco %}
<th rowspan="{{ rowspans|get:reserva.espaco.id }}">{{ reserva.espaco.nome }}</th>
{% endifchanged %}
<td>{{ reserva.inicio }}</td>
<td>{{ reserva.termino }}</td>
<td>{{ reserva.proposito }}</td>
<td>{{ reserva.solicitante }}</td>
<td>{{ reserva.contato }}</td>
<td>{{ reserva.telefone_contato }}</td>
<td>{{ reserva.informacoes }}</td>
<td>
<ul>
{% for recurso in reserva.recursosolicitado_set.all %}
<li>{{ recurso.quantidade}} {{ recurso.recurso }} ( {{ recurso.observacoes }})</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>

56
sigi/apps/espacos/templates/espacos/uso_espaco.html

@ -0,0 +1,56 @@
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "css/calendario.css" %}">
<style>
tr {
border-bottom: 1px solid var(--border-color);
}
th {
background: var(--darkened-bg);
}
</style>
{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block content %}
<div class="row">
<div class="col s12">
<form method="get" action="">
<div class="card">
<div class="card-content">
{{ form }}
</div>
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit">
{% trans "View" %}
<i class="material-icons right">send</i>
</button>
<button class="btn waves-effect waves-light" type="submit" name="pdf" value="1">
{% trans "PDF" %}
<i class="material-icons right">picture_as_pdf</i>
</button>
</div>
</div>
</form>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
{% include "espacos/snippets/uso_espaco_snippet.html" %}
</div>
</div>
</div>
</div>
{% endblock %}
{% block footer %}
{{ block.super }}
{{ form.media }}
{% endblock %}

19
sigi/apps/espacos/templates/espacos/uso_espaco_pdf.html

@ -0,0 +1,19 @@
{% extends "pdf/base_report.html" %}
{% load i18n static %}
{% block extra_style %}
{{ block.super }}
h4 {
margin: 20px 0;
padding-left: 1.5rem;
border-left: 5px solid #ee6e73;
}
{% endblock %}
{% block main_content %}
<h4>
{% blocktranslate%}Semana de {{ data_inicio }} a {{ data_termino }}{% endblocktranslate %}
</h4>
<br/>
{% include "espacos/snippets/uso_espaco_snippet.html" %}
{% endblock %}

87
sigi/apps/espacos/views.py

@ -2,29 +2,24 @@ import calendar
import locale
from typing import Any
from django import http
from django.db.models import Q
from django.template.response import TemplateResponse
from django.db.models import Q, Count
from django.utils import timezone
from django.utils.translation import (
to_locale,
get_language,
ngettext,
gettext as _,
)
from django.views.generic.base import TemplateView
from django_weasyprint.views import WeasyTemplateResponse
from sigi.apps.espacos.models import Espaco, Reserva
from sigi.apps.espacos.forms import UsoEspacoReportForm
from sigi.apps.utils.mixins import ReportViewMixin, StaffMemberRequiredMixin
class Agenda(TemplateView):
def _is_pdf(self):
return bool(self.request.GET.get("pdf", 0))
def get_template_names(self):
if self._is_pdf():
return ["espacos/agenda_pdf.html"]
else:
return ["espacos/agenda.html"]
class Agenda(ReportViewMixin, StaffMemberRequiredMixin, TemplateView):
html_template_name = "espacos/agenda.html"
pdf_template_name = "espacos/agenda_pdf.html"
report_title = _("Reserva de espaços do ILB")
pagesize = "A4 landscape"
def get_context_data(self, **kwargs):
mes_pesquisa = int(
@ -108,19 +103,59 @@ class Agenda(TemplateView):
context["semanas"] = semanas
context["day_names"] = calendar.day_abbr
if self._is_pdf():
context["pdf"] = True
context["title"] = _("Reserva de espaços do ILB")
return context
def render_to_response(self, context, **response_kwargs):
self.response_class = TemplateResponse
self.content_type = None
if self._is_pdf():
self.content_type = "application/pdf"
self.response_class = WeasyTemplateResponse
response_kwargs.setdefault(
"filename", f"agenda-{timezone.localdate()}.pdf"
class UsoEspacos(ReportViewMixin, StaffMemberRequiredMixin, TemplateView):
html_template_name = "espacos/uso_espaco.html"
pdf_template_name = "espacos/uso_espaco_pdf.html"
report_title = _("Uso dos espaços")
pagesize = "A4 landscape"
def get_context_data(self, **kwargs):
form = UsoEspacoReportForm(self.request.GET)
if form.is_valid():
data_inicio = form.cleaned_data["data_inicio"]
data_fim = form.cleaned_data["data_fim"]
sel_espacos = form.cleaned_data["espaco"]
else:
form = UsoEspacoReportForm(
initial={"espaco": Espaco.objects.all()}
)
semana = form.get_semana()
data_inicio = semana["first"]
data_fim = semana["last"]
sel_espacos = None
if not sel_espacos:
sel_espacos = Espaco.objects.all()
reservas = (
Reserva.objects.filter(
status=Reserva.STATUS_ATIVO, espaco__in=sel_espacos
)
.filter(
Q(inicio__range=(data_inicio, data_fim))
| Q(termino__range=(data_inicio, data_fim))
)
.order_by("espaco", "inicio", "termino")
)
return super().render_to_response(context, **response_kwargs)
rowspans = dict(
reservas.order_by("espaco")
.values_list("espaco")
.annotate(Count("espaco"))
)
context = super().get_context_data(**kwargs)
context.update(
{
"reservas": reservas,
"rowspans": rowspans,
"form": form,
"data_inicio": data_inicio,
"data_termino": data_fim,
"sel_espacos": sel_espacos,
}
)
return context

53
sigi/apps/utils/mixins.py

@ -5,12 +5,15 @@ from django.contrib import admin
from django.contrib.admin import helpers
from django.contrib.admin.options import csrf_protect_m
from django.contrib.admin.utils import pretty_name
from django.contrib.auth.mixins import UserPassesTestMixin
from django.core.exceptions import PermissionDenied, ImproperlyConfigured
from django.http import Http404
from django.http.response import HttpResponse, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.urls import path
from django.utils import timezone
from django.utils.translation import gettext as _, ngettext
from django_weasyprint.views import WeasyTemplateResponse
from import_export import resources
from import_export.admin import ImportMixin, ExportMixin
from import_export.fields import Field
@ -308,6 +311,7 @@ class ReturnMixin:
return HttpResponseRedirect(self._return_path)
return response
class AsciifyQParameter:
def asciify_q_param(self, request):
if "q" in request.GET:
@ -318,3 +322,52 @@ class AsciifyQParameter:
def get_queryset(self, request):
self.asciify_q_param(request)
return super().get_queryset(request)
class StaffMemberRequiredMixin(UserPassesTestMixin):
def test_func(self):
return self.request.user.is_staff
class ReportViewMixin:
html_template_name = None
pdf_template_name = None
report_title = _("Report")
pagesize = None
attachment = True
def _is_pdf(self):
return bool(self.request.GET.get("pdf", 0))
def get_template_names(self):
if self.html_template_name is None or self.pdf_template_name is None:
raise ImproperlyConfigured(
"TemplateResponseMixin requires either a definition of "
"'html_template_name' and 'pdf_template_name' or an "
"implementation of 'get_template_names()'"
)
if self._is_pdf():
return [self.pdf_template_name]
else:
return [self.html_template_name]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["title"] = self.report_title
context["pdf"] = self._is_pdf()
if self.pagesize:
context["pagesize"] = self.pagesize
return context
def render_to_response(self, context, **response_kwargs):
self.response_class = TemplateResponse
self.content_type = None
if self._is_pdf():
self.content_type = "application/pdf"
self.response_class = WeasyTemplateResponse
response_kwargs.setdefault(
"filename",
f"{self.report_title.lower()}-{timezone.localdate()}.pdf",
)
response_kwargs.setdefault("attachment", self.attachment)
return super().render_to_response(context, **response_kwargs)

2
sigi/menu_conf.yaml

@ -79,6 +79,8 @@ main_menu:
querystr: status=A
- title: Agenda de reservas
view_name: espacos_agenda
- title: Uso dos espaços
view_name: espacos_usoespaco
- title: Eventos
icon: school
children:

2
sigi/templates/pdf/base.html

@ -7,7 +7,7 @@
<meta name="author" content="Interlegis">
<style type="text/css">
@page {
size: {% block page_size %}A4 portrait{% endblock page_size %};
size: {% block page_size %}{{ pagesize|default:"A4 portrait" }}{% endblock page_size %};
margin: {% block page_margin %}3cm 2cm 2cm 2cm{% endblock page_margin %};
font-family: "Helvetica", "Arial", "sans-serif";
font-size: 10px;

Loading…
Cancel
Save