perf(batch): optimise dashboard with query builder
This commit is contained in:
+117
-2
@@ -24,6 +24,8 @@ from frappe.utils import (
|
||||
pretty_date,
|
||||
rounded,
|
||||
)
|
||||
from pypika import Case
|
||||
from pypika import functions as fn
|
||||
|
||||
from lms.lms.md import find_macros
|
||||
|
||||
@@ -1381,6 +1383,116 @@ def get_batch_students(filters, offset=0, limit_start=0, limit_page_length=None,
|
||||
return students
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_batch_student_count(batch):
|
||||
if not frappe.db.exists("LMS Batch", batch):
|
||||
frappe.throw(_("The specified batch does not exist."))
|
||||
return frappe.db.count("LMS Batch Enrollment", filters={"batch": batch})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_batch_certificate_count(batch):
|
||||
if not frappe.db.exists("LMS Batch", batch):
|
||||
frappe.throw(_("The specified batch does not exist."))
|
||||
return frappe.db.count("LMS Certificate", filters={"batch_name": batch})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_batch_assessment_count(batch):
|
||||
if not frappe.db.exists("LMS Batch", batch):
|
||||
frappe.throw(_("The specified batch does not exist."))
|
||||
return frappe.db.count("LMS Assessment", filters={"parent": batch})
|
||||
|
||||
|
||||
def get_course_completion_stats(batch):
|
||||
"""Get completion counts per course in batch"""
|
||||
BatchCourse = frappe.qb.DocType("Batch Course")
|
||||
BatchEnrollment = frappe.qb.DocType("LMS Batch Enrollment")
|
||||
Enrollment = frappe.qb.DocType("LMS Enrollment")
|
||||
|
||||
rows = (
|
||||
frappe.qb.from_(BatchCourse)
|
||||
.left_join(BatchEnrollment)
|
||||
.on(BatchEnrollment.batch == BatchCourse.parent)
|
||||
.left_join(Enrollment)
|
||||
.on((Enrollment.course == BatchCourse.course) & (Enrollment.member == BatchEnrollment.member))
|
||||
.where(BatchCourse.parent == batch)
|
||||
.groupby(BatchCourse.course, BatchCourse.title)
|
||||
.select(
|
||||
BatchCourse.title,
|
||||
fn.Count(Case().when(Enrollment.progress == 100, Enrollment.member)).distinct().as_("completed"),
|
||||
)
|
||||
).run(as_dict=True)
|
||||
|
||||
return [{"task": row.title, "value": row.completed or 0} for row in rows]
|
||||
|
||||
|
||||
def get_assignment_pass_stats(batch):
|
||||
"""Get pass counts per assignment in batch"""
|
||||
Assessment = frappe.qb.DocType("LMS Assessment")
|
||||
Assignment = frappe.qb.DocType("LMS Assignment")
|
||||
BatchEnrollment = frappe.qb.DocType("LMS Batch Enrollment")
|
||||
Submission = frappe.qb.DocType("LMS Assignment Submission")
|
||||
|
||||
rows = (
|
||||
frappe.qb.from_(Assessment)
|
||||
.join(Assignment)
|
||||
.on(Assignment.name == Assessment.assessment_name)
|
||||
.left_join(BatchEnrollment)
|
||||
.on(BatchEnrollment.batch == Assessment.parent)
|
||||
.left_join(Submission)
|
||||
.on(
|
||||
(Submission.assignment == Assessment.assessment_name)
|
||||
& (Submission.member == BatchEnrollment.member)
|
||||
)
|
||||
.where((Assessment.parent == batch) & (Assessment.assessment_type == "LMS Assignment"))
|
||||
.groupby(Assessment.assessment_name, Assignment.title)
|
||||
.select(
|
||||
Assignment.title,
|
||||
fn.Count(Case().when(Submission.status == "Pass", Submission.member)).distinct().as_("passed"),
|
||||
)
|
||||
).run(as_dict=True)
|
||||
|
||||
return [{"task": row.title, "value": row.passed or 0} for row in rows]
|
||||
|
||||
|
||||
def get_quiz_pass_stats(batch):
|
||||
"""Get pass counts per quiz in batch"""
|
||||
Assessment = frappe.qb.DocType("LMS Assessment")
|
||||
Quiz = frappe.qb.DocType("LMS Quiz")
|
||||
BatchEnrollment = frappe.qb.DocType("LMS Batch Enrollment")
|
||||
Submission = frappe.qb.DocType("LMS Quiz Submission")
|
||||
|
||||
rows = (
|
||||
frappe.qb.from_(Assessment)
|
||||
.join(Quiz)
|
||||
.on(Quiz.name == Assessment.assessment_name)
|
||||
.left_join(BatchEnrollment)
|
||||
.on(BatchEnrollment.batch == Assessment.parent)
|
||||
.left_join(Submission)
|
||||
.on((Submission.quiz == Assessment.assessment_name) & (Submission.member == BatchEnrollment.member))
|
||||
.where((Assessment.parent == batch) & (Assessment.assessment_type == "LMS Quiz"))
|
||||
.groupby(Assessment.assessment_name, Quiz.title)
|
||||
.select(
|
||||
Quiz.title,
|
||||
fn.Count(Case().when(Submission.percentage >= Submission.passing_percentage, Submission.member))
|
||||
.distinct()
|
||||
.as_("passed"),
|
||||
)
|
||||
).run(as_dict=True)
|
||||
|
||||
return [{"task": row.title, "value": row.passed or 0} for row in rows]
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_batch_chart_data(batch):
|
||||
"""Get completion counts per course and assessment"""
|
||||
if not frappe.db.exists("LMS Batch", batch):
|
||||
frappe.throw(_("The specified batch does not exist."))
|
||||
|
||||
return get_course_completion_stats(batch) + get_assignment_pass_stats(batch) + get_quiz_pass_stats(batch)
|
||||
|
||||
|
||||
def get_batch_student_details(student):
|
||||
details = frappe.db.get_value(
|
||||
"User",
|
||||
@@ -1423,8 +1535,11 @@ def calculate_course_progress(batch_courses, details):
|
||||
details.courses = frappe._dict()
|
||||
|
||||
for course in batch_courses:
|
||||
progress = frappe.db.get_value(
|
||||
"LMS Enrollment", {"course": course.course, "member": details.email}, "progress"
|
||||
progress = (
|
||||
frappe.db.get_value(
|
||||
"LMS Enrollment", {"course": course.course, "member": details.email}, "progress"
|
||||
)
|
||||
or 0
|
||||
)
|
||||
details.courses[course.title] = progress
|
||||
course_progress.append(progress)
|
||||
|
||||
Reference in New Issue
Block a user