Fixed bugs 2 #15

Merged
jkuijperm merged 13 commits from dev into main 2026-07-24 09:38:43 +00:00
5 changed files with 115 additions and 1 deletions
Showing only changes of commit 03016209b0 - Show all commits

View File

@ -0,0 +1,38 @@
{% extends "expenses/base.html" %}
{% block title %}
Categorías
{% endblock %}
{% block content %}
<h2>Eliminar categoría</h2>
<p>¿Seguro que quieres eliminar la categoría <strong>{{ category.name }}</strong>?</p>
{% if expense_count %}
<p class="form-errors">
Esta categoría tiene {{ expense_count }} gasto{{ expense_count|pluralize }} asociado{{ expense_count|pluralize }}
y no se puede eliminar. Reasigna esos gastos a otra categoría primero.
</p>
{% else %}
{% if children %}
<p class="form-errors">
Atención: también se eliminarán sus subcategorías:
{% for child in children %}<strong>{{child.name}}</strong>{% if not forloop.last %}, {% endif %}{% endfor %}.
</p>
{% endif %}
{% if goal_count %}
<p class="form-errors">
Atención: se eliminarán también {{ goal_count }} objetivo{{ goal_count|pluralize }} asociado{{ goal_count|pluralize }} a esta categoría.
</p>
{% endif %}
{% endif %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button class="btn danger">Eliminar</button>
<a class="btn" href="{% url 'category_list' %}">Cancelar</a>
</form>
{% endblock %}

View File

@ -0,0 +1,16 @@
{% extends "expenses/base.html" %}
{% block title %}
Categorías
{% endblock %}
{% block content %}
<h2>Editar categoría</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Guardar</button>
<a class="btn" href="{% url 'category_list' %}">Cancelar</a>
</form>
{% endblock %}

View File

@ -30,6 +30,10 @@
<tr>
<td>{{ category.name }}</td>
<td>{% if category.parent %}{{ category.parent.name }}{% endif %}</td>
<td class="table-actions">
<a href="{% url 'category_edit' category.id %}">Editar</a>
<a href="{% url 'category_delete' category.id %}" class="danger">Eliminar</a>
</td>
</tr>
{% endfor %}
</tbody>

View File

@ -24,6 +24,8 @@ urlpatterns = [
path('fuel/create/', views.fuel_create, name='fuel_create'),
path('fuel/<int:pk>/edit/', views.fuel_edit, name='fuel_edit'),
path('categories/', views.category_list, name='category_list'),
path('categories/<int:pk>/edit/', views.category_edit, name='category_edit'),
path('categories/<int:pk>/delete/', views.category_delete, name='category_delete'),
path('settings/', views.settings_index, name='settings_index'),
path('goals/', views.goal_list, name='goal_list'),
path('goals/new/', views.goal_create, name='goal_create'),

View File

@ -13,8 +13,8 @@ from .forms import (
GoalForm,
)
from django.db.models import Sum
from django.core.paginator import Paginator
from django.db.models import Sum, ProtectedError
from django.db.models.functions import ExtractMonth, ExtractYear, ExtractDay
from django.contrib.auth.decorators import login_required
@ -859,6 +859,60 @@ def category_list(request):
)
@login_required
def category_edit(request, pk):
category = get_object_or_404(Category, pk=pk, owner=request.user)
if request.method == "POST":
form = CategoryForm(request.POST, instance=category, user=request.user)
if form.is_valid():
form.save()
messages.success(request, "Categoría actualizada")
return redirect("category_list")
else:
form = CategoryForm(instance=category, user=request.user)
return render(
request,
"categories/form.html",
{
"active_menu": "settings",
"form":form,
"category": category,
}
)
@login_required
def category_delete(request, pk):
category = get_object_or_404(Category, pk=pk, owner=request.user)
if request.method == "POST":
try:
category.delete()
except ProtectedError:
messages.error(
request,
f"No se puede eliminar «{category.name}»; tiene gastos asociados. "
"Reasigna esos gastos a otra categoría antes de borrarla."
)
else:
messages.success(request, "Categoría eliminada.")
return redirect("category_list")
return render(
request,
"categories/confirm_delete.html",
{
"active_menu": "settings",
"category": category,
"children": category.children.all(),
"expense_count": category.expenses.count(),
"goal_count": category.goal_set.count(),
},
)
@login_required
def goal_list(request):
goals = Goal.objects.filter(owner=request.user)