wagtail-enap-designsystem 1.2.1.121__py3-none-any.whl → 1.2.1.122__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of wagtail-enap-designsystem might be problematic. Click here for more details.

enap_designsystem/urls.py CHANGED
@@ -39,7 +39,10 @@ urlpatterns = [
39
39
  path('reports/form/<int:page_id>/', views.form_report, name='form_report'),
40
40
 
41
41
  path('votar/', views.votar_projeto, name='votar_projeto'),
42
- path('estatisticas/', views.estatisticas_votacao, name='estatisticas_votacao'),
43
- path('ranking/', views.ranking_projetos, name='ranking_projetos'),
44
- path('ranking/<int:categoria_id>/', views.ranking_projetos, name='ranking_projetos_categoria'),
42
+
43
+ # URLs auxiliares de votação
44
+ path('api/estatisticas/', views.estatisticas_votacao, name='estatisticas_votacao'),
45
+ path('api/ranking/', views.ranking_projetos, name='ranking_projetos'),
46
+ path('api/ranking/<int:categoria_id>/', views.ranking_projetos, name='ranking_projetos_categoria'),
47
+
45
48
  ]
@@ -2052,225 +2052,190 @@ def save_file_linked_to_form(uploaded_file, page_id, submission_id, field_name):
2052
2052
 
2053
2053
 
2054
2054
 
2055
+ # views.py - View corrigida para votação
2055
2056
 
2056
- # views.py - Views completas do Sistema de Votação
2057
-
2058
- import json
2059
2057
  from django.http import JsonResponse
2060
2058
  from django.views.decorators.http import require_http_methods
2061
- from django.shortcuts import get_object_or_404
2062
- from django.utils import timezone
2063
- from .models import ProjetoVotacao, VotoRegistrado, CategoriaVotacao
2059
+ from django.views.decorators.csrf import csrf_exempt
2060
+ from django.contrib.sessions.models import Session
2061
+ import json
2062
+ import logging
2063
+
2064
+ logger = logging.getLogger(__name__)
2064
2065
 
2065
2066
 
2066
- def get_client_ip(request):
2067
- """Extrai o IP real do cliente"""
2068
- x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
2069
- if x_forwarded_for:
2070
- ip = x_forwarded_for.split(',')[0].strip()
2071
- else:
2072
- ip = request.META.get('REMOTE_ADDR')
2073
- return ip
2074
2067
 
2068
+ @require_http_methods(["POST"])
2069
+ @csrf_exempt
2070
+ # views.py - Versão simples sem restrições de tempo
2075
2071
 
2076
2072
  @require_http_methods(["POST"])
2073
+ @csrf_exempt
2077
2074
  def votar_projeto(request):
2078
- """
2079
- View AJAX para registrar voto em um projeto
2080
- """
2075
+ """View simples para votação - sem restrições"""
2076
+
2081
2077
  try:
2082
- # Parse do JSON
2083
- data = json.loads(request.body)
2078
+ logger.info(f"=== VOTAÇÃO ===")
2079
+
2080
+ # Parse JSON
2081
+ if not request.body:
2082
+ return JsonResponse({
2083
+ 'success': False,
2084
+ 'message': 'Dados não fornecidos'
2085
+ }, status=400)
2086
+
2087
+ try:
2088
+ data = json.loads(request.body)
2089
+ except json.JSONDecodeError:
2090
+ return JsonResponse({
2091
+ 'success': False,
2092
+ 'message': 'JSON inválido'
2093
+ }, status=400)
2094
+
2095
+ # Dados obrigatórios
2084
2096
  projeto_id = data.get('projeto_id')
2085
2097
  categoria_id = data.get('categoria_id')
2086
2098
 
2087
2099
  if not projeto_id or not categoria_id:
2088
2100
  return JsonResponse({
2089
2101
  'success': False,
2090
- 'message': 'Dados inválidos. Projeto e categoria são obrigatórios.'
2102
+ 'message': 'projeto_id e categoria_id são obrigatórios'
2091
2103
  }, status=400)
2092
2104
 
