Compare commits
No commits in common. "feat/sgmp-solicitacoes-only" and "main" have entirely different histories.
feat/sgmp-
...
main
|
|
@ -1,21 +1,13 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib import admin, messages
|
from django.contrib import admin, messages
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.forms import BaseInlineFormSet
|
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import path, reverse
|
from django.urls import path, reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from .intf_sqlserver import listar_para_selecionar_colaborador
|
from .intf_sqlserver import listar_para_selecionar_colaborador
|
||||||
from .intf_winthor import buscar_colaborador_oracle
|
from .intf_winthor import buscar_colaborador_oracle
|
||||||
from .models import (
|
from .models import ConfiguracaoSGMP, HeadGestor, PessoaRM, Solicitacao, UsuarioSistema
|
||||||
ConfiguracaoSGMP,
|
|
||||||
HeadGestor,
|
|
||||||
PessoaRM,
|
|
||||||
Solicitacao,
|
|
||||||
UsuarioPerfilExtra,
|
|
||||||
UsuarioSistema,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ConfiguracaoSGMPForm(forms.ModelForm):
|
class ConfiguracaoSGMPForm(forms.ModelForm):
|
||||||
|
|
@ -215,43 +207,12 @@ class PessoaRMAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
return redirect("..")
|
return redirect("..")
|
||||||
|
|
||||||
class UsuarioPerfilExtraInlineFormSet(BaseInlineFormSet):
|
|
||||||
def clean(self):
|
|
||||||
super().clean()
|
|
||||||
vistos = set()
|
|
||||||
principal = self.data.get("perfil") or getattr(self.instance, "perfil", None)
|
|
||||||
for form in self.forms:
|
|
||||||
if not hasattr(form, "cleaned_data"):
|
|
||||||
continue
|
|
||||||
if form.cleaned_data.get("DELETE"):
|
|
||||||
continue
|
|
||||||
perfil_extra = form.cleaned_data.get("perfil")
|
|
||||||
if not perfil_extra:
|
|
||||||
continue
|
|
||||||
if perfil_extra == principal:
|
|
||||||
raise ValidationError(
|
|
||||||
"Perfil extra não pode ser igual ao perfil principal."
|
|
||||||
)
|
|
||||||
if perfil_extra in vistos:
|
|
||||||
raise ValidationError(f"Perfil extra duplicado: {perfil_extra}.")
|
|
||||||
vistos.add(perfil_extra)
|
|
||||||
|
|
||||||
|
|
||||||
class UsuarioPerfilExtraInline(admin.TabularInline):
|
|
||||||
model = UsuarioPerfilExtra
|
|
||||||
formset = UsuarioPerfilExtraInlineFormSet
|
|
||||||
extra = 0
|
|
||||||
fields = ("perfil", "criado_em")
|
|
||||||
readonly_fields = ("criado_em",)
|
|
||||||
|
|
||||||
|
|
||||||
@admin.register(UsuarioSistema)
|
@admin.register(UsuarioSistema)
|
||||||
class UsuarioSistemaAdmin(admin.ModelAdmin):
|
class UsuarioSistemaAdmin(admin.ModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
"nome",
|
"nome",
|
||||||
"matricula",
|
"matricula",
|
||||||
"perfil",
|
"perfil",
|
||||||
"perfis_ativos_display",
|
|
||||||
"ativo",
|
"ativo",
|
||||||
"criado_em",
|
"criado_em",
|
||||||
)
|
)
|
||||||
|
|
@ -270,8 +231,6 @@ class UsuarioSistemaAdmin(admin.ModelAdmin):
|
||||||
"criado_em",
|
"criado_em",
|
||||||
"atualizado_em",
|
"atualizado_em",
|
||||||
)
|
)
|
||||||
|
|
||||||
inlines = (UsuarioPerfilExtraInline,)
|
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
("Informações Básicas", {
|
("Informações Básicas", {
|
||||||
|
|
@ -286,25 +245,6 @@ class UsuarioSistemaAdmin(admin.ModelAdmin):
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_queryset(self, request):
|
|
||||||
qs = super().get_queryset(request)
|
|
||||||
return qs.prefetch_related("perfis_extras")
|
|
||||||
|
|
||||||
@admin.display(description="Perfis ativos")
|
|
||||||
def perfis_ativos_display(self, obj):
|
|
||||||
codigos = obj.perfis_ativos()
|
|
||||||
labels = dict(UsuarioSistema.Perfil.choices)
|
|
||||||
resolved = [str(labels.get(c, c)) for c in codigos]
|
|
||||||
return ", ".join(resolved)
|
|
||||||
|
|
||||||
|
|
||||||
@admin.register(UsuarioPerfilExtra)
|
|
||||||
class UsuarioPerfilExtraAdmin(admin.ModelAdmin):
|
|
||||||
list_display = ("usuario", "perfil", "criado_em")
|
|
||||||
list_filter = ("perfil",)
|
|
||||||
search_fields = ("usuario__nome", "usuario__matricula")
|
|
||||||
autocomplete_fields = ("usuario",)
|
|
||||||
|
|
||||||
@admin.register(HeadGestor)
|
@admin.register(HeadGestor)
|
||||||
class HeadGestorAdmin(admin.ModelAdmin):
|
class HeadGestorAdmin(admin.ModelAdmin):
|
||||||
list_display = ("head", "gestor")
|
list_display = ("head", "gestor")
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ def usuario_sistema(request):
|
||||||
usuario_eh_gestor or usuario_eh_admin or usuario_eh_diretoria
|
usuario_eh_gestor or usuario_eh_admin or usuario_eh_diretoria
|
||||||
),
|
),
|
||||||
"usuario_pode_ver_todas_solicitacoes": (
|
"usuario_pode_ver_todas_solicitacoes": (
|
||||||
not usuario.eh_apenas_gestor()
|
usuario.perfil != UsuarioSistema.Perfil.GESTOR or usuario_eh_admin
|
||||||
),
|
),
|
||||||
"usuario_pode_gerenciar_permissoes": usuario_pode_gerenciar_permissoes(
|
"usuario_pode_gerenciar_permissoes": usuario_pode_gerenciar_permissoes(
|
||||||
usuario
|
usuario
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ def get_sqlserver_connection():
|
||||||
database=settings.SQLSERVER_CONFIG["DATABASE"],
|
database=settings.SQLSERVER_CONFIG["DATABASE"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def listar_para_selecionar_colaborador(apenas_desligados=False):
|
def listar_para_selecionar_colaborador(apenas_desligados=False):
|
||||||
"""
|
"""
|
||||||
Lista colaboradores do RM para seleção.
|
Lista colaboradores do RM para seleção.
|
||||||
|
|
|
||||||
|
|
@ -140,25 +140,6 @@ class UsuarioSistema(BaseModel):
|
||||||
# Garante que o principal venha primeiro e não seja duplicado
|
# Garante que o principal venha primeiro e não seja duplicado
|
||||||
return [self.perfil] + [p for p in extras if p != self.perfil]
|
return [self.perfil] + [p for p in extras if p != self.perfil]
|
||||||
|
|
||||||
def eh_apenas_gestor(self) -> bool:
|
|
||||||
"""
|
|
||||||
Verdadeiro quando o usuário possui somente capacidades de gestor.
|
|
||||||
|
|
||||||
Útil para regras que restringem funcionalidades administrativas
|
|
||||||
(ex.: listagem "todas as solicitações") sem bloquear usuários que
|
|
||||||
acumulam gestor + outro perfil operacional.
|
|
||||||
"""
|
|
||||||
perfis_nao_gestor = [
|
|
||||||
self.Perfil.ADMIN,
|
|
||||||
self.Perfil.GG,
|
|
||||||
self.Perfil.CONTROLADORIA,
|
|
||||||
self.Perfil.HEAD,
|
|
||||||
self.Perfil.DIRETORIA,
|
|
||||||
]
|
|
||||||
return self.tem_perfil(self.Perfil.GESTOR) and not any(
|
|
||||||
self.tem_perfil(perfil) for perfil in perfis_nao_gestor
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.nome} ({self.matricula})"
|
return f"{self.nome} ({self.matricula})"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from django.test import Client, TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from ..acesso import usuario_pode_gerenciar_permissoes
|
from ..acesso import usuario_pode_gerenciar_permissoes
|
||||||
from ..models import ConfiguracaoSGMP, UsuarioPerfilExtra, UsuarioSistema
|
from ..models import ConfiguracaoSGMP, UsuarioSistema
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
@ -91,29 +91,3 @@ class GerenciarPermissoesViewTests(TestCase):
|
||||||
self.client.login(username="20", password="secret")
|
self.client.login(username="20", password="secret")
|
||||||
r = self.client.get(self.url)
|
r = self.client.get(self.url)
|
||||||
self.assertEqual(r.status_code, 200)
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
class TodasSolicitacoesPerfilCombinadoTests(TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.client = Client()
|
|
||||||
self.url = reverse("solicitacoes:todas_solicitacoes")
|
|
||||||
|
|
||||||
User.objects.create_user(username="30", password="secret")
|
|
||||||
self.usuario = UsuarioSistema.objects.create(
|
|
||||||
matricula="30",
|
|
||||||
nome="GG com perfil Gestor",
|
|
||||||
perfil=UsuarioSistema.Perfil.GG,
|
|
||||||
ativo=True,
|
|
||||||
)
|
|
||||||
UsuarioPerfilExtra.objects.create(
|
|
||||||
usuario=self.usuario,
|
|
||||||
perfil=UsuarioSistema.Perfil.GESTOR,
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_usuario_com_gg_e_gestor_acessa_todas_solicitacoes(self):
|
|
||||||
self.client.login(username="30", password="secret")
|
|
||||||
r = self.client.get(self.url)
|
|
||||||
self.assertEqual(r.status_code, 200)
|
|
||||||
|
|
||||||
def test_eh_apenas_gestor_false_quando_ha_perfil_operacional(self):
|
|
||||||
self.assertFalse(self.usuario.eh_apenas_gestor())
|
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,6 @@ urlpatterns = [
|
||||||
views.todas_solicitacoes_view,
|
views.todas_solicitacoes_view,
|
||||||
name="todas_solicitacoes",
|
name="todas_solicitacoes",
|
||||||
),
|
),
|
||||||
path(
|
|
||||||
"solicitacoes/todas/exportar.xlsx",
|
|
||||||
views.exportar_todas_solicitacoes_xlsx,
|
|
||||||
name="exportar_todas_solicitacoes_xlsx",
|
|
||||||
),
|
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# DESLIGAMENTO
|
# DESLIGAMENTO
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,7 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
import uuid
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from io import BytesIO
|
|
||||||
from urllib.parse import urlencode
|
|
||||||
from django.contrib.auth import login, logout, get_user_model
|
from django.contrib.auth import login, logout, get_user_model
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
@ -13,9 +10,7 @@ from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.db.models import Q
|
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from openpyxl import Workbook
|
|
||||||
from .models import (
|
from .models import (
|
||||||
HeadGestor,
|
HeadGestor,
|
||||||
PessoaRM,
|
PessoaRM,
|
||||||
|
|
@ -46,9 +41,8 @@ def _queryset_dashboard_solicitacoes(usuario: UsuarioSistema):
|
||||||
"""
|
"""
|
||||||
Queryset visível no dashboard para o usuário (antes de order_by/paginação).
|
Queryset visível no dashboard para o usuário (antes de order_by/paginação).
|
||||||
|
|
||||||
A seleção do ramo principal é baseada em ``usuario.perfil`` para preservar
|
Usa :meth:`UsuarioSistema.tem_perfil` (perfil principal + ``UsuarioPerfilExtra``),
|
||||||
precedência do perfil principal. Perfis extras são considerados apenas
|
não apenas ``usuario.perfil``, para alinhar com perfis secundários.
|
||||||
como capacidades complementares dentro de cada ramo quando necessário.
|
|
||||||
|
|
||||||
**Precedência** (primeiro ramo que se aplica; papéis operacionais antes de GESTOR):
|
**Precedência** (primeiro ramo que se aplica; papéis operacionais antes de GESTOR):
|
||||||
1. ADMIN — todas as solicitações
|
1. ADMIN — todas as solicitações
|
||||||
|
|
@ -61,36 +55,36 @@ def _queryset_dashboard_solicitacoes(usuario: UsuarioSistema):
|
||||||
Total e pendentes no dashboard devem usar ``.count()`` sobre este mesmo queryset
|
Total e pendentes no dashboard devem usar ``.count()`` sobre este mesmo queryset
|
||||||
(pendentes = excluir FINALIZADA e REPROVADA).
|
(pendentes = excluir FINALIZADA e REPROVADA).
|
||||||
"""
|
"""
|
||||||
perfil_principal = usuario.perfil
|
if usuario.tem_perfil(UsuarioSistema.Perfil.ADMIN):
|
||||||
if perfil_principal == UsuarioSistema.Perfil.ADMIN:
|
|
||||||
return Solicitacao.objects.all()
|
return Solicitacao.objects.all()
|
||||||
if perfil_principal in (
|
if usuario.tem_perfil(UsuarioSistema.Perfil.GG) or usuario.tem_perfil(
|
||||||
UsuarioSistema.Perfil.GG,
|
UsuarioSistema.Perfil.CONTROLADORIA
|
||||||
UsuarioSistema.Perfil.CONTROLADORIA,
|
|
||||||
):
|
):
|
||||||
qs_fila = Solicitacao.objects.filter(status=StatusSolicitacao.ENVIADA)
|
qs_fila = Solicitacao.objects.filter(status=StatusSolicitacao.ENVIADA)
|
||||||
if perfil_principal == UsuarioSistema.Perfil.GG:
|
if usuario.tem_perfil(UsuarioSistema.Perfil.GG) and not usuario.tem_perfil(
|
||||||
|
UsuarioSistema.Perfil.CONTROLADORIA
|
||||||
|
):
|
||||||
qs_fila = qs_fila.exclude(
|
qs_fila = qs_fila.exclude(
|
||||||
pareceres__etapa=EtapaAprovacao.GG, pareceres__usuario=usuario
|
pareceres__etapa=EtapaAprovacao.GG, pareceres__usuario=usuario
|
||||||
)
|
)
|
||||||
elif perfil_principal == UsuarioSistema.Perfil.CONTROLADORIA:
|
elif usuario.tem_perfil(UsuarioSistema.Perfil.CONTROLADORIA) and not usuario.tem_perfil(
|
||||||
|
UsuarioSistema.Perfil.GG
|
||||||
|
):
|
||||||
qs_fila = qs_fila.exclude(
|
qs_fila = qs_fila.exclude(
|
||||||
pareceres__etapa=EtapaAprovacao.CONTROLADORIA,
|
pareceres__etapa=EtapaAprovacao.CONTROLADORIA,
|
||||||
pareceres__usuario=usuario,
|
pareceres__usuario=usuario,
|
||||||
)
|
)
|
||||||
return _qs_dashboard_unir_fila_com_minhas(qs_fila, usuario)
|
return _qs_dashboard_unir_fila_com_minhas(qs_fila, usuario)
|
||||||
if perfil_principal == UsuarioSistema.Perfil.HEAD:
|
if usuario.tem_perfil(UsuarioSistema.Perfil.HEAD):
|
||||||
matriculas = matriculas_gestores_do_head(usuario)
|
matriculas = matriculas_gestores_do_head(usuario)
|
||||||
qs_fila = Solicitacao.objects.filter(status=StatusSolicitacao.AGUARDANDO_HEAD)
|
qs_fila = Solicitacao.objects.filter(status=StatusSolicitacao.AGUARDANDO_HEAD)
|
||||||
if matriculas:
|
if matriculas:
|
||||||
qs_fila = qs_fila.filter(solicitante__matricula__in=matriculas)
|
qs_fila = qs_fila.filter(solicitante__matricula__in=matriculas)
|
||||||
return _qs_dashboard_unir_fila_com_minhas(qs_fila, usuario)
|
return _qs_dashboard_unir_fila_com_minhas(qs_fila, usuario)
|
||||||
if perfil_principal == UsuarioSistema.Perfil.DIRETORIA:
|
if usuario.tem_perfil(UsuarioSistema.Perfil.DIRETORIA):
|
||||||
qs_fila = Solicitacao.objects.filter(status=StatusSolicitacao.AGUARDANDO_DIRETORIA)
|
qs_fila = Solicitacao.objects.filter(status=StatusSolicitacao.AGUARDANDO_DIRETORIA)
|
||||||
if usuario.perfis_extras.filter(perfil=UsuarioSistema.Perfil.HEAD).exists():
|
|
||||||
qs_fila = qs_fila | Solicitacao.objects.filter(status=StatusSolicitacao.AGUARDANDO_HEAD)
|
|
||||||
return _qs_dashboard_unir_fila_com_minhas(qs_fila, usuario)
|
return _qs_dashboard_unir_fila_com_minhas(qs_fila, usuario)
|
||||||
if perfil_principal == UsuarioSistema.Perfil.GESTOR:
|
if usuario.tem_perfil(UsuarioSistema.Perfil.GESTOR):
|
||||||
return Solicitacao.objects.filter(solicitante=usuario)
|
return Solicitacao.objects.filter(solicitante=usuario)
|
||||||
return Solicitacao.objects.none()
|
return Solicitacao.objects.none()
|
||||||
|
|
||||||
|
|
@ -728,7 +722,7 @@ def dashboard_view(request):
|
||||||
paginator = Paginator(solicitacoes, 10)
|
paginator = Paginator(solicitacoes, 10)
|
||||||
page = request.GET.get('page')
|
page = request.GET.get('page')
|
||||||
solicitacoes_page = paginator.get_page(page)
|
solicitacoes_page = paginator.get_page(page)
|
||||||
|
|
||||||
# Prepara informações sobre quais solicitações podem ser aprovadas ou receber parecer
|
# Prepara informações sobre quais solicitações podem ser aprovadas ou receber parecer
|
||||||
solicitacoes_com_acao = []
|
solicitacoes_com_acao = []
|
||||||
for solicitacao in solicitacoes_page:
|
for solicitacao in solicitacoes_page:
|
||||||
|
|
@ -784,10 +778,23 @@ def dashboard_view(request):
|
||||||
def todas_solicitacoes_view(request):
|
def todas_solicitacoes_view(request):
|
||||||
"""Listagem de solicitações: Gestor não acessa; Head vê só dos gestores vinculados a ele; GG/Controladoria/Diretoria veem todas."""
|
"""Listagem de solicitações: Gestor não acessa; Head vê só dos gestores vinculados a ele; GG/Controladoria/Diretoria veem todas."""
|
||||||
usuario = get_usuario_sistema(request)
|
usuario = get_usuario_sistema(request)
|
||||||
if usuario.eh_apenas_gestor():
|
if usuario.tem_perfil(UsuarioSistema.Perfil.GESTOR) and not usuario.tem_perfil(UsuarioSistema.Perfil.ADMIN):
|
||||||
return redirect("solicitacoes:dashboard")
|
return redirect("solicitacoes:dashboard")
|
||||||
|
|
||||||
qs_base, filtro_status, busca = _build_solicitacoes_queryset(request, usuario)
|
qs_base = Solicitacao.objects.all().order_by("-criado_em")
|
||||||
|
|
||||||
|
# Head: apenas solicitações dos gestores que ele aprova (subordinados imediatos)
|
||||||
|
if usuario.tem_perfil(UsuarioSistema.Perfil.HEAD) and not usuario.tem_perfil(UsuarioSistema.Perfil.ADMIN):
|
||||||
|
matriculas = matriculas_gestores_do_head(usuario)
|
||||||
|
if matriculas:
|
||||||
|
qs_base = qs_base.filter(solicitante__matricula__in=matriculas)
|
||||||
|
else:
|
||||||
|
qs_base = qs_base.none()
|
||||||
|
|
||||||
|
# Filtro por status (GET)
|
||||||
|
filtro_status = request.GET.get("status", "").strip()
|
||||||
|
if filtro_status:
|
||||||
|
qs_base = qs_base.filter(status=filtro_status)
|
||||||
|
|
||||||
total = qs_base.count()
|
total = qs_base.count()
|
||||||
|
|
||||||
|
|
@ -835,116 +842,15 @@ def todas_solicitacoes_view(request):
|
||||||
"is_solicitante": is_solicitante,
|
"is_solicitante": is_solicitante,
|
||||||
"dados_winthor_organizados": dados_winthor_organizados,
|
"dados_winthor_organizados": dados_winthor_organizados,
|
||||||
})
|
})
|
||||||
_exp_params = {}
|
|
||||||
if filtro_status:
|
|
||||||
_exp_params["status"] = filtro_status
|
|
||||||
if busca:
|
|
||||||
_exp_params["q"] = busca
|
|
||||||
export_query = ("?" + urlencode(_exp_params)) if _exp_params else ""
|
|
||||||
return render(request, "solicitacoes/todas_solicitacoes.html", {
|
return render(request, "solicitacoes/todas_solicitacoes.html", {
|
||||||
"solicitacoes": solicitacoes_page,
|
"solicitacoes": solicitacoes_page,
|
||||||
"solicitacoes_com_acao": solicitacoes_com_acao,
|
"solicitacoes_com_acao": solicitacoes_com_acao,
|
||||||
"total": total,
|
"total": total,
|
||||||
"filtro_status": filtro_status,
|
"filtro_status": filtro_status,
|
||||||
"busca": busca,
|
|
||||||
"export_query": export_query,
|
|
||||||
"status_choices": StatusSolicitacao.choices,
|
"status_choices": StatusSolicitacao.choices,
|
||||||
})
|
})
|
||||||
|
|
||||||
def _build_solicitacoes_queryset(request, usuario: UsuarioSistema):
|
|
||||||
"""Queryset base para listagem/exportação da tela 'Todas as Solicitações'."""
|
|
||||||
qs_base = Solicitacao.objects.all().order_by("-criado_em")
|
|
||||||
|
|
||||||
# Head: apenas solicitações dos gestores que ele aprova (subordinados imediatos)
|
|
||||||
if usuario.tem_perfil(UsuarioSistema.Perfil.HEAD) and not usuario.tem_perfil(
|
|
||||||
UsuarioSistema.Perfil.ADMIN
|
|
||||||
):
|
|
||||||
matriculas = matriculas_gestores_do_head(usuario)
|
|
||||||
if matriculas:
|
|
||||||
qs_base = qs_base.filter(solicitante__matricula__in=matriculas)
|
|
||||||
else:
|
|
||||||
qs_base = qs_base.none()
|
|
||||||
|
|
||||||
filtro_status = request.GET.get("status", "").strip()
|
|
||||||
if filtro_status:
|
|
||||||
qs_base = qs_base.filter(status=filtro_status)
|
|
||||||
|
|
||||||
busca = request.GET.get("q", "").strip()
|
|
||||||
if busca:
|
|
||||||
q_filter = (
|
|
||||||
Q(funcionario__nome__icontains=busca)
|
|
||||||
| Q(solicitante__nome__icontains=busca)
|
|
||||||
| Q(tipo__icontains=busca)
|
|
||||||
)
|
|
||||||
if len(busca) == 36:
|
|
||||||
try:
|
|
||||||
q_filter |= Q(id=uuid.UUID(busca))
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
qs_base = qs_base.filter(q_filter)
|
|
||||||
|
|
||||||
return qs_base, filtro_status, busca
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exportar_todas_solicitacoes_xlsx(request):
|
|
||||||
"""Exporta todas as solicitações visíveis ao usuário com os filtros atuais."""
|
|
||||||
usuario = get_usuario_sistema(request)
|
|
||||||
if usuario.eh_apenas_gestor():
|
|
||||||
return redirect("solicitacoes:dashboard")
|
|
||||||
|
|
||||||
qs_base, filtro_status, busca = _build_solicitacoes_queryset(request, usuario)
|
|
||||||
|
|
||||||
wb = Workbook()
|
|
||||||
ws = wb.active
|
|
||||||
ws.title = "Solicitacoes"
|
|
||||||
ws.append(
|
|
||||||
[
|
|
||||||
"ID",
|
|
||||||
"Tipo",
|
|
||||||
"Colaborador",
|
|
||||||
"Solicitante",
|
|
||||||
"Status",
|
|
||||||
"Criada em",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
def excel_text(value):
|
|
||||||
if value is None:
|
|
||||||
return ""
|
|
||||||
return str(value)
|
|
||||||
|
|
||||||
for solicitacao in qs_base.iterator():
|
|
||||||
ws.append(
|
|
||||||
[
|
|
||||||
excel_text(solicitacao.id),
|
|
||||||
excel_text(solicitacao.get_tipo_display()),
|
|
||||||
excel_text(
|
|
||||||
solicitacao.funcionario.nome if solicitacao.funcionario else ""
|
|
||||||
),
|
|
||||||
excel_text(solicitacao.solicitante.nome),
|
|
||||||
excel_text(solicitacao.get_status_display_para_usuario(usuario)),
|
|
||||||
excel_text(
|
|
||||||
timezone.localtime(solicitacao.criado_em).strftime("%d/%m/%Y %H:%M")
|
|
||||||
),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
output = BytesIO()
|
|
||||||
wb.save(output)
|
|
||||||
output.seek(0)
|
|
||||||
|
|
||||||
suffix = f"_{filtro_status}" if filtro_status else ""
|
|
||||||
filename = f"solicitacoes_todas{suffix}.xlsx"
|
|
||||||
response = HttpResponse(
|
|
||||||
output.getvalue(),
|
|
||||||
content_type=(
|
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
||||||
),
|
|
||||||
)
|
|
||||||
response["Content-Disposition"] = f'attachment; filename="{filename}"'
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@pode_criar_solicitacao
|
@pode_criar_solicitacao
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue