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,
},
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):
"""Saves the current lesson for a student/mentor."""
name = frappe.get_value(
doctype="LMS Batch Membership",
doctype="LMS Enrollment",
filters={"course": course_name, "member": frappe.session.user},
fieldname="name",
)
if not name:
return
doc = frappe.get_doc("LMS Batch Membership", name)
doc = frappe.get_doc("LMS Enrollment", name)
doc.current_lesson = lesson_name
doc.save(ignore_permissions=True)
return {"current_lesson": doc.current_lesson}

View File

@@ -7,7 +7,7 @@
"custom_options": "{\"type\": \"line\", \"axisOptions\": {\"xIsSeries\": 1}, \"lineOptions\": {\"regionFill\": 1}}",
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "LMS Batch Membership",
"document_type": "LMS Enrollment",
"dynamic_filters_json": "[]",
"filters_json": "[]",
"group_by_type": "Count",
@@ -15,7 +15,7 @@
"is_public": 1,
"is_standard": 1,
"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",
"module": "LMS",
"name": "Course Enrollments",

View File

@@ -16,7 +16,7 @@ class Cohort(Document):
if include_counts:
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")
for s in subgroups:
s.num_mentors = mentors.get(s.name, 0)
@@ -56,7 +56,7 @@ class Cohort(Document):
return {
"subgroups": self._get_count("Cohort Subgroup"),
"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"),
}

View File

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

View File

