refactor: replaced Batch Student child table with LMS Batch Enrollment doctype
This commit is contained in:
Submodule frappe-ui updated: 8cd9b06a5e...1c97498fb2
@@ -285,7 +285,7 @@ const deleteStudents = createResource({
|
|||||||
url: 'lms.lms.api.delete_documents',
|
url: 'lms.lms.api.delete_documents',
|
||||||
makeParams(values) {
|
makeParams(values) {
|
||||||
return {
|
return {
|
||||||
doctype: 'Batch Student',
|
doctype: 'LMS Batch Enrollment',
|
||||||
documents: values.students,
|
documents: values.students,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -46,11 +46,9 @@ const studentResource = createResource({
|
|||||||
makeParams(values) {
|
makeParams(values) {
|
||||||
return {
|
return {
|
||||||
doc: {
|
doc: {
|
||||||
doctype: 'Batch Student',
|
doctype: 'LMS Batch Enrollment',
|
||||||
parent: props.batch,
|
batch: props.batch,
|
||||||
parenttype: 'LMS Batch',
|
member: student.value,
|
||||||
parentfield: 'students',
|
|
||||||
student: student.value,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
<div class="border-r">
|
<div class="border-r">
|
||||||
<Tabs
|
<Tabs
|
||||||
v-model="tabIndex"
|
v-model="tabIndex"
|
||||||
|
as="div"
|
||||||
:tabs="tabs"
|
:tabs="tabs"
|
||||||
tablistClass="overflow-y-hidden bg-white"
|
tablistClass="overflow-y-hidden bg-white"
|
||||||
>
|
>
|
||||||
@@ -54,7 +55,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #default="{ tab }">
|
<template #tab-panel="{ tab }">
|
||||||
<div class="pt-5 px-5 pb-10">
|
<div class="pt-5 px-5 pb-10">
|
||||||
<div v-if="tab.label == 'Courses'">
|
<div v-if="tab.label == 'Courses'">
|
||||||
<BatchCourses :batch="batch.data.name" />
|
<BatchCourses :batch="batch.data.name" />
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
<div class="">
|
<div class="">
|
||||||
<Tabs
|
<Tabs
|
||||||
v-if="hasCourses"
|
v-if="hasCourses"
|
||||||
|
as="div"
|
||||||
v-model="tabIndex"
|
v-model="tabIndex"
|
||||||
tablistClass="overflow-x-visible flex-wrap !gap-3 md:flex-nowrap"
|
tablistClass="overflow-x-visible flex-wrap !gap-3 md:flex-nowrap"
|
||||||
:tabs="makeTabs"
|
:tabs="makeTabs"
|
||||||
@@ -68,7 +69,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #default="{ tab }">
|
<template #tab-panel="{ tab }">
|
||||||
<div
|
<div
|
||||||
v-if="tab.courses && tab.courses.value.length"
|
v-if="tab.courses && tab.courses.value.length"
|
||||||
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 3xl:grid-cols-5 gap-7 my-5 mx-5"
|
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 3xl:grid-cols-5 gap-7 my-5 mx-5"
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
server: {
|
||||||
|
allowedHosts: ['fs'],
|
||||||
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': path.resolve(__dirname, 'src'),
|
'@': path.resolve(__dirname, 'src'),
|
||||||
|
|||||||
1018
frontend/yarn.lock
1018
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -220,7 +220,7 @@ def validate_billing_access(type, name):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
membership = frappe.db.exists(
|
membership = frappe.db.exists(
|
||||||
"Batch Student", {"student": frappe.session.user, "parent": name}
|
"LMS Batch Enrollment", {"member": frappe.session.user, "batch": name}
|
||||||
)
|
)
|
||||||
if membership:
|
if membership:
|
||||||
access = False
|
access = False
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-10-26 16:52:04.266693",
|
"modified": "2023-10-26 16:52:04.266694",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "Batch Student",
|
"name": "Batch Student",
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
"batch_details",
|
"batch_details",
|
||||||
"batch_details_raw",
|
"batch_details_raw",
|
||||||
"section_break_jgji",
|
"section_break_jgji",
|
||||||
"students",
|
|
||||||
"courses",
|
"courses",
|
||||||
"assessment_tab",
|
"assessment_tab",
|
||||||
"assessment",
|
"assessment",
|
||||||
@@ -86,12 +85,6 @@
|
|||||||
"fieldname": "section_break_6",
|
"fieldname": "section_break_6",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "students",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"label": "Students",
|
|
||||||
"options": "Batch Student"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "courses",
|
"fieldname": "courses",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
@@ -328,8 +321,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [
|
||||||
"modified": "2025-01-17 10:23:10.580311",
|
{
|
||||||
|
"link_doctype": "LMS Batch Enrollment",
|
||||||
|
"link_fieldname": "batch"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"modified": "2025-02-10 12:01:22.476325",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Batch",
|
"name": "LMS Batch",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import json
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import cint, format_date, format_datetime, get_time, getdate, add_days
|
from frappe.utils import cint, format_datetime, get_time
|
||||||
from lms.lms.utils import (
|
from lms.lms.utils import (
|
||||||
get_lessons,
|
get_lessons,
|
||||||
get_lesson_index,
|
get_lesson_index,
|
||||||
@@ -18,7 +18,6 @@ from lms.lms.utils import (
|
|||||||
update_payment_record,
|
update_payment_record,
|
||||||
generate_slug,
|
generate_slug,
|
||||||
)
|
)
|
||||||
from frappe.email.doctype.email_template.email_template import get_email_template
|
|
||||||
|
|
||||||
|
|
||||||
class LMSBatch(Document):
|
class LMSBatch(Document):
|
||||||
@@ -27,15 +26,12 @@ class LMSBatch(Document):
|
|||||||
self.validate_seats_left()
|
self.validate_seats_left()
|
||||||
self.validate_batch_end_date()
|
self.validate_batch_end_date()
|
||||||
self.validate_duplicate_courses()
|
self.validate_duplicate_courses()
|
||||||
self.validate_duplicate_students()
|
|
||||||
self.validate_payments_app()
|
self.validate_payments_app()
|
||||||
self.validate_amount_and_currency()
|
self.validate_amount_and_currency()
|
||||||
self.validate_duplicate_assessments()
|
self.validate_duplicate_assessments()
|
||||||
self.validate_membership()
|
self.validate_membership()
|
||||||
self.validate_timetable()
|
self.validate_timetable()
|
||||||
self.send_confirmation_mail()
|
|
||||||
self.validate_evaluation_end_date()
|
self.validate_evaluation_end_date()
|
||||||
self.add_students_to_live_class()
|
|
||||||
|
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
if not self.name:
|
if not self.name:
|
||||||
@@ -91,86 +87,20 @@ class LMSBatch(Document):
|
|||||||
if self.evaluation_end_date and self.evaluation_end_date < self.end_date:
|
if self.evaluation_end_date and self.evaluation_end_date < self.end_date:
|
||||||
frappe.throw(_("Evaluation end date cannot be less than the batch end date."))
|
frappe.throw(_("Evaluation end date cannot be less than the batch end date."))
|
||||||
|
|
||||||
def send_confirmation_mail(self):
|
|
||||||
for student in self.students:
|
|
||||||
outgoing_email_account = frappe.get_cached_value(
|
|
||||||
"Email Account", {"default_outgoing": 1, "enable_outgoing": 1}, "name"
|
|
||||||
)
|
|
||||||
if (
|
|
||||||
not student.confirmation_email_sent
|
|
||||||
and getdate(student.creation) >= add_days(getdate(), -2)
|
|
||||||
and (outgoing_email_account or frappe.conf.get("mail_login"))
|
|
||||||
):
|
|
||||||
self.send_mail(student)
|
|
||||||
student.confirmation_email_sent = 1
|
|
||||||
|
|
||||||
def send_mail(self, student):
|
|
||||||
subject = _("Enrollment Confirmation for the Next Training Batch")
|
|
||||||
template = "batch_confirmation"
|
|
||||||
custom_template = frappe.db.get_single_value(
|
|
||||||
"LMS Settings", "batch_confirmation_template"
|
|
||||||
)
|
|
||||||
|
|
||||||
args = {
|
|
||||||
"title": self.title,
|
|
||||||
"student_name": student.student_name,
|
|
||||||
"start_time": self.start_time,
|
|
||||||
"start_date": self.start_date,
|
|
||||||
"medium": self.medium,
|
|
||||||
"name": self.name,
|
|
||||||
}
|
|
||||||
|
|
||||||
if custom_template:
|
|
||||||
email_template = get_email_template(custom_template, args)
|
|
||||||
subject = email_template.get("subject")
|
|
||||||
content = email_template.get("message")
|
|
||||||
|
|
||||||
frappe.sendmail(
|
|
||||||
recipients=student.student,
|
|
||||||
subject=subject,
|
|
||||||
template=template if not custom_template else None,
|
|
||||||
content=content if custom_template else None,
|
|
||||||
args=args,
|
|
||||||
header=[subject, "green"],
|
|
||||||
retry=3,
|
|
||||||
)
|
|
||||||
|
|
||||||
def validate_membership(self):
|
def validate_membership(self):
|
||||||
|
members = frappe.get_all('LMS Batch Enrollment', filters={'batch': self.name}, pluck=['member'])
|
||||||
for course in self.courses:
|
for course in self.courses:
|
||||||
for student in self.students:
|
for member in members:
|
||||||
filters = {
|
if not frappe.db.exists('LMS Enrollment', {'course': course.course, 'member': member}):
|
||||||
"doctype": "LMS Enrollment",
|
enrollment = frappe.new_doc('LMS Enrollment')
|
||||||
"member": student.student,
|
enrollment.course = course.course
|
||||||
"course": course.course,
|
enrollment.member = member
|
||||||
}
|
enrollment.save()
|
||||||
if not frappe.db.exists(filters):
|
|
||||||
frappe.get_doc(filters).save()
|
|
||||||
|
|
||||||
def validate_seats_left(self):
|
def validate_seats_left(self):
|
||||||
if cint(self.seat_count) < len(self.students):
|
if cint(self.seat_count) < len(self.students):
|
||||||
frappe.throw(_("There are no seats available in this batch."))
|
frappe.throw(_("There are no seats available in this batch."))
|
||||||
|
|
||||||
def add_students_to_live_class(self):
|
|
||||||
for student in self.students:
|
|
||||||
if student.is_new():
|
|
||||||
live_classes = frappe.get_all(
|
|
||||||
"LMS Live Class", {"batch_name": self.name}, ["name", "event"]
|
|
||||||
)
|
|
||||||
|
|
||||||
for live_class in live_classes:
|
|
||||||
if live_class.event:
|
|
||||||
frappe.get_doc(
|
|
||||||
{
|
|
||||||
"doctype": "Event Participants",
|
|
||||||
"reference_doctype": "User",
|
|
||||||
"reference_docname": student.student,
|
|
||||||
"email": student.student,
|
|
||||||
"parent": live_class.event,
|
|
||||||
"parenttype": "Event",
|
|
||||||
"parentfield": "event_participants",
|
|
||||||
}
|
|
||||||
).save()
|
|
||||||
|
|
||||||
def validate_timetable(self):
|
def validate_timetable(self):
|
||||||
for schedule in self.timetable:
|
for schedule in self.timetable:
|
||||||
if schedule.start_time and schedule.end_time:
|
if schedule.start_time and schedule.end_time:
|
||||||
|
|||||||
0
lms/lms/doctype/lms_batch_enrollment/__init__.py
Normal file
0
lms/lms/doctype/lms_batch_enrollment/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2025, Frappe and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
// frappe.ui.form.on("LMS Batch Enrollment", {
|
||||||
|
// refresh(frm) {
|
||||||
|
|
||||||
|
// },
|
||||||
|
// });
|
||||||
121
lms/lms/doctype/lms_batch_enrollment/lms_batch_enrollment.json
Normal file
121
lms/lms/doctype/lms_batch_enrollment/lms_batch_enrollment.json
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"creation": "2025-02-10 11:17:12.462368",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"member",
|
||||||
|
"member_name",
|
||||||
|
"member_username",
|
||||||
|
"column_break_sjzm",
|
||||||
|
"batch",
|
||||||
|
"payment",
|
||||||
|
"source",
|
||||||
|
"confirmation_email_sent"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "member",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Member",
|
||||||
|
"options": "User",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "member.full_name",
|
||||||
|
"fieldname": "member_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Member Name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "member.username",
|
||||||
|
"fieldname": "member_username",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Member Username"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "payment",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Payment",
|
||||||
|
"options": "LMS Payment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "source",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Source",
|
||||||
|
"options": "LMS Source"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "confirmation_email_sent",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Confirmation Email Sent"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_sjzm",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "batch",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Batch",
|
||||||
|
"options": "LMS Batch",
|
||||||
|
"reqd": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2025-02-10 16:06:48.720780",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "LMS",
|
||||||
|
"name": "LMS Batch Enrollment",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Moderator",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "LMS Student",
|
||||||
|
"share": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sort_field": "creation",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
|
}
|
||||||
99
lms/lms/doctype/lms_batch_enrollment/lms_batch_enrollment.py
Normal file
99
lms/lms/doctype/lms_batch_enrollment/lms_batch_enrollment.py
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# Copyright (c) 2025, Frappe and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.model.document import Document
|
||||||
|
from frappe.email.doctype.email_template.email_template import get_email_template
|
||||||
|
|
||||||
|
|
||||||
|
class LMSBatchEnrollment(Document):
|
||||||
|
|
||||||
|
def after_insert(self):
|
||||||
|
self.send_confirmation_email()
|
||||||
|
self.add_member_to_live_class()
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
self.validate_duplicate_members()
|
||||||
|
self.validate_course_enrollment()
|
||||||
|
|
||||||
|
def validate_duplicate_members(self):
|
||||||
|
if frappe.db.exists("LMS Batch Enrollment", {"batch": self.batch, "member": self.member}):
|
||||||
|
frappe.throw(_("Member already enrolled in this batch"))
|
||||||
|
|
||||||
|
def validate_course_enrollment(self):
|
||||||
|
courses = frappe.get_all(
|
||||||
|
"Batch Course", filters={"parent": self.batch}, fields=["course"]
|
||||||
|
)
|
||||||
|
|
||||||
|
for course in courses:
|
||||||
|
if not frappe.db.exists(
|
||||||
|
"LMS Enrollment",
|
||||||
|
{"course": course.course, "member": self.member},
|
||||||
|
):
|
||||||
|
enrollment = frappe.new_doc("LMS Enrollment")
|
||||||
|
enrollment.course = course.course
|
||||||
|
enrollment.member = self.member
|
||||||
|
enrollment.save()
|
||||||
|
|
||||||
|
def send_confirmation_email(self):
|
||||||
|
if not self.confirmation_email_sent:
|
||||||
|
outgoing_email_account = frappe.get_cached_value(
|
||||||
|
"Email Account", {"default_outgoing": 1, "enable_outgoing": 1}, "name"
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
not self.confirmation_email_sent
|
||||||
|
and (outgoing_email_account or frappe.conf.get("mail_login"))
|
||||||
|
):
|
||||||
|
self.send_mail()
|
||||||
|
self.confirmation_email_sent = 1
|
||||||
|
|
||||||
|
def send_mail(self):
|
||||||
|
subject = _("Enrollment Confirmation for the Next Training Batch")
|
||||||
|
template = "batch_confirmation"
|
||||||
|
custom_template = frappe.db.get_single_value(
|
||||||
|
"LMS Settings", "batch_confirmation_template"
|
||||||
|
)
|
||||||
|
batch = frappe.db.get_value("LMS Batch", self.batch, ["name", "title", "start_date", "start_time", "medium"], as_dict=1)
|
||||||
|
args = {
|
||||||
|
"title": batch.title,
|
||||||
|
"student_name": self.member_name,
|
||||||
|
"start_time": batch.start_time,
|
||||||
|
"start_date": batch.start_date,
|
||||||
|
"medium": batch.medium,
|
||||||
|
"name": batch.name,
|
||||||
|
}
|
||||||
|
|
||||||
|
if custom_template:
|
||||||
|
email_template = get_email_template(custom_template, args)
|
||||||
|
subject = email_template.get("subject")
|
||||||
|
content = email_template.get("message")
|
||||||
|
|
||||||
|
frappe.sendmail(
|
||||||
|
recipients=self.member,
|
||||||
|
subject=subject,
|
||||||
|
template=template if not custom_template else None,
|
||||||
|
content=content if custom_template else None,
|
||||||
|
args=args,
|
||||||
|
header=[subject, "green"],
|
||||||
|
retry=3,
|
||||||
|
)
|
||||||
|
|
||||||
|
def add_member_to_live_class(self):
|
||||||
|
live_classes = frappe.get_all(
|
||||||
|
"LMS Live Class", {"batch_name": self.batch}, ["name", "event"]
|
||||||
|
)
|
||||||
|
|
||||||
|
for live_class in live_classes:
|
||||||
|
if live_class.event:
|
||||||
|
frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Event Participants",
|
||||||
|
"reference_doctype": "User",
|
||||||
|
"reference_docname": self.member,
|
||||||
|
"email": self.member,
|
||||||
|
"parent": live_class.event,
|
||||||
|
"parenttype": "Event",
|
||||||
|
"parentfield": "event_participants",
|
||||||
|
}
|
||||||
|
).save()
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Copyright (c) 2025, Frappe and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.tests import IntegrationTestCase, UnitTestCase
|
||||||
|
|
||||||
|
|
||||||
|
# On IntegrationTestCase, the doctype test records and all
|
||||||
|
# link-field test record dependencies are recursively loaded
|
||||||
|
# Use these module variables to add/remove to/from that list
|
||||||
|
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||||
|
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
|
||||||
|
|
||||||
|
|
||||||
|
class UnitTestLMSBatchEnrollment(UnitTestCase):
|
||||||
|
"""
|
||||||
|
Unit tests for LMSBatchEnrollment.
|
||||||
|
Use this class for testing individual functions and methods.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class IntegrationTestLMSBatchEnrollment(IntegrationTestCase):
|
||||||
|
"""
|
||||||
|
Integration tests for LMSBatchEnrollment.
|
||||||
|
Use this class for testing interactions between multiple components.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
@@ -30,12 +30,11 @@ class LMSLiveClass(Document):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
event.save()
|
event.save()
|
||||||
|
|
||||||
return event
|
return event
|
||||||
|
|
||||||
def add_event_participants(self, event, calendar):
|
def add_event_participants(self, event, calendar):
|
||||||
participants = frappe.get_all(
|
participants = frappe.get_all(
|
||||||
"Batch Student", {"parent": self.batch_name}, pluck="student"
|
"LMS Batch Enrollment", {"batch": self.batch_name}, pluck="member"
|
||||||
)
|
)
|
||||||
|
|
||||||
participants.append(frappe.session.user)
|
participants.append(frappe.session.user)
|
||||||
|
|||||||
@@ -1226,9 +1226,10 @@ def get_batch_details(batch):
|
|||||||
batch_details.courses = frappe.get_all(
|
batch_details.courses = frappe.get_all(
|
||||||
"Batch Course", filters={"parent": batch}, fields=["course", "title", "evaluator"]
|
"Batch Course", filters={"parent": batch}, fields=["course", "title", "evaluator"]
|
||||||
)
|
)
|
||||||
batch_details.students = frappe.get_all(
|
batch_details.students = frappe.get_all("LMS Batch Enrollment", {
|
||||||
"Batch Student", {"parent": batch}, pluck="student"
|
"batch": batch
|
||||||
)
|
}, pluck='member')
|
||||||
|
|
||||||
if batch_details.paid_batch and batch_details.start_date >= getdate():
|
if batch_details.paid_batch and batch_details.start_date >= getdate():
|
||||||
batch_details.amount, batch_details.currency = check_multicurrency(
|
batch_details.amount, batch_details.currency = check_multicurrency(
|
||||||
batch_details.amount, batch_details.currency, None, batch_details.amount_usd
|
batch_details.amount, batch_details.currency, None, batch_details.amount_usd
|
||||||
@@ -1258,7 +1259,7 @@ def categorize_batches(batches):
|
|||||||
|
|
||||||
if frappe.session.user != "Guest":
|
if frappe.session.user != "Guest":
|
||||||
if frappe.db.exists(
|
if frappe.db.exists(
|
||||||
"Batch Student", {"student": frappe.session.user, "parent": batch.name}
|
"LMS Batch Enrollment", {"member": frappe.session.user, "batch": batch.name}
|
||||||
):
|
):
|
||||||
enrolled.append(batch)
|
enrolled.append(batch)
|
||||||
|
|
||||||
@@ -1406,7 +1407,7 @@ def get_quiz_details(assessment, member):
|
|||||||
def get_batch_students(batch):
|
def get_batch_students(batch):
|
||||||
students = []
|
students = []
|
||||||
students_list = frappe.get_all(
|
students_list = frappe.get_all(
|
||||||
"Batch Student", filters={"parent": batch}, fields=["student", "name"]
|
"LMS Batch Enrollment", filters={"batch": batch}, fields=["member", "name"]
|
||||||
)
|
)
|
||||||
|
|
||||||
batch_courses = frappe.get_all("Batch Course", {"parent": batch}, ["course", "title"])
|
batch_courses = frappe.get_all("Batch Course", {"parent": batch}, ["course", "title"])
|
||||||
@@ -1421,7 +1422,7 @@ def get_batch_students(batch):
|
|||||||
assessments_completed = 0
|
assessments_completed = 0
|
||||||
detail = frappe.db.get_value(
|
detail = frappe.db.get_value(
|
||||||
"User",
|
"User",
|
||||||
student.student,
|
student.member,
|
||||||
["full_name", "email", "username", "last_active", "user_image"],
|
["full_name", "email", "username", "last_active", "user_image"],
|
||||||
as_dict=True,
|
as_dict=True,
|
||||||
)
|
)
|
||||||
@@ -1715,19 +1716,18 @@ def enroll_in_course(payment_name, course):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def enroll_in_batch(batch, payment_name=None):
|
def enroll_in_batch(batch, payment_name=None):
|
||||||
if not frappe.db.exists(
|
if not frappe.db.exists(
|
||||||
"Batch Student", {"parent": batch, "student": frappe.session.user}
|
"LMS Batch Enrollment", {"batch": batch, "member": frappe.session.user}
|
||||||
):
|
):
|
||||||
batch_doc = frappe.get_doc("LMS Batch", batch)
|
batch_doc = frappe.db.get_value('LMS Batch', batch, ['name', 'seat_count'], as_dict=True)
|
||||||
if batch_doc.seat_count and len(batch_doc.students) >= batch_doc.seat_count:
|
students = frappe.db.count("LMS Batch Enrollment", {"batch": batch})
|
||||||
|
if batch_doc.seat_count and students >= batch_doc.seat_count:
|
||||||
frappe.throw(_("The batch is full. Please contact the Administrator."))
|
frappe.throw(_("The batch is full. Please contact the Administrator."))
|
||||||
|
|
||||||
new_student = {
|
new_student = frappe.new_doc("LMS Batch Enrollment")
|
||||||
"student": frappe.session.user,
|
new_student.update({
|
||||||
"parent": batch,
|
"member": frappe.session.user,
|
||||||
"parenttype": "LMS Batch",
|
"batch": batch,
|
||||||
"parentfield": "students",
|
})
|
||||||
"idx": len(batch_doc.students) + 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
if payment_name:
|
if payment_name:
|
||||||
payment = frappe.db.get_value(
|
payment = frappe.db.get_value(
|
||||||
@@ -1739,9 +1739,7 @@ def enroll_in_batch(batch, payment_name=None):
|
|||||||
"source": payment.source,
|
"source": payment.source,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
new_student.save()
|
||||||
batch_doc.append("students", new_student)
|
|
||||||
batch_doc.save(ignore_permissions=True)
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@@ -1839,7 +1837,7 @@ def get_batches(filters=None, start=0, page_length=20, order_by="start_date"):
|
|||||||
|
|
||||||
if filters.get("enrolled"):
|
if filters.get("enrolled"):
|
||||||
enrolled_batches = frappe.get_all(
|
enrolled_batches = frappe.get_all(
|
||||||
"Batch Student", {"student": frappe.session.user}, pluck="parent"
|
"LMS Batch Enrollment", {"member": frappe.session.user}, pluck="batch"
|
||||||
)
|
)
|
||||||
filters.update({"name": ["in", enrolled_batches]})
|
filters.update({"name": ["in", enrolled_batches]})
|
||||||
del filters["enrolled"]
|
del filters["enrolled"]
|
||||||
@@ -1911,7 +1909,7 @@ def get_batch_type(filters):
|
|||||||
def get_batch_card_details(batches):
|
def get_batch_card_details(batches):
|
||||||
for batch in batches:
|
for batch in batches:
|
||||||
batch.instructors = get_instructors(batch.name)
|
batch.instructors = get_instructors(batch.name)
|
||||||
students_count = frappe.db.count("Batch Student", {"parent": batch.name})
|
students_count = frappe.db.count("LMS Batch Enrollment", {"batch": batch.name})
|
||||||
|
|
||||||
if batch.seat_count:
|
if batch.seat_count:
|
||||||
batch.seats_left = batch.seat_count - students_count
|
batch.seats_left = batch.seat_count - students_count
|
||||||
|
|||||||
@@ -97,4 +97,5 @@ lms.patches.v2_0.delete_web_forms
|
|||||||
lms.patches.v2_0.update_desk_access_for_lms_roles
|
lms.patches.v2_0.update_desk_access_for_lms_roles
|
||||||
lms.patches.v2_0.update_quiz_submission_data
|
lms.patches.v2_0.update_quiz_submission_data
|
||||||
lms.patches.v2_0.convert_quiz_duration_to_minutes
|
lms.patches.v2_0.convert_quiz_duration_to_minutes
|
||||||
lms.patches.v2_0.allow_guest_access #05-02-2025
|
lms.patches.v2_0.allow_guest_access #05-02-2025
|
||||||
|
lms.patches.v2_0.migrate_batch_student_data
|
||||||
17
lms/patches/v2_0/migrate_batch_student_data.py
Normal file
17
lms/patches/v2_0/migrate_batch_student_data.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
students = frappe.get_all("Batch Student", fields=["student", "student_name", "username", "payment", "source", "parent", "confirmation_email_sent"])
|
||||||
|
|
||||||
|
for student in students:
|
||||||
|
doc = frappe.new_doc("LMS Batch Enrollment")
|
||||||
|
doc.member = student.student
|
||||||
|
doc.member_name = student.student_name
|
||||||
|
doc.member_username = student.username
|
||||||
|
doc.payment = student.payment
|
||||||
|
doc.source = student.source
|
||||||
|
doc.batch = student.parent
|
||||||
|
doc.confirmation_email_sent = student.confirmation_email_sent
|
||||||
|
doc.save()
|
||||||
|
|
||||||
|
frappe.delete_doc("DocType", "Batch Student")
|
||||||
Reference in New Issue
Block a user