diff --git a/frontend/src/pages/Billing.vue b/frontend/src/pages/Billing.vue
index a98af8cb..a87aaa22 100644
--- a/frontend/src/pages/Billing.vue
+++ b/frontend/src/pages/Billing.vue
@@ -38,7 +38,7 @@
v-if="orderSummary.data.gst_applied"
class="flex items-center justify-between mt-2"
>
-
+
{{ __('GST Amount') }}
@@ -171,7 +171,7 @@ import { Input, Button, createResource, call } from 'frappe-ui'
import { reactive, inject, onMounted, ref } from 'vue'
import Link from '@/components/Controls/Link.vue'
import NotPermitted from '@/components/NotPermitted.vue'
-import { createToast } from '@/utils/'
+import { showToast } from '@/utils/'
const user = inject('$user')
@@ -224,73 +224,45 @@ const orderSummary = createResource({
const billingDetails = reactive({})
const setBillingDetails = (data) => {
- billingDetails.billing_name = data.billing_name || ''
- billingDetails.address_line1 = data.address_line1 || ''
- billingDetails.address_line2 = data.address_line2 || ''
- billingDetails.city = data.city || ''
- billingDetails.state = data.state || ''
- billingDetails.country = data.country || ''
- billingDetails.pincode = data.pincode || ''
- billingDetails.phone = data.phone || ''
- billingDetails.source = data.source || ''
- billingDetails.gstin = data.gstin || ''
- billingDetails.pan = data.pan || ''
+ billingDetails.billing_name = data?.billing_name || ''
+ billingDetails.address_line1 = data?.address_line1 || ''
+ billingDetails.address_line2 = data?.address_line2 || ''
+ billingDetails.city = data?.city || ''
+ billingDetails.state = data?.state || ''
+ billingDetails.country = data?.country || ''
+ billingDetails.pincode = data?.pincode || ''
+ billingDetails.phone = data?.phone || ''
+ billingDetails.source = data?.source || ''
+ billingDetails.gstin = data?.gstin || ''
+ billingDetails.pan = data?.pan || ''
}
-const paymentOptions = createResource({
- url: 'lms.lms.utils.get_payment_options',
+const paymentLink = createResource({
+ url: 'lms.lms.payments.get_payment_link',
makeParams(values) {
return {
doctype: props.type == 'course' ? 'LMS Course' : 'LMS Batch',
docname: props.name,
- phone: billingDetails.phone,
- country: billingDetails.country,
+ amount: orderSummary.data.original_amount,
+ total_amount: orderSummary.data.amount,
+ currency: orderSummary.data.currency,
+ address: billingDetails,
}
},
})
const generatePaymentLink = () => {
- call('lms.lms.payments.get_payment_link', {
- doctype: props.type == 'course' ? 'LMS Course' : 'LMS Batch',
- docname: props.name,
- amount: orderSummary.data.amount,
- currency: orderSummary.data.currency,
- billing_name: billingDetails.billing_name,
- }).then((data) => {
- window.location.href = data
- })
-}
-
-const paymentResource = createResource({
- url: 'lms.lms.utils.verify_payment',
- makeParams(values) {
- return {
- response: values.response,
- doctype: props.type == 'course' ? 'LMS Course' : 'LMS Batch',
- docname: props.name,
- address: billingDetails,
- order_id: values.orderId,
- }
- },
-})
-
-const handleSuccess = (response, doctype, docname, orderId) => {
- paymentResource.submit(
- {
- response: response,
- orderId: orderId,
- },
+ paymentLink.submit(
+ {},
{
+ validate() {
+ return validateAddress()
+ },
onSuccess(data) {
- createToast({
- title: 'Success',
- text: 'Payment Successful',
- icon: 'check',
- iconClasses: 'bg-green-600 text-white rounded-md p-px',
- })
- setTimeout(() => {
- window.location.href = data
- }, 3000)
+ window.location.href = data
+ },
+ onError(err) {
+ showToast(__('Error'), err.messages?.[0] || err, 'x')
},
}
)
diff --git a/lms/lms/doctype/lms_batch/lms_batch.py b/lms/lms/doctype/lms_batch/lms_batch.py
index 306a1cee..82006ca1 100644
--- a/lms/lms/doctype/lms_batch/lms_batch.py
+++ b/lms/lms/doctype/lms_batch/lms_batch.py
@@ -165,25 +165,64 @@ class LMSBatch(Document):
)
def on_payment_authorized(self, payment_status):
- print(payment_status)
+ if payment_status == "Authorized":
+ self.update_payment_record()
+
+ def update_payment_record(self):
+ request = frappe.get_all(
+ "Integration Request",
+ {
+ "reference_doctype": self.doctype,
+ "reference_docname": self.name,
+ "owner": frappe.session.user,
+ },
+ order_by="creation desc",
+ limit=1,
+ )
+
+ if len(request):
+ data = frappe.db.get_value("Integration Request", request[0].name, "data")
+ data = frappe._dict(json.loads(data))
+
+ payment_gateway = data.get("payment_gateway")
+ frappe.db.set_value(
+ "LMS Payment",
+ data.payment,
+ {
+ "payment_received": 1,
+ "payment_id": data[f"{payment_gateway.lower()}_payment_id"],
+ "order_id": data["order_id"],
+ },
+ )
+
+ try:
+ enroll_in_batch(data.payment, self)
+ except Exception as e:
+ frappe.log_error(frappe.get_traceback(), _("Enrollment Failed"))
-@frappe.whitelist()
-def remove_student(student, batch_name):
- frappe.only_for("Moderator")
- frappe.db.delete("Batch Student", {"student": student, "parent": batch_name})
+def enroll_in_batch(payment_name, batch):
+ if not frappe.db.exists(
+ "Batch Student", {"parent": batch.name, "student": frappe.session.user}
+ ):
+ student = frappe.new_doc("Batch Student")
+ current_count = frappe.db.count("Batch Student", {"parent": batch.name})
+ payment = frappe.db.get_value(
+ "LMS Payment", payment_name, ["name", "source"], as_dict=True
+ )
-
-@frappe.whitelist()
-def remove_course(course, parent):
- frappe.only_for("Moderator")
- frappe.db.delete("Batch Course", {"course": course, "parent": parent})
-
-
-@frappe.whitelist()
-def remove_assessment(assessment, parent):
- frappe.only_for("Moderator")
- frappe.db.delete("LMS Assessment", {"assessment_name": assessment, "parent": parent})
+ student.update(
+ {
+ "student": frappe.session.user,
+ "payment": payment.name,
+ "source": payment.source,
+ "parent": batch.name,
+ "parenttype": "LMS Batch",
+ "parentfield": "students",
+ "idx": current_count + 1,
+ }
+ )
+ student.save(ignore_permissions=True)
@frappe.whitelist()
diff --git a/lms/lms/doctype/lms_settings/lms_settings.json b/lms/lms/doctype/lms_settings/lms_settings.json
index 03bcaf42..9b8dd0fd 100644
--- a/lms/lms/doctype/lms_settings/lms_settings.json
+++ b/lms/lms/doctype/lms_settings/lms_settings.json
@@ -42,6 +42,7 @@
"mentor_request_status_update",
"payment_settings_tab",
"payment_section",
+ "payment_gateway",
"razorpay_key",
"razorpay_secret",
"apply_gst",
@@ -331,12 +332,18 @@
"fieldname": "custom_signup_content",
"fieldtype": "HTML Editor",
"label": "Custom Signup Content"
+ },
+ {
+ "fieldname": "payment_gateway",
+ "fieldtype": "Select",
+ "label": "Payment Gateway",
+ "options": "Razorpay\nMpesa\nPaytm\nBraintree\nStripe\nPaypal\nGoCardless"
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2024-09-23 17:57:01.350020",
+ "modified": "2024-09-24 18:09:25.366651",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Settings",
diff --git a/lms/lms/payments.py b/lms/lms/payments.py
index d89508b9..cc8ccd4e 100644
--- a/lms/lms/payments.py
+++ b/lms/lms/payments.py
@@ -3,7 +3,7 @@ from payments.utils import get_payment_gateway_controller
def get_payment_gateway():
- return "Razorpay"
+ return frappe.db.get_single_value("LMS Settings", "payment_gateway")
def get_controller(payment_gateway):
@@ -16,21 +16,73 @@ def validate_currency(payment_gateway, currency):
@frappe.whitelist()
-def get_payment_link(doctype, docname, amount, currency, billing_name):
+def get_payment_link(doctype, docname, amount, total_amount, currency, address):
payment_gateway = get_payment_gateway()
+ address = frappe._dict(address)
+ amount_with_gst = total_amount if total_amount != amount else 0
+
+ payment = record_payment(address, doctype, docname, amount, currency, amount_with_gst)
payment_details = {
- "amount": amount,
+ "amount": total_amount,
"title": f"Payment for {doctype} {docname}",
- "description": f"{billing_name}'s payment for {doctype} {docname}",
+ "description": f"{address.billing_name}'s payment for {doctype} {docname}",
"reference_doctype": doctype,
"reference_docname": docname,
"payer_email": frappe.session.user,
- "payer_name": billing_name,
+ "payer_name": address.billing_name,
"order_id": docname,
"currency": currency,
"payment_gateway": payment_gateway,
+ "redirect_to": f"/lms/batches/{docname}",
+ "payment": payment.name,
}
controller = get_controller(payment_gateway)
- url = controller().get_payment_url(**payment_details)
+ url = controller.get_payment_url(**payment_details)
+
return url
+
+
+def record_payment(address, doctype, docname, amount, currency, amount_with_gst=0):
+ address = frappe._dict(address)
+ address_name = save_address(address)
+
+ payment_doc = frappe.new_doc("LMS Payment")
+ payment_doc.update(
+ {
+ "member": frappe.session.user,
+ "billing_name": address.billing_name,
+ "address": address_name,
+ "amount": amount,
+ "currency": currency,
+ "amount_with_gst": amount_with_gst,
+ "gstin": address.gstin,
+ "pan": address.pan,
+ "source": address.source,
+ "payment_for_document_type": doctype,
+ "payment_for_document": docname,
+ }
+ )
+ payment_doc.save(ignore_permissions=True)
+ return payment_doc
+
+
+def save_address(address):
+ filters = {"email_id": frappe.session.user}
+ exists = frappe.db.exists("Address", filters)
+ if exists:
+ address_doc = frappe.get_last_doc("Address", filters=filters)
+ else:
+ address_doc = frappe.new_doc("Address")
+
+ address_doc.update(address)
+ address_doc.update(
+ {
+ "address_title": frappe.db.get_value("User", frappe.session.user, "full_name"),
+ "address_type": "Billing",
+ "is_primary_address": 1,
+ "email_id": frappe.session.user,
+ }
+ )
+ address_doc.save(ignore_permissions=True)
+ return address_doc.name
diff --git a/lms/lms/utils.py b/lms/lms/utils.py
index b2692b23..8e2945c7 100644
--- a/lms/lms/utils.py
+++ b/lms/lms/utils.py
@@ -1021,27 +1021,6 @@ def get_details(doctype, docname):
return details
-def save_address(address):
- filters = {"email_id": frappe.session.user}
- exists = frappe.db.exists("Address", filters)
- if exists:
- address_doc = frappe.get_last_doc("Address", filters=filters)
- else:
- address_doc = frappe.new_doc("Address")
-
- address_doc.update(address)
- address_doc.update(
- {
- "address_title": frappe.db.get_value("User", frappe.session.user, "full_name"),
- "address_type": "Billing",
- "is_primary_address": 1,
- "email_id": frappe.session.user,
- }
- )
- address_doc.save(ignore_permissions=True)
- return address_doc.name
-
-
def get_client():
settings = frappe.get_single("LMS Settings")
razorpay_key = settings.razorpay_key
@@ -1073,52 +1052,6 @@ def create_order(client, amount, currency):
)
-@frappe.whitelist()
-def verify_payment(response, doctype, docname, address, order_id):
- client = get_client()
- client.utility.verify_payment_signature(
- {
- "razorpay_order_id": order_id,
- "razorpay_payment_id": response["razorpay_payment_id"],
- "razorpay_signature": response["razorpay_signature"],
- }
- )
-
- payment = record_payment(address, response, client, doctype, docname)
- if doctype == "LMS Course":
- return create_membership(docname, payment)
- else:
- return add_student_to_batch(docname, payment)
-
-
-def record_payment(address, response, client, doctype, docname):
- address = frappe._dict(address)
- address_name = save_address(address)
-
- payment_details = get_payment_details(doctype, docname, address)
- payment_doc = frappe.new_doc("LMS Payment")
- payment_doc.update(
- {
- "member": frappe.session.user,
- "billing_name": address.billing_name,
- "address": address_name,
- "payment_received": 1,
- "order_id": response["razorpay_order_id"],
- "payment_id": response["razorpay_payment_id"],
- "amount": payment_details["amount"],
- "currency": payment_details["currency"],
- "amount_with_gst": payment_details["amount_with_gst"],
- "gstin": address.gstin,
- "pan": address.pan,
- "source": address.source,
- "payment_for_document_type": doctype,
- "payment_for_document": docname,
- }
- )
- payment_doc.save(ignore_permissions=True)
- return payment_doc
-
-
def get_payment_details(doctype, docname, address):
amount_field = "course_price" if doctype == "LMS Course" else "amount"
amount = frappe.db.get_value(doctype, docname, amount_field)
@@ -1146,24 +1079,6 @@ def create_membership(course, payment):
return f"/lms/courses/{course}/learn/1-1"
-def add_student_to_batch(batchname, payment):
- student = frappe.new_doc("Batch Student")
- current_count = frappe.db.count("Batch Student", {"parent": batchname})
- student.update(
- {
- "student": frappe.session.user,
- "payment": payment.name,
- "source": payment.source,
- "parent": batchname,
- "parenttype": "LMS Batch",
- "parentfield": "students",
- "idx": current_count + 1,
- }
- )
- student.save(ignore_permissions=True)
- return f"/batches/{batchname}"
-
-
def get_current_exchange_rate(source, target="USD"):
url = f"https://api.frankfurter.app/latest?from={source}&to={target}"
@@ -1765,6 +1680,7 @@ def get_order_summary(doctype, docname, country=None):
details.amount, details.currency = check_multicurrency(
details.amount, details.currency, country, details.amount_usd
)
+ details.original_amount = details.amount
details.original_amount_formatted = fmt_money(details.amount, 0, details.currency)
if details.currency == "INR":