167 lines
4.0 KiB
Python
167 lines
4.0 KiB
Python
from decimal import Decimal, InvalidOperation
|
|
|
|
from django.template.loader import render_to_string
|
|
from liveview import liveview_handler, send
|
|
|
|
from app.yearly.models import PlannedExpense
|
|
|
|
|
|
MONTH_LABELS = [
|
|
"January",
|
|
"February",
|
|
"March",
|
|
"April",
|
|
"May",
|
|
"June",
|
|
"July",
|
|
"August",
|
|
"September",
|
|
"October",
|
|
"November",
|
|
"December",
|
|
]
|
|
|
|
|
|
def _render_planned_tables(year, editing_id=None):
|
|
months_data = []
|
|
for m in range(1, 13):
|
|
items = PlannedExpense.objects.filter(year=year, month=m)
|
|
total = sum(i.amount for i in items)
|
|
months_data.append(
|
|
{
|
|
"month": m,
|
|
"label": MONTH_LABELS[m - 1],
|
|
"items": items,
|
|
"total": total,
|
|
}
|
|
)
|
|
grand_total = sum(md["total"] for md in months_data)
|
|
|
|
# Clone years
|
|
available_years = (
|
|
PlannedExpense.objects.exclude(year=year)
|
|
.values_list("year", flat=True)
|
|
.distinct()
|
|
.order_by("-year")
|
|
)
|
|
|
|
return render_to_string(
|
|
"pages/yearly/partials/planned_tables.html",
|
|
{
|
|
"months_data": months_data,
|
|
"year": year,
|
|
"grand_total": grand_total,
|
|
"editing_id": editing_id,
|
|
"clone_years": list(available_years),
|
|
},
|
|
)
|
|
|
|
|
|
@liveview_handler("add_planned_expense")
|
|
def add_planned_expense(consumer, content):
|
|
form = content.get("form", {})
|
|
year = int(form.get("year", 0))
|
|
month = int(form.get("pe_month", 0))
|
|
concept = form.get("pe_concept", "").strip()
|
|
amount_raw = form.get("pe_amount", "").replace(",", ".")
|
|
|
|
if not concept or not amount_raw or not year or not month:
|
|
return
|
|
|
|
try:
|
|
amount = Decimal(amount_raw)
|
|
except (InvalidOperation, ValueError):
|
|
return
|
|
|
|
PlannedExpense.objects.create(
|
|
year=year, month=month, concept=concept, amount=amount
|
|
)
|
|
|
|
html = _render_planned_tables(year)
|
|
send(consumer, {"target": "#planned-expenses", "html": html})
|
|
|
|
|
|
@liveview_handler("edit_planned_expense")
|
|
def edit_planned_expense(consumer, content):
|
|
data = content.get("data", {})
|
|
pe_id = data.get("data_id", "")
|
|
year = int(data.get("data_year", 0))
|
|
|
|
if not pe_id or not year:
|
|
return
|
|
|
|
html = _render_planned_tables(year, editing_id=int(pe_id))
|
|
send(consumer, {"target": "#planned-expenses", "html": html})
|
|
|
|
|
|
@liveview_handler("save_planned_expense")
|
|
def save_planned_expense(consumer, content):
|
|
form = content.get("form", {})
|
|
pe_id = form.get("pe_id", "")
|
|
year = int(form.get("year", 0))
|
|
month = int(form.get("pe_month", 0))
|
|
concept = form.get("pe_concept", "").strip()
|
|
amount_raw = form.get("pe_amount", "").replace(",", ".")
|
|
|
|
if not pe_id or not concept or not amount_raw or not year or not month:
|
|
return
|
|
|
|
try:
|
|
amount = Decimal(amount_raw)
|
|
pe = PlannedExpense.objects.get(id=pe_id)
|
|
pe.month = month
|
|
pe.concept = concept
|
|
pe.amount = amount
|
|
pe.save()
|
|
except (InvalidOperation, ValueError, PlannedExpense.DoesNotExist):
|
|
return
|
|
|
|
html = _render_planned_tables(year)
|
|
send(consumer, {"target": "#planned-expenses", "html": html})
|
|
|
|
|
|
@liveview_handler("cancel_edit_planned_expense")
|
|
def cancel_edit_planned_expense(consumer, content):
|
|
data = content.get("data", {})
|
|
year = int(data.get("data_year", 0))
|
|
|
|
if not year:
|
|
return
|
|
|
|
html = _render_planned_tables(year)
|
|
send(consumer, {"target": "#planned-expenses", "html": html})
|
|
|
|
|
|
@liveview_handler("delete_planned_expense")
|
|
def delete_planned_expense(consumer, content):
|
|
data = content.get("data", {})
|
|
pe_id = data.get("data_id", "")
|
|
year = int(data.get("data_year", 0))
|
|
|
|
if not pe_id or not year:
|
|
return
|
|
|
|
PlannedExpense.objects.filter(id=pe_id).delete()
|
|
|
|
html = _render_planned_tables(year)
|
|
send(consumer, {"target": "#planned-expenses", "html": html})
|
|
|
|
|
|
@liveview_handler("clone_planned_expenses")
|
|
def clone_planned_expenses(consumer, content):
|
|
form = content.get("form", {})
|
|
source_year = int(form.get("clone_pe_source", 0))
|
|
year = int(form.get("year", 0))
|
|
|
|
if not source_year or not year:
|
|
return
|
|
|
|
source_items = PlannedExpense.objects.filter(year=source_year)
|
|
for item in source_items:
|
|
PlannedExpense.objects.create(
|
|
year=year, month=item.month, concept=item.concept, amount=item.amount
|
|
)
|
|
|
|
html = _render_planned_tables(year)
|
|
send(consumer, {"target": "#planned-expenses", "html": html})
|