dev #6
@ -13,6 +13,7 @@ class ExpenseForm(forms.ModelForm):
|
|||||||
self.fields['category'].queryset = Category.objects.filter(owner=user)
|
self.fields['category'].queryset = Category.objects.filter(owner=user)
|
||||||
self.fields['tags'].queryset = Tag.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['account'].queryset = Account.objects.filter(owner=user, active=True)
|
||||||
|
self.fields['date'].input_formats = ['%Y-%m-%d']
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Expense
|
model = Expense
|
||||||
@ -25,7 +26,9 @@ class ExpenseForm(forms.ModelForm):
|
|||||||
'tags',
|
'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'date': forms.DateInput(attrs={'type': 'date'}),
|
'date': forms.DateInput(
|
||||||
|
format='%Y-%m-%d',
|
||||||
|
attrs={'type': 'date'}),
|
||||||
'widget': forms.CheckboxSelectMultiple(),
|
'widget': forms.CheckboxSelectMultiple(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +49,9 @@ class IncomeForm(forms.ModelForm):
|
|||||||
model = Income
|
model = Income
|
||||||
fields = ['account', 'name', 'amount', 'date']
|
fields = ['account', 'name', 'amount', 'date']
|
||||||
widgets = {
|
widgets = {
|
||||||
'date': forms.DateInput(attrs={'type': 'date'})
|
'date': forms.DateInput(
|
||||||
|
format='%Y-%m-%d',
|
||||||
|
attrs={'type': 'date'})
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@ -59,7 +64,9 @@ class IncomeForm(forms.ModelForm):
|
|||||||
|
|
||||||
class FuelEntryForm(forms.Form):
|
class FuelEntryForm(forms.Form):
|
||||||
# Expense fields
|
# 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)
|
amount = forms.DecimalField(max_digits=10, decimal_places=2)
|
||||||
account = forms.ModelChoiceField(queryset=None)
|
account = forms.ModelChoiceField(queryset=None)
|
||||||
|
|
||||||
@ -67,13 +74,15 @@ class FuelEntryForm(forms.Form):
|
|||||||
odometer = forms.DecimalField(label='Current kilometers')
|
odometer = forms.DecimalField(label='Current kilometers')
|
||||||
liters = forms.DecimalField(max_digits=8, decimal_places=2)
|
liters = forms.DecimalField(max_digits=8, decimal_places=2)
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
user = kwargs.pop('user')
|
user = kwargs.pop('user')
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
self.fields['account'].queryset = (
|
if user:
|
||||||
user.accounts.filter(active=True)
|
self.fields['account'].queryset = (
|
||||||
)
|
user.accounts.filter(active=True)
|
||||||
|
)
|
||||||
|
|
||||||
class CategoryForm(forms.ModelForm):
|
class CategoryForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@ -128,7 +128,11 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
<td class="table-actions">
|
<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>
|
<a href="{% url 'expense_delete' expense.id %}" class="danger">Eliminar</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -144,17 +148,17 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
<span class="step-links">
|
<span class="step-links">
|
||||||
{% if page_obj.has_previous %}
|
{% 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 %}">« Primero</a>
|
<a href="?page=1{% if query_params %}&{{ query_params }}{% endif %}">« 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={{ page_obj.previous_page_number }}{% if query_params %}&{{ query_params }}{% endif %}">Anterior</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<span>Página {{ page_obj.number }} de {{ page_obj.paginator.num_pages }}</span>
|
<span>Página {{ page_obj.number }} de {{ page_obj.paginator.num_pages }}</span>
|
||||||
|
|
||||||
{% if page_obj.has_next %}
|
{% 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.next_page_number }}{% if query_params %}&{{ query_params }}{% 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 »</a>
|
<a href="?page={{ page_obj.paginator.num_pages }}{% if query_params %}&{{ query_params }}{% endif %}">Último »</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,21 +1,37 @@
|
|||||||
{% extends "expenses/base.html" %}
|
{% extends "expenses/base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
Nuevo repostaje
|
{% if editing %}
|
||||||
|
Editar repostaje
|
||||||
|
{% else %}
|
||||||
|
Nuevo repostaje
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>
|
<h1>
|
||||||
Nuevo repostaje
|
{% if editing %}
|
||||||
|
Editar repostaje
|
||||||
|
{% else %}
|
||||||
|
Nuevo repostaje
|
||||||
|
{% endif %}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form.as_p }}
|
{{ form.as_p }}
|
||||||
<button type="submit">
|
<button type="submit">
|
||||||
Crear repostaje
|
{% if editing %}
|
||||||
|
Guardar repostaje
|
||||||
|
{% else %}
|
||||||
|
Crear repostaje
|
||||||
|
{% endif %}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</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 %}
|
{% endblock %}
|
||||||
@ -22,5 +22,6 @@ urlpatterns = [
|
|||||||
path('incomes/<int:pk>/delete/', views.income_delete, name='income_delete'),
|
path('incomes/<int:pk>/delete/', views.income_delete, name='income_delete'),
|
||||||
path('fuel/', views.fuel_list, name='fuel_list'),
|
path('fuel/', views.fuel_list, name='fuel_list'),
|
||||||
path('fuel/create/', views.fuel_create, name='fuel_create'),
|
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/', views.category_list, name='category_list'),
|
||||||
]
|
]
|
||||||
@ -1,6 +1,7 @@
|
|||||||
from operator import truediv
|
from operator import truediv
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django.template import context
|
||||||
from .models import Account, Category, Expense, FuelEntry, Tag, Income
|
from .models import Account, Category, Expense, FuelEntry, Tag, Income
|
||||||
from .forms import ExpenseForm, IncomeForm, TagForm, AccountForm, FuelEntryForm, CategoryForm
|
from .forms import ExpenseForm, IncomeForm, TagForm, AccountForm, FuelEntryForm, CategoryForm
|
||||||
# from dateutli.relativedelta import relativedelta
|
# from dateutli.relativedelta import relativedelta
|
||||||
@ -156,7 +157,10 @@ def expense_list(request):
|
|||||||
# Pagination
|
# Pagination
|
||||||
paginator = Paginator(expenses, 10)
|
paginator = Paginator(expenses, 10)
|
||||||
page_number = request.GET.get('page')
|
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
|
||||||
tags_with_state = []
|
tags_with_state = []
|
||||||
@ -203,7 +207,8 @@ def expense_list(request):
|
|||||||
'tags_with_state': tags_with_state,
|
'tags_with_state': tags_with_state,
|
||||||
'accounts': Account.objects.filter(owner=request.user),
|
'accounts': Account.objects.filter(owner=request.user),
|
||||||
'selected_account': account_id,
|
'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
|
@login_required
|
||||||
def expense_edit(request, pk):
|
def expense_edit(request, pk):
|
||||||
|
# sourcery skip: assign-if-exp, merge-else-if-into-elif
|
||||||
expense = get_object_or_404(
|
expense = get_object_or_404(
|
||||||
Expense,
|
Expense,
|
||||||
pk=pk,
|
pk=pk,
|
||||||
owner=request.user,
|
owner=request.user,
|
||||||
)
|
)
|
||||||
|
|
||||||
if request.method == "POST":
|
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():
|
if form.is_valid():
|
||||||
expense = form.save()
|
expense = form.save()
|
||||||
messages.success(request, 'Gasto actualizado')
|
messages.success(request, 'Gasto actualizado')
|
||||||
return redirect('expense_list')
|
return redirect('expense_list')
|
||||||
else:
|
else:
|
||||||
form = ExpenseForm(instance=expense, user=request.user)
|
form = ExpenseForm(instance=expense, user=request.user)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
'expenses/expense_form.html',
|
'expenses/expense_form.html', {
|
||||||
{'active_menu': 'expenses','form': form}
|
'active_menu': 'expenses',
|
||||||
|
'form': form,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -782,33 +795,29 @@ def fuel_create(request):
|
|||||||
@login_required
|
@login_required
|
||||||
def fuel_list(request):
|
def fuel_list(request):
|
||||||
selected_year = request.GET.get('year')
|
selected_year = request.GET.get('year')
|
||||||
|
|
||||||
current_year = datetime.now().year
|
current_year = datetime.now().year
|
||||||
|
|
||||||
if selected_year:
|
selected_year = int(selected_year) if selected_year else current_year
|
||||||
selected_year = int(selected_year)
|
|
||||||
else:
|
|
||||||
selected_year = current_year
|
|
||||||
|
|
||||||
fuels = FuelEntry.objects.filter(
|
fuels = FuelEntry.objects.filter(
|
||||||
expense__owner=request.user,
|
expense__owner=request.user,
|
||||||
expense__date__year=selected_year
|
expense__date__year=selected_year
|
||||||
).select_related('expense').order_by('expense__date')
|
).select_related('expense').order_by('expense__date')
|
||||||
|
|
||||||
monthly_expenses = (
|
monthly_expenses = (
|
||||||
fuels
|
fuels
|
||||||
.annotate(month=ExtractMonth('expense__date'))
|
.annotate(month=ExtractMonth('expense__date'))
|
||||||
.values('month')
|
.values('month')
|
||||||
.annotate(total=Sum('expense__amount'))
|
.annotate(total=Sum('expense__amount'))
|
||||||
)
|
)
|
||||||
|
|
||||||
month_map = {m['month']: float(m['total']) for m in monthly_expenses}
|
month_map = {m['month']: float(m['total']) for m in monthly_expenses}
|
||||||
|
|
||||||
monthly_data = [
|
monthly_data = [
|
||||||
month_map.get(month, 0)
|
month_map.get(month, 0)
|
||||||
for month in range(1, 13)
|
for month in range(1, 13)
|
||||||
]
|
]
|
||||||
|
|
||||||
year_list = (
|
year_list = (
|
||||||
FuelEntry.objects.filter(
|
FuelEntry.objects.filter(
|
||||||
expense__owner=request.user,)
|
expense__owner=request.user,)
|
||||||
@ -817,16 +826,16 @@ def fuel_list(request):
|
|||||||
.distinct()
|
.distinct()
|
||||||
.order_by('year')
|
.order_by('year')
|
||||||
)
|
)
|
||||||
|
|
||||||
km_data = []
|
km_data = []
|
||||||
dates = []
|
dates = []
|
||||||
|
|
||||||
for fuel in fuels:
|
for fuel in fuels:
|
||||||
km = fuel.km_since_previous()
|
km = fuel.km_since_previous()
|
||||||
if km:
|
if km:
|
||||||
km_data.append(km)
|
km_data.append(km)
|
||||||
dates.append(fuel.expense.date.strftime('%Y-%m-%d'))
|
dates.append(fuel.expense.date.strftime('%Y-%m-%d'))
|
||||||
|
|
||||||
return render( request, 'fuel/list.html',
|
return render( request, 'fuel/list.html',
|
||||||
{
|
{
|
||||||
'active_menu': 'fuel',
|
'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
|
@login_required
|
||||||
def category_list(request):
|
def category_list(request):
|
||||||
categories = Category.objects.filter(
|
categories = Category.objects.filter(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user