Merge pull request #24632 from ankush/ladakh_gst_addition

fix(India): Add GST state code for Ladakh
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py
index 66d0e5f..5f990cd 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py
@@ -20,7 +20,7 @@
 			client_id=self.settings.plaid_client_id,
 			secret=self.settings.get_password("plaid_secret"),
 			environment=self.settings.plaid_env,
-			api_version="2019-05-29"
+			api_version="2020-09-14"
 		)
 
 	def get_access_token(self, public_token):
@@ -29,7 +29,7 @@
 		response = self.client.Item.public_token.exchange(public_token)
 		access_token = response["access_token"]
 		return access_token
-	
+
 	def get_token_request(self, update_mode=False):
 		country_codes = ["US", "CA", "FR", "IE", "NL", "ES", "GB"] if self.settings.enable_european_access else ["US", "CA"]
 		args = {
diff --git a/erpnext/public/images/erpnext-logo.png b/erpnext/public/images/erpnext-logo.png
new file mode 100644
index 0000000..3090727
--- /dev/null
+++ b/erpnext/public/images/erpnext-logo.png
Binary files differ
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index 2623c3c..d49a813 100644
--- a/erpnext/public/js/utils/serial_no_batch_selector.js
+++ b/erpnext/public/js/utils/serial_no_batch_selector.js
@@ -140,6 +140,7 @@
 					() => me.update_batch_serial_no_items(),
 					() => {
 						refresh_field("items");
+						refresh_field("packed_items");
 						if (me.callback) {
 							return me.callback(me.item);
 						}
@@ -154,7 +155,7 @@
 			if (this.item.serial_no) {
 				this.dialog.fields_dict.serial_no.set_value(this.item.serial_no);
 			}
-			
+
 			if (this.has_batch && !this.has_serial_no && d.batch_no) {
 				this.frm.doc.items.forEach(data => {
 					if(data.item_code == d.item_code) {
@@ -231,7 +232,7 @@
 				this.map_row_values(row, batch, 'batch_no',
 					'selected_qty', this.values.warehouse);
 			});
-		} 
+		}
 	},
 
 	update_serial_no_item() {
@@ -250,7 +251,7 @@
 				filters: { 'name': ["in", selected_serial_nos]},
 				fields: ["batch_no", "name"]
 			}).then((data) => {
-				// data = [{batch_no: 'batch-1', name: "SR-001"}, 
+				// data = [{batch_no: 'batch-1', name: "SR-001"},
 				// 	{batch_no: 'batch-2', name: "SR-003"}, {batch_no: 'batch-2', name: "SR-004"}]
 				const batch_serial_map = data.reduce((acc, d) => {
 					if (!acc[d['batch_no']]) acc[d['batch_no']] = [];
@@ -298,6 +299,8 @@
 		} else {
 			row.warehouse = values.warehouse || warehouse;
 		}
+
+		this.frm.dirty();
 	},
 
 	update_total_qty: function() {
diff --git a/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py
index e8a8ed8..ad60db0 100644
--- a/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py
+++ b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py
@@ -5,12 +5,16 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-from frappe.utils import getdate
+from frappe.utils import getdate, get_link_to_form
 from frappe.model.document import Document
 from erpnext.accounts.utils import get_fiscal_year
 
 class LowerDeductionCertificate(Document):
 	def validate(self):
+		self.validate_dates()
+		self.validate_supplier_against_section_code()
+		
+	def validate_dates(self):
 		if getdate(self.valid_upto) < getdate(self.valid_from):
 			frappe.throw(_("Valid Upto date cannot be before Valid From date"))
 
@@ -24,3 +28,20 @@
 			<= fiscal_year.year_end_date):
 			frappe.throw(_("Valid Upto date not in Fiscal Year {0}").format(frappe.bold(self.fiscal_year)))
 
+	def validate_supplier_against_section_code(self):
+		duplicate_certificate = frappe.db.get_value('Lower Deduction Certificate', {'supplier': self.supplier, 'section_code': self.section_code}, ['name', 'valid_from', 'valid_upto'], as_dict=True)
+		if duplicate_certificate and self.are_dates_overlapping(duplicate_certificate):
+			certificate_link = get_link_to_form('Lower Deduction Certificate', duplicate_certificate.name)
+			frappe.throw(_("There is already a valid Lower Deduction Certificate {0} for Supplier {1} against Section Code {2} for this time period.")
+				.format(certificate_link, frappe.bold(self.supplier), frappe.bold(self.section_code)))
+
+	def are_dates_overlapping(self,duplicate_certificate):
+		valid_from = duplicate_certificate.valid_from
+		valid_upto = duplicate_certificate.valid_upto
+		if valid_from <= getdate(self.valid_from) <= valid_upto:
+			return True
+		elif valid_from <= getdate(self.valid_upto) <= valid_upto:
+			return True
+		elif getdate(self.valid_from) <= valid_from and valid_upto <= getdate(self.valid_upto):
+			return True
+		return False
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index e492377..e3b41e6 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -514,7 +514,7 @@
 	make_delivery_note: function() {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
-			frm: me.frm
+			frm: this.frm
 		})
 	},
 
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 95f8c43..8c9c172 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -194,6 +194,8 @@
 			self.process_sle(sle)
 
 	def get_sle_against_current_voucher(self):
+		self.args['time_format'] = '%H:%i:%s'
+
 		return frappe.db.sql("""
 			select
 				*, timestamp(posting_date, posting_time) as "timestamp"
@@ -202,7 +204,7 @@
 			where
 				item_code = %(item_code)s
 				and warehouse = %(warehouse)s
-				and timestamp(posting_date, time_format(posting_time, '%H:%i:%s')) = timestamp(%(posting_date)s, time_format(%(posting_time)s, '%H:%i:%s'))
+				and timestamp(posting_date, time_format(posting_time, %(time_format)s)) = timestamp(%(posting_date)s, time_format(%(posting_time)s, %(time_format)s))
 			order by
 				creation ASC
 			for update
diff --git a/requirements.txt b/requirements.txt
index 4511aa5..5a35236 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,7 +3,7 @@
 gocardless-pro==1.11.0
 googlemaps==3.1.1
 pandas>=1.0.5
-plaid-python==6.0.0
+plaid-python>=7.0.0
 pycountry==19.8.18
 PyGithub==1.44.1
 python-stdnum==1.12
@@ -12,4 +12,4 @@
 tweepy==3.8.0
 Unidecode==1.1.1
 WooCommerce==2.1.1
-pycryptodome==3.9.8
\ No newline at end of file
+pycryptodome==3.9.8