From 814487a39041b937a171d1fe5de3de1257eb7f23 Mon Sep 17 00:00:00 2001 From: JKuijperM Date: Wed, 9 Sep 2026 16:21:35 +0200 Subject: [PATCH] Anade columna con el numero de gastos de cada categoria El listado de categorias no daba ninguna pista de cuales estan en uso. Anade la columna con el mismo criterio que el de etiquetas: annotate en la vista para no disparar una query por fila. Cuenta solo los gastos directos de cada categoria, no los de sus descendientes. Si el numero incluyera a los hijos, un padre sin gastos propios mostraria una cifra que no corresponde a ninguna fila suya y que no cuadraria con lo que se ve al filtrar por esa categoria. Con Category.Meta.ordering = [Lower("name")], Django anade la expresion al GROUP BY del annotate. Verificado que no multiplica filas ni fusiona categorias cuyo nombre solo difiere en mayusculas. Co-Authored-By: Claude Opus 5 --- .../expenses/templates/categories/list.html | 4 +++- .../expenses/tests/test_categories.py | 23 +++++++++++++++++++ expenses_manager/expenses/views.py | 6 ++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/expenses_manager/expenses/templates/categories/list.html b/expenses_manager/expenses/templates/categories/list.html index 0a40561..224af55 100644 --- a/expenses_manager/expenses/templates/categories/list.html +++ b/expenses_manager/expenses/templates/categories/list.html @@ -23,6 +23,7 @@ Categoría + Gastos @@ -30,6 +31,7 @@ {% for row in category_rows %} {{ row.category.name }} + {{ row.category.expense_count }} Editar Eliminar @@ -37,7 +39,7 @@ {% empty %} - +

No hay categorías

diff --git a/expenses_manager/expenses/tests/test_categories.py b/expenses_manager/expenses/tests/test_categories.py index 0d6a6c2..6c9bf74 100644 --- a/expenses_manager/expenses/tests/test_categories.py +++ b/expenses_manager/expenses/tests/test_categories.py @@ -116,3 +116,26 @@ def test_category_list_view_returns_tree_ordered_with_depth(auth_client, user): ("Nieto", 2), ("B raiz", 0), ] + + +def test_category_list_counts_only_direct_expenses(auth_client, user, account): + parent = Category.objects.create(name="Padre", owner=user) + child = Category.objects.create(name="Hija", owner=user, parent=parent) + + Expense.objects.create( + owner=user, account=account, category=parent, + amount=Decimal("10"), date=date.today(), + ) + for _ in range(2): + Expense.objects.create( + owner=user, account=account, category=child, + amount=Decimal("5"), date=date.today(), + ) + + response = auth_client.get(reverse('category_list')) + + counts = { + row["category"].name: row["category"].expense_count + for row in response.context["category_rows"] + } + assert counts == {"Padre": 1, "Hija": 2} diff --git a/expenses_manager/expenses/views.py b/expenses_manager/expenses/views.py index 4f73831..34d77ac 100644 --- a/expenses_manager/expenses/views.py +++ b/expenses_manager/expenses/views.py @@ -990,7 +990,11 @@ def fuel_delete(request, pk): @login_required def category_list(request): - categories = Category.objects.filter(owner=request.user) + categories = list( + Category.objects.filter(owner=request.user) + .annotate(expense_count=Count("expenses")) + .select_related("parent") + ) if request.method == "POST": form = CategoryForm(request.POST, user=request.user)