Merge pull request #2182 from pateljannat/issues-207

feat: payment reminder setting
This commit is contained in:
Jannat Patel
2026-03-11 14:23:11 +05:30
committed by GitHub
6 changed files with 111 additions and 84 deletions
+27 -11
View File
@@ -21,10 +21,17 @@ describe("Course Creation", () => {
"Test Course Description. I need a very big description to test the UI. This is a very big description. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now."
);
cy.fixture("profile.png", "base64").then((fileContent) => {
cy.contains("Course Image")
.should("exist")
.parent()
.find('input[type="file"]')
.attachFile("profile.png", { force: true });
/* cy.fixture("profile.png", "base64").then((fileContent) => {
expect(fileContent).to.exist;
cy.get("div")
.contains("Course Image")
.siblings("div")
.parent()
.children('input[type="file"]')
.attachFile({
fileContent,
@@ -32,7 +39,7 @@ describe("Course Creation", () => {
mimeType: "image/png",
encoding: "base64",
});
});
}); */
/* Instructor */
cy.get("label")
@@ -74,10 +81,10 @@ describe("Course Creation", () => {
cy.button("Save").click();
// Add Chapter
cy.wait(1000);
cy.wait(500);
cy.button("Add").click();
cy.wait(1000);
cy.wait(500);
cy.get("[data-dismissable-layer]")
.should("be.visible")
.within(() => {
@@ -86,12 +93,10 @@ describe("Course Creation", () => {
});
// Add Lesson
cy.wait(1000);
cy.wait(500);
cy.button("Add Lesson").click();
cy.wait(1000);
cy.wait(500);
cy.url().should("include", "/learn/1-1/edit");
cy.wait(1000);
cy.get("label").contains("Title").type("Test Lesson");
cy.get("#content .ce-block").type(
"{enter}This is an extremely big paragraph that is meant to test the UI. This is a very long paragraph. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now."
@@ -99,7 +104,7 @@ describe("Course Creation", () => {
cy.button("Save").click();
// View Course
cy.wait(1000);
cy.wait(500);
cy.visit("/lms/courses");
cy.closeOnboardingModal();
@@ -133,7 +138,7 @@ describe("Course Creation", () => {
cy.get("[id^=headlessui-disclosure-panel-").within(() => {
cy.get("div").contains("Test Lesson").click();
});
cy.wait(3000);
cy.wait(500);
// View Lesson
cy.url().should("include", "/learn/1-1");
@@ -166,5 +171,16 @@ describe("Course Creation", () => {
cy.get("div").contains(
"This is a test comment. This will check if the UI is working properly."
);
// Delete Course
cy.get("div").contains("Test Course").click();
cy.get("button").contains("Settings").click();
cy.get("header").within(() => {
cy.get("svg.lucide.lucide-trash2-icon").click();
});
cy.get("span").contains("Delete").click();
cy.wait(500);
cy.url().should("include", "/lms/courses");
cy.get("div").contains("Test Course").should("not.exist");
});
});
+41 -8
View File
@@ -331,29 +331,62 @@ const tabsStructure = computed(() => {
doctype: 'Currency',
},
{
label: 'Payment Gateway',
name: 'payment_gateway',
type: 'Link',
doctype: 'Payment Gateway',
label: 'Show USD equivalent amount',
name: 'show_usd_equivalent',
type: 'checkbox',
description:
'If enabled, it shows the USD equivalent amount for all transactions based on the current exchange rate.',
},
{
label: 'Apply rounding on equivalent',
name: 'apply_rounding',
type: 'checkbox',
description:
'If enabled, it applies rounding on the USD equivalent amount.',
},
],
},
{
fields: [
{
label: 'Payment Gateway',
name: 'payment_gateway',
type: 'Link',
doctype: 'Payment Gateway',
},
{
label: 'Apply GST for India',
name: 'apply_gst',
type: 'checkbox',
description:
'If enabled, GST will be applied to the price for students from India.',
},
],
},
],
},
{
label: 'Payment Reminders',
columns: [
{
fields: [
{
label: 'Show USD equivalent amount',
name: 'show_usd_equivalent',
label: 'Send payment reminders for batch',
name: 'send_payment_reminders_for_batch',
type: 'checkbox',
description:
'If enabled, it sends payment reminders to students who left the payment incomplete for a batch.',
},
],
},
{
fields: [
{
label: 'Apply rounding on equivalent',
name: 'apply_rounding',
label: 'Send payment reminders for course',
name: 'send_payment_reminders_for_course',
type: 'checkbox',
description:
'If enabled, it sends payment reminders to students who left the payment incomplete for a course.',
},
],
},
+5 -61
View File
@@ -1275,11 +1275,6 @@
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
"@kurkle/color@^0.3.0":
version "0.3.4"
resolved "https://registry.yarnpkg.com/@kurkle/color/-/color-0.3.4.tgz#4d4ff677e1609214fc71c580125ddddd86abcabf"
integrity sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==
"@lezer/common@^1.0.0", "@lezer/common@^1.0.2", "@lezer/common@^1.1.0", "@lezer/common@^1.2.0", "@lezer/common@^1.2.1", "@lezer/common@^1.3.0", "@lezer/common@^1.5.0":
version "1.5.1"
resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.5.1.tgz#6e8c114ff5d36a41148e146a253734d3bb8807d3"
@@ -1574,33 +1569,6 @@
magic-string "^0.25.0"
string.prototype.matchall "^4.0.6"
"@svgdotjs/svg.draggable.js@^3.0.4":
version "3.0.6"
resolved "https://registry.yarnpkg.com/@svgdotjs/svg.draggable.js/-/svg.draggable.js-3.0.6.tgz#bca1065ec27b1dbae5a92a0558777ed964a395cb"
integrity sha512-7iJFm9lL3C40HQcqzEfezK2l+dW2CpoVY3b77KQGqc8GXWa6LhhmX5Ckv7alQfUXBuZbjpICZ+Dvq1czlGx7gA==
"@svgdotjs/svg.filter.js@^3.0.8":
version "3.0.9"
resolved "https://registry.yarnpkg.com/@svgdotjs/svg.filter.js/-/svg.filter.js-3.0.9.tgz#758e336b79e73a6797358d655b60842131a9a52b"
integrity sha512-/69XMRCDoam2HgC4ldHIaDgeQf1ViHIsa0Ld4uWgiXtZ+E24DWHe/9Ib6kbNiZ7WRIdlVokUDR1Fg0kjIpkfbw==
dependencies:
"@svgdotjs/svg.js" "^3.2.4"
"@svgdotjs/svg.js@^3.2.4":
version "3.2.5"
resolved "https://registry.yarnpkg.com/@svgdotjs/svg.js/-/svg.js-3.2.5.tgz#fbbc56728b2b565f3ae3e3713301ff82abbb45bd"
integrity sha512-/VNHWYhNu+BS7ktbYoVGrCmsXDh+chFMaONMwGNdIBcFHrWqk2jY8fNyr3DLdtQUIalvkPfM554ZSFa3dm3nxQ==
"@svgdotjs/svg.resize.js@^2.0.2":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@svgdotjs/svg.resize.js/-/svg.resize.js-2.0.5.tgz#732e4cae15d09ad3021adeac63bc9fad0dc7255a"
integrity sha512-4heRW4B1QrJeENfi7326lUPYBCevj78FJs8kfeDxn5st0IYPIRXoTtOSYvTzFWgaWWXd3YCDE6ao4fmv91RthA==
"@svgdotjs/svg.select.js@^4.0.1":
version "4.0.3"
resolved "https://registry.yarnpkg.com/@svgdotjs/svg.select.js/-/svg.select.js-4.0.3.tgz#6af12755fd71caf703825d4f490fdf02a001cbfc"
integrity sha512-qkMgso1sd2hXKd1FZ1weO7ANq12sNmQJeGDjs46QwDVsxSRcHmvWKL2NDF7Yimpwf3sl5esOLkPqtV2bQ3v/Jg==
"@swc/helpers@^0.5.0":
version "0.5.18"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.18.tgz#feeeabea0d10106ee25aaf900165df911ab6d3b1"
@@ -2105,11 +2073,6 @@
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-14.2.1.tgz#829a271147937f6b105bb1422d3171e6142f47ba"
integrity sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw==
"@yr/monotone-cubic-spline@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz#7272d89f8e4f6fb7a1600c28c378cc18d3b577b9"
integrity sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==
ace-builds@1.36.2:
version "1.36.2"
resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.36.2.tgz#9499bd59e839a335ac4850e74549ca8d849dc554"
@@ -2155,18 +2118,6 @@ anymatch@~3.1.2:
normalize-path "^3.0.0"
picomatch "^2.0.4"
apexcharts@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/apexcharts/-/apexcharts-4.3.0.tgz#eccf28e830ce1b5e018cfc0e99d1c6af0076c9c7"
integrity sha512-PfvZQpv91T68hzry9l5zP3Gip7sQvF0nFK91uCBrswIKX7rbIdbVNS4fOks9m9yP3Ppgs6LHgU2M/mjoG4NM0A==
dependencies:
"@svgdotjs/svg.draggable.js" "^3.0.4"
"@svgdotjs/svg.filter.js" "^3.0.8"
"@svgdotjs/svg.js" "^3.2.4"
"@svgdotjs/svg.resize.js" "^2.0.2"
"@svgdotjs/svg.select.js" "^4.0.1"
"@yr/monotone-cubic-spline" "^1.0.3"
arg@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
@@ -2374,13 +2325,6 @@ chalk@^4.1.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chart.js@4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.4.1.tgz#ac5dc0e69a7758909158a96fe80ce43b3bb96a9f"
integrity sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==
dependencies:
"@kurkle/color" "^0.3.0"
chokidar@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
@@ -2962,10 +2906,10 @@ fraction.js@^4.1.2:
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
frappe-ui@^0.1.261:
version "0.1.262"
resolved "https://registry.yarnpkg.com/frappe-ui/-/frappe-ui-0.1.262.tgz#b88416aac76fdce183f95f2ac935ce65ffb2b2eb"
integrity sha512-KKH7LLLa3yvfM3QeLaiaSqeSS+BUdCu3+8BrvXAG09ejGU1Z6k0wXEG314J0yXxK4rLifd83zpKbtUCG9zIKFA==
frappe-ui@^0.1.264:
version "0.1.265"
resolved "https://registry.yarnpkg.com/frappe-ui/-/frappe-ui-0.1.265.tgz#3aee2dd5593fb36f9f2d7eeb3c92246abaa2a974"
integrity sha512-N/4LXMcFAzoTfMWqap9e2rxxMKShVWnX63+Q+48CBbt2sfjeqR/4P7HRjXi7DUCEMfRt4xkv/1eIuBdNAuIT1A==
dependencies:
"@floating-ui/dom" "^1.7.4"
"@floating-ui/vue" "^1.1.6"
@@ -4324,7 +4268,7 @@ regjsparser@^0.13.0:
dependencies:
jsesc "~3.1.0"
reka-ui@^2.5.0, reka-ui@^2.8.0:
reka-ui@^2.5.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/reka-ui/-/reka-ui-2.8.0.tgz#612023ad40c5c10999aef304f2b828cdd08da6a8"
integrity sha512-N4JOyIrmDE7w2i06WytqcV2QICubtS2PsK5Uo8FIMAgmO13KhUAgAByP26cXjjm2oF/w7rTyRs8YaqtvaBT+SA==
+3 -1
View File
@@ -885,8 +885,10 @@ def delete_course(course: str):
frappe.db.delete("LMS Enrollment", {"course": course})
frappe.db.delete("LMS Course Progress", {"course": course})
frappe.db.delete("LMS Certificate", {"course": course})
frappe.db.delete("Batch Course", {"course": course})
frappe.db.delete("LMS Course Review", {"course": course})
frappe.db.set_value("LMS Quiz", {"course": course}, "course", None)
frappe.db.set_value("LMS Quiz", {"course": course}, {"course": None, "lesson": None})
frappe.db.set_value("LMS Quiz Submission", {"course": course}, "course", None)
chapters = frappe.get_all("Course Chapter", {"course": course}, pluck="name")
+19 -1
View File
@@ -24,7 +24,11 @@ def send_payment_reminder():
incomplete_payments = frappe.get_all(
"LMS Payment",
{"payment_received": 0, "creation": [">", add_days(nowdate(), -1)]},
{
"payment_received": 0,
"creation": [">", add_days(nowdate(), -1)],
"payment_for_document_type": ["in", allowed_payment_types()],
},
[
"name",
"member",
@@ -44,6 +48,20 @@ def send_payment_reminder():
send_mail(payment)
def allowed_payment_types():
send_batch_reminders = frappe.db.get_single_value("LMS Settings", "send_payment_reminders_for_batch")
send_course_reminders = frappe.db.get_single_value("LMS Settings", "send_payment_reminders_for_course")
allowed_types = []
if send_batch_reminders:
allowed_types.append("LMS Batch")
if send_course_reminders:
allowed_types.append("LMS Course")
return allowed_types
def has_paid_later(payment):
return frappe.db.exists(
"LMS Payment",
+16 -2
View File
@@ -62,6 +62,8 @@
"apply_gst",
"show_usd_equivalent",
"apply_rounding",
"send_payment_reminders_for_batch",
"send_payment_reminders_for_course",
"no_payments_app",
"payments_app_is_not_installed",
"email_templates_tab",
@@ -492,14 +494,26 @@
"fieldtype": "Check",
"label": "Demo Data Present",
"read_only": 1
},
{
"default": "0",
"fieldname": "send_payment_reminders_for_batch",
"fieldtype": "Check",
"label": "Send Payment Reminders for Batch"
},
{
"default": "0",
"fieldname": "send_payment_reminders_for_course",
"fieldtype": "Check",
"label": "Send Payment Reminders for Course"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2026-03-05 13:57:56.303744",
"modified_by": "Administrator",
"modified": "2026-03-10 18:18:51.733955",
"modified_by": "sayali@frappe.io",
"module": "LMS",
"name": "LMS Settings",
"owner": "Administrator",