· 7 months ago · Mar 14, 2025, 01:05 PM
1# Django Core
2from django.shortcuts import render, redirect, get_object_or_404
3from django.http import HttpResponse, JsonResponse, HttpResponseNotAllowed
4from django.core.paginator import Paginator
5from django.db.models import Q
6from django.views.generic import ListView
7from django.views.decorators.csrf import csrf_exempt
8from django.views.decorators.http import require_http_methods
9from django.views.decorators.http import require_GET, require_POST
10from django.db.models import Sum
11from django.contrib import messages
12from usuarios.models import FormaPago
13
14# Autenticación
15from django.contrib.auth import authenticate, login, logout
16from django.contrib.auth.decorators import login_required, user_passes_test
17from .models import Cliente, DireccionInstalacion
18
19# Formularios locales
20from .forms import (
21 ClienteForm,
22 ContratoForm,
23 DireccionFormSet,
24 DireccionForm,
25 ServicioForm
26)
27
28# Modelos locales
29from .models import (
30 Cliente,
31 Contrato,
32 Servicio,
33 Usuario,
34 Rol,
35 Empleado,
36 Zona,
37 Pago,
38 DireccionInstalacion # Usa la clase actualizada
39)
40
41# Librerías estándar
42import random
43import json
44import traceback
45
46def login_view(request):
47 if request.method == "POST":
48 username = request.POST['username']
49 password = request.POST['password']
50 user = authenticate(request, username=username, password=password)
51 if user is not None:
52 login(request, user)
53 return redirect('dashboard') # Redirigir al dashboard si el login es exitoso
54 else:
55 messages.error(request, "Usuario o contraseña incorrectos")
56 return render(request, 'usuarios/login.html')
57
58def logout_view(request):
59 logout(request)
60 return redirect('login') # Redirigir al login después de cerrar sesión
61
62@login_required
63def dashboard(request):
64 return render(request, 'usuarios/dashboard.html')
65
66### CRUD USUARIOS ###
67
68@login_required
69def lista_usuarios(request):
70 usuarios = Usuario.objects.all()
71 roles = Rol.objects.all() # ✅ Asegurar que los roles estén disponibles en la plantilla
72 return render(request, 'usuarios/lista_usuarios.html', {'usuarios': usuarios, 'roles': roles})
73
74@login_required
75def editar_usuario(request, user_id):
76 usuario = get_object_or_404(Usuario, id=user_id)
77
78 if request.method == 'POST':
79 usuario.username = request.POST['username']
80 usuario.first_name = request.POST['first_name']
81 usuario.last_name = request.POST['last_name']
82 usuario.email = request.POST['email']
83 usuario.rol_id = request.POST.get('rol')
84 usuario.estatus = 'estatus' in request.POST # Checkbox activo/inactivo
85 usuario.save()
86 messages.success(request, "Usuario actualizado correctamente.")
87 return redirect('lista_usuarios')
88
89 roles = Rol.objects.all()
90 return render(request, 'usuarios/editar_usuario.html', {'usuario': usuario, 'roles': roles})
91
92@login_required
93def eliminar_usuario(request, user_id):
94 usuario = get_object_or_404(Usuario, id=user_id)
95 usuario.delete()
96 messages.success(request, "Usuario eliminado correctamente.")
97 return redirect('lista_usuarios')
98
99@login_required
100def crear_usuario(request):
101 if request.method == "POST":
102 username = request.POST.get('username').strip()
103 first_name = request.POST.get('first_name').strip()
104 last_name = request.POST.get('last_name').strip()
105 email = request.POST.get('email').strip()
106 password = request.POST.get('password')
107 rol_id = request.POST.get('rol')
108
109 # Validar que no haya campos vacíos
110 if not username or not first_name or not last_name or not email or not password or not rol_id:
111 messages.error(request, "Todos los campos son obligatorios.")
112 return redirect('lista_usuarios')
113
114 # Validar si el usuario ya existe
115 if Usuario.objects.filter(username=username).exists():
116 messages.error(request, "El nombre de usuario ya está en uso.")
117 return redirect('lista_usuarios')
118
119 # Verificar si el rol existe en la base de datos
120 try:
121 rol = Rol.objects.get(id=rol_id)
122 except Rol.DoesNotExist:
123 messages.error(request, "El rol seleccionado no es válido.")
124 return redirect('lista_usuarios')
125
126 # Crear usuario y cifrar la contraseña
127 nuevo_usuario = Usuario(
128 username=username,
129 first_name=first_name,
130 last_name=last_name,
131 email=email,
132 rol=rol
133 )
134 nuevo_usuario.set_password(password) # 🔐 Cifra la contraseña
135 nuevo_usuario.save()
136
137 messages.success(request, f"Usuario '{username}' creado correctamente.")
138 return redirect('lista_usuarios')
139
140 # Si el método no es POST, regresar la lista de usuarios
141 usuarios = Usuario.objects.all()
142 roles = Rol.objects.all()
143 return render(request, 'usuarios/lista_usuarios.html', {'usuarios': usuarios, 'roles': roles})
144
145
146### CRUD EMPLEADOS ###
147
148@login_required
149def lista_empleados(request):
150 empleados = Empleado.objects.all()
151 return render(request, 'usuarios/lista_empleados.html', {'empleados': empleados})
152
153@login_required
154def crear_empleado(request):
155 if request.method == "POST":
156 nombre = request.POST['nombre']
157 apellido = request.POST['apellido']
158 dni = request.POST['dni']
159 rol_id = request.POST.get('rol')
160 rol = Rol.objects.get(id=rol_id)
161
162 Empleado.objects.create(nombre=nombre, apellido=apellido, dni=dni, rol=rol)
163 messages.success(request, "Empleado agregado correctamente.")
164 return redirect('lista_empleados')
165
166 roles = Rol.objects.all()
167 return render(request, 'usuarios/crear_empleado.html', {'roles': roles})
168
169@login_required
170def editar_empleado(request, emp_id):
171 empleado = get_object_or_404(Empleado, id=emp_id)
172
173 if request.method == "POST":
174 empleado.nombre = request.POST['nombre']
175 empleado.apellido = request.POST['apellido']
176 empleado.dni = request.POST['dni']
177 empleado.rol_id = request.POST.get('rol')
178 empleado.save()
179 messages.success(request, "Empleado actualizado correctamente.")
180 return redirect('lista_empleados')
181
182 roles = Rol.objects.all()
183 return render(request, 'usuarios/editar_empleado.html', {'empleado': empleado, 'roles': roles})
184
185@login_required
186def eliminar_empleado(request, emp_id):
187 empleado = get_object_or_404(Empleado, id=emp_id)
188 empleado.delete()
189 messages.success(request, "Empleado eliminado correctamente.")
190 return redirect('lista_empleados')
191
192### CRUD ROLES ###
193
194@login_required
195def lista_roles(request):
196 roles = Rol.objects.all()
197 return render(request, 'usuarios/lista_roles.html', {'roles': roles})
198
199@login_required
200def crear_rol(request):
201 if request.method == "POST":
202 nombre = request.POST['nombre']
203 Rol.objects.create(nombre=nombre)
204 messages.success(request, "Rol creado correctamente.")
205 return redirect('lista_roles')
206
207 return render(request, 'usuarios/crear_rol.html')
208
209@login_required
210def editar_rol(request, rol_id):
211 rol = get_object_or_404(Rol, id=rol_id)
212
213 if request.method == "POST":
214 rol.nombre = request.POST['nombre']
215 rol.save()
216 messages.success(request, "Rol actualizado correctamente.")
217 return redirect('lista_roles')
218
219 return render(request, 'usuarios/editar_rol.html', {'rol': rol})
220
221@login_required
222def eliminar_rol(request, rol_id):
223 rol = get_object_or_404(Rol, id=rol_id)
224 rol.delete()
225 messages.success(request, "Rol eliminado correctamente.")
226 return redirect('lista_roles')
227
228
229@login_required
230def editar_usuario(request, user_id):
231 usuario = get_object_or_404(Usuario, id=user_id)
232
233 if request.method == "POST":
234 usuario.username = request.POST.get('username').strip()
235 usuario.first_name = request.POST.get('first_name').strip()
236 usuario.last_name = request.POST.get('last_name').strip()
237 usuario.email = request.POST.get('email').strip()
238 rol_id = request.POST.get('rol')
239 usuario.estatus = 'estatus' in request.POST # Checkbox para activar/desactivar usuario
240
241 # Validar si el usuario ya existe con otro ID
242 if Usuario.objects.exclude(id=user_id).filter(username=usuario.username).exists():
243 messages.error(request, "El nombre de usuario ya está en uso por otro usuario.")
244 return redirect('lista_usuarios')
245
246 # Verificar si el rol existe
247 try:
248 usuario.rol = Rol.objects.get(id=rol_id)
249 except Rol.DoesNotExist:
250 messages.error(request, "El rol seleccionado no es válido.")
251 return redirect('lista_usuarios')
252
253 usuario.save()
254 messages.success(request, f"Usuario '{usuario.username}' actualizado correctamente.")
255 return redirect('lista_usuarios')
256
257 roles = Rol.objects.all()
258 return render(request, 'usuarios/editar_usuario.html', {'usuario': usuario, 'roles': roles})
259
260
261@login_required
262def eliminar_usuario(request, user_id):
263 usuario = get_object_or_404(Usuario, id=user_id)
264 usuario.delete()
265 messages.success(request, f"Usuario '{usuario.username}' eliminado correctamente.")
266 return redirect('lista_usuarios')
267
268
269# Función para verificar si el usuario es administrador
270def es_admin(user):
271 return user.is_authenticated and user.is_superuser
272
273### RESTRINGIR VISTAS A ADMINISTRADORES ###
274
275@login_required
276@user_passes_test(es_admin, login_url='/dashboard/') # Redirigir si no es admin
277def lista_usuarios(request):
278 usuarios = Usuario.objects.all()
279 roles = Rol.objects.all()
280 return render(request, 'usuarios/lista_usuarios.html', {'usuarios': usuarios, 'roles': roles})
281
282@login_required
283@user_passes_test(es_admin, login_url='/dashboard/')
284def crear_usuario(request):
285 if request.method == "POST":
286 username = request.POST.get('username').strip()
287 first_name = request.POST.get('first_name').strip()
288 last_name = request.POST.get('last_name').strip()
289 email = request.POST.get('email').strip()
290 password = request.POST.get('password')
291 rol_id = request.POST.get('rol')
292
293 if Usuario.objects.filter(username=username).exists():
294 messages.error(request, "El nombre de usuario ya está en uso.")
295 return redirect('lista_usuarios')
296
297 try:
298 rol = Rol.objects.get(id=rol_id)
299 except Rol.DoesNotExist:
300 messages.error(request, "El rol seleccionado no es válido.")
301 return redirect('lista_usuarios')
302
303 nuevo_usuario = Usuario(
304 username=username,
305 first_name=first_name,
306 last_name=last_name,
307 email=email,
308 rol=rol
309 )
310 nuevo_usuario.set_password(password)
311 nuevo_usuario.save()
312
313 messages.success(request, f"Usuario '{username}' creado correctamente.")
314 return redirect('lista_usuarios')
315
316 return redirect('lista_usuarios')
317
318@login_required
319@user_passes_test(es_admin, login_url='/dashboard/')
320def eliminar_usuario(request, user_id):
321 usuario = get_object_or_404(Usuario, id=user_id)
322 usuario.delete()
323 messages.success(request, f"Usuario '{usuario.username}' eliminado correctamente.")
324 return redirect('lista_usuarios')
325
326@login_required
327@user_passes_test(es_admin, login_url='/dashboard/')
328def lista_roles(request):
329 roles = Rol.objects.all()
330 return render(request, 'usuarios/lista_roles.html', {'roles': roles})
331
332@login_required
333@user_passes_test(es_admin, login_url='/dashboard/')
334def crear_rol(request):
335 if request.method == "POST":
336 nombre = request.POST['nombre']
337 Rol.objects.create(nombre=nombre)
338 messages.success(request, "Rol creado correctamente.")
339 return redirect('lista_roles')
340
341 return render(request, 'usuarios/crear_rol.html')
342
343@login_required
344@user_passes_test(es_admin, login_url='/dashboard/')
345def eliminar_rol(request, rol_id):
346 rol = get_object_or_404(Rol, id=rol_id)
347 rol.delete()
348 messages.success(request, "Rol eliminado correctamente.")
349 return redirect('lista_roles')
350
351
352def lista_zonas(request):
353 zonas = Zona.objects.all()
354 return render(request, "usuarios/lista_zonas.html", {"zonas": zonas})
355
356def crear_zona(request):
357 if request.method == "POST":
358 nombre = request.POST["nombre"]
359 Zona.objects.create(nombre=nombre)
360 messages.success(request, "Zona creada correctamente.")
361 return redirect("lista_zonas")
362 return redirect("lista_zonas")
363
364def editar_zona(request, zona_id):
365 zona = get_object_or_404(Zona, id=zona_id)
366 if request.method == "POST":
367 zona.nombre = request.POST["nombre"]
368 zona.save()
369 messages.success(request, "Zona actualizada correctamente.")
370 return redirect("lista_zonas")
371 return redirect("lista_zonas")
372
373def eliminar_zona(request, zona_id):
374 zona = get_object_or_404(Zona, id=zona_id)
375 zona.delete()
376 messages.success(request, "Zona eliminada correctamente.")
377 return redirect("lista_zonas")
378
379
380def get_zonas(request):
381 zonas = list(Zona.objects.values('id', 'nombre'))
382 return JsonResponse({'zonas': zonas})
383
384
385
386# Lista todos los clientes
387class ClienteListView(ListView):
388 model = Cliente
389 template_name = 'usuarios/cliente_list.html'
390 context_object_name = 'clientes'
391 paginate_by = 10 # Muestra de 10 en 10
392
393 def get_queryset(self):
394 queryset = super().get_queryset()
395 buscar = self.request.GET.get('buscar', '')
396 if buscar:
397 queryset = queryset.filter(
398 Q(nombre__icontains=buscar) |
399 Q(apellido_paterno__icontains=buscar) |
400 Q(apellido_materno__icontains=buscar) |
401 Q(numero_documento__icontains=buscar)
402 )
403 return queryset.order_by('nombre')
404
405 def get_context_data(self, **kwargs):
406 context = super().get_context_data(**kwargs)
407 context['buscar'] = self.request.GET.get('buscar', '')
408 return context
409
410# Crea un nuevo cliente con múltiples direcciones
411def crear_cliente(request):
412 if request.method == 'POST':
413 form = ClienteForm(request.POST)
414 formset = DireccionFormSet(request.POST)
415 if form.is_valid() and formset.is_valid():
416 cliente = form.save()
417 direcciones = formset.save(commit=False)
418 for direccion in direcciones:
419 direccion.cliente = cliente
420 direccion.save()
421 return redirect('cliente_list')
422 else:
423 form = ClienteForm()
424 formset = DireccionFormSet()
425
426 return render(request, 'usuarios/cliente_form.html', {
427 'form': form,
428 'formset': formset,
429 })
430
431
432def editar_cliente(request, pk):
433 cliente = get_object_or_404(Cliente, pk=pk)
434
435 if request.method == "POST":
436 form = ClienteForm(request.POST, instance=cliente)
437 formset = DireccionFormSet(request.POST, instance=cliente)
438
439 if form.is_valid() and formset.is_valid():
440 form.save()
441 formset.save()
442 print("✅ Cliente guardado correctamente")
443 return redirect('cliente_list')
444
445 else:
446 print("❌ Error en el formulario:")
447 print(form.errors)
448 print(formset.errors)
449
450 else:
451 form = ClienteForm(instance=cliente)
452 formset = DireccionFormSet(instance=cliente)
453
454 return render(request, 'usuarios/cliente_form.html', {'form': form, 'formset': formset})
455
456def obtener_direcciones_cliente(request, cliente_id):
457 try:
458 cliente = Cliente.objects.get(id=cliente_id)
459 data = {'direccion': cliente.direccion} # Asegúrate de que 'direccion' sea el campo correcto
460 except Cliente.DoesNotExist:
461 data = {'direccion': ''} # Si el cliente no existe, devuelve una dirección vacía
462 return JsonResponse(data)
463
464def crear_contrato(request):
465 if request.method == 'POST':
466 form = ContratoForm(request.POST, cliente_id=request.POST.get('cliente'))
467 if form.is_valid():
468 contrato = form.save(commit=False)
469 contrato.total = sum(servicio.precio for servicio in form.cleaned_data['servicios'])
470 contrato.save()
471 form.save_m2m()
472 return redirect('lista_contratos')
473 else:
474 form = ContratoForm()
475
476 return render(request, 'usuarios/contrato_form.html', {'form': form})
477
478# Editar un contrato existente
479def editar_contrato(request, pk):
480 contrato = get_object_or_404(Contrato, pk=pk)
481 if request.method == 'POST':
482 form = ContratoForm(request.POST, instance=contrato, cliente_id=contrato.cliente.id)
483 if form.is_valid():
484 contrato = form.save(commit=False)
485 contrato.total = sum(servicio.precio for servicio in form.cleaned_data['servicios'])
486 contrato.save()
487 form.save_m2m()
488 return redirect('lista_contratos')
489 else:
490 form = ContratoForm(instance=contrato, cliente_id=contrato.cliente.id)
491
492 return render(request, 'usuarios/contrato_form.html', {'form': form})
493
494def lista_contratos(request):
495 contratos = Contrato.objects.all()
496 return render(request, 'usuarios/lista_contratos.html', {'contratos': contratos})
497
498def eliminar_contrato(request, pk):
499 contrato = get_object_or_404(Contrato, pk=pk)
500 contrato.delete()
501 messages.success(request, "Contrato eliminado correctamente.")
502 return redirect('lista_contratos') # Asegúrate de que esta vista existe en `urls.py`
503
504
505def lista_servicios(request):
506 servicios = Servicio.objects.all()
507 return render(request, 'usuarios/lista_servicios.html', {'servicios': servicios})
508
509def agregar_servicio(request):
510 if request.method == 'POST':
511 form = ServicioForm(request.POST)
512 if form.is_valid():
513 form.save()
514 return redirect('servicios')
515 else:
516 form = ServicioForm()
517 return render(request, 'usuarios/agregar_servicio.html', {'form': form})
518
519def editar_servicio(request, servicio_id):
520 servicio = get_object_or_404(Servicio, pk=servicio_id)
521 if request.method == 'POST':
522 form = ServicioForm(request.POST, instance=servicio)
523 if form.is_valid():
524 form.save()
525 return redirect('servicios')
526 else:
527 form = ServicioForm(instance=servicio)
528 return render(request, 'usuarios/editar_servicio.html', {'form': form, 'servicio': servicio})
529
530
531def eliminar_servicio(request, servicio_id):
532 servicio = get_object_or_404(Servicio, pk=servicio_id)
533 try:
534 servicio.delete()
535 messages.success(request, "Servicio eliminado correctamente.")
536 except Exception as e:
537 messages.error(request, f"No se pudo eliminar el servicio: {e}")
538
539 return redirect('servicios')
540# API para obtener la lista de clientes
541def api_clientes(request):
542 clientes = Cliente.objects.all().values("id", "numero_documento", "nombre")
543 return JsonResponse(list(clientes), safe=False)
544
545# API para obtener direcciones del cliente seleccionado
546def api_direcciones_cliente(request, cliente_id):
547 direcciones = DireccionInstalacion.objects.filter(cliente_id=cliente_id).values("id", "direccion", "zona__nombre")
548 return JsonResponse(list(direcciones), safe=False)
549
550
551# Vista para renderizar la página de pago de servicios
552def pago_servicios(request):
553 return render(request, 'usuarios/pago_servicios.html')
554
555# API para buscar clientes por nombre o número de documento
556def buscar_cliente(request):
557 query = request.GET.get('query', '')
558
559 if query:
560 clientes = Cliente.objects.filter(
561 Q(nombre__icontains=query) | Q(numero_documento__icontains=query)
562 ).values('id', 'nombre', 'telefono')
563
564 clientes_lista = list(clientes)
565
566 # Agregar dirección y servicio del cliente si existen
567 for cliente in clientes_lista:
568 direccion = DireccionInstalacion.objects.filter(cliente_id=cliente['id']).first()
569 servicio = Servicio.objects.filter(cliente_id=cliente['id']).first()
570
571 cliente['direccion'] = direccion.direccion if direccion else "No registrada"
572 cliente['servicio'] = servicio.nombre if servicio else "Sin servicio"
573
574 return JsonResponse(clientes_lista, safe=False)
575
576 return JsonResponse({'error': 'No se encontraron clientes'}, status=404)
577
578
579# API para obtener los pagos pendientes del cliente
580def obtener_pagos_cliente(request, cliente_id):
581 try:
582 cliente = get_object_or_404(Cliente, id=cliente_id)
583 pagos_pendientes = Pago.objects.filter(cliente=cliente).values(
584 'id', 'mes_pagado', 'monto', 'servicio__nombre'
585 )
586
587 if pagos_pendientes:
588 return JsonResponse(list(pagos_pendientes), safe=False)
589 else:
590 return JsonResponse({'mensaje': 'No hay pagos pendientes para este cliente'})
591
592 except Exception as e:
593 return JsonResponse({'error': f'Error al obtener pagos: {str(e)}'}, status=500)
594
595# API para obtener las formas de pago
596def obtener_formas_pago(request):
597 formas_pago = FormaPago.objects.all().values('id', 'nombre')
598 return JsonResponse(list(formas_pago), safe=False)
599
600# API para registrar un pago
601def registrar_pago(request):
602 if request.method == "POST":
603 try:
604 cliente_id = request.POST.get('cliente_id')
605 mes_pagado = request.POST.get('mes_pagado')
606 monto = request.POST.get('monto')
607 forma_pago_id = request.POST.get('forma_pago')
608 numero_boleta = request.POST.get('numero_boleta')
609
610 cliente = get_object_or_404(Cliente, id=cliente_id)
611 forma_pago = get_object_or_404(FormaPago, id=forma_pago_id)
612
613 # Obtener el servicio asociado al cliente
614 servicio = Servicio.objects.filter(cliente=cliente).first()
615
616 if not servicio:
617 return JsonResponse({'error': 'No se encontró un servicio asociado al cliente'}, status=400)
618
619 # Registrar el pago
620 nuevo_pago = Pago.objects.create(
621 cliente=cliente,
622 servicio=servicio,
623 mes_pagado=mes_pagado,
624 monto=monto,
625 forma_pago=forma_pago,
626 numero_boleta=numero_boleta
627 )
628
629 return JsonResponse({'mensaje': 'Pago registrado correctamente'})
630
631 except Exception as e:
632 return JsonResponse({'error': f'Error al registrar pago: {str(e)}'}, status=500)
633
634 return JsonResponse({'error': 'Método no permitido'}, status=405)