Merge pull request #602 from pateljannat/rename-batch-doctype

refactor: renamed batch and membership doctypes
This commit is contained in:
Jannat Patel
2023-08-26 15:53:56 +05:30
committed by GitHub
51 changed files with 303 additions and 328 deletions

View File

@@ -13,6 +13,6 @@ module.exports = defineConfig({
openMode: 0, openMode: 0,
}, },
e2e: { e2e: {
baseUrl: "http://test_site_ui:8000", baseUrl: "http://dd1:8000",
}, },
}); });

View File

@@ -32,13 +32,13 @@ def submit_solution(exercise, code):
def save_current_lesson(course_name, lesson_name): def save_current_lesson(course_name, lesson_name):
"""Saves the current lesson for a student/mentor.""" """Saves the current lesson for a student/mentor."""
name = frappe.get_value( name = frappe.get_value(
doctype="LMS Batch Membership", doctype="LMS Enrollment",
filters={"course": course_name, "member": frappe.session.user}, filters={"course": course_name, "member": frappe.session.user},
fieldname="name", fieldname="name",
) )
if not name: if not name:
return return
doc = frappe.get_doc("LMS Batch Membership", name) doc = frappe.get_doc("LMS Enrollment", name)
doc.current_lesson = lesson_name doc.current_lesson = lesson_name
doc.save(ignore_permissions=True) doc.save(ignore_permissions=True)
return {"current_lesson": doc.current_lesson} return {"current_lesson": doc.current_lesson}

View File

@@ -7,7 +7,7 @@
"custom_options": "{\"type\": \"line\", \"axisOptions\": {\"xIsSeries\": 1}, \"lineOptions\": {\"regionFill\": 1}}", "custom_options": "{\"type\": \"line\", \"axisOptions\": {\"xIsSeries\": 1}, \"lineOptions\": {\"regionFill\": 1}}",
"docstatus": 0, "docstatus": 0,
"doctype": "Dashboard Chart", "doctype": "Dashboard Chart",
"document_type": "LMS Batch Membership", "document_type": "LMS Enrollment",
"dynamic_filters_json": "[]", "dynamic_filters_json": "[]",
"filters_json": "[]", "filters_json": "[]",
"group_by_type": "Count", "group_by_type": "Count",
@@ -15,7 +15,7 @@
"is_public": 1, "is_public": 1,
"is_standard": 1, "is_standard": 1,
"last_synced_on": "2022-10-20 10:46:56.859520", "last_synced_on": "2022-10-20 10:46:56.859520",
"modified": "2022-10-20 11:30:26.863008", "modified": "2022-10-20 11:30:26.863009",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "Course Enrollments", "name": "Course Enrollments",

View File

@@ -16,7 +16,7 @@ class Cohort(Document):
if include_counts: if include_counts:
mentors = self._get_subgroup_counts("Cohort Mentor") mentors = self._get_subgroup_counts("Cohort Mentor")
students = self._get_subgroup_counts("LMS Batch Membership") students = self._get_subgroup_counts("LMS Enrollment")
join_requests = self._get_subgroup_counts("Cohort Join Request", status="Pending") join_requests = self._get_subgroup_counts("Cohort Join Request", status="Pending")
for s in subgroups: for s in subgroups:
s.num_mentors = mentors.get(s.name, 0) s.num_mentors = mentors.get(s.name, 0)
@@ -56,7 +56,7 @@ class Cohort(Document):
return { return {
"subgroups": self._get_count("Cohort Subgroup"), "subgroups": self._get_count("Cohort Subgroup"),
"mentors": self._get_count("Cohort Mentor"), "mentors": self._get_count("Cohort Mentor"),
"students": self._get_count("LMS Batch Membership"), "students": self._get_count("LMS Enrollment"),
"join_requests": self._get_count("Cohort Join Request", status="Pending"), "join_requests": self._get_count("Cohort Join Request", status="Pending"),
} }

View File

