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