Merge pull request 'dev' (#6) from dev into main

Reviewed-on: #6
This commit is contained in:
jkuijperm 2026-04-29 16:15:19 +00:00
commit 48d7fc576d
5 changed files with 129 additions and 38 deletions

View File

@ -13,6 +13,7 @@ class ExpenseForm(forms.ModelForm):
self.fields['category'].queryset = Category.objects.filter(owner=user)
self.fields['tags'].queryset = Tag.objects.filter(owner=user)
self.fields['account'].queryset = Account.objects.filter(owner=user, active=True)
self.fields['date'].input_formats = ['%Y-%m-%d']
class Meta:
model = Expense
@ -25,7 +26,9 @@ class ExpenseForm(forms.ModelForm):
'tags',
]
widgets = {
'date': forms.DateInput(attrs={'type': 'date'}),
'date': forms.DateInput(
format='%Y-%m-%d',
attrs={'type': 'date'}),
'widget': forms.CheckboxSelectMultiple(),
}
@ -46,7 +49,9 @@ class IncomeForm(forms.ModelForm):
model = Income
fields = ['account', 'name', 'amount', 'date']
widgets = {
'date': forms.DateInput(attrs={'type': 'date'})
'date': forms.DateInput(
format='%Y-%m-%d',
attrs={'type': 'date'})
}
def __init__(self, *args, **kwargs):
@ -59,7 +64,9 @@ class IncomeForm(forms.ModelForm):
class FuelEntryForm(forms.Form):
# Expense fields
date = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'}))
date = forms.DateField(widget=forms.DateInput(
format='%Y-%m-%d',
attrs={'type': 'date'}))
amount = forms.DecimalField(max_digits=10, decimal_places=2)
account = forms.ModelChoiceField(queryset=None)
@ -67,13 +74,15 @@ class FuelEntryForm(forms.Form):
odometer = forms.DecimalField(label='Current kilometers')
liters = forms.DecimalField(max_digits=8, decimal_places=2)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
self.fields['account'].queryset = (
user.accounts.filter(active=True)
)
if user:
self.fields['account'].queryset = (
user.accounts.filter(active=True)
)
class CategoryForm(forms.ModelForm):
class Meta:

View File

@ -128,7 +128,11 @@
{% endfor %}
</td>
<td class="table-actions">
<a href="{% url 'expense_edit' expense.id %}">Editar</a>
{% if expense.category.slug == 'gasolina' %}
<a href="{% url 'fuel_edit' expense.id %}">Editar</a>
{% else %}
<a href="{% url 'expense_edit' expense.id %}">Editar</a>
{% endif %}
<a href="{% url 'expense_delete' expense.id %}" class="danger">Eliminar</a>
</td>
</tr>
@ -144,17 +148,17 @@
</table>
<div class="pagination">
<span class="step-links">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1{% if selected_year %}&year={{ selected_year }}{% endif %}{% if selected_month %}&month={{ selected_month }}{% endif %}{% if selected_category %}&category={{ selected_category }}{% endif %}{% if selected_tag %}&tag={{ selected_tag }}{% endif %}">&laquo; Primero</a>
<a href="?page={{ page_obj.previous_page_number }}{% if selected_year %}&year={{ selected_year }}{% endif %}{% if selected_month %}&month={{ selected_month }}{% endif %}{% if selected_category %}&category={{ selected_category }}{% endif %}{% if selected_tag %}&tag={{ selected_tag }}{% endif %}">Anterior</a>
<a href="?page=1{% if query_params %}&{{ query_params }}{% endif %}">&laquo; Primero</a>
<a href="?page={{ page_obj.previous_page_number }}{% if query_params %}&{{ query_params }}{% endif %}">Anterior</a>
{% endif %}
<span>Página {{ page_obj.number }} de {{ page_obj.paginator.num_pages }}</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}{% if selected_year %}&year={{ selected_year }}{% endif %}{% if selected_month %}&month={{ selected_month }}{% endif %}{% if selected_category %}&category={{ selected_category }}{% endif %}{% if selected_tag %}&tag={{ selected_tag }}{% endif %}">Siguiente</a>
<a href="?page={{ page_obj.paginator.num_pages }}{% if selected_year %}&year={{ selected_year }}{% endif %}{% if selected_month %}&month={{ selected_month }}{% endif %}{% if selected_category %}&category={{ selected_category }}{% endif %}{% if selected_tag %}&tag={{ selected_tag }}{% endif %}">Último &raquo;</a>
<a href="?page={{ page_obj.next_page_number }}{% if query_params %}&{{ query_params }}{% endif %}">Siguiente</a>
<a href="?page={{ page_obj.paginator.num_pages }}{% if query_params %}&{{ query_params }}{% endif %}">Último &raquo;</a>
{% endif %}
</span>
</div>

View File