@@ -13,7 +13,7 @@ class CohortJoinRequest(Document):
def ensure_student(self): def ensure_student(self):
# case 1 - user is already a member # case 1 - user is already a member
q = { q = {
"doctype": "LMS Batch Membership", "doctype": "LMS Enrollment",
"cohort": self.cohort, "cohort": self.cohort,
"subgroup": self.subgroup, "subgroup": self.subgroup,
"member": self.email, "member": self.email,
@@ -26,21 +26,21 @@ class CohortJoinRequest(Document):
cohort = frappe.get_doc("Cohort", self.cohort) cohort = frappe.get_doc("Cohort", self.cohort)
q = { q = {
"doctype": "LMS Batch Membership", "doctype": "LMS Enrollment",
"course": cohort.course, "course": cohort.course,
"member": self.email, "member": self.email,
"member_type": "Student", "member_type": "Student",
} }
name = frappe.db.exists(q) name = frappe.db.exists(q)
if name: if name:
doc = frappe.get_doc("LMS Batch Membership", name) doc = frappe.get_doc("LMS Enrollment", name)
doc.cohort = self.cohort doc.cohort = self.cohort
doc.subgroup = self.subgroup doc.subgroup = self.subgroup
doc.save(ignore_permissions=True) doc.save(ignore_permissions=True)
else: else:
# case 3 - user has not signed up for this course yet # case 3 - user has not signed up for this course yet
data = { data = {
"doctype": "LMS Batch Membership", "doctype": "LMS Enrollment",
"course": cohort.course, "course": cohort.course,
"cohort": self.cohort, "cohort": self.cohort,
"subgroup": self.subgroup, "subgroup": self.subgroup,

View File

@@ -23,7 +23,7 @@ class CohortSubgroup(Document):
def has_student(self, email): def has_student(self, email):
"""Check if given user is a student of this subgroup.""" """Check if given user is a student of this subgroup."""
q = {"doctype": "LMS Batch Membership", "subgroup": self.name, "member": email} q = {"doctype": "LMS Enrollment", "subgroup": self.name, "member": email}
return frappe.db.exists(q) return frappe.db.exists(q)
def has_join_request(self, email): def has_join_request(self, email):
@@ -45,7 +45,7 @@ class CohortSubgroup(Document):
def get_students(self): def get_students(self):
emails = frappe.get_all( emails = frappe.get_all(
"LMS Batch Membership", "LMS Enrollment",
filters={"subgroup": self.name}, filters={"subgroup": self.name},
fields=["member"], fields=["member"],
pluck="member", pluck="member",

View File

@@ -89,7 +89,7 @@ class CourseLesson(Document):
@frappe.whitelist() @frappe.whitelist()
def save_progress(lesson, course, status): def save_progress(lesson, course, status):
membership = frappe.db.exists( membership = frappe.db.exists(
"LMS Batch Membership", {"member": frappe.session.user, "course": course} "LMS Enrollment", {"member": frappe.session.user, "course": course}
) )
if not membership: if not membership:
return 0 return 0
@@ -120,7 +120,7 @@ def save_progress(lesson, course, status):
).save(ignore_permissions=True) ).save(ignore_permissions=True)
progress = get_course_progress(course) progress = get_course_progress(course)
frappe.db.set_value("LMS Batch Membership", membership, "progress", progress) frappe.db.set_value("LMS Enrollment", membership, "progress", progress)
return progress return progress

View File

@@ -7,7 +7,7 @@
"field_order": [ "field_order": [
"exercise", "exercise",
"status", "status",
"batch", "batch_old",
"column_break_4", "column_break_4",
"exercise_title", "exercise_title",
"course", "course",
@@ -40,10 +40,10 @@
"options": "Correct\nIncorrect" "options": "Correct\nIncorrect"
}, },
{ {
"fieldname": "batch", "fieldname": "batch_old",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Batch", "label": "Batch Old",
"options": "LMS Batch" "options": "LMS Batch Old"
}, },
{ {
"fieldname": "column_break_4", "fieldname": "column_break_4",
@@ -110,7 +110,7 @@
"fieldname": "member", "fieldname": "member",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Member", "label": "Member",
"options": "LMS Batch Membership" "options": "LMS Enrollment"
}, },
{ {
"fetch_from": "member.member", "fetch_from": "member.member",
@@ -141,7 +141,7 @@
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2021-12-08 22:58:46.312861", "modified": "2021-12-08 22:58:46.312863",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "Exercise Latest Submission", "name": "Exercise Latest Submission",

View File

@@ -7,7 +7,7 @@
"field_order": [ "field_order": [
"exercise", "exercise",
"status", "status",
"batch", "batch_old",
"column_break_4", "column_break_4",
"exercise_title", "exercise_title",
"course", "course",
@@ -44,10 +44,10 @@
"read_only": 1 "read_only": 1
}, },
{ {
"fieldname": "batch", "fieldname": "batch_old",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Batch", "label": "Batch Old",
"options": "LMS Batch" "options": "LMS Batch Old"
}, },
{ {
"fetch_from": "exercise.lesson", "fetch_from": "exercise.lesson",
@@ -96,12 +96,12 @@
"fieldname": "member", "fieldname": "member",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Member", "label": "Member",
"options": "LMS Batch Membership" "options": "LMS Enrollment"
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2021-12-08 22:25:05.809376", "modified": "2021-12-08 22:25:05.809377",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "Exercise Submission", "name": "Exercise Submission",

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors // Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on("LMS Batch", { frappe.ui.form.on("LMS Batch Old", {
// refresh: function(frm) { // refresh: function(frm) {
// } // }
}); });

View File

@@ -118,14 +118,14 @@
"links": [ "links": [
{ {
"group": "Members", "group": "Members",
"link_doctype": "LMS Batch Membership", "link_doctype": "LMS Enrollment",
"link_fieldname": "batch" "link_fieldname": "batch_old"
} }
], ],
"modified": "2022-09-28 18:43:22.955907", "modified": "2022-09-28 18:43:22.955907",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Batch", "name": "LMS Batch Old",
"naming_rule": "Expression", "naming_rule": "Expression",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [

View File

@@ -5,11 +5,11 @@ import frappe
from frappe import _ from frappe import _
from frappe.model.document import Document from frappe.model.document import Document
from lms.lms.doctype.lms_batch_membership.lms_batch_membership import create_membership from lms.lms.doctype.lms_enrollment.lms_enrollment import create_membership
from lms.lms.utils import is_mentor from lms.lms.utils import is_mentor
class LMSBatch(Document): class LMSBatchOld(Document):
def validate(self): def validate(self):
pass pass
# self.validate_if_mentor() # self.validate_if_mentor()
@@ -28,19 +28,19 @@ class LMSBatch(Document):
If member_type is specified, checks if the person is a Student/Mentor. If member_type is specified, checks if the person is a Student/Mentor.
""" """
filters = {"batch": self.name, "member": email} filters = {"batch_old": self.name, "member": email}
if member_type: if member_type:
filters["member_type"] = member_type filters["member_type"] = member_type
return frappe.db.exists("LMS Batch Membership", filters) return frappe.db.exists("LMS Enrollment", filters)
def get_membership(self, email): def get_membership(self, email):
"""Returns the membership document of given user.""" """Returns the membership document of given user."""
name = frappe.get_value( name = frappe.get_value(
doctype="LMS Batch Membership", doctype="LMS Enrollment",
filters={"batch": self.name, "member": email}, filters={"batch_old": self.name, "member": email},
fieldname="name", fieldname="name",
) )
return frappe.get_doc("LMS Batch Membership", name) return frappe.get_doc("LMS Enrollment", name)
def get_current_lesson(self, user): def get_current_lesson(self, user):
"""Returns the name of the current lesson for the given user.""" """Returns the name of the current lesson for the given user."""
@@ -53,7 +53,7 @@ def save_message(message, batch):
doc = frappe.get_doc( doc = frappe.get_doc(
{ {
"doctype": "LMS Message", "doctype": "LMS Message",
"batch": batch, "batch_old": batch,
"author": frappe.session.user, "author": frappe.session.user,
"message": message, "message": message,
} }
@@ -64,10 +64,10 @@ def save_message(message, batch):
def switch_batch(course_name, email, batch_name): def switch_batch(course_name, email, batch_name):
"""Switches the user from the current batch of the course to a new batch.""" """Switches the user from the current batch of the course to a new batch."""
membership = frappe.get_last_doc( membership = frappe.get_last_doc(
"LMS Batch Membership", filters={"course": course_name, "member": email} "LMS Enrollment", filters={"course": course_name, "member": email}
) )
batch = frappe.get_doc("LMS Batch", batch_name) batch = frappe.get_doc("LMS Batch Old", batch_name)
if not batch: if not batch:
raise ValueError(f"Invalid Batch: {batch_name}") raise ValueError(f"Invalid Batch: {batch_name}")
@@ -78,15 +78,15 @@ def switch_batch(course_name, email, batch_name):
print(f"{email} is already a member of {batch.title}") print(f"{email} is already a member of {batch.title}")
return return
old_batch = frappe.get_doc("LMS Batch", membership.batch) old_batch = frappe.get_doc("LMS Batch Old", membership.batch_old)
membership.batch = batch_name membership.batch_old = batch_name
membership.save() membership.save()
# update exercise submissions # update exercise submissions
filters = {"owner": email, "batch": old_batch.name} filters = {"owner": email, "batch_old": old_batch.name}
for name in frappe.db.get_all("Exercise Submission", filters=filters, pluck="name"): for name in frappe.db.get_all("Exercise Submission", filters=filters, pluck="name"):
doc = frappe.get_doc("Exercise Submission", name) doc = frappe.get_doc("Exercise Submission", name)
print("updating exercise submission", name) print("updating exercise submission", name)
doc.batch = batch_name doc.batch_old = batch_name
doc.save() doc.save()

View File

@@ -5,5 +5,5 @@
import unittest import unittest
class TestLMSBatch(unittest.TestCase): class TestLMSBatchOld(unittest.TestCase):
pass pass

View File

@@ -108,7 +108,7 @@ def create_certificate_request(
course, date, day, start_time, end_time, class_name=None course, date, day, start_time, end_time, class_name=None
): ):
is_member = frappe.db.exists( is_member = frappe.db.exists(
{"doctype": "LMS Batch Membership", "course": course, "member": frappe.session.user} {"doctype": "LMS Enrollment", "course": course, "member": frappe.session.user}
) )
if not is_member: if not is_member:

View File

@@ -57,7 +57,7 @@ class LMSClass(Document):
for course in self.courses: for course in self.courses:
for student in self.students: for student in self.students:
filters = { filters = {
"doctype": "LMS Batch Membership", "doctype": "LMS Enrollment",
"member": student.student, "member": student.student,
"course": course.course, "course": course.course,
} }

View File

@@ -239,7 +239,7 @@
}, },
{ {
"group": "Batches", "group": "Batches",
"link_doctype": "LMS Batch", "link_doctype": "LMS Batch Old",
"link_fieldname": "course" "link_fieldname": "course"
}, },
{ {
@@ -254,7 +254,7 @@
} }
], ],
"make_attachments_public": 1, "make_attachments_public": 1,
"modified": "2023-08-02 12:07:26.354110", "modified": "2023-08-02 12:07:26.354111",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Course", "name": "LMS Course",

View File

@@ -119,20 +119,18 @@ class LMSCourse(Document):
return return
batch_name = frappe.get_value( batch_name = frappe.get_value(
doctype="LMS Batch Membership", doctype="LMS Enrollment",
filters={"course": self.name, "member_type": "Student", "member": email}, filters={"course": self.name, "member_type": "Student", "member": email},
fieldname="batch", fieldname="batch_old",
) )
return batch_name and frappe.get_doc("LMS Batch", batch_name) return batch_name and frappe.get_doc("LMS Batch Old", batch_name)
def get_batches(self, mentor=None): def get_batches(self, mentor=None):
batches = frappe.get_all("LMS Batch", {"course": self.name}) batches = frappe.get_all("LMS Batch Old", {"course": self.name})
if mentor: if mentor:
# TODO: optimize this # TODO: optimize this
memberships = frappe.db.get_all( memberships = frappe.db.get_all("LMS Enrollment", {"member": mentor}, ["batch_old"])
"LMS Batch Membership", {"member": mentor}, ["batch"] batch_names = {m.batch_old for m in memberships}
)
batch_names = {m.batch for m in memberships}
return [b for b in batches if b.name in batch_names] return [b for b in batches if b.name in batch_names]
def get_cohorts(self): def get_cohorts(self):
@@ -162,10 +160,12 @@ class LMSCourse(Document):
def get_all_memberships(self, member): def get_all_memberships(self, member):
all_memberships = frappe.get_all( all_memberships = frappe.get_all(
"LMS Batch Membership", {"member": member, "course": self.name}, ["batch"] "LMS Enrollment", {"member": member, "course": self.name}, ["batch_old"]
) )
for membership in all_memberships: for membership in all_memberships:
membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title") membership.batch_title = frappe.db.get_value(
"LMS Batch Old", membership.batch_old, "title"
)
return all_memberships return all_memberships
@@ -452,7 +452,7 @@ def verify_payment(response, course, address, order_id):
def create_membership(address, response, course, client): def create_membership(address, response, course, client):
try: try:
address_name = save_address(address) address_name = save_address(address)
membership = frappe.new_doc("LMS Batch Membership") membership = frappe.new_doc("LMS Enrollment")
payment = client.payment.fetch(response["razorpay_payment_id"]) payment = client.payment.fetch(response["razorpay_payment_id"])
membership.update( membership.update(

View File

@@ -12,7 +12,6 @@ class TestLMSCourse(unittest.TestCase):
def test_new_course(self): def test_new_course(self):
course = new_course("Test Course") course = new_course("Test Course")
assert course.title == "Test Course" assert course.title == "Test Course"
assert course.name == "test-course"
# disabled this test as it is failing # disabled this test as it is failing
def _test_add_mentors(self): def _test_add_mentors(self):
@@ -36,8 +35,10 @@ class TestLMSCourse(unittest.TestCase):
frappe.db.delete("Exercise Submission", {"course": "test-course"}) frappe.db.delete("Exercise Submission", {"course": "test-course"})
frappe.db.delete("Exercise Latest Submission", {"course": "test-course"}) frappe.db.delete("Exercise Latest Submission", {"course": "test-course"})
frappe.db.delete("LMS Exercise", {"course": "test-course"}) frappe.db.delete("LMS Exercise", {"course": "test-course"})
frappe.db.delete("LMS Batch Membership", {"course": "test-course"}) frappe.db.delete("LMS Enrollment", {"course": "test-course"})
frappe.db.delete("LMS Batch", {"course": "test-course"}) frappe.db.delete("Course Lesson", {"course": "test-course"})
frappe.db.delete("Course Chapter", {"course": "test-course"})
frappe.db.delete("LMS Batch Old", {"course": "test-course"})
frappe.db.delete("LMS Course Mentor Mapping", {"course": "test-course"}) frappe.db.delete("LMS Course Mentor Mapping", {"course": "test-course"})
frappe.db.delete("Course Instructor", {"parent": "test-course"}) frappe.db.delete("Course Instructor", {"parent": "test-course"})
frappe.db.sql("delete from `tabCourse Instructor`") frappe.db.sql("delete from `tabCourse Instructor`")
@@ -50,14 +51,14 @@ def new_user(name, email):
return frappe.get_doc("User", user) return frappe.get_doc("User", user)
else: else:
filters = { filters = {
"doctype": "User",
"email": email, "email": email,
"first_name": name, "first_name": name,
"send_welcome_email": False, "send_welcome_email": False,
} }
doc = frappe.get_doc(filters) doc = frappe.new_doc("User")
doc.insert() doc.update(filters)
doc.save()
return doc return doc
@@ -68,7 +69,6 @@ def new_course(title, additional_filters=None):
else: else:
create_evaluator() create_evaluator()
filters = { filters = {
"doctype": "LMS Course",
"title": title, "title": title,
"short_introduction": title, "short_introduction": title,
"description": title, "description": title,
@@ -77,8 +77,9 @@ def new_course(title, additional_filters=None):
if additional_filters: if additional_filters:
filters.update(additional_filters) filters.update(additional_filters)
doc = frappe.get_doc(filters) doc = frappe.new_doc("LMS Course")
doc.insert(ignore_permissions=True) doc.update(filters)
doc.save()
return doc return doc

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors // Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on("LMS Batch Membership", { frappe.ui.form.on("LMS Enrollment", {
onload: function (frm) { onload: function (frm) {
frm.set_query("member", function (doc) { frm.set_query("member", function (doc) {
return { return {

View File

@@ -7,7 +7,7 @@
"field_order": [ "field_order": [
"course", "course",
"member_type", "member_type",
"batch", "batch_old",
"column_break_3", "column_break_3",
"member", "member",
"member_name", "member_name",
@@ -30,10 +30,10 @@
], ],
"fields": [ "fields": [
{ {
"fieldname": "batch", "fieldname": "batch_old",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Batch", "label": "Batch Old",
"options": "LMS Batch" "options": "LMS Batch Old"
}, },
{ {
"fieldname": "member", "fieldname": "member",
@@ -167,10 +167,10 @@
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2023-08-17 13:52:49.450499", "modified": "2023-08-17 13:52:49.450491",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Batch Membership", "name": "LMS Enrollment",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [
{ {

View File

@@ -6,17 +6,17 @@ from frappe import _
from frappe.model.document import Document from frappe.model.document import Document
class LMSBatchMembership(Document): class LMSEnrollment(Document):
def validate(self): def validate(self):
self.validate_membership_in_same_batch() self.validate_membership_in_same_batch()
self.validate_membership_in_different_batch_same_course() self.validate_membership_in_different_batch_same_course()
def validate_membership_in_same_batch(self): def validate_membership_in_same_batch(self):
filters = {"member": self.member, "course": self.course, "name": ["!=", self.name]} filters = {"member": self.member, "course": self.course, "name": ["!=", self.name]}
if self.batch: if self.batch_old:
filters["batch"] = self.batch filters["batch_old"] = self.batch_old
previous_membership = frappe.db.get_value( previous_membership = frappe.db.get_value(
"LMS Batch Membership", filters, fieldname=["member_type", "member"], as_dict=1 "LMS Enrollment", filters, fieldname=["member_type", "member"], as_dict=1
) )
if previous_membership: if previous_membership:
@@ -34,16 +34,16 @@ class LMSBatchMembership(Document):
if self.member_type != "Student": if self.member_type != "Student":
return return
course = frappe.db.get_value("LMS Batch", self.batch, "course") course = frappe.db.get_value("LMS Batch Old", self.batch_old, "course")
memberships = frappe.get_all( memberships = frappe.get_all(
"LMS Batch Membership", "LMS Enrollment",
filters={ filters={
"member": self.member, "member": self.member,
"name": ["!=", self.name], "name": ["!=", self.name],
"member_type": "Student", "member_type": "Student",
"course": self.course, "course": self.course,
}, },
fields=["batch", "member_type", "name"], fields=["batch_old", "member_type", "name"],
) )
if memberships: if memberships:
@@ -51,7 +51,7 @@ class LMSBatchMembership(Document):
member_name = frappe.db.get_value("User", self.member, "full_name") member_name = frappe.db.get_value("User", self.member, "full_name")
frappe.throw( frappe.throw(
_("{0} is already a Student of {1} course through {2} batch").format( _("{0} is already a Student of {1} course through {2} batch").format(
member_name, course, membership.batch member_name, course, membership.batch_old
) )
) )
@@ -62,8 +62,8 @@ def create_membership(
): ):
frappe.get_doc( frappe.get_doc(
{ {
"doctype": "LMS Batch Membership", "doctype": "LMS Enrollment",
"batch": batch, "batch_old": batch,
"course": course, "course": course,
"role": role, "role": role,
"member_type": member_type, "member_type": member_type,
@@ -76,15 +76,13 @@ def create_membership(
@frappe.whitelist() @frappe.whitelist()
def update_current_membership(batch, course, member): def update_current_membership(batch, course, member):
all_memberships = frappe.get_all( all_memberships = frappe.get_all(
"LMS Batch Membership", {"member": member, "course": course} "LMS Enrollment", {"member": member, "course": course}
) )
for membership in all_memberships: for membership in all_memberships:
frappe.db.set_value("LMS Batch Membership", membership.name, "is_current", 0) frappe.db.set_value("LMS Enrollment", membership.name, "is_current", 0)
current_membership = frappe.get_all( current_membership = frappe.get_all(
"LMS Batch Membership", {"batch": batch, "member": member} "LMS Enrollment", {"batch_old": batch, "member": member}
) )
if len(current_membership): if len(current_membership):
frappe.db.set_value( frappe.db.set_value("LMS Enrollment", current_membership[0].name, "is_current", 1)
"LMS Batch Membership", current_membership[0].name, "is_current", 1
)

View File

@@ -8,12 +8,12 @@ import frappe
from lms.lms.doctype.lms_course.test_lms_course import new_course, new_user from lms.lms.doctype.lms_course.test_lms_course import new_course, new_user
class TestLMSBatchMembership(unittest.TestCase): class TestLMSEnrollment(unittest.TestCase):
def setUp(self): def setUp(self):
frappe.db.sql("DELETE FROM `tabLMS Batch Membership`") frappe.db.delete("LMS Enrollment")
frappe.db.sql("DELETE FROM `tabLMS Batch`") frappe.db.delete("LMS Batch Old")
frappe.db.sql("delete from `tabLMS Course Mentor Mapping`") frappe.db.delete("LMS Course Mentor Mapping")
frappe.db.sql("DELETE FROM `tabUser` where email like '%@test.com'") frappe.db.delete("User", {"email": ("like", "%@test.com")})
def new_course_batch(self): def new_course_batch(self):
course = new_course("Test Course") course = new_course("Test Course")
@@ -26,7 +26,7 @@ class TestLMSBatchMembership(unittest.TestCase):
batch = frappe.get_doc( batch = frappe.get_doc(
{ {
"doctype": "LMS Batch", "doctype": "LMS Batch Old",
"name": "test-batch", "name": "test-batch",
"title": "Test Batch", "title": "Test Batch",
"course": course.name, "course": course.name,
@@ -37,13 +37,14 @@ class TestLMSBatchMembership(unittest.TestCase):
frappe.session.user = "Administrator" frappe.session.user = "Administrator"
return course, batch return course, batch
def add_membership(self, batch_name, member_name, member_type="Student"): def add_membership(self, batch_name, member_name, course, member_type="Student"):
doc = frappe.get_doc( doc = frappe.get_doc(
{ {
"doctype": "LMS Batch Membership", "doctype": "LMS Enrollment",
"batch": batch_name, "batch_old": batch_name,
"member": member_name, "member": member_name,
"member_type": member_type, "member_type": member_type,
"course": course,
} }
) )
doc.insert() doc.insert()
@@ -52,7 +53,7 @@ class TestLMSBatchMembership(unittest.TestCase):
def test_membership(self): def test_membership(self):
course, batch = self.new_course_batch() course, batch = self.new_course_batch()
member = new_user("Test", "test01@test.com") member = new_user("Test", "test01@test.com")
membership = self.add_membership(batch.name, member.name) membership = self.add_membership(batch.name, member.name, course.name)
assert membership.course == course.name assert membership.course == course.name
assert membership.member_name == member.full_name assert membership.member_name == member.full_name
@@ -60,7 +61,7 @@ class TestLMSBatchMembership(unittest.TestCase):
def test_membership_change_role(self): def test_membership_change_role(self):
course, batch = self.new_course_batch() course, batch = self.new_course_batch()
member = new_user("Test", "test01@test.com") member = new_user("Test", "test01@test.com")
membership = self.add_membership(batch.name, member.name) membership = self.add_membership(batch.name, member.name, course.name)
# it should be possible to change role # it should be possible to change role
membership.role = "Admin" membership.role = "Admin"

View File

@@ -43,7 +43,7 @@ class LMSExercise(Document):
exercise_title=self.title, exercise_title=self.title,
course=self.course, course=self.course,
lesson=self.lesson, lesson=self.lesson,
batch=member.batch, batch=member.batch_old,
solution=code, solution=code,
member=member.name, member=member.name,
) )

View File

@@ -13,7 +13,7 @@ class TestLMSExercise(unittest.TestCase):
course = new_course("Test Course") course = new_course("Test Course")
member = frappe.get_doc( member = frappe.get_doc(
{ {
"doctype": "LMS Batch Membership", "doctype": "LMS Enrollment",
"course": course.name, "course": course.name,
"member": frappe.session.user, "member": frappe.session.user,
} }
@@ -49,6 +49,6 @@ class TestLMSExercise(unittest.TestCase):
assert user_submission.name == submission.name assert user_submission.name == submission.name
def tearDown(self): def tearDown(self):
frappe.db.sql("delete from `tabLMS Batch Membership`") frappe.db.delete("LMS Enrollment")
frappe.db.sql("delete from `tabExercise Submission`") frappe.db.delete("Exercise Submission")
frappe.db.sql("delete from `tabLMS Exercise`") frappe.db.delete("LMS Exercise")

View File

@@ -1,6 +1,6 @@
"""Handy module to make access to all doctypes from a single place. """Handy module to make access to all doctypes from a single place.
""" """
from .doctype.lms_batch_membership.lms_batch_membership import ( from .doctype.lms_enrollment.lms_enrollment import (
LMSBatchMembership as Membership, LMSBatchMembership as Membership,
) )
from .doctype.lms_course.lms_course import LMSCourse as Course from .doctype.lms_course.lms_course import LMSCourse as Course

View File

@@ -9,13 +9,13 @@
"filters": [], "filters": [],
"idx": 0, "idx": 0,
"is_standard": "Yes", "is_standard": "Yes",
"modified": "2021-09-28 17:09:40.761819", "modified": "2021-09-28 17:09:40.761810",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "Course Progress Summary", "name": "Course Progress Summary",
"owner": "Administrator", "owner": "Administrator",
"prepared_report": 0, "prepared_report": 0,
"ref_doctype": "LMS Batch Membership", "ref_doctype": "LMS Enrollment",
"report_name": "Course Progress Summary", "report_name": "Course Progress Summary",
"report_type": "Script Report", "report_type": "Script Report",
"roles": [ "roles": [

View File

@@ -21,7 +21,7 @@ def get_data(filters=None):
query_filter = {"course": filters.course} query_filter = {"course": filters.course}
memberships = frappe.get_all( memberships = frappe.get_all(
"LMS Batch Membership", "LMS Enrollment",
query_filter, query_filter,
["name", "course", "member", "member_name", "progress"], ["name", "course", "member", "member_name", "progress"],
order_by="course", order_by="course",

View File

@@ -63,19 +63,21 @@ def get_membership(course, member=None, batch=None):
filters = {"member": member, "course": course} filters = {"member": member, "course": course}
if batch: if batch:
filters["batch"] = batch filters["batch_old"] = batch
is_member = frappe.db.exists("LMS Batch Membership", filters) is_member = frappe.db.exists("LMS Enrollment", filters)
if is_member: if is_member:
membership = frappe.db.get_value( membership = frappe.db.get_value(
"LMS Batch Membership", "LMS Enrollment",
filters, filters,
["name", "batch", "current_lesson", "member_type", "progress"], ["name", "batch_old", "current_lesson", "member_type", "progress"],
as_dict=True, as_dict=True,
) )
if membership and membership.batch: if membership and membership.batch_old:
membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title") membership.batch_title = frappe.db.get_value(
"LMS Batch Old", membership.batch_old, "title"
)
return membership return membership
return False return False
@@ -194,9 +196,9 @@ def get_students(course, batch=None):
filters = {"course": course, "member_type": "Student"} filters = {"course": course, "member_type": "Student"}
if batch: if batch:
filters["batch"] = batch filters["batch_old"] = batch
return frappe.get_all("LMS Batch Membership", filters, ["member"]) return frappe.get_all("LMS Enrollment", filters, ["member"])
def get_average_rating(course): def get_average_rating(course):
@@ -275,7 +277,7 @@ def get_lesson_url(course, lesson_number):
def get_batch(course, batch_name): def get_batch(course, batch_name):
return frappe.get_all("LMS Batch", {"name": batch_name, "course": course}) return frappe.get_all("LMS Batch Old", {"name": batch_name, "course": course})
def get_slugified_chapter_title(chapter): def get_slugified_chapter_title(chapter):
@@ -337,7 +339,7 @@ def get_mentors(course):
"User", mentor.mentor, ["name", "username", "full_name", "user_image"] "User", mentor.mentor, ["name", "username", "full_name", "user_image"]
) )
member.batch_count = frappe.db.count( member.batch_count = frappe.db.count(
"LMS Batch Membership", {"member": member.name, "member_type": "Mentor"} "LMS Enrollment", {"member": member.name, "member_type": "Mentor"}
) )
course_mentors.append(member) course_mentors.append(member)
return course_mentors return course_mentors
@@ -368,9 +370,7 @@ def get_course_progress(course, member=None):
def get_initial_members(course): def get_initial_members(course):
members = frappe.get_all( members = frappe.get_all("LMS Enrollment", {"course": course}, ["member"], limit=3)
"LMS Batch Membership", {"course": course}, ["member"], limit=3
)
member_details = [] member_details = []
for member in members: for member in members:
@@ -423,7 +423,7 @@ def get_popular_courses():
course_membership.append( course_membership.append(
{ {
"course": course.name, "course": course.name,
"members": cint(frappe.db.count("LMS Batch Membership", {"course": course.name})), "members": cint(frappe.db.count("LMS Enrollment", {"course": course.name})),
} }
) )
@@ -648,9 +648,9 @@ def get_restriction_details():
def get_all_memberships(member): def get_all_memberships(member):
return frappe.get_all( return frappe.get_all(
"LMS Batch Membership", "LMS Enrollment",
{"member": member}, {"member": member},
["name", "course", "batch", "current_lesson", "member_type", "progress"], ["name", "course", "batch_old", "current_lesson", "member_type", "progress"],
) )
@@ -724,8 +724,8 @@ def get_chart_data(chart_name, timespan, timegrain, from_date, to_date):
@frappe.whitelist() @frappe.whitelist()
def get_course_completion_data(): def get_course_completion_data():
all_membership = frappe.db.count("LMS Batch Membership") all_membership = frappe.db.count("LMS Enrollment")
completed = frappe.db.count("LMS Batch Membership", {"progress": ["like", "%100%"]}) completed = frappe.db.count("LMS Enrollment", {"progress": ["like", "%100%"]})
return { return {
"labels": ["Completed", "In Progress"], "labels": ["Completed", "In Progress"],

View File

@@ -12,14 +12,14 @@
"button_label": "Save", "button_label": "Save",
"creation": "2021-04-20 11:37:49.135114", "creation": "2021-04-20 11:37:49.135114",
"custom_css": ".datepicker.active {\n background-color: white;\n}\n\n[data-doctype=\"Web Form\"] {\n max-width: 720px;\n margin: 6rem auto;\n}", "custom_css": ".datepicker.active {\n background-color: white;\n}\n\n[data-doctype=\"Web Form\"] {\n max-width: 720px;\n margin: 6rem auto;\n}",
"doc_type": "LMS Batch", "doc_type": "LMS Batch Old",
"docstatus": 0, "docstatus": 0,
"doctype": "Web Form", "doctype": "Web Form",
"idx": 0, "idx": 0,
"is_standard": 1, "is_standard": 1,
"login_required": 1, "login_required": 1,
"max_attachment_size": 0, "max_attachment_size": 0,
"modified": "2021-06-15 18:49:50.530001", "modified": "2021-06-15 18:49:50.530002",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "add-a-new-batch", "name": "add-a-new-batch",

View File

@@ -1,7 +1,7 @@
{% if frappe.session.user != "Guest" %} {% if frappe.session.user != "Guest" %}
{% set membership = frappe.db.get_value("LMS Batch Membership", {% set membership = frappe.db.get_value("LMS Enrollment",
{"member": frappe.session.user, "course": course.name}, {"member": frappe.session.user, "course": course.name},
["name", "course", "batch", "current_lesson", "member_type", "progress"], as_dict=1) %} ["name", "course", "batch_old", "current_lesson", "member_type", "progress"], as_dict=1) %}
{% set progress = frappe.utils.cint(membership.progress) %} {% set progress = frappe.utils.cint(membership.progress) %}
{% else %} {% else %}
{% set membership, progress = None, None %} {% set membership, progress = None, None %}
@@ -123,7 +123,7 @@
{% set lesson_index = get_lesson_index(membership.current_lesson) or "1.1" %} {% set lesson_index = get_lesson_index(membership.current_lesson) or "1.1" %}
{% set query_parameter = "?batch=" + membership.batch if membership.batch else "" %} {% set query_parameter = "?batch=" + membership.batch_old if membership.batch_old else "" %}
<a class="stretched-link" href="{{ get_lesson_url(course.name, lesson_index) }}{{ query_parameter }}"></a> <a class="stretched-link" href="{{ get_lesson_url(course.name, lesson_index) }}{{ query_parameter }}"></a>

View File

@@ -144,7 +144,7 @@
"type": "Link" "type": "Link"
} }
], ],
"modified": "2023-05-11 15:41:25.514442", "modified": "2023-05-11 15:41:25.514443",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS", "name": "LMS",
@@ -161,7 +161,7 @@
"doc_view": "List", "doc_view": "List",
"format": "{} Enrolled", "format": "{} Enrolled",
"label": "Enrollments", "label": "Enrollments",
"link_to": "LMS Batch Membership", "link_to": "LMS Enrollment",
"stats_filter": "{\"member_type\":[\"=\",\"Student\"]}", "stats_filter": "{\"member_type\":[\"=\",\"Student\"]}",
"type": "DocType" "type": "DocType"
}, },
@@ -170,7 +170,7 @@
"doc_view": "List", "doc_view": "List",
"format": "{} Completed", "format": "{} Completed",
"label": "Course Completed", "label": "Course Completed",
"link_to": "LMS Batch Membership", "link_to": "LMS Enrollment",
"stats_filter": "{\"progress\":[\"like\",\"%100%\"]}", "stats_filter": "{\"progress\":[\"like\",\"%100%\"]}",
"type": "DocType" "type": "DocType"
}, },

View File

@@ -54,7 +54,7 @@ class CustomUser(User):
def get_batch_count(self) -> int: def get_batch_count(self) -> int:
"""Returns the number of batches authored by this user.""" """Returns the number of batches authored by this user."""
return frappe.db.count( return frappe.db.count(
"LMS Batch Membership", {"member": self.name, "member_type": "Mentor"} "LMS Enrollment", {"member": self.name, "member_type": "Mentor"}
) )
def get_user_reviews(self): def get_user_reviews(self):
@@ -112,7 +112,7 @@ def get_enrolled_courses():
if not course.published: if not course.published:
continue continue
course.enrollment_count = frappe.db.count( course.enrollment_count = frappe.db.count(
"LMS Batch Membership", {"course": course.name, "member_type": "Student"} "LMS Enrollment", {"course": course.name, "member_type": "Student"}
) )
course.avg_rating = get_average_rating(course.name) or 0 course.avg_rating = get_average_rating(course.name) or 0
progress = cint(membership.progress) progress = cint(membership.progress)
@@ -134,7 +134,7 @@ def get_course_membership(member=None, member_type=None):
if member_type: if member_type:
filters["member_type"] = member_type filters["member_type"] = member_type
return frappe.get_all("LMS Batch Membership", filters, ["name", "course", "progress"]) return frappe.get_all("LMS Enrollment", filters, ["name", "course", "progress"])
def get_authored_courses(member=None, only_published=True): def get_authored_courses(member=None, only_published=True):
@@ -167,7 +167,7 @@ def get_authored_courses(member=None, only_published=True):
if only_published and detail and not detail.published: if only_published and detail and not detail.published:
continue continue
detail.enrollment_count = frappe.db.count( detail.enrollment_count = frappe.db.count(
"LMS Batch Membership", {"course": detail.name, "member_type": "Student"} "LMS Enrollment", {"course": detail.name, "member_type": "Student"}
) )
detail.avg_rating = get_average_rating(detail.name) or 0 detail.avg_rating = get_average_rating(detail.name) or 0
course_details.append(detail) course_details.append(detail)

View File

@@ -62,4 +62,6 @@ execute:frappe.permissions.reset_perms("Course Evaluator")
execute:frappe.permissions.reset_perms("LMS Certificate Request") execute:frappe.permissions.reset_perms("LMS Certificate Request")
execute:frappe.permissions.reset_perms("LMS Certificate Evaluation") execute:frappe.permissions.reset_perms("LMS Certificate Evaluation")
lms.patches.v1_0.paid_certificate_to_paid_course #18-08-2023 lms.patches.v1_0.paid_certificate_to_paid_course #18-08-2023
lms.patches.v1_0.revert_class_registration #18-08-2023 lms.patches.v1_0.revert_class_registration #18-08-2023
lms.patches.v1_0.rename_lms_batch_doctype
lms.patches.v1_0.rename_lms_batch_membership_doctype

View File

@@ -3,7 +3,7 @@ import frappe
def execute(): def execute():
frappe.reload_doc("lms", "doctype", "lms_batch_membership") frappe.reload_doc("lms", "doctype", "lms_batch_membership")
memberships = frappe.get_all("LMS Batch Membership", ["member", "name"]) memberships = frappe.get_all("LMS Enrollment", ["member", "name"])
for membership in memberships: for membership in memberships:
email = frappe.db.get_value("Community Member", membership.member, "email") email = frappe.db.get_value("Community Member", membership.member, "email")
frappe.db.set_value("LMS Batch Membership", membership.name, "member", email) frappe.db.set_value("LMS Enrollment", membership.name, "member", email)

View File

@@ -7,7 +7,7 @@ from lms.lms.utils import get_course_progress
def execute(): def execute():
frappe.reload_doc("lms", "doctype", "lms_batch_membership") frappe.reload_doc("lms", "doctype", "lms_batch_membership")
memberships = frappe.get_all( memberships = frappe.get_all(
"LMS Batch Membership", ["name", "course", "member"], order_by="course" "LMS Enrollment", ["name", "course", "member"], order_by="course"
) )
if len(memberships): if len(memberships):
@@ -17,7 +17,7 @@ def execute():
current_course = membership.course current_course = membership.course
progress = rounded(get_course_progress(current_course, membership.member)) progress = rounded(get_course_progress(current_course, membership.member))
frappe.db.set_value("LMS Batch Membership", membership.name, "progress", progress) frappe.db.set_value("LMS Enrollment", membership.name, "progress", progress)
frappe.db.delete("Prepared Report", {"ref_report_doctype": "Course Progress Summary"}) frappe.db.delete("Prepared Report", {"ref_report_doctype": "Course Progress Summary"})
frappe.db.set_value("Report", "Course Progress Summary", "prepared_report", 0) frappe.db.set_value("Report", "Course Progress Summary", "prepared_report", 0)

View File

@@ -4,8 +4,8 @@ from frappe.utils import flt
def execute(): def execute():
frappe.reload_doc("lms", "doctype", "lms_course_progress") frappe.reload_doc("lms", "doctype", "lms_course_progress")
progress_records = frappe.get_all("LMS Batch Membership", fields=["name", "progress"]) progress_records = frappe.get_all("LMS Enrollment", fields=["name", "progress"])
for progress in progress_records: for progress in progress_records:
frappe.db.set_value( frappe.db.set_value(
"LMS Batch Membership", progress.name, "progress", flt(progress.progress) "LMS Enrollment", progress.name, "progress", flt(progress.progress)
) )

View File

@@ -0,0 +1,13 @@
import frappe
from frappe.model.rename_doc import rename_doc
def execute():
if frappe.db.exists("DocType", "LMS Batch Old"):
return
frappe.flags.ignore_route_conflict_validation = True
rename_doc("DocType", "LMS Batch", "LMS Batch Old")
frappe.flags.ignore_route_conflict_validation = False
frappe.reload_doctype("LMS Batch Old", force=True)

View File

@@ -0,0 +1,13 @@
import frappe
from frappe.model.rename_doc import rename_doc
def execute():
if frappe.db.exists("DocType", "LMS Enrollment"):
return
frappe.flags.ignore_route_conflict_validation = True
rename_doc("DocType", "LMS Batch Membership", "LMS Enrollment")
frappe.flags.ignore_route_conflict_validation = False
frappe.reload_doctype("LMS Enrollment", force=True)

View File

@@ -47,4 +47,4 @@ def get_add_on_members(plan: str) -> int:
def get_members() -> int: def get_members() -> int:
return frappe.db.count("LMS Batch Membership") return frappe.db.count("LMS Enrollment")

View File

@@ -1,75 +1,42 @@
<div class="stats-parent"> <div class="stats-parent">
{% if published_courses %}
{% if published_courses %}
<div class="common-card-style p-4 flex-column">
<div class="stats-label">
{{ _("Published Courses") }}
</div>
<div class="stats-value">
{{ frappe.utils.fmt_money(
frappe.db.count("LMS Course", {
"published": 1,
"upcoming": 0
})
, 0) }}
</div>
</div>
{% endif %}
{% if total_signups %}
<div class="common-card-style p-4 flex-column">
<div class="stats-label">
{{ _("Total Signups") }}
</div>
<div class="stats-value">
{{ frappe.utils.fmt_money(
frappe.db.count("User", {
"enabled": 1
})
, 0) }}
</div>
</div>
{% endif %}
{% if enrollment_count %}
<div class="common-card-style p-4 flex-column"> <div class="common-card-style p-4 flex-column">
<div class="stats-label"> <div class="stats-label">{{ _("Published Courses") }}</div>
{{ _("Enrollment Count") }}
</div>
<div class="stats-value"> <div class="stats-value">
{{ frappe.utils.fmt_money( {{ frappe.utils.fmt_money( frappe.db.count("LMS Course", {
frappe.db.count("LMS Batch Membership") "published": 1, "upcoming": 0 }) , 0) }}
, 0) }}
</div> </div>
</div> </div>
{% endif %} {% endif %} {% if total_signups %}
{% if course_completion %}
{% set course_completion_count = frappe.db.count("LMS Batch Membership", {
"progress":["like","%100%"]
}) %}
<div class="common-card-style p-4 flex-column"> <div class="common-card-style p-4 flex-column">
<div class="stats-label"> <div class="stats-label">{{ _("Total Signups") }}</div>
{{ _("Courses Completed") }} <div class="stats-value">
{{ frappe.utils.fmt_money( frappe.db.count("User", { "enabled": 1 })
, 0) }}
</div> </div>
</div>
{% endif %} {% if enrollment_count %}
<div class="common-card-style p-4 flex-column">
<div class="stats-label">{{ _("Enrollment Count") }}</div>
<div class="stats-value">
{{ frappe.utils.fmt_money( frappe.db.count("LMS Enrollment") , 0) }}
</div>
</div>
{% endif %} {% if course_completion %} {% set course_completion_count =
frappe.db.count("LMS Enrollment", { "progress":["like","%100%"] }) %}
<div class="common-card-style p-4 flex-column">
<div class="stats-label">{{ _("Courses Completed") }}</div>
<div class="stats-value"> <div class="stats-value">
{{ frappe.utils.fmt_money(course_completion_count, 0) }} {{ frappe.utils.fmt_money(course_completion_count, 0) }}
</div> </div>
</div> </div>
{% endif %} {% endif %} {% if lesson_completion %} {% set lesson_completion_count =
frappe.db.count("LMS Course Progress") %}
{% if lesson_completion %}
{% set lesson_completion_count = frappe.db.count("LMS Course Progress") %}
<div class="common-card-style p-4 flex-column"> <div class="common-card-style p-4 flex-column">
<div class="stats-label"> <div class="stats-label">{{ _("Lessons Completed") }}</div>
{{ _("Lessons Completed") }}
</div>
<div class="stats-value"> <div class="stats-value">
{{ frappe.utils.fmt_money(lesson_completion_count, 0) }} {{ frappe.utils.fmt_money(lesson_completion_count, 0) }}
</div> </div>
</div> </div>
{% endif %} {% endif %}
</div> </div>

View File

@@ -51,7 +51,7 @@ frappe.ready(() => {
frappe.call({ frappe.call({
"method": "lms.lms.doctype.lms_batch_membership.lms_batch_membership.create_membership", "method": "lms.lms.doctype.lms_batch_membership.lms_batch_membership.create_membership",
"args": { "args": {
"batch": {{ batch.name }}, "batch_old": {{ batch.name }},
"course": {{ batch.course }} "course": {{ batch.course }}
}, },
"callback": (data) => { "callback": (data) => {

View File

@@ -4,8 +4,8 @@ import frappe
def get_context(context): def get_context(context):
context.no_cache = 1 context.no_cache = 1
batch_name = frappe.form_dict["batch"] batch_name = frappe.form_dict["batch"]
context.batch = frappe.get_doc("LMS Batch", batch_name) context.batch_old = frappe.get_doc("LMS Batch Old", batch_name)
context.already_a_member = context.batch.is_member(frappe.session.user) context.already_a_member = context.batch_old.is_member(frappe.session.user)
context.batch.course_title = frappe.db.get_value( context.batch_old.course_title = frappe.db.get_value(
"LMS Course", context.batch.course, "title" "LMS Course", context.batch_old.course, "title"
) )

View File

@@ -72,7 +72,7 @@ def get_context(context):
context.page_extensions = get_page_extensions(context) context.page_extensions = get_page_extensions(context)
context.page_context = { context.page_context = {
"course": context.course.name, "course": context.course.name,
"batch": context.batch, "batch_old": context.batch_old,
"lesson": context.lesson.name if context.lesson.name else "New Lesson", "lesson": context.lesson.name if context.lesson.name else "New Lesson",
"is_member": context.membership is not None, "is_member": context.membership is not None,
} }

View File

@@ -12,7 +12,7 @@ def get_context(context):
raise frappe.PermissionError(_("You are not allowed to access this page.")) raise frappe.PermissionError(_("You are not allowed to access this page."))
membership = frappe.db.exists( membership = frappe.db.exists(
"LMS Batch Membership", {"member": frappe.session.user, "course": course_name} "LMS Enrollment", {"member": frappe.session.user, "course": course_name}
) )
if membership: if membership:

View File

@@ -1,78 +1,69 @@
{% extends "www/cohorts/base.html" %} {% extends "www/cohorts/base.html" %} {% block title %} {{ _("Manage") }} {{
{% block title %} course.title }} {% endblock %} {% block page_content %}
{{ _("Manage") }} {{ course.title }} <div class="course-home-headings">{{ cohort.title }}</div>
{% endblock %}
{% block page_content %}
<div class="course-home-headings">
{{ cohort.title }}
</div>
<p> <p>
{{ frappe.db.count("Cohort Subgroup", {"cohort": cohort.name}) }} {{ _("Subgroups") }} {{ frappe.db.count("Cohort Subgroup", {"cohort": cohort.name}) }} {{
| {{ frappe.db.count("Cohort Mentor", {"cohort": cohort.name}) }} {{ _("Mentors") }} _("Subgroups") }} | {{ frappe.db.count("Cohort Mentor", {"cohort":
| {{ frappe.db.count("LMS Batch Membership", {"cohort": cohort.name}) }} {{ _("Students") }} cohort.name}) }} {{ _("Mentors") }} | {{ frappe.db.count("LMS Enrollment",
| {{ frappe.db.count("Cohort Join Request", {"cohort": cohort.name}) }} {{ _("Join Requests") }} {"cohort": cohort.name}) }} {{ _("Students") }} | {{ frappe.db.count("Cohort
Join Request", {"cohort": cohort.name}) }} {{ _("Join Requests") }}
</p> </p>
{% if is_mentor %} {% if is_mentor %} {% set sg = mentor.get_subgroup() %}
{% set sg = mentor.get_subgroup() %}
<div class="alert alert-info medium"> <div class="alert alert-info medium">
<a href="{{sg.get_url()}}"> <a href="{{sg.get_url()}}">
{{ _("You are a mentor of {0} subgroup.").format(frappe.bold(sg.title)) }} {{ _("You are a mentor of {0} subgroup.").format(frappe.bold(sg.title))
</a> }}
</a>
</div> </div>
{% endif %} {% endif %}
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
{% set num_subgroups = cohort.get_subgroups() | length %} {% set num_subgroups = cohort.get_subgroups() | length %} {{
{{ render_navitem("Subgroups", "", page=page, count=num_subgroups) }} render_navitem("Subgroups", "", page=page, count=num_subgroups) }} {% for p
{% for p in cohort.get_pages(scope="Cohort") %} in cohort.get_pages(scope="Cohort") %} {{ render_navitem(p.title, p.slug,
{{ render_navitem(p.title, p.slug, page=page) }} page=page) }} {% endfor %}
{% endfor %}
</ul> </ul>
<div class="my-5"> <div class="my-5">
{% if not page %} {% if not page %} {{ render_subgroups() }} {% else %} {{ render_page(page)
{{ render_subgroups() }} }} {% endif %}
{% else %}
{{ render_page(page) }}
{% endif %}
</div> </div>
{% endblock %} {% endblock %} {% macro render_subgroups() %}
<ul class="list-group">
{% macro render_subgroups() %} {% for sg in cohort.get_subgroups(include_counts=True) %}
<ul class="list-group"> <li class="list-group-item">
{% for sg in cohort.get_subgroups(include_counts=True) %} <div>
<li class="list-group-item"> <a
<div> class="subgroup-title"
<a class="subgroup-title" style="font-weight: 700; color: inherit;" style="font-weight: 700; color: inherit"
href="/courses/{{course.name}}/subgroups/{{cohort.slug}}/{{sg.slug}}"> href="/courses/{{course.name}}/subgroups/{{cohort.slug}}/{{sg.slug}}"
{{ sg.title }} >
</a> {{ sg.title }}
</div> </a>
<div style="font-size: 0.8em;"> </div>
{{ sg.num_mentors }} {{ _("Mentors") }} <div style="font-size: 0.8em">
| {{ sg.num_mentors }} {{ _("Mentors") }} | {{sg.num_students}} {{
{{sg.num_students}} {{ _("Students") }} _("Students") }} | {{sg.num_join_requests}} {{ _("Join Requests") }}
| </div>
{{sg.num_join_requests}} {{ _("Join Requests") }} </li>
</div> {% endfor %}
</li> </ul>
{% endfor %} {% endmacro %} {% macro render_navitem(title, link, page, count=-1) %}
</ul> <li class="nav-item">
{% endmacro %} <a
class="nav-link {{ 'active' if link==page }}"
{% macro render_navitem(title, link, page, count=-1) %} href="/courses/{{course.name}}/cohorts/{{cohort.slug}}/{{link}}"
<li class="nav-item"> >
<a class="nav-link {{ 'active' if link==page }}" href="/courses/{{course.name}}/cohorts/{{cohort.slug}}/{{link}}"> {{ title }} {% if count != -1 %}
{{ title }} <span
{% if count != -1 %} class="badge {{'badge-primary' if link==page else 'badge-secondary'}}"
<span class="badge {{'badge-primary' if link==page else 'badge-secondary'}}"> >
{{ count }} {{ count }}
</span> </span>
{% endif %} {% endif %}
</a> </a>
</li> </li>
{% endmacro %} {% endmacro %}

View File

@@ -1,53 +1,40 @@
{% extends "www/cohorts/base.html" %} {% extends "www/cohorts/base.html" %} {% block title %} _("Manage") {{
{% block title %} course.title }} {% endblock %} {% block page_content %} {% if cohorts %}
_("Manage") {{ course.title }} <h2>{{ _("Cohorts") }}</h2>
{% endblock %} <div class="row">
{% for cohort in cohorts %}
{% block page_content %} <div class="col-md-6">{{ render_cohort(course, cohort) }}</div>
{% if cohorts %} {% endfor %}
<h2> </div>
{{ _("Cohorts") }} {% else %}
</h2> <h2>{{ _("Permission Denied") }}</h2>
<div class="row"> <p>{{ _("You don't have permission to manage this course.") }}</p>
{% for cohort in cohorts %} {% endif %} {% endblock %} {% macro render_cohort(course, cohort) %}
<div class="col-md-6">
{{ render_cohort(course, cohort) }}
</div>
{% endfor %}
</div>
{% else %}
<h2>
{{ _("Permission Denied") }}
</h2>
<p>
{{ _("You don't have permission to manage this course.") }}
</p>
{% endif %}
{% endblock %}
{% macro render_cohort(course, cohort) %}
<div class="cards-parent"> <div class="cards-parent">
<div class="common-card-style flex-column p-5"> <div class="common-card-style flex-column p-5">
<h5 class="card-title"> <h5 class="card-title">{{ cohort.title }}</h5>
{{ cohort.title }}
</h5>
{% if cohort.begin_date %} {% if cohort.begin_date %}
<h6 class="card-subtitle mb-2 text-muted"> <h6 class="card-subtitle mb-2 text-muted">
{{ frappe.utils.format_date(cohort.begin_date, "medium") }} - {{ frappe.utils.format_date(cohort.end_date, "medium") }} {{ frappe.utils.format_date(cohort.begin_date, "medium") }} - {{
</h6> frappe.utils.format_date(cohort.end_date, "medium") }}
{% endif %} </h6>
{% endif %}
<p class="mb-0"> <p class="mb-0">
{{ frappe.db.count("Cohort Subgroup", {"cohort": cohort.name}) }} {{ _("Subgroups") }} {{ frappe.db.count("Cohort Subgroup", {"cohort": cohort.name}) }} {{
| {{ frappe.db.count("Cohort Mentor", {"cohort": cohort.name}) }} {{ _("Mentors") }} _("Subgroups") }} | {{ frappe.db.count("Cohort Mentor", {"cohort":
| {{ frappe.db.count("LMS Batch Membership", {"cohort": cohort.name}) }} {{ _("Students") }} cohort.name}) }} {{ _("Mentors") }} | {{ frappe.db.count("LMS
| {{ frappe.db.count("Cohort Join Request", {"cohort": cohort.name}) }} {{ _("Join Requests") }} Enrollment", {"cohort": cohort.name}) }} {{ _("Students") }} | {{
</p> frappe.db.count("Cohort Join Request", {"cohort": cohort.name}) }}
{{ _("Join Requests") }}
</p>
<a
<a class="stretched-link" href="/courses/{{course.name}}/cohorts/{{cohort.slug}}"></a> class="stretched-link"
</div> href="/courses/{{course.name}}/cohorts/{{cohort.slug}}"
></a>
</div>
</div> </div>
{% endmacro %} {% endmacro %}

View File

@@ -85,7 +85,7 @@ def set_course_context(context, course_name):
context.course = course context.course = course
membership = get_membership(course.name, frappe.session.user) membership = get_membership(course.name, frappe.session.user)
context.course.query_parameter = ( context.course.query_parameter = (
"?batch=" + membership.batch if membership and membership.batch else "" "?batch=" + membership.batch_old if membership and membership.batch_old else ""
) )
context.membership = membership context.membership = membership
context.is_instructor = is_instructor(course.name) context.is_instructor = is_instructor(course.name)

View File

@@ -56,7 +56,7 @@ def get_courses():
live_courses, upcoming_courses = [], [] live_courses, upcoming_courses = [], []
for course in courses: for course in courses:
course.enrollment_count = frappe.db.count( course.enrollment_count = frappe.db.count(
"LMS Batch Membership", {"course": course.name, "member_type": "Student"} "LMS Enrollment", {"course": course.name, "member_type": "Student"}
) )
course.avg_rating = get_average_rating(course.name) or 0 course.avg_rating = get_average_rating(course.name) or 0
if course.upcoming: if course.upcoming:

View File

@@ -27,9 +27,11 @@ def get_common_context(context):
membership = get_membership(course.name, frappe.session.user, batch_name) membership = get_membership(course.name, frappe.session.user, batch_name)
context.membership = membership context.membership = membership
context.progress = frappe.utils.cint(membership.progress) if membership else 0 context.progress = frappe.utils.cint(membership.progress) if membership else 0
context.batch = membership.batch if membership and membership.batch else None context.batch_old = (
membership.batch_old if membership and membership.batch_old else None
)
context.course.query_parameter = ( context.course.query_parameter = (
"?batch=" + membership.batch if membership and membership.batch else "" "?batch=" + membership.batch_old if membership and membership.batch_old else ""
) )
context.livecode_url = get_livecode_url() context.livecode_url = get_livecode_url()