diff --git a/app/apps/common/models.py b/app/apps/common/models.py
index 7d33dc5..d446921 100644
--- a/app/apps/common/models.py
+++ b/app/apps/common/models.py
@@ -65,6 +65,18 @@ class SharedObject(models.Model):
super().save(*args, **kwargs)
+class OwnedObjectManager(models.Manager):
+ def get_queryset(self):
+ """Return only objects the user can access"""
+ user = get_current_user()
+ base_qs = super().get_queryset()
+
+ if user and user.is_authenticated:
+ return base_qs.filter(Q(owner=user) | Q(owner=None)).distinct()
+
+ return base_qs
+
+
class OwnedObject(models.Model):
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
diff --git a/app/apps/transactions/forms.py b/app/apps/transactions/forms.py
index 456cd3a..5299901 100644
--- a/app/apps/transactions/forms.py
+++ b/app/apps/transactions/forms.py
@@ -7,6 +7,7 @@ from crispy_forms.layout import (
Column,
Field,
Div,
+ HTML,
)
from django import forms
from django.db.models import Q
@@ -29,8 +30,8 @@ from apps.transactions.models import (
InstallmentPlan,
RecurringTransaction,
TransactionEntity,
+ QuickTransaction,
)
-from apps.common.middleware.thread_local import get_current_user
class TransactionForm(forms.ModelForm):
@@ -247,6 +248,140 @@ class TransactionForm(forms.ModelForm):
return instance
+class QuickTransactionForm(forms.ModelForm):
+ category = DynamicModelChoiceField(
+ create_field="name",
+ model=TransactionCategory,
+ required=False,
+ label=_("Category"),
+ queryset=TransactionCategory.objects.filter(active=True),
+ )
+ tags = DynamicModelMultipleChoiceField(
+ model=TransactionTag,
+ to_field_name="name",
+ create_field="name",
+ required=False,
+ label=_("Tags"),
+ queryset=TransactionTag.objects.filter(active=True),
+ )
+ entities = DynamicModelMultipleChoiceField(
+ model=TransactionEntity,
+ to_field_name="name",
+ create_field="name",
+ required=False,
+ label=_("Entities"),
+ )
+ account = forms.ModelChoiceField(
+ queryset=Account.objects.filter(is_archived=False),
+ label=_("Account"),
+ widget=TomSelect(clear_button=False, group_by="group"),
+ )
+
+ class Meta:
+ model = QuickTransaction
+ fields = [
+ "name",
+ "account",
+ "type",
+ "is_paid",
+ "amount",
+ "description",
+ "notes",
+ "category",
+ "tags",
+ "entities",
+ ]
+ widgets = {
+ "notes": forms.Textarea(attrs={"rows": 3}),
+ "account": TomSelect(clear_button=False, group_by="group"),
+ }
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ # if editing a transaction display non-archived items and it's own item even if it's archived
+ if self.instance.id:
+ self.fields["account"].queryset = Account.objects.filter(
+ Q(is_archived=False) | Q(transactions=self.instance.id),
+ )
+
+ self.fields["category"].queryset = TransactionCategory.objects.filter(
+ Q(active=True) | Q(transaction=self.instance.id)
+ )
+
+ self.fields["tags"].queryset = TransactionTag.objects.filter(
+ Q(active=True) | Q(transaction=self.instance.id)
+ )
+
+ self.fields["entities"].queryset = TransactionEntity.objects.filter(
+ Q(active=True) | Q(transactions=self.instance.id)
+ )
+ else:
+ self.fields["account"].queryset = Account.objects.filter(
+ is_archived=False,
+ )
+
+ self.fields["category"].queryset = TransactionCategory.objects.filter(
+ active=True
+ )
+ self.fields["tags"].queryset = TransactionTag.objects.filter(active=True)
+ self.fields["entities"].queryset = TransactionEntity.objects.all()
+
+ self.helper = FormHelper()
+ self.helper.form_tag = False
+ self.helper.form_method = "post"
+ self.helper.layout = Layout(
+ Field(
+ "type",
+ template="transactions/widgets/income_expense_toggle_buttons.html",
+ ),
+ Field("is_paid", template="transactions/widgets/paid_toggle_button.html"),
+ "name",
+ HTML("
"),
+ Row(
+ Column("account", css_class="form-group col-md-6 mb-0"),
+ Column("entities", css_class="form-group col-md-6 mb-0"),
+ css_class="form-row",
+ ),
+ Row(
+ Column(Field("date"), css_class="form-group col-md-6 mb-0"),
+ Column(Field("reference_date"), css_class="form-group col-md-6 mb-0"),
+ css_class="form-row",
+ ),
+ "description",
+ Field("amount", inputmode="decimal"),
+ Row(
+ Column("category", css_class="form-group col-md-6 mb-0"),
+ Column("tags", css_class="form-group col-md-6 mb-0"),
+ css_class="form-row",
+ ),
+ "notes",
+ )
+
+ if self.instance and self.instance.pk:
+ decimal_places = self.instance.account.currency.decimal_places
+ self.fields["amount"].widget = ArbitraryDecimalDisplayNumberInput(
+ decimal_places=decimal_places
+ )
+ self.helper.layout.append(
+ FormActions(
+ NoClassSubmit(
+ "submit", _("Update"), css_class="btn btn-outline-primary w-100"
+ ),
+ ),
+ )
+ else:
+ self.fields["amount"].widget = ArbitraryDecimalDisplayNumberInput()
+ self.helper.layout.append(
+ Div(
+ NoClassSubmit(
+ "submit", _("Add"), css_class="btn btn-outline-primary"
+ ),
+ css_class="d-grid gap-2",
+ ),
+ )
+
+
class BulkEditTransactionForm(TransactionForm):
is_paid = forms.NullBooleanField(required=False)
diff --git a/app/apps/transactions/migrations/0043_quicktransaction.py b/app/apps/transactions/migrations/0043_quicktransaction.py
new file mode 100644
index 0000000..275d854
--- /dev/null
+++ b/app/apps/transactions/migrations/0043_quicktransaction.py
@@ -0,0 +1,45 @@
+# Generated by Django 5.1.11 on 2025-06-20 03:57
+
+import apps.transactions.validators
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('accounts', '0014_alter_account_options_alter_accountgroup_options'),
+ ('transactions', '0042_alter_transactioncategory_options_and_more'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='QuickTransaction',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=100, verbose_name='Name')),
+ ('type', models.CharField(choices=[('IN', 'Income'), ('EX', 'Expense')], default='EX', max_length=2, verbose_name='Type')),
+ ('is_paid', models.BooleanField(default=True, verbose_name='Paid')),
+ ('amount', models.DecimalField(decimal_places=30, max_digits=42, validators=[apps.transactions.validators.validate_non_negative, apps.transactions.validators.validate_decimal_places], verbose_name='Amount')),
+ ('description', models.CharField(blank=True, max_length=500, verbose_name='Description')),
+ ('notes', models.TextField(blank=True, verbose_name='Notes')),
+ ('internal_note', models.TextField(blank=True, verbose_name='Internal Note')),
+ ('internal_id', models.TextField(blank=True, null=True, unique=True, verbose_name='Internal ID')),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('updated_at', models.DateTimeField(auto_now=True)),
+ ('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='quick_transactions', to='accounts.account', verbose_name='Account')),
+ ('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='transactions.transactioncategory', verbose_name='Category')),
+ ('entities', models.ManyToManyField(blank=True, related_name='quick_transactions', to='transactions.transactionentity', verbose_name='Entities')),
+ ('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_owned', to=settings.AUTH_USER_MODEL)),
+ ('tags', models.ManyToManyField(blank=True, to='transactions.transactiontag', verbose_name='Tags')),
+ ],
+ options={
+ 'verbose_name': 'Quick Transaction',
+ 'verbose_name_plural': 'Quick Transactions',
+ 'db_table': 'quick_transactions',
+ 'default_manager_name': 'objects',
+ },
+ ),
+ ]
diff --git a/app/apps/transactions/migrations/0044_alter_quicktransaction_unique_together.py b/app/apps/transactions/migrations/0044_alter_quicktransaction_unique_together.py
new file mode 100644
index 0000000..fa07fb1
--- /dev/null
+++ b/app/apps/transactions/migrations/0044_alter_quicktransaction_unique_together.py
@@ -0,0 +1,19 @@
+# Generated by Django 5.1.11 on 2025-06-20 04:02
+
+from django.conf import settings
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('transactions', '0043_quicktransaction'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.AlterUniqueTogether(
+ name='quicktransaction',
+ unique_together={('name', 'owner')},
+ ),
+ ]
diff --git a/app/apps/transactions/models.py b/app/apps/transactions/models.py
index 6fd6d36..82cfe90 100644
--- a/app/apps/transactions/models.py
+++ b/app/apps/transactions/models.py
@@ -16,7 +16,12 @@ from apps.common.templatetags.decimal import localize_number, drop_trailing_zero
from apps.currencies.utils.convert import convert
from apps.transactions.validators import validate_decimal_places, validate_non_negative
from apps.common.middleware.thread_local import get_current_user
-from apps.common.models import SharedObject, SharedObjectManager, OwnedObject
+from apps.common.models import (
+ SharedObject,
+ SharedObjectManager,
+ OwnedObject,
+ OwnedObjectManager,
+)
logger = logging.getLogger()
@@ -886,3 +891,86 @@ class RecurringTransaction(models.Model):
"""
today = timezone.localdate(timezone.now())
self.transactions.filter(is_paid=False, date__gt=today).delete()
+
+
+class QuickTransaction(OwnedObject):
+ class Type(models.TextChoices):
+ INCOME = "IN", _("Income")
+ EXPENSE = "EX", _("Expense")
+
+ name = models.CharField(
+ max_length=100,
+ null=False,
+ blank=False,
+ verbose_name=_("Name"),
+ )
+
+ account = models.ForeignKey(
+ "accounts.Account",
+ on_delete=models.CASCADE,
+ verbose_name=_("Account"),
+ related_name="quick_transactions",
+ )
+ type = models.CharField(
+ max_length=2,
+ choices=Type,
+ default=Type.EXPENSE,
+ verbose_name=_("Type"),
+ )
+ is_paid = models.BooleanField(default=True, verbose_name=_("Paid"))
+
+ amount = models.DecimalField(
+ max_digits=42,
+ decimal_places=30,
+ verbose_name=_("Amount"),
+ validators=[validate_non_negative, validate_decimal_places],
+ )
+
+ description = models.CharField(
+ max_length=500, verbose_name=_("Description"), blank=True
+ )
+ notes = models.TextField(blank=True, verbose_name=_("Notes"))
+ category = models.ForeignKey(
+ TransactionCategory,
+ on_delete=models.SET_NULL,
+ verbose_name=_("Category"),
+ blank=True,
+ null=True,
+ )
+ tags = models.ManyToManyField(
+ TransactionTag,
+ verbose_name=_("Tags"),
+ blank=True,
+ )
+ entities = models.ManyToManyField(
+ TransactionEntity,
+ verbose_name=_("Entities"),
+ blank=True,
+ related_name="quick_transactions",
+ )
+
+ internal_note = models.TextField(blank=True, verbose_name=_("Internal Note"))
+ internal_id = models.TextField(
+ blank=True, null=True, unique=True, verbose_name=_("Internal ID")
+ )
+
+ created_at = models.DateTimeField(auto_now_add=True)
+ updated_at = models.DateTimeField(auto_now=True)
+
+ objects = OwnedObjectManager()
+ all_objects = models.Manager() # Unfiltered manager
+
+ class Meta:
+ verbose_name = _("Quick Transaction")
+ verbose_name_plural = _("Quick Transactions")
+ unique_together = ("name", "owner")
+ db_table = "quick_transactions"
+ default_manager_name = "objects"
+
+ def save(self, *args, **kwargs):
+ self.amount = truncate_decimal(
+ value=self.amount, decimal_places=self.account.currency.decimal_places
+ )
+
+ self.full_clean()
+ super().save(*args, **kwargs)
diff --git a/app/apps/transactions/urls.py b/app/apps/transactions/urls.py
index d1a8fac..b808872 100644
--- a/app/apps/transactions/urls.py
+++ b/app/apps/transactions/urls.py
@@ -307,4 +307,39 @@ urlpatterns = [
views.recurring_transaction_finish,
name="recurring_transaction_finish",
),
+ path(
+ "quick-transactions/",
+ views.quick_transactions_index,
+ name="quick_transactions_index",
+ ),
+ path(
+ "quick-transactions/list/",
+ views.quick_transactions_list,
+ name="quick_transactions_list",
+ ),
+ path(
+ "quick-transactions/add/",
+ views.quick_transaction_add,
+ name="quick_transaction_add",
+ ),
+ path(
+ "quick-transactions//edit/",
+ views.quick_transaction_edit,
+ name="quick_transaction_edit",
+ ),
+ path(
+ "quick-transactions//delete/",
+ views.quick_transaction_delete,
+ name="quick_transaction_delete",
+ ),
+ path(
+ "quick-transactions/create-menu/",
+ views.quick_transactions_create_menu,
+ name="quick_transactions_create_menu",
+ ),
+ path(
+ "quick-transactions//create/",
+ views.quick_transaction_add_as_transaction,
+ name="quick_transaction_add_as_transaction",
+ ),
]
diff --git a/app/apps/transactions/views/__init__.py b/app/apps/transactions/views/__init__.py
index fa20bc8..b784666 100644
--- a/app/apps/transactions/views/__init__.py
+++ b/app/apps/transactions/views/__init__.py
@@ -5,3 +5,4 @@ from .categories import *
from .actions import *
from .installment_plans import *
from .recurring_transactions import *
+from .quick_transactions import *
diff --git a/app/apps/transactions/views/quick_transactions.py b/app/apps/transactions/views/quick_transactions.py
new file mode 100644
index 0000000..26deec7
--- /dev/null
+++ b/app/apps/transactions/views/quick_transactions.py
@@ -0,0 +1,152 @@
+from django.contrib import messages
+from django.contrib.auth.decorators import login_required
+from django.forms import model_to_dict
+from django.http import HttpResponse
+from django.shortcuts import render, get_object_or_404
+from django.utils import timezone
+from django.utils.translation import gettext_lazy as _
+from django.views.decorators.http import require_http_methods
+
+from apps.common.decorators.htmx import only_htmx
+from apps.transactions.forms import QuickTransactionForm
+from apps.transactions.models import QuickTransaction
+from apps.transactions.models import Transaction
+
+
+@login_required
+@require_http_methods(["GET"])
+def quick_transactions_index(request):
+ return render(
+ request,
+ "quick_transactions/pages/index.html",
+ )
+
+
+@only_htmx
+@login_required
+@require_http_methods(["GET"])
+def quick_transactions_list(request):
+ quick_transactions = QuickTransaction.objects.all().order_by("name")
+ return render(
+ request,
+ "quick_transactions/fragments/list.html",
+ context={"quick_transactions": quick_transactions},
+ )
+
+
+@only_htmx
+@login_required
+@require_http_methods(["GET", "POST"])
+def quick_transaction_add(request):
+ if request.method == "POST":
+ form = QuickTransactionForm(request.POST)
+ if form.is_valid():
+ form.save()
+ messages.success(request, _("Item added successfully"))
+
+ return HttpResponse(
+ status=204,
+ headers={
+ "HX-Trigger": "updated, hide_offcanvas",
+ },
+ )
+ else:
+ form = QuickTransactionForm()
+
+ return render(
+ request,
+ "quick_transactions/fragments/add.html",
+ {"form": form},
+ )
+
+
+@only_htmx
+@login_required
+@require_http_methods(["GET", "POST"])
+def quick_transaction_edit(request, quick_transaction_id):
+ quick_transaction = get_object_or_404(QuickTransaction, id=quick_transaction_id)
+
+ if request.method == "POST":
+ form = QuickTransactionForm(request.POST, instance=quick_transaction)
+ if form.is_valid():
+ form.save()
+ messages.success(request, _("Item updated successfully"))
+
+ return HttpResponse(
+ status=204,
+ headers={
+ "HX-Trigger": "updated, hide_offcanvas",
+ },
+ )
+ else:
+ form = QuickTransactionForm(instance=quick_transaction)
+
+ return render(
+ request,
+ "quick_transactions/fragments/edit.html",
+ {"form": form, "quick_transaction": quick_transaction},
+ )
+
+
+@only_htmx
+@login_required
+@require_http_methods(["DELETE"])
+def quick_transaction_delete(request, quick_transaction_id):
+ quick_transaction = get_object_or_404(QuickTransaction, id=quick_transaction_id)
+
+ quick_transaction.delete()
+
+ messages.success(request, _("Item deleted successfully"))
+
+ return HttpResponse(
+ status=204,
+ headers={
+ "HX-Trigger": "updated, hide_offcanvas",
+ },
+ )
+
+
+@only_htmx
+@login_required
+@require_http_methods(["GET"])
+def quick_transactions_create_menu(request):
+ quick_transactions = QuickTransaction.objects.all().order_by("name")
+ return render(
+ request,
+ "quick_transactions/fragments/create_menu.html",
+ context={"quick_transactions": quick_transactions},
+ )
+
+
+@only_htmx
+@login_required
+@require_http_methods(["GET"])
+def quick_transaction_add_as_transaction(request, quick_transaction_id):
+ quick_transaction: QuickTransaction = get_object_or_404(
+ QuickTransaction, id=quick_transaction_id
+ )
+ today = timezone.localdate(timezone.now())
+
+ quick_transaction_data = model_to_dict(
+ quick_transaction,
+ exclude=["id", "name", "owner", "account", "category", "tags", "entities"],
+ )
+
+ new_transaction = Transaction(**quick_transaction_data)
+ new_transaction.account = quick_transaction.account
+ new_transaction.category = quick_transaction.category
+
+ new_transaction.date = today
+ new_transaction.reference_date = today.replace(day=1)
+ new_transaction.save()
+ new_transaction.tags.set(quick_transaction.tags.all())
+ new_transaction.entities.set(quick_transaction.entities.all())
+
+ messages.success(request, _("Transaction added successfully"))
+
+ return HttpResponse(
+ status=204,
+ headers={
+ "HX-Trigger": "updated, hide_offcanvas",
+ },
+ )
diff --git a/app/apps/users/migrations/0021_alter_usersettings_timezone.py b/app/apps/users/migrations/0021_alter_usersettings_timezone.py
index 7a764d9..d8c1dc2 100644
--- a/app/apps/users/migrations/0021_alter_usersettings_timezone.py
+++ b/app/apps/users/migrations/0021_alter_usersettings_timezone.py
@@ -1,4 +1,5 @@
-# Generated by Django 5.1.11 on 2025-06-16 02:28
+# Generated by Django 5.1.11 on 2025-06-20 03:57
+
from django.db import migrations, models
diff --git a/app/locale/de/LC_MESSAGES/django.po b/app/locale/de/LC_MESSAGES/django.po
index fef1cf8..42ad18d 100644
--- a/app/locale/de/LC_MESSAGES/django.po
+++ b/app/locale/de/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-05-11 15:47+0000\n"
+"POT-Creation-Date: 2025-06-20 05:02+0000\n"
"PO-Revision-Date: 2025-05-23 17:16+0000\n"
"Last-Translator: JHoh \n"
"Language-Team: German \n"
"Language-Team: LANGUAGE \n"
@@ -26,11 +26,12 @@ msgstr ""
#: apps/currencies/forms.py:53 apps/currencies/forms.py:91
#: apps/currencies/forms.py:142 apps/dca/forms.py:49 apps/dca/forms.py:224
#: apps/import_app/forms.py:34 apps/rules/forms.py:51 apps/rules/forms.py:93
-#: apps/rules/forms.py:365 apps/transactions/forms.py:203
-#: apps/transactions/forms.py:281 apps/transactions/forms.py:641
-#: apps/transactions/forms.py:684 apps/transactions/forms.py:716
-#: apps/transactions/forms.py:751 apps/transactions/forms.py:903
-#: apps/users/forms.py:210 apps/users/forms.py:372
+#: apps/rules/forms.py:365 apps/transactions/forms.py:204
+#: apps/transactions/forms.py:369 apps/transactions/forms.py:416
+#: apps/transactions/forms.py:776 apps/transactions/forms.py:819
+#: apps/transactions/forms.py:851 apps/transactions/forms.py:886
+#: apps/transactions/forms.py:1038 apps/users/forms.py:210
+#: apps/users/forms.py:372
msgid "Update"
msgstr ""
@@ -39,11 +40,12 @@ msgstr ""
#: apps/currencies/forms.py:99 apps/currencies/forms.py:150
#: apps/dca/forms.py:57 apps/dca/forms.py:232 apps/import_app/forms.py:42
#: apps/rules/forms.py:59 apps/rules/forms.py:101 apps/rules/forms.py:373
-#: apps/transactions/forms.py:188 apps/transactions/forms.py:212
-#: apps/transactions/forms.py:649 apps/transactions/forms.py:692
-#: apps/transactions/forms.py:724 apps/transactions/forms.py:759
-#: apps/transactions/forms.py:911 apps/users/forms.py:218
-#: apps/users/forms.py:380 templates/account_groups/fragments/list.html:9
+#: apps/transactions/forms.py:189 apps/transactions/forms.py:213
+#: apps/transactions/forms.py:378 apps/transactions/forms.py:784
+#: apps/transactions/forms.py:827 apps/transactions/forms.py:859
+#: apps/transactions/forms.py:894 apps/transactions/forms.py:1046
+#: apps/users/forms.py:218 apps/users/forms.py:380
+#: templates/account_groups/fragments/list.html:9
#: templates/accounts/fragments/list.html:9
#: templates/categories/fragments/list.html:9
#: templates/currencies/fragments/list.html:9
@@ -56,6 +58,7 @@ msgstr ""
#: templates/import_app/fragments/profiles/list.html:10
#: templates/installment_plans/fragments/list.html:9
#: templates/mini_tools/unit_price_calculator.html:162
+#: templates/quick_transactions/pages/index.html:15
#: templates/recurring_transactions/fragments/list.html:9
#: templates/rules/fragments/list.html:9 templates/tags/fragments/list.html:9
#: templates/users/fragments/list.html:10
@@ -73,10 +76,11 @@ msgstr ""
#: apps/accounts/forms.py:121 apps/dca/forms.py:85 apps/dca/forms.py:92
#: apps/insights/forms.py:118 apps/rules/forms.py:174 apps/rules/forms.py:189
#: apps/rules/models.py:38 apps/rules/models.py:286
-#: apps/transactions/forms.py:41 apps/transactions/forms.py:315
-#: apps/transactions/forms.py:322 apps/transactions/forms.py:522
-#: apps/transactions/forms.py:783 apps/transactions/models.py:312
-#: apps/transactions/models.py:495 apps/transactions/models.py:695
+#: apps/transactions/forms.py:42 apps/transactions/forms.py:256
+#: apps/transactions/forms.py:450 apps/transactions/forms.py:457
+#: apps/transactions/forms.py:657 apps/transactions/forms.py:918
+#: apps/transactions/models.py:317 apps/transactions/models.py:500
+#: apps/transactions/models.py:700 apps/transactions/models.py:936
#: templates/insights/fragments/category_overview/index.html:63
#: templates/insights/fragments/category_overview/index.html:420
msgid "Category"
@@ -86,11 +90,12 @@ msgstr ""
#: apps/export_app/forms.py:44 apps/export_app/forms.py:135
#: apps/rules/forms.py:177 apps/rules/forms.py:186 apps/rules/models.py:39
#: apps/rules/models.py:290 apps/transactions/filters.py:74
-#: apps/transactions/forms.py:49 apps/transactions/forms.py:331
-#: apps/transactions/forms.py:339 apps/transactions/forms.py:515
-#: apps/transactions/forms.py:776 apps/transactions/models.py:318
-#: apps/transactions/models.py:497 apps/transactions/models.py:699
-#: templates/includes/navbar.html:108
+#: apps/transactions/forms.py:50 apps/transactions/forms.py:264
+#: apps/transactions/forms.py:466 apps/transactions/forms.py:474
+#: apps/transactions/forms.py:650 apps/transactions/forms.py:911
+#: apps/transactions/models.py:323 apps/transactions/models.py:502
+#: apps/transactions/models.py:704 apps/transactions/models.py:942
+#: templates/includes/navbar.html:110
#: templates/insights/fragments/category_overview/index.html:35
#: templates/tags/fragments/list.html:5 templates/tags/pages/index.html:4
msgid "Tags"
@@ -98,8 +103,8 @@ msgstr ""
#: apps/accounts/models.py:12 apps/accounts/models.py:29 apps/dca/models.py:13
#: apps/import_app/models.py:14 apps/rules/models.py:13
-#: apps/transactions/models.py:205 apps/transactions/models.py:230
-#: apps/transactions/models.py:254
+#: apps/transactions/models.py:210 apps/transactions/models.py:235
+#: apps/transactions/models.py:259 apps/transactions/models.py:905
#: templates/account_groups/fragments/list.html:25
#: templates/accounts/fragments/list.html:25
#: templates/categories/fragments/table.html:16
@@ -108,6 +113,7 @@ msgstr ""
#: templates/exchange_rates_services/fragments/list.html:32
#: templates/import_app/fragments/profiles/list.html:36
#: templates/installment_plans/fragments/table.html:16
+#: templates/quick_transactions/fragments/list.html:13
#: templates/recurring_transactions/fragments/table.html:18
#: templates/rules/fragments/list.html:26
#: templates/tags/fragments/table.html:16
@@ -121,7 +127,7 @@ msgstr ""
#: apps/accounts/models.py:19 templates/account_groups/fragments/list.html:5
#: templates/account_groups/pages/index.html:4
-#: templates/includes/navbar.html:118
+#: templates/includes/navbar.html:120
msgid "Account Groups"
msgstr ""
@@ -161,17 +167,18 @@ msgstr ""
#: apps/accounts/models.py:70 apps/rules/forms.py:166 apps/rules/forms.py:179
#: apps/rules/models.py:30 apps/rules/models.py:242
-#: apps/transactions/forms.py:61 apps/transactions/forms.py:507
-#: apps/transactions/forms.py:768 apps/transactions/models.py:285
-#: apps/transactions/models.py:455 apps/transactions/models.py:677
+#: apps/transactions/forms.py:62 apps/transactions/forms.py:276
+#: apps/transactions/forms.py:642 apps/transactions/forms.py:903
+#: apps/transactions/models.py:290 apps/transactions/models.py:460
+#: apps/transactions/models.py:682 apps/transactions/models.py:911
msgid "Account"
msgstr ""
#: apps/accounts/models.py:71 apps/export_app/forms.py:20
#: apps/export_app/forms.py:132 apps/transactions/filters.py:53
#: templates/accounts/fragments/list.html:5
-#: templates/accounts/pages/index.html:4 templates/includes/navbar.html:114
-#: templates/includes/navbar.html:116
+#: templates/accounts/pages/index.html:4 templates/includes/navbar.html:116
+#: templates/includes/navbar.html:118
#: templates/monthly_overview/pages/overview.html:94
#: templates/transactions/fragments/summary.html:12
#: templates/transactions/pages/transactions.html:72
@@ -454,8 +461,8 @@ msgstr ""
#: apps/currencies/forms.py:69 apps/dca/models.py:158 apps/rules/forms.py:169
#: apps/rules/forms.py:182 apps/rules/models.py:33 apps/rules/models.py:254
-#: apps/transactions/forms.py:65 apps/transactions/forms.py:343
-#: apps/transactions/models.py:295
+#: apps/transactions/forms.py:66 apps/transactions/forms.py:478
+#: apps/transactions/models.py:300
#: templates/dca/fragments/strategy/details.html:52
#: templates/exchange_rates/fragments/table.html:10
#: templates/exchange_rates_services/fragments/table.html:10
@@ -477,8 +484,8 @@ msgstr ""
#: apps/currencies/models.py:40 apps/export_app/forms.py:26
#: apps/export_app/forms.py:133 apps/transactions/filters.py:60
#: templates/currencies/fragments/list.html:5
-#: templates/currencies/pages/index.html:4 templates/includes/navbar.html:122
-#: templates/includes/navbar.html:124
+#: templates/currencies/pages/index.html:4 templates/includes/navbar.html:124
+#: templates/includes/navbar.html:126
#: templates/monthly_overview/pages/overview.html:81
#: templates/transactions/fragments/summary.html:8
#: templates/transactions/pages/transactions.html:59
@@ -508,7 +515,7 @@ msgstr ""
#: apps/currencies/models.py:75 apps/export_app/forms.py:68
#: apps/export_app/forms.py:145 templates/exchange_rates/fragments/list.html:6
#: templates/exchange_rates/pages/index.html:4
-#: templates/includes/navbar.html:126
+#: templates/includes/navbar.html:128
msgid "Exchange Rates"
msgstr ""
@@ -536,8 +543,8 @@ msgstr ""
msgid "Service Type"
msgstr ""
-#: apps/currencies/models.py:110 apps/transactions/models.py:209
-#: apps/transactions/models.py:233 apps/transactions/models.py:257
+#: apps/currencies/models.py:110 apps/transactions/models.py:214
+#: apps/transactions/models.py:238 apps/transactions/models.py:262
#: templates/categories/fragments/list.html:21
#: templates/entities/fragments/list.html:21
#: templates/recurring_transactions/fragments/list.html:21
@@ -657,11 +664,11 @@ msgstr ""
msgid "Create transaction"
msgstr ""
-#: apps/dca/forms.py:70 apps/transactions/forms.py:290
+#: apps/dca/forms.py:70 apps/transactions/forms.py:425
msgid "From Account"
msgstr ""
-#: apps/dca/forms.py:76 apps/transactions/forms.py:295
+#: apps/dca/forms.py:76 apps/transactions/forms.py:430
msgid "To Account"
msgstr ""
@@ -686,7 +693,7 @@ msgstr ""
msgid "You must provide an account."
msgstr ""
-#: apps/dca/forms.py:312 apps/transactions/forms.py:457
+#: apps/dca/forms.py:312 apps/transactions/forms.py:592
msgid "From and To accounts must be different."
msgstr ""
@@ -705,8 +712,9 @@ msgstr ""
#: apps/dca/models.py:26 apps/dca/models.py:181 apps/rules/forms.py:173
#: apps/rules/forms.py:188 apps/rules/models.py:37 apps/rules/models.py:270
-#: apps/transactions/forms.py:359 apps/transactions/models.py:308
-#: apps/transactions/models.py:504 apps/transactions/models.py:705
+#: apps/transactions/forms.py:494 apps/transactions/models.py:313
+#: apps/transactions/models.py:509 apps/transactions/models.py:710
+#: apps/transactions/models.py:932
msgid "Notes"
msgstr ""
@@ -763,14 +771,14 @@ msgid "Entry deleted successfully"
msgstr ""
#: apps/export_app/forms.py:14 apps/export_app/forms.py:131
-#: templates/includes/navbar.html:147 templates/users/fragments/list.html:6
+#: templates/includes/navbar.html:149 templates/users/fragments/list.html:6
#: templates/users/pages/index.html:4
msgid "Users"
msgstr ""
#: apps/export_app/forms.py:32 apps/export_app/forms.py:137
-#: apps/transactions/models.py:369 templates/includes/navbar.html:57
-#: templates/includes/navbar.html:104
+#: apps/transactions/models.py:374 templates/includes/navbar.html:57
+#: templates/includes/navbar.html:106
#: templates/recurring_transactions/fragments/list_transactions.html:5
#: templates/recurring_transactions/fragments/table.html:37
#: templates/transactions/pages/transactions.html:5
@@ -779,30 +787,31 @@ msgstr ""
#: apps/export_app/forms.py:38 apps/export_app/forms.py:134
#: apps/transactions/filters.py:67 templates/categories/fragments/list.html:5
-#: templates/categories/pages/index.html:4 templates/includes/navbar.html:106
+#: templates/categories/pages/index.html:4 templates/includes/navbar.html:108
msgid "Categories"
msgstr ""
#: apps/export_app/forms.py:50 apps/export_app/forms.py:136
#: apps/rules/forms.py:178 apps/rules/forms.py:187 apps/rules/models.py:40
#: apps/rules/models.py:282 apps/transactions/filters.py:81
-#: apps/transactions/forms.py:57 apps/transactions/forms.py:530
-#: apps/transactions/forms.py:791 apps/transactions/models.py:268
-#: apps/transactions/models.py:323 apps/transactions/models.py:500
-#: apps/transactions/models.py:702 templates/entities/fragments/list.html:5
-#: templates/entities/pages/index.html:4 templates/includes/navbar.html:110
+#: apps/transactions/forms.py:58 apps/transactions/forms.py:272
+#: apps/transactions/forms.py:665 apps/transactions/forms.py:926
+#: apps/transactions/models.py:273 apps/transactions/models.py:328
+#: apps/transactions/models.py:505 apps/transactions/models.py:707
+#: apps/transactions/models.py:947 templates/entities/fragments/list.html:5
+#: templates/entities/pages/index.html:4 templates/includes/navbar.html:112
msgid "Entities"
msgstr ""
#: apps/export_app/forms.py:56 apps/export_app/forms.py:140
-#: apps/transactions/models.py:739 templates/includes/navbar.html:74
+#: apps/transactions/models.py:744 templates/includes/navbar.html:76
#: templates/recurring_transactions/fragments/list.html:5
#: templates/recurring_transactions/pages/index.html:4
msgid "Recurring Transactions"
msgstr ""
#: apps/export_app/forms.py:62 apps/export_app/forms.py:138
-#: apps/transactions/models.py:518 templates/includes/navbar.html:72
+#: apps/transactions/models.py:523 templates/includes/navbar.html:74
#: templates/installment_plans/fragments/list.html:5
#: templates/installment_plans/pages/index.html:4
msgid "Installment Plans"
@@ -811,16 +820,16 @@ msgstr ""
#: apps/export_app/forms.py:74 apps/export_app/forms.py:143
#: templates/exchange_rates_services/fragments/list.html:6
#: templates/exchange_rates_services/pages/index.html:4
-#: templates/includes/navbar.html:140
+#: templates/includes/navbar.html:142
msgid "Automatic Exchange Rates"
msgstr ""
-#: apps/export_app/forms.py:80 templates/includes/navbar.html:132
+#: apps/export_app/forms.py:80 templates/includes/navbar.html:134
#: templates/rules/fragments/list.html:5 templates/rules/pages/index.html:4
msgid "Rules"
msgstr ""
-#: apps/export_app/forms.py:86 templates/cotton/transaction/item.html:56
+#: apps/export_app/forms.py:86 templates/cotton/transaction/item.html:57
msgid "DCA"
msgstr ""
@@ -855,7 +864,7 @@ msgstr ""
msgid "Update or create transaction actions"
msgstr ""
-#: apps/export_app/forms.py:185 templates/cotton/transaction/item.html:158
+#: apps/export_app/forms.py:185 templates/cotton/transaction/item.html:159
#: templates/cotton/ui/deleted_transactions_action_bar.html:47
#: templates/export_app/fragments/restore.html:5
#: templates/export_app/pages/index.html:24
@@ -885,7 +894,7 @@ msgstr ""
#: apps/import_app/forms.py:61
#: templates/import_app/fragments/profiles/list.html:62
-#: templates/includes/navbar.html:134
+#: templates/includes/navbar.html:136
msgid "Import"
msgstr ""
@@ -1039,48 +1048,52 @@ msgid "Operator"
msgstr ""
#: apps/rules/forms.py:167 apps/rules/forms.py:180 apps/rules/models.py:31
-#: apps/rules/models.py:246 apps/transactions/models.py:292
-#: apps/transactions/models.py:460 apps/transactions/models.py:683
+#: apps/rules/models.py:246 apps/transactions/models.py:297
+#: apps/transactions/models.py:465 apps/transactions/models.py:688
+#: apps/transactions/models.py:918
msgid "Type"
msgstr ""
#: apps/rules/forms.py:168 apps/rules/forms.py:181 apps/rules/models.py:32
#: apps/rules/models.py:250 apps/transactions/filters.py:23
-#: apps/transactions/models.py:294 templates/cotton/transaction/item.html:21
-#: templates/cotton/transaction/item.html:31
+#: apps/transactions/models.py:299 apps/transactions/models.py:920
+#: templates/cotton/transaction/item.html:22
+#: templates/cotton/transaction/item.html:32
#: templates/transactions/widgets/paid_toggle_button.html:12
#: templates/transactions/widgets/unselectable_paid_toggle_button.html:16
msgid "Paid"
msgstr ""
#: apps/rules/forms.py:170 apps/rules/forms.py:183 apps/rules/models.py:34
-#: apps/rules/models.py:258 apps/transactions/forms.py:69
-#: apps/transactions/forms.py:346 apps/transactions/forms.py:536
-#: apps/transactions/models.py:296 apps/transactions/models.py:478
-#: apps/transactions/models.py:707
+#: apps/rules/models.py:258 apps/transactions/forms.py:70
+#: apps/transactions/forms.py:481 apps/transactions/forms.py:671
+#: apps/transactions/models.py:301 apps/transactions/models.py:483
+#: apps/transactions/models.py:712
msgid "Reference Date"
msgstr ""
#: apps/rules/forms.py:171 apps/rules/forms.py:184 apps/rules/models.py:35
-#: apps/rules/models.py:262 apps/transactions/models.py:301
-#: apps/transactions/models.py:688 templates/insights/fragments/sankey.html:95
+#: apps/rules/models.py:262 apps/transactions/models.py:306
+#: apps/transactions/models.py:693 apps/transactions/models.py:925
+#: templates/insights/fragments/sankey.html:95
msgid "Amount"
msgstr ""
#: apps/rules/forms.py:172 apps/rules/forms.py:185 apps/rules/models.py:14
#: apps/rules/models.py:36 apps/rules/models.py:266
-#: apps/transactions/forms.py:350 apps/transactions/models.py:306
-#: apps/transactions/models.py:462 apps/transactions/models.py:691
+#: apps/transactions/forms.py:485 apps/transactions/models.py:311
+#: apps/transactions/models.py:467 apps/transactions/models.py:696
+#: apps/transactions/models.py:930
msgid "Description"
msgstr ""
#: apps/rules/forms.py:175 apps/rules/forms.py:190 apps/rules/models.py:274
-#: apps/transactions/models.py:345
+#: apps/transactions/models.py:350 apps/transactions/models.py:952
msgid "Internal Note"
msgstr ""
#: apps/rules/forms.py:176 apps/rules/forms.py:191 apps/rules/models.py:278
-#: apps/transactions/models.py:347
+#: apps/transactions/models.py:352 apps/transactions/models.py:954
msgid "Internal ID"
msgstr ""
@@ -1206,8 +1219,8 @@ msgstr ""
msgid "Update or Create Transaction action deleted successfully"
msgstr ""
-#: apps/transactions/filters.py:24 templates/cotton/transaction/item.html:21
-#: templates/cotton/transaction/item.html:31 templates/includes/navbar.html:46
+#: apps/transactions/filters.py:24 templates/cotton/transaction/item.html:22
+#: templates/cotton/transaction/item.html:32 templates/includes/navbar.html:46
#: templates/insights/fragments/category_overview/index.html:46
#: templates/transactions/widgets/paid_toggle_button.html:8
#: templates/transactions/widgets/unselectable_paid_toggle_button.html:12
@@ -1242,231 +1255,244 @@ msgstr ""
msgid "Amount max"
msgstr ""
-#: apps/transactions/forms.py:172
+#: apps/transactions/forms.py:173
msgid "More"
msgstr ""
-#: apps/transactions/forms.py:216
+#: apps/transactions/forms.py:217
msgid "Save and add similar"
msgstr ""
-#: apps/transactions/forms.py:221
+#: apps/transactions/forms.py:222
msgid "Save and add another"
msgstr ""
-#: apps/transactions/forms.py:302
+#: apps/transactions/forms.py:437
msgid "From Amount"
msgstr ""
-#: apps/transactions/forms.py:307
+#: apps/transactions/forms.py:442
msgid "To Amount"
msgstr ""
-#: apps/transactions/forms.py:424
+#: apps/transactions/forms.py:559
#: templates/cotton/ui/quick_transactions_buttons.html:40
+#: templates/cotton/ui/transactions_fab.html:44
msgid "Transfer"
msgstr ""
-#: apps/transactions/forms.py:670
+#: apps/transactions/forms.py:805
msgid "Tag name"
msgstr ""
-#: apps/transactions/forms.py:702
+#: apps/transactions/forms.py:837
msgid "Entity name"
msgstr ""
-#: apps/transactions/forms.py:734
+#: apps/transactions/forms.py:869
msgid "Category name"
msgstr ""
-#: apps/transactions/forms.py:736
+#: apps/transactions/forms.py:871
msgid "Muted categories won't count towards your monthly total"
msgstr ""
-#: apps/transactions/forms.py:922
+#: apps/transactions/forms.py:1057
msgid "End date should be after the start date"
msgstr ""
-#: apps/transactions/models.py:206
+#: apps/transactions/models.py:211
msgid "Mute"
msgstr ""
-#: apps/transactions/models.py:211
+#: apps/transactions/models.py:216
msgid ""
"Deactivated categories won't be able to be selected when creating new "
"transactions"
msgstr ""
-#: apps/transactions/models.py:219
+#: apps/transactions/models.py:224
msgid "Transaction Category"
msgstr ""
-#: apps/transactions/models.py:220
+#: apps/transactions/models.py:225
msgid "Transaction Categories"
msgstr ""
-#: apps/transactions/models.py:235
+#: apps/transactions/models.py:240
msgid ""
"Deactivated tags won't be able to be selected when creating new transactions"
msgstr ""
-#: apps/transactions/models.py:243 apps/transactions/models.py:244
+#: apps/transactions/models.py:248 apps/transactions/models.py:249
msgid "Transaction Tags"
msgstr ""
-#: apps/transactions/models.py:259
+#: apps/transactions/models.py:264
msgid ""
"Deactivated entities won't be able to be selected when creating new "
"transactions"
msgstr ""
-#: apps/transactions/models.py:267
+#: apps/transactions/models.py:272
msgid "Entity"
msgstr ""
-#: apps/transactions/models.py:279
+#: apps/transactions/models.py:284 apps/transactions/models.py:898
#: templates/calendar_view/fragments/list.html:42
#: templates/calendar_view/fragments/list.html:44
#: templates/calendar_view/fragments/list.html:52
#: templates/calendar_view/fragments/list.html:54
#: templates/cotton/ui/quick_transactions_buttons.html:10
+#: templates/cotton/ui/transactions_fab.html:10
#: templates/insights/fragments/category_overview/index.html:64
#: templates/monthly_overview/fragments/monthly_summary.html:39
msgid "Income"
msgstr ""
-#: apps/transactions/models.py:280
+#: apps/transactions/models.py:285 apps/transactions/models.py:899
#: templates/calendar_view/fragments/list.html:46
#: templates/calendar_view/fragments/list.html:48
#: templates/calendar_view/fragments/list.html:56
#: templates/calendar_view/fragments/list.html:58
#: templates/cotton/ui/quick_transactions_buttons.html:18
+#: templates/cotton/ui/transactions_fab.html:19
#: templates/insights/fragments/category_overview/index.html:65
msgid "Expense"
msgstr ""
-#: apps/transactions/models.py:334 apps/transactions/models.py:517
+#: apps/transactions/models.py:339 apps/transactions/models.py:522
msgid "Installment Plan"
msgstr ""
-#: apps/transactions/models.py:343 apps/transactions/models.py:738
+#: apps/transactions/models.py:348 apps/transactions/models.py:743
msgid "Recurring Transaction"
msgstr ""
-#: apps/transactions/models.py:351
+#: apps/transactions/models.py:356
msgid "Deleted"
msgstr ""
-#: apps/transactions/models.py:356
+#: apps/transactions/models.py:361
msgid "Deleted At"
msgstr ""
-#: apps/transactions/models.py:368
+#: apps/transactions/models.py:373
msgid "Transaction"
msgstr ""
-#: apps/transactions/models.py:440 templates/tags/fragments/table.html:71
+#: apps/transactions/models.py:445 templates/tags/fragments/table.html:71
msgid "No tags"
msgstr ""
-#: apps/transactions/models.py:441
+#: apps/transactions/models.py:446
msgid "No category"
msgstr ""
-#: apps/transactions/models.py:443
+#: apps/transactions/models.py:448
msgid "No description"
msgstr ""
-#: apps/transactions/models.py:449
+#: apps/transactions/models.py:454
msgid "Yearly"
msgstr ""
-#: apps/transactions/models.py:450 apps/users/models.py:26
+#: apps/transactions/models.py:455 apps/users/models.py:26
#: templates/includes/navbar.html:26
msgid "Monthly"
msgstr ""
-#: apps/transactions/models.py:451
+#: apps/transactions/models.py:456
msgid "Weekly"
msgstr ""
-#: apps/transactions/models.py:452
+#: apps/transactions/models.py:457
msgid "Daily"
msgstr ""
-#: apps/transactions/models.py:465
+#: apps/transactions/models.py:470
msgid "Number of Installments"
msgstr ""
-#: apps/transactions/models.py:470
+#: apps/transactions/models.py:475
msgid "Installment Start"
msgstr ""
-#: apps/transactions/models.py:471
+#: apps/transactions/models.py:476
msgid "The installment number to start counting from"
msgstr ""
-#: apps/transactions/models.py:476 apps/transactions/models.py:711
+#: apps/transactions/models.py:481 apps/transactions/models.py:716
msgid "Start Date"
msgstr ""
-#: apps/transactions/models.py:480 apps/transactions/models.py:712
+#: apps/transactions/models.py:485 apps/transactions/models.py:717
msgid "End Date"
msgstr ""
-#: apps/transactions/models.py:485
+#: apps/transactions/models.py:490
msgid "Recurrence"
msgstr ""
-#: apps/transactions/models.py:488
+#: apps/transactions/models.py:493
msgid "Installment Amount"
msgstr ""
-#: apps/transactions/models.py:507 apps/transactions/models.py:728
+#: apps/transactions/models.py:512 apps/transactions/models.py:733
msgid "Add description to transactions"
msgstr ""
-#: apps/transactions/models.py:510 apps/transactions/models.py:731
+#: apps/transactions/models.py:515 apps/transactions/models.py:736
msgid "Add notes to transactions"
msgstr ""
-#: apps/transactions/models.py:670
+#: apps/transactions/models.py:675
msgid "day(s)"
msgstr ""
-#: apps/transactions/models.py:671
+#: apps/transactions/models.py:676
msgid "week(s)"
msgstr ""
-#: apps/transactions/models.py:672
+#: apps/transactions/models.py:677
msgid "month(s)"
msgstr ""
-#: apps/transactions/models.py:673
+#: apps/transactions/models.py:678
msgid "year(s)"
msgstr ""
-#: apps/transactions/models.py:675
+#: apps/transactions/models.py:680
#: templates/recurring_transactions/fragments/list.html:24
msgid "Paused"
msgstr ""
-#: apps/transactions/models.py:714
+#: apps/transactions/models.py:719
msgid "Recurrence Type"
msgstr ""
-#: apps/transactions/models.py:717
+#: apps/transactions/models.py:722
msgid "Recurrence Interval"
msgstr ""
-#: apps/transactions/models.py:721
+#: apps/transactions/models.py:726
msgid "Last Generated Date"
msgstr ""
-#: apps/transactions/models.py:724
+#: apps/transactions/models.py:729
msgid "Last Generated Reference Date"
msgstr ""
+#: apps/transactions/models.py:964 templates/cotton/ui/transactions_fab.html:59
+msgid "Quick Transaction"
+msgstr ""
+
+#: apps/transactions/models.py:965 templates/includes/navbar.html:72
+#: templates/quick_transactions/pages/index.html:5
+#: templates/quick_transactions/pages/index.html:11
+msgid "Quick Transactions"
+msgstr ""
+
#: apps/transactions/validators.py:8
#, python-format
msgid "%(value)s has too many decimal places. Maximum is 30."
@@ -1552,6 +1578,24 @@ msgstr ""
msgid "Installment Plan deleted successfully"
msgstr ""
+#: apps/transactions/views/quick_transactions.py:45 apps/users/views.py:152
+msgid "Item added successfully"
+msgstr ""
+
+#: apps/transactions/views/quick_transactions.py:73 apps/users/views.py:184
+msgid "Item updated successfully"
+msgstr ""
+
+#: apps/transactions/views/quick_transactions.py:99
+msgid "Item deleted successfully"
+msgstr ""
+
+#: apps/transactions/views/quick_transactions.py:145
+#: apps/transactions/views/transactions.py:52
+#: apps/transactions/views/transactions.py:148
+msgid "Transaction added successfully"
+msgstr ""
+
#: apps/transactions/views/recurring_transactions.py:112
msgid "Recurring Transaction added successfully"
msgstr ""
@@ -1588,11 +1632,6 @@ msgstr ""
msgid "Tag deleted successfully"
msgstr ""
-#: apps/transactions/views/transactions.py:52
-#: apps/transactions/views/transactions.py:148
-msgid "Transaction added successfully"
-msgstr ""
-
#: apps/transactions/views/transactions.py:182
msgid "Transaction updated successfully"
msgstr ""
@@ -1798,14 +1837,6 @@ msgstr ""
msgid "Your settings have been updated"
msgstr ""
-#: apps/users/views.py:152
-msgid "Item added successfully"
-msgstr ""
-
-#: apps/users/views.py:184
-msgid "Item updated successfully"
-msgstr ""
-
#: templates/account_groups/fragments/add.html:5
msgid "Add account group"
msgstr ""
@@ -1825,6 +1856,7 @@ msgstr ""
#: templates/exchange_rates_services/fragments/table.html:19
#: templates/import_app/fragments/profiles/list.html:44
#: templates/installment_plans/fragments/table.html:23
+#: templates/quick_transactions/fragments/list.html:20
#: templates/recurring_transactions/fragments/table.html:25
#: templates/rules/fragments/list.html:33
#: templates/tags/fragments/table.html:23
@@ -1835,7 +1867,7 @@ msgstr ""
#: templates/account_groups/fragments/list.html:36
#: templates/accounts/fragments/list.html:41
#: templates/categories/fragments/table.html:29
-#: templates/cotton/transaction/item.html:130
+#: templates/cotton/transaction/item.html:131
#: templates/cotton/ui/transactions_action_bar.html:49
#: templates/currencies/fragments/list.html:37
#: templates/dca/fragments/strategy/details.html:67
@@ -1846,6 +1878,7 @@ msgstr ""
#: templates/exchange_rates_services/fragments/table.html:23
#: templates/import_app/fragments/profiles/list.html:48
#: templates/installment_plans/fragments/table.html:27
+#: templates/quick_transactions/fragments/list.html:24
#: templates/recurring_transactions/fragments/table.html:29
#: templates/rules/fragments/transaction_rule/view.html:23
#: templates/rules/fragments/transaction_rule/view.html:47
@@ -1858,8 +1891,8 @@ msgstr ""
#: templates/account_groups/fragments/list.html:43
#: templates/accounts/fragments/list.html:48
#: templates/categories/fragments/table.html:36
-#: templates/cotton/transaction/item.html:145
-#: templates/cotton/transaction/item.html:164
+#: templates/cotton/transaction/item.html:146
+#: templates/cotton/transaction/item.html:165
#: templates/cotton/ui/deleted_transactions_action_bar.html:55
#: templates/cotton/ui/transactions_action_bar.html:86
#: templates/currencies/fragments/list.html:44
@@ -1873,6 +1906,7 @@ msgstr ""
#: templates/import_app/fragments/runs/list.html:102
#: templates/installment_plans/fragments/table.html:56
#: templates/mini_tools/unit_price_calculator.html:18
+#: templates/quick_transactions/fragments/list.html:32
#: templates/recurring_transactions/fragments/table.html:91
#: templates/rules/fragments/list.html:44
#: templates/rules/fragments/transaction_rule/view.html:55
@@ -1884,8 +1918,8 @@ msgstr ""
#: templates/account_groups/fragments/list.html:47
#: templates/accounts/fragments/list.html:52
#: templates/categories/fragments/table.html:41
-#: templates/cotton/transaction/item.html:149
-#: templates/cotton/transaction/item.html:168
+#: templates/cotton/transaction/item.html:150
+#: templates/cotton/transaction/item.html:169
#: templates/cotton/ui/deleted_transactions_action_bar.html:57
#: templates/cotton/ui/transactions_action_bar.html:88
#: templates/currencies/fragments/list.html:48
@@ -1899,6 +1933,7 @@ msgstr ""
#: templates/import_app/fragments/runs/list.html:106
#: templates/installment_plans/fragments/table.html:48
#: templates/installment_plans/fragments/table.html:60
+#: templates/quick_transactions/fragments/list.html:37
#: templates/recurring_transactions/fragments/table.html:53
#: templates/recurring_transactions/fragments/table.html:67
#: templates/recurring_transactions/fragments/table.html:82
@@ -1913,8 +1948,8 @@ msgstr ""
#: templates/account_groups/fragments/list.html:48
#: templates/accounts/fragments/list.html:53
#: templates/categories/fragments/table.html:42
-#: templates/cotton/transaction/item.html:150
-#: templates/cotton/transaction/item.html:169
+#: templates/cotton/transaction/item.html:151
+#: templates/cotton/transaction/item.html:170
#: templates/cotton/ui/deleted_transactions_action_bar.html:58
#: templates/cotton/ui/transactions_action_bar.html:89
#: templates/currencies/fragments/list.html:49
@@ -1935,8 +1970,8 @@ msgstr ""
#: templates/account_groups/fragments/list.html:49
#: templates/accounts/fragments/list.html:54
#: templates/categories/fragments/table.html:43
-#: templates/cotton/transaction/item.html:151
-#: templates/cotton/transaction/item.html:170
+#: templates/cotton/transaction/item.html:152
+#: templates/cotton/transaction/item.html:171
#: templates/currencies/fragments/list.html:50
#: templates/dca/fragments/strategy/details.html:82
#: templates/dca/fragments/strategy/list.html:50
@@ -1947,6 +1982,7 @@ msgstr ""
#: templates/import_app/fragments/profiles/list.html:75
#: templates/import_app/fragments/runs/list.html:108
#: templates/installment_plans/fragments/table.html:62
+#: templates/quick_transactions/fragments/list.html:39
#: templates/recurring_transactions/fragments/table.html:98
#: templates/rules/fragments/list.html:50
#: templates/rules/fragments/transaction_rule/view.html:61
@@ -2096,7 +2132,7 @@ msgstr ""
msgid "Select"
msgstr ""
-#: templates/cotton/transaction/item.html:137
+#: templates/cotton/transaction/item.html:138
#: templates/cotton/ui/transactions_action_bar.html:78
msgid "Duplicate"
msgstr ""
@@ -2205,14 +2241,17 @@ msgid "Count"
msgstr ""
#: templates/cotton/ui/quick_transactions_buttons.html:25
+#: templates/cotton/ui/transactions_fab.html:27
msgid "Installment"
msgstr ""
#: templates/cotton/ui/quick_transactions_buttons.html:32
+#: templates/cotton/ui/transactions_fab.html:35
msgid "Recurring"
msgstr ""
#: templates/cotton/ui/quick_transactions_buttons.html:47
+#: templates/cotton/ui/transactions_fab.html:52
msgid "Balance"
msgstr ""
@@ -2378,8 +2417,8 @@ msgstr ""
#: templates/exchange_rates/fragments/list.html:25
#: templates/includes/navbar.html:61
#: templates/installment_plans/fragments/list.html:21
-#: templates/yearly_overview/pages/overview_by_account.html:92
-#: templates/yearly_overview/pages/overview_by_currency.html:94
+#: templates/yearly_overview/pages/overview_by_account.html:94
+#: templates/yearly_overview/pages/overview_by_currency.html:96
msgid "All"
msgstr ""
@@ -2432,7 +2471,7 @@ msgstr ""
msgid "No services configured"
msgstr ""
-#: templates/export_app/pages/index.html:4 templates/includes/navbar.html:137
+#: templates/export_app/pages/index.html:4 templates/includes/navbar.html:139
msgid "Export and Restore"
msgstr ""
@@ -2545,47 +2584,47 @@ msgstr ""
msgid "Trash Can"
msgstr ""
-#: templates/includes/navbar.html:82
+#: templates/includes/navbar.html:84
msgid "Tools"
msgstr ""
-#: templates/includes/navbar.html:86
+#: templates/includes/navbar.html:88
msgid "Dollar Cost Average Tracker"
msgstr ""
-#: templates/includes/navbar.html:89
+#: templates/includes/navbar.html:91
#: templates/mini_tools/unit_price_calculator.html:5
#: templates/mini_tools/unit_price_calculator.html:10
msgid "Unit Price Calculator"
msgstr ""
-#: templates/includes/navbar.html:92
+#: templates/includes/navbar.html:94
#: templates/mini_tools/currency_converter/currency_converter.html:8
#: templates/mini_tools/currency_converter/currency_converter.html:15
msgid "Currency Converter"
msgstr ""
-#: templates/includes/navbar.html:101
+#: templates/includes/navbar.html:103
msgid "Management"
msgstr ""
-#: templates/includes/navbar.html:130
+#: templates/includes/navbar.html:132
msgid "Automation"
msgstr ""
-#: templates/includes/navbar.html:145
+#: templates/includes/navbar.html:147
msgid "Admin"
msgstr ""
-#: templates/includes/navbar.html:154
+#: templates/includes/navbar.html:156
msgid "Only use this if you know what you're doing"
msgstr ""
-#: templates/includes/navbar.html:155
+#: templates/includes/navbar.html:157
msgid "Django Admin"
msgstr ""
-#: templates/includes/navbar.html:165
+#: templates/includes/navbar.html:167
msgid "Calculator"
msgstr ""
@@ -2731,8 +2770,8 @@ msgid "Month"
msgstr ""
#: templates/insights/pages/index.html:40
-#: templates/yearly_overview/pages/overview_by_account.html:61
-#: templates/yearly_overview/pages/overview_by_currency.html:63
+#: templates/yearly_overview/pages/overview_by_account.html:62
+#: templates/yearly_overview/pages/overview_by_currency.html:64
msgid "Year"
msgstr ""
@@ -2924,6 +2963,24 @@ msgstr ""
msgid "Evolution by account"
msgstr ""
+#: templates/quick_transactions/fragments/add.html:5
+#: templates/quick_transactions/fragments/create_menu.html:5
+msgid "Add quick transaction"
+msgstr ""
+
+#: templates/quick_transactions/fragments/create_menu.html:13
+#: templates/quick_transactions/fragments/list.html:55
+msgid "Nothing to see here..."
+msgstr ""
+
+#: templates/quick_transactions/fragments/edit.html:5
+msgid "Edit quick transaction"
+msgstr ""
+
+#: templates/quick_transactions/fragments/list.html:38
+msgid "This will delete this item"
+msgstr ""
+
#: templates/recurring_transactions/fragments/add.html:5
msgid "Add recurring transaction"
msgstr ""
diff --git a/app/locale/es/LC_MESSAGES/django.po b/app/locale/es/LC_MESSAGES/django.po
index 9a609f2..61f2528 100644
--- a/app/locale/es/LC_MESSAGES/django.po
+++ b/app/locale/es/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-05-11 15:47+0000\n"
+"POT-Creation-Date: 2025-06-20 05:02+0000\n"
"PO-Revision-Date: 2025-04-13 02:40+0000\n"
"Last-Translator: Prefill add-on \n"
"Language-Team: Spanish \n"
"Language-Team: French \n"
"Language-Team: Dutch \n"
"Language-Team: Portuguese \n"
"Language-Team: Portuguese (Brazil) \n"
"Language-Team: Swedish \n"
"Language-Team: Ukrainian
-
-{# Date picker#}
-
-
-
+
+
+ {# Date picker#}
+
+
+
+ {{ month|month_name }} {{ year }}
+
+
-
- {{ month|month_name }} {{ year }}
-
-
-
-
-
+ {# Action buttons#}
+
+ {# #}
-{# Action buttons#}
-
-
-
+
{% endblock %}
diff --git a/app/templates/cotton/components/fab.html b/app/templates/cotton/components/fab.html
new file mode 100644
index 0000000..e25c177
--- /dev/null
+++ b/app/templates/cotton/components/fab.html
@@ -0,0 +1,33 @@
+
diff --git a/app/templates/cotton/components/fab_menu_button.html b/app/templates/cotton/components/fab_menu_button.html
new file mode 100644
index 0000000..26e496b
--- /dev/null
+++ b/app/templates/cotton/components/fab_menu_button.html
@@ -0,0 +1,11 @@
+{% load i18n %}
+
+
+
+ {{ title }}
+
+
diff --git a/app/templates/cotton/transaction/item.html b/app/templates/cotton/transaction/item.html
index 7df49bd..3f9df66 100644
--- a/app/templates/cotton/transaction/item.html
+++ b/app/templates/cotton/transaction/item.html
@@ -15,7 +15,8 @@
_="on mouseover remove .tw-invisible from the first .transaction-actions in me end
on mouseout add .tw-invisible to the first .transaction-actions in me end">
-
{# Action buttons#}
-
-
-
+{#
#}
+{# #}
+{#
#}
{# Monthly summary#}
@@ -174,8 +174,9 @@
-
+ {% crispy form %}
+
+{% endblock %}
diff --git a/app/templates/quick_transactions/fragments/create_menu.html b/app/templates/quick_transactions/fragments/create_menu.html
new file mode 100644
index 0000000..af2d84e
--- /dev/null
+++ b/app/templates/quick_transactions/fragments/create_menu.html
@@ -0,0 +1,17 @@
+{% extends 'extends/offcanvas.html' %}
+{% load i18n %}
+{% load crispy_forms_tags %}
+
+{% block title %}{% translate 'Add quick transaction' %}{% endblock %}
+
+{% block body %}
+
+ {% for qt in quick_transactions %}
+
{{ qt.name }}
+ {% empty %}
+
+ {% endfor %}
+
+
+{% endblock %}
diff --git a/app/templates/quick_transactions/fragments/edit.html b/app/templates/quick_transactions/fragments/edit.html
new file mode 100644
index 0000000..608da0f
--- /dev/null
+++ b/app/templates/quick_transactions/fragments/edit.html
@@ -0,0 +1,13 @@
+{% extends 'extends/offcanvas.html' %}
+{% load i18n %}
+{% load crispy_forms_tags %}
+
+{% block title %}{% translate 'Edit quick transaction' %}{% endblock %}
+
+{% block body %}
+
+{% endblock %}
diff --git a/app/templates/quick_transactions/fragments/list.html b/app/templates/quick_transactions/fragments/list.html
new file mode 100644
index 0000000..9682e84
--- /dev/null
+++ b/app/templates/quick_transactions/fragments/list.html
@@ -0,0 +1,59 @@
+{% load i18n %}
+
+
+
+ {% if quick_transactions %}
+
+
+
+
+
+
+
+ {% translate 'Name' %}
+
+
+
+ {% for qt in quick_transactions %}
+
+
+
+
+
+
+ {{ qt.name }}
+
+
+
+ {% endfor %}
+
+
+
+ {% else %}
+
+ {% endif %}
+
+
+
diff --git a/app/templates/quick_transactions/pages/index.html b/app/templates/quick_transactions/pages/index.html
new file mode 100644
index 0000000..5db431a
--- /dev/null
+++ b/app/templates/quick_transactions/pages/index.html
@@ -0,0 +1,25 @@
+{% extends "layouts/base.html" %}
+
+{% load i18n %}
+
+{% block title %}{% translate 'Quick Transactions' %}{% endblock %}
+
+{% block content %}
+
+
+ {% spaceless %}
+
{% translate 'Quick Transactions' %}
+
+
+
+ {% endspaceless %}
+
+
+
+
+{% endblock %}
diff --git a/app/templates/yearly_overview/pages/overview_by_account.html b/app/templates/yearly_overview/pages/overview_by_account.html
index 58f9e43..3ff0ca9 100644
--- a/app/templates/yearly_overview/pages/overview_by_account.html
+++ b/app/templates/yearly_overview/pages/overview_by_account.html
@@ -12,55 +12,56 @@
{% endblock %}
{% block content %}
-
-
-{# Date picker#}
-
-
-
-
+
+
+ {# Date picker#}
+
-
- {{ year }}
-
-
-
-
-
+ {# Action buttons#}
+
+ {# #}
-{# Action buttons#}
-
-
-
-
-
-
-
-
-
- {% translate 'Year' %}
-
- {% for month in months %}
+
+
+
+
+
+ {% translate 'Year' %}
+
+ {% for month in months %}
- {{ month|month_name }}
+ {{ month|month_name }}
- {% endfor %}
+ {% endfor %}
-
+
-
-
-
-
-
- {% translate 'All' %}
-
- {% for account in accounts %}
+
+
+
+
+
+ {% translate 'All' %}
+
+ {% for account in accounts %}
- {{ account.group.name }} {{ account.name }}
+ {{ account.group.name }} {{ account.name }}
- {% endfor %}
+ {% endfor %}
-
+
-
-
+
{% endblock %}
diff --git a/app/templates/yearly_overview/pages/overview_by_currency.html b/app/templates/yearly_overview/pages/overview_by_currency.html
index da4c890..9281824 100644
--- a/app/templates/yearly_overview/pages/overview_by_currency.html
+++ b/app/templates/yearly_overview/pages/overview_by_currency.html
@@ -14,55 +14,56 @@
{% endblock %}
{% block content %}
-
-
-{# Date picker#}
-
-
-
-
+
+
+ {# Date picker#}
+
-
- {{ year }}
-
-
-
-
-
+ {# Action buttons#}
+
+ {# #}
-{# Action buttons#}
-
-
-
-
-
-
-
-
-
- {% translate 'Year' %}
-
- {% for month in months %}
+
+
+
+
+
+ {% translate 'Year' %}
+
+ {% for month in months %}
- {{ month|month_name }}
+ {{ month|month_name }}
- {% endfor %}
+ {% endfor %}
-
+
-
-
-
-
-
- {% translate 'All' %}
-
- {% for currency in currencies %}
+
+
+
+
+
+ {% translate 'All' %}
+
+ {% for currency in currencies %}
- {{ currency.name }}
+ {{ currency.name }}
- {% endfor %}
+ {% endfor %}
-
+
-
-
+
{% endblock %}
diff --git a/frontend/src/styles/_scrollbar.scss b/frontend/src/styles/_scrollbar.scss
index c83dc83..811e65a 100644
--- a/frontend/src/styles/_scrollbar.scss
+++ b/frontend/src/styles/_scrollbar.scss
@@ -2,7 +2,7 @@
/* custom scrollbar */
::-webkit-scrollbar {
- width: 10px;
+ width: 13px;
}
::-webkit-scrollbar-track {
diff --git a/frontend/src/styles/_variables.scss b/frontend/src/styles/_variables.scss
index 592a695..ebcf0f6 100644
--- a/frontend/src/styles/_variables.scss
+++ b/frontend/src/styles/_variables.scss
@@ -35,3 +35,6 @@ $min-contrast-ratio: 1.9 !default;
$nav-pills-link-active-color: $gray-900;
$dropdown-link-active-color: $gray-900;
+
+$body-bg-dark: #1e1f24 !default;
+$body-tertiary-bg-dark: #232429 !default;