From 9ecf8279b4271ef0db970ba77a73b1d7b5aedb08 Mon Sep 17 00:00:00 2001
From: pawelaugustyn <26120235+pawelaugustyn@users.noreply.github.com>
Date: Sun, 15 Feb 2026 22:59:17 +0100
Subject: [PATCH 1/3] feat: default account for new transactions
---
app/apps/transactions/forms.py | 11 +++++++++
app/apps/users/forms.py | 24 +++++++++++++++++++
.../0024_usersettings_default_account.py | 20 ++++++++++++++++
app/apps/users/models.py | 6 +++++
4 files changed, 61 insertions(+)
create mode 100644 app/apps/users/migrations/0024_usersettings_default_account.py
diff --git a/app/apps/transactions/forms.py b/app/apps/transactions/forms.py
index f6f9b70..04fafe8 100644
--- a/app/apps/transactions/forms.py
+++ b/app/apps/transactions/forms.py
@@ -5,6 +5,7 @@ from apps.common.fields.forms.dynamic_select import (
DynamicModelChoiceField,
DynamicModelMultipleChoiceField,
)
+from apps.common.middleware.thread_local import get_current_user
from apps.common.widgets.crispy.daisyui import Switch
from apps.common.widgets.crispy.submit import NoClassSubmit
from apps.common.widgets.datepicker import AirDatePickerInput, AirMonthYearPickerInput
@@ -116,6 +117,9 @@ class TransactionForm(forms.ModelForm):
self.fields["account"].queryset = Account.objects.filter(
is_archived=False,
)
+ user_settings = get_current_user().settings
+ if user_settings.default_account:
+ self.fields["account"].initial = user_settings.default_account
self.fields["category"].queryset = TransactionCategory.objects.filter(
active=True
@@ -768,6 +772,9 @@ class InstallmentPlanForm(forms.ModelForm):
).distinct()
else:
self.fields["account"].queryset = Account.objects.filter(is_archived=False)
+ user_settings = get_current_user().settings
+ if user_settings.default_account:
+ self.fields["account"].initial = user_settings.default_account
self.fields["category"].queryset = TransactionCategory.objects.filter(
active=True
@@ -1010,6 +1017,10 @@ class RecurringTransactionForm(forms.ModelForm):
).distinct()
else:
self.fields["account"].queryset = Account.objects.filter(is_archived=False)
+
+ user_settings = get_current_user().settings
+ if user_settings.default_account:
+ self.fields["account"].initial = user_settings.default_account
self.fields["category"].queryset = TransactionCategory.objects.filter(
active=True
diff --git a/app/apps/users/forms.py b/app/apps/users/forms.py
index e48aaac..71e1b5f 100644
--- a/app/apps/users/forms.py
+++ b/app/apps/users/forms.py
@@ -1,6 +1,8 @@
from apps.common.middleware.thread_local import get_current_user
from apps.common.widgets.crispy.submit import NoClassSubmit
+from apps.common.widgets.tom_select import TomSelect
from apps.users.models import UserSettings
+from apps.accounts.models import Account
from crispy_forms.bootstrap import (
FormActions,
)
@@ -116,6 +118,15 @@ class UserSettingsForm(forms.ModelForm):
label=_("Number Format"),
)
+ default_account = forms.ModelChoiceField(
+ queryset=Account.objects.filter(
+ is_archived=False,
+ ),
+ label=_("Default Account"),
+ widget=TomSelect(clear_button=False, group_by="group"),
+ required=False,
+ )
+
class Meta:
model = UserSettings
fields = [
@@ -126,11 +137,19 @@ class UserSettingsForm(forms.ModelForm):
"datetime_format",
"number_format",
"volume",
+ "default_account",
]
+ widgets = {
+ "default_account": TomSelect(clear_button=False, group_by="group"),
+ }
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ self.fields["default_account"].queryset = Account.objects.filter(
+ is_archived=False,
+ )
+
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.form_method = "post"
@@ -141,6 +160,7 @@ class UserSettingsForm(forms.ModelForm):
"date_format",
"datetime_format",
"number_format",
+ "default_account",
HTML('
'),
"start_page",
HTML('
'),
@@ -157,6 +177,10 @@ class UserSettingsForm(forms.ModelForm):
"translation_link": 'translations.herculino.com'
}
+ self.fields["default_account"].help_text = _(
+ "Selects the account by default when creating new transactions"
+ )
+
class UserUpdateForm(forms.ModelForm):
new_password1 = forms.CharField(
diff --git a/app/apps/users/migrations/0024_usersettings_default_account.py b/app/apps/users/migrations/0024_usersettings_default_account.py
new file mode 100644
index 0000000..4fc6caa
--- /dev/null
+++ b/app/apps/users/migrations/0024_usersettings_default_account.py
@@ -0,0 +1,20 @@
+# Generated by Django 5.2.9 on 2026-02-15 21:35
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('accounts', '0016_account_untracked_by'),
+ ('users', '0023_alter_usersettings_timezone'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='usersettings',
+ name='default_account',
+ field=models.ForeignKey(blank=True, default=0, null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.account', verbose_name='Default account'),
+ ),
+ ]
diff --git a/app/apps/users/models.py b/app/apps/users/models.py
index 6f286c7..aec7919 100644
--- a/app/apps/users/models.py
+++ b/app/apps/users/models.py
@@ -510,6 +510,12 @@ class UserSettings(models.Model):
default=StartPage.MONTHLY,
verbose_name=_("Start page"),
)
+ default_account = models.ForeignKey(
+ "accounts.Account", on_delete=models.SET_NULL,
+ verbose_name=_("Default account"),
+ blank=True,
+ null=True,
+ )
def __str__(self):
return f"{self.user.email}'s settings"
From 0413921dbe7a7ed1f0809fd39ee96be222ae3781 Mon Sep 17 00:00:00 2001
From: Herculino Trotta
Date: Sun, 15 Feb 2026 23:22:10 -0300
Subject: [PATCH 2/3] fix: migrations set default as 0 instead of null
---
.../0024_usersettings_default_account.py | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/app/apps/users/migrations/0024_usersettings_default_account.py b/app/apps/users/migrations/0024_usersettings_default_account.py
index 4fc6caa..0523c80 100644
--- a/app/apps/users/migrations/0024_usersettings_default_account.py
+++ b/app/apps/users/migrations/0024_usersettings_default_account.py
@@ -5,16 +5,21 @@ from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('accounts', '0016_account_untracked_by'),
- ('users', '0023_alter_usersettings_timezone'),
+ ("accounts", "0016_account_untracked_by"),
+ ("users", "0023_alter_usersettings_timezone"),
]
operations = [
migrations.AddField(
- model_name='usersettings',
- name='default_account',
- field=models.ForeignKey(blank=True, default=0, null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.account', verbose_name='Default account'),
+ model_name="usersettings",
+ name="default_account",
+ field=models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ to="accounts.account",
+ verbose_name="Default account",
+ ),
),
]
From c787565c04ba4b263223727340da43371128a082 Mon Sep 17 00:00:00 2001
From: Herculino Trotta
Date: Sun, 15 Feb 2026 23:22:52 -0300
Subject: [PATCH 3/3] refactor: move help_text to model definition
---
app/apps/users/forms.py | 10 +++-------
...0025_alter_usersettings_default_account.py | 20 +++++++++++++++++++
app/apps/users/models.py | 4 +++-
3 files changed, 26 insertions(+), 8 deletions(-)
create mode 100644 app/apps/users/migrations/0025_alter_usersettings_default_account.py
diff --git a/app/apps/users/forms.py b/app/apps/users/forms.py
index 71e1b5f..a2b06e9 100644
--- a/app/apps/users/forms.py
+++ b/app/apps/users/forms.py
@@ -120,8 +120,8 @@ class UserSettingsForm(forms.ModelForm):
default_account = forms.ModelChoiceField(
queryset=Account.objects.filter(
- is_archived=False,
- ),
+ is_archived=False,
+ ),
label=_("Default Account"),
widget=TomSelect(clear_button=False, group_by="group"),
required=False,
@@ -160,9 +160,9 @@ class UserSettingsForm(forms.ModelForm):
"date_format",
"datetime_format",
"number_format",
- "default_account",
HTML('
'),
"start_page",
+ "default_account",
HTML('
'),
"volume",
FormActions(
@@ -177,10 +177,6 @@ class UserSettingsForm(forms.ModelForm):
"translation_link": 'translations.herculino.com'
}
- self.fields["default_account"].help_text = _(
- "Selects the account by default when creating new transactions"
- )
-
class UserUpdateForm(forms.ModelForm):
new_password1 = forms.CharField(
diff --git a/app/apps/users/migrations/0025_alter_usersettings_default_account.py b/app/apps/users/migrations/0025_alter_usersettings_default_account.py
new file mode 100644
index 0000000..d10bef2
--- /dev/null
+++ b/app/apps/users/migrations/0025_alter_usersettings_default_account.py
@@ -0,0 +1,20 @@
+# Generated by Django 5.2.9 on 2026-02-16 01:32
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('accounts', '0016_account_untracked_by'),
+ ('users', '0024_usersettings_default_account'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='usersettings',
+ name='default_account',
+ field=models.ForeignKey(blank=True, help_text='Selects the account by default when creating new transactions', null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.account', verbose_name='Default account'),
+ ),
+ ]
diff --git a/app/apps/users/models.py b/app/apps/users/models.py
index aec7919..d1e4b32 100644
--- a/app/apps/users/models.py
+++ b/app/apps/users/models.py
@@ -511,8 +511,10 @@ class UserSettings(models.Model):
verbose_name=_("Start page"),
)
default_account = models.ForeignKey(
- "accounts.Account", on_delete=models.SET_NULL,
+ "accounts.Account",
+ on_delete=models.SET_NULL,
verbose_name=_("Default account"),
+ help_text=_("Selects the account by default when creating new transactions"),
blank=True,
null=True,
)