+
{{ row[column.key] }}
+
+ {{ Math.ceil(row.courses[column.key]) }}%
+
+
+
+ {{ row.assessments[column.key] }}
+
+
{{ parseInt(row.assessments[column.key]) }}%
+
@@ -74,7 +93,11 @@
diff --git a/frontend/src/components/Modals/StudentModal.vue b/frontend/src/components/Modals/StudentModal.vue
index 54bd05b7..a6bab400 100644
--- a/frontend/src/components/Modals/StudentModal.vue
+++ b/frontend/src/components/Modals/StudentModal.vue
@@ -28,6 +28,7 @@
import { Dialog, createResource } from 'frappe-ui'
import { ref } from 'vue'
import Link from '@/components/Controls/Link.vue'
+import { showToast } from '@/utils'
const students = defineModel('reloadStudents')
const student = ref()
@@ -61,8 +62,11 @@ const addStudent = (close) => {
{
onSuccess() {
students.value.reload()
- close()
student.value = null
+ close()
+ },
+ onError(err) {
+ showToast(__('Error'), __(err.messages?.[0] || err), 'x')
},
}
)
diff --git a/frontend/src/pages/BatchForm.vue b/frontend/src/pages/BatchForm.vue
index 14c16c92..1979c9f1 100644
--- a/frontend/src/pages/BatchForm.vue
+++ b/frontend/src/pages/BatchForm.vue
@@ -252,7 +252,7 @@ import {
} from 'frappe-ui'
import Link from '@/components/Controls/Link.vue'
import { useRouter } from 'vue-router'
-import { showToast } from '../utils'
+import { showToast } from '@/utils'
import { Image } from 'lucide-vue-next'
import { capture } from '@/telemetry'
import MultiSelect from '@/components/Controls/MultiSelect.vue'
@@ -345,6 +345,10 @@ const batchDetail = createResource({
data.instructors.forEach((instructor) => {
instructors.value.push(instructor.instructor)
})
+ } else if (['start_time', 'end_time'].includes(key)) {
+ let [hours, minutes, seconds] = data[key].split(':')
+ hours = hours.length == 1 ? '0' + hours : hours
+ batch[key] = `${hours}:${minutes}`
} else if (Object.hasOwn(batch, key)) batch[key] = data[key]
})
let checkboxes = ['published', 'paid_batch', 'allow_self_enrollment']
diff --git a/lms/__init__.py b/lms/__init__.py
index 90c1ae3a..8f4a3517 100644
--- a/lms/__init__.py
+++ b/lms/__init__.py
@@ -1 +1 @@
-__version__ = "2.15.0"
+__version__ = "2.16.0"
diff --git a/lms/lms/utils.py b/lms/lms/utils.py
index 933d626d..ece56ca4 100644
--- a/lms/lms/utils.py
+++ b/lms/lms/utils.py
@@ -874,26 +874,6 @@ def is_onboarding_complete():
}
-def has_submitted_assessment(assessment, type, member=None):
- if not member:
- member = frappe.session.user
-
- doctype = (
- "LMS Assignment Submission" if type == "LMS Assignment" else "LMS Quiz Submission"
- )
- docfield = "assignment" if type == "LMS Assignment" else "quiz"
-
- filters = {}
- filters[docfield] = assessment
- filters["member"] = member
- return frappe.db.exists(doctype, filters)
-
-
-def has_graded_assessment(submission):
- status = frappe.db.get_value("LMS Assignment Submission", submission, "status")
- return False if status == "Not Graded" else True
-
-
def get_evaluator(course, batch):
evaluator = None
evaluator = frappe.db.get_value(
@@ -1459,13 +1439,11 @@ def get_quiz_details(assessment, member):
@frappe.whitelist()
def get_batch_students(batch):
students = []
-
students_list = frappe.get_all(
"Batch Student", filters={"parent": batch}, fields=["student", "name"]
)
- batch_courses = frappe.get_all("Batch Course", {"parent": batch}, pluck="course")
-
+ batch_courses = frappe.get_all("Batch Course", {"parent": batch}, ["course", "title"])
assessments = frappe.get_all(
"LMS Assessment",
filters={"parent": batch},
@@ -1483,29 +1461,64 @@ def get_batch_students(batch):
)
detail.last_active = format_datetime(detail.last_active, "dd MMM YY")
detail.name = student.name
- students.append(detail)
+ detail.courses = frappe._dict()
+ detail.assessments = frappe._dict()
+ """ Iterate through courses and track their progress """
for course in batch_courses:
progress = frappe.db.get_value(
- "LMS Enrollment", {"course": course, "member": student.student}, "progress"
+ "LMS Enrollment", {"course": course.course, "member": student.student}, "progress"
)
-
+ detail.courses[course.title] = progress
if progress == 100:
courses_completed += 1
- detail.courses_completed = courses_completed
-
+ """ Iterate through assessments and track their progress """
for assessment in assessments:
- if has_submitted_assessment(
+ title = frappe.db.get_value(
+ assessment.assessment_type, assessment.assessment_name, "title"
+ )
+ status = has_submitted_assessment(
assessment.assessment_name, assessment.assessment_type, student.student
- ):
+ )
+ detail.assessments[title] = status
+ if status not in ["Not Attempted", 0]:
assessments_completed += 1
+ detail.courses_completed = courses_completed
detail.assessments_completed = assessments_completed
+ students.append(detail)
return students
+def has_submitted_assessment(assessment, assessment_type, member=None):
+ if not member:
+ member = frappe.session.user
+
+ if assessment_type == "LMS Assignment":
+ doctype = "LMS Assignment Submission"
+ docfield = "assignment"
+ fields = ["status"]
+ not_attempted = "Not Attempted"
+ elif assessment_type == "LMS Quiz":
+ doctype = "LMS Quiz Submission"
+ docfield = "quiz"
+ fields = ["percentage"]
+ not_attempted = 0
+
+ filters = {}
+ filters[docfield] = assessment
+ filters["member"] = member
+
+ attempt = frappe.db.exists(doctype, filters)
+ if attempt:
+ attempt_details = frappe.db.get_value(doctype, filters, fields)
+ return attempt_details
+ else:
+ return not_attempted
+
+
@frappe.whitelist()
def get_discussion_topics(doctype, docname, single_thread):
if single_thread: