Modificaciones en filtrado y creada opción para marcar que un gasto/ingreso es un traspaso de cuentas #34
@ -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;
|
||||
}
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
{% comment %}
|
||||
Campos del rango de fechas libre. Se incluye dentro de un <form method="get">.
|
||||
Espera date_from y date_to en el contexto.
|
||||
{% endcomment %}
|
||||
|
||||
<label class="sr-only" for="dateFrom">Desde</label>
|
||||
<input type="date" name="date_from" id="dateFrom"
|
||||
value="{% if date_from %}{{ date_from|date:'Y-m-d' }}{% endif %}">
|
||||
|
||||
<label class="sr-only" for="dateTo">Hasta</label>
|
||||
<input type="date" name="date_to" id="dateTo"
|
||||
value="{% if date_to %}{{ date_to|date:'Y-m-d' }}{% endif %}">
|
||||
@ -47,10 +47,20 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
{% include "expenses/_date_range.html" %}
|
||||
|
||||
<button type="submit" class="btn btn-primary">Filtrar</button>
|
||||
<a href="{% url 'expense_list' %}" class="btn btn-secondary">Limpiar</a>
|
||||
</div>
|
||||
|
||||
{% if range_active %}
|
||||
<p class="range-notice">
|
||||
Mostrando el rango de fechas seleccionado; los filtros de año y mes no
|
||||
se aplican.
|
||||
<a href="{% url 'expense_list' %}">Quitar el rango</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<br>
|
||||
|
||||
<details class="filters-advanced"
|
||||
|
||||
@ -31,6 +31,37 @@ def _get_int(value):
|
||||
return None
|
||||
|
||||
|
||||
# Umbral del eje del gráfico con rango libre: dos meses es donde un gráfico
|
||||
# diario deja de leerse, así que por encima se agrupa por mes.
|
||||
RANGE_DAY_CHART_MAX_DAYS = 62
|
||||
|
||||
|
||||
def _get_date(value):
|
||||
"""Parsea una fecha AAAA-MM-DD de la URL. None si falta o no es válida."""
|
||||
try:
|
||||
return datetime.strptime(value, "%Y-%m-%d").date()
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def _resolve_date_range(request):
|
||||
"""Lee el rango de fechas libre de la URL.
|
||||
|
||||
Devuelve (date_from, date_to); cualquiera de los dos puede ser None, porque
|
||||
"desde el 1 de marzo" sin fecha final es un filtro válido.
|
||||
|
||||
Si el rango está invertido (desde > 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],
|
||||
|
||||
Loading…
Reference in New Issue
Block a user