feat: validate razorpay data
This commit is contained in:
@@ -9,6 +9,8 @@ from frappe.utils import cint
|
|||||||
from frappe.utils.telemetry import capture
|
from frappe.utils.telemetry import capture
|
||||||
from lms.lms.utils import get_chapters, can_create_courses
|
from lms.lms.utils import get_chapters, can_create_courses
|
||||||
from ...utils import generate_slug, validate_image
|
from ...utils import generate_slug, validate_image
|
||||||
|
from frappe import _
|
||||||
|
import razorpay
|
||||||
|
|
||||||
|
|
||||||
class LMSCourse(Document):
|
class LMSCourse(Document):
|
||||||
@@ -354,3 +356,44 @@ def reorder_chapter(chapter_array):
|
|||||||
"idx": chapter_array.index(chap) + 1,
|
"idx": chapter_array.index(chap) + 1,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def buy_course(course):
|
||||||
|
razorpay_key = frappe.get_single_value("LMS Settings", "razorpay_key")
|
||||||
|
razorpay_secret = frappe.get_single_value("LMS Settings", "razorpay_secret")
|
||||||
|
|
||||||
|
if not razorpay_key and not razorpay_secret:
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"There is a problem with the payment gateway. Please contact the Administrator to proceed."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
create_payment_link(razorpay_key, razorpay_secret, course)
|
||||||
|
|
||||||
|
|
||||||
|
def create_payment_link(razorpy_key, razorpay_secret, course):
|
||||||
|
client = razorpay.Client(auth=(razorpy_key, razorpay_secret))
|
||||||
|
|
||||||
|
course_details = frappe.db.get_value(
|
||||||
|
"LMS Course", course, ["title", "price_course", "currency"], as_dict=True
|
||||||
|
)
|
||||||
|
user_details = frappe.db.get_value(
|
||||||
|
"User", frappe.session.user, ["full_name", "email"], as_dict=True
|
||||||
|
)
|
||||||
|
|
||||||
|
client.payment_link.create(
|
||||||
|
{
|
||||||
|
"amount": course_details.price_course,
|
||||||
|
"currency": course_details.currency,
|
||||||
|
"description": "Complete your course purchase",
|
||||||
|
"customer": {
|
||||||
|
"name": user_details.full_name,
|
||||||
|
"email": user_details.email,
|
||||||
|
},
|
||||||
|
"notify": {"sms": True, "email": True},
|
||||||
|
"callback_url": "/api/method/lms.lms.doctype.lms_course.lms_course.verify_payment",
|
||||||
|
"callback_method": "get",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|||||||
@@ -19,8 +19,10 @@
|
|||||||
"column_break_2",
|
"column_break_2",
|
||||||
"allow_student_progress",
|
"allow_student_progress",
|
||||||
"payment_section",
|
"payment_section",
|
||||||
|
"razorpay_key",
|
||||||
"default_currency",
|
"default_currency",
|
||||||
"column_break_cfcv",
|
"column_break_cfcv",
|
||||||
|
"razorpay_secret",
|
||||||
"signup_settings_tab",
|
"signup_settings_tab",
|
||||||
"signup_settings_section",
|
"signup_settings_section",
|
||||||
"terms_of_use",
|
"terms_of_use",
|
||||||
@@ -211,12 +213,22 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "column_break_iqxy",
|
"fieldname": "column_break_iqxy",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "razorpay_key",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Razorpay Key"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "razorpay_secret",
|
||||||
|
"fieldtype": "Password",
|
||||||
|
"label": "Razorpay Secret"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-08-02 12:30:50.897156",
|
"modified": "2023-08-02 18:59:01.267732",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Settings",
|
"name": "LMS Settings",
|
||||||
|
|||||||
@@ -222,9 +222,9 @@
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
{% elif course.paid_course %}
|
{% elif course.paid_course %}
|
||||||
<a class="btn btn-primary wide-button" id="buy-course">
|
<div class="btn btn-primary wide-button" id="buy-course" data-course="{{ course.name | urlencode }}">
|
||||||
{{ _("Buy This Course") }}
|
{{ _("Buy This Course") }}
|
||||||
</a>
|
</div>
|
||||||
|
|
||||||
{% elif show_start_learing_cta(course, membership) %}
|
{% elif show_start_learing_cta(course, membership) %}
|
||||||
<div class="btn btn-primary wide-button enroll-in-course" data-course="{{ course.name | urlencode }}">
|
<div class="btn btn-primary wide-button enroll-in-course" data-course="{{ course.name | urlencode }}">
|
||||||
|
|||||||
@@ -21,24 +21,17 @@ frappe.ready(() => {
|
|||||||
submit_for_review(e);
|
submit_for_review(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#apply-certificate").click((e) => {
|
$("#buy-course").click((e) => {
|
||||||
apply_cetificate(e);
|
e.preventDefault();
|
||||||
});
|
frappe.call({
|
||||||
|
method: "lms.lms.doctype.lms_course.lms_course.buy_course",
|
||||||
$("#slot-date").on("change", (e) => {
|
args: {
|
||||||
display_slots(e);
|
course: decodeURIComponent(
|
||||||
});
|
$(e.currentTarget).attr("data-course")
|
||||||
|
),
|
||||||
$("#submit-slot").click((e) => {
|
},
|
||||||
submit_slot(e);
|
callback: (data) => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".close-slot-modal").click((e) => {
|
|
||||||
close_slot_modal(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on("click", ".slot", (e) => {
|
|
||||||
select_slot(e);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -162,99 +155,3 @@ const submit_for_review = (e) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const apply_cetificate = (e) => {
|
|
||||||
$("#slot-modal").modal("show");
|
|
||||||
};
|
|
||||||
|
|
||||||
const submit_slot = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
const slot = window.selected_slot;
|
|
||||||
frappe.call({
|
|
||||||
method: "lms.lms.doctype.lms_certificate_request.lms_certificate_request.create_certificate_request",
|
|
||||||
args: {
|
|
||||||
course: slot.data("course"),
|
|
||||||
date: $("#slot-date").val(),
|
|
||||||
day: slot.data("day"),
|
|
||||||
start_time: slot.data("start"),
|
|
||||||
end_time: slot.data("end"),
|
|
||||||
},
|
|
||||||
callback: (data) => {
|
|
||||||
$("#slot-modal").modal("hide");
|
|
||||||
frappe.show_alert(
|
|
||||||
{
|
|
||||||
message: __(
|
|
||||||
"Your slot has been booked. Prepare well for the evaluations."
|
|
||||||
),
|
|
||||||
indicator: "green",
|
|
||||||
},
|
|
||||||
3
|
|
||||||
);
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.reload();
|
|
||||||
}, 3000);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const display_slots = (e) => {
|
|
||||||
frappe.call({
|
|
||||||
method: "lms.lms.doctype.course_evaluator.course_evaluator.get_schedule",
|
|
||||||
args: {
|
|
||||||
course: $(e.currentTarget).data("course"),
|
|
||||||
date: $(e.currentTarget).val(),
|
|
||||||
},
|
|
||||||
callback: (data) => {
|
|
||||||
let options = "";
|
|
||||||
data.message.forEach((obj) => {
|
|
||||||
options += `<button type="button" class="btn btn-sm btn-secondary mb-3 mr-3 slot hide"
|
|
||||||
data-course="${$(e.currentTarget).data("course")}"
|
|
||||||
data-day="${obj.day}" data-start="${
|
|
||||||
obj.start_time
|
|
||||||
}" data-end="${obj.end_time}">
|
|
||||||
${format_time(obj.start_time)} - ${format_time(
|
|
||||||
obj.end_time
|
|
||||||
)}</button>`;
|
|
||||||
});
|
|
||||||
e.preventDefault();
|
|
||||||
$("#slot-modal .slots").html(options);
|
|
||||||
const weekday = [
|
|
||||||
"Sunday",
|
|
||||||
"Monday",
|
|
||||||
"Tuesday",
|
|
||||||
"Wednesday",
|
|
||||||
"Thursday",
|
|
||||||
"Friday",
|
|
||||||
"Saturday",
|
|
||||||
];
|
|
||||||
const day = weekday[new Date($(e.currentTarget).val()).getDay()];
|
|
||||||
|
|
||||||
$(".slot").addClass("hide");
|
|
||||||
$(".slot-label").addClass("hide");
|
|
||||||
|
|
||||||
if ($(`[data-day='${day}']`).length) {
|
|
||||||
$(".slot-label").removeClass("hide");
|
|
||||||
$(`[data-day='${day}']`).removeClass("hide");
|
|
||||||
$("#no-slots-message").addClass("hide");
|
|
||||||
} else {
|
|
||||||
$("#no-slots-message").removeClass("hide");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const select_slot = (e) => {
|
|
||||||
$(".slot").removeClass("btn-outline-primary");
|
|
||||||
$(e.currentTarget).addClass("btn-outline-primary");
|
|
||||||
window.selected_slot = $(e.currentTarget);
|
|
||||||
};
|
|
||||||
|
|
||||||
const format_time = (time) => {
|
|
||||||
let date = moment(new Date()).format("ddd MMM DD YYYY");
|
|
||||||
return moment(`${date} ${time}`).format("HH:mm a");
|
|
||||||
};
|
|
||||||
|
|
||||||
const close_slot_modal = (e) => {
|
|
||||||
$("#slot-date").val("");
|
|
||||||
$(".slot-label").addClass("hide");
|
|
||||||
};
|
|
||||||
|
|||||||
Reference in New Issue
Block a user