fix: notification on quiz update and mention

This commit is contained in:
Jannat Patel
2026-01-07 14:28:56 +05:30
parent ea94813d94
commit 45e98b9ddc
12 changed files with 384 additions and 152 deletions

View File

@@ -1238,25 +1238,51 @@ def get_notifications(filters):
notifications = frappe.get_all(
"Notification Log",
filters,
["subject", "from_user", "link", "read", "name", "creation", "document_type", "document_name"],
[
"subject",
"from_user",
"link",
"read",
"name",
"creation",
"document_type",
"document_name",
"type",
"email_content",
],
order_by="creation desc",
)
for notification in notifications:
notification = update_user_details(notification)
notification = update_document_details(notification)
notification = update_user_details(notification)
return notifications
def update_user_details(notification):
from_user_details = frappe.db.get_value(
"User", notification.from_user, ["full_name", "user_image"], as_dict=1
)
notification.update(from_user_details)
if (
notification.document_details
and len(notification.document_details.get("instructors", []))
and not is_mention(notification)
):
from_user_details = notification.document_details["instructors"][0]
else:
from_user_details = frappe.db.get_value(
"User", notification.from_user, ["full_name", "user_image"], as_dict=1
)
notification["from_user_details"] = from_user_details
return notification
def is_mention(notification):
if notification.type == "Mention":
return True
if "mentioned you" in notification.subject.lower():
return True
return False
def update_document_details(notification):
if notification.document_type == "LMS Course":
details = frappe.db.get_value(
@@ -1265,6 +1291,25 @@ def update_document_details(notification):
instructors = get_instructors("LMS Course", notification.document_name)
details["instructors"] = instructors
notification["document_details"] = details
elif notification.document_type == "LMS Batch":
details = frappe.db.get_value(
"LMS Batch",
notification.document_name,
[
"title",
"description as short_introduction",
"video_link",
"start_date",
"end_date",
"start_time",
"timezone",
],
as_dict=1,
)
instructors = get_instructors("LMS Batch", notification.document_name)
details["instructors"] = instructors
notification["document_details"] = details
return notification

View File

@@ -26,6 +26,7 @@
"description",
"column_break_hlqw",
"instructors",
"video_link",
"zoom_account",
"section_break_rgfj",
"medium",
@@ -361,6 +362,11 @@
"fieldtype": "Link",
"label": "Zoom Account",
"options": "LMS Zoom Settings"
},
{
"fieldname": "video_link",
"fieldtype": "Attach",
"label": "Preview Video"
}
],
"grid_page_length": 50,
@@ -383,7 +389,7 @@
"link_fieldname": "payment_for_document"
}
],
"modified": "2025-12-23 11:27:00.424331",
"modified": "2026-01-06 18:54:22.216656",
"modified_by": "sayali@frappe.io",
"module": "LMS",
"name": "LMS Batch",

View File

