Merge pull request #2292 from raizasafeel/feat/zero-amount-checkout

fix: allow zero amount checkout with coupons
This commit is contained in:
Raizaaa
2026-04-06 20:45:16 +05:30
committed by GitHub
3 changed files with 61 additions and 38 deletions

View File

@@ -199,8 +199,15 @@
}}
</div>
</div>
<Button variant="solid" size="md" @click="generatePaymentLink()">
{{ __('Proceed to Payment') }}
<Button
variant="solid"
size="md"
class="ms-auto"
@click="generatePaymentLink()"
>
{{
isZeroAmount ? __('Enroll for Free') : __('Proceed to Payment')
}}
</Button>
</div>
</div>
@@ -326,16 +333,10 @@ const paymentLink = createResource({
let data = {
doctype: props.type == 'batch' ? 'LMS Batch' : 'LMS Course',
docname: props.name,
title: orderSummary.data.title,
amount: orderSummary.data.original_amount,
discount_amount: orderSummary.data.discount_amount || 0,
gst_amount: orderSummary.data.gst_applied || 0,
currency: orderSummary.data.currency,
address: billingDetails,
redirect_to: redirectTo.value,
payment_for_certificate: props.type == 'certificate',
coupon_code: appliedCoupon.value,
coupon: orderSummary.data.coupon,
country: billingDetails.country,
}
return data
},
@@ -458,14 +459,8 @@ const changeCurrency = (country) => {
orderSummary.reload()
}
const redirectTo = computed(() => {
if (props.type == 'course') {
return getLmsRoute(`courses/${props.name}`)
} else if (props.type == 'batch') {
return getLmsRoute(`batches/${props.name}`)
} else if (props.type == 'certificate') {
return getLmsRoute(`courses/${props.name}/certification`)
}
const isZeroAmount = computed(() => {
return orderSummary.data && parseFloat(orderSummary.data.total_amount) <= 0
})
watch(billingDetails, () => {

View File

@@ -1,5 +1,11 @@
import frappe
from lms.lms.utils import (
complete_enrollment,
get_lms_route,
get_order_summary,
)
def get_payment_gateway():
return frappe.db.get_single_value("LMS Settings", "payment_gateway")
@@ -21,22 +27,25 @@ def validate_currency(payment_gateway, currency):
def get_payment_link(
doctype: str,
docname: str,
title: str,
amount: float,
discount_amount: float,
gst_amount: float,
currency: str,
address: dict,
redirect_to: str,
payment_for_certificate: int,
coupon_code: str = None,
coupon: str = None,
coupon_code: str,
country: str,
):
payment_gateway = get_payment_gateway()
address = frappe._dict(address)
original_amount = amount
amount -= discount_amount
redirect_to = get_redirect_url(doctype, docname, payment_for_certificate)
details = frappe._dict(get_order_summary(doctype, docname, coupon=coupon_code, country=country))
title = details.title
currency = details.currency
original_amount = details.original_amount
discount_amount = details.get("discount_amount", 0)
gst_amount = details.get("gst_applied", 0)
amount = original_amount - discount_amount
amount_with_gst = get_amount_with_gst(amount, gst_amount)
coupon = details.get("coupon")
total_amount = amount_with_gst if amount_with_gst else amount
payment = record_payment(
address,
@@ -51,10 +60,16 @@ def get_payment_link(
coupon_code,
coupon,
)
if total_amount <= 0:
frappe.db.set_value("LMS Payment", payment.name, "payment_received", 1)
complete_enrollment(payment.name, doctype, docname)
return redirect_to
controller = get_controller(payment_gateway)
payment_details = {
"amount": amount_with_gst if amount_with_gst else amount,
"amount": total_amount,
"title": f"Payment for {doctype} {title} {docname}",
"description": f"{address.billing_name}'s payment for {title}",
"reference_doctype": doctype,
@@ -99,8 +114,8 @@ def record_payment(
amount_with_gst: float = 0,
discount_amount: float = 0,
payment_for_certificate: int = 0,
coupon_code: str = None,
coupon: str = None,
coupon_code: str | None = None,
coupon: str | None = None,
):
address = frappe._dict(address)
address_name = save_address(address)
@@ -138,6 +153,15 @@ def record_payment(
return payment_doc
def get_redirect_url(doctype: str, docname: str, payment_for_certificate: int) -> str:
if int(payment_for_certificate):
return get_lms_route(f"courses/{docname}/certification")
elif doctype == "LMS Course":
return get_lms_route(f"courses/{docname}")
else:
return get_lms_route(f"batches/{docname}")
def save_address(address: dict) -> str:
filters = {"email_id": frappe.session.user}
exists = frappe.db.exists("Address", filters)

View File

@@ -1907,17 +1907,21 @@ def update_payment_record(doctype: str, docname: str):
if len(request):
data = request[0].data
data = frappe._dict(json.loads(data))
payment_doc = get_payment_doc(data.payment)
update_payment_details(data)
update_coupon_redemption(payment_doc)
complete_enrollment(data.payment, doctype, docname)
if payment_doc.payment_for_certificate:
update_certificate_purchase(docname, data.payment)
elif doctype == "LMS Course":
enroll_in_course(docname, data.payment)
else:
enroll_in_batch(docname, data.payment)
def complete_enrollment(payment_name: str, doctype: str, docname: str):
payment_doc = get_payment_doc(payment_name)
update_coupon_redemption(payment_doc)
if payment_doc.payment_for_certificate:
update_certificate_purchase(docname, payment_name)
elif doctype == "LMS Course":
enroll_in_course(docname, payment_name)
else:
enroll_in_batch(docname, payment_name)
def get_integration_requests(doctype: str, docname: str):