2093
- # Buscar projeto
2094
- projeto = get_object_or_404(ProjetoVotacao, id=projeto_id, ativo=True)
2105
+ # Dados da requisição
2106
+ ip_address = request.META.get('REMOTE_ADDR', 'unknown')
2107
+ user_agent = request.META.get('HTTP_USER_AGENT', '')
2108
+
2109
+ # Importar e validar
2110
+ from .models import VotoRegistrado, ProjetoVotacao, CategoriaVotacao
2095
2111
 
2096
- # Verificar se o projeto pertence à categoria
2097
- if projeto.categoria.id != int(categoria_id):
2112
+ try:
2113
+ projeto = ProjetoVotacao.objects.get(id=projeto_id, ativo=True)
2114
+ categoria = CategoriaVotacao.objects.get(id=categoria_id, ativo=True)
2115
+ except (ProjetoVotacao.DoesNotExist, CategoriaVotacao.DoesNotExist):
2098
2116
  return JsonResponse({
2099
2117
  'success': False,
2100
- 'message': 'Projeto não pertence à categoria especificada.'
2101
- }, status=400)
2102
-
2103
- # Obter dados do request
2104
- ip_address = get_client_ip(request)
2105
- user_agent = request.META.get('HTTP_USER_AGENT', '')[:500]
2118
+ 'message': 'Projeto ou categoria não encontrados'
2119
+ }, status=404)
2106
2120
 
2107
- # Registrar o voto
2121
+ # REGISTRAR VOTO - SEM VERIFICAÇÕES DE DUPLICAÇÃO
2108
2122
  voto = VotoRegistrado.objects.create(
2109
2123
  projeto=projeto,
2124
+ categoria_nome=categoria.nome,
2110
2125
  ip_address=ip_address,
2111
- user_agent=user_agent,
2112
- categoria_nome=projeto.categoria.nome
2126
+ user_agent=user_agent[:500] if user_agent else ''
2113
2127
  )
2114
2128
 
2115
- # Resposta de sucesso
2129
+ logger.info(f"Voto registrado: {voto.id}")
2130
+
2131
+ # Estatísticas
2132
+ total_votos_projeto = VotoRegistrado.objects.filter(projeto=projeto).count()
2133
+ total_votos_categoria = VotoRegistrado.objects.filter(
2134
+ projeto__categoria=categoria
2135
+ ).count()
2136
+
2116
2137
  return JsonResponse({
2117
2138
  'success': True,
2118
2139
  'message': 'Voto registrado com sucesso!',
2119
- 'voto_id': str(voto.id),
2120
- 'projeto_id': projeto.id,
2121
- 'categoria_id': projeto.categoria.id,
2122
- 'total_votos': projeto.total_votos,
2123
- 'timestamp': voto.timestamp.isoformat()
2140
+ 'voto_id': voto.id,
2141
+ 'total_votos': total_votos_projeto,
2142
+ 'total_votos_categoria': total_votos_categoria,
2143
+ 'projeto_titulo': projeto.titulo
2124
2144
  })
2125
2145
 
2126
- except json.JSONDecodeError:
2127
- return JsonResponse({
2128
- 'success': False,
2129
- 'message': 'Dados JSON inválidos.'
2130
- }, status=400)
2131
-
2132
- except ProjetoVotacao.DoesNotExist:
2133
- return JsonResponse({
2134
- 'success': False,
2135
- 'message': 'Projeto não encontrado ou inativo.'
2136
- }, status=404)
2137
-
2138
2146
  except Exception as e:
2139
- # Log do erro em produção
2140
- import logging
2141
- logger = logging.getLogger(__name__)
2142
- logger.error(f"Erro ao processar voto: {str(e)}", exc_info=True)
2143
-
2147
+ logger.error(f"Erro: {str(e)}", exc_info=True)
2144
2148
  return JsonResponse({
2145
2149
  'success': False,
2146
- 'message': 'Erro interno do servidor. Tente novamente.'
2150
+ 'message': f'Erro interno: {str(e)}'
2147
2151
  }, status=500)
2148
-
2152
+ # Views auxiliares também corrigidas
2149
2153
 
2150
2154
  @require_http_methods(["GET"])
