diff --git a/lms/lms/doctype/course_evaluator/__init__.py b/lms/lms/doctype/course_evaluator/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/lms/lms/doctype/course_evaluator/course_evaluator.js b/lms/lms/doctype/course_evaluator/course_evaluator.js new file mode 100644 index 00000000..eb893de9 --- /dev/null +++ b/lms/lms/doctype/course_evaluator/course_evaluator.js @@ -0,0 +1,6 @@ +// Copyright (c) 2022, Frappe and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Course Evaluator', { + +}); diff --git a/lms/lms/doctype/course_evaluator/course_evaluator.json b/lms/lms/doctype/course_evaluator/course_evaluator.json new file mode 100644 index 00000000..1a7d04fe --- /dev/null +++ b/lms/lms/doctype/course_evaluator/course_evaluator.json @@ -0,0 +1,51 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2022-03-29 10:51:47.667284", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "evaluator", + "schedule" + ], + "fields": [ + { + "fieldname": "evaluator", + "fieldtype": "Link", + "label": "Evaluator", + "options": "User" + }, + { + "fieldname": "schedule", + "fieldtype": "Table", + "label": "Schedule", + "options": "Evaluator Schedule" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2022-03-29 12:47:10.975155", + "modified_by": "Administrator", + "module": "LMS", + "name": "Course Evaluator", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "title_field": "evaluator" +} \ No newline at end of file diff --git a/lms/lms/doctype/course_evaluator/course_evaluator.py b/lms/lms/doctype/course_evaluator/course_evaluator.py new file mode 100644 index 00000000..20b83470 --- /dev/null +++ b/lms/lms/doctype/course_evaluator/course_evaluator.py @@ -0,0 +1,33 @@ +# Copyright (c) 2022, Frappe and contributors +# For license information, please see license.txt + +import frappe +from frappe import _ +from frappe.model.document import Document + +class CourseEvaluator(Document): + + def validate(self): + self.validate_time_slots() + + def validate_time_slots(self): + for schedule in self.schedule: + if schedule.start_time >= schedule.end_time: + frappe.throw(_("Start Time cannot be greater than End Time")) + + self.validate_overlaps(schedule) + + def validate_overlaps(self, schedule): + same_day_slots = list(filter(lambda x: x.day == schedule.day and x.name != schedule.name , self.schedule)) + overlap = False + + for slot in same_day_slots: + if schedule.start_time < slot.start_time < schedule.end_time: + overlap = True + if schedule.start_time < slot.end_time < schedule.end_time: + overlap = True + if slot.start_time < schedule.start_time and schedule.end_time < slot.end_time: + overlap = True + + if overlap: + frappe.throw(_("Slot Times are overlapping for some schedules.")) diff --git a/lms/lms/doctype/course_evaluator/test_course_evaluator.py b/lms/lms/doctype/course_evaluator/test_course_evaluator.py new file mode 100644 index 00000000..cde3cf75 --- /dev/null +++ b/lms/lms/doctype/course_evaluator/test_course_evaluator.py @@ -0,0 +1,9 @@ +# Copyright (c) 2022, Frappe and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestCourseEvaluator(FrappeTestCase): + pass diff --git a/lms/lms/doctype/evaluator_schedule/__init__.py b/lms/lms/doctype/evaluator_schedule/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/lms/lms/doctype/evaluator_schedule/evaluator_schedule.json b/lms/lms/doctype/evaluator_schedule/evaluator_schedule.json new file mode 100644 index 00000000..9821c145 --- /dev/null +++ b/lms/lms/doctype/evaluator_schedule/evaluator_schedule.json @@ -0,0 +1,50 @@ +{ + "actions": [], + "autoname": "autoincrement", + "creation": "2022-03-29 11:09:47.726629", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "day", + "start_time", + "end_time" + ], + "fields": [ + { + "fieldname": "day", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Day", + "options": "Sunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday", + "reqd": 1 + }, + { + "fieldname": "start_time", + "fieldtype": "Time", + "in_list_view": 1, + "label": "Start Time", + "reqd": 1 + }, + { + "fieldname": "end_time", + "fieldtype": "Time", + "in_list_view": 1, + "label": "End Time", + "reqd": 1 + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2022-03-29 12:58:22.229033", + "modified_by": "Administrator", + "module": "LMS", + "name": "Evaluator Schedule", + "naming_rule": "Autoincrement", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/lms/lms/doctype/evaluator_schedule/evaluator_schedule.py b/lms/lms/doctype/evaluator_schedule/evaluator_schedule.py new file mode 100644 index 00000000..894126db --- /dev/null +++ b/lms/lms/doctype/evaluator_schedule/evaluator_schedule.py @@ -0,0 +1,8 @@ +# Copyright (c) 2022, Frappe and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + +class EvaluatorSchedule(Document): + pass diff --git a/lms/lms/doctype/lms_batch_membership/lms_batch_membership.json b/lms/lms/doctype/lms_batch_membership/lms_batch_membership.json index 07061b24..7a8123f0 100644 --- a/lms/lms/doctype/lms_batch_membership/lms_batch_membership.json +++ b/lms/lms/doctype/lms_batch_membership/lms_batch_membership.json @@ -115,7 +115,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2022-03-09 15:17:15.386067", + "modified": "2022-03-29 09:47:05.007133", "modified_by": "Administrator", "module": "LMS", "name": "LMS Batch Membership", @@ -135,7 +135,9 @@ } ], "quick_entry": 1, + "show_title_field_in_link": 1, "sort_field": "modified", "sort_order": "DESC", - "states": [] + "states": [], + "title_field": "member" } \ No newline at end of file diff --git a/lms/lms/doctype/lms_certificate_evaluation/__init__.py b/lms/lms/doctype/lms_certificate_evaluation/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.js b/lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.js new file mode 100644 index 00000000..094b2345 --- /dev/null +++ b/lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.js @@ -0,0 +1,23 @@ +// Copyright (c) 2022, Frappe and contributors +// For license information, please see license.txt + +frappe.ui.form.on('LMS Certificate Evaluation', { + onload: function(frm) { + frm.set_query("course", function(doc) { + return { + filters: { + "enable_certification": true, + "grant_certificate_after": "Evaluation" + } + }; + }); + + frm.set_query("member", function(doc) { + return { + filters: { + "course": doc.course, + } + }; + }); + } +}); diff --git a/lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json b/lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json new file mode 100644 index 00000000..e9cc5f38 --- /dev/null +++ b/lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json @@ -0,0 +1,86 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2022-03-29 09:32:16.769951", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "course", + "member", + "start", + "end", + "column_break_5", + "rating", + "summary" + ], + "fields": [ + { + "fieldname": "course", + "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Course", + "options": "LMS Course", + "reqd": 1 + }, + { + "fieldname": "member", + "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Member", + "options": "LMS Batch Membership", + "reqd": 1 + }, + { + "fieldname": "start", + "fieldtype": "Datetime", + "label": "Start" + }, + { + "fieldname": "end", + "fieldtype": "Datetime", + "label": "End" + }, + { + "fieldname": "column_break_5", + "fieldtype": "Column Break" + }, + { + "fieldname": "rating", + "fieldtype": "Rating", + "in_list_view": 1, + "label": "Rating" + }, + { + "fieldname": "summary", + "fieldtype": "Text", + "label": "Summary" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2022-03-29 09:48:45.682678", + "modified_by": "Administrator", + "module": "LMS", + "name": "LMS Certificate Evaluation", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.py b/lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.py new file mode 100644 index 00000000..86a2d1fd --- /dev/null +++ b/lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.py @@ -0,0 +1,8 @@ +# Copyright (c) 2022, Frappe and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + +class LMSCertificateEvaluation(Document): + pass diff --git a/lms/lms/doctype/lms_certificate_evaluation/test_lms_certificate_evaluation.py b/lms/lms/doctype/lms_certificate_evaluation/test_lms_certificate_evaluation.py new file mode 100644 index 00000000..06e6996e --- /dev/null +++ b/lms/lms/doctype/lms_certificate_evaluation/test_lms_certificate_evaluation.py @@ -0,0 +1,9 @@ +# Copyright (c) 2022, Frappe and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestLMSCertificateEvaluation(FrappeTestCase): + pass diff --git a/lms/lms/doctype/lms_certificate_request/__init__.py b/lms/lms/doctype/lms_certificate_request/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/lms/lms/doctype/lms_certificate_request/lms_certificate_request.js b/lms/lms/doctype/lms_certificate_request/lms_certificate_request.js new file mode 100644 index 00000000..4ee82193 --- /dev/null +++ b/lms/lms/doctype/lms_certificate_request/lms_certificate_request.js @@ -0,0 +1,8 @@ +// Copyright (c) 2022, Frappe and contributors +// For license information, please see license.txt + +frappe.ui.form.on('LMS Certificate Request', { + // refresh: function(frm) { + + // } +}); diff --git a/lms/lms/doctype/lms_certificate_request/lms_certificate_request.json b/lms/lms/doctype/lms_certificate_request/lms_certificate_request.json new file mode 100644 index 00000000..e482f9e0 --- /dev/null +++ b/lms/lms/doctype/lms_certificate_request/lms_certificate_request.json @@ -0,0 +1,66 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2022-03-29 10:43:50.889723", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "course", + "member", + "evaluator", + "slot" + ], + "fields": [ + { + "fieldname": "course", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Course", + "options": "LMS Course", + "reqd": 1 + }, + { + "fieldname": "member", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Member", + "options": "LMS Batch Membership", + "reqd": 1 + }, + { + "fieldname": "evaluator", + "fieldtype": "Data", + "label": "Evaluator" + }, + { + "fieldname": "slot", + "fieldtype": "Data", + "label": "Slot" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2022-03-29 10:43:50.889723", + "modified_by": "Administrator", + "module": "LMS", + "name": "LMS Certificate Request", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/lms/lms/doctype/lms_certificate_request/lms_certificate_request.py b/lms/lms/doctype/lms_certificate_request/lms_certificate_request.py new file mode 100644 index 00000000..e6c629f0 --- /dev/null +++ b/lms/lms/doctype/lms_certificate_request/lms_certificate_request.py @@ -0,0 +1,8 @@ +# Copyright (c) 2022, Frappe and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + +class LMSCertificateRequest(Document): + pass diff --git a/lms/lms/doctype/lms_certificate_request/test_lms_certificate_request.py b/lms/lms/doctype/lms_certificate_request/test_lms_certificate_request.py new file mode 100644 index 00000000..87149242 --- /dev/null +++ b/lms/lms/doctype/lms_certificate_request/test_lms_certificate_request.py @@ -0,0 +1,9 @@ +# Copyright (c) 2022, Frappe and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestLMSCertificateRequest(FrappeTestCase): + pass diff --git a/lms/lms/doctype/lms_course/lms_course.json b/lms/lms/doctype/lms_course/lms_course.json index f07718eb..e4bb8a2f 100644 --- a/lms/lms/doctype/lms_course/lms_course.json +++ b/lms/lms/doctype/lms_course/lms_course.json @@ -34,7 +34,11 @@ "related_courses", "certification_section", "enable_certification", - "expiry" + "expiry", + "column_break_22", + "paid_certificate", + "grant_certificate_after", + "evaluator" ], "fields": [ { @@ -129,9 +133,8 @@ "default": "0", "depends_on": "enable_certification", "fieldname": "expiry", - "fieldtype": "Select", - "label": "Certification Expires After Years", - "options": "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10" + "fieldtype": "Int", + "label": "Certification Expires After (Years)" }, { "fieldname": "related_courses", @@ -161,6 +164,31 @@ { "fieldname": "column_break_12", "fieldtype": "Column Break" + }, + { + "default": "0", + "depends_on": "enable_certification", + "fieldname": "paid_certificate", + "fieldtype": "Check", + "label": "Paid Certificate" + }, + { + "fieldname": "column_break_22", + "fieldtype": "Column Break" + }, + { + "depends_on": "enable_certification", + "fieldname": "grant_certificate_after", + "fieldtype": "Select", + "label": "Grant Certificate After", + "options": "Completion\nEvaluation" + }, + { + "depends_on": "eval: doc.grant_certificate_after == \"Evaluation\"", + "fieldname": "evaluator", + "fieldtype": "Link", + "label": "Evaluator", + "options": "Course Evaluator" } ], "is_published_field": "published", @@ -186,7 +214,7 @@ "link_fieldname": "course" } ], - "modified": "2022-03-24 13:09:37.228855", + "modified": "2022-03-29 14:56:03.989375", "modified_by": "Administrator", "module": "LMS", "name": "LMS Course", @@ -225,4 +253,4 @@ "states": [], "title_field": "title", "track_changes": 1 -} +} \ No newline at end of file diff --git a/lms/www/courses/course.html b/lms/www/courses/course.html index 96cda3f9..a8861cce 100644 --- a/lms/www/courses/course.html +++ b/lms/www/courses/course.html @@ -189,15 +189,21 @@ {% set certificate = is_certified(course.name) %} {% set progress = frappe.utils.cint(membership.progress) %} + {% if membership and course.enable_certification %} {% if certificate %} {{ _("Get Certificate") }} - {% elif course.enable_certification and progress == 100 %} + {% elif course.grant_certificate_after == "Evaluation" %} + + {{ _("Apply for Certificate") }} + + {% elif progress == 100 %}
{% endif %} + {% endif %} diff --git a/lms/www/courses/course.py b/lms/www/courses/course.py index ef969cdd..33c59b1d 100644 --- a/lms/www/courses/course.py +++ b/lms/www/courses/course.py @@ -13,7 +13,7 @@ def get_context(context): course = frappe.db.get_value("LMS Course", course_name, ["name", "title", "image", "short_introduction", "description", "published", "upcoming", - "disable_self_learning", "video_link", "enable_certification", "status"], + "disable_self_learning", "video_link", "enable_certification", "status", "grant_certificate_after"], as_dict=True) related_courses = frappe.get_all("Related Courses", {"parent": course.name}, ["course"])