feat: payment verification and membership
This commit is contained in:
75
lms/www/billing/billing.html
Normal file
75
lms/www/billing/billing.html
Normal file
@@ -0,0 +1,75 @@
|
||||
{% extends "lms/templates/lms_base.html" %}
|
||||
{% block title %}
|
||||
{{ course.title if course.title else _("New Course") }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block page_content %}
|
||||
<div class="common-page-style">
|
||||
<div class="container form-width common-card-style column-card px-0 h-0 mt-8">
|
||||
{{ Header() }}
|
||||
{{ CourseDetails() }}
|
||||
{{ BillingDetails() }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% macro Header() %}
|
||||
<div class="px-4">
|
||||
<div class="page-title">
|
||||
{{ _("Order Details") }}
|
||||
</div>
|
||||
<div>
|
||||
{{ _("Enter the billing information and complete the payment to purchase this course.") }}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro CourseDetails() %}
|
||||
<div class="px-4 pt-10 pb-8 border-bottom">
|
||||
<div class="flex justify-between">
|
||||
<div class="">
|
||||
{{ _("Course:") }}
|
||||
</div>
|
||||
<div class="field-label">
|
||||
{{ course.title }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-divider my-2"></div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<div class="">
|
||||
{{ _("Total Price:") }}
|
||||
</div>
|
||||
<div class="field-label">
|
||||
<!-- $ 50k -->
|
||||
{{ frappe.utils.fmt_money(course.course_price, 2, course.currency) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro BillingDetails() %}
|
||||
<div class="mt-8 px-4">
|
||||
<div class="bold-heading mb-4">
|
||||
{{ _("Billing Details") }}
|
||||
</div>
|
||||
<div id="billing-form"></div>
|
||||
<button class="btn btn-primary btn-md btn-pay" data-course="{{ course.name | urlencode }}">
|
||||
{{ "Proceed to Payment" }}
|
||||
</button>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{%- block script %}
|
||||
{{ super() }}
|
||||
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
|
||||
<script>
|
||||
frappe.boot.user = {
|
||||
"can_create": [],
|
||||
"can_select": ["Country"],
|
||||
"can_read": ["Country"]
|
||||
};
|
||||
</script>
|
||||
{% endblock %}
|
||||
105
lms/www/billing/billing.js
Normal file
105
lms/www/billing/billing.js
Normal file
@@ -0,0 +1,105 @@
|
||||
frappe.ready(() => {
|
||||
if ($("#billing-form").length) {
|
||||
setup_billing();
|
||||
}
|
||||
|
||||
$(".btn-pay").click((e) => {
|
||||
generate_payment_link(e);
|
||||
});
|
||||
});
|
||||
|
||||
const setup_billing = () => {
|
||||
this.billing = new frappe.ui.FieldGroup({
|
||||
fields: [
|
||||
{
|
||||
fieldtype: "Data",
|
||||
label: __("Address Line 1"),
|
||||
fieldname: "address_line1",
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldtype: "Data",
|
||||
label: __("Address Line 2"),
|
||||
fieldname: "address_line2",
|
||||
},
|
||||
{
|
||||
fieldtype: "Data",
|
||||
label: __("City/Town"),
|
||||
fieldname: "city",
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldtype: "Data",
|
||||
label: __("State/Province"),
|
||||
fieldname: "state",
|
||||
},
|
||||
{
|
||||
fieldtype: "Column Break",
|
||||
},
|
||||
{
|
||||
fieldtype: "Link",
|
||||
label: __("Country"),
|
||||
fieldname: "country",
|
||||
options: "Country",
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldtype: "Data",
|
||||
label: __("Postal Code"),
|
||||
fieldname: "pincode",
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldtype: "Data",
|
||||
label: __("Phone Number"),
|
||||
fieldname: "phone",
|
||||
reqd: 1,
|
||||
},
|
||||
],
|
||||
body: $("#billing-form").get(0),
|
||||
});
|
||||
this.billing.make();
|
||||
$("#billing-form .form-section:last").removeClass("empty-section");
|
||||
$("#billing-form .frappe-control").removeClass("hide-control");
|
||||
$("#billing-form .form-column").addClass("p-0");
|
||||
};
|
||||
|
||||
const generate_payment_link = (e) => {
|
||||
address = this.billing.get_values();
|
||||
let course = decodeURIComponent($(e.currentTarget).attr("data-course"));
|
||||
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_course.lms_course.get_payment_options",
|
||||
args: {
|
||||
course: course,
|
||||
phone: address.phone,
|
||||
},
|
||||
callback: (data) => {
|
||||
data.message.handler = (response) => {
|
||||
handle_success(
|
||||
response,
|
||||
course,
|
||||
address,
|
||||
data.message.order_id
|
||||
);
|
||||
};
|
||||
let rzp1 = new Razorpay(data.message);
|
||||
rzp1.open();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handle_success = (response, course, address, order_id) => {
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_course.lms_course.verify_payment",
|
||||
args: {
|
||||
response: response,
|
||||
course: course,
|
||||
address: address,
|
||||
order_id: order_id,
|
||||
},
|
||||
callback: (data) => {
|
||||
window.location.href = data.message;
|
||||
},
|
||||
});
|
||||
};
|
||||
23
lms/www/billing/billing.py
Normal file
23
lms/www/billing/billing.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_context(context):
|
||||
course_name = frappe.form_dict.course
|
||||
|
||||
if not course_name:
|
||||
raise ValueError(_("Course is required."))
|
||||
|
||||
if frappe.session.user == "Guest":
|
||||
raise frappe.PermissionError(_("You are not allowed to access this page."))
|
||||
|
||||
membership = frappe.db.exists(
|
||||
"LMS Batch Membership", {"member": frappe.session.user, "course": course_name}
|
||||
)
|
||||
|
||||
if membership:
|
||||
raise frappe.PermissionError(_("You are already enrolled for this course"))
|
||||
|
||||
context.course = frappe.db.get_value(
|
||||
"LMS Course", course_name, ["title", "name", "course_price", "currency"], as_dict=True
|
||||
)
|
||||
Reference in New Issue
Block a user