diff --git a/expenses_manager/expenses/forms.py b/expenses_manager/expenses/forms.py index 58f86d3..fca301c 100644 --- a/expenses_manager/expenses/forms.py +++ b/expenses_manager/expenses/forms.py @@ -1,5 +1,5 @@ from django import forms -from .models import Expense, Category, Tag +from .models import Expense, Category, Tag, Account class ExpenseForm(forms.ModelForm): @@ -12,6 +12,7 @@ class ExpenseForm(forms.ModelForm): if user: self.fields['category'].queryset = Category.objects.filter(owner=user) self.fields['tags'].queryset = Tag.objects.filter(owner=user) + self.fields['account'].queryset = Account.objects(owner=user, active=True) class Meta: model = Expense @@ -31,4 +32,10 @@ class ExpenseForm(forms.ModelForm): class TagForm(forms.ModelForm): class Meta: model = Tag - fields = ['name'] \ No newline at end of file + fields = ['name'] + +class AccountForm(forms.ModelForm): + + class Meta: + model = Account + fields = ['name', 'initial_balance', 'active'] \ No newline at end of file diff --git a/expenses_manager/expenses/migrations/0002_alter_account_options_alter_category_unique_together_and_more.py b/expenses_manager/expenses/migrations/0002_alter_account_options_alter_category_unique_together_and_more.py new file mode 100644 index 0000000..5459f63 --- /dev/null +++ b/expenses_manager/expenses/migrations/0002_alter_account_options_alter_category_unique_together_and_more.py @@ -0,0 +1,65 @@ +# Generated by Django 5.2.10 on 2026-01-30 20:12 + +import django.db.models.deletion +import django.utils.timezone +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('expenses', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AlterModelOptions( + name='account', + options={'ordering': ['name']}, + ), + migrations.AlterUniqueTogether( + name='category', + unique_together=set(), + ), + migrations.AddField( + model_name='account', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='account', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='account', + name='initial_balance', + field=models.DecimalField(decimal_places=2, default=0, max_digits=12), + ), + migrations.AddField( + model_name='category', + name='owner', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='categories', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='account', + name='owner', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='accounts', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='expense', + name='account', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='expenses', to='expenses.account'), + ), + migrations.AlterField( + model_name='expense', + name='category', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='expenses', to='expenses.category'), + ), + migrations.AlterUniqueTogether( + name='category', + unique_together={('name', 'parent', 'owner')}, + ), + ] diff --git a/expenses_manager/expenses/migrations/0002_alter_category_parent.py b/expenses_manager/expenses/migrations/0002_alter_category_parent.py deleted file mode 100644 index 8256457..0000000 --- a/expenses_manager/expenses/migrations/0002_alter_category_parent.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 5.2.10 on 2026-01-09 08:42 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('expenses', '0001_initial'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.AlterField( - model_name='category', - name='parent', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/expenses_manager/expenses/migrations/0003_alter_category_unique_together_category_owner_and_more.py b/expenses_manager/expenses/migrations/0003_alter_category_unique_together_category_owner_and_more.py deleted file mode 100644 index 4d36f13..0000000 --- a/expenses_manager/expenses/migrations/0003_alter_category_unique_together_category_owner_and_more.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 5.2.10 on 2026-01-09 09:27 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('expenses', '0002_alter_category_parent'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.AlterUniqueTogether( - name='category', - unique_together=set(), - ), - migrations.AddField( - model_name='category', - name='owner', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='categories', to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='category', - name='parent', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='expenses.category'), - ), - migrations.AlterField( - model_name='expense', - name='category', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='expenses', to='expenses.category'), - ), - migrations.AlterUniqueTogether( - name='category', - unique_together={('name', 'parent', 'owner')}, - ), - ] diff --git a/expenses_manager/expenses/migrations/0004_alter_expense_category.py b/expenses_manager/expenses/migrations/0004_alter_expense_category.py deleted file mode 100644 index 21fd047..0000000 --- a/expenses_manager/expenses/migrations/0004_alter_expense_category.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.2.10 on 2026-01-09 09:50 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('expenses', '0003_alter_category_unique_together_category_owner_and_more'), - ] - - operations = [ - migrations.AlterField( - model_name='expense', - name='category', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='expenses', to='expenses.category'), - ), - ] diff --git a/expenses_manager/expenses/migrations/0005_alter_category_owner.py b/expenses_manager/expenses/migrations/0005_alter_category_owner.py deleted file mode 100644 index 33288a4..0000000 --- a/expenses_manager/expenses/migrations/0005_alter_category_owner.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 5.2.10 on 2026-01-09 10:03 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('expenses', '0004_alter_expense_category'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.AlterField( - model_name='category', - name='owner', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='categories', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/expenses_manager/expenses/models.py b/expenses_manager/expenses/models.py index 2a3abb6..e9a74f2 100644 --- a/expenses_manager/expenses/models.py +++ b/expenses_manager/expenses/models.py @@ -26,14 +26,25 @@ class Category(models.Model): return self.name -class Account(models.Model): - name = models.CharField(max_length=100) +class Account(models.Model): owner = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="accounts", ) + name = models.CharField(max_length=100) + initial_balance = models.DecimalField( + max_digits=12, + decimal_places=2, + default=0 + ) + active = models.BooleanField(default=True) + created_at = models.DateTimeField(auto_now_add=True) + + class Meta: + ordering = ['name'] + def __str__(self): return self.name @@ -72,9 +83,7 @@ class Expense(models.Model): account = models.ForeignKey( Account, - on_delete=models.SET_NULL, - null=True, - blank=True, + on_delete=models.PROTECT, related_name="expenses", ) diff --git a/expenses_manager/expenses/templates/expenses/expense_list.html b/expenses_manager/expenses/templates/expenses/expense_list.html index f55ba6c..1d4b4df 100644 --- a/expenses_manager/expenses/templates/expenses/expense_list.html +++ b/expenses_manager/expenses/templates/expenses/expense_list.html @@ -45,6 +45,17 @@ + +
{% for tag in tags_with_state %} @@ -77,6 +88,7 @@ Fecha Categoría Importe + Cuenta Etiquetas @@ -87,6 +99,7 @@ {{ expense.date }} {{ expense.category.name }} {{ expense.amount }} + {{ expense.account.name }} {% for tag in expense.tags.all %} diff --git a/expenses_manager/expenses/views.py b/expenses_manager/expenses/views.py index 51a8a42..248ca72 100644 --- a/expenses_manager/expenses/views.py +++ b/expenses_manager/expenses/views.py @@ -1,7 +1,7 @@ from datetime import date from operator import truediv from .forms import ExpenseForm, TagForm -from .models import Category, Expense, Tag +from .models import Account, Category, Expense, Tag # from dateutli.relativedelta import relativedelta from django.db.models import Sum @@ -115,6 +115,7 @@ def expense_list(request): year = _get_int(request.GET.get('year')) month = _get_int(request.GET.get('month')) category = _get_int(request.GET.get('category')) + account_id = _get_int(request.GET.get('account')) tag_ids = request.GET.getlist('tag') tag_ids = [int(t) for t in tag_ids] @@ -131,6 +132,9 @@ def expense_list(request): if tag_ids: expenses = expenses.filter(tags__id__in=tag_ids).distinct() + if account_id: + expenses = expense.filter(account_id=account_id) + selected_tags = tag_ids or [] expenses = expenses.order_by('-date') @@ -190,6 +194,8 @@ def expense_list(request): 'selected_tags': selected_tags, 'tags': Tag.objects.filter(owner=request.user), 'tags_with_state': tags_with_state, + 'accounts': Account.object.filter(owner=request.user), + 'selected_account': account_id, }, ) @@ -549,3 +555,36 @@ def tag_delete(request, pk): 'expenses/tag_confirm_delete.html', {'tag': tag} ) + + +@login_required +def account_list(request): + accounts = Account.objects.filter(owner=request.user) + return render( + request, + 'expenses/account_list.html', + {'account': accounts} + ) + + +@login_required +def account_create(request): + if request.method == 'POST': + form = AccountForm(request.POST) + if form.is_valid(): + account = form.save(commit=False) + account.owner = request.user + account.save() + return redirect('account_list') + else: + form = AccountForm() + + return render( + request, + 'expenses/account_form.html', + {'form': form} + ) + + + +