feat(app): add a demo mode

This commit is contained in:
Herculino Trotta
2025-03-31 02:14:00 -03:00
parent 046e02d506
commit 47d34f3c27
14 changed files with 216 additions and 50 deletions
+15
View File
@@ -0,0 +1,15 @@
from functools import wraps
from django.conf import settings
from django.core.exceptions import PermissionDenied
def disabled_on_demo(view):
@wraps(view)
def _view(request, *args, **kwargs):
if settings.DEMO and not request.user.is_superuser:
raise PermissionDenied
return view(request, *args, **kwargs)
return _view
+38
View File
@@ -1,7 +1,9 @@
import logging
from asgiref.sync import sync_to_async
from django.conf import settings
from django.core import management
from django.db import DEFAULT_DB_ALIAS
from procrastinate import builtin_tasks
from procrastinate.contrib.django import app
@@ -40,3 +42,39 @@ async def remove_expired_sessions(timestamp=None):
"Error while executing 'remove_expired_sessions' task",
exc_info=True,
)
@app.periodic(cron="0 6 * * *")
@app.task(name="reset_demo_data")
def reset_demo_data():
"""
Wipes the database and loads fresh demo data if DEMO mode is active.
Runs daily at 6:00 AM.
"""
if not settings.DEMO:
return # Exit if not in demo mode
logger.info("Demo mode active. Starting daily data reset...")
try:
# 1. Flush the database (wipe all data)
logger.info("Flushing the database...")
# Using --noinput prevents prompts. Specify database if not default.
management.call_command(
"flush", "--noinput", database=DEFAULT_DB_ALIAS, verbosity=1
)
logger.info("Database flushed successfully.")
# 2. Load data from the fixture
fixture_name = "fixtures/demo_data.json"
logger.info(f"Loading data from fixture: {fixture_name}...")
management.call_command(
"loaddata", fixture_name, database=DEFAULT_DB_ALIAS, verbosity=1
)
logger.info(f"Data loaded successfully from {fixture_name}.")
logger.info("Daily demo data reset completed.")
except Exception as e:
logger.exception(f"Error during daily demo data reset: {e}")
raise
@@ -11,9 +11,11 @@ from apps.common.decorators.htmx import only_htmx
from apps.currencies.forms import ExchangeRateForm, ExchangeRateServiceForm
from apps.currencies.models import ExchangeRate, ExchangeRateService
from apps.currencies.tasks import manual_fetch_exchange_rates
from apps.common.decorators.demo import disabled_on_demo
@login_required
@disabled_on_demo
@require_http_methods(["GET"])
def exchange_rates_services_index(request):
return render(
@@ -24,6 +26,7 @@ def exchange_rates_services_index(request):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET"])
def exchange_rates_services_list(request):
services = ExchangeRateService.objects.all()
@@ -37,6 +40,7 @@ def exchange_rates_services_list(request):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def exchange_rate_service_add(request):
if request.method == "POST":
@@ -63,6 +67,7 @@ def exchange_rate_service_add(request):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def exchange_rate_service_edit(request, pk):
service = get_object_or_404(ExchangeRateService, id=pk)
@@ -91,6 +96,7 @@ def exchange_rate_service_edit(request, pk):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["DELETE"])
def exchange_rate_service_delete(request, pk):
service = get_object_or_404(ExchangeRateService, id=pk)
@@ -109,6 +115,7 @@ def exchange_rate_service_delete(request, pk):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET"])
def exchange_rate_service_force_fetch(request):
manual_fetch_exchange_rates.defer()
+4
View File
@@ -41,11 +41,13 @@ from apps.export_app.resources.transactions import (
RecurringTransactionResource,
)
from apps.export_app.resources.users import UserResource
from apps.common.decorators.demo import disabled_on_demo
logger = logging.getLogger()
@login_required
@disabled_on_demo
@user_passes_test(lambda u: u.is_superuser)
@require_http_methods(["GET"])
def export_index(request):
@@ -53,6 +55,7 @@ def export_index(request):
@login_required
@disabled_on_demo
@user_passes_test(lambda u: u.is_superuser)
@require_http_methods(["GET", "POST"])
def export_form(request):
@@ -182,6 +185,7 @@ def export_form(request):
@only_htmx
@login_required
@disabled_on_demo
@user_passes_test(lambda u: u.is_superuser)
@require_http_methods(["GET", "POST"])
def import_form(request):
+11
View File
@@ -13,9 +13,11 @@ from apps.import_app.forms import ImportRunFileUploadForm, ImportProfileForm
from apps.import_app.models import ImportRun, ImportProfile
from apps.import_app.services import PresetService
from apps.import_app.tasks import process_import
from apps.common.decorators.demo import disabled_on_demo
@login_required
@disabled_on_demo
@require_http_methods(["GET"])
def import_presets_list(request):
presets = PresetService.get_all_presets()
@@ -27,6 +29,7 @@ def import_presets_list(request):
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def import_profile_index(request):
return render(
@@ -37,6 +40,7 @@ def import_profile_index(request):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def import_profile_list(request):
profiles = ImportProfile.objects.all()
@@ -50,6 +54,7 @@ def import_profile_list(request):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def import_profile_add(request):
message = request.POST.get("message", None)
@@ -85,6 +90,7 @@ def import_profile_add(request):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def import_profile_edit(request, profile_id):
profile = get_object_or_404(ImportProfile, id=profile_id)
@@ -114,6 +120,7 @@ def import_profile_edit(request, profile_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["DELETE"])
def import_profile_delete(request, profile_id):
profile = ImportProfile.objects.get(id=profile_id)
@@ -132,6 +139,7 @@ def import_profile_delete(request, profile_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def import_runs_list(request, profile_id):
profile = ImportProfile.objects.get(id=profile_id)
@@ -147,6 +155,7 @@ def import_runs_list(request, profile_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def import_run_log(request, profile_id, run_id):
run = ImportRun.objects.get(profile__id=profile_id, id=run_id)
@@ -160,6 +169,7 @@ def import_run_log(request, profile_id, run_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def import_run_add(request, profile_id):
profile = ImportProfile.objects.get(id=profile_id)
@@ -202,6 +212,7 @@ def import_run_add(request, profile_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["DELETE"])
def import_run_delete(request, profile_id, run_id):
run = ImportRun.objects.get(profile__id=profile_id, id=run_id)
+16
View File
@@ -18,9 +18,11 @@ from apps.rules.models import (
)
from apps.common.models import SharedObject
from apps.common.forms import SharedObjectForm
from apps.common.decorators.demo import disabled_on_demo
@login_required
@disabled_on_demo
@require_http_methods(["GET"])
def rules_index(request):
return render(
@@ -31,6 +33,7 @@ def rules_index(request):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET"])
def rules_list(request):
transaction_rules = TransactionRule.objects.all().order_by("id")
@@ -43,6 +46,7 @@ def rules_list(request):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def transaction_rule_toggle_activity(request, transaction_rule_id, **kwargs):
transaction_rule = get_object_or_404(TransactionRule, id=transaction_rule_id)
@@ -65,6 +69,7 @@ def transaction_rule_toggle_activity(request, transaction_rule_id, **kwargs):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def transaction_rule_add(request, **kwargs):
if request.method == "POST":
@@ -91,6 +96,7 @@ def transaction_rule_add(request, **kwargs):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def transaction_rule_edit(request, transaction_rule_id):
transaction_rule = get_object_or_404(TransactionRule, id=transaction_rule_id)
@@ -129,6 +135,7 @@ def transaction_rule_edit(request, transaction_rule_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def transaction_rule_view(request, transaction_rule_id):
transaction_rule = get_object_or_404(TransactionRule, id=transaction_rule_id)
@@ -142,6 +149,7 @@ def transaction_rule_view(request, transaction_rule_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["DELETE"])
def transaction_rule_delete(request, transaction_rule_id):
transaction_rule = get_object_or_404(TransactionRule, id=transaction_rule_id)
@@ -166,6 +174,7 @@ def transaction_rule_delete(request, transaction_rule_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET"])
def transaction_rule_take_ownership(request, transaction_rule_id):
transaction_rule = get_object_or_404(TransactionRule, id=transaction_rule_id)
@@ -187,6 +196,7 @@ def transaction_rule_take_ownership(request, transaction_rule_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def transaction_rule_share(request, pk):
obj = get_object_or_404(TransactionRule, id=pk)
@@ -225,6 +235,7 @@ def transaction_rule_share(request, pk):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def transaction_rule_action_add(request, transaction_rule_id):
transaction_rule = get_object_or_404(TransactionRule, id=transaction_rule_id)
@@ -252,6 +263,7 @@ def transaction_rule_action_add(request, transaction_rule_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def transaction_rule_action_edit(request, transaction_rule_action_id):
transaction_rule_action = get_object_or_404(
@@ -289,6 +301,7 @@ def transaction_rule_action_edit(request, transaction_rule_action_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["DELETE"])
def transaction_rule_action_delete(request, transaction_rule_action_id):
transaction_rule_action = get_object_or_404(
@@ -309,6 +322,7 @@ def transaction_rule_action_delete(request, transaction_rule_action_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def update_or_create_transaction_rule_action_add(request, transaction_rule_id):
transaction_rule = get_object_or_404(TransactionRule, id=transaction_rule_id)
@@ -340,6 +354,7 @@ def update_or_create_transaction_rule_action_add(request, transaction_rule_id):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["GET", "POST"])
def update_or_create_transaction_rule_action_edit(request, pk):
linked_action = get_object_or_404(UpdateOrCreateTransactionRuleAction, id=pk)
@@ -374,6 +389,7 @@ def update_or_create_transaction_rule_action_edit(request, pk):
@only_htmx
@login_required
@disabled_on_demo
@require_http_methods(["DELETE"])
def update_or_create_transaction_rule_action_delete(request, pk):
linked_action = get_object_or_404(UpdateOrCreateTransactionRuleAction, id=pk)