from django.shortcuts import render, redirect, get_object_or_404 from django.utils import translation from django.conf import settings from django.http import JsonResponse from django.contrib.admin.views.decorators import staff_member_required from django.contrib.auth.decorators import login_required from django.contrib.auth import logout, login from django.urls import reverse from .models import Classroom, Subject, Teacher, Student, City from .forms import StudentRegistrationForm from .wablas import send_whatsapp_message from .thawani import ThawaniClient import random import string def index(request): levels = Classroom.objects.prefetch_related('subjects').all() context = {'levels': levels} return render(request, 'core/index.html', context) def set_language(request, lang_code): next_url = request.GET.get('next', '/') response = redirect(next_url) if lang_code in [lang[0] for lang in settings.LANGUAGES]: translation.activate(lang_code) if hasattr(request, 'session'): request.session['_language'] = lang_code response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code) return response def subject_detail(request, pk): subject = get_object_or_404(Subject, pk=pk) return render(request, 'core/subject_detail.html', {'subject': subject}) @staff_member_required def get_subjects_by_level(request): level_id = request.GET.get('level_id') or request.GET.get('classroom_id') if not level_id: return JsonResponse([], safe=False) subjects = Subject.objects.filter(classroom_id=level_id).values('id', 'name_en', 'name_ar') return JsonResponse(list(subjects), safe=False) def get_classroom_subjects(request): classroom_id = request.GET.get('classroom_id') if not classroom_id: return JsonResponse([], safe=False) subjects = Subject.objects.filter(classroom_id=classroom_id).values('id', 'name_en', 'price') return JsonResponse(list(subjects), safe=False) def get_cities_by_governorate(request): governorate_id = request.GET.get('governorate_id') if not governorate_id: return JsonResponse([], safe=False) cities = City.objects.filter(governorate_id=governorate_id).values('id', 'name_en', 'name_ar') return JsonResponse(list(cities), safe=False) def generate_otp(): return ''.join(random.choices(string.digits, k=6)) def register_student(request): if request.method == 'POST': form = StudentRegistrationForm(request.POST, request.FILES) if form.is_valid(): student = form.save() # Generate OTPs mobile_otp = generate_otp() email_otp = generate_otp() student.mobile_otp_code = mobile_otp student.email_otp_code = email_otp student.save() # Send OTP via WhatsApp if student.mobile_number: # Attempt to send WhatsApp message # Note: This will only work if Wablas is configured in Admin send_whatsapp_message( student.mobile_number, f"Your Verification Code is: {mobile_otp}" ) # Simulate sending OTPs (Log to console) print(f"========================================") print(f"SIMULATED OTP SENDING:") print(f"User: {student.user.username}") print(f"Mobile OTP for {student.mobile_number}: {mobile_otp}") print(f"Email OTP for {student.user.email}: {email_otp}") print(f"========================================") # Log the user in login(request, student.user) # Redirect to verification page return redirect('verify_otp') else: form = StudentRegistrationForm() return render(request, 'core/registration.html', {'form': form}) @login_required def verify_otp(request): try: student = request.user.student_profile except Student.DoesNotExist: return redirect('index') if student.is_mobile_verified and student.is_email_verified: return redirect('profile') error = None if request.method == 'POST': entered_mobile_otp = request.POST.get('mobile_otp') entered_email_otp = request.POST.get('email_otp') mobile_ok = student.is_mobile_verified email_ok = student.is_email_verified if not mobile_ok: if entered_mobile_otp == student.mobile_otp_code: student.is_mobile_verified = True mobile_ok = True else: error = "Invalid Mobile OTP" if not email_ok and (error is None or "Mobile" not in error): if entered_email_otp == student.email_otp_code: student.is_email_verified = True email_ok = True else: error = "Invalid Email OTP" if mobile_ok and email_ok: student.mobile_otp_code = "" # Clear codes student.email_otp_code = "" student.save() return redirect('profile') else: student.save() # Save partial verification if any return render(request, 'core/verify_otp.html', {'error': error, 'student': student}) @login_required def profile(request): user = request.user # Check for Teacher if hasattr(user, 'teacher_profile'): teacher_profile = user.teacher_profile subjects = teacher_profile.subjects.all() return render(request, 'core/teacher_dashboard.html', { 'teacher_profile': teacher_profile, 'subjects': subjects }) # Check for Student elif hasattr(user, 'student_profile'): student_profile = user.student_profile subscribed_subjects = student_profile.subscribed_subjects.all() # Get available subjects (in same classroom, not yet subscribed) available_subjects = [] if student_profile.classroom: available_subjects = Subject.objects.filter( classroom=student_profile.classroom ).exclude( id__in=subscribed_subjects.values_list('id', flat=True) ) return render(request, 'core/student_dashboard.html', { 'student_profile': student_profile, 'subscribed_subjects': subscribed_subjects, 'available_subjects': available_subjects }) # Fallback (Superuser or Admin without profile) else: student_profile = None return render(request, 'core/profile.html', {'student_profile': student_profile}) def custom_logout(request): logout(request) return redirect('index') @login_required def subscribe_subject(request, subject_id): try: student = request.user.student_profile except Student.DoesNotExist: return redirect('index') subject = get_object_or_404(Subject, pk=subject_id) # Check if already subscribed if subject in student.subscribed_subjects.all(): return redirect('profile') try: thawani = ThawaniClient() success_url = request.build_absolute_uri(reverse('payment_success')) + '?session_id={session_id}' cancel_url = request.build_absolute_uri(reverse('payment_cancel')) session = thawani.create_checkout_session(subject, request.user, success_url, cancel_url) session_id = session.get('data', {}).get('session_id') if not session_id: return render(request, 'core/error.html', {'message': 'Could not create payment session.'}) return redirect(f"{thawani.checkout_base_url}/{session_id}") except Exception as e: print(f"Payment Error: {e}") return render(request, 'core/error.html', {'message': f'Payment initialization failed: {str(e)}'}) @login_required def payment_success(request): session_id = request.GET.get('session_id') if not session_id: return redirect('profile') try: thawani = ThawaniClient() response = thawani.get_checkout_session(session_id) data = response.get('data', {}) payment_status = data.get('payment_status') metadata = data.get('metadata', {}) subject_id = metadata.get('subject_id') if payment_status == 'paid' and subject_id: try: student = request.user.student_profile subject = get_object_or_404(Subject, pk=subject_id) student.subscribed_subjects.add(subject) except Exception: pass # Already handled or user mismatch? return redirect('profile') else: return render(request, 'core/error.html', {'message': f'Payment was not successful. Status: {payment_status}'}) except Exception as e: print(f"Payment Verification Error: {e}") return render(request, 'core/error.html', {'message': f'Payment verification failed: {str(e)}'}) @login_required def payment_cancel(request): return redirect('profile')