From da39da627c5fc5ffad8ea15858ab485fea4935a2 Mon Sep 17 00:00:00 2001 From: scmmishra Date: Thu, 13 Dec 2018 11:51:31 +0530 Subject: [PATCH] [Major][Breaking] Server side changes to handle Topic Layer - Moved `get_course_progress` to CourseEnrollment class. - Added Topic context to progress functions in lms.py - Create user on creation of a student --- .../course_enrollment/course_enrollment.py | 34 +++++++----------- erpnext/education/doctype/student/student.py | 7 ++-- erpnext/education/utils.py | 8 ++--- erpnext/www/lms.py | 35 +++++++++---------- 4 files changed, 37 insertions(+), 47 deletions(-) diff --git a/erpnext/education/doctype/course_enrollment/course_enrollment.py b/erpnext/education/doctype/course_enrollment/course_enrollment.py index dd90a5e96e..a70d40d089 100644 --- a/erpnext/education/doctype/course_enrollment/course_enrollment.py +++ b/erpnext/education/doctype/course_enrollment/course_enrollment.py @@ -5,27 +5,19 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document +from functools import reduce class CourseEnrollment(Document): - - def get_linked_activity(self): - course_activity_list = frappe.get_all("Course Activity", filters={'enrollment':self.name}) - course_activity = [frappe.get_doc("Course Activity", activity.name) for activity in course_activity_list] - quiz_activity_list = frappe.get_all("Quiz Activity", filters={'enrollment':self.name}) - quiz_activity = [frappe.get_doc("Quiz Activity", activity.name) for activity in quiz_activity_list] - return course_activity, quiz_activity + def get_progress(self, student): + """ + Returns Progress of given student for a particular course enrollment - def get_all_activity(self): - courses, quizes = self.get_linked_activity() - joined = courses + quizes - activity = sorted(joined, key = lambda i: i.modified) # Sorting based on modified timestamp - return activity - - def check_course_completion(self): - pass - - def get_last_activity(self): - if len(self.get_all_activity()) == 0: - return None - else: - return self.get_all_activity()[-1] \ No newline at end of file + :param self: Course Enrollment Object + :param student: Student Object + """ + course = frappe.get_doc('Course', self.course) + topics = course.get_topics() + progress = [] + for topic in topics: + progress.append(student.get_topic_progress(self.name, topic)) + return reduce(lambda x,y: x+y, progress) # Flatten out the List \ No newline at end of file diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py index 64b6d9a341..dbd154b1ee 100644 --- a/erpnext/education/doctype/student/student.py +++ b/erpnext/education/doctype/student/student.py @@ -40,6 +40,9 @@ class Student(Document): frappe.throw(_("Student {0} exist against student applicant {1}").format(student[0][0], self.student_applicant)) def after_insert(self): + self.create_student() + + def create_student(self): """Create a website user for student creation if not already exists""" if self.user == None: student_user = frappe.get_doc({ @@ -56,8 +59,6 @@ class Student(Document): self.user = student_user.name self.save() update_password_link = student_user.reset_password() - print(update_password_link) - def update_applicant_status(self): """Updates Student Applicant status to Admitted""" @@ -66,7 +67,7 @@ class Student(Document): def get_all_course_enrollments(self): """Returns a list of course enrollments linked with the current student""" - course_enrollments = frappe.get_list("Course Enrollment", filters={"student": self.name}, fields=['course', 'name']) + course_enrollments = frappe.get_all("Course Enrollment", filters={"student": self.name}, fields=['course', 'name']) if not course_enrollments: return None else: diff --git a/erpnext/education/utils.py b/erpnext/education/utils.py index 01cd5f3872..0aa5555082 100644 --- a/erpnext/education/utils.py +++ b/erpnext/education/utils.py @@ -65,7 +65,7 @@ def get_current_student(): if email in ('Administrator', 'Guest'): return None try: - student_id = frappe.db.get_all("Student", {"student_email_id": email}, ["name"])[0].name + student_id = frappe.get_all("Student", {"student_email_id": email}, ["name"])[0].name return student_id except IndexError: return None @@ -78,7 +78,7 @@ def get_program_enrollment(program_name): if not student: return None else: - enrollment = frappe.get_list("Program Enrollment", filters={'student':student, 'program': program_name}) + enrollment = frappe.get_all("Program Enrollment", filters={'student':student, 'program': program_name}) if enrollment: return enrollment[0].name else: @@ -122,14 +122,14 @@ def check_activity_exists(enrollment, content_type, content): return bool(activity) def check_content_completion(content_name, content_type, enrollment_name): - activity = frappe.get_list("Course Activity", filters={'enrollment': enrollment_name, 'content_type': content_type, 'content': content_name}) + activity = frappe.get_all("Course Activity", filters={'enrollment': enrollment_name, 'content_type': content_type, 'content': content_name}) if activity: return True else: return False def check_quiz_completion(quiz, enrollment_name): - attempts = frappe.get_list("Quiz Activity", filters={'enrollment': enrollment_name, 'quiz': quiz.name}, fields=["name", "activity_date", "score", "status"]) + attempts = frappe.get_all("Quiz Activity", filters={'enrollment': enrollment_name, 'quiz': quiz.name}, fields=["name", "activity_date", "score", "status"]) status = bool(len(attempts) == quiz.max_attempts) score = None result = None diff --git a/erpnext/www/lms.py b/erpnext/www/lms.py index 2af6ca98db..def75a4dd9 100644 --- a/erpnext/www/lms.py +++ b/erpnext/www/lms.py @@ -70,12 +70,12 @@ def get_courses(program_name): return courses @frappe.whitelist() -def get_next_content(content, content_type, course): +def get_next_content(current_content, current_content_type, topic): if frappe.session.user == "Guest": return None - course_doc = frappe.get_doc("Course", course) - content_list = [{'content_type':item.content_type, 'content':item.content} for item in course_doc.get_all_children()] - current_index = content_list.index({'content': content, 'content_type': content_type}) + topic = frappe.get_doc("Topic", topic) + content_list = [{'content_type':item.doctype, 'content':item.name} for item in topic.get_contents()] + current_index = content_list.index({'content': current_content, 'content_type': current_content_type}) try: # print(content_list[current_index + 1]) return content_list[current_index + 1] @@ -166,26 +166,22 @@ def add_activity(course, content_type, content): activity.save() frappe.db.commit() -def get_course_progress(course_enrollment): - student_id = utils.get_current_student() - student = frappe.get_doc("Student", student_id) - course = frappe.get_doc('Course', course_enrollment.course) - topics = course.get_topics() - progress = [] - for topic in topics: - progress.append(student.get_topic_progress(course_enrollment.name, topic)) - return progress - @frappe.whitelist() def get_course_meta(course_name, program_name): + """ + Return the porgress of a course in a program as well as the content to continue from. + :param course_name: + :param program_name: + """ course_enrollment = utils.get_course_enrollment(course_name) program_enrollment = utils.get_program_enrollment(program_name) + student = frappe.get_doc("Student", utils.get_current_student()) if not program_enrollment: return None if not course_enrollment: utils.enroll_in_course(course_name, program_name) - progress = get_course_progress(course_enrollment) - count = sum([act['is_complete'] for act in progress]) + progress = course_enrollment.get_progress(student) + count = sum([activity['is_complete'] for activity in progress]) if count == 0: return {'flag':'Start Course', 'content_type': progress[0]['content_type'], 'content': progress[0]['content']} elif count == len(progress): @@ -198,7 +194,7 @@ def get_course_meta(course_name, program_name): def get_program_progress(program_name): import math program = frappe.get_doc("Program", program_name) - program_enrollment = frappe.get_list("Program Enrollment", filters={'student': utils.get_current_student(), 'program': program_name })[0].name + program_enrollment = utils.get_program_enrollment(program_name) program_meta = {} if not program_enrollment: return None @@ -224,15 +220,16 @@ def get_joining_date(): @frappe.whitelist() def get_quiz_progress(program_name): program = frappe.get_doc("Program", program_name) - program_enrollment = frappe.get_list("Program Enrollment", filters={'student': utils.get_current_student(), 'program': program_name })[0].name + program_enrollment = utils.get_program_enrollment(program_name) quiz_meta = frappe._dict() + student = frappe.get_doc("Student", utils.get_current_student()) if not program_enrollment: return None else: progress_list = [] for course in program.get_all_children(): course_enrollment = utils.get_course_enrollment(course.course) - meta = get_course_progress(course_enrollment) + meta = course_enrollment.get_progress(student) for progress_item in meta: # if progress_item['content_type'] == "Quiz" and progress_item['is_complete'] == True: if progress_item['content_type'] == "Quiz":