2151
2155
  def estatisticas_votacao(request):
2152
- """
2153
- View AJAX para obter estatísticas da votação
2154
- """
2156
+ """Estatísticas da votação"""
2155
2157
  try:
2158
+ from .models import VotoRegistrado, CategoriaVotacao, ProjetoVotacao
2159
+ from django.db.models import Count
2160
+
2156
2161
  # Estatísticas gerais
2157
2162
  total_votos = VotoRegistrado.objects.count()
2158
- total_projetos = ProjetoVotacao.objects.filter(ativo=True).count()
2159
2163
  total_categorias = CategoriaVotacao.objects.filter(ativo=True).count()
2164
+ total_projetos = ProjetoVotacao.objects.filter(ativo=True).count()
2160
2165
 
2161
- # Estatísticas por categoria
2162
- categorias_stats = []
2163
- for categoria in CategoriaVotacao.objects.filter(ativo=True).order_by('ordem'):
2164
- projetos_categoria = categoria.projetos.filter(ativo=True)
2165
- votos_categoria = VotoRegistrado.objects.filter(projeto__in=projetos_categoria).count()
2166
-
2167
- # Projeto mais votado da categoria
2168
- projeto_top = None
2169
- if projetos_categoria.exists():
2170
- projeto_mais_votado = max(projetos_categoria, key=lambda p: p.total_votos)
2171
- if projeto_mais_votado.total_votos > 0:
2172
- projeto_top = {
2173
- 'id': projeto_mais_votado.id,
2174
- 'titulo': projeto_mais_votado.titulo,
2175
- 'votos': projeto_mais_votado.total_votos
2176
- }
2177
-
2178
- categorias_stats.append({
2179
- 'id': categoria.id,
2180
- 'nome': categoria.nome,
2181
- 'total_projetos': projetos_categoria.count(),
2182
- 'total_votos': votos_categoria,
2183
- 'projeto_top': projeto_top
2184
- })
2185
-
2186
- # Projetos mais votados (top 5)
2187
- projetos_top = []
2188
- for projeto in ProjetoVotacao.objects.filter(ativo=True):
2189
- projetos_top.append({
2190
- 'id': projeto.id,
2191
- 'titulo': projeto.titulo,
2192
- 'categoria': projeto.categoria.nome,
2193
- 'votos': projeto.total_votos
2194
- })
2166
+ # Votos por categoria (usando relacionamento)
2167
+ votos_categoria = (VotoRegistrado.objects
2168
+ .values('projeto__categoria__nome', 'projeto__categoria__id')
2169
+ .annotate(total=Count('id'))
2170
+ .order_by('-total'))
2195
2171
 
2196
- # Ordenar por votos (descending)
2197
- projetos_top = sorted(projetos_top, key=lambda p: p['votos'], reverse=True)[:5]
2172
+ # Projetos mais votados
2173
+ projetos_top = (VotoRegistrado.objects
2174
+ .values('projeto__titulo', 'projeto__id', 'projeto__categoria__nome')
2175
+ .annotate(total=Count('id'))
2176
+ .order_by('-total')[:10])
2198
2177
 
