| from __future__ import unicode_literals |
| import erpnext.education.utils as utils |
| import frappe |
| from frappe import _ |
| |
| # LMS Utils to Update State for Vue Store |
| @frappe.whitelist() |
| def get_program_enrollments(): |
| student = utils.get_current_student() |
| if student == None: |
| return None |
| return student.get_program_enrollments() |
| |
| @frappe.whitelist() |
| def get_all_course_enrollments(): |
| student = utils.get_current_student() |
| if student == None: |
| return None |
| return student.get_all_course_enrollments() |
| |
| # Vue Client Functions |
| @frappe.whitelist(allow_guest=True) |
| def get_portal_details(): |
| """ |
| Returns portal details from Education Settings Doctype. This contains the Title and Description for LMS amoung other things. |
| """ |
| from erpnext import get_default_company |
| |
| settings = frappe.get_doc("Education Settings") |
| title = settings.portal_title or get_default_company() |
| description = settings.description |
| return dict(title=title, description=description) |
| |
| @frappe.whitelist(allow_guest=True) |
| def get_featured_programs(): |
| featured_program_names = frappe.get_all("Program", filters={"is_published": True, "is_featured": True}) |
| if featured_program_names: |
| featured_list = [utils.get_program_and_enrollment_status(program['name']) for program in featured_program_names] |
| return featured_list |
| else: |
| return get_all_programs()[:2] |
| |
| @frappe.whitelist(allow_guest=True) |
| def get_all_programs(): |
| program_names = frappe.get_all("Program", filters={"is_published": True}) |
| if program_names: |
| program_list = [utils.get_program_and_enrollment_status(program['name']) for program in program_names] |
| return program_list |
| |
| @frappe.whitelist(allow_guest=True) |
| def get_program(program_name): |
| try: |
| return frappe.get_doc('Program', program_name) |
| except frappe.DoesNotExistError: |
| frappe.throw(_("Program {0} does not exist.".format(program_name))) |
| |
| # Functions to get program & course details |
| @frappe.whitelist(allow_guest=True) |
| def get_courses(program_name): |
| program = frappe.get_doc('Program', program_name) |
| courses = program.get_course_list() |
| return courses |
| |
| @frappe.whitelist() |
| def get_next_content(current_content, current_content_type, topic): |
| if frappe.session.user == "Guest": |
| return None |
| 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: |
| return content_list[current_index + 1] |
| except IndexError: |
| return None |
| |
| def get_quiz_with_answers(quiz_name): |
| try: |
| quiz = frappe.get_doc("Quiz", quiz_name).get_questions() |
| quiz_output = [{'name':question.name, 'question':question.question, 'options':[{'name': option.name, 'option':option.option, 'is_correct':option.is_correct} for option in question.options]} for question in quiz] |
| return quiz_output |
| except: |
| frappe.throw("Quiz {0} does not exist".format(quiz_name)) |
| return None |
| |
| @frappe.whitelist() |
| def get_quiz_without_answers(quiz_name, course_name): |
| try: |
| quiz = frappe.get_doc("Quiz", quiz_name) |
| questions = quiz.get_questions() |
| except: |
| frappe.throw("Quiz {0} does not exist".format(quiz_name)) |
| return None |
| |
| if utils.check_super_access(): |
| quiz_output = [{'name':question.name, 'question':question.question, 'type': question.type, 'options':[{'name': option.name, 'option':option.option} for option in question.options]} for question in questions] |
| return { 'quizData': quiz_output, 'status': None} |
| |
| enrollment = utils.get_course_enrollment(course_name).name |
| quiz_progress = {} |
| quiz_progress['is_complete'], quiz_progress['score'], quiz_progress['result'] = utils.check_quiz_completion(quiz, enrollment) |
| quiz_output = [{'name':question.name, 'question':question.question, 'type': question.type, 'options':[{'name': option.name, 'option':option.option} for option in question.options]} for question in questions] |
| return { 'quizData': quiz_output, 'status': quiz_progress} |
| |
| @frappe.whitelist() |
| def evaluate_quiz(course, quiz_response, quiz_name): |
| """LMS Function: Evaluates a simple multiple choice quiz. |
| :param course: name of the course |
| :param quiz_response: contains user selected choices for a quiz in the form of a string formatted as a dictionary. The function uses `json.loads()` to convert it to a python dictionary. |
| :param quiz_name: Name of the quiz attempted |
| """ |
| import json |
| quiz_response = json.loads(quiz_response) |
| quiz = frappe.get_doc("Quiz", quiz_name) |
| answers, score, status = quiz.evaluate(quiz_response, quiz_name) |
| print(answers) |
| |
| course_enrollment = utils.get_course_enrollment(course) |
| if course_enrollment: |
| course_enrollment.add_quiz_activity(quiz_name, quiz_response, answers, score, status) |
| |
| return score |
| |
| @frappe.whitelist() |
| def enroll_in_program(program_name): |
| student = utils.get_current_student() |
| if not student: |
| student = utils.create_student_from_current_user() |
| program_enrollment = student.enroll_in_program(program_name) |
| return program_name |
| |
| # Academdy Activity |
| @frappe.whitelist() |
| def add_activity(course, content_type, content): |
| if not utils.get_current_student(): |
| return |
| enrollment = utils.get_course_enrollment(course) |
| enrollment.add_activity(content_type, content) |
| |
| @frappe.whitelist() |
| def get_student_course_details(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: |
| """ |
| student = utils.get_current_student() |
| if not student: |
| return {'flag':'Start Course' } |
| |
| course_enrollment = utils.get_course_enrollment(course_name) |
| program_enrollment = utils.get_program_enrollment(program_name) |
| |
| if not program_enrollment: |
| return None |
| |
| if not course_enrollment: |
| course_enrollment = utils.enroll_in_course(course_name, program_name) |
| |
| progress = course_enrollment.get_progress(student) |
| count = sum([activity['is_complete'] for activity in progress]) |
| if count == 0: |
| return {'flag':'Start Course'} |
| elif count == len(progress): |
| return {'flag':'Completed'} |
| elif count < len(progress): |
| next_item = next(item for item in progress if item['is_complete']==False) |
| return {'flag':'Continue'} |
| |
| @frappe.whitelist() |
| def get_student_topic_details(topic_name, course_name): |
| """ |
| Return the porgress of a course in a program as well as the content to continue from. |
| :param topic_name: |
| :param course_name: |
| """ |
| topic = frappe.get_doc("Topic", topic_name) |
| student = utils.get_current_student() |
| if not student: |
| topic_content = topic.get_all_children() |
| if topic_content: |
| return {'flag':'Start Course', 'content_type': topic_content[0].content_type, 'content': topic_content[0].content} |
| else: |
| return None |
| course_enrollment = utils.get_course_enrollment(course_name) |
| progress = student.get_topic_progress(course_enrollment.name, topic) |
| if not progress: |
| return { 'flag':'Start Topic', 'content_type': None, 'content': None } |
| count = sum([activity['is_complete'] for activity in progress]) |
| if count == 0: |
| return {'flag':'Start Topic', 'content_type': progress[0]['content_type'], 'content': progress[0]['content']} |
| elif count == len(progress): |
| return {'flag':'Completed', 'content_type': progress[0]['content_type'], 'content': progress[0]['content']} |
| elif count < len(progress): |
| next_item = next(item for item in progress if item['is_complete']==False) |
| return {'flag':'Continue', 'content_type': next_item['content_type'], 'content': next_item['content']} |
| |
| @frappe.whitelist() |
| def get_program_progress(program_name): |
| program_enrollment = frappe.get_doc("Program Enrollment", utils.get_program_enrollment(program_name)) |
| if not program_enrollment: |
| return None |
| else: |
| return program_enrollment.get_program_progress() |
| |
| @frappe.whitelist() |
| def get_joining_date(): |
| student = utils.get_current_student() |
| if student: |
| return student.joining_date |
| |
| @frappe.whitelist() |
| def get_quiz_progress_of_program(program_name): |
| program_enrollment = frappe.get_doc("Program Enrollment", utils.get_program_enrollment(program_name)) |
| if not program_enrollment: |
| return None |
| else: |
| return program_enrollment.get_quiz_progress() |
| |
| |
| @frappe.whitelist(allow_guest=True) |
| def get_course_details(course_name): |
| try: |
| course = frappe.get_doc('Course', course_name) |
| return course |
| except: |
| return None |
| |
| # Functions to get program & course details |
| @frappe.whitelist(allow_guest=True) |
| def get_topics(course_name): |
| try: |
| course = frappe.get_doc('Course', course_name) |
| return course.get_topics() |
| except frappe.DoesNotExistError: |
| frappe.throw(_("Course {0} does not exist.".format(course_name))) |
| |
| @frappe.whitelist() |
| def get_content(content_type, content): |
| try: |
| return frappe.get_doc(content_type, content) |
| except frappe.DoesNotExistError: |
| frappe.throw(_("{0} {1} does not exist.".format(content_type, content))) |