Merge branch 'develop' into exotel-fixes
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
index 35c2f84..a519d8b 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -34,7 +34,9 @@
 
 	def validate_thresholds(self):
 		for d in self.get("rates"):
-			if d.cumulative_threshold and d.cumulative_threshold < d.single_threshold:
+			if (
+				d.cumulative_threshold and d.single_threshold and d.cumulative_threshold < d.single_threshold
+			):
 				frappe.throw(
 					_("Row #{0}: Cumulative threshold cannot be less than Single Transaction threshold").format(
 						d.idx
diff --git a/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html b/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html
index e658049..605ce83 100644
--- a/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html
+++ b/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html
@@ -1,7 +1,8 @@
 {%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value -%}
-{%- set einvoice = json.loads(doc.signed_einvoice) -%}
 
 <div class="page-break">
+	{% if doc.signed_einvoice %}
+	{%- set einvoice = json.loads(doc.signed_einvoice) -%}
 	<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
 		{% if letter_head and not no_letterhead %}
 			<div class="letter-head">{{ letter_head }}</div>
@@ -170,4 +171,10 @@
 			</tbody>
 		</table>
 	</div>
+	{% else %}
+	<div class="text-center" style="color: var(--gray-500); font-size: 14px;">
+		You must generate IRN before you can preview GST E-Invoice.
+	</div>
+	{% endif %}
 </div>
+
diff --git a/erpnext/e_commerce/doctype/website_item/website_item.js b/erpnext/e_commerce/doctype/website_item/website_item.js
index 7108cab..7295e4b 100644
--- a/erpnext/e_commerce/doctype/website_item/website_item.js
+++ b/erpnext/e_commerce/doctype/website_item/website_item.js
@@ -2,7 +2,7 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Website Item', {
-	onload: function(frm) {
+	onload: (frm) => {
 		// should never check Private
 		frm.fields_dict["website_image"].df.is_private = 0;
 
@@ -13,18 +13,35 @@
 		});
 	},
 
-	image: function() {
+	refresh: (frm) => {
+		frm.add_custom_button(__("Prices"), function() {
+			frappe.set_route("List", "Item Price", {"item_code": frm.doc.item_code});
+		}, __("View"));
+
+		frm.add_custom_button(__("Stock"), function() {
+			frappe.route_options = {
+				"item_code": frm.doc.item_code
+			};
+			frappe.set_route("query-report", "Stock Balance");
+		}, __("View"));
+
+		frm.add_custom_button(__("E Commerce Settings"), function() {
+			frappe.set_route("Form", "E Commerce Settings");
+		}, __("View"));
+	},
+
+	image: () => {
 		refresh_field("image_view");
 	},
 
-	copy_from_item_group: function(frm) {
+	copy_from_item_group: (frm) => {
 		return frm.call({
 			doc: frm.doc,
 			method: "copy_specification_from_item_group"
 		});
 	},
 
-	set_meta_tags(frm) {
+	set_meta_tags: (frm) => {
 		frappe.utils.set_meta_tag(frm.doc.route);
 	}
 });
diff --git a/erpnext/regional/india/e_invoice/einvoice.js b/erpnext/regional/india/e_invoice/einvoice.js
index 348f0c6..17b018c 100644
--- a/erpnext/regional/india/e_invoice/einvoice.js
+++ b/erpnext/regional/india/e_invoice/einvoice.js
@@ -105,6 +105,30 @@
 						},
 						primary_action_label: __('Submit')
 					});
+					d.fields_dict.transporter.df.onchange = function () {
+						const transporter = d.fields_dict.transporter.value;
+						if (transporter) {
+							frappe.db.get_value('Supplier', transporter, ['gst_transporter_id', 'supplier_name'])
+								.then(({ message }) => {
+									d.set_value('gst_transporter_id', message.gst_transporter_id);
+									d.set_value('transporter_name', message.supplier_name);
+								});
+						} else {
+							d.set_value('gst_transporter_id', '');
+							d.set_value('transporter_name', '');
+						}
+					};
+					d.fields_dict.driver.df.onchange = function () {
+						const driver = d.fields_dict.driver.value;
+						if (driver) {
+							frappe.db.get_value('Driver', driver, ['full_name'])
+								.then(({ message }) => {
+									d.set_value('driver_name', message.full_name);
+								});
+						} else {
+							d.set_value('driver_name', '');
+						}
+					};
 					d.show();
 				};
 