2199
2178
  return JsonResponse({
2200
2179
  'success': True,
2201
- 'data': {
2202
- 'resumo': {
2203
- 'total_votos': total_votos,
2204
- 'total_projetos': total_projetos,
2205
- 'total_categorias': total_categorias
2206
- },
2207
- 'categorias': categorias_stats,
2208
- 'projetos_top': projetos_top,
2209
- 'timestamp': timezone.now().isoformat()
2180
+ 'estatisticas': {
2181
+ 'total_votos': total_votos,
2182
+ 'total_categorias': total_categorias,
2183
+ 'total_projetos': total_projetos,
2184
+ 'votos_por_categoria': list(votos_categoria),
2185
+ 'projetos_mais_votados': list(projetos_top)
2210
2186
  }
2211
2187
  })
2212
2188
 
2213
2189
  except Exception as e:
2214
- import logging
2215
- logger = logging.getLogger(__name__)
2216
- logger.error(f"Erro ao obter estatísticas: {str(e)}", exc_info=True)
2217
-
2190
+ logger.error(f"Erro estatísticas: {e}")
2218
2191
  return JsonResponse({
2219
2192
  'success': False,
2220
- 'message': 'Erro ao obter estatísticas.'
2193
+ 'message': 'Erro ao buscar estatísticas'
2221
2194
  }, status=500)
2222
2195
 
2223
2196
 
2224
- @require_http_methods(["GET"])
2197
+ @require_http_methods(["GET"])
2225
2198
  def ranking_projetos(request, categoria_id=None):
2226
- """
2227
- View AJAX para obter ranking de projetos
2228
- """
2199
+ """Ranking de projetos por categoria"""
2229
2200
  try:
2230
- # Filtrar por categoria se especificado
2231
- if categoria_id:
2232
- categoria = get_object_or_404(CategoriaVotacao, id=categoria_id, ativo=True)
2233
- projetos = ProjetoVotacao.objects.filter(categoria=categoria, ativo=True)
2234
- else:
2235
- projetos = ProjetoVotacao.objects.filter(ativo=True)
2236
-
2237
- # Criar lista com dados dos projetos
2238
- ranking = []
2239
- for projeto in projetos:
2240
- ranking.append({
2241
- 'id': projeto.id,
2242
- 'titulo': projeto.titulo,
2243
- 'categoria': projeto.categoria.nome,
2244
- 'equipe': projeto.nome_equipe,
2245
- 'total_votos': projeto.total_votos,
2246
- 'destacado': projeto.destacado
2247
- })
2201
+ from .models import VotoRegistrado, ProjetoVotacao, CategoriaVotacao
2202
+ from django.db.models import Count
2248
2203
 
2249
- # Ordenar por votos (descending)
2250
- ranking.sort(key=lambda p: p['total_votos'], reverse=True)
2204
+ # Base query
2205
+ queryset = VotoRegistrado.objects.select_related('projeto', 'projeto__categoria')
2206
+
2207
+ # Filtrar por categoria se fornecida
2208
+ if categoria_id:
2209
+ try:
2210
+ categoria = CategoriaVotacao.objects.get(id=categoria_id, ativo=True)
2211
+ queryset = queryset.filter(projeto__categoria=categoria)
2212
+ except CategoriaVotacao.DoesNotExist:
2213
+ return JsonResponse({
2214
+ 'success': False,
2215
+ 'message': 'Categoria não encontrada'
2216
+ }, status=404)
2217
+
2218
+ # Ranking
2219
+ ranking = (queryset
2220
+ .values(
2221
+ 'projeto__id',
2222
+ 'projeto__titulo',
2223
+ 'projeto__categoria__nome',
2224
+ 'projeto__categoria__id',
2225
+ 'projeto__nome_equipe'
2226
+ )
2227
+ .annotate(total_votos=Count('id'))
2228
+ .order_by('-total_votos'))
2251
2229
 
2252
2230
  return JsonResponse({
2253
2231
  'success': True,
2254
- 'data': {
2255
- 'ranking': ranking,
2256
- 'categoria': categoria.nome if categoria_id else 'Todas',
2257
- 'total_projetos': len(ranking),
2258
- 'timestamp': timezone.now().isoformat()
2259
- }
2232
+ 'ranking': list(ranking),
2233
+ 'categoria_id': categoria_id
2260
2234
  })
2261
2235
 
2262
- except CategoriaVotacao.DoesNotExist:
2263
- return JsonResponse({
2264
- 'success': False,
2265
- 'message': 'Categoria não encontrada.'
2266
- }, status=404)
2267
-
2268
2236
  except Exception as e:
2269
- import logging
2270
- logger = logging.getLogger(__name__)
2271
- logger.error(f"Erro ao obter ranking: {str(e)}", exc_info=True)
2272
-
2237
+ logger.error(f"Erro ranking: {e}")
2273
2238
  return JsonResponse({
2274
2239
  'success': False,
2275
- 'message': 'Erro ao obter ranking.'
2240
+ 'message': 'Erro ao buscar ranking'
2276
2241
  }, status=500)