Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 141 additions & 1 deletion cron/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@
from events.models import FossMdlCourses, TestAttendance, State, City, InstituteType
from creation.models import FossCategory

from django.db import transaction
from training.models import TrainingAttend
from events.models import Test, TestAttendance
from mdldjango.helper import get_moodle_user
from events.helpers import get_fossmdlcourse
from django.db import close_old_connections



def bulk_email(taskid, *args, **kwargs):
task = AsyncCronMail.objects.get(pk=taskid)
if task.log_file.name == "":
Expand Down Expand Up @@ -166,4 +175,135 @@ def filter_student_grades(key=None):


def async_filter_student_grades(key):
TOPPER_QUEUE.enqueue(filter_student_grades, key, job_id=key, job_timeout='72h')
TOPPER_QUEUE.enqueue(filter_student_grades, key, job_id=key, job_timeout='72h')



def process_test_attendance(test_id):
"""
Background task:
- Create TestAttendance
- Sync Moodle users
"""
close_old_connections()
job = get_current_job()
if job:
job.meta['test_id'] = test_id
job.save_meta()

try:
test = Test.objects.select_related('training', 'foss').get(pk=test_id)
except Test.DoesNotExist:
return

if not test.training_id:
return

tras = TrainingAttend.objects.select_related(
'student__user',
'training__training_planner'
).filter(training=test.training)

fossmdlcourse = get_fossmdlcourse(
test.foss_id,
fossmdlmap_id=test.training.fossmdlmap_id
)

existing = {
(x.student_id, x.mdluser_id)
for x in TestAttendance.objects.filter(test=test)
}

mdluser_cache = {}
new_rows = []

for tra in tras:
user = tra.student.user

key = (
tra.training.training_planner.academic_id,
user.first_name,
user.last_name,
tra.student.gender,
user.email
)

if key not in mdluser_cache:
mdluser_cache[key] = get_moodle_user(*key)

mdluser = mdluser_cache[key]
if not mdluser:
continue

pair = (tra.student.id, mdluser.id)
if pair in existing:
continue

new_rows.append(
TestAttendance(
student_id=tra.student.id,
test=test,
mdluser_id=mdluser.id,
mdlcourse_id=fossmdlcourse.mdlcourse_id,
mdlquiz_id=fossmdlcourse.mdlquiz_id,
mdlattempt_id=0,
status=0
)
)

if new_rows:
close_old_connections()
with transaction.atomic():
TestAttendance.objects.bulk_create(new_rows)


def process_test_post_save(test_id, user_id, message,academic_id):
"""
Background task:
- Event log
- Notifications
"""
close_old_connections()
from events.views import (
update_events_log,
update_events_notification
)

update_events_log(
user_id=user_id,
role=0,
category=1,
category_id=test_id,
academic=academic_id,
status=0
)

update_events_notification(
user_id=user_id,
role=0,
category=1,
category_id=test_id,
academic=academic_id,
status=0,
message=message
)


def async_process_test_attendance(test):
DEFAULT_QUEUE.enqueue(
process_test_attendance,
test.pk,
job_id="test_attendance_%s" % test.pk,
job_timeout='72h'
)


def async_test_post_save(test, user, message):
DEFAULT_QUEUE.enqueue(
process_test_post_save,
test.pk,
user.pk,
message,
job_id="test_post_save_%s" % test.pk,
job_timeout='24h'
)
125 changes: 65 additions & 60 deletions events/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ def get_batches(request):

from django.core.exceptions import PermissionDenied

from django.core.exceptions import PermissionDenied
from django.views.decorators.csrf import csrf_protect
from django.db import connection

from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
from django.contrib import messages
Expand All @@ -20,9 +24,8 @@ def get_batches(request):
from django.template import RequestContext
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.http import HttpResponse, HttpResponseBadRequest
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

from django.http import Http404
from django.db.models import Q
from django.db import IntegrityError
Expand Down Expand Up @@ -71,6 +74,12 @@ def get_batches(request):
from PyPDF2 import PdfFileWriter, PdfFileReader
from django.template.context_processors import csrf

from cron.tasks import (
async_process_test_attendance,
async_test_post_save
)


from io import StringIO, BytesIO


Expand Down Expand Up @@ -1858,41 +1867,49 @@ def training_participant_ceritificate(request, wid, participant_id):
return response



@login_required
def test_request(request, role, rid = None):
''' Test request by organiser '''

user = request.user
if not (user.is_authenticated() and ( is_organiser(user) or is_resource_person(user) or is_event_manager(user))):
raise PermissionDenied()
context = {}
form = TestForm(user = user)

if rid:
t = Test.objects.get(pk = rid)
user = t.organiser.user
form = TestForm(user = user, instance = t)
context['instance'] = t

if request.method == 'POST':
form = TestForm(request.POST, user = user)

if form.is_valid():
dateTime = request.POST['tdate'].split(' ')
t = Test()
error = 0

if rid:
t = Test.objects.get(pk = rid)
else:
print("New Test.............")
t = Test()
t.organiser_id = user.organiser.id
t.academic = user.organiser.academic

