feat: certificate evaluation

This commit is contained in:
Jannat Patel
2022-03-29 16:49:50 +05:30
parent b4eda0e7cd
commit ca5ea6032c
22 changed files with 420 additions and 10 deletions

View File

@@ -0,0 +1,6 @@
// Copyright (c) 2022, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('Course Evaluator', {
});

View File

@@ -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"
}

View File

@@ -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."))

View File

@@ -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

View File

@@ -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": []
}

View File

@@ -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

View File

@@ -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"
}

View File

@@ -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,
}
};
});
}
});

View File

@@ -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": []
}

View File

@@ -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

View File

@@ -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

View File

@@ -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) {
// }
});

View File

@@ -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": []
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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 %}
<a class="button wide-button is-secondary mt-2" href="/courses/{{ course.name }}/{{ certificate }}">
{{ _("Get Certificate") }}
</a>
{% elif course.enable_certification and progress == 100 %}
{% elif course.grant_certificate_after == "Evaluation" %}
<a class="button wide-button is-secondary mt-2" href="/courses/{{ course.name }}/{{ certificate }}">
{{ _("Apply for Certificate") }}
</a>
{% elif progress == 100 %}
<div class="button wide-button is-secondary mt-4" id="certification" data-course="{{ course.name }}">
{{ _("Get Certificate") }}
</div>
{% endif %}
{% endif %}
</div>

View File

@@ -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"])