Merge pull request #1223 from pateljannat/assignments-in-courses
feat: assignments in courses
This commit is contained in:
@@ -17,6 +17,7 @@ from frappe.utils import time_diff, now_datetime, get_datetime, flt
|
||||
from typing import Optional
|
||||
from lms.lms.utils import get_average_rating, get_lesson_count
|
||||
from xml.dom.minidom import parseString
|
||||
from lms.lms.doctype.course_lesson.course_lesson import save_progress
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -168,6 +169,7 @@ def get_user_info():
|
||||
user.is_instructor = "Course Creator" in user.roles
|
||||
user.is_moderator = "Moderator" in user.roles
|
||||
user.is_evaluator = "Batch Evaluator" in user.roles
|
||||
user.is_student = "LMS Student" in user.roles
|
||||
return user
|
||||
|
||||
|
||||
@@ -1030,3 +1032,14 @@ def delete_scorm_package(scorm_package_path):
|
||||
scorm_package_path = frappe.get_site_path("public", scorm_package_path[1:])
|
||||
if os.path.exists(scorm_package_path):
|
||||
shutil.rmtree(scorm_package_path)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def mark_lesson_progress(course, chapter_number, lesson_number):
|
||||
chapter_name = frappe.get_value(
|
||||
"Chapter Reference", {"parent": course, "idx": chapter_number}, "chapter"
|
||||
)
|
||||
lesson_name = frappe.get_value(
|
||||
"Lesson Reference", {"parent": chapter_name, "idx": lesson_number}, "lesson"
|
||||
)
|
||||
save_progress(lesson_name, course)
|
||||
|
||||
@@ -89,27 +89,25 @@ def save_progress(lesson, course):
|
||||
"LMS Enrollment", {"course": course, "member": frappe.session.user}
|
||||
)
|
||||
if not membership:
|
||||
return
|
||||
|
||||
frappe.db.set_value("LMS Enrollment", membership, "current_lesson", lesson)
|
||||
|
||||
if frappe.db.exists(
|
||||
"LMS Course Progress", {"lesson": lesson, "member": frappe.session.user}
|
||||
):
|
||||
return
|
||||
|
||||
quiz_completed = get_quiz_progress(lesson)
|
||||
if not quiz_completed:
|
||||
return 0
|
||||
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "LMS Course Progress",
|
||||
"lesson": lesson,
|
||||
"status": "Complete",
|
||||
"member": frappe.session.user,
|
||||
}
|
||||
).save(ignore_permissions=True)
|
||||
frappe.db.set_value("LMS Enrollment", membership, "current_lesson", lesson)
|
||||
already_completed = frappe.db.exists(
|
||||
"LMS Course Progress", {"lesson": lesson, "member": frappe.session.user}
|
||||
)
|
||||
|
||||
quiz_completed = get_quiz_progress(lesson)
|
||||
assignment_completed = get_assignment_progress(lesson)
|
||||
|
||||
if not already_completed and quiz_completed and assignment_completed:
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "LMS Course Progress",
|
||||
"lesson": lesson,
|
||||
"status": "Complete",
|
||||
"member": frappe.session.user,
|
||||
}
|
||||
).save(ignore_permissions=True)
|
||||
|
||||
progress = get_course_progress(course)
|
||||
capture_progress_for_analytics(progress, course)
|
||||
@@ -159,6 +157,32 @@ def get_quiz_progress(lesson):
|
||||
return True
|
||||
|
||||
|
||||
def get_assignment_progress(lesson):
|
||||
lesson_details = frappe.db.get_value(
|
||||
"Course Lesson", lesson, ["body", "content"], as_dict=1
|
||||
)
|
||||
assignments = []
|
||||
|
||||
if lesson_details.content:
|
||||
content = json.loads(lesson_details.content)
|
||||
|
||||
for block in content.get("blocks"):
|
||||
if block.get("type") == "assignment":
|
||||
assignments.append(block.get("data").get("assignment"))
|
||||
|
||||
elif lesson_details.body:
|
||||
macros = find_macros(lesson_details.body)
|
||||
assignments = [value for name, value in macros if name == "Assignment"]
|
||||
|
||||
for assignment in assignments:
|
||||
if not frappe.db.exists(
|
||||
"LMS Assignment Submission",
|
||||
{"assignment": assignment, "member": frappe.session.user},
|
||||
):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_lesson_info(chapter):
|
||||
return frappe.db.get_value("Course Chapter", chapter, "course")
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"title",
|
||||
"grade_assignment",
|
||||
"question",
|
||||
"column_break_hmwv",
|
||||
"type",
|
||||
"grade_assignment",
|
||||
"section_break_sjti",
|
||||
"show_answer",
|
||||
"answer"
|
||||
],
|
||||
@@ -20,7 +21,8 @@
|
||||
{
|
||||
"fieldname": "question",
|
||||
"fieldtype": "Text Editor",
|
||||
"label": "Question"
|
||||
"label": "Question",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "type",
|
||||
@@ -28,14 +30,16 @@
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Type",
|
||||
"options": "Document\nPDF\nURL\nImage\nText"
|
||||
"options": "Document\nPDF\nURL\nImage\nText",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Title"
|
||||
"label": "Title",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_hmwv",
|
||||
@@ -60,11 +64,15 @@
|
||||
"fieldname": "grade_assignment",
|
||||
"fieldtype": "Check",
|
||||
"label": "Grade Assignment"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_sjti",
|
||||
"fieldtype": "Section Break"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2024-04-05 12:01:36.601160",
|
||||
"modified": "2024-12-24 09:36:31.464508",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "LMS Assignment",
|
||||
|
||||
@@ -14,19 +14,17 @@
|
||||
"member",
|
||||
"member_name",
|
||||
"section_break_dlzh",
|
||||
"question",
|
||||
"column_break_zvis",
|
||||
"assignment_attachment",
|
||||
"answer",
|
||||
"section_break_rqal",
|
||||
"status",
|
||||
"column_break_oqqy",
|
||||
"evaluator",
|
||||
"column_break_esgd",
|
||||
"status",
|
||||
"comments",
|
||||
"section_break_cwaw",
|
||||
"lesson",
|
||||
"section_break_rqal",
|
||||
"question",
|
||||
"column_break_esgd",
|
||||
"course",
|
||||
"column_break_ygdu"
|
||||
"lesson"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -89,8 +87,7 @@
|
||||
"fieldname": "evaluator",
|
||||
"fieldtype": "Link",
|
||||
"label": "Evaluator",
|
||||
"options": "User",
|
||||
"read_only": 1
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!([\"URL\", \"Text\"]).includes(doc.type);",
|
||||
@@ -128,14 +125,6 @@
|
||||
"fieldname": "column_break_esgd",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_cwaw",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_ygdu",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:([\"URL\", \"Text\"]).includes(doc.type);",
|
||||
"fieldname": "answer",
|
||||
@@ -148,14 +137,14 @@
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_zvis",
|
||||
"fieldname": "column_break_oqqy",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"make_attachments_public": 1,
|
||||
"modified": "2024-04-05 15:57:22.758563",
|
||||
"modified": "2024-12-24 21:22:35.212732",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "LMS Assignment Submission",
|
||||
|
||||
@@ -6,12 +6,14 @@ from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import validate_url, validate_email_address
|
||||
from frappe.email.doctype.email_template.email_template import get_email_template
|
||||
from frappe.desk.doctype.notification_log.notification_log import make_notification_logs
|
||||
|
||||
|
||||
class LMSAssignmentSubmission(Document):
|
||||
def validate(self):
|
||||
self.validate_duplicates()
|
||||
self.validate_url()
|
||||
self.validate_status()
|
||||
|
||||
def after_insert(self):
|
||||
if not frappe.flags.in_test:
|
||||
@@ -69,6 +71,28 @@ class LMSAssignmentSubmission(Document):
|
||||
header=[subject, "green"],
|
||||
)
|
||||
|
||||
def validate_status(self):
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
if doc_before_save.status != self.status or doc_before_save.comments != self.comments:
|
||||
self.trigger_update_notification()
|
||||
|
||||
def trigger_update_notification(self):
|
||||
notification = frappe._dict(
|
||||
{
|
||||
"subject": _(
|
||||
"There has been an update on your submission for assignment {0}"
|
||||
).format(self.assignment_title),
|
||||
"email_content": self.comments,
|
||||
"document_type": self.doctype,
|
||||
"document_name": self.name,
|
||||
"for_user": self.owner,
|
||||
"from_user": self.evaluator,
|
||||
"type": "Alert",
|
||||
"link": f"/assignment-submission/{self.assignment}/{self.name}",
|
||||
}
|
||||
)
|
||||
make_notification_logs(notification, [self.member])
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def upload_assignment(
|
||||
|
||||
@@ -1421,7 +1421,7 @@ def get_quiz_details(assessment, member):
|
||||
if len(existing_submission):
|
||||
assessment.submission = existing_submission[0]
|
||||
assessment.completed = True
|
||||
assessment.status = assessment.submission.score
|
||||
assessment.status = assessment.submission.percentage or assessment.submission.score
|
||||
else:
|
||||
assessment.status = "Not Attempted"
|
||||
assessment.color = "red"
|
||||
|
||||
Reference in New Issue
Block a user