mirror of
https://github.com/frappe/lms.git
synced 2026-05-02 13:39:31 +03:00
Merge pull request #2182 from pateljannat/issues-207
feat: payment reminder setting
This commit is contained in:
@@ -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");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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
@@ -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
@@ -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")
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user