diff --git a/app/WYGIWYH/settings.py b/app/WYGIWYH/settings.py index 545f7d7..94a1abd 100644 --- a/app/WYGIWYH/settings.py +++ b/app/WYGIWYH/settings.py @@ -68,6 +68,7 @@ INSTALLED_APPS = [ "cachalot", "rest_framework", "drf_spectacular", + "django_cotton", ] MIDDLEWARE = [ diff --git a/app/apps/transactions/templatetags/currency_display.py b/app/apps/transactions/templatetags/currency_display.py index cdbb28e..2da28cc 100644 --- a/app/apps/transactions/templatetags/currency_display.py +++ b/app/apps/transactions/templatetags/currency_display.py @@ -16,26 +16,6 @@ def _format_string(prefix, amount, decimal_places, suffix): return f"{prefix}{formatted_amount}{suffix}" -@register.simple_tag(name="transaction_amount") -def transaction_currency(transaction: Transaction): - prefix = transaction.account.currency.prefix - amount = transaction.amount - decimal_places = transaction.account.currency.decimal_places - suffix = transaction.account.currency.suffix - - return _format_string(prefix, amount, decimal_places, suffix) - - -@register.simple_tag(name="entry_amount") -def entry_currency(entry): - prefix = entry["prefix"] - amount = entry["amount"] - decimal_places = entry["decimal_places"] - suffix = entry["suffix"] - - return _format_string(prefix, amount, decimal_places, suffix) - - @register.simple_tag(name="currency_display") def currency_display(amount, prefix, suffix, decimal_places): return _format_string(prefix, amount, decimal_places, suffix) diff --git a/app/apps/yearly_overview/views.py b/app/apps/yearly_overview/views.py index bba95d1..1a06eee 100644 --- a/app/apps/yearly_overview/views.py +++ b/app/apps/yearly_overview/views.py @@ -20,229 +20,79 @@ def index(request): return redirect(to="yearly_overview", year=now.year) -# def yearly_overview(request, year: int): -# transactions = Transaction.objects.filter(date__year=year) -# -# monthly_data = ( -# transactions.annotate(month=TruncMonth("date")) -# .values( -# "month", -# "account__id", -# "account__name", -# "account__group__name", -# "account__currency__code", -# "account__currency__suffix", -# "account__currency__prefix", -# "account__currency__decimal_places", -# ) -# .annotate( -# income_paid=Coalesce( -# Sum( -# Case( -# When( -# type=Transaction.Type.INCOME, is_paid=True, then=F("amount") -# ), -# default=Value(Decimal("0")), -# output_field=DecimalField(), -# ) -# ), -# Value(Decimal("0")), -# output_field=DecimalField(), -# ), -# expense_paid=Coalesce( -# Sum( -# Case( -# When( -# type=Transaction.Type.EXPENSE, -# is_paid=True, -# then=F("amount"), -# ), -# default=Value(Decimal("0")), -# output_field=DecimalField(), -# ) -# ), -# Value(Decimal("0")), -# output_field=DecimalField(), -# ), -# income_unpaid=Coalesce( -# Sum( -# Case( -# When( -# type=Transaction.Type.INCOME, -# is_paid=False, -# then=F("amount"), -# ), -# default=Value(Decimal("0")), -# output_field=DecimalField(), -# ) -# ), -# Value(Decimal("0")), -# output_field=DecimalField(), -# ), -# expense_unpaid=Coalesce( -# Sum( -# Case( -# When( -# type=Transaction.Type.EXPENSE, -# is_paid=False, -# then=F("amount"), -# ), -# default=Value(Decimal("0")), -# output_field=DecimalField(), -# ) -# ), -# Value(Decimal("0")), -# output_field=DecimalField(), -# ), -# ) -# .annotate( -# balance_unpaid=F("income_unpaid") - F("expense_unpaid"), -# balance_paid=F("income_paid") - F("expense_paid"), -# balance_total=F("income_paid") -# + F("income_unpaid") -# - F("expense_paid") -# - F("expense_unpaid"), -# ) -# .order_by("month", "account__group__name") -# ) -# -# # Create a list of all months in the year -# all_months = [date(year, month, 1) for month in range(1, 13)] -# -# # Create a dictionary to store the final result -# result = { -# month: { -# "income_paid": [], -# "expense_paid": [], -# "income_unpaid": [], -# "expense_unpaid": [], -# "balance_unpaid": [], -# "balance_paid": [], -# "balance_total": [], -# } -# for month in all_months -# } -# -# # Fill in the data -# for entry in monthly_data: -# month = entry["month"] -# account_info = { -# "id": entry["account__id"], -# "name": entry["account__name"], -# "currency": entry["account__currency__code"], -# "suffix": entry["account__currency__suffix"], -# "prefix": entry["account__currency__prefix"], -# "decimal_places": entry["account__currency__decimal_places"], -# "group": entry["account__group__name"], -# } -# -# for field in [ -# "income_paid", -# "expense_paid", -# "income_unpaid", -# "expense_unpaid", -# "balance_unpaid", -# "balance_paid", -# "balance_total", -# ]: -# result[month][field].append( -# {"account": account_info, "amount": entry[field]} -# ) -# -# # Fill in missing months with empty lists -# for month in all_months: -# if not any(result[month].values()): -# result[month] = { -# "income_paid": [], -# "expense_paid": [], -# "income_unpaid": [], -# "expense_unpaid": [], -# "balance_unpaid": [], -# "balance_paid": [], -# "balance_total": [], -# } -# -# from pprint import pprint -# -# pprint(result) -# -# return render( -# request, -# "yearly_overview/pages/overview2.html", -# context={ -# "year": year, -# # "next_month": next_month, -# # "next_year": next_year, -# # "previous_month": previous_month, -# # "previous_year": previous_year, -# "data": result, -# }, -# ) - - def yearly_overview(request, year: int): - # First, let's create a base queryset for the given year - base_queryset = Transaction.objects.filter(date__year=year) + transactions = Transaction.objects.filter(date__year=year) - # Create a list of all months in the year - months = [f"{year}-{month:02d}-01" for month in range(1, 13)] - - # Create the queryset with all the required annotations - queryset = ( - base_queryset.annotate(month=TruncMonth("date")) - .values("month", "account__group__name") + monthly_data = ( + transactions.annotate(month=TruncMonth("date")) + .values( + "month", + "account__id", + "account__name", + "account__group__name", + "account__currency__code", + "account__currency__suffix", + "account__currency__prefix", + "account__currency__decimal_places", + ) .annotate( income_paid=Coalesce( Sum( Case( When( - Q(type=Transaction.Type.INCOME, is_paid=True), - then=F("amount"), + type=Transaction.Type.INCOME, is_paid=True, then=F("amount") ), - default=Value(0), + default=Value(Decimal("0")), output_field=DecimalField(), ) ), - Value(0, output_field=DecimalField()), + Value(Decimal("0")), + output_field=DecimalField(), ), expense_paid=Coalesce( Sum( Case( When( - Q(type=Transaction.Type.EXPENSE, is_paid=True), + type=Transaction.Type.EXPENSE, + is_paid=True, then=F("amount"), ), - default=Value(0), + default=Value(Decimal("0")), output_field=DecimalField(), ) ), - Value(0, output_field=DecimalField()), + Value(Decimal("0")), + output_field=DecimalField(), ), income_unpaid=Coalesce( Sum( Case( When( - Q(type=Transaction.Type.INCOME, is_paid=False), + type=Transaction.Type.INCOME, + is_paid=False, then=F("amount"), ), - default=Value(0), + default=Value(Decimal("0")), output_field=DecimalField(), ) ), - Value(0, output_field=DecimalField()), + Value(Decimal("0")), + output_field=DecimalField(), ), expense_unpaid=Coalesce( Sum( Case( When( - Q(type=Transaction.Type.EXPENSE, is_paid=False), + type=Transaction.Type.EXPENSE, + is_paid=False, then=F("amount"), ), - default=Value(0), + default=Value(Decimal("0")), output_field=DecimalField(), ) ), - Value(0, output_field=DecimalField()), + Value(Decimal("0")), + output_field=DecimalField(), ), ) .annotate( @@ -256,45 +106,65 @@ def yearly_overview(request, year: int): .order_by("month", "account__group__name") ) - # Create a dictionary to store results - results = {month: {} for month in months} + # Create a list of all months in the year + all_months = [date(year, month, 1) for month in range(1, 13)] - # Populate the results dictionary - for entry in queryset: + # Create a dictionary to store the final result + result = { + month: { + "income_paid": [], + "expense_paid": [], + "income_unpaid": [], + "expense_unpaid": [], + "balance_unpaid": [], + "balance_paid": [], + "balance_total": [], + } + for month in all_months + } + + # Fill in the data + for entry in monthly_data: month = entry["month"] - account_group = entry["account__group__name"] + account_info = { + "id": entry["account__id"], + "name": entry["account__name"], + "currency": entry["account__currency__code"], + "suffix": entry["account__currency__suffix"], + "prefix": entry["account__currency__prefix"], + "decimal_places": entry["account__currency__decimal_places"], + "group": entry["account__group__name"], + } - if account_group not in results[month]: - results[month][account_group] = { - "income_paid": entry["income_paid"], - "expense_paid": entry["expense_paid"], - "income_unpaid": entry["income_unpaid"], - "expense_unpaid": entry["expense_unpaid"], - "balance_unpaid": entry["balance_unpaid"], - "balance_paid": entry["balance_paid"], - "balance_total": entry["balance_total"], + for field in [ + "income_paid", + "expense_paid", + "income_unpaid", + "expense_unpaid", + "balance_unpaid", + "balance_paid", + "balance_total", + ]: + result[month][field].append( + {"account": account_info, "amount": entry[field]} + ) + + # Fill in missing months with empty lists + for month in all_months: + if not any(result[month].values()): + result[month] = { + "income_paid": [], + "expense_paid": [], + "income_unpaid": [], + "expense_unpaid": [], + "balance_unpaid": [], + "balance_paid": [], + "balance_total": [], } - else: - # If the account group already exists, update the values - for key in [ - "income_paid", - "expense_paid", - "income_unpaid", - "expense_unpaid", - "balance_unpaid", - "balance_paid", - "balance_total", - ]: - results[month][account_group][key] += entry[key] - - # Replace empty months with "-" - for month in results: - if not results[month]: - results[month] = "-" from pprint import pprint - pprint(results) + pprint(result) return render( request, @@ -305,11 +175,142 @@ def yearly_overview(request, year: int): # "next_year": next_year, # "previous_month": previous_month, # "previous_year": previous_year, - "data": results, + "data": result, }, ) +# def yearly_overview(request, year: int): +# # First, let's create a base queryset for the given year +# base_queryset = Transaction.objects.filter(date__year=year) +# +# # Create a list of all months in the year +# months = [month for month in range(1, 13)] +# +# # Create the queryset with all the required annotations +# queryset = ( +# base_queryset.annotate(month=TruncMonth("date")) +# .values("month", "account__group__name") +# .annotate( +# income_paid=Coalesce( +# Sum( +# Case( +# When( +# Q(type=Transaction.Type.INCOME, is_paid=True), +# then=F("amount"), +# ), +# default=Value(0), +# output_field=DecimalField(), +# ) +# ), +# Value(0, output_field=DecimalField()), +# ), +# expense_paid=Coalesce( +# Sum( +# Case( +# When( +# Q(type=Transaction.Type.EXPENSE, is_paid=True), +# then=F("amount"), +# ), +# default=Value(0), +# output_field=DecimalField(), +# ) +# ), +# Value(0, output_field=DecimalField()), +# ), +# income_unpaid=Coalesce( +# Sum( +# Case( +# When( +# Q(type=Transaction.Type.INCOME, is_paid=False), +# then=F("amount"), +# ), +# default=Value(0), +# output_field=DecimalField(), +# ) +# ), +# Value(0, output_field=DecimalField()), +# ), +# expense_unpaid=Coalesce( +# Sum( +# Case( +# When( +# Q(type=Transaction.Type.EXPENSE, is_paid=False), +# then=F("amount"), +# ), +# default=Value(0), +# output_field=DecimalField(), +# ) +# ), +# Value(0, output_field=DecimalField()), +# ), +# ) +# .annotate( +# balance_unpaid=F("income_unpaid") - F("expense_unpaid"), +# balance_paid=F("income_paid") - F("expense_paid"), +# balance_total=F("income_paid") +# + F("income_unpaid") +# - F("expense_paid") +# - F("expense_unpaid"), +# ) +# .order_by("month", "account__group__name") +# ) +# +# # Create a dictionary to store results +# results = {month: {} for month in months} +# print(results) +# +# # Populate the results dictionary +# for entry in queryset: +# month = int(entry["month"].strftime("%m")) +# account_group = entry["account__group__name"] +# +# if account_group not in results[month]: +# results[month][account_group] = { +# "income_paid": entry["income_paid"], +# "expense_paid": entry["expense_paid"], +# "income_unpaid": entry["income_unpaid"], +# "expense_unpaid": entry["expense_unpaid"], +# "balance_unpaid": entry["balance_unpaid"], +# "balance_paid": entry["balance_paid"], +# "balance_total": entry["balance_total"], +# } +# else: +# # If the account group already exists, update the values +# for key in [ +# "income_paid", +# "expense_paid", +# "income_unpaid", +# "expense_unpaid", +# "balance_unpaid", +# "balance_paid", +# "balance_total", +# ]: +# results[month][account_group][key] += entry[key] +# +# # Replace empty months with "-" +# for month in results: +# if not results[month]: +# results[month] = "-" +# +# from pprint import pprint +# +# pprint(results) +# +# return render( +# request, +# "yearly_overview/pages/overview2.html", +# context={ +# "year": year, +# # "next_month": next_month, +# # "next_year": next_year, +# # "previous_month": previous_month, +# # "previous_year": previous_year, +# "data": results, +# }, +# ) + + # def yearly_overview(request, year: int): # transactions = Transaction.objects.filter(reference_date__year=year) # diff --git a/app/templates/cotton/amount/display.html b/app/templates/cotton/amount/display.html new file mode 100644 index 0000000..e0513ed --- /dev/null +++ b/app/templates/cotton/amount/display.html @@ -0,0 +1,7 @@ +{% load currency_display %} + +
+
+
+
diff --git a/app/templates/monthly_overview/fragments/monthly_summary.html b/app/templates/monthly_overview/fragments/monthly_summary.html index 7ac6b3b..5b57cd6 100644 --- a/app/templates/monthly_overview/fragments/monthly_summary.html +++ b/app/templates/monthly_overview/fragments/monthly_summary.html @@ -16,7 +16,11 @@
{% for entry in totals.daily_spending_allowance %} -
+ {% empty %}
-
{% endfor %} @@ -40,7 +44,11 @@
{% for entry in totals.paid_income %} -
+ {% empty %}
-
{% endfor %} @@ -53,7 +61,11 @@
{% for entry in totals.projected_income %} -
+ {% empty %}
-
{% endfor %} @@ -77,7 +89,11 @@
{% for entry in totals.paid_expenses %} -
+ {% empty %}
-
{% endfor %} @@ -90,7 +106,11 @@
{% for entry in totals.projected_expenses %} -
+ {% empty %}
-
{% endfor %} @@ -114,7 +134,11 @@
{% for entry in totals.total_current %} -
+ {% empty %}
-
{% endfor %} @@ -126,7 +150,11 @@
{% for entry in totals.total_projected %} -
+ {% empty %}
-
{% endfor %} @@ -136,7 +164,11 @@
{% for entry in totals.total_final %} -
+ {% empty %}
-
{% endfor %} diff --git a/app/templates/net_worth/net_worth.html b/app/templates/net_worth/net_worth.html index bb9ff2a..996f92e 100644 --- a/app/templates/net_worth/net_worth.html +++ b/app/templates/net_worth/net_worth.html @@ -26,7 +26,12 @@
{{ currency.name }}
-
+
{% endfor %} @@ -56,12 +61,21 @@
{{ account_data.name }}
-
+
{% if account_data.exchange %} -
+ {% endif %} {% endfor %} {% else %} @@ -70,13 +84,22 @@
{{ account_data.name }}
-
- {% if account_data.exchange %} -
- {% endif %} +
+ {% if account_data.exchange %} + + {% endif %} {% endfor %} {% endif %} {% endfor %} diff --git a/app/templates/transactions/fragments/item.html b/app/templates/transactions/fragments/item.html index 39bddbf..404eb6c 100644 --- a/app/templates/transactions/fragments/item.html +++ b/app/templates/transactions/fragments/item.html @@ -66,15 +66,23 @@
-
-
-
+ {# Exchange Rate#} {% with exchanged=transaction.exchanged_amount %} {% if exchanged %} -
-
+ {% endif %} {% endwith %}
{{ transaction.account.name }}
diff --git a/app/templates/yearly_overview/fragments/monthly_summary.html b/app/templates/yearly_overview/fragments/monthly_summary.html index 7ac6b3b..5b57cd6 100644 --- a/app/templates/yearly_overview/fragments/monthly_summary.html +++ b/app/templates/yearly_overview/fragments/monthly_summary.html @@ -16,7 +16,11 @@
{% for entry in totals.daily_spending_allowance %} -
+ {% empty %}
-
{% endfor %} @@ -40,7 +44,11 @@
{% for entry in totals.paid_income %} -
+ {% empty %}
-
{% endfor %} @@ -53,7 +61,11 @@
{% for entry in totals.projected_income %} -
+ {% empty %}
-
{% endfor %} @@ -77,7 +89,11 @@
{% for entry in totals.paid_expenses %} -
+ {% empty %}
-
{% endfor %} @@ -90,7 +106,11 @@
{% for entry in totals.projected_expenses %} -
+ {% empty %}
-
{% endfor %} @@ -114,7 +134,11 @@
{% for entry in totals.total_current %} -
+ {% empty %}
-
{% endfor %} @@ -126,7 +150,11 @@
{% for entry in totals.total_projected %} -
+ {% empty %}
-
{% endfor %} @@ -136,7 +164,11 @@
{% for entry in totals.total_final %} -
+ {% empty %}
-
{% endfor %} diff --git a/app/templates/yearly_overview/pages/overview2.html b/app/templates/yearly_overview/pages/overview2.html index fcc62cb..72e3689 100644 --- a/app/templates/yearly_overview/pages/overview2.html +++ b/app/templates/yearly_overview/pages/overview2.html @@ -15,6 +15,34 @@ {% block content %}
+
+ Card image +
+
Card Title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+ +
{#
#} {# Date picker#} {#
#} diff --git a/requirements.txt b/requirements.txt index 9f9d205..3dac577 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,6 +11,7 @@ django-filter==24.3 django-anymail[sendinblue]==10.2 django-debug-toolbar==4.3.0 django-cachalot~=2.6.3 +django-cotton~=1.2.1 djangorestframework~=3.15.2 drf-spectacular~=0.27.2