from django.shortcuts import render,redirect,get_object_or_404 from django.http import HttpResponse from django.contrib.auth.forms import AuthenticationForm, UserCreationForm from django.contrib.auth import login, logout, authenticate from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required from .models import RegistrarCompra, RegistroPagos from .forms import RegistrarCompraForm, RegistroPagosForm from django.template.loader import get_template from xhtml2pdf import pisa import openpyxl from django import forms import csv # Create your views here. def base(request): return render(request, 'index.html') class CustomUserCreationForm(UserCreationForm): email = forms.EmailField(required=True, help_text="Introduce un correo electrónico válido.") class Meta: model = User fields = ('username', 'email', 'password1', 'password2') def save(self, commit=True): user = super().save(commit=False) user.email = self.cleaned_data["email"] if commit: user.save() return user def signup(request): if request.method == 'POST': form = CustomUserCreationForm(request.POST) # Verificamos si el formulario es válido if form.is_valid(): # Guardamos el usuario si todo está bien form.save() # Mensaje de éxito return redirect('signin') # Redirige a la página de inicio de sesión else: # Si el formulario no es válido, mostramos los errores en los campos específicos if 'username' not in form.cleaned_data: form.add_error('username', 'El nombre de usuario es obligatorio.') if 'email' not in form.cleaned_data: form.add_error('email', 'El correo electrónico es obligatorio.') if 'password1' not in form.cleaned_data: form.add_error('password1', 'La contraseña es obligatoria.') if 'password2' not in form.cleaned_data: form.add_error('password2', 'Debes confirmar la contraseña.') return render(request, 'singup.html', {'form': form}) else: # Si es un GET, mostramos un formulario vacío form = CustomUserCreationForm() return render(request, 'singup.html', {'form': form}) def signin(request): if request.method == 'GET': return render ( request, 'index.html',{ 'form': AuthenticationForm }) else: user=authenticate(request, username=request.POST['username'], password=request.POST['password']) if user is None: return render ( request, 'index.html',{ 'form': AuthenticationForm , 'error': 'Username or password is incorrect' }) else: login(request, user) return redirect('lista_compras') def signout(request): logout(request) return redirect('signin') @login_required def crear_compra(request): if request.method == 'POST': form = RegistrarCompraForm(request.POST) if form.is_valid(): # Guardamos el formulario y asignamos el usuario autenticado al campo 'user_compra' compra = form.save(commit=False) # No guardamos todavía en la base de datos compra.user_compra = request.user # Asignamos el usuario autenticado compra.save() # Guardamos la compra en la base de datos return redirect('lista_compras') # Redirige a una vista que liste las compras else: form = RegistrarCompraForm() return render(request, 'crear_compra.html', {'form': form}) @login_required def registrar_pago(request, compra_id): compra = get_object_or_404(RegistrarCompra, id=compra_id, user_compra=request.user) # Filtrar por el usuario # Calcular el total pagado actual (monto_pagado + monto_extra) pagos = compra.pagos.all() total_pagado = sum(pago.monto_pagado + pago.monto_extra for pago in pagos) # Calcular el monto restante de la compra restante = compra.monto_pago - total_pagado if request.method == 'POST': form = RegistroPagosForm(request.POST) if form.is_valid(): pago = form.save(commit=False) # Verificar si el nuevo pago no excede el monto restante total_nuevo_pago = pago.monto_pagado + pago.monto_extra if total_pagado + total_nuevo_pago > compra.monto_pago: form.add_error(None, "El pago total no puede superar el monto de la compra.") else: pago.registro_compra = compra # Relacionar con la compra específica pago.user = request.user # Asignar el usuario autenticado pago.save() return redirect('detalle_compra', compra_id=compra.id) # Redirige a la vista de detalle de la compra else: form = RegistroPagosForm() return render(request, 'registrar_pago.html', {'form': form, 'compra': compra, 'restante': restante}) @login_required def detalle_compra(request, compra_id): compra = get_object_or_404(RegistrarCompra, id=compra_id, user_compra=request.user) # Filtrar por el usuario pagos = compra.pagos.all() # Obtén todos los pagos relacionados con esta compra # Calcular el total pagado (monto_pagado + monto_extra) total_pagado = sum(pago.monto_pagado + pago.monto_extra for pago in pagos) # Calcular el monto restante restante = max(0, compra.monto_pago - total_pagado) # Calcular el estado estado = compra.calcular_estado() # Utilizamos el método que definimos en el modelo context = { 'compra': compra, 'pagos': pagos, 'total_pagado': total_pagado, 'restante': restante, 'estado': estado, } return render(request, 'detalle_compra.html', context) @login_required def lista_compras(request): compras = RegistrarCompra.objects.filter(user_compra=request.user) # Filtrar por el usuario actual compras_con_estado = [ { 'compra': compra, 'estado': compra.calcular_estado(), # Calcula el estado de la compra 'restante': compra.calcular_restante(), # Calcula el monto restante } for compra in compras ] return render(request, 'lista_compras.html', {'compras_con_estado': compras_con_estado}) def generar_pdf(template_src, context_dict={}): template = get_template(template_src) html = template.render(context_dict) response = HttpResponse(content_type='application/pdf') response['Content-Disposition'] = 'inline; filename="detalle_compra.pdf"' pisa_status = pisa.CreatePDF(html, dest=response) if pisa_status.err: return HttpResponse('Error al generar el PDF', content_type='text/plain') return response def reporte_detalle_compra(request, compra_id): compra = get_object_or_404(RegistrarCompra, id=compra_id) pagos = compra.pagos.all() total_pagado = sum(pago.total_pagado for pago in pagos) restante = max(0, compra.monto_pago - total_pagado) context = { 'compra': compra, 'pagos': pagos, 'total_pagado': total_pagado, 'restante': restante, } return generar_pdf('detalle_compra_pdf.html', context) def exportar_excel_detalle_compra(request, compra_id): compra = get_object_or_404(RegistrarCompra, id=compra_id) pagos = compra.pagos.all() # Crear el archivo de Excel wb = openpyxl.Workbook() ws = wb.active ws.title = "Detalle de Compra" # Escribir encabezados ws.append(["Fecha de Pago", "Monto Pagado", "Monto Extra", "Observaciones"]) # Agregar los datos de los pagos for pago in pagos: ws.append([ pago.fecha_pago, float(pago.monto_pagado), float(pago.monto_extra), pago.observaciones, ]) # Configurar la respuesta HTTP response = HttpResponse(content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") response['Content-Disposition'] = f'attachment; filename="detalle_compra_{compra.id}.xlsx"' wb.save(response) return response def exportar_csv_detalle_compra(request, compra_id): compra = get_object_or_404(RegistrarCompra, id=compra_id) pagos = compra.pagos.all() # Configurar la respuesta HTTP response = HttpResponse(content_type="text/csv") response['Content-Disposition'] = f'attachment; filename="detalle_compra_{compra.id}.csv"' # Crear el escritor CSV writer = csv.writer(response) writer.writerow(["Fecha de Pago", "Monto Pagado", "Monto Extra", "Observaciones"]) # Encabezados # Agregar los datos de los pagos for pago in pagos: writer.writerow([ pago.fecha_pago, float(pago.monto_pagado), float(pago.monto_extra), pago.observaciones, ]) return response