@@ -153,7 +177,6 @@
 			'fieldname': 'gst_transporter_id',
 			'label': 'GST Transporter ID',
 			'fieldtype': 'Data',
-			'fetch_from': 'transporter.gst_transporter_id',
 			'default': frm.doc.gst_transporter_id
 		},
 		{
@@ -189,9 +212,9 @@
 			'fieldname': 'transporter_name',
 			'label': 'Transporter Name',
 			'fieldtype': 'Data',
-			'fetch_from': 'transporter.name',
 			'read_only': 1,
-			'default': frm.doc.transporter_name
+			'default': frm.doc.transporter_name,
+			'depends_on': 'transporter'
 		},
 		{
 			'fieldname': 'mode_of_transport',
@@ -206,7 +229,8 @@
 			'fieldtype': 'Data',
 			'fetch_from': 'driver.full_name',
 			'read_only': 1,
-			'default': frm.doc.driver_name
+			'default': frm.doc.driver_name,
+			'depends_on': 'driver'
 		},
 		{
 			'fieldname': 'lr_date',
diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py
index cbdec56..8fd9c1c 100644
--- a/erpnext/regional/india/e_invoice/utils.py
+++ b/erpnext/regional/india/e_invoice/utils.py
@@ -387,7 +387,7 @@
 
 def get_payment_details(invoice):
 	payee_name = invoice.company
-	mode_of_payment = ", ".join([d.mode_of_payment for d in invoice.payments])
+	mode_of_payment = ""
 	paid_amount = invoice.base_paid_amount
 	outstanding_amount = invoice.outstanding_amount
 
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 9e8b3bd..23301a6 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -55,10 +55,15 @@
 
 		if (frm.doc.has_variants) {
 			frm.set_intro(__("This Item is a Template and cannot be used in transactions. Item attributes will be copied over into the variants unless 'No Copy' is set"), true);
+
 			frm.add_custom_button(__("Show Variants"), function() {
 				frappe.set_route("List", "Item", {"variant_of": frm.doc.name});
 			}, __("View"));
 
+			frm.add_custom_button(__("Item Variant Settings"), function() {
+				frappe.set_route("Form", "Item Variant Settings");
+			}, __("View"));
+
 			frm.add_custom_button(__("Variant Details Report"), function() {
 				frappe.set_route("query-report", "Item Variant Details", {"item": frm.doc.name});
 			}, __("View"));
@@ -110,6 +115,13 @@
 					}
 				});
 			}, __('Actions'));
+		} else {
+			frm.add_custom_button(__("Website Item"), function() {
+				frappe.db.get_value("Website Item", {item_code: frm.doc.name}, "name", (d) => {
+					if (!d.name) frappe.throw(__("Website Item not found"));
+					frappe.set_route("Form", "Website Item", d.name);
+				});
+			}, __("View"));
 		}
 
 		erpnext.item.edit_prices_button(frm);
@@ -131,12 +143,6 @@
 			frappe.set_route('Form', 'Item', new_item.name);
 		});
 
-		if(frm.doc.has_variants) {
-			frm.add_custom_button(__("Item Variant Settings"), function() {
-				frappe.set_route("Form", "Item Variant Settings");
-			}, __("View"));
-		}
-
 		const stock_exists = (frm.doc.__onload
 			&& frm.doc.__onload.stock_exists) ? 1 : 0;
 
diff --git a/erpnext/stock/doctype/item/item_dashboard.py b/erpnext/stock/doctype/item/item_dashboard.py
index 33acf4b..3caed02 100644
--- a/erpnext/stock/doctype/item/item_dashboard.py
+++ b/erpnext/stock/doctype/item/item_dashboard.py
@@ -32,5 +32,6 @@
 			{"label": _("Manufacture"), "items": ["Production Plan", "Work Order", "Item Manufacturer"]},
 			{"label": _("Traceability"), "items": ["Serial No", "Batch"]},
 			{"label": _("Move"), "items": ["Stock Entry"]},
+			{"label": _("E-commerce"), "items": ["Website Item"]},
 		],
 	}