From 12b32857b46a4a34cfa8c7b69b394302991e3044 Mon Sep 17 00:00:00 2001 From: Naman Sharma Date: Mon, 15 Sep 2025 09:38:27 +0000 Subject: [PATCH 1/4] made changes to the password reset page; schools and batches now show up after selecting a state, reducing slowness --- .gitignore | 3 ++ events/forms.py | 24 +++++++++- events/urls.py | 2 + events/views.py | 48 +++++++++++-------- .../templates/reset_student_password.html | 14 +++--- 5 files changed, 61 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 05439b9af..9c2341c5d 100644 --- a/.gitignore +++ b/.gitignore @@ -104,3 +104,6 @@ cron/* creation/hr-receipts/ *.DS_Store static/spoken/embedding/ + +*.sql +env/ \ No newline at end of file diff --git a/events/forms.py b/events/forms.py index 8e7a1b5b2..c94537631 100644 --- a/events/forms.py +++ b/events/forms.py @@ -513,11 +513,31 @@ def __init__(self, *args, **kwargs): class StudentPasswordResetForm(forms.Form): state = forms.ModelChoiceField(queryset=State.objects.all(), empty_label="Select State",) - school = forms.ModelChoiceField(queryset=AcademicCenter.objects.filter(institution_type_id=5)) - batches = forms.ModelMultipleChoiceField(queryset=StudentBatch.objects.filter(academic__institution_type_id=5)) + school = forms.ModelChoiceField(queryset=AcademicCenter.objects.none()) + batches = forms.ModelMultipleChoiceField(queryset=StudentBatch.objects.none()) new_password = forms.CharField() confirm_password = forms.CharField() + def __init__(self, *args, **kwargs): + state_id = None + school_id = None + if 'data' in kwargs: + state_id = kwargs['data'].get('state') + school_id = kwargs['data'].get('school') + elif 'initial' in kwargs: + state_id = kwargs['initial'].get('state') + school_id = kwargs['initial'].get('school') + else: + state_id = None + school_id = None + super().__init__(*args, **kwargs) + if state_id: + self.fields['school'].queryset = AcademicCenter.objects.filter(state_id=state_id) + if school_id: + self.fields['batches'].queryset = StudentBatch.objects.filter(academic_id=school_id) + else: + self.fields['batches'].queryset = StudentBatch.objects.none() + def clean(self): cleaned_data = super().clean() new_password = cleaned_data.get('new_password') diff --git a/events/urls.py b/events/urls.py index 27504170a..2f6f85f40 100644 --- a/events/urls.py +++ b/events/urls.py @@ -1,6 +1,8 @@ from django.conf.urls import url, include from events.views import * from events.notification import nemail +from .views import get_schools, get_batches + app_name = 'events' urlpatterns = [ url(r'^$', events_dashboard, name='events_dashboard'), diff --git a/events/views.py b/events/views.py index 409b9180a..4b3779fc0 100644 --- a/events/views.py +++ b/events/views.py @@ -1,3 +1,14 @@ +# --- BEGIN: get_batches view for AJAX batch dropdown --- +from django.http import JsonResponse +from .models import StudentBatch + +def get_batches(request): + school_id = request.GET.get('school_id') + if school_id: + batches = StudentBatch.objects.filter(academic_id=school_id).values('id', 'batch_name') + return JsonResponse(list(batches), safe=False) + return JsonResponse([]) + from django.core.exceptions import PermissionDenied from django.contrib.auth.decorators import login_required @@ -1344,7 +1355,7 @@ def training_clone(request, role, rid = None): messages.error(request, "You have already scheduled "+ str(request.POST['tdate']) + " training on "+ str(master_training.tdate) + ". Please select some other date.") - if not csv_file_error:# and request.POST.get('remove-error')): + if not csv_file_error:# and request.POST.get('remove-error'): existing_emails = None if reattempt_list and more_then_two_per_day_list: existing_emails = set(reattempt_list.split(',')).union(set(more_then_two_per_day_list.split(','))) @@ -2248,7 +2259,7 @@ def test_participant(request, tid=None): #if t.status == 4 and (user == t.organiser or user == t.invigilator): # can_download_certificate = 1 context = {'collection' : test_mdlusers, 'test' : t, 'can_download_certificate':can_download_certificate} - return render(request, 'events/templates/test/test_participant.html', context) + return render(request, 'events/templates/test_participant.html', context) def test_participant_ceritificate(request, wid, participant_id): #response = HttpResponse(content_type='application/pdf') @@ -2318,8 +2329,10 @@ def test_participant_ceritificate(request, wid, participant_id): # Draw image on Canvas and save PDF in buffer imgPath = get_signature(ta.test.tdate) imgDoc.drawImage(imgPath, 600, 95, 150, 76) ## at (399,760) with size 160x160 + credits = "

Credits: "+str(w.foss.credits)+"   Score: "+str('{:.2f}'.format(mdlgrade.grade))+"%

" + #paragraphe text = get_test_cert_text(ta.test, mdluser, credits=credits) centered = ParagraphStyle(name = 'centered', fontSize = 15, @@ -2331,7 +2344,6 @@ def test_participant_ceritificate(request, wid, participant_id): p.wrap(700, 200) p.drawOn(imgDoc, 3 * cm, 6.5 * cm) - #paragraphe text = "Certificate for the Completion of
"+w.foss.foss+" Training" @@ -2351,7 +2363,6 @@ def test_participant_ceritificate(request, wid, participant_id): # Use PyPDF to merge the image-PDF into the template template_path = get_test_certificate(ta) page = PdfFileReader(open(template_path,"rb")).getPage(0) - overlay = PdfFileReader(BytesIO(imgTemp.getvalue())).getPage(0) page.mergePage(overlay) @@ -2859,13 +2870,13 @@ def ajax_district_data(request): tmp +='' data['location'] = tmp - if request.POST.get('fields[institute]'): - collages = AcademicCenter.objects.filter(district=district).order_by('institution_name') - if collages: - tmp = '' - for i in collages: - tmp +='' - data['institute'] = tmp + if request.POST.get('fields[institute]'): + collages = AcademicCenter.objects.filter(district=district).order_by('institution_name') + if collages: + tmp = '' + for i in collages: + tmp +='' + data['institute'] = tmp return HttpResponse(json.dumps(data), content_type='application/json') @@ -3247,18 +3258,13 @@ def get_schools(request): state_id = request.GET.get('state_id') if state_id: schools = AcademicCenter.objects.filter( - institution_type_id=5, state_id=state_id, + state_id=state_id, studentbatch__isnull=False).distinct().values( - 'id', 'institution_name', 'academic_code').order_by('institution_name') # 5 for school + 'id', 'institution_name', 'academic_code').order_by('institution_name') + print('DEBUG: state_id:', state_id) + print('DEBUG: schools queryset:', list(schools)) return JsonResponse(list(schools), safe=False) - return JsonResponse([]) - - -def get_batches(request): - school_id = request.GET.get('school_id') - if school_id: - batches = StudentBatch.objects.filter(academic_id=school_id).values('id', 'batch_name') - return JsonResponse(list(batches), safe=False) + print('DEBUG: No state_id provided') return JsonResponse([]) diff --git a/static/events/templates/reset_student_password.html b/static/events/templates/reset_student_password.html index d861571a3..0b3eeda74 100644 --- a/static/events/templates/reset_student_password.html +++ b/static/events/templates/reset_student_password.html @@ -44,7 +44,9 @@
- {% render_field form.batches class+="form-control" multiple="multiple" %} +
@@ -105,22 +107,20 @@ // Fetch batches based on selected school $("#id_school").change(function(){ let schoolId = $(this).val(); + let batchSelect = $("#id_batches"); + batchSelect.empty().append(''); if(!schoolId) return; - fetch(`{% url 'events:get_batches' %}?school_id=${schoolId}`) .then(response => response.json()) .then(data => { - let batchSelect = $("#id_batches"); - batchSelect.empty(); data.forEach(batch => { - batchSelect.append(``); + batchSelect.append(``); }) }) .catch(error => { alert('an error occurred') }); - - }) + }); }) {% endblock %} From 0dcf5ecbfc90092f6fa4ca5d38f2962aeae66cc8 Mon Sep 17 00:00:00 2001 From: Naman Sharma Date: Mon, 15 Sep 2025 09:54:53 +0000 Subject: [PATCH 2/4] made changes to the password reset page; schools and batches now show up after selecting a state, reducing slowness --- events/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/events/views.py b/events/views.py index 4b3779fc0..e356e4afb 100644 --- a/events/views.py +++ b/events/views.py @@ -1,4 +1,3 @@ -# --- BEGIN: get_batches view for AJAX batch dropdown --- from django.http import JsonResponse from .models import StudentBatch From 847c2fb5115c146f528d1a2124b6700171190804 Mon Sep 17 00:00:00 2001 From: Naman Sharma Date: Tue, 16 Sep 2025 19:35:14 +0000 Subject: [PATCH 3/4] fixed the password change confirmation message not showing up after successful form submission --- events/forms.py | 15 +++++++++------ events/views.py | 17 ++++++++++++----- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/events/forms.py b/events/forms.py index c94537631..2e466b51b 100644 --- a/events/forms.py +++ b/events/forms.py @@ -521,16 +521,19 @@ class StudentPasswordResetForm(forms.Form): def __init__(self, *args, **kwargs): state_id = None school_id = None - if 'data' in kwargs: - state_id = kwargs['data'].get('state') - school_id = kwargs['data'].get('school') + + # Extract data from args (when form is created with POST data) + if args and len(args) > 0 and hasattr(args[0], 'get'): + state_id = args[0].get('state') + school_id = args[0].get('school') + # Extract data from kwargs (when form has initial data) elif 'initial' in kwargs: state_id = kwargs['initial'].get('state') school_id = kwargs['initial'].get('school') - else: - state_id = None - school_id = None + super().__init__(*args, **kwargs) + + # Set querysets based on the extracted data if state_id: self.fields['school'].queryset = AcademicCenter.objects.filter(state_id=state_id) if school_id: diff --git a/events/views.py b/events/views.py index e356e4afb..e5927e235 100644 --- a/events/views.py +++ b/events/views.py @@ -3229,13 +3229,16 @@ def reset_student_pwd(request): template = 'events/templates/reset_student_password.html' form = StudentPasswordResetForm() context['form'] = form + if request.method == "POST": form = StudentPasswordResetForm(request.POST) context['form'] = form + if form.is_valid(): school = form.cleaned_data['school'] batches = form.cleaned_data['batches'] new_password = form.cleaned_data['new_password'] + batch_ids = [x.id for x in batches] batches = StudentBatch.objects.filter(id__in=batch_ids) student_ids = StudentMaster.objects.filter(batch__in=batches).values_list('student_id', flat=True) @@ -3248,8 +3251,15 @@ def reset_student_pwd(request): emails = [user.email for user in users] mdlUsers = MdlUser.objects.filter(email__in=emails) mdlUsers.update(password=encript_password(new_password)) - send_bulk_student_reset_mail(school,batches,users.count(), new_password,request.user) - messages.add_message(request, messages.SUCCESS, f"Password updated for {users.count()} students.") + # send_bulk_student_reset_mail(school,batches,users.count(), new_password,request.user) # Temporarily disabled + + # Add the success message + success_msg = "Password updated for {} students.".format(users.count()) + messages.success(request, success_msg) + + from django.urls import reverse + redirect_url = reverse('events:reset_student_pwd') + return HttpResponseRedirect(redirect_url) return render(request,template,context) @@ -3260,10 +3270,7 @@ def get_schools(request): state_id=state_id, studentbatch__isnull=False).distinct().values( 'id', 'institution_name', 'academic_code').order_by('institution_name') - print('DEBUG: state_id:', state_id) - print('DEBUG: schools queryset:', list(schools)) return JsonResponse(list(schools), safe=False) - print('DEBUG: No state_id provided') return JsonResponse([]) From 71148ee2eb7b7db4f6fae93aa372f589a699625d Mon Sep 17 00:00:00 2001 From: Naman Sharma Date: Thu, 18 Sep 2025 13:54:47 +0000 Subject: [PATCH 4/4] adressed the minor review comments; fixed import path, uncommented temp changes --- events/views.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/events/views.py b/events/views.py index e5927e235..57f801446 100644 --- a/events/views.py +++ b/events/views.py @@ -1,5 +1,6 @@ from django.http import JsonResponse from .models import StudentBatch +from django.urls import reverse def get_batches(request): school_id = request.GET.get('school_id') @@ -2258,7 +2259,7 @@ def test_participant(request, tid=None): #if t.status == 4 and (user == t.organiser or user == t.invigilator): # can_download_certificate = 1 context = {'collection' : test_mdlusers, 'test' : t, 'can_download_certificate':can_download_certificate} - return render(request, 'events/templates/test_participant.html', context) + return render(request, 'events/templates/test/test_participant.html', context) def test_participant_ceritificate(request, wid, participant_id): #response = HttpResponse(content_type='application/pdf') @@ -3251,13 +3252,13 @@ def reset_student_pwd(request): emails = [user.email for user in users] mdlUsers = MdlUser.objects.filter(email__in=emails) mdlUsers.update(password=encript_password(new_password)) - # send_bulk_student_reset_mail(school,batches,users.count(), new_password,request.user) # Temporarily disabled + send_bulk_student_reset_mail(school,batches,users.count(), new_password,request.user) # Add the success message success_msg = "Password updated for {} students.".format(users.count()) messages.success(request, success_msg) - from django.urls import reverse + redirect_url = reverse('events:reset_student_pwd') return HttpResponseRedirect(redirect_url) return render(request,template,context)