feat: email notifications for published courses

This commit is contained in:
Jannat Patel
2026-01-05 18:18:56 +05:30
parent e21f0e3a7f
commit b2b1d2bb00
7 changed files with 7138 additions and 31 deletions

View File

@@ -132,6 +132,7 @@ scheduler_events = {
"lms.lms.doctype.lms_payment.lms_payment.send_payment_reminder",
"lms.lms.doctype.lms_batch.lms_batch.send_batch_start_reminder",
"lms.lms.doctype.lms_live_class.lms_live_class.send_live_class_reminder",
"lms.lms.doctype.lms_course.lms_course.send_notification_for_published_courses",
],
}

View File

@@ -1,14 +1,12 @@
# Copyright (c) 2021, Frappe and contributors
# For license information, please see license.txt
import json
import random
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import cint, today
from frappe.desk.doctype.notification_log.notification_log import make_notification_logs
from ...utils import generate_slug, update_payment_record, validate_image
@@ -131,3 +129,67 @@ class LMSCourse(Document):
def __repr__(self):
return f"<Course#{self.name}>"
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:
return
courses_published_today = frappe.get_all("LMS Course", {
"published_on": today(),
}, ["name", "title", "video_link", "short_introduction"])
if not courses_published_today:
return
if send_notification_for_published_courses == "Email":
send_email_notification_for_published_courses(courses_published_today)
else:
send_system_notification_for_published_courses(courses_published_today)
def send_email_notification_for_published_courses(courses):
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_course_notification"
students = frappe.get_all("User", { "enabled": 1 }, pluck="name")
for course in courses:
instructor_details = []
instructors = frappe.get_all("Course Instructor", { "parent": course.name }, pluck="instructor")
for instructor in instructors:
details = frappe.db.get_value("User", instructor, ["full_name", "email", "user_image"], as_dict=True)
instructor_details.append(details)
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": instructor_details,
"course_url": f"{frappe.utils.get_url()}/lms/courses/{course.name}",
}
frappe.sendmail(
recipients=instructors,
bcc=students,
subject=subject,
template=template,
args=args,
)
def send_system_notification_for_published_courses(courses):
for course in courses:
students = frappe.get_all("User", { "enabled": 1 }, pluck="name")
instructors = frappe.get_all("Course Instructor", { "parent": course.name }, pluck="instructor")
notification = frappe._dict({
"subject": course.title,
"email_content": _("A new course '{0}' has been published that might interest you. Check it out!").format(course.title),
"document_type": "LMS Course",
"document_name": course.name,
"from_user": instructors[0] if instructors else None,
"type": "Alert",
"link": f"/lms/courses/{course.name}",
})
make_notification_logs(notification, ["ash@ipp.com"])

View File

@@ -0,0 +1,38 @@
<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 course 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;">
{{ title }}
</div>
<div>
{{ short_introduction }}
</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="{{ course_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 course") }}
</a>
</div>