Merge pull request #26473 from deepeshgarg007/bootstrapped_gst_setup_develop

feat(India): Bootstrapped GST Setup
diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
index e15715d..6b9df41 100644
--- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
+++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
@@ -75,7 +75,8 @@
 		select voucher_no, credit
 		from `tabGL Entry`
 		where party in (%s) and credit > 0
-			and company=%s and posting_date between %s and %s
+			and company=%s and is_cancelled = 0
+			and posting_date between %s and %s
 	""", (supplier, company, from_date, to_date), as_dict=1)
 
 	supplier_credit_amount = flt(sum(d.credit for d in entries))
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 39a6024..5976e01 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -77,9 +77,6 @@
 		if flt(self.progress or 0) > 100:
 			frappe.throw(_("Progress % for a task cannot be more than 100."))
 
-		if flt(self.progress) == 100:
-			self.status = 'Completed'
-
 		if self.status == 'Completed':
 			self.progress = 100
 
diff --git a/erpnext/public/js/help_links.js b/erpnext/public/js/help_links.js
index 5c9a453..d0c935f 100644
--- a/erpnext/public/js/help_links.js
+++ b/erpnext/public/js/help_links.js
@@ -54,7 +54,7 @@
 
 frappe.help.help_links["Form/System Settings"] = [
 	{
-		label: "Naming Series",
+		label: "System Settings",
 		url: docsUrl + "user/manual/en/setting-up/settings/system-settings",
 	},
 ];
@@ -206,7 +206,7 @@
 		label: "PayPal Settings",
 		url:
 			docsUrl +
-			"user/manual/en/setting-up/integrations/paypal-integration",
+			"user/manual/en/erpnext_integration/paypal-integration",
 	},
 ];
 
@@ -215,14 +215,14 @@
 		label: "Razorpay Settings",
 		url:
 			docsUrl +
-			"user/manual/en/setting-up/integrations/razorpay-integration",
+			"user/manual/en/erpnext_integration/razorpay-integration",
 	},
 ];
 
 frappe.help.help_links["Form/Dropbox Settings"] = [
 	{
 		label: "Dropbox Settings",
-		url: docsUrl + "user/manual/en/setting-up/integrations/dropbox-backup",
+		url: docsUrl + "user/manual/en/erpnext_integration/dropbox-backup",
 	},
 ];
 
@@ -230,7 +230,7 @@
 	{
 		label: "LDAP Settings",
 		url:
-			docsUrl + "user/manual/en/setting-up/integrations/ldap-integration",
+			docsUrl + "user/manual/en/erpnext_integration/ldap-integration",
 	},
 ];
 
@@ -239,7 +239,7 @@
 		label: "Stripe Settings",
 		url:
 			docsUrl +
-			"user/manual/en/setting-up/integrations/stripe-integration",
+			"user/manual/en/erpnext_integration/stripe-integration",
 	},
 ];
 
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index cb939e6..93482e8 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -89,17 +89,16 @@
 		if item_det.is_stock_item != 1:
 			frappe.throw(_("Item {0} must be a stock Item").format(self.item_code))
 
-		# check if batch number is required
-		if self.voucher_type != 'Stock Reconciliation':
-			if item_det.has_batch_no == 1:
-				batch_item = self.item_code if self.item_code == item_det.item_name else self.item_code + ":" +  item_det.item_name
-				if not self.batch_no:
-					frappe.throw(_("Batch number is mandatory for Item {0}").format(batch_item))
-				elif not frappe.db.get_value("Batch",{"item": self.item_code, "name": self.batch_no}):
-					frappe.throw(_("{0} is not a valid Batch Number for Item {1}").format(self.batch_no, batch_item))
+		# check if batch number is valid
+		if item_det.has_batch_no == 1:
+			batch_item = self.item_code if self.item_code == item_det.item_name else self.item_code + ":" + item_det.item_name
+			if not self.batch_no:
+				frappe.throw(_("Batch number is mandatory for Item {0}").format(batch_item))
+			elif not frappe.db.get_value("Batch",{"item": self.item_code, "name": self.batch_no}):
+				frappe.throw(_("{0} is not a valid Batch Number for Item {1}").format(self.batch_no, batch_item))
 
-			elif item_det.has_batch_no == 0 and self.batch_no and self.is_cancelled == 0:
-				frappe.throw(_("The Item {0} cannot have Batch").format(self.item_code))
+		elif item_det.has_batch_no == 0 and self.batch_no and self.is_cancelled == 0:
+			frappe.throw(_("The Item {0} cannot have Batch").format(self.item_code))
 
 		if item_det.has_variants:
 			frappe.throw(_("Stock cannot exist for Item {0} since has variants").format(self.item_code),
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index 76a3f1a..4540954 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -17,6 +17,14 @@
 				}
 			}
 		});
+		frm.set_query("batch_no", "items", function(doc, cdt, cdn) {
+			var item = locals[cdt][cdn];
+			return {
+				filters: {
+					'item': item.item_code
+				}
+			};
+		});
 
 		if (frm.doc.company) {
 			erpnext.queries.setup_queries(frm, "Warehouse", function() {
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index 7b98c7b..cbe413b 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -16,6 +16,7 @@
 from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
 
+
 class TestStockReconciliation(unittest.TestCase):
 	@classmethod
 	def setUpClass(self):
@@ -316,6 +317,26 @@
 		dn2.cancel()
 		pr1.cancel()
 
+	def test_valid_batch(self):
+		create_batch_item_with_batch("Testing Batch Item 1", "001")
+		create_batch_item_with_batch("Testing Batch Item 2", "002")
+		sr = create_stock_reconciliation(item_code="Testing Batch Item 1", qty=1, rate=100, batch_no="002"
+			, do_not_submit=True)
+		self.assertRaises(frappe.ValidationError, sr.submit)
+
+def create_batch_item_with_batch(item_name, batch_id):
+	batch_item_doc = create_item(item_name, is_stock_item=1)
+	if not batch_item_doc.has_batch_no:
+		batch_item_doc.has_batch_no = 1
+		batch_item_doc.create_new_batch = 1
+		batch_item_doc.save(ignore_permissions=True)
+
+	if not frappe.db.exists('Batch', batch_id):
+		b = frappe.new_doc('Batch')
+		b.item = item_name
+		b.batch_id = batch_id
+		b.save()
+
 def insert_existing_sle(warehouse):
 	from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry