diff --git a/app/apps/monthly_overview/urls.py b/app/apps/monthly_overview/urls.py index 2080a81..74f082d 100644 --- a/app/apps/monthly_overview/urls.py +++ b/app/apps/monthly_overview/urls.py @@ -19,4 +19,19 @@ urlpatterns = [ views.monthly_summary, name="monthly_summary", ), + path( + "monthly///summary/accounts/", + views.monthly_account_summary, + name="monthly_account_summary", + ), + path( + "monthly///summary/currencies/", + views.monthly_currency_summary, + name="monthly_currency_summary", + ), + path( + "monthly/summary/select//", + views.monthly_summary_select, + name="monthly_summary_select", + ), ] diff --git a/app/apps/monthly_overview/views.py b/app/apps/monthly_overview/views.py index 01f6414..09215dc 100644 --- a/app/apps/monthly_overview/views.py +++ b/app/apps/monthly_overview/views.py @@ -2,6 +2,7 @@ from django.contrib.auth.decorators import login_required from django.db.models import ( Q, ) +from django.http import HttpResponse from django.shortcuts import render, redirect from django.utils import timezone from django.views.decorators.http import require_http_methods @@ -16,6 +17,7 @@ from apps.transactions.models import Transaction from apps.transactions.utils.calculations import ( calculate_currency_totals, calculate_percentage_distribution, + calculate_account_totals, ) from apps.transactions.utils.default_ordering import default_order @@ -31,6 +33,7 @@ def index(request): @require_http_methods(["GET"]) def monthly_overview(request, month: int, year: int): order = request.session.get("monthly_transactions_order", "default") + summary_tab = request.session.get("monthly_summary_tab", "summary") if month < 1 or month > 12: from django.http import Http404 @@ -57,6 +60,7 @@ def monthly_overview(request, month: int, year: int): "previous_year": previous_year, "filter": f, "order": order, + "summary_tab": summary_tab, }, ) @@ -131,3 +135,61 @@ def monthly_summary(request, month: int, year: int): "monthly_overview/fragments/monthly_summary.html", context=context, ) + + +@only_htmx +@login_required +@require_http_methods(["GET"]) +def monthly_account_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, + ).exclude(Q(category__mute=True) & ~Q(category=None)) + + account_data = calculate_account_totals(transactions_queryset=base_queryset.all()) + account_percentages = calculate_percentage_distribution(account_data) + + context = { + "account_data": account_data, + "account_percentages": account_percentages, + } + + return render( + request, + "monthly_overview/fragments/monthly_account_summary.html", + context=context, + ) + + +@only_htmx +@login_required +@require_http_methods(["GET"]) +def monthly_currency_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, + ).exclude(Q(category__mute=True) & ~Q(category=None)) + + currency_data = calculate_currency_totals(base_queryset.all(), ignore_empty=True) + currency_percentages = calculate_percentage_distribution(currency_data) + + context = { + "currency_data": currency_data, + "currency_percentages": currency_percentages, + } + + return render( + request, "monthly_overview/fragments/monthly_currency_summary.html", context + ) + + +@login_required +@require_http_methods(["GET"]) +def monthly_summary_select(request, selected): + request.session["monthly_summary_tab"] = selected + + return HttpResponse( + status=204, + ) diff --git a/app/apps/transactions/urls.py b/app/apps/transactions/urls.py index 5dae195..9aaf416 100644 --- a/app/apps/transactions/urls.py +++ b/app/apps/transactions/urls.py @@ -11,6 +11,21 @@ urlpatterns = [ views.transaction_all_summary, name="transactions_all_summary", ), + path( + "transactions/summary/account/", + views.transaction_all_account_summary, + name="transaction_all_account_summary", + ), + path( + "transactions/summary/currency/", + views.transaction_all_currency_summary, + name="transaction_all_currency_summary", + ), + path( + "transactions/summary/select//", + views.transaction_all_summary_select, + name="transaction_all_summary_select", + ), path( "transactions/actions/pay/", views.bulk_pay_transactions, diff --git a/app/apps/transactions/views/transactions.py b/app/apps/transactions/views/transactions.py index 42502c7..86a061f 100644 --- a/app/apps/transactions/views/transactions.py +++ b/app/apps/transactions/views/transactions.py @@ -314,9 +314,13 @@ def transaction_pay(request, transaction_id): @require_http_methods(["GET"]) def transaction_all_index(request): order = request.session.get("all_transactions_order", "default") + summary_tab = request.session.get("transaction_all_summary_tab", "currency") + f = TransactionsFilter(request.GET) return render( - request, "transactions/pages/transactions.html", {"filter": f, "order": order} + request, + "transactions/pages/transactions.html", + {"filter": f, "order": order, "summary_tab": summary_tab}, ) @@ -382,16 +386,74 @@ def transaction_all_summary(request): account_percentages = calculate_percentage_distribution(account_data) context = { - "income_current": remove_falsey_entries(currency_data, "income_current"), - "income_projected": remove_falsey_entries(currency_data, "income_projected"), - "expense_current": remove_falsey_entries(currency_data, "expense_current"), - "expense_projected": remove_falsey_entries(currency_data, "expense_projected"), - "total_current": remove_falsey_entries(currency_data, "total_current"), - "total_final": remove_falsey_entries(currency_data, "total_final"), - "total_projected": remove_falsey_entries(currency_data, "total_projected"), + "currency_data": currency_data, "currency_percentages": currency_percentages, "account_data": account_data, "account_percentages": account_percentages, } return render(request, "transactions/fragments/summary.html", context) + + +@only_htmx +@login_required +@require_http_methods(["GET"]) +def transaction_all_account_summary(request): + transactions = Transaction.objects.prefetch_related( + "account", + "account__group", + "category", + "tags", + "account__exchange_currency", + "account__currency", + "installment_plan", + ).all() + + f = TransactionsFilter(request.GET, queryset=transactions) + + account_data = calculate_account_totals(transactions_queryset=f.qs.all()) + account_percentages = calculate_percentage_distribution(account_data) + + context = { + "account_data": account_data, + "account_percentages": account_percentages, + } + + return render(request, "transactions/fragments/all_account_summary.html", context) + + +@only_htmx +@login_required +@require_http_methods(["GET"]) +def transaction_all_currency_summary(request): + transactions = Transaction.objects.prefetch_related( + "account", + "account__group", + "category", + "tags", + "account__exchange_currency", + "account__currency", + "installment_plan", + ).all() + + f = TransactionsFilter(request.GET, queryset=transactions) + + currency_data = calculate_currency_totals(f.qs.all(), ignore_empty=True) + currency_percentages = calculate_percentage_distribution(currency_data) + + context = { + "currency_data": currency_data, + "currency_percentages": currency_percentages, + } + + return render(request, "transactions/fragments/all_currency_summary.html", context) + + +@login_required +@require_http_methods(["GET"]) +def transaction_all_summary_select(request, selected): + request.session["transaction_all_summary_tab"] = selected + + return HttpResponse( + status=204, + ) diff --git a/app/templates/cotton/ui/account_card.html b/app/templates/cotton/ui/account_card.html new file mode 100644 index 0000000..49e2670 --- /dev/null +++ b/app/templates/cotton/ui/account_card.html @@ -0,0 +1,184 @@ +{% load tools %} +{% load i18n %} +
+
+ {% if account.account.group %} +
+ {{ account.account.group }} +
+ {% endif %} +
+ {{ account.account.name }} +
+
+
+
{% translate 'projected income' %}
+
+
+
+ +
+
+ {% if account.exchanged and account.exchanged.income_projected %} +
+ +
+ {% endif %} +
+
+
{% translate 'projected expenses' %}
+
+
+
+
+ +
+
+
+ {% if account.exchanged and account.exchanged.expense_projected %} +
+ +
+ {% endif %} +
+
+
{% translate 'projected total' %}
+
+
+
+ +
+
+ {% if account.exchanged.total_projected and account.exchanged.total_projected %} +
+ +
+ {% endif %} +
+
+
+
{% translate 'current income' %}
+
+
+
+ +
+
+ {% if account.exchanged and account.exchanged.income_current %} +
+ +
+ {% endif %} +
+
+
{% translate 'current expenses' %}
+
+
+
+ +
+
+ {% if account.exchanged and account.exchanged.expense_current %} +
+ +
+ {% endif %} +
+
+
{% translate 'current total' %}
+
+
+
+ +
+
+ {% if account.exchanged and account.exchanged.total_current %} +
+ +
+ {% endif %} +
+
+
+
+
{% translate 'final total' %}
+
+
+
+ +
+
+ {% if account.exchanged and account.exchanged.total_final %} +
+ +
+ {% endif %} +
+ {% with p=percentages|get_dict_item:account_id %} +
+ +
+ {% endwith %} +
+
diff --git a/app/templates/cotton/ui/currency_card.html b/app/templates/cotton/ui/currency_card.html new file mode 100644 index 0000000..7bd2faf --- /dev/null +++ b/app/templates/cotton/ui/currency_card.html @@ -0,0 +1,182 @@ +{% load tools %} +{% load i18n %} +
+
+
+ {{ currency.currency.code }} +
+
+ {{ currency.currency.name }} +
+
+
+
{% translate 'projected income' %}
+
+
+
+ +
+
+ {% if currency.exchanged and currency.exchanged.income_projected %} +
+ +
+ {% endif %} +
+
+
{% translate 'projected expenses' %}
+
+
+
+
+ +
+
+
+ {% if currency.exchanged and currency.exchanged.expense_projected %} +
+ +
+ {% endif %} +
+
+
{% translate 'projected total' %}
+
+
+
+ +
+
+ {% if currency.exchanged.total_projected and currency.exchanged.total_projected %} +
+ +
+ {% endif %} +
+
+
+
{% translate 'current income' %}
+
+
+
+ +
+
+ {% if currency.exchanged and currency.exchanged.income_current %} +
+ +
+ {% endif %} +
+
+
{% translate 'current expenses' %}
+
+
+
+ +
+
+ {% if currency.exchanged and currency.exchanged.expense_current %} +
+ +
+ {% endif %} +
+
+
{% translate 'current total' %}
+
+
+
+ +
+
+ {% if currency.exchanged and currency.exchanged.total_current %} +
+ +
+ {% endif %} +
+
+
+
+
{% translate 'final total' %}
+
+
+
+ +
+
+ {% if currency.exchanged and currency.exchanged.total_final %} +
+ +
+ {% endif %} +
+ {% with p=percentages|get_dict_item:currency_id %} +
+ +
+ {% endwith %} +
+
diff --git a/app/templates/cotton/ui/transactions_action_bar.html b/app/templates/cotton/ui/transactions_action_bar.html index 4eeebde..df6b095 100644 --- a/app/templates/cotton/ui/transactions_action_bar.html +++ b/app/templates/cotton/ui/transactions_action_bar.html @@ -1,16 +1,18 @@ {% load i18n %}
diff --git a/app/templates/monthly_overview/fragments/monthly_account_summary.html b/app/templates/monthly_overview/fragments/monthly_account_summary.html new file mode 100644 index 0000000..0d197c6 --- /dev/null +++ b/app/templates/monthly_overview/fragments/monthly_account_summary.html @@ -0,0 +1,17 @@ +{% load tools %} +{% load i18n %} +{% load currency_display %} + +
+ {% for account_id, account in account_data.items %} +
+ +
+ {% empty %} +
+ + {% endfor %} +
+
diff --git a/app/templates/monthly_overview/fragments/monthly_currency_summary.html b/app/templates/monthly_overview/fragments/monthly_currency_summary.html new file mode 100644 index 0000000..ef3630b --- /dev/null +++ b/app/templates/monthly_overview/fragments/monthly_currency_summary.html @@ -0,0 +1,16 @@ +{% load tools %} +{% load i18n %} +{% load currency_display %} +
+ {% for currency_id, currency in currency_data.items %} +
+ +
+ {% empty %} +
+ +
+ {% endfor %} +
diff --git a/app/templates/monthly_overview/fragments/monthly_summary.html b/app/templates/monthly_overview/fragments/monthly_summary.html index 5d36e65..f6f26c6 100644 --- a/app/templates/monthly_overview/fragments/monthly_summary.html +++ b/app/templates/monthly_overview/fragments/monthly_summary.html @@ -1,6 +1,6 @@ {% load i18n %} {% load currency_display %} -
+
{# Daily Spending#}
@@ -252,6 +252,7 @@
+ {% if percentages %}
{% for p in percentages.values %} @@ -260,4 +261,5 @@ {% endfor %}
+ {% endif %}
diff --git a/app/templates/monthly_overview/pages/overview.html b/app/templates/monthly_overview/pages/overview.html index 4933d62..f6b6d01 100644 --- a/app/templates/monthly_overview/pages/overview.html +++ b/app/templates/monthly_overview/pages/overview.html @@ -13,89 +13,172 @@ {% endblock %} {% block content %} -
-
-{# Date picker#} -
-
- -
-
- {{ month|month_name }} {{ year }} -
-
- - - -
-
-{# Action buttons#} -
- -
-
-{# Monthly summary#} -
-
-
-
-
-
-
-
-{# Filter transactions button #} - +
+
+ {# Date picker#} +
+
+
-{# Ordering button#} -
-
- - +
+ {{ month|month_name }} {{ year }} +
+
+ + + +
+
+ {# Action buttons#} +
+ +
+
+ {# Monthly summary#} +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
-{# Filter transactions form#} -
-
-
+
+
+ {# Filter transactions button #} + +
+ {# Ordering button#} +
+
+ + +
+
+
+ {# Filter transactions form#} +
+
+ - {% crispy filter.form %} - - + id="filter"> + {% crispy filter.form %} + + +
+
+ {# Transactions list#} +
-
-{# Transactions list#} -
-
{% endblock %} diff --git a/app/templates/transactions/fragments/all_account_summary.html b/app/templates/transactions/fragments/all_account_summary.html new file mode 100644 index 0000000..0d197c6 --- /dev/null +++ b/app/templates/transactions/fragments/all_account_summary.html @@ -0,0 +1,17 @@ +{% load tools %} +{% load i18n %} +{% load currency_display %} + +
+ {% for account_id, account in account_data.items %} +
+ +
+ {% empty %} +
+ + {% endfor %} +
+
diff --git a/app/templates/transactions/fragments/all_currency_summary.html b/app/templates/transactions/fragments/all_currency_summary.html new file mode 100644 index 0000000..ef3630b --- /dev/null +++ b/app/templates/transactions/fragments/all_currency_summary.html @@ -0,0 +1,16 @@ +{% load tools %} +{% load i18n %} +{% load currency_display %} +
+ {% for currency_id, currency in currency_data.items %} +
+ +
+ {% empty %} +
+ +
+ {% endfor %} +
diff --git a/app/templates/transactions/fragments/summary.html b/app/templates/transactions/fragments/summary.html index d7a3369..34bd883 100644 --- a/app/templates/transactions/fragments/summary.html +++ b/app/templates/transactions/fragments/summary.html @@ -1,431 +1,47 @@ {% load tools %} {% load i18n %} {% load currency_display %} -