Files
WYGIWYH/app/apps/yearly_overview/views.py
Herculino Trotta d20897a28a more changes
2024-10-13 12:10:50 -03:00

469 lines
15 KiB
Python

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,
# },
# )