more changes

This commit is contained in:
Herculino Trotta
2024-10-13 12:10:50 -03:00
parent 1717d8a94e
commit d20897a28a
33 changed files with 1552 additions and 153 deletions

View File

View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class YearlyOverviewConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "apps.yearly_overview"

View File

@@ -0,0 +1,12 @@
from django.urls import path
from . import views
urlpatterns = [
path("yearly/", views.index, name="yearly_index"),
path(
"yearly/<int:year>/",
views.yearly_overview,
name="yearly_overview",
),
]

View File

@@ -0,0 +1,468 @@
from datetime import date
from decimal import Decimal
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.utils import timezone
from django.db.models import Sum, F, Q, Value, CharField, DecimalField
from django.db.models.functions import TruncMonth, Coalesce
from django.db.models.expressions import Case, When
from django.db.models.functions import Concat
from apps.transactions.models import Transaction
# Create your views here.
@login_required
def index(request):
now = timezone.localdate(timezone.now())
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)
# 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")
.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}
# Populate the results dictionary
for entry in queryset:
month = entry["month"]
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)
#
# monthly_data = (
# transactions.annotate(month=TruncMonth("reference_date"))
# .values(
# "month",
# "account__currency__code",
# "account__currency__prefix",
# "account__currency__suffix",
# "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__currency__code")
# )
#
# # 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"]
# currency_code = entry["account__currency__code"]
# prefix = entry["account__currency__prefix"]
# suffix = entry["account__currency__suffix"]
# decimal_places = entry["account__currency__decimal_places"]
#
# for field in [
# "income_paid",
# "expense_paid",
# "income_unpaid",
# "expense_unpaid",
# "balance_unpaid",
# "balance_paid",
# "balance_total",
# ]:
# result[month][field].append(
# {
# "code": currency_code,
# "prefix": prefix,
# "suffix": suffix,
# "decimal_places": decimal_places,
# "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/overview.html",
# context={
# "year": year,
# # "next_month": next_month,
# # "next_year": next_year,
# # "previous_month": previous_month,
# # "previous_year": previous_year,
# "totals": result,
# },
# )