def __init__(self, *args, **kwargs): user = kwargs.pop("user", None) super().__init__(*args, **kwargs) self.fields["category"].queryset = Category.objects.filter( user=user).order_by("order") self.fields["date"].default = today_date().strftime("%Y-%m-%d") self.fields["description"].required = False
def exp_template_actions(the_template, show_title=False, show_date=False): return { "template": the_template, "show_title": show_title, "show_date": show_date, "today": today_date() }
def expense_table(context, expenses): show_form = context.get("show_form", False) ctx = {"expenses": expenses, "show_form": show_form, "pid": context["pid"]} if show_form: ctx["categories"] = context.get("categories", None) ctx["today"] = today_date() return ctx
def template_run(request, pk): template = get_object_or_404(ExpenseTemplate, pk=pk, user=request.user) expense = Expense(vendor=template.vendor, category=template.category) if "date" in request.GET: expense.date = request.GET["date"] else: expense.date = today_date() if template.type == "count": if not request.GET.get("count"): count = decimal.Decimal(1) else: count = parse_amount_input(request.GET["count"]) if count is None: return HttpResponseBadRequest() expense.amount = round_money(template.amount * count) desc_lines = template.description.strip().split("\n") desc_possibilities = len(desc_lines) desc = desc_lines[0] if count % 1 != 0: # Is decimal, use last possibility desc = desc_lines[desc_possibilities - 1] elif desc_possibilities == 2: # 0 → 1, 1 → anything else (English) desc = desc_lines[int(count != 1)] elif desc_possibilities in {3, 4}: # Polish scheme if count == 1: desc = desc_lines[0] else: # Expression from gettext, simplified desc = desc_lines[1 if (2 <= count % 10 <= 4 and (count % 100 < 10 or count % 100 >= 20)) else 2] expense.description = desc.replace("!count!", str(count)) elif template.type == "description": expense.amount = template.amount expense.description = template.description.replace("!description!", request.GET["description"]) elif template.type == "desc_select": main_desc, *desc_options = template.description.strip().split("\n") desc_id = int(request.GET["desc_id"]) expense.amount = template.amount expense.description = main_desc.strip().replace("!description!", desc_options[desc_id].strip()) elif template.type == "menu": desc_id = int(request.GET["desc_id"]) desc_options = template.description.strip().split("\n") amount_str, desc = desc_options[desc_id].strip().split(" ", 1) expense.amount = parse_amount_input(amount_str.strip()) if expense.amount is None: return HttpResponseBadRequest() expense.description = desc.strip() else: expense.amount = template.amount expense.description = template.description expense.user = request.user expense.save() return HttpResponseRedirect(expense.get_absolute_url())
def expense_repeat(request, pk): old_expense = get_object_or_404(Expense, pk=pk, user=request.user, is_bill=False) new_expense = Expense( date=today_date(), vendor=old_expense.vendor, category=old_expense.category, amount=old_expense.amount, description=old_expense.description, user=request.user, is_bill=False, ) new_expense.save() messages.add_message(request, messages.SUCCESS, _("Expense has been repeated successfully.")) return HttpResponseRedirect(reverse("expenses:expense_show", args=[new_expense.pk]))
def index(request): last_n_expenses = revchron(Expense.objects.filter(user=request.user).select_related("category"))[ : settings.EXPENSES_INDEX_COUNT ] with connection.cursor() as cursor: cursor.execute( """ SELECT date, SUM(amount) FROM expenses_expense WHERE user_id = %s GROUP BY date ORDER BY date DESC LIMIT 3""", [request.user.pk], ) last_3_days = cursor.fetchall() last_3_days_sum = sum(r[1] for r in last_3_days) last_3_days = reversed(last_3_days) today = today_date() prev_month = today.month - 1 prev_year = today.year while prev_month < 0: prev_month += 12 prev_year -= 1 current_months_total = Expense.objects.filter( user=request.user, date__year=today.year, date__month=today.month ).aggregate(Sum("amount"))["amount__sum"] previous_months_total = ( Expense.objects.filter(user=request.user, date__year=prev_year, date__month=prev_month).aggregate( Sum("amount") )["amount__sum"] or 0 ) spending_per_category_qs = ( Expense.objects.filter(user=request.user).values("category").annotate(sum=Sum("amount")).order_by("-sum") ) categories = {cat.pk: cat for cat in Category.objects.filter(user=request.user)} spending_per_category = [(categories[i["category"]], i["sum"]) for i in spending_per_category_qs] pie_chart = pygal.Pie( disable_xml_declaration=True, margin=0, legend_at_bottom=True, print_values=True, print_labels=True, style=pygal.style.DefaultStyle( plot_background="white", background="white", font_family="var(--font-family-sans-serif)", label_font_size=20, value_font_size=20, value_label_font_size=20, tooltip_font_size=20, legend_font_size=20, ), ) for c, s in spending_per_category: pie_chart.add(c.name, float(s), formatter=format_money) category_chart = mark_safe(pie_chart.render()) return render( request, "expenses/index.html", { "htmltitle": _("Expenses Dashboard"), "pid": "expenses_index", "last_n_expenses": last_n_expenses, "EXPENSES_INDEX_COUNT": settings.EXPENSES_INDEX_COUNT, "last_3_days": last_3_days, "last_3_days_sum": last_3_days_sum, "current_months_total": current_months_total, "previous_months_total": previous_months_total, "spending_per_category": spending_per_category, "category_chart": category_chart, }, )