t.test_category_id = request.POST['test_category']

"""if int(request.POST['test_category']) == 1:
t.training_id = request.POST['workshop']"""
if int(request.POST['test_category']) == 2:
t.training_id = request.POST['training']
if int(request.POST['test_category']) == 3:
else:
t.training_id = None
test_trainings = request.POST['training']
test_training_dept = t.training.department_id
if request.POST['id_foss']:

test_training_dept = None
if t.training_id:
test_training_dept = t.training.department_id

if request.POST.get('id_foss'):
test_foss = request.POST['id_foss']
else:
test_foss = t.training.course.foss_id
Expand All @@ -1901,74 +1918,62 @@ def test_request(request, role, rid = None):
t.foss_id = test_foss
t.tdate = dateTime[0]
t.ttime = dateTime[1]
error = 0
errmsg = ""

try:
t.save()
except IntegrityError as e:
print(f"Test creation failed for {user.email}: {e}")
except IntegrityError:
error = 1
errmsg = "Test already created"
prev_test = Test.objects.filter(organiser = t.organiser_id, academic = t.academic, foss = t.foss_id, tdate = t.tdate, ttime = t.ttime)
if prev_test:
messages.error(request, "You have already scheduled <b>"+ t.foss.foss + "</b> Test on <b>"+t.tdate + " "+ t.ttime + "</b>. Please select some other time.")

if not error and t.id and t.training_id:
tras = TrainingAttend.objects.filter(training=t.training)
fossmdlcourse = get_fossmdlcourse(t.foss_id, fossmdlmap_id=t.training.fossmdlmap_id)
# try:
# fossmdlcourse = FossMdlCourses.objects.get(foss_id = t.foss_id)
# except FossMdlCourses.MultipleObjectsReturned:
# fossmdlcourse = FossMdlCourses.objects.get(id = t.training.fossmdlmap_id)
for tra in tras:
user = tra.student.user
mdluser = get_moodle_user(tra.training.training_planner.academic_id, user.first_name, user.last_name, tra.student.gender, tra.student.user.email)# if it create user rest password for django user too

if mdluser:
print("mdluser present", mdluser.id)
try:
instance = TestAttendance.objects.get(test_id=t.id, mdluser_id=mdluser.id)
except Exception as e:
print(e)
instance = TestAttendance()
instance.student_id = tra.student.id
instance.test_id = t.id
instance.mdluser_id = mdluser.id
instance.mdlcourse_id = fossmdlcourse.mdlcourse_id
instance.mdlquiz_id = fossmdlcourse.mdlquiz_id
instance.mdlattempt_id = 0
instance.status = 0
instance.save()

print("test_attendance created for ",tra.student.id)
else:
print("mdluser not found for", user.email)
error = 1
messages.error(request, "You have already scheduled <b>"+ t.foss.foss + "</b> Test on <b>"+t.tdate + " "+ t.ttime + "</b>. Please select some other time.")

if not error:
t.department.clear()
t.department.add(test_training_dept)
#update logs
message = t.academic.institution_name+" has made a test request for "+t.foss.foss+" on "+t.tdate
# 🔥 async attendance
if t.training_id:
async_process_test_attendance(t)

# 🔥 faster M2M update
if test_training_dept:
t.department.set([test_training_dept])
else:
t.department.clear()

message = (
t.academic.institution_name +
" has made a test request for " +
t.foss.foss + " on " + t.tdate
)
if rid:
message = t.academic.institution_name+" has updated test for "+t.foss.foss+" on dated "+t.tdate
update_events_log(user_id = user.id, role = 0, category = 1, category_id = t.id, academic = t.academic_id, status = 0)
update_events_notification(user_id = user.id, role = 0, category = 1, category_id = t.id, academic = t.academic_id, status = 0, message = message)
message = (
t.academic.institution_name +
" has updated test for " +
t.foss.foss + " dated " + t.tdate
)

# 🔥 async logs & notifications
async_test_post_save(t, user, message)

return HttpResponseRedirect(
"/software-training/test/{}/pending/".format(role)
)

return HttpResponseRedirect("/software-training/test/"+role+"/pending/")
messages.info(request, """
<ul>
<li>Please make sure that before making the test request a faculty/trainer should have registered as invigilator.</li>
<li>Same person cannot be an organiser and the invigilator for the same test.</li>
<li>Please confirm the Invigilator's availability and acceptance to invigilate before selecting his name in this form.</li>
<li>Upgrade the browser with version of Mozilla Firefox 30 or higher on all the systems before the test.</li>
- <li>Please confirm the Invigilator's availability and acceptance to invigilate before selecting his name in this form.</li>
- <li>Upgrade the browser with version of Mozilla Firefox 30 or higher on all the systems before the test.</li>
</ul>
""")

context['role'] = role
context['status'] = 'request'
context.update(csrf(request))
context['form'] = form
return render(request, 'events/templates/test/form.html', context)





@login_required
def test_list(request, role, status):
""" Organiser test index page """
Expand Down