Просмотр исходного кода

Permite la creación de movimientos favoritos

Celestino Rey 1 год назад
Родитель
Сommit
31a20c072c

+ 3 - 2
finanzas/admin.py

@@ -1,7 +1,8 @@
 # budget/admin.py
 
 from django.contrib import admin
-from .models import Movimiento, Cuenta
+from .models import Movimiento, Cuenta, MovimientoFrecuente
 
 admin.site.register(Movimiento)
-admin.site.register(Cuenta)
+admin.site.register(Cuenta)
+admin.site.register(MovimientoFrecuente)

+ 27 - 0
finanzas/migrations/0004_movimientofrecuente.py

@@ -0,0 +1,27 @@
+# Generated by Django 5.2 on 2025-05-09 11:29
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('finanzas', '0003_alter_movimiento_fecha'),
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='MovimientoFrecuente',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('nombre', models.CharField(max_length=100)),
+                ('monto', models.DecimalField(decimal_places=2, max_digits=10)),
+                ('cuenta_destino', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frecuente_destino', to='finanzas.cuenta')),
+                ('cuenta_origen', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frecuente_origen', to='finanzas.cuenta')),
+                ('usuario', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]

+ 10 - 0
finanzas/models.py

@@ -25,3 +25,13 @@ class Movimiento(models.Model):
 
     def __str__(self):
         return f"{self.cuenta_origen.nombre} → {self.cuenta_destino.nombre} - {self.monto} ({self.fecha})"
+
+class MovimientoFrecuente(models.Model):
+    nombre = models.CharField(max_length=100)
+    usuario = models.ForeignKey(ReyMotaUser, on_delete=models.CASCADE)
+    cuenta_origen = models.ForeignKey(Cuenta, on_delete=models.CASCADE, related_name='frecuente_origen')
+    cuenta_destino = models.ForeignKey(Cuenta, on_delete=models.CASCADE, related_name='frecuente_destino')
+    monto = models.DecimalField(max_digits=10, decimal_places=2)
+
+    def __str__(self):
+        return f"{self.nombre}: {self.cuenta_origen} → {self.cuenta_destino} ({self.monto} €)"

+ 39 - 2
finanzas/views.py

@@ -1,22 +1,34 @@
 from django.shortcuts import render, redirect,  get_object_or_404
+from decimal import Decimal, InvalidOperation
+import logging
+import re
 
 from accounts import models
-from .models import Movimiento, Cuenta
+from .models import Movimiento, Cuenta, MovimientoFrecuente
 from .forms import MovimientoForm, FiltroForm, CuentaForm
 from django.contrib.auth.decorators import login_required
 from django.contrib import messages
 from django.utils.timezone import now
 
+logger = logging.getLogger(__name__)
+
 @login_required
 def dashboard(request):
     movimientos = Movimiento.objects.filter(usuario=request.user).order_by('-fecha')
 
     favoritas = Cuenta.objects.filter(favorita='True')
 
+    frecuentes = MovimientoFrecuente.objects.filter(usuario=request.user)
+
+    logger.warning(f"Frecuentes: {frecuentes}")
+    logger.warning(f"Monto: {frecuentes[0].monto}")
+    # Aplicar filtros si se han proporcionado
+
     return render(request, 'dashboard.html', {
         'movimientos': movimientos,
         'user': request.user,
         'favoritas': favoritas,
+        'frecuentes': frecuentes,
     })
 
 # Movimientos
@@ -36,9 +48,34 @@ def agregar_movimiento(request):
             movimiento.cuenta_origen.save()
             movimiento.cuenta_destino.saldo += movimiento.monto
             movimiento.cuenta_destino.save()
+            messages.success(request, 'Movimiento registrado con éxito.')
+
             return redirect('dashboard')
     else:
-        form = MovimientoForm()
+        datos_iniciales = {}
+        origen = request.GET.get('origen')
+        destino = request.GET.get('destino')
+        monto_raw = request.GET.get('monto')
+
+        try:
+            if origen:
+                datos_iniciales['cuenta_origen'] = Cuenta.objects.get(nombre=request.GET['origen'], usuario=request.user)
+            if destino:
+                datos_iniciales['cuenta_destino'] = Cuenta.objects.get(nombre=request.GET['destino'], usuario=request.user)
+            if monto_raw:
+                # Reemplaza coma por punto, elimina símbolos y espacios
+                monto_normalizado = re.sub(r'[^\d,.-]', '', monto_raw).replace(',', '.')
+                try:
+                    datos_iniciales['monto'] = str(Decimal(monto_normalizado).quantize(Decimal('0.01')))
+                except InvalidOperation:
+                    pass  # Ignorar monto malformado
+                    logger.warning(f"monto: {datos_iniciales['monto']}")
+        except (Cuenta.DoesNotExist, InvalidOperation):
+            pass
+
+        logger.warning(f"datos iniciales: {datos_iniciales}")
+
+        form = MovimientoForm(initial=datos_iniciales)
         form.fields['cuenta_origen'].queryset = Cuenta.objects.filter(usuario=request.user)
         form.fields['cuenta_destino'].queryset = Cuenta.objects.filter(usuario=request.user)
     return render(request, 'agregar_movimiento.html', {'form': form})

+ 22 - 0
static/style.css

@@ -384,6 +384,17 @@ body {
    font-size: 15px;
    color: #828997;
 }
+
+.values .val-favoritos {
+   background: #d6d8d7;
+   width: 235px;
+   padding: 16px 20px;
+   border-radius: 5px;
+   display: flex;
+   justify-content: flex-start;   
+   align-items: center;
+}
+
 /* Estilo del panel principal donde irá el contenido */
 
 .board{
@@ -514,18 +525,29 @@ tbody .movimiento-monto {
       width: 100%;
   }
 
+  /* las cajas de valores */
+
   .values {
    padding: 30px 40px 0 30px;
    justify-content: flex-start;
   }
+
   .values .val-box {
    padding: 16px 20px;
    margin: 10px 20px 10px 0;
   }
+
   .values .val-cuenta {
    padding: 16px 20px;
    margin: 10px 20px 10px 0;
   }
+
+  .values .val-favoritos{
+   padding: 16px 20px;
+   margin: 10px 20px 10px 0;
+  }
+  /* el contenedor del panel principal */
+
   .board {
    width: 92%;
    padding: 0;

+ 14 - 0
templates/dashboard.html

@@ -20,6 +20,20 @@
         {% endfor %}
     </div>
 
+    <div class="values">
+        {% for f in frecuentes %}
+        <div class="val-favoritos">
+            <div>
+                <a href="{% url 'agregar_movimiento' %}?origen={{ f.cuenta_origen.nombre|urlencode }}&destino={{ f.cuenta_destino.nombre|urlencode }}&monto={{ f.monto }}">
+                    {{ f.nombre }} ({{ f.monto }} €)
+                </a>                
+            </div>
+        </div>
+        {% empty %}
+            <li>Sin movmimientos frecuentes configurados</li>
+        {% endfor %}
+    </div>
+
     <div class="board">
         <h3>Movimientos recientes</h3>
         <table width="100%">