- Remove user ForeignKey from all 7 models (single-user app) - Update all views, handlers, forms, admin, API, seed, and tests - Add MonthlyGoal model with goals and promises sections - Goals/promises: add, toggle (strikethrough), delete via LiveView
260 lines
6.3 KiB
Python
260 lines
6.3 KiB
Python
from django.template.loader import render_to_string
|
|
from liveview import liveview_handler, send
|
|
|
|
from app.expenses.models import Category, FixedExpenseConcept, Subcategory
|
|
|
|
|
|
def _render_categories(editing_category=None, editing_subcategory=None):
|
|
categories = Category.objects.prefetch_related("subcategories").all()
|
|
return render_to_string(
|
|
"pages/expenses/partials/categories_section.html",
|
|
{
|
|
"categories": categories,
|
|
"editing_category": editing_category,
|
|
"editing_subcategory": editing_subcategory,
|
|
},
|
|
)
|
|
|
|
|
|
def _render_fixed_expenses(editing_id=None):
|
|
fixed_expenses = FixedExpenseConcept.objects.all()
|
|
return render_to_string(
|
|
"pages/expenses/partials/fixed_expenses_section.html",
|
|
{"fixed_expenses": fixed_expenses, "editing_id": editing_id},
|
|
)
|
|
|
|
|
|
# --- Categories ---
|
|
|
|
|
|
@liveview_handler("add_category")
|
|
def add_category(consumer, content):
|
|
form = content.get("form", {})
|
|
name = form.get("cat_name", "").strip()
|
|
order = form.get("cat_order", "0")
|
|
|
|
if not name:
|
|
return
|
|
|
|
try:
|
|
order = int(order)
|
|
except ValueError:
|
|
order = 0
|
|
|
|
Category.objects.create(name=name, order=order)
|
|
html = _render_categories()
|
|
send(consumer, {"target": "#categories-section", "html": html})
|
|
|
|
|
|
@liveview_handler("edit_category")
|
|
def edit_category(consumer, content):
|
|
data = content.get("data", {})
|
|
cat_id = data.get("data_id", "")
|
|
if not cat_id:
|
|
return
|
|
|
|
try:
|
|
category = Category.objects.get(id=cat_id)
|
|
except Category.DoesNotExist:
|
|
return
|
|
|
|
html = _render_categories(editing_category=category.id)
|
|
send(consumer, {"target": "#categories-section", "html": html})
|
|
|
|
|
|
@liveview_handler("save_category")
|
|
def save_category(consumer, content):
|
|
form = content.get("form", {})
|
|
cat_id = form.get("cat_id", "")
|
|
name = form.get("cat_name", "").strip()
|
|
order = form.get("cat_order", "0")
|
|
|
|
if not cat_id or not name:
|
|
return
|
|
|
|
try:
|
|
category = Category.objects.get(id=cat_id)
|
|
category.name = name
|
|
category.order = int(order)
|
|
category.save()
|
|
except (Category.DoesNotExist, ValueError):
|
|
return
|
|
|
|
html = _render_categories()
|
|
send(consumer, {"target": "#categories-section", "html": html})
|
|
|
|
|
|
@liveview_handler("delete_category")
|
|
def delete_category(consumer, content):
|
|
data = content.get("data", {})
|
|
cat_id = data.get("data_id", "")
|
|
if not cat_id:
|
|
return
|
|
|
|
Category.objects.filter(id=cat_id).delete()
|
|
html = _render_categories()
|
|
send(consumer, {"target": "#categories-section", "html": html})
|
|
|
|
|
|
@liveview_handler("cancel_edit_settings")
|
|
def cancel_edit_settings(consumer, content):
|
|
data = content.get("data", {})
|
|
section = data.get("data_section", "categories")
|
|
|
|
if section == "fixed_expenses":
|
|
html = _render_fixed_expenses()
|
|
send(consumer, {"target": "#fixed-expenses-section", "html": html})
|
|
else:
|
|
html = _render_categories()
|
|
send(consumer, {"target": "#categories-section", "html": html})
|
|
|
|
|
|
# --- Subcategories ---
|
|
|
|
|
|
@liveview_handler("add_subcategory")
|
|
def add_subcategory(consumer, content):
|
|
form = content.get("form", {})
|
|
name = form.get("sub_name", "").strip()
|
|
order = form.get("sub_order", "0")
|
|
cat_id = form.get("sub_category_id", "")
|
|
|
|
if not name or not cat_id:
|
|
return
|
|
|
|
try:
|
|
category = Category.objects.get(id=cat_id)
|
|
order = int(order)
|
|
except (Category.DoesNotExist, ValueError):
|
|
return
|
|
|
|
Subcategory.objects.create(name=name, order=order, category=category)
|
|
html = _render_categories()
|
|
send(consumer, {"target": "#categories-section", "html": html})
|
|
|
|
|
|
@liveview_handler("edit_subcategory")
|
|
def edit_subcategory(consumer, content):
|
|
data = content.get("data", {})
|
|
sub_id = data.get("data_id", "")
|
|
if not sub_id:
|
|
return
|
|
|
|
try:
|
|
sub = Subcategory.objects.get(id=sub_id)
|
|
except Subcategory.DoesNotExist:
|
|
return
|
|
|
|
html = _render_categories(editing_subcategory=sub.id)
|
|
send(consumer, {"target": "#categories-section", "html": html})
|
|
|
|
|
|
@liveview_handler("save_subcategory")
|
|
def save_subcategory(consumer, content):
|
|
form = content.get("form", {})
|
|
sub_id = form.get("sub_id", "")
|
|
name = form.get("sub_name", "").strip()
|
|
order = form.get("sub_order", "0")
|
|
|
|
if not sub_id or not name:
|
|
return
|
|
|
|
try:
|
|
sub = Subcategory.objects.get(id=sub_id)
|
|
sub.name = name
|
|
sub.order = int(order)
|
|
sub.save()
|
|
except (Subcategory.DoesNotExist, ValueError):
|
|
return
|
|
|
|
html = _render_categories()
|
|
send(consumer, {"target": "#categories-section", "html": html})
|
|
|
|
|
|
@liveview_handler("delete_subcategory")
|
|
def delete_subcategory_handler(consumer, content):
|
|
data = content.get("data", {})
|
|
sub_id = data.get("data_id", "")
|
|
if not sub_id:
|
|
return
|
|
|
|
try:
|
|
sub = Subcategory.objects.get(id=sub_id)
|
|
if sub.order == 99:
|
|
return
|
|
other = Subcategory.objects.get(category=sub.category, order=99)
|
|
sub.expenses.update(subcategory=other)
|
|
sub.delete()
|
|
except Subcategory.DoesNotExist:
|
|
return
|
|
|
|
html = _render_categories()
|
|
send(consumer, {"target": "#categories-section", "html": html})
|
|
|
|
|
|
# --- Fixed Expenses ---
|
|
|
|
|
|
@liveview_handler("add_fixed_expense")
|
|
def add_fixed_expense(consumer, content):
|
|
form = content.get("form", {})
|
|
name = form.get("fe_name", "").strip()
|
|
order = form.get("fe_order", "0")
|
|
|
|
if not name:
|
|
return
|
|
|
|
try:
|
|
order = int(order)
|
|
except ValueError:
|
|
order = 0
|
|
|
|
FixedExpenseConcept.objects.create(name=name, order=order)
|
|
html = _render_fixed_expenses()
|
|
send(consumer, {"target": "#fixed-expenses-section", "html": html})
|
|
|
|
|
|
@liveview_handler("edit_fixed_expense")
|
|
def edit_fixed_expense(consumer, content):
|
|
data = content.get("data", {})
|
|
fe_id = data.get("data_id", "")
|
|
if not fe_id:
|
|
return
|
|
|
|
html = _render_fixed_expenses(editing_id=int(fe_id))
|
|
send(consumer, {"target": "#fixed-expenses-section", "html": html})
|
|
|
|
|
|
@liveview_handler("save_fixed_expense")
|
|
def save_fixed_expense(consumer, content):
|
|
form = content.get("form", {})
|
|
fe_id = form.get("fe_id", "")
|
|
name = form.get("fe_name", "").strip()
|
|
order = form.get("fe_order", "0")
|
|
|
|
if not fe_id or not name:
|
|
return
|
|
|
|
try:
|
|
fe = FixedExpenseConcept.objects.get(id=fe_id)
|
|
fe.name = name
|
|
fe.order = int(order)
|
|
fe.save()
|
|
except (FixedExpenseConcept.DoesNotExist, ValueError):
|
|
return
|
|
|
|
html = _render_fixed_expenses()
|
|
send(consumer, {"target": "#fixed-expenses-section", "html": html})
|
|
|
|
|
|
@liveview_handler("delete_fixed_expense")
|
|
def delete_fixed_expense_handler(consumer, content):
|
|
data = content.get("data", {})
|
|
fe_id = data.get("data_id", "")
|
|
if not fe_id:
|
|
return
|
|
|
|
FixedExpenseConcept.objects.filter(id=fe_id).delete()
|
|
html = _render_fixed_expenses()
|
|
send(consumer, {"target": "#fixed-expenses-section", "html": html})
|