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 <noreply@anthropic.com>
This commit is contained in:
parent
f154127f9e
commit
814487a390
@ -23,6 +23,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Categoría</th>
|
||||
<th>Gastos</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -30,6 +31,7 @@
|
||||
{% for row in category_rows %}
|
||||
<tr>
|
||||
<td class="cat-depth-{{ row.depth }}">{{ row.category.name }}</td>
|
||||
<td>{{ row.category.expense_count }}</td>
|
||||
<td class="table-actions">
|
||||
<a href="{% url 'category_edit' row.category.id %}">Editar</a>
|
||||
<a href="{% url 'category_delete' row.category.id %}" class="danger">Eliminar</a>
|
||||
@ -37,7 +39,7 @@
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="2" class="empty-state">
|
||||
<td colspan="3" class="empty-state">
|
||||
<p>No hay categorías</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user