@@ -23,7 +23,7 @@ class CohortSubgroup(Document):
def has_student(self, email):
"""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)
def has_join_request(self, email):
@@ -45,7 +45,7 @@ class CohortSubgroup(Document):
def get_students(self):
emails = frappe.get_all(
"LMS Batch Membership",
"LMS Enrollment",
filters={"subgroup": self.name},
fields=["member"],
pluck="member",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,11 +5,11 @@ import frappe
from frappe import _
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
class LMSBatch(Document):
class LMSBatchOld(Document):
def validate(self):
pass
# self.validate_if_mentor()
@@ -28,19 +28,19 @@ class LMSBatch(Document):
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:
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):
"""Returns the membership document of given user."""
name = frappe.get_value(
doctype="LMS Batch Membership",
filters={"batch": self.name, "member": email},
doctype="LMS Enrollment",
filters={"batch_old": self.name, "member": email},
fieldname="name",
)
return frappe.get_doc("LMS Batch Membership", name)
return frappe.get_doc("LMS Enrollment", name)
def get_current_lesson(self, 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(
{
"doctype": "LMS Message",
"batch": batch,
"batch_old": batch,
"author": frappe.session.user,
"message": message,
}
@@ -64,10 +64,10 @@ def save_message(message, batch):
def switch_batch(course_name, email, batch_name):
"""Switches the user from the current batch of the course to a new batch."""
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:
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}")
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()
# 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"):
doc = frappe.get_doc("Exercise Submission", name)
print("updating exercise submission", name)
doc.batch = batch_name
doc.batch_old = batch_name
doc.save()

View File

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

View File

@@ -108,7 +108,7 @@ def create_certificate_request(
course, date, day, start_time, end_time, class_name=None
):
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:

View File

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

View File

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

View File

@@ -119,20 +119,18 @@ class LMSCourse(Document):
return
batch_name = frappe.get_value(
doctype="LMS Batch Membership",
doctype="LMS Enrollment",
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):
batches = frappe.get_all("LMS Batch", {"course": self.name})
batches = frappe.get_all("LMS Batch Old", {"course": self.name})
if mentor:
# TODO: optimize this
memberships = frappe.db.get_all(
"LMS Batch Membership", {"member": mentor}, ["batch"]
)
batch_names = {m.batch for m in memberships}
memberships = frappe.db.get_all("LMS Enrollment", {"member": mentor}, ["batch_old"])
batch_names = {m.batch_old for m in memberships}
return [b for b in batches if b.name in batch_names]
def get_cohorts(self):
@@ -162,10 +160,12 @@ class LMSCourse(Document):
def get_all_memberships(self, member):
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:
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
@@ -452,7 +452,7 @@ def verify_payment(response, course, address, order_id):
def create_membership(address, response, course, client):
try:
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"])
membership.update(

View File

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

View File

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

View File

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

View File

@@ -6,17 +6,17 @@ from frappe import _
from frappe.model.document import Document
class LMSBatchMembership(Document):
class LMSEnrollment(Document):
def validate(self):
self.validate_membership_in_same_batch()
self.validate_membership_in_different_batch_same_course()
def validate_membership_in_same_batch(self):
filters = {"member": self.member, "course": self.course, "name": ["!=", self.name]}
if self.batch:
filters["batch"] = self.batch
if self.batch_old:
filters["batch_old"] = self.batch_old
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:
@@ -34,16 +34,16 @@ class LMSBatchMembership(Document):
if self.member_type != "Student":
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(
"LMS Batch Membership",
"LMS Enrollment",
filters={
"member": self.member,
"name": ["!=", self.name],
"member_type": "Student",
"course": self.course,
},
fields=["batch", "member_type", "name"],
fields=["batch_old", "member_type", "name"],
)
if memberships:
@@ -51,7 +51,7 @@ class LMSBatchMembership(Document):
member_name = frappe.db.get_value("User", self.member, "full_name")
frappe.throw(
_("{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(
{
"doctype": "LMS Batch Membership",
"batch": batch,
"doctype": "LMS Enrollment",
"batch_old": batch,
"course": course,
"role": role,
"member_type": member_type,
@@ -76,15 +76,13 @@ def create_membership(
@frappe.whitelist()
def update_current_membership(batch, course, member):
all_memberships = frappe.get_all(
"LMS Batch Membership", {"member": member, "course": course}
"LMS Enrollment", {"member": member, "course": course}
)
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(
"LMS Batch Membership", {"batch": batch, "member": member}
"LMS Enrollment", {"batch_old": batch, "member": member}
)
if len(current_membership):
frappe.db.set_value(
"LMS Batch Membership", current_membership[0].name, "is_current", 1
)
frappe.db.set_value("LMS Enrollment", 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
class TestLMSBatchMembership(unittest.TestCase):
class TestLMSEnrollment(unittest.TestCase):
def setUp(self):
frappe.db.sql("DELETE FROM `tabLMS Batch Membership`")
frappe.db.sql("DELETE FROM `tabLMS Batch`")
frappe.db.sql("delete from `tabLMS Course Mentor Mapping`")
frappe.db.sql("DELETE FROM `tabUser` where email like '%@test.com'")
frappe.db.delete("LMS Enrollment")
frappe.db.delete("LMS Batch Old")
frappe.db.delete("LMS Course Mentor Mapping")
frappe.db.delete("User", {"email": ("like", "%@test.com")})
def new_course_batch(self):
course = new_course("Test Course")
@@ -26,7 +26,7 @@ class TestLMSBatchMembership(unittest.TestCase):
batch = frappe.get_doc(
{
"doctype": "LMS Batch",
"doctype": "LMS Batch Old",
"name": "test-batch",
"title": "Test Batch",
"course": course.name,
@@ -37,13 +37,14 @@ class TestLMSBatchMembership(unittest.TestCase):
frappe.session.user = "Administrator"
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(
{
"doctype": "LMS Batch Membership",
"batch": batch_name,
"doctype": "LMS Enrollment",
"batch_old": batch_name,
"member": member_name,
"member_type": member_type,
"course": course,
}
)
doc.insert()
@@ -52,7 +53,7 @@ class TestLMSBatchMembership(unittest.TestCase):
def test_membership(self):
course, batch = self.new_course_batch()
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.member_name == member.full_name
@@ -60,7 +61,7 @@ class TestLMSBatchMembership(unittest.TestCase):
def test_membership_change_role(self):
course, batch = self.new_course_batch()
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
membership.role = "Admin"

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
"""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,
)
from .doctype.lms_course.lms_course import LMSCourse as Course

