import datetime import json from django.contrib.admin.views.decorators import staff_member_required from django.http import HttpResponse, JsonResponse from django.shortcuts import render, redirect from .scheduled_tasks import nightly_check_active_status from .utils.rollover import RolloverForm, execute_rollover from .backup.backup_helpers import get_export_dict, serialize_all, compare_backup from .utils.send_sms import SMSTestForm, send_sms_test @staff_member_required def settings(request): return render(request, 'admin/settings_index.html') @staff_member_required def rollover(request): if request.method == 'POST': form = RolloverForm(request.POST) if form.is_valid(): execute_rollover(form.cleaned_data['exit_date']) return redirect('settings:index') form = RolloverForm() return render(request, 'admin/rollover_form.html', context={'form': form}) @staff_member_required def sms_test(request): if request.method == 'POST': form = SMSTestForm(request.POST) if form.is_valid(): send_sms_test(request) return redirect('settings:index') else: form = SMSTestForm() return render(request, 'admin/sms_test_form.html', context={'form': form}) @staff_member_required def nightly_task(request): nightly_check_active_status() return redirect('settings:index') @staff_member_required def backup(request): if request.method == "POST" and request.FILES.get("backup_file"): uploaded_file = request.FILES["backup_file"] request.session["backup_file"] = { "content": uploaded_file.read().decode("utf-8"), "timestamp": datetime.datetime.now().timestamp(), } return JsonResponse({"status": "success", "message": "Backup uploaded."}) return render(request, "admin/backup.html") @staff_member_required def export_backup(request): date = datetime.date.today().strftime("%Y-%m-%d") data = serialize_all() response = HttpResponse( json.dumps(data, indent=2), # pretty print for readability content_type="application/json", ) response["Content-Disposition"] = f'attachment; filename="busportal_export-{date}.json"' return response def backup_view(request): context = {} if request.method == "POST": if "backup_file" in request.FILES: uploaded_file = request.FILES["backup_file"] # Read JSON content from uploaded file backup_content = uploaded_file.read().decode("utf-8") # Compare backup with current DB state summary, diffs = compare_backup(backup_content) context["compare_summary"] = summary context["diffs"] = diffs context["uploaded_file_name"] = uploaded_file.name elif "execute_restore" in request.POST: # You can pass the JSON content in a hidden input if needed backup_content = request.POST.get("backup_content") # restore_backup(backup_content) context["success_message"] = "Backup restored successfully." return render(request, "backup.html", context) @staff_member_required @staff_member_required def upload_backup_view(request): if request.method == 'POST' and request.FILES.get("backup_file"): uploaded_file = request.FILES["backup_file"] request.session["backup_file_content"] = uploaded_file.read().decode("utf-8") return JsonResponse({"status": "success", "message": "File uploaded successfully"}) return render(request, 'admin/upload_backup_view.html') # --- Delete uploaded backup --- def cancel_backup_upload(request): request.session.pop("backup_file", None) return JsonResponse({"status": "success", "message": "Uploaded backup cleared."}) # --- Compare backup --- def compare_backup_view(request): backup_entry = request.session.get("backup_file") if not backup_entry: return JsonResponse({"error": "No backup uploaded."}, status=400) backup_data = backup_entry["content"] summary, details = compare_backup(backup_data) return render(request, "backup_compare.html", {"summary": summary, "details": details}) def apply_backup(backup_data): pass # --- Execute restore --- def restore_backup_view(request): backup_entry = request.session.pop("backup_file", None) if not backup_entry: return JsonResponse({"error": "No backup uploaded."}, status=400) backup_data = json.loads(backup_entry["content"]) apply_backup(backup_data) return JsonResponse({"status": "success", "message": "Backup restored successfully."})