|
|
@@ -328,6 +328,10 @@ def listar_categorias(request):
|
|
|
|
|
|
form_filtro = FiltroForm(request.GET or None)
|
|
|
|
|
|
+
|
|
|
+ fecha_fin = timezone.localtime().strftime('%Y-%m-%d')
|
|
|
+ fecha_inicio = timezone.localtime().date().replace(day=1).strftime('%Y-%m-%d')
|
|
|
+
|
|
|
if form_filtro.is_valid():
|
|
|
busqueda = form_filtro.cleaned_data.get('buscar')
|
|
|
if busqueda:
|
|
|
@@ -335,132 +339,11 @@ def listar_categorias(request):
|
|
|
db_models.Q(nombre__icontains=busqueda)
|
|
|
)
|
|
|
|
|
|
- return render(request, 'listar_categorias.html', {'categorias': categorias, 'form_filtro': form_filtro})
|
|
|
-
|
|
|
-@login_required
|
|
|
-def informe_categoria(request):
|
|
|
- categoria_id = request.GET.get('categoria_id')
|
|
|
-
|
|
|
- categoria = get_object_or_404(Categoria, id=categoria_id)
|
|
|
-
|
|
|
- form = FiltroInformeCuentaForm(request.GET or None)
|
|
|
-
|
|
|
- if form.is_valid():
|
|
|
- # obtener fechas desde GET o establecer por defecto (mes actual)
|
|
|
- hoy = timezone.localtime()
|
|
|
- primer_dia = hoy.replace(day=1)
|
|
|
-
|
|
|
- fecha_inicio_str = request.GET.get('fecha_inicio')
|
|
|
- fecha_fin_str = request.GET.get('fecha_fin')
|
|
|
-
|
|
|
- if fecha_inicio_str and fecha_fin_str:
|
|
|
- fecha_inicio = datetime.strptime(fecha_inicio_str, '%Y-%m-%d').date()
|
|
|
- fecha_fin = datetime.strptime(fecha_fin_str, '%Y-%m-%d').date()
|
|
|
- else:
|
|
|
- fecha_inicio = primer_dia
|
|
|
- fecha_fin = hoy
|
|
|
-
|
|
|
- # Convertir a datetime aware para evitar warnings
|
|
|
- fecha_inicio_dt = timezone.make_aware(datetime.combine(fecha_inicio, time.min))
|
|
|
- fecha_fin_dt = timezone.make_aware(datetime.combine(fecha_fin, time.max))
|
|
|
-
|
|
|
- movimientos = Movimiento.objects.filter(
|
|
|
- categoria=categoria,
|
|
|
- usuario=request.user,
|
|
|
- fecha__range=(fecha_inicio_dt, fecha_fin_dt)
|
|
|
- ).order_by('fecha')
|
|
|
-
|
|
|
- context = {
|
|
|
- 'categoria': categoria,
|
|
|
- 'movimientos': movimientos,
|
|
|
- 'fecha_inicio': fecha_inicio_str,
|
|
|
- 'fecha_fin': fecha_fin_str,
|
|
|
- }
|
|
|
-
|
|
|
- return render(request, 'informe_categoria.html', context)
|
|
|
-
|
|
|
-@login_required
|
|
|
-def informe_categoria_pdf(request):
|
|
|
- categoria_id = request.GET.get('categoria_id')
|
|
|
-
|
|
|
- categoria = get_object_or_404(Categoria, id=categoria_id)
|
|
|
-
|
|
|
- # obtener fechas desde GET o establecer por defecto (mes actual)
|
|
|
- hoy = timezone.localtime()
|
|
|
- primer_dia = hoy.replace(day=1)
|
|
|
-
|
|
|
- fecha_inicio_str = request.GET.get('fecha_inicio')
|
|
|
- fecha_fin_str = request.GET.get('fecha_fin')
|
|
|
-
|
|
|
- if fecha_inicio_str and fecha_fin_str:
|
|
|
- fecha_inicio = datetime.strptime(fecha_inicio_str, '%Y-%m-%d').date()
|
|
|
- fecha_fin = datetime.strptime(fecha_fin_str, '%Y-%m-%d').date()
|
|
|
- else:
|
|
|
- fecha_inicio = primer_dia
|
|
|
- fecha_fin = hoy
|
|
|
-
|
|
|
- # Convertir a datetime aware para evitar warnings
|
|
|
- fecha_inicio_dt = timezone.make_aware(datetime.combine(fecha_inicio, time.min))
|
|
|
- fecha_fin_dt = timezone.make_aware(datetime.combine(fecha_fin, time.max))
|
|
|
-
|
|
|
- movimientos = Movimiento.objects.filter(
|
|
|
- categoria=categoria,
|
|
|
- usuario=request.user,
|
|
|
- fecha__range=(fecha_inicio_dt, fecha_fin_dt)
|
|
|
- ).order_by('fecha')
|
|
|
-
|
|
|
- template = get_template('informe_categoria_pdf.html')
|
|
|
- html = template.render({'categoria': categoria, 'fecha_inicio': fecha_inicio_str, 'fecha_fin': fecha_fin_str, 'movimientos': movimientos})
|
|
|
-
|
|
|
- with tempfile.NamedTemporaryFile(delete=True) as output:
|
|
|
- HTML(string=html).write_pdf(output.name)
|
|
|
-
|
|
|
- output.seek(0)
|
|
|
- response = HttpResponse(output.read(), content_type='application/pdf')
|
|
|
- response['Content-Disposition'] = f'filename=informe_{categoria.nombre}.pdf'
|
|
|
- return response
|
|
|
-
|
|
|
-@login_required
|
|
|
-def informe_categoria(request):
|
|
|
- categoria_id = request.GET.get('categoria_id')
|
|
|
-
|
|
|
- categoria = get_object_or_404(Categoria, id=categoria_id)
|
|
|
-
|
|
|
- form = FiltroInformeCuentaForm(request.GET or None)
|
|
|
-
|
|
|
- if form.is_valid():
|
|
|
- # obtener fechas desde GET o establecer por defecto (mes actual)
|
|
|
- hoy = timezone.localtime()
|
|
|
- primer_dia = hoy.replace(day=1)
|
|
|
-
|
|
|
- fecha_inicio_str = request.GET.get('fecha_inicio')
|
|
|
- fecha_fin_str = request.GET.get('fecha_fin')
|
|
|
-
|
|
|
- if fecha_inicio_str and fecha_fin_str:
|
|
|
- fecha_inicio = datetime.strptime(fecha_inicio_str, '%Y-%m-%d').date()
|
|
|
- fecha_fin = datetime.strptime(fecha_fin_str, '%Y-%m-%d').date()
|
|
|
- else:
|
|
|
- fecha_inicio = primer_dia
|
|
|
- fecha_fin = hoy
|
|
|
-
|
|
|
- # Convertir a datetime aware para evitar warnings
|
|
|
- fecha_inicio_dt = timezone.make_aware(datetime.combine(fecha_inicio, time.min))
|
|
|
- fecha_fin_dt = timezone.make_aware(datetime.combine(fecha_fin, time.max))
|
|
|
-
|
|
|
- movimientos = Movimiento.objects.filter(
|
|
|
- categoria=categoria,
|
|
|
- usuario=request.user,
|
|
|
- fecha__range=(fecha_inicio_dt, fecha_fin_dt)
|
|
|
- ).order_by('fecha')
|
|
|
-
|
|
|
- context = {
|
|
|
- 'categoria': categoria,
|
|
|
- 'movimientos': movimientos,
|
|
|
- 'fecha_inicio': fecha_inicio_str,
|
|
|
- 'fecha_fin': fecha_fin_str,
|
|
|
- }
|
|
|
-
|
|
|
- return render(request, 'informe_categoria.html', context)
|
|
|
+ return render(request, 'listar_categorias.html',
|
|
|
+ {'categorias': categorias,
|
|
|
+ 'form_filtro': form_filtro,
|
|
|
+ 'fecha_inicio': fecha_inicio,
|
|
|
+ 'fecha_fin': fecha_fin})
|
|
|
|
|
|
# API
|
|
|
|
|
|
@@ -749,3 +632,118 @@ def informe_cuenta_pdf(request):
|
|
|
response = HttpResponse(output.read(), content_type='application/pdf')
|
|
|
response['Content-Disposition'] = f'filename=informe_{cuenta.nombre}.pdf'
|
|
|
return response
|
|
|
+
|
|
|
+@login_required
|
|
|
+def informe_categoria(request):
|
|
|
+ categoria_id = request.GET.get('categoria_id')
|
|
|
+
|
|
|
+ categoria = get_object_or_404(Categoria, id=categoria_id)
|
|
|
+
|
|
|
+ form = FiltroInformeCuentaForm(request.GET or None)
|
|
|
+
|
|
|
+ if form.is_valid():
|
|
|
+ # obtener fechas desde GET o establecer por defecto (mes actual)
|
|
|
+ hoy = timezone.localtime()
|
|
|
+ primer_dia = hoy.replace(day=1)
|
|
|
+
|
|
|
+ fecha_inicio_str = request.GET.get('fecha_inicio')
|
|
|
+ fecha_fin_str = request.GET.get('fecha_fin')
|
|
|
+
|
|
|
+ if fecha_inicio_str and fecha_fin_str:
|
|
|
+ fecha_inicio = datetime.strptime(fecha_inicio_str, '%Y-%m-%d').date()
|
|
|
+ fecha_fin = datetime.strptime(fecha_fin_str, '%Y-%m-%d').date()
|
|
|
+ else:
|
|
|
+ fecha_inicio = primer_dia
|
|
|
+ fecha_fin = hoy
|
|
|
+
|
|
|
+ # Convertir a datetime aware para evitar warnings
|
|
|
+ fecha_inicio_dt = timezone.make_aware(datetime.combine(fecha_inicio, time.min))
|
|
|
+ fecha_fin_dt = timezone.make_aware(datetime.combine(fecha_fin, time.max))
|
|
|
+
|
|
|
+ movimientos = Movimiento.objects.filter(
|
|
|
+ Q(categoria=categoria),
|
|
|
+ fecha__range=(fecha_inicio_dt, fecha_fin_dt)
|
|
|
+ ).order_by('fecha')
|
|
|
+
|
|
|
+ saldo = 0
|
|
|
+
|
|
|
+ movimientos_con_saldo = []
|
|
|
+
|
|
|
+ for mov in movimientos:
|
|
|
+ saldo += mov.monto
|
|
|
+
|
|
|
+ movimientos_con_saldo.append({
|
|
|
+ 'movimiento': mov,
|
|
|
+ 'saldo_despues': saldo
|
|
|
+ })
|
|
|
+
|
|
|
+ saldo_final = saldo
|
|
|
+
|
|
|
+ context = {
|
|
|
+ 'categoria': categoria,
|
|
|
+ 'movimientos_con_saldo': movimientos_con_saldo,
|
|
|
+ 'fecha_inicio': fecha_inicio_str,
|
|
|
+ 'fecha_fin': fecha_fin_str,
|
|
|
+ 'saldo_final': saldo
|
|
|
+ }
|
|
|
+
|
|
|
+ return render(request, 'informe_categoria.html', context)
|
|
|
+
|
|
|
+@login_required
|
|
|
+def informe_categoria_pdf(request):
|
|
|
+ categoria_id = request.GET.get('categoria_id')
|
|
|
+
|
|
|
+ categoria = get_object_or_404(Categoria, id=categoria_id)
|
|
|
+
|
|
|
+ # obtener fechas desde GET o establecer por defecto (mes actual)
|
|
|
+ hoy = timezone.localtime()
|
|
|
+ primer_dia = hoy.replace(day=1)
|
|
|
+
|
|
|
+ fecha_inicio_str = request.GET.get('fecha_inicio')
|
|
|
+ fecha_fin_str = request.GET.get('fecha_fin')
|
|
|
+
|
|
|
+ if fecha_inicio_str and fecha_fin_str:
|
|
|
+ fecha_inicio = datetime.strptime(fecha_inicio_str, '%Y-%m-%d').date()
|
|
|
+ fecha_fin = datetime.strptime(fecha_fin_str, '%Y-%m-%d').date()
|
|
|
+ else:
|
|
|
+ fecha_inicio = primer_dia
|
|
|
+ fecha_fin = hoy
|
|
|
+
|
|
|
+ # Convertir a datetime aware para evitar warnings
|
|
|
+ fecha_inicio_dt = timezone.make_aware(datetime.combine(fecha_inicio, time.min))
|
|
|
+ fecha_fin_dt = timezone.make_aware(datetime.combine(fecha_fin, time.max))
|
|
|
+
|
|
|
+ movimientos = Movimiento.objects.filter(
|
|
|
+ categoria=categoria,
|
|
|
+ usuario=request.user,
|
|
|
+ fecha__range=(fecha_inicio_dt, fecha_fin_dt)
|
|
|
+ ).order_by('fecha')
|
|
|
+
|
|
|
+ saldo = 0
|
|
|
+
|
|
|
+ historial = []
|
|
|
+
|
|
|
+ for mov in movimientos:
|
|
|
+ saldo += mov.monto
|
|
|
+
|
|
|
+ historial.append({
|
|
|
+ 'fecha': mov.fecha,
|
|
|
+ 'descripcion': mov.descripcion,
|
|
|
+ 'desde': mov.cuenta_origen.nombre if mov.cuenta_origen else 'N/A',
|
|
|
+ 'hasta': mov.cuenta_destino.nombre if mov.cuenta_destino else 'N/A',
|
|
|
+ 'monto': mov.monto,
|
|
|
+ 'saldo_despues': saldo
|
|
|
+ })
|
|
|
+
|
|
|
+ saldo_final = saldo
|
|
|
+
|
|
|
+ template = get_template('informe_categoria_pdf.html')
|
|
|
+ html = template.render({'categoria': categoria, 'fecha_inicio': fecha_inicio_str, 'fecha_fin': fecha_fin_str, 'saldo_final': saldo, 'historial': historial})
|
|
|
+
|
|
|
+ with tempfile.NamedTemporaryFile(delete=True) as output:
|
|
|
+ HTML(string=html).write_pdf(output.name)
|
|
|
+
|
|
|
+ output.seek(0)
|
|
|
+ response = HttpResponse(output.read(), content_type='application/pdf')
|
|
|
+ response['Content-Disposition'] = f'filename=informe_{categoria.nombre}.pdf'
|
|
|
+ return response
|