From fb0f9885c1778ca57de58abdeb43ebd98da1ea1a Mon Sep 17 00:00:00 2001 From: pateljannat Date: Tue, 28 Sep 2021 18:03:12 +0530 Subject: [PATCH 1/2] feat: course progress summary --- .../lms/doctype/lms_course/lms_course.py | 4 +- community/lms/report/__init__.py | 0 .../course_progress_summary/__init__.py | 0 .../course_progress_summary.js | 14 +++ .../course_progress_summary.json | 26 +++++ .../course_progress_summary.py | 106 ++++++++++++++++++ 6 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 community/lms/report/__init__.py create mode 100644 community/lms/report/course_progress_summary/__init__.py create mode 100644 community/lms/report/course_progress_summary/course_progress_summary.js create mode 100644 community/lms/report/course_progress_summary/course_progress_summary.json create mode 100644 community/lms/report/course_progress_summary/course_progress_summary.py diff --git a/community/lms/doctype/lms_course/lms_course.py b/community/lms/doctype/lms_course/lms_course.py index 56330d77..d2805505 100644 --- a/community/lms/doctype/lms_course/lms_course.py +++ b/community/lms/doctype/lms_course/lms_course.py @@ -329,6 +329,8 @@ class LMSCourse(Document): def get_course_progress(self, member=None): """ Returns the course progress of the session user """ lesson_count = len(self.get_lessons()) + if not lesson_count: + return 0 completed_lessons = frappe.db.count("LMS Course Progress", { "course": self.name, @@ -336,8 +338,6 @@ class LMSCourse(Document): "status": "Complete" }) precision = cint(frappe.db.get_default("float_precision")) or 3 - if not lesson_count: - return 0 return flt(((completed_lessons/lesson_count) * 100), precision) def get_neighbours(self, current, lessons): diff --git a/community/lms/report/__init__.py b/community/lms/report/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/community/lms/report/course_progress_summary/__init__.py b/community/lms/report/course_progress_summary/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/community/lms/report/course_progress_summary/course_progress_summary.js b/community/lms/report/course_progress_summary/course_progress_summary.js new file mode 100644 index 00000000..668e5000 --- /dev/null +++ b/community/lms/report/course_progress_summary/course_progress_summary.js @@ -0,0 +1,14 @@ +// Copyright (c) 2016, FOSS United and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Course Progress Summary"] = { + "filters": [ + { + "fieldname": "course", + "label": __("Course"), + "fieldtype": "Link", + "options": "LMS Course" + } + ] +}; diff --git a/community/lms/report/course_progress_summary/course_progress_summary.json b/community/lms/report/course_progress_summary/course_progress_summary.json new file mode 100644 index 00000000..c3e85f54 --- /dev/null +++ b/community/lms/report/course_progress_summary/course_progress_summary.json @@ -0,0 +1,26 @@ +{ + "add_total_row": 0, + "columns": [], + "creation": "2021-09-28 15:31:27.205036", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "modified": "2021-09-28 17:09:40.761819", + "modified_by": "Administrator", + "module": "LMS", + "name": "Course Progress Summary", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "LMS Batch Membership", + "report_name": "Course Progress Summary", + "report_type": "Script Report", + "roles": [ + { + "role": "System Manager" + } + ] +} \ No newline at end of file diff --git a/community/lms/report/course_progress_summary/course_progress_summary.py b/community/lms/report/course_progress_summary/course_progress_summary.py new file mode 100644 index 00000000..67f5e4cb --- /dev/null +++ b/community/lms/report/course_progress_summary/course_progress_summary.py @@ -0,0 +1,106 @@ +# Copyright (c) 2013, FOSS United and contributors +# License: MIT. See LICENSE + +import frappe +from frappe.utils import rounded +from frappe import _ + +def execute(filters=None): + columns, data = [], [] + columns = get_columns() + data = get_data(filters) + charts = get_charts(data) + return columns, data, [], charts + +def get_data(filters=None): + summary = [] + query_filter = {} + if filters: + query_filter = { + "course": filters.course + } + + memberships = frappe.get_all( + "LMS Batch Membership", + query_filter, + ["name", "course", "member", "member_name"], + order_by="course") + + current_course = memberships[0].course + for membership in memberships: + if current_course != membership.course: + current_course = membership.course + + course_details = frappe.get_doc("LMS Course", current_course) + summary.append(frappe._dict({ + "course": course_details.title, + "member": membership.member_name, + "progress": rounded(course_details.get_course_progress(membership.member)) + })) + + return summary + +def get_columns(): + return [ + { + "fieldname": "course", + "fieldtype": "Link", + "label": _("Course"), + "options": "LMS Course", + "width": 300 + }, + { + "fieldname": "member", + "fieldtype": "Link", + "label": _("Member"), + "options": "User", + "width": 150 + }, + { + "fieldname": "progress", + "fieldtype": "Data", + "label": _("Progress (%)"), + "width": 150 + } + ] + +def get_charts(data): + if not data: + return None + + labels = [] + completed = 0 + less_than_hundred = 0 + less_than_seventy = 0 + less_than_forty = 0 + less_than_ten = 0 + + + for row in data: + if row.progress == 100: + completed += 1 + elif row.progress < 100 and row.progress > 70: + less_than_hundred += 1 + elif row.progress < 70 and row.progress > 40: + less_than_seventy += 1 + elif row.progress < 40 and row.progress > 10: + less_than_forty += 1 + elif row.progress < 10: + less_than_ten += 1 + + + + charts = { + "data": { + "labels": ["0-10", "10-40", "40-70", "70-99", "100"], + "datasets": [ + { + "name": "Progress (%)", + "values": [less_than_ten, less_than_forty, less_than_seventy, less_than_hundred, completed] + } + ] + }, + "type": "pie", + "colors": ["#ff0e0e", "#ff9966", "#ffcc00", "#99cc33", "#339900"] + } + return charts From ea6bd1f59828b0edd753f476b6ad8d63bac3a76a Mon Sep 17 00:00:00 2001 From: pateljannat Date: Tue, 28 Sep 2021 19:58:07 +0530 Subject: [PATCH 2/2] fix: columns --- .../course_progress_summary.py | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/community/lms/report/course_progress_summary/course_progress_summary.py b/community/lms/report/course_progress_summary/course_progress_summary.py index 67f5e4cb..efda989f 100644 --- a/community/lms/report/course_progress_summary/course_progress_summary.py +++ b/community/lms/report/course_progress_summary/course_progress_summary.py @@ -33,8 +33,10 @@ def get_data(filters=None): course_details = frappe.get_doc("LMS Course", current_course) summary.append(frappe._dict({ - "course": course_details.title, - "member": membership.member_name, + "course": course_details.name, + "course_name": course_details.title, + "member": membership.member, + "member_name": membership.member_name, "progress": rounded(course_details.get_course_progress(membership.member)) })) @@ -47,6 +49,12 @@ def get_columns(): "fieldtype": "Link", "label": _("Course"), "options": "LMS Course", + "width": 200 + }, + { + "fieldname": "course_name", + "fieldtype": "Data", + "label": _("Course Name"), "width": 300 }, { @@ -54,13 +62,19 @@ def get_columns(): "fieldtype": "Link", "label": _("Member"), "options": "User", + "width": 200 + }, + { + "fieldname": "member_name", + "fieldtype": "Data", + "label": _("Member Name"), "width": 150 }, { "fieldname": "progress", "fieldtype": "Data", "label": _("Progress (%)"), - "width": 150 + "width": 120 } ] @@ -68,14 +82,12 @@ def get_charts(data): if not data: return None - labels = [] completed = 0 less_than_hundred = 0 less_than_seventy = 0 less_than_forty = 0 less_than_ten = 0 - for row in data: if row.progress == 100: completed += 1 @@ -88,8 +100,6 @@ def get_charts(data): elif row.progress < 10: less_than_ten += 1 - - charts = { "data": { "labels": ["0-10", "10-40", "40-70", "70-99", "100"],