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