diff --git a/app/apps/mini_tools/urls.py b/app/apps/mini_tools/urls.py index e4740424..0166de22 100644 --- a/app/apps/mini_tools/urls.py +++ b/app/apps/mini_tools/urls.py @@ -8,6 +8,11 @@ urlpatterns = [ views.unit_price_calculator, name="unit_price_calculator", ), + path( + "tools/simulator/", + views.simulator, + name="simulator", + ), path( "tools/currency-converter/", views.currency_converter, diff --git a/app/apps/mini_tools/views.py b/app/apps/mini_tools/views.py index 2acd039d..359b1470 100644 --- a/app/apps/mini_tools/views.py +++ b/app/apps/mini_tools/views.py @@ -1,11 +1,14 @@ from django.contrib.auth.decorators import login_required from django.shortcuts import render +from django.utils import timezone +from apps.common.widgets.datepicker import AirMonthYearPickerInput from apps.common.widgets.decimal import convert_to_decimal from apps.currencies.models import Currency from apps.currencies.utils.convert import convert from apps.mini_tools.forms import CurrencyConverterForm from apps.mini_tools.utils.exchange_rate_map import get_currency_exchange_map +from apps.mini_tools.utils.simulator import get_simulator_baseline @login_required @@ -13,6 +16,22 @@ def unit_price_calculator(request): return render(request, "mini_tools/unit_price_calculator.html") +@login_required +def simulator(request): + start_month_input = AirMonthYearPickerInput( + clear_button=False, attrs={"class": "w-full sim-start"} + ).render("start_month", timezone.localdate(timezone.now()).replace(day=1)) + + return render( + request, + "mini_tools/simulator.html", + context={ + "baseline": get_simulator_baseline(request.user), + "start_month_input": start_month_input, + }, + ) + + @login_required def currency_converter(request): rate_map = get_currency_exchange_map() diff --git a/app/templates/mini_tools/simulator.html b/app/templates/mini_tools/simulator.html new file mode 100644 index 00000000..4912bb32 --- /dev/null +++ b/app/templates/mini_tools/simulator.html @@ -0,0 +1,479 @@ +{% extends "layouts/base.html" %} +{% load formats %} +{% load i18n %} + +{% block title %}{% translate 'Simulator' %}{% endblock %} + +{% block content %} + {% get_current_language as LANGUAGE_CODE %} + {{ baseline|json_script:"simulator-baseline" }} +
+ {% translate 'See how a one-time, recurring or installment expense or income would affect your projected balance in the coming months.' %} +
+ + {% if not baseline.currencies %} +| {% translate 'Month' %} | +{% translate 'Projected change' %} | +{% translate 'Simulated change' %} | +{% translate 'Balance without simulation' %} | +{% translate 'Balance with simulation' %} | +
|---|
+ {% translate 'The simulation starts at the earliest starting month among your entries, or the current month if there are none. Balances include paid and unpaid transactions, and archived and untracked accounts are ignored. Converted amounts use the latest exchange rate.' %} +
+ {% endif %} + + +