From 3c9c4d34a702ca4beafdf097b917d720864d085d Mon Sep 17 00:00:00 2001
From: Rahul Agrawal <12agrawalrahul@gmail.com>
Date: Thu, 30 Apr 2026 00:26:55 +0530
Subject: [PATCH 1/5] feat: add GSTIN fields in core
---
buzz/api/__init__.py | 8 ++++
.../doctype/event_booking/event_booking.json | 33 ++++++++++++++
dashboard/src/components/BookingForm.vue | 43 +++++++++++++++++++
.../src/composables/useBookingFormStorage.ts | 10 +++++
4 files changed, 94 insertions(+)
diff --git a/buzz/api/__init__.py b/buzz/api/__init__.py
index 7ed096a9..ab9c6611 100644
--- a/buzz/api/__init__.py
+++ b/buzz/api/__init__.py
@@ -332,6 +332,9 @@ def process_booking(
payment_proof: str | None = None,
is_offline: bool = False,
offline_payment_method: str | None = None,
+ request_invoice: bool = False,
+ gst_in: str | None = None,
+ billing_address: str | None = None,
) -> dict:
event_doc = frappe.get_cached_doc("Buzz Event", event)
if not event_doc.is_published:
@@ -378,6 +381,11 @@ def process_booking(
booking.coupon_code = coupon_code
booking.user = booking_user
+ if event_doc.apply_tax and request_invoice:
+ booking.request_invoice = 1
+ booking.gst_in = gst_in
+ booking.billing_address = billing_address
+
if utm_parameters:
for utm_param in utm_parameters:
booking.append(
diff --git a/buzz/ticketing/doctype/event_booking/event_booking.json b/buzz/ticketing/doctype/event_booking/event_booking.json
index 1d4fb71a..83375630 100644
--- a/buzz/ticketing/doctype/event_booking/event_booking.json
+++ b/buzz/ticketing/doctype/event_booking/event_booking.json
@@ -32,6 +32,11 @@
"currency",
"coupon_code",
"discount_amount",
+ "billing_details_section",
+ "request_invoice",
+ "gst_in",
+ "column_break_billing",
+ "billing_address",
"section_break_sdfp",
"amended_from",
"marketing_tab",
@@ -176,6 +181,34 @@
"options": "currency",
"read_only": 1
},
+ {
+ "fieldname": "billing_details_section",
+ "fieldtype": "Section Break",
+ "label": "Billing Details"
+ },
+ {
+ "default": "0",
+ "fieldname": "request_invoice",
+ "fieldtype": "Check",
+ "label": "Request Invoice"
+ },
+ {
+ "depends_on": "eval:doc.request_invoice==1",
+ "fieldname": "gst_in",
+ "fieldtype": "Data",
+ "label": "GST IN"
+ },
+ {
+ "fieldname": "column_break_billing",
+ "fieldtype": "Column Break"
+ },
+ {
+ "depends_on": "eval:doc.request_invoice==1",
+ "fieldname": "billing_address",
+ "fieldtype": "Small Text",
+ "label": "Billing Address",
+ "mandatory_depends_on": "eval:doc.request_invoice==1"
+ },
{
"fieldname": "section_break_status",
"fieldtype": "Section Break",
diff --git a/dashboard/src/components/BookingForm.vue b/dashboard/src/components/BookingForm.vue
index 13b0f8a1..823b88eb 100644
--- a/dashboard/src/components/BookingForm.vue
+++ b/dashboard/src/components/BookingForm.vue
@@ -171,6 +171,37 @@
/>
+
+
+ {{ __("Billing Details") }}
+
+
+
+
+
+
+
+
+
+
`${guestFirstName.value} ${guestLastName.value}`.trim());
@@ -1052,6 +1086,10 @@ function removeCoupon() {
const validateForm = () => {
const errors = [];
+ if (shouldApplyTax.value && requestInvoice.value && !billingAddress.value?.trim()) {
+ errors.push(__("Billing Address is required"));
+ }
+
// Validate booking-level mandatory fields
for (const field of bookingCustomFields.value) {
if (field.mandatory) {
@@ -1160,6 +1198,8 @@ async function submit() {
const utmParameters = getUtmParameters();
+ const includeInvoice = shouldApplyTax.value && requestInvoice.value;
+
const final_payload = {
event: eventId.value,
attendees: attendees_payload,
@@ -1170,6 +1210,9 @@ async function submit() {
guest_email: props.isGuestMode ? guestEmail.value.trim() : null,
guest_full_name: props.isGuestMode ? guestFullName.value.trim() : null,
guest_phone: props.isGuestMode && isPhoneOtp.value ? guestPhone.value.trim() : null,
+ request_invoice: includeInvoice ? 1 : 0,
+ gst_in: includeInvoice ? gstIn.value?.trim() || null : null,
+ billing_address: includeInvoice ? billingAddress.value?.trim() || null : null,
};
if (props.isGuestMode) {
diff --git a/dashboard/src/composables/useBookingFormStorage.ts b/dashboard/src/composables/useBookingFormStorage.ts
index 53150447..362073db 100644
--- a/dashboard/src/composables/useBookingFormStorage.ts
+++ b/dashboard/src/composables/useBookingFormStorage.ts
@@ -26,6 +26,10 @@ export function useBookingFormStorage(eventRoute: string) {
const guestEmail = useStorage(`${storageKeyPrefix}-guest-email`, "")
const guestPhone = useStorage(`${storageKeyPrefix}-guest-phone`, "")
+ const requestInvoice = useStorage(`${storageKeyPrefix}-request-invoice`, false)
+ const gstIn = useStorage(`${storageKeyPrefix}-gst-in`, "")
+ const billingAddress = useStorage(`${storageKeyPrefix}-billing-address`, "")
+
/**
* Clear all stored booking form data
* This should be called when payment is successful
@@ -38,6 +42,9 @@ export function useBookingFormStorage(eventRoute: string) {
guestLastName.value = ""
guestEmail.value = ""
guestPhone.value = ""
+ requestInvoice.value = false
+ gstIn.value = ""
+ billingAddress.value = ""
}
/**
@@ -58,6 +65,9 @@ export function useBookingFormStorage(eventRoute: string) {
guestLastName,
guestEmail,
guestPhone,
+ requestInvoice,
+ gstIn,
+ billingAddress,
clearStoredData,
hasStoredData,
}
From e88068e7f27fe56d527fdf3bc1104e9af2a61841 Mon Sep 17 00:00:00 2001
From: Rahul Agrawal <12agrawalrahul@gmail.com>
Date: Thu, 30 Apr 2026 01:35:59 +0530
Subject: [PATCH 2/5] fix: invoice details card design
---
dashboard/src/components/BookingForm.vue | 33 ++++++++++++------------
1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/dashboard/src/components/BookingForm.vue b/dashboard/src/components/BookingForm.vue
index 823b88eb..3f1a888d 100644
--- a/dashboard/src/components/BookingForm.vue
+++ b/dashboard/src/components/BookingForm.vue
@@ -175,7 +175,7 @@
v-if="shouldApplyTax"
class="bg-surface-white border border-outline-gray-3 rounded-xl p-4 md:p-6 mb-6 shadow-sm"
>
-
+
{{ __("Billing Details") }}
@@ -191,13 +191,18 @@
:label="__('GST IN')"
:placeholder="__('Enter GST IN')"
/>
-
+
+
+
+
@@ -432,7 +437,7 @@ import { useLoginDialog } from "@/composables/useLoginDialog";
import { userResource } from "@/data/user";
import { formatCurrency, formatPriceOrFree } from "@/utils/currency";
import { clearBookingCache } from "@/utils/index";
-import { FormControl, createResource, toast } from "frappe-ui";
+import { FormControl, Textarea, createResource, toast } from "frappe-ui";
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useRouteQuery } from "@vueuse/router";
@@ -1086,10 +1091,6 @@ function removeCoupon() {
const validateForm = () => {
const errors = [];
- if (shouldApplyTax.value && requestInvoice.value && !billingAddress.value?.trim()) {
- errors.push(__("Billing Address is required"));
- }
-
// Validate booking-level mandatory fields
for (const field of bookingCustomFields.value) {
if (field.mandatory) {
@@ -1210,9 +1211,9 @@ async function submit() {
guest_email: props.isGuestMode ? guestEmail.value.trim() : null,
guest_full_name: props.isGuestMode ? guestFullName.value.trim() : null,
guest_phone: props.isGuestMode && isPhoneOtp.value ? guestPhone.value.trim() : null,
- request_invoice: includeInvoice ? 1 : 0,
- gst_in: includeInvoice ? gstIn.value?.trim() || null : null,
- billing_address: includeInvoice ? billingAddress.value?.trim() || null : null,
+ request_invoice: includeInvoice,
+ gst_in: includeInvoice ? gstIn.value?.trim() : null,
+ billing_address: includeInvoice ? billingAddress.value?.trim() : null,
};
if (props.isGuestMode) {
From 82abcfc39ce7697a5fce665b6c871489ac2e3c79 Mon Sep 17 00:00:00 2001
From: Rahul Agrawal <12agrawalrahul@gmail.com>
Date: Thu, 30 Apr 2026 01:48:12 +0530
Subject: [PATCH 3/5] feat: extract invoice detail
---
dashboard/components.d.ts | 1 +
dashboard/src/components/BillingDetail.vue | 60 ++++++++++++++++++++++
dashboard/src/components/BookingForm.vue | 42 +++------------
3 files changed, 68 insertions(+), 35 deletions(-)
create mode 100644 dashboard/src/components/BillingDetail.vue
diff --git a/dashboard/components.d.ts b/dashboard/components.d.ts
index d8d060ca..e62e38f0 100644
--- a/dashboard/components.d.ts
+++ b/dashboard/components.d.ts
@@ -12,6 +12,7 @@ declare module 'vue' {
AttendeeFormControl: typeof import('./src/components/AttendeeFormControl.vue')['default']
BackButton: typeof import('./src/components/common/BackButton.vue')['default']
BaseCustomEventForm: typeof import('./src/components/BaseCustomEventForm.vue')['default']
+ BillingDetail: typeof import('./src/components/BillingDetail.vue')['default']
BookingEventInfo: typeof import('./src/components/BookingEventInfo.vue')['default']
BookingFinancialSummary: typeof import('./src/components/BookingFinancialSummary.vue')['default']
BookingForm: typeof import('./src/components/BookingForm.vue')['default']
diff --git a/dashboard/src/components/BillingDetail.vue b/dashboard/src/components/BillingDetail.vue
new file mode 100644
index 00000000..41a433db
--- /dev/null
+++ b/dashboard/src/components/BillingDetail.vue
@@ -0,0 +1,60 @@
+
+
+
+ {{ __("Billing Details") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dashboard/src/components/BookingForm.vue b/dashboard/src/components/BookingForm.vue
index 3f1a888d..1521ad45 100644
--- a/dashboard/src/components/BookingForm.vue
+++ b/dashboard/src/components/BookingForm.vue
@@ -171,41 +171,12 @@
/>
-
-
- {{ __("Billing Details") }}
-
-
-
-
-
-
-
-
-
-
-
-
+ v-model:request-invoice="requestInvoice"
+ v-model:gst-in="gstIn"
+ v-model:billing-address="billingAddress"
+ />
Date: Thu, 30 Apr 2026 15:33:20 +0530
Subject: [PATCH 4/5] fix: use TAX ID instead of GST IN
---
buzz/api/__init__.py | 4 ++--
.../doctype/event_booking/event_booking.json | 6 +++---
dashboard/src/components/BillingDetail.vue | 21 ++++++++++++-------
dashboard/src/components/BookingForm.vue | 7 ++++---
.../src/composables/useBookingFormStorage.ts | 6 +++---
5 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/buzz/api/__init__.py b/buzz/api/__init__.py
index ab9c6611..c860ab39 100644
--- a/buzz/api/__init__.py
+++ b/buzz/api/__init__.py
@@ -333,7 +333,7 @@ def process_booking(
is_offline: bool = False,
offline_payment_method: str | None = None,
request_invoice: bool = False,
- gst_in: str | None = None,
+ tax_id: str | None = None,
billing_address: str | None = None,
) -> dict:
event_doc = frappe.get_cached_doc("Buzz Event", event)
@@ -383,7 +383,7 @@ def process_booking(
if event_doc.apply_tax and request_invoice:
booking.request_invoice = 1
- booking.gst_in = gst_in
+ booking.tax_id = tax_id
booking.billing_address = billing_address
if utm_parameters:
diff --git a/buzz/ticketing/doctype/event_booking/event_booking.json b/buzz/ticketing/doctype/event_booking/event_booking.json
index 83375630..09cb8597 100644
--- a/buzz/ticketing/doctype/event_booking/event_booking.json
+++ b/buzz/ticketing/doctype/event_booking/event_booking.json
@@ -34,7 +34,7 @@
"discount_amount",
"billing_details_section",
"request_invoice",
- "gst_in",
+ "tax_id",
"column_break_billing",
"billing_address",
"section_break_sdfp",
@@ -194,9 +194,9 @@
},
{
"depends_on": "eval:doc.request_invoice==1",
- "fieldname": "gst_in",
+ "fieldname": "tax_id",
"fieldtype": "Data",
- "label": "GST IN"
+ "label": "Tax ID"
},
{
"fieldname": "column_break_billing",
diff --git a/dashboard/src/components/BillingDetail.vue b/dashboard/src/components/BillingDetail.vue
index 41a433db..89f712ea 100644
--- a/dashboard/src/components/BillingDetail.vue
+++ b/dashboard/src/components/BillingDetail.vue
@@ -14,11 +14,11 @@
/>