· 10 months ago · Feb 27, 2025, 01:10 AM
1from django.contrib import messages
2from django.views.decorators.http import require_http_methods
3from django.contrib.auth import authenticate, login, logout
4from django.contrib.auth.decorators import login_required, user_passes_test
5from django.http import HttpResponse, JsonResponse, HttpResponseNotAllowed
6from django.shortcuts import get_object_or_404, render, redirect
7from django.views.decorators.csrf import csrf_exempt
8from reportlab.lib.pagesizes import letter
9from reportlab.pdfgen import canvas
10import random, json
11import traceback # Importa traceback una sola vez
12from .models import Cliente, Contrato, Servicio, Usuario, Rol, Empleado, Zona, Avenida, Direccion # Importa todos los modelos en una línea
13from .forms import ClienteForm, ContratoForm # Importa los formularios
14from django.core.paginator import Paginator
15from django.db.models import Q # Importa Q para consultas OR
16from .forms import ContratoForm
17
18
19
20@csrf_exempt
21def registrar_cliente(request):
22 if request.method == "POST":
23 try:
24 form = ClienteForm(request.POST)
25 if form.is_valid():
26 form.save()
27 return JsonResponse({"mensaje": "Cliente agregado correctamente"}, status=200)
28 else:
29 return JsonResponse({"error": "Error en el formulario", "detalles": form.errors}, status=400)
30 except Exception as e:
31 # Capturamos el traceback para ver detalles del error.
32 traceback_str = traceback.format_exc()
33 return JsonResponse({"error": "Error interno", "detalles": traceback_str}, status=500)
34 return JsonResponse({"error": "Método no permitido"}, status=405)
35
36
37
38
39
40
41def login_view(request):
42 if request.method == "POST":
43 username = request.POST['username']
44 password = request.POST['password']
45 user = authenticate(request, username=username, password=password)
46 if user is not None:
47 login(request, user)
48 return redirect('dashboard') # Redirigir al dashboard si el login es exitoso
49 else:
50 messages.error(request, "Usuario o contraseña incorrectos")
51 return render(request, 'usuarios/login.html')
52
53def logout_view(request):
54 logout(request)
55 return redirect('login') # Redirigir al login después de cerrar sesión
56
57@login_required
58def dashboard(request):
59 return render(request, 'usuarios/dashboard.html')
60
61### CRUD USUARIOS ###
62
63@login_required
64def lista_usuarios(request):
65 usuarios = Usuario.objects.all()
66 roles = Rol.objects.all() # ✅ Asegurar que los roles estén disponibles en la plantilla
67 return render(request, 'usuarios/lista_usuarios.html', {'usuarios': usuarios, 'roles': roles})
68
69@login_required
70def editar_usuario(request, user_id):
71 usuario = get_object_or_404(Usuario, id=user_id)
72
73 if request.method == 'POST':
74 usuario.username = request.POST['username']
75 usuario.first_name = request.POST['first_name']
76 usuario.last_name = request.POST['last_name']
77 usuario.email = request.POST['email']
78 usuario.rol_id = request.POST.get('rol')
79 usuario.estatus = 'estatus' in request.POST # Checkbox activo/inactivo
80 usuario.save()
81 messages.success(request, "Usuario actualizado correctamente.")
82 return redirect('lista_usuarios')
83
84 roles = Rol.objects.all()
85 return render(request, 'usuarios/editar_usuario.html', {'usuario': usuario, 'roles': roles})
86
87@login_required
88def eliminar_usuario(request, user_id):
89 usuario = get_object_or_404(Usuario, id=user_id)
90 usuario.delete()
91 messages.success(request, "Usuario eliminado correctamente.")
92 return redirect('lista_usuarios')
93
94@login_required
95def crear_usuario(request):
96 if request.method == "POST":
97 username = request.POST.get('username').strip()
98 first_name = request.POST.get('first_name').strip()
99 last_name = request.POST.get('last_name').strip()
100 email = request.POST.get('email').strip()
101 password = request.POST.get('password')
102 rol_id = request.POST.get('rol')
103
104 # Validar que no haya campos vacíos
105 if not username or not first_name or not last_name or not email or not password or not rol_id:
106 messages.error(request, "Todos los campos son obligatorios.")
107 return redirect('lista_usuarios')
108
109 # Validar si el usuario ya existe
110 if Usuario.objects.filter(username=username).exists():
111 messages.error(request, "El nombre de usuario ya está en uso.")
112 return redirect('lista_usuarios')
113
114 # Verificar si el rol existe en la base de datos
115 try:
116 rol = Rol.objects.get(id=rol_id)
117 except Rol.DoesNotExist:
118 messages.error(request, "El rol seleccionado no es válido.")
119 return redirect('lista_usuarios')
120
121 # Crear usuario y cifrar la contraseña
122 nuevo_usuario = Usuario(
123 username=username,
124 first_name=first_name,
125 last_name=last_name,
126 email=email,
127 rol=rol
128 )
129 nuevo_usuario.set_password(password) # 🔐 Cifra la contraseña
130 nuevo_usuario.save()
131
132 messages.success(request, f"Usuario '{username}' creado correctamente.")
133 return redirect('lista_usuarios')
134
135 # Si el método no es POST, regresar la lista de usuarios
136 usuarios = Usuario.objects.all()
137 roles = Rol.objects.all()
138 return render(request, 'usuarios/lista_usuarios.html', {'usuarios': usuarios, 'roles': roles})
139
140
141### CRUD EMPLEADOS ###
142
143@login_required
144def lista_empleados(request):
145 empleados = Empleado.objects.all()
146 return render(request, 'usuarios/lista_empleados.html', {'empleados': empleados})
147
148@login_required
149def crear_empleado(request):
150 if request.method == "POST":
151 nombre = request.POST['nombre']
152 apellido = request.POST['apellido']
153 dni = request.POST['dni']
154 rol_id = request.POST.get('rol')
155 rol = Rol.objects.get(id=rol_id)
156
157 Empleado.objects.create(nombre=nombre, apellido=apellido, dni=dni, rol=rol)
158 messages.success(request, "Empleado agregado correctamente.")
159 return redirect('lista_empleados')
160
161 roles = Rol.objects.all()
162 return render(request, 'usuarios/crear_empleado.html', {'roles': roles})
163
164@login_required
165def editar_empleado(request, emp_id):
166 empleado = get_object_or_404(Empleado, id=emp_id)
167
168 if request.method == "POST":
169 empleado.nombre = request.POST['nombre']
170 empleado.apellido = request.POST['apellido']
171 empleado.dni = request.POST['dni']
172 empleado.rol_id = request.POST.get('rol')
173 empleado.save()
174 messages.success(request, "Empleado actualizado correctamente.")
175 return redirect('lista_empleados')
176
177 roles = Rol.objects.all()
178 return render(request, 'usuarios/editar_empleado.html', {'empleado': empleado, 'roles': roles})
179
180@login_required
181def eliminar_empleado(request, emp_id):
182 empleado = get_object_or_404(Empleado, id=emp_id)
183 empleado.delete()
184 messages.success(request, "Empleado eliminado correctamente.")
185 return redirect('lista_empleados')
186
187### CRUD ROLES ###
188
189@login_required
190def lista_roles(request):
191 roles = Rol.objects.all()
192 return render(request, 'usuarios/lista_roles.html', {'roles': roles})
193
194@login_required
195def crear_rol(request):
196 if request.method == "POST":
197 nombre = request.POST['nombre']
198 Rol.objects.create(nombre=nombre)
199 messages.success(request, "Rol creado correctamente.")
200 return redirect('lista_roles')
201
202 return render(request, 'usuarios/crear_rol.html')
203
204@login_required
205def editar_rol(request, rol_id):
206 rol = get_object_or_404(Rol, id=rol_id)
207
208 if request.method == "POST":
209 rol.nombre = request.POST['nombre']
210 rol.save()
211 messages.success(request, "Rol actualizado correctamente.")
212 return redirect('lista_roles')
213
214 return render(request, 'usuarios/editar_rol.html', {'rol': rol})
215
216@login_required
217def eliminar_rol(request, rol_id):
218 rol = get_object_or_404(Rol, id=rol_id)
219 rol.delete()
220 messages.success(request, "Rol eliminado correctamente.")
221 return redirect('lista_roles')
222
223
224
225@login_required
226def editar_usuario(request, user_id):
227 usuario = get_object_or_404(Usuario, id=user_id)
228
229 if request.method == "POST":
230 usuario.username = request.POST.get('username').strip()
231 usuario.first_name = request.POST.get('first_name').strip()
232 usuario.last_name = request.POST.get('last_name').strip()
233 usuario.email = request.POST.get('email').strip()
234 rol_id = request.POST.get('rol')
235 usuario.estatus = 'estatus' in request.POST # Checkbox para activar/desactivar usuario
236
237 # Validar si el usuario ya existe con otro ID
238 if Usuario.objects.exclude(id=user_id).filter(username=usuario.username).exists():
239 messages.error(request, "El nombre de usuario ya está en uso por otro usuario.")
240 return redirect('lista_usuarios')
241
242 # Verificar si el rol existe
243 try:
244 usuario.rol = Rol.objects.get(id=rol_id)
245 except Rol.DoesNotExist:
246 messages.error(request, "El rol seleccionado no es válido.")
247 return redirect('lista_usuarios')
248
249 usuario.save()
250 messages.success(request, f"Usuario '{usuario.username}' actualizado correctamente.")
251 return redirect('lista_usuarios')
252
253 roles = Rol.objects.all()
254 return render(request, 'usuarios/editar_usuario.html', {'usuario': usuario, 'roles': roles})
255
256
257@login_required
258def eliminar_usuario(request, user_id):
259 usuario = get_object_or_404(Usuario, id=user_id)
260 usuario.delete()
261 messages.success(request, f"Usuario '{usuario.username}' eliminado correctamente.")
262 return redirect('lista_usuarios')
263
264
265
266# Función para verificar si el usuario es administrador
267def es_admin(user):
268 return user.is_authenticated and user.is_superuser
269
270### RESTRINGIR VISTAS A ADMINISTRADORES ###
271
272@login_required
273@user_passes_test(es_admin, login_url='/dashboard/') # Redirigir si no es admin
274def lista_usuarios(request):
275 usuarios = Usuario.objects.all()
276 roles = Rol.objects.all()
277 return render(request, 'usuarios/lista_usuarios.html', {'usuarios': usuarios, 'roles': roles})
278
279@login_required
280@user_passes_test(es_admin, login_url='/dashboard/')
281def crear_usuario(request):
282 if request.method == "POST":
283 username = request.POST.get('username').strip()
284 first_name = request.POST.get('first_name').strip()
285 last_name = request.POST.get('last_name').strip()
286 email = request.POST.get('email').strip()
287 password = request.POST.get('password')
288 rol_id = request.POST.get('rol')
289
290 if Usuario.objects.filter(username=username).exists():
291 messages.error(request, "El nombre de usuario ya está en uso.")
292 return redirect('lista_usuarios')
293
294 try:
295 rol = Rol.objects.get(id=rol_id)
296 except Rol.DoesNotExist:
297 messages.error(request, "El rol seleccionado no es válido.")
298 return redirect('lista_usuarios')
299
300 nuevo_usuario = Usuario(
301 username=username,
302 first_name=first_name,
303 last_name=last_name,
304 email=email,
305 rol=rol
306 )
307 nuevo_usuario.set_password(password)
308 nuevo_usuario.save()
309
310 messages.success(request, f"Usuario '{username}' creado correctamente.")
311 return redirect('lista_usuarios')
312
313 return redirect('lista_usuarios')
314
315@login_required
316@user_passes_test(es_admin, login_url='/dashboard/')
317def eliminar_usuario(request, user_id):
318 usuario = get_object_or_404(Usuario, id=user_id)
319 usuario.delete()
320 messages.success(request, f"Usuario '{usuario.username}' eliminado correctamente.")
321 return redirect('lista_usuarios')
322
323@login_required
324@user_passes_test(es_admin, login_url='/dashboard/')
325def lista_roles(request):
326 roles = Rol.objects.all()
327 return render(request, 'usuarios/lista_roles.html', {'roles': roles})
328
329@login_required
330@user_passes_test(es_admin, login_url='/dashboard/')
331def crear_rol(request):
332 if request.method == "POST":
333 nombre = request.POST['nombre']
334 Rol.objects.create(nombre=nombre)
335 messages.success(request, "Rol creado correctamente.")
336 return redirect('lista_roles')
337
338 return render(request, 'usuarios/crear_rol.html')
339
340@login_required
341@user_passes_test(es_admin, login_url='/dashboard/')
342def eliminar_rol(request, rol_id):
343 rol = get_object_or_404(Rol, id=rol_id)
344 rol.delete()
345 messages.success(request, "Rol eliminado correctamente.")
346 return redirect('lista_roles')
347
348
349def lista_zonas(request):
350 zonas = Zona.objects.all()
351 return render(request, "usuarios/lista_zonas.html", {"zonas": zonas})
352
353def crear_zona(request):
354 if request.method == "POST":
355 nombre = request.POST["nombre"]
356 Zona.objects.create(nombre=nombre)
357 messages.success(request, "Zona creada correctamente.")
358 return redirect("lista_zonas")
359 return redirect("lista_zonas")
360
361def editar_zona(request, zona_id):
362 zona = get_object_or_404(Zona, id=zona_id)
363 if request.method == "POST":
364 zona.nombre = request.POST["nombre"]
365 zona.save()
366 messages.success(request, "Zona actualizada correctamente.")
367 return redirect("lista_zonas")
368 return redirect("lista_zonas")
369
370def eliminar_zona(request, zona_id):
371 zona = get_object_or_404(Zona, id=zona_id)
372 zona.delete()
373 messages.success(request, "Zona eliminada correctamente.")
374 return redirect("lista_zonas")
375
376
377def lista_avenidas(request):
378 avenidas = Avenida.objects.select_related("zona").order_by("zona_id")
379 zonas = Zona.objects.all() # Enviar zonas al template para el formulario
380
381 return render(request, "usuarios/lista_avenidas.html", {"avenidas": avenidas, "zonas": zonas})
382
383
384def crear_avenida(request):
385 if request.method == "POST":
386 nombre = request.POST["nombre"]
387 zona_id = request.POST["zona"]
388 zona = get_object_or_404(Zona, id=zona_id)
389 Avenida.objects.create(nombre=nombre, zona=zona)
390 messages.success(request, "Avenida creada correctamente.")
391 return redirect("lista_avenidas")
392 return redirect("lista_avenidas")
393
394def editar_avenida(request, avenida_id):
395 avenida = get_object_or_404(Avenida, id=avenida_id)
396 if request.method == "POST":
397 avenida.nombre = request.POST["nombre"]
398 zona_id = request.POST["zona"]
399 avenida.zona = get_object_or_404(Zona, id=zona_id)
400 avenida.save()
401 messages.success(request, "Avenida actualizada correctamente.")
402 return redirect("lista_avenidas")
403 return redirect("lista_avenidas")
404
405def eliminar_avenida(request, avenida_id):
406 avenida = get_object_or_404(Avenida, id=avenida_id)
407 avenida.delete()
408 messages.success(request, "Avenida eliminada correctamente.")
409 return redirect("lista_avenidas")
410
411def lista_clientes(request):
412 clientes_list = Cliente.objects.all().order_by('id')
413
414 query = request.GET.get('q') # Obtiene el término de búsqueda del formulario
415
416 if query:
417 # Filtra clientes por nombre, documento o cualquier otro campo que desees
418 clientes_list = clientes_list.filter(
419 Q(nombre__icontains=query) | Q(documento__icontains=query)
420 )
421
422 paginator = Paginator(clientes_list, 6)
423 page_number = request.GET.get('page')
424 clientes = paginator.get_page(page_number)
425
426 zonas = Zona.objects.all()
427 return render(request, 'usuarios/lista_clientes.html', {'clientes': clientes, 'zonas': zonas})
428
429
430
431def obtener_cliente(request, id):
432 """Devuelve datos del cliente en JSON para edición"""
433 cliente = get_object_or_404(Cliente, id=id)
434 data = {
435 "id": cliente.id,
436 "documento": cliente.documento,
437 "nombre": cliente.nombre,
438 "apellido_paterno": cliente.apellido_paterno,
439 "apellido_materno": cliente.apellido_materno,
440 "fecha_nacimiento": cliente.fecha_nacimiento.strftime("%Y-%m-%d"),
441 "sexo": cliente.sexo,
442 "telefono": cliente.telefono,
443 "email": cliente.email,
444 "direccion": cliente.direccion,
445 "estatus": cliente.estatus,
446 "zona_id": cliente.zona.id,
447 "avenida_id": cliente.avenida.id,
448 }
449 return JsonResponse(data)
450
451def get_avenidas(request, zona_id):
452 avenidas = Avenida.objects.filter(zona_id=zona_id).values('id', 'nombre')
453 return JsonResponse({'avenidas': list(avenidas)})
454
455def get_zonas(request):
456 zonas = list(Zona.objects.values('id', 'nombre'))
457 return JsonResponse({'zonas': zonas})
458
459
460
461@require_http_methods(["GET", "POST"])
462def editar_cliente(request, cliente_id):
463 cliente = get_object_or_404(Cliente, id=cliente_id)
464
465 if request.method == "GET":
466 # Devolver los datos del cliente en formato JSON
467 data = {
468 "id": cliente.id,
469 "documento": cliente.documento,
470 "nombre": cliente.nombre,
471 "apellido_paterno": cliente.apellido_paterno,
472 "apellido_materno": cliente.apellido_materno,
473 "fecha_nacimiento": cliente.fecha_nacimiento.strftime("%Y-%m-%d") if cliente.fecha_nacimiento else None,
474 "sexo": cliente.sexo,
475 "telefono": cliente.telefono,
476 "email": cliente.email,
477 "direccion": cliente.direccion,
478 "estatus": cliente.estatus,
479 "zona_id": cliente.zona.id if cliente.zona else None,
480 "avenida_id": cliente.avenida.id if cliente.avenida else None,
481 }
482 return JsonResponse(data, safe=False)
483
484 elif request.method == "POST":
485 try:
486 # Procesar el formulario de edición
487 form = ClienteForm(request.POST, instance=cliente)
488 if form.is_valid():
489 cliente = form.save(commit=False)
490
491 # Procesar el campo 'estatus' manualmente
492 estatus = request.POST.get("estatus", "1") # Por defecto, "1" (Activo)
493 cliente.estatus = estatus == "1" # Convertir a booleano
494
495 # Guardar los cambios en la base de datos
496 cliente.save()
497
498 # Devolver una respuesta JSON con el mensaje de éxito
499 return JsonResponse({
500 "message": "Cliente actualizado correctamente",
501 "id": cliente.id,
502 "estatus": cliente.estatus, # Devolver el estado actualizado
503 }, status=200)
504 else:
505 # Si el formulario no es válido, devolver los errores
506 return JsonResponse({
507 "error": "Error en el formulario",
508 "detalles": form.errors,
509 }, status=400)
510 except Exception as e:
511 # Manejar errores inesperados
512 return JsonResponse({
513 "error": "Error interno del servidor",
514 "detalles": str(e),
515 }, status=500)
516
517 return JsonResponse({"error": "Método no permitido"}, status=405)
518
519
520
521@csrf_exempt
522def eliminar_cliente(request, cliente_id):
523 if request.method == "DELETE": # Verifica que el método sea DELETE
524 cliente = get_object_or_404(Cliente, id=cliente_id)
525 cliente.delete()
526 return JsonResponse({"mensaje": "Cliente eliminado correctamente"}, status=200)
527
528 return JsonResponse({"error": "Método no permitido"}, status=405)
529
530
531
532@csrf_exempt
533def agregar_cliente(request):
534 if request.method == "POST":
535 form = ClienteForm(request.POST)
536 if form.is_valid():
537 # Guardar el cliente, pero sin commit para poder modificar campos manualmente
538 cliente = form.save(commit=False)
539
540 # Procesar el campo 'estatus' manualmente
541 estatus = request.POST.get("estatus", "1") # Por defecto, "1" (Activo)
542 cliente.estatus = estatus == "1" # Convertir a booleano (True si es "1", False si es "0")
543
544 # Guardar el cliente en la base de datos
545 cliente.save()
546
547 # Procesar las direcciones (si se enviaron)
548 zonas = request.POST.getlist("zona[]") # Obtener todas las zonas
549 avenidas = request.POST.getlist("avenida[]") # Obtener todas las avenidas
550 direcciones = request.POST.getlist("direccion[]") # Obtener todas las direcciones
551
552 # Verificar que se hayan enviado direcciones
553 if zonas and avenidas and direcciones:
554 for zona_id, avenida_id, direccion in zip(zonas, avenidas, direcciones):
555 Direccion.objects.create(
556 cliente=cliente,
557 zona_id=zona_id,
558 avenida_id=avenida_id,
559 direccion=direccion,
560 )
561
562 # Devolver una respuesta JSON con los datos del cliente
563 return JsonResponse({
564 "mensaje": "Cliente y direcciones agregados correctamente.",
565 "id": cliente.id,
566 "documento": cliente.documento,
567 "nombre": cliente.nombre,
568 "apellido_paterno": cliente.apellido_paterno,
569 "apellido_materno": cliente.apellido_materno,
570 "telefono": cliente.telefono,
571 "email": cliente.email,
572 "estatus": cliente.estatus, # Devolver el estado actualizado
573 }, status=200)
574 else:
575 # Si el formulario no es válido, devolver errores
576 return JsonResponse({
577 "error": "Error en el formulario",
578 "detalles": form.errors,
579 }, status=400)
580 else:
581 # Si el método no es POST, devolver un error
582 return JsonResponse({
583 "error": "Método no permitido",
584 }, status=405)
585
586
587def cliente_detail(request, cliente_id):
588 cliente = get_object_or_404(Cliente, pk=cliente_id)
589 if request.method == "GET":
590 data = {
591 'id': cliente.id,
592 'documento': cliente.documento,
593 'nombre': cliente.nombre,
594 'apellido_paterno': cliente.apellido_paterno,
595 'apellido_materno': cliente.apellido_materno,
596 'fecha_nacimiento': cliente.fecha_nacimiento.strftime('%Y-%m-%d'),
597 'sexo': cliente.sexo,
598 'telefono': cliente.telefono,
599 'email': cliente.email,
600 'estatus': cliente.estatus,
601 'numero_cliente': cliente.numero_cliente,
602 # Se devuelven todas las direcciones asociadas al cliente, incluyendo los IDs para zona y avenida
603 'direcciones': [
604 {
605 'id': d.id,
606 'zona': d.zona.nombre if d.zona else None,
607 'zona_id': d.zona.id if d.zona else None,
608 'avenida': d.avenida.nombre if d.avenida else None,
609 'avenida_id': d.avenida.id if d.avenida else None,
610 'direccion': d.direccion,
611 } for d in cliente.direcciones.all()
612 ]
613 }
614 return JsonResponse(data)
615 elif request.method == "POST":
616 # Aquí procesa la actualización de los datos del cliente
617 return JsonResponse({'mensaje': 'Cliente actualizado correctamente.'})
618 else:
619 return HttpResponseNotAllowed(['GET', 'POST'])
620
621
622def detalle_cliente(request, cliente_id):
623 cliente = get_object_or_404(Cliente, pk=cliente_id)
624 return render(request, 'cliente_detail.html', {'cliente': cliente})
625
626
627
628def detalle_cliente_html(request, cliente_id):
629 # Obtener el cliente (y sus direcciones) como ya lo haces en cliente_detail
630 cliente = get_object_or_404(Cliente, pk=cliente_id)
631 return render(request, 'usuarios/detalle_cliente.html', {'cliente': cliente})
632
633
634
635# --- Agregado de Reportes y Generación de PDF ---
636def generar_pdf_clientes(request):
637 response = HttpResponse(content_type='application/pdf')
638 response['Content-Disposition'] = 'attachment; filename="reporte_clientes.pdf"'
639 pdf = canvas.Canvas(response, pagesize=letter)
640 pdf.setTitle("Reporte de Clientes")
641 pdf.setFont("Helvetica-Bold", 14)
642 pdf.drawString(200, 750, "Reporte de Clientes")
643 pdf.setFont("Helvetica", 10)
644 clientes = Cliente.objects.all()
645 y = 720
646 for cliente in clientes:
647 pdf.drawString(50, y, f"{cliente.documento} - {cliente.nombre} - {cliente.telefono} - {cliente.email}")
648 y -= 20
649 pdf.showPage()
650 pdf.save()
651 return response
652
653
654# Vista para listar servicios
655def lista_servicios(request):
656 servicios = Servicio.objects.all()
657 return render(request, 'usuarios/lista_servicios.html', {'servicios': servicios})
658
659# Vista para agregar un servicio
660def agregar_servicio(request):
661 if request.method == "POST":
662 nombre = request.POST.get("nombre")
663 costo = request.POST.get("costo")
664
665 if nombre and costo:
666 Servicio.objects.create(nombre=nombre, costo=int(costo))
667 messages.success(request, "Servicio agregado correctamente")
668 return redirect("servicios") # Redirige a la lista de servicios
669
670 return render(request, "usuarios/lista_servicios.html")
671
672# Vista para editar un servicio
673def editar_servicio(request, servicio_id):
674 servicio = get_object_or_404(Servicio, id=servicio_id)
675
676 if request.method == "GET":
677 # Retornar datos del servicio en formato JSON
678 return JsonResponse({
679 "id": servicio.id,
680 "nombre": servicio.nombre,
681 "costo": servicio.costo
682 })
683
684 elif request.method == "POST":
685 try:
686 servicio.nombre = request.POST.get("nombre")
687 servicio.costo = int(request.POST.get("costo"))
688 servicio.save()
689 messages.success(request, "Servicio actualizado correctamente")
690 return JsonResponse({"mensaje": "Servicio actualizado correctamente"})
691 except Exception as e:
692 return JsonResponse({"error": f"Error al actualizar el servicio: {str(e)}"}, status=400)
693
694 return JsonResponse({"error": "Método no permitido"}, status=405)
695
696
697# Vista para eliminar un servicio
698def eliminar_servicio(request, servicio_id):
699 servicio = get_object_or_404(Servicio, id=servicio_id)
700 servicio.delete()
701 messages.success(request, "Servicio eliminado correctamente")
702 return JsonResponse({"mensaje": "Servicio eliminado correctamente"})
703
704
705
706# Vista para listar contratos
707def lista_contratos(request):
708 contratos = Contrato.objects.all()
709 form = ContratoForm()
710 return render(request, "usuarios/lista_contratos.html", {"contratos": contratos, "form": form})
711
712
713# Vista para generar número de abonado único
714def generar_numero_abonado():
715 return "C" + str(random.randint(100000, 999999))
716
717def obtener_servicio(request, servicio_id):
718 """ Obtiene información de un servicio específico """
719 try:
720 servicio = get_object_or_404(Servicio, pk=servicio_id)
721 return JsonResponse({"id": servicio.id, "nombre": servicio.nombre, "costo": servicio.costo})
722 except Exception as e:
723 return JsonResponse({'error': f'Ocurrió un error al obtener el servicio: {e}'}, status=500)
724
725
726
727
728
729
730
731# Vista para obtener los datos de un contrato
732def obtener_contrato(request, id):
733 try:
734 contrato = get_object_or_404(Contrato, id=id)
735
736 # Construir el nombre completo correctamente
737 cliente = contrato.cliente
738 cliente_nombre = f"{cliente.nombre} {cliente.apellido_paterno} {cliente.apellido_materno or ''}".strip()
739
740 return JsonResponse({
741 "success": True,
742 "contrato": {
743 "id": contrato.id,
744 "cliente": cliente.id,
745 "cliente_nombre": cliente_nombre, # ✅ Usa apellido_paterno y apellido_materno
746 "numero_abonado": contrato.numero_abonado,
747 "descripcion": contrato.descripcion,
748 "total": contrato.total
749 }
750 })
751 except Exception as e:
752 return JsonResponse({"success": False, "message": f"Error en el servidor: {str(e)}"}, status=500)
753
754
755# Vista para editar un registrar_contrato
756@csrf_exempt
757def obtener_cliente(request, cliente_id):
758 """ Devuelve los datos de un cliente en formato JSON. """
759 cliente = get_object_or_404(Cliente, id=cliente_id)
760 data = {
761 "id": cliente.id,
762 "documento": cliente.documento,
763 "nombre": cliente.nombre,
764 "apellido_paterno": cliente.apellido_paterno,
765 "apellido_materno": cliente.apellido_materno,
766 "telefono": cliente.telefono,
767 "email": cliente.email,
768 "direccion": cliente.direccion,
769 "estatus": cliente.estatus,
770 }
771 return JsonResponse(data)
772
773@csrf_exempt
774def editar_cliente(request, cliente_id):
775 """ Actualiza un cliente existente. """
776 if request.method == "POST":
777 try:
778 cliente = get_object_or_404(Cliente, id=cliente_id)
779 for key, value in request.POST.items():
780 setattr(cliente, key, value)
781 cliente.save()
782 return JsonResponse({"mensaje": "Cliente actualizado correctamente"}, status=200)
783 except Exception as e:
784 return JsonResponse({"error": f"Error interno: {str(e)}"}, status=500)
785 return JsonResponse({"error": "Método no permitido"}, status=405)
786
787
788
789
790
791
792
793# Vista para eliminar contrato
794def eliminar_contrato(request, id):
795 if request.method == "DELETE":
796 contrato = get_object_or_404(Contrato, id=id)
797 contrato.delete()
798 return JsonResponse({"success": True})
799 return JsonResponse({"success": False, "error": "Método no permitido"}, status=405)
800
801
802# Buscar clientes por nombre o documento
803def buscar_clientes(request):
804 query = request.GET.get("query", "").strip()
805 if query:
806 clientes = Cliente.objects.filter(nombre__icontains=query) | Cliente.objects.filter(documento__icontains=query)
807 data = list(clientes.values("id", "nombre", "documento"))
808 return JsonResponse(data, safe=False)
809 return JsonResponse([], safe=False)
810
811
812
813
814
815
816@csrf_exempt
817def agregar_contrato(request):
818 """ Agrega un nuevo contrato con sus servicios asociados. """
819 if request.method == "POST":
820 form = ContratoForm(request.POST)
821 if form.is_valid():
822 contrato = form.save(commit=False)
823 contrato.total = contrato.calcular_total()
824 contrato.save()
825 form.save_m2m()
826 return JsonResponse({"mensaje": "Contrato agregado correctamente"}, status=201)
827 return JsonResponse({"error": "Formulario inválido", "detalles": form.errors}, status=400)
828 return JsonResponse({"error": "Método no permitido"}, status=405)
829
830@csrf_exempt
831def editar_contrato(request, id):
832 """ Edita los detalles de un contrato existente. """
833 contrato = get_object_or_404(Contrato, id=id)
834 if request.method == "POST":
835 try:
836 data = json.loads(request.body.decode("utf-8"))
837 for key, value in data.items():
838 setattr(contrato, key, value)
839 contrato.save()
840 return JsonResponse({"mensaje": "Contrato actualizado correctamente"}, status=200)
841 except Exception as e:
842 return JsonResponse({"error": f"Error interno: {str(e)}"}, status=500)
843 return JsonResponse({"error": "Método no permitido"}, status=405)
844
845
846
847def generar_numero_abonado(request):
848 """
849 Genera un número de abonado único basado en el último contrato registrado.editar_cliente
850 """
851 ultimo_contrato = Contrato.objects.order_by('-numero_abonado').first()
852 nuevo_numero = (ultimo_contrato.numero_abonado + 1) if ultimo_contrato and ultimo_contrato.numero_abonado else 1000
853 return JsonResponse({"numero_abonado": nuevo_numero})
854
855
856def get_zonas(request):
857 zonas = list(Zona.objects.values('id', 'nombre'))
858 return JsonResponse({'zonas': zonas})
859
860def obtener_avenidas(request):
861 """ Devuelve la lista de avenidas filtradas por zona. """
862 zona_id = request.GET.get("zona_id")
863 avenidas = list(Avenida.objects.filter(zona_id=zona_id).values("id", "nombre")) if zona_id else []
864 return JsonResponse({"avenidas": avenidas})
865
866
867
868
869
870def obtener_direcciones_cliente(request, cliente_id):
871 try:
872 direcciones = Direccion.objects.filter(cliente_id=cliente_id).values("id", "direccion")
873 return JsonResponse({"direcciones": list(direcciones)})
874 except Exception as e:
875 print(f"Error al obtener direcciones: {e}") # Depuración
876 return JsonResponse({"error": "Ocurrió un error al obtener las direcciones."}, status=500)
877
878
879def obtener_estado_cliente(request, cliente_id):
880 try:
881 cliente = Cliente.objects.get(id=cliente_id)
882 return JsonResponse({'estatus': cliente.estatus}) # Ajusta según el nombre del campo en el modelo
883 except Cliente.DoesNotExist:
884 return JsonResponse({'error': 'Cliente no encontrado'}, status=404)