mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-03-22 09:29:30 +01:00
Merge pull request #282
feat: allow single transactions to be hidden from summaries fix #274
This commit is contained in:
@@ -91,6 +91,8 @@ def get_transactions(request, include_unpaid=True, include_silent=False):
|
||||
transactions = transactions.filter(is_paid=True)
|
||||
|
||||
if not include_silent:
|
||||
transactions = transactions.exclude(Q(category__mute=True) & ~Q(category=None))
|
||||
transactions = transactions.exclude(
|
||||
Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True)
|
||||
)
|
||||
|
||||
return transactions
|
||||
|
||||
@@ -260,6 +260,7 @@ def emergency_fund(request):
|
||||
reference_date__gte=start_date,
|
||||
reference_date__lte=end_date,
|
||||
category__mute=False,
|
||||
mute=False,
|
||||
)
|
||||
.values("reference_date", "account__currency")
|
||||
.annotate(monthly_total=Sum("amount"))
|
||||
|
||||
@@ -109,7 +109,7 @@ def monthly_summary(request, month: int, year: int):
|
||||
# Base queryset with all required filters
|
||||
base_queryset = Transaction.objects.filter(
|
||||
reference_date__year=year, reference_date__month=month, account__is_asset=False
|
||||
).exclude(Q(category__mute=True) & ~Q(category=None))
|
||||
).exclude(Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True))
|
||||
|
||||
data = calculate_currency_totals(base_queryset, ignore_empty=True)
|
||||
percentages = calculate_percentage_distribution(data)
|
||||
@@ -143,7 +143,7 @@ def monthly_account_summary(request, month: int, year: int):
|
||||
base_queryset = Transaction.objects.filter(
|
||||
reference_date__year=year,
|
||||
reference_date__month=month,
|
||||
).exclude(Q(category__mute=True) & ~Q(category=None))
|
||||
).exclude(Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True))
|
||||
|
||||
account_data = calculate_account_totals(transactions_queryset=base_queryset.all())
|
||||
account_percentages = calculate_percentage_distribution(account_data)
|
||||
@@ -168,7 +168,7 @@ def monthly_currency_summary(request, month: int, year: int):
|
||||
base_queryset = Transaction.objects.filter(
|
||||
reference_date__year=year,
|
||||
reference_date__month=month,
|
||||
).exclude(Q(category__mute=True) & ~Q(category=None))
|
||||
).exclude(Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True))
|
||||
|
||||
currency_data = calculate_currency_totals(base_queryset.all(), ignore_empty=True)
|
||||
currency_percentages = calculate_percentage_distribution(currency_data)
|
||||
|
||||
@@ -290,11 +290,15 @@ class QuickTransactionForm(forms.ModelForm):
|
||||
"category",
|
||||
"tags",
|
||||
"entities",
|
||||
"mute",
|
||||
]
|
||||
widgets = {
|
||||
"notes": forms.Textarea(attrs={"rows": 3}),
|
||||
"account": TomSelect(clear_button=False, group_by="group"),
|
||||
}
|
||||
help_texts = {
|
||||
"mute": _("Muted transactions won't be displayed on monthly summaries")
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -356,6 +360,7 @@ class QuickTransactionForm(forms.ModelForm):
|
||||
css_class="form-row",
|
||||
),
|
||||
"notes",
|
||||
Switch("mute"),
|
||||
)
|
||||
|
||||
if self.instance and self.instance.pk:
|
||||
@@ -616,6 +621,7 @@ class TransferForm(forms.Form):
|
||||
description=description,
|
||||
category=from_category,
|
||||
notes=notes,
|
||||
mute=True,
|
||||
)
|
||||
from_transaction.tags.set(self.cleaned_data.get("from_tags", []))
|
||||
|
||||
@@ -630,6 +636,7 @@ class TransferForm(forms.Form):
|
||||
description=description,
|
||||
category=to_category,
|
||||
notes=notes,
|
||||
mute=True,
|
||||
)
|
||||
to_transaction.tags.set(self.cleaned_data.get("to_tags", []))
|
||||
|
||||
@@ -868,7 +875,7 @@ class TransactionCategoryForm(forms.ModelForm):
|
||||
fields = ["name", "mute", "active"]
|
||||
labels = {"name": _("Category name")}
|
||||
help_texts = {
|
||||
"mute": _("Muted categories won't count towards your monthly total")
|
||||
"mute": _("Muted categories won't be displayed on monthly summaries")
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
18
app/apps/transactions/migrations/0045_transaction_mute.py
Normal file
18
app/apps/transactions/migrations/0045_transaction_mute.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.11 on 2025-07-19 18:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('transactions', '0044_alter_quicktransaction_unique_together'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='transaction',
|
||||
name='mute',
|
||||
field=models.BooleanField(default=False, verbose_name='Mute'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.11 on 2025-07-19 18:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('transactions', '0045_transaction_mute'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='quicktransaction',
|
||||
name='mute',
|
||||
field=models.BooleanField(default=False, verbose_name='Mute'),
|
||||
),
|
||||
]
|
||||
@@ -299,6 +299,7 @@ class Transaction(OwnedObject):
|
||||
is_paid = models.BooleanField(default=True, verbose_name=_("Paid"))
|
||||
date = models.DateField(verbose_name=_("Date"))
|
||||
reference_date = MonthYearModelField(verbose_name=_("Reference Date"))
|
||||
mute = models.BooleanField(default=False, verbose_name=_("Mute"))
|
||||
|
||||
amount = models.DecimalField(
|
||||
max_digits=42,
|
||||
@@ -918,6 +919,7 @@ class QuickTransaction(OwnedObject):
|
||||
verbose_name=_("Type"),
|
||||
)
|
||||
is_paid = models.BooleanField(default=True, verbose_name=_("Paid"))
|
||||
mute = models.BooleanField(default=False, verbose_name=_("Mute"))
|
||||
|
||||
amount = models.DecimalField(
|
||||
max_digits=42,
|
||||
|
||||
@@ -66,6 +66,11 @@ urlpatterns = [
|
||||
views.transaction_pay,
|
||||
name="transaction_pay",
|
||||
),
|
||||
path(
|
||||
"transaction/<int:transaction_id>/mute/",
|
||||
views.transaction_mute,
|
||||
name="transaction_mute",
|
||||
),
|
||||
path(
|
||||
"transaction/<int:transaction_id>/delete/",
|
||||
views.transaction_delete,
|
||||
|
||||
@@ -388,6 +388,26 @@ def transaction_pay(request, transaction_id):
|
||||
return response
|
||||
|
||||
|
||||
@only_htmx
|
||||
@login_required
|
||||
@require_http_methods(["GET"])
|
||||
def transaction_mute(request, transaction_id):
|
||||
transaction = get_object_or_404(Transaction, pk=transaction_id)
|
||||
|
||||
new_mute = False if transaction.mute else True
|
||||
transaction.mute = new_mute
|
||||
transaction.save()
|
||||
transaction_updated.send(sender=transaction)
|
||||
|
||||
response = render(
|
||||
request,
|
||||
"transactions/fragments/item.html",
|
||||
context={"transaction": transaction, **request.GET},
|
||||
)
|
||||
response.headers["HX-Trigger"] = "selective_update"
|
||||
return response
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["GET"])
|
||||
def transaction_all_index(request):
|
||||
|
||||
@@ -75,7 +75,7 @@ def yearly_overview_by_currency(request, year: int):
|
||||
|
||||
transactions = (
|
||||
Transaction.objects.filter(**filter_params)
|
||||
.exclude(Q(category__mute=True) & ~Q(category=None))
|
||||
.exclude(Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True))
|
||||
.order_by("account__currency__name")
|
||||
)
|
||||
|
||||
@@ -141,7 +141,7 @@ def yearly_overview_by_account(request, year: int):
|
||||
|
||||
transactions = (
|
||||
Transaction.objects.filter(**filter_params)
|
||||
.exclude(Q(category__mute=True) & ~Q(category=None))
|
||||
.exclude(Q(Q(category__mute=True) & ~Q(category=None)) | Q(mute=True))
|
||||
.order_by(
|
||||
"account__group__name",
|
||||
"account__name",
|
||||
|
||||
@@ -146,6 +146,21 @@
|
||||
<i class="fa-solid fa-ellipsis fa-fw"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if transaction.category.mute %}
|
||||
<li>
|
||||
<a class="dropdown-item disabled d-flex align-items-center" aria-disabled="true">
|
||||
<i class="fa-solid fa-eye fa-fw me-2"></i>
|
||||
<div>
|
||||
{% translate 'Show on summaries' %}
|
||||
<div class="d-block text-body-secondary tw:text-xs tw:font-medium">{% translate 'Controlled by category' %}</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{% elif transaction.mute %}
|
||||
<li><a class="dropdown-item" href="#" hx-get="{% url 'transaction_mute' transaction_id=transaction.id %}" hx-target="closest .transaction" hx-swap="outerHTML"><i class="fa-solid fa-eye fa-fw me-2"></i>{% translate 'Show on summaries' %}</a></li>
|
||||
{% else %}
|
||||
<li><a class="dropdown-item" href="#" hx-get="{% url 'transaction_mute' transaction_id=transaction.id %}" hx-target="closest .transaction" hx-swap="outerHTML"><i class="fa-solid fa-eye-slash fa-fw me-2"></i>{% translate 'Hide from summaries' %}</a></li>
|
||||
{% endif %}
|
||||
<li><a class="dropdown-item" href="#" hx-get="{% url 'transaction_clone' transaction_id=transaction.id %}"><i class="fa-solid fa-clone fa-fw me-2"></i>{% translate 'Duplicate' %}</a></li>
|
||||
</ul>
|
||||
{% else %}
|
||||
|
||||
Reference in New Issue
Block a user