From c395c638e9523910af2c5060a0afea56235a18b1 Mon Sep 17 00:00:00 2001 From: JKuijperM Date: Wed, 16 Sep 2026 08:32:11 +0200 Subject: [PATCH] Anade un rango de fechas libre al listado de gastos Los selectores de ano y mes solo saben expresar periodos naturales completos. "Del 15 de marzo al 3 de abril" o "desde que empece el trabajo nuevo" no se pueden pedir, y son justo las preguntas que uno le hace a un gestor de gastos. Se anaden dos parametros date_from y date_to, opcionales por separado: "desde el 1 de marzo" sin fecha final es un filtro perfectamente valido. Si el rango viene invertido se ignoran las dos fechas, porque devolver una lista vacia sin explicacion es peor que descartar un filtro mal puesto. Cuando hay rango, manda el rango y los selectores de ano y mes no se aplican: combinar ambos criterios da intersecciones que el usuario no ha pedido y no puede ver. La plantilla lo avisa con un mensaje y un enlace para quitarlo, en vez de dejar los selectores mostrando un periodo que no es el que se esta viendo. Los campos de fecha comparten estilo con el resto de filtros, incluido el anillo de foco, para que no desentonen con los selectores de al lado. Co-Authored-By: Claude Opus 5 --- .../expenses/static/expenses/css/base.css | 12 ++++- .../templates/expenses/_date_range.html | 12 +++++ .../templates/expenses/expense_list.html | 10 ++++ expenses_manager/expenses/views.py | 52 +++++++++++++++++-- 4 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 expenses_manager/expenses/templates/expenses/_date_range.html diff --git a/expenses_manager/expenses/static/expenses/css/base.css b/expenses_manager/expenses/static/expenses/css/base.css index 5031c8c..6593c5a 100644 --- a/expenses_manager/expenses/static/expenses/css/base.css +++ b/expenses_manager/expenses/static/expenses/css/base.css @@ -396,7 +396,8 @@ button[type="submit"]:hover, gap: 0.5rem; } -.filters-main select { +.filters-main select, +.filters-main input[type="date"] { padding: 0.5rem 0.7rem; font-family: inherit; font-size: 0.95rem; @@ -406,11 +407,18 @@ button[type="submit"]:hover, border-radius: 6px; } -.filters-main select:focus { +.filters-main select:focus, +.filters-main input[type="date"]:focus { outline: 2px solid var(--color-focus-ring); outline-offset: 1px; } +.range-notice { + margin-top: 0.5rem; + font-size: 0.9rem; + color: var(--color-text-muted); +} + .filters-advanced { margin-top: 0.5rem; } diff --git a/expenses_manager/expenses/templates/expenses/_date_range.html b/expenses_manager/expenses/templates/expenses/_date_range.html new file mode 100644 index 0000000..16c6f82 --- /dev/null +++ b/expenses_manager/expenses/templates/expenses/_date_range.html @@ -0,0 +1,12 @@ +{% comment %} +Campos del rango de fechas libre. Se incluye dentro de un
. +Espera date_from y date_to en el contexto. +{% endcomment %} + + + + + + diff --git a/expenses_manager/expenses/templates/expenses/expense_list.html b/expenses_manager/expenses/templates/expenses/expense_list.html index d31d670..b484fa0 100644 --- a/expenses_manager/expenses/templates/expenses/expense_list.html +++ b/expenses_manager/expenses/templates/expenses/expense_list.html @@ -47,10 +47,20 @@ {% endfor %} + {% include "expenses/_date_range.html" %} + Limpiar + {% if range_active %} +

+ Mostrando el rango de fechas seleccionado; los filtros de año y mes no + se aplican. + Quitar el rango +

+ {% endif %} +
hasta) se ignoran LAS DOS fechas: devolver + una lista vacía sin explicación es peor que ignorar un filtro mal puesto. + """ + date_from = _get_date(request.GET.get("date_from")) + date_to = _get_date(request.GET.get("date_to")) + + if date_from and date_to and date_from > date_to: + return None, None + + return date_from, date_to + + def _safe_next(request): next_url = request.POST.get("next") or request.GET.get("next") @@ -336,11 +367,21 @@ def expense_list(request): if (t_id:= _get_int(t)) is not None ] - if year: - expenses = expenses.filter(date__year=year) + date_from, date_to = _resolve_date_range(request) + range_active = bool(date_from or date_to) - if month: - expenses = expenses.filter(date__month=month) + # Un solo criterio de periodo a la vez: si hay rango, manda el rango y los + # selectores de año y mes no se aplican (la plantilla lo avisa). + if range_active: + if date_from: + expenses = expenses.filter(date__gte=date_from) + if date_to: + expenses = expenses.filter(date__lte=date_to) + else: + if year: + expenses = expenses.filter(date__year=year) + if month: + expenses = expenses.filter(date__month=month) if category: expenses = expenses.filter(category_id=category) @@ -407,6 +448,9 @@ def expense_list(request): "page_obj": page_obj, "selected_year": year, "selected_month": month, + "date_from": date_from, + "date_to": date_to, + "range_active": range_active, "selected_category": category, "categories": categories, "year_list": [y.year for y in year_list],