@@ -8,12 +8,14 @@ from datetime import timedelta
import frappe
import requests
from frappe import _
from frappe.desk.doctype.notification_log.notification_log import make_notification_logs
from frappe.model.document import Document
from frappe.utils import add_days, cint, format_datetime, get_time, nowdate
from lms.lms.utils import (
generate_slug,
get_assignment_details,
get_instructors,
get_lesson_index,
get_lesson_url,
get_quiz_details,
@@ -33,6 +35,10 @@ class LMSBatch(Document):
self.validate_timetable()
self.validate_evaluation_end_date()
def on_update(self):
if self.has_value_changed("published") and self.published:
frappe.enqueue(send_notification_for_published_batch, batch=self, now=True)
def autoname(self):
if not self.name:
self.name = generate_slug(self.title, "LMS Batch")
@@ -123,6 +129,80 @@ class LMSBatch(Document):
update_payment_record("LMS Batch", self.name)
def send_notification_for_published_batch(batch):
send_notification = frappe.db.get_single_value("LMS Settings", "send_notification_for_published_batches")
if not send_notification:
return
if not batch.published:
return
if send_notification == "Email":
send_email_notification_for_published_batch(batch)
else:
send_system_notification_for_published_batch(batch)
def send_email_notification_for_published_batch(batch):
brand_name = frappe.db.get_single_value("Website Settings", "app_name")
brand_logo = frappe.db.get_single_value("Website Settings", "banner_image")
subject = _("A new course has been published on {0}").format(brand_name)
template = "published_batch_notification"
students = frappe.get_all("User", {"enabled": 1}, pluck="name")
instructors = get_instructors("LMS Batch", batch.name)
args = {
"brand_logo": brand_logo,
"brand_name": brand_name,
"title": batch.title,
"short_introduction": batch.description,
"start_date": batch.start_date,
"end_date": batch.end_date,
"start_time": batch.start_time,
"medium": batch.medium,
"timezone": batch.timezone,
"instructors": instructors,
"batch_url": f"{frappe.utils.get_url()}/lms/batches/details/{batch.name}",
}
frappe.sendmail(
recipients=instructors,
bcc=students,
subject=subject,
template=template,
args=args,
)
""" frappe.sendmail(
recipients=["jannat@frappe.io"],
subject=subject,
template=template,
args=args,
) """
def send_system_notification_for_published_batch(batch):
students = frappe.get_all("User", {"enabled": 1}, pluck="name")
instructors = frappe.get_all("Course Instructor", {"parent": batch.name}, pluck="instructor")
instructor_name = frappe.db.get_value("User", instructors[0], "full_name")
notification = frappe._dict(
{
"subject": _("{0} has published a new batch {1}").format(
frappe.bold(instructor_name), frappe.bold(batch.title)
),
"email_content": _(
"A new batch '{0}' has been published that might interest you. Check it out!"
).format(batch.title),
"document_type": "LMS Batch",
"document_name": batch.name,
"from_user": instructors[0] if instructors else None,
"type": "Alert",
"link": f"/lms/batches/details/{batch.name}",
}
)
make_notification_logs(notification, students)
@frappe.whitelist()
def create_live_class(
batch_name,

View File

@@ -134,10 +134,8 @@ class LMSCourse(Document):
def send_notification_for_published_courses():
send_notification_for_published_courses = frappe.db.get_single_value(
"LMS Settings", "send_notification_for_published_courses"
)
if not send_notification_for_published_courses:
send_notification = frappe.db.get_single_value("LMS Settings", "send_notification_for_published_courses")
if not send_notification:
return
courses_published_today = frappe.get_all(
@@ -145,13 +143,13 @@ def send_notification_for_published_courses():
{
"published_on": today(),
},
["name", "title", "video_link", "short_introduction"],
["name", "title", "short_introduction"],
)
if not courses_published_today:
return
if send_notification_for_published_courses == "Email":
if send_notification == "Email":
send_email_notification_for_published_courses(courses_published_today)
else:
send_system_notification_for_published_courses(courses_published_today)
@@ -170,7 +168,6 @@ def send_email_notification_for_published_courses(courses):
args = {
"brand_logo": brand_logo,
"brand_name": brand_name,
"preview_video": f"https://www.youtube.com/embed/{course.video_link}",
"title": course.title,
"short_introduction": course.short_introduction,
"instructors": instructors,

View File

@@ -54,15 +54,15 @@ class LMSQuizSubmission(Document):
notification = frappe._dict(
{
"subject": _("You have got a score of {0} for the quiz {1}").format(
self.score, self.quiz_title
(frappe.bold(self.score)), frappe.bold(self.quiz_title)
),
"email_content": _(
"There has been an update on your submission. You have got a score of {0} for the quiz {1}"
).format(self.score, self.quiz_title),
).format(frappe.bold(self.score), frappe.bold(self.quiz_title)),
"document_type": self.doctype,
"document_name": self.name,
"for_user": self.member,
"from_user": "Administrator",
"from_user": frappe.session.user,
"type": "Alert",
"link": "",
}

View File

@@ -444,12 +444,16 @@ def notify_mentions_on_portal(doc, topic):
if topic.reference_doctype == "Course Lesson":
course = frappe.db.get_value("Course Lesson", topic.reference_docname, "course")
subject = _("{0} mentioned you in a comment in {1}").format(from_user_name, topic.title)
subject = _("{0} mentioned you in a comment in {1}").format(
frappe.bold(from_user_name), frappe.bold(topic.title)
)
link = get_lesson_url(course, get_lesson_index(topic.reference_docname))
else:
batch_title = frappe.db.get_value("LMS Batch", topic.reference_docname, "title")
subject = _("{0} mentioned you in a comment in {1}").format(from_user_name, batch_title)
link = f"/batches/{topic.reference_docname}"
subject = _("{0} mentioned you in a comment in {1}").format(
frappe.bold(from_user_name), frappe.bold(batch_title)
)
link = f"/lms/batches/{topic.reference_docname}"
for user in mentions:
notification = frappe._dict(
@@ -460,7 +464,7 @@ def notify_mentions_on_portal(doc, topic):
"document_name": topic.reference_docname,
"for_user": user,
"from_user": doc.owner,
"type": "Alert",
"type": "Mention",
"link": link,
}
)

View File

@@ -0,0 +1,54 @@
<div style="width: 70%; margin: 0 auto;">
<img src="{{ brand_logo }}" style="width: 30px; height: 30px;" />
<p style="font-size: 16px; font-weight: 600;">
{{ _("Hello Learner") }},
</p>
<p>
{{ _("A new batch has been published on ")}} {{ brand_name }} {{ _("that might interest you!") }} {{ _("Here are the details:") }}
</p>
<div style="background-color: #F8F8F8; border-radius: 12px; padding: 12px; margin-bottom: 6px;">
<div style="font-weight: 600; margin-bottom: 6px; font-size: 15px;">
{{ title }}
</div>
<div>
{{ short_introduction }}
</div>
<div style="margin-top: 20px; font-size: 13px;">
{% if end_date %}
<span>
{{ _("From ") }} {{ frappe.utils.format_date(start_date, "dd MMM YYYY") }} {{ _(" to ") }} {{ frappe.utils.format_date(end_date, "dd MMM YYYY") }}
</span>
{% else %}
<span>
{{ frappe.utils.format_date(start_date, "dd MMM YYYY") }}
</span>
{% endif %}
</div>
<div style="color: #525252; margin-top: 4px; font-size: 13px;">
<span>
{{ _("Time: ") }} {{ frappe.utils.format_time(start_time, "HH:mm a") }} {{ timezone }}
</span>
</div>
<div style="margin-top: 20px;">
{% for instructor in instructors %}
<div style="display: flex; align-items: center; margin-bottom: 5px;">
{% if instructor.user_image %}
<img src="{{ instructor.user_image }}" style="width: 20px; height: 20px; border-radius: 50%; margin-right: 5px;" />
{% else %}
<div style="width: 20px; height: 20px; border-radius: 50%; background-color: #ccc; display: flex; align-items: center; justify-content: center; margin-right: 5px;">
<span style="font-size: 12px; color: #fff;">
{{ instructor.full_name.split("")[0] | upper }}
</span>
</div>
{% endif %}
<div>
{{ instructor.full_name }}
</div>
</div>
{% endfor %}
</div>
</div>
<a href="{{ batch_url }}" style="display: inline-block; padding: 4px 8px; background-color: #171717; color: #fff; text-decoration: none; cursor: pointer; border-radius: 8px; margin-top: 10px;">
{{ _("Checkout the batch") }}
</a>
</div>