@ -1,21 +1,37 @@
{% extends "expenses/base.html" %}
{% block title %}
Nuevo repostaje
{% if editing %}
Editar repostaje
{% else %}
Nuevo repostaje
{% endif %}
{% endblock %}
{% block content %}
<h1>
Nuevo repostaje
{% if editing %}
Editar repostaje
{% else %}
Nuevo repostaje
{% endif %}
</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">
Crear repostaje
{% if editing %}
Guardar repostaje
{% else %}
Crear repostaje
{% endif %}
</button>
</form>
<a href="{% url 'fuel_list' %}">Volver</a>
{% if editing %}
<a href="{% url 'expense_list' %}">Volver</a>
{% else %}
<a href="{% url 'fuel_list' %}">Volver</a>
{% endif %}
{% endblock %}

View File

@ -22,5 +22,6 @@ urlpatterns = [
path('incomes/<int:pk>/delete/', views.income_delete, name='income_delete'),
path('fuel/', views.fuel_list, name='fuel_list'),
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'),
]

View File

@ -1,6 +1,7 @@
from operator import truediv
from datetime import date, datetime
from django.contrib import messages
from django.template import context
from .models import Account, Category, Expense, FuelEntry, Tag, Income
from .forms import ExpenseForm, IncomeForm, TagForm, AccountForm, FuelEntryForm, CategoryForm
# from dateutli.relativedelta import relativedelta
@ -156,7 +157,10 @@ def expense_list(request):
# Pagination
paginator = Paginator(expenses, 10)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
page_obj = paginator.get_page(page_number)
query_params = request.GET.copy()
query_params.pop('page', None)
# tags with state
tags_with_state = []
@ -203,7 +207,8 @@ def expense_list(request):
'tags_with_state': tags_with_state,
'accounts': Account.objects.filter(owner=request.user),
'selected_account': account_id,
'advanced_filters_open' : advanced_filters_open
'advanced_filters_open' : advanced_filters_open,
'query_params': query_params.urlencode(),
},
)
@ -232,24 +237,32 @@ def expense_create(request):
@login_required
def expense_edit(request, pk):
# sourcery skip: assign-if-exp, merge-else-if-into-elif
expense = get_object_or_404(
Expense,
pk=pk,
owner=request.user,
)
if request.method == "POST":
form = ExpenseForm(request.POST or None, instance=expense, user=request.user)
form = ExpenseForm(
request.POST or None,
instance=expense,
user=request.user)
if form.is_valid():
expense = form.save()
messages.success(request, 'Gasto actualizado')
return redirect('expense_list')
else:
form = ExpenseForm(instance=expense, user=request.user)
form = ExpenseForm(instance=expense, user=request.user)
return render(
request,
'expenses/expense_form.html',
{'active_menu': 'expenses','form': form}
'expenses/expense_form.html', {
'active_menu': 'expenses',
'form': form,
}
)
@ -782,33 +795,29 @@ def fuel_create(request):
@login_required
def fuel_list(request):
selected_year = request.GET.get('year')
current_year = datetime.now().year
if selected_year:
selected_year = int(selected_year)
else:
selected_year = current_year
selected_year = int(selected_year) if selected_year else current_year
fuels = FuelEntry.objects.filter(
expense__owner=request.user,
expense__date__year=selected_year
).select_related('expense').order_by('expense__date')
monthly_expenses = (
fuels
.annotate(month=ExtractMonth('expense__date'))
.values('month')
.annotate(total=Sum('expense__amount'))
)
month_map = {m['month']: float(m['total']) for m in monthly_expenses}
monthly_data = [
month_map.get(month, 0)
for month in range(1, 13)
]
year_list = (
FuelEntry.objects.filter(
expense__owner=request.user,)
@ -817,16 +826,16 @@ def fuel_list(request):
.distinct()
.order_by('year')
)
km_data = []
dates = []
for fuel in fuels:
km = fuel.km_since_previous()
if km:
km_data.append(km)
dates.append(fuel.expense.date.strftime('%Y-%m-%d'))
return render( request, 'fuel/list.html',
{
'active_menu': 'fuel',
@ -839,6 +848,58 @@ def fuel_list(request):
}
)
@login_required
def fuel_edit(request, pk):
expense = get_object_or_404(
Expense,
pk=pk,
owner=request.user,
)
fuel = get_object_or_404(FuelEntry, expense=expense)
if request.method == "POST":
form = FuelEntryForm(
request.POST,
user=request.user
)
if form.is_valid():
# Update expense
expense.date = form.cleaned_data['date']
expense.amount = form.cleaned_data['amount']
expense.account = form.cleaned_data['account']
expense.description = 'Repostaje'
expense.save()
# Update FuelEntry
fuel.odometer = form.cleaned_data['odometer']
fuel.liters = form.cleaned_data['liters']
fuel.save()
return redirect('expense_list')
else:
fuel = expense.fuel_data
# Initialize manually
form = FuelEntryForm(
initial={
'date': expense.date,
'amount': expense.amount,
'account': expense.account,
'odometer': fuel.odometer,
'liters': fuel.liters
},
user=request.user
)
return render(
request, 'fuel/create.html', {
'active_menu': 'expenses',
'form': form,
'editing': True,
}
)
@login_required
def category_list(request):
categories = Category.objects.filter(