View File

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

View File

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

View File

@@ -63,19 +63,21 @@ def get_membership(course, member=None, batch=None):
filters = {"member": member, "course": course}
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:
membership = frappe.db.get_value(
"LMS Batch Membership",
"LMS Enrollment",
filters,
["name", "batch", "current_lesson", "member_type", "progress"],
["name", "batch_old", "current_lesson", "member_type", "progress"],
as_dict=True,
)
if membership and membership.batch:
membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title")
if membership and membership.batch_old:
membership.batch_title = frappe.db.get_value(
"LMS Batch Old", membership.batch_old, "title"
)
return membership
return False
@@ -194,9 +196,9 @@ def get_students(course, batch=None):
filters = {"course": course, "member_type": "Student"}
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):
@@ -275,7 +277,7 @@ def get_lesson_url(course, lesson_number):
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):
@@ -337,7 +339,7 @@ def get_mentors(course):
"User", mentor.mentor, ["name", "username", "full_name", "user_image"]
)
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)
return course_mentors
@@ -368,9 +370,7 @@ def get_course_progress(course, member=None):
def get_initial_members(course):
members = frappe.get_all(
"LMS Batch Membership", {"course": course}, ["member"], limit=3
)
members = frappe.get_all("LMS Enrollment", {"course": course}, ["member"], limit=3)
member_details = []
for member in members:
@@ -423,7 +423,7 @@ def get_popular_courses():
course_membership.append(
{
"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):
return frappe.get_all(
"LMS Batch Membership",
"LMS Enrollment",
{"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()
def get_course_completion_data():
all_membership = frappe.db.count("LMS Batch Membership")
completed = frappe.db.count("LMS Batch Membership", {"progress": ["like", "%100%"]})
all_membership = frappe.db.count("LMS Enrollment")
completed = frappe.db.count("LMS Enrollment", {"progress": ["like", "%100%"]})
return {
"labels": ["Completed", "In Progress"],

View File

@@ -12,14 +12,14 @@
"button_label": "Save",
"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}",
"doc_type": "LMS Batch",
"doc_type": "LMS Batch Old",
"docstatus": 0,
"doctype": "Web Form",
"idx": 0,
"is_standard": 1,
"login_required": 1,
"max_attachment_size": 0,
"modified": "2021-06-15 18:49:50.530001",
"modified": "2021-06-15 18:49:50.530002",
"modified_by": "Administrator",
"module": "LMS",
"name": "add-a-new-batch",

View File

@@ -1,7 +1,7 @@
{% 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},
["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) %}
{% else %}
{% set membership, progress = None, None %}
@@ -123,7 +123,7 @@
{% 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>

View File

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

View File

@@ -54,7 +54,7 @@ class CustomUser(User):
def get_batch_count(self) -> int:
"""Returns the number of batches authored by this user."""
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):
@@ -112,7 +112,7 @@ def get_enrolled_courses():
if not course.published:
continue
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
progress = cint(membership.progress)
@@ -134,7 +134,7 @@ def get_course_membership(member=None, member_type=None):
if 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):
@@ -167,7 +167,7 @@ def get_authored_courses(member=None, only_published=True):
if only_published and detail and not detail.published:
continue
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
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 Evaluation")
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():
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:
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():
frappe.reload_doc("lms", "doctype", "lms_batch_membership")
memberships = frappe.get_all(
"LMS Batch Membership", ["name", "course", "member"], order_by="course"
"LMS Enrollment", ["name", "course", "member"], order_by="course"
)
if len(memberships):
@@ -17,7 +17,7 @@ def execute():
current_course = membership.course
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.set_value("Report", "Course Progress Summary", "prepared_report", 0)

View File

@@ -4,8 +4,8 @@ from frappe.utils import flt
def execute():
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:
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:
return frappe.db.count("LMS Batch Membership")
return frappe.db.count("LMS Enrollment")

View File

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

View File

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

View File

@@ -4,8 +4,8 @@ import frappe
def get_context(context):
context.no_cache = 1
batch_name = frappe.form_dict["batch"]
context.batch = frappe.get_doc("LMS Batch", batch_name)
context.already_a_member = context.batch.is_member(frappe.session.user)
context.batch.course_title = frappe.db.get_value(
"LMS Course", context.batch.course, "title"
context.batch_old = frappe.get_doc("LMS Batch Old", batch_name)
context.already_a_member = context.batch_old.is_member(frappe.session.user)
context.batch_old.course_title = frappe.db.get_value(
"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_context = {
"course": context.course.name,
"batch": context.batch,
"batch_old": context.batch_old,
"lesson": context.lesson.name if context.lesson.name else "New Lesson",
"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."))
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:

View File

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

View File

@@ -1,53 +1,40 @@
{% extends "www/cohorts/base.html" %}
{% block title %}
_("Manage") {{ course.title }}
{% endblock %}
{% block page_content %}
{% if cohorts %}
<h2>
{{ _("Cohorts") }}
</h2>
<div class="row">
{% for cohort in cohorts %}
<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) %}
{% extends "www/cohorts/base.html" %} {% block title %} _("Manage") {{
course.title }} {% endblock %} {% block page_content %} {% if cohorts %}
<h2>{{ _("Cohorts") }}</h2>
<div class="row">
{% for cohort in cohorts %}
<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="common-card-style flex-column p-5">
<h5 class="card-title">
{{ cohort.title }}
</h5>
<div class="common-card-style flex-column p-5">
<h5 class="card-title">{{ cohort.title }}</h5>
{% if cohort.begin_date %}
<h6 class="card-subtitle mb-2 text-muted">
{{ frappe.utils.format_date(cohort.begin_date, "medium") }} - {{ frappe.utils.format_date(cohort.end_date, "medium") }}
</h6>
{% endif %}
{% if cohort.begin_date %}
<h6 class="card-subtitle mb-2 text-muted">
{{ frappe.utils.format_date(cohort.begin_date, "medium") }} - {{
frappe.utils.format_date(cohort.end_date, "medium") }}
</h6>
{% endif %}
<p class="mb-0">
{{ frappe.db.count("Cohort Subgroup", {"cohort": cohort.name}) }} {{ _("Subgroups") }}
| {{ frappe.db.count("Cohort Mentor", {"cohort": cohort.name}) }} {{ _("Mentors") }}
| {{ frappe.db.count("LMS Batch Membership", {"cohort": cohort.name}) }} {{ _("Students") }}
| {{ frappe.db.count("Cohort Join Request", {"cohort": cohort.name}) }} {{ _("Join Requests") }}
</p>
<p class="mb-0">
{{ frappe.db.count("Cohort Subgroup", {"cohort": cohort.name}) }} {{
_("Subgroups") }} | {{ frappe.db.count("Cohort Mentor", {"cohort":
cohort.name}) }} {{ _("Mentors") }} | {{ frappe.db.count("LMS
Enrollment", {"cohort": cohort.name}) }} {{ _("Students") }} | {{
frappe.db.count("Cohort Join Request", {"cohort": cohort.name}) }}
{{ _("Join Requests") }}
</p>
<a class="stretched-link" href="/courses/{{course.name}}/cohorts/{{cohort.slug}}"></a>
</div>
<a
class="stretched-link"
href="/courses/{{course.name}}/cohorts/{{cohort.slug}}"
></a>
</div>
</div>
{% endmacro %}

View File

@@ -85,7 +85,7 @@ def set_course_context(context, course_name):
context.course = course
membership = get_membership(course.name, frappe.session.user)
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.is_instructor = is_instructor(course.name)

View File

@@ -56,7 +56,7 @@ def get_courses():
live_courses, upcoming_courses = [], []
for course in courses:
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
if course.upcoming:

View File

@@ -27,9 +27,11 @@ def get_common_context(context):
membership = get_membership(course.name, frappe.session.user, batch_name)
context.membership = membership
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 = (
"?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()