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