Merge pull request #25828 from Anuja-pawar/issue-summary-report-fix

fix: Add Hold status column in the Issue Summary Report
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
deleted file mode 100644
index 84ecfb1..0000000
--- a/.github/workflows/ci-tests.yml
+++ /dev/null
@@ -1,108 +0,0 @@
-name: CI
-
-on: [pull_request, workflow_dispatch, push]
-
-jobs:
-  test:
-    runs-on: ubuntu-18.04
-
-    strategy:
-      fail-fast: false
-
-      matrix:
-       include:
-        - TYPE: "server"
-          JOB_NAME: "Server"
-          RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-tests --app erpnext --coverage
-        - TYPE: "patch"
-          JOB_NAME: "Patch"
-          RUN_COMMAND: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz &&  bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate
-
-    name: ${{ matrix.JOB_NAME }}
-
-    services:
-      mysql:
-        image: mariadb:10.3
-        env:
-          MYSQL_ALLOW_EMPTY_PASSWORD: YES
-        ports:
-          - 3306:3306
-        options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
-
-    steps:
-      - name: Clone
-        uses: actions/checkout@v2
-
-      - name: Setup Python
-        uses: actions/setup-python@v2
-        with:
-          python-version: 3.6
-
-      - name: Add to Hosts
-        run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
-
-      - name: Cache pip
-        uses: actions/cache@v2
-        with:
-          path: ~/.cache/pip
-          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
-          restore-keys: |
-            ${{ runner.os }}-pip-
-            ${{ runner.os }}-
-      - name: Cache node modules
-        uses: actions/cache@v2
-        env:
-          cache-name: cache-node-modules
-        with:
-          path: ~/.npm
-          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
-          restore-keys: |
-            ${{ runner.os }}-build-${{ env.cache-name }}-
-            ${{ runner.os }}-build-
-            ${{ runner.os }}-
-      - name: Get yarn cache directory path
-        id: yarn-cache-dir-path
-        run: echo "::set-output name=dir::$(yarn cache dir)"
-
-      - uses: actions/cache@v2
-        id: yarn-cache
-        with:
-          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
-          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
-          restore-keys: |
-            ${{ runner.os }}-yarn-
-
-      - name: Install
-        run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
-
-      - name: Run Tests
-        run: ${{ matrix.RUN_COMMAND }}
-        env:
-          TYPE: ${{ matrix.TYPE }}
-
-      - name: Coverage - Pull Request
-        if: matrix.TYPE == 'server' && github.event_name == 'pull_request'
-        run: |
-          cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
-          cd ${GITHUB_WORKSPACE}
-          pip install coveralls==2.2.0
-          pip install coverage==4.5.4
-          coveralls --service=github
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-          COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
-          COVERALLS_SERVICE_NAME: github
-          
-      - name: Coverage - Push
-        if: matrix.TYPE == 'server' && github.event_name == 'push'
-        run: |
-          cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
-          cd ${GITHUB_WORKSPACE}
-          pip install coveralls==2.2.0
-          pip install coverage==4.5.4
-          coveralls --service=github-actions
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-          COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
-          COVERALLS_SERVICE_NAME: github-actions
-
diff --git a/.github/workflows/patch.yml b/.github/workflows/patch.yml
new file mode 100644
index 0000000..7c9e027
--- /dev/null
+++ b/.github/workflows/patch.yml
@@ -0,0 +1,69 @@
+name: Patch
+
+on: [pull_request, workflow_dispatch]
+
+jobs:
+  test:
+    runs-on: ubuntu-18.04
+
+    name: Patch Test
+
+    services:
+      mysql:
+        image: mariadb:10.3
+        env:
+          MYSQL_ALLOW_EMPTY_PASSWORD: YES
+        ports:
+          - 3306:3306
+        options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
+
+    steps:
+      - name: Clone
+        uses: actions/checkout@v2
+
+      - name: Setup Python
+        uses: actions/setup-python@v2
+        with:
+          python-version: 3.6
+
+      - name: Add to Hosts
+        run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
+
+      - name: Cache pip
+        uses: actions/cache@v2
+        with:
+          path: ~/.cache/pip
+          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+          restore-keys: |
+            ${{ runner.os }}-pip-
+            ${{ runner.os }}-
+
+      - name: Cache node modules
+        uses: actions/cache@v2
+        env:
+          cache-name: cache-node-modules
+        with:
+          path: ~/.npm
+          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
+          restore-keys: |
+            ${{ runner.os }}-build-${{ env.cache-name }}-
+            ${{ runner.os }}-build-
+            ${{ runner.os }}-
+
+      - name: Get yarn cache directory path
+        id: yarn-cache-dir-path
+        run: echo "::set-output name=dir::$(yarn cache dir)"
+
+      - uses: actions/cache@v2
+        id: yarn-cache
+        with:
+          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
+          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
+          restore-keys: |
+            ${{ runner.os }}-yarn-
+
+      - name: Install
+        run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
+
+      - name: Run Patch Tests
+        run: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz &&  bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
new file mode 100644
index 0000000..92685e2
--- /dev/null
+++ b/.github/workflows/server-tests.yml
@@ -0,0 +1,110 @@
+name: Server
+
+on: [pull_request, workflow_dispatch]
+
+jobs:
+  test:
+    runs-on: ubuntu-18.04
+
+    strategy:
+      fail-fast: false
+
+      matrix:
+        container: [1, 2, 3]
+
+    name: Python Unit Tests
+
+    services:
+      mysql:
+        image: mariadb:10.3
+        env:
+          MYSQL_ALLOW_EMPTY_PASSWORD: YES
+        ports:
+          - 3306:3306
+        options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
+
+    steps:
+      - name: Clone
+        uses: actions/checkout@v2
+
+      - name: Setup Python
+        uses: actions/setup-python@v2
+        with:
+          python-version: 3.7
+
+      - name: Add to Hosts
+        run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
+
+      - name: Cache pip
+        uses: actions/cache@v2
+        with:
+          path: ~/.cache/pip
+          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+          restore-keys: |
+            ${{ runner.os }}-pip-
+            ${{ runner.os }}-
+
+      - name: Cache node modules
+        uses: actions/cache@v2
+        env:
+          cache-name: cache-node-modules
+        with:
+          path: ~/.npm
+          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
+          restore-keys: |
+            ${{ runner.os }}-build-${{ env.cache-name }}-
+            ${{ runner.os }}-build-
+            ${{ runner.os }}-
+
+      - name: Get yarn cache directory path
+        id: yarn-cache-dir-path
+        run: echo "::set-output name=dir::$(yarn cache dir)"
+
+      - uses: actions/cache@v2
+        id: yarn-cache
+        with:
+          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
+          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
+          restore-keys: |
+            ${{ runner.os }}-yarn-
+
+      - name: Install
+        run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
+
+      - name: Run Tests
+        run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --use-orchestrator --with-coverage
+        env:
+          TYPE: server
+          CI_BUILD_ID: ${{ github.run_id }}
+          ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
+
+      - name: Upload Coverage Data
+        run: |
+          cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
+          cd ${GITHUB_WORKSPACE}
+          pip3 install coverage==5.5
+          pip3 install coveralls==3.0.1
+          coveralls
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          COVERALLS_FLAG_NAME: run-${{ matrix.container }}
+          COVERALLS_SERVICE_NAME: ${{ github.event_name == 'pull_request' && 'github' || 'github-actions' }}
+          COVERALLS_PARALLEL: true
+
+  coveralls:
+    name: Coverage Wrap Up
+    needs: test
+    container: python:3-slim
+    runs-on: ubuntu-18.04
+    steps:
+      - name: Clone
+        uses: actions/checkout@v2
+
+      - name: Coveralls Finished
+        run: |
+          cd ${GITHUB_WORKSPACE}
+          pip3 install coverage==5.5
+          pip3 install coveralls==3.0.1
+          coveralls --finish
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
index 0ebf0eb..7cd1e77 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
@@ -27,7 +27,7 @@
 		exists = frappe.db.get_value("Accounting Dimension", {'document_type': self.document_type}, ['name'])
 
 		if exists and self.is_new():
-			frappe.throw("Document Type already used as a dimension")
+			frappe.throw(_("Document Type already used as a dimension"))
 
 		if not self.is_new():
 			self.validate_document_type_change()
diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
index fc1d7e3..e657a9a 100644
--- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
@@ -7,7 +7,8 @@
 import unittest
 from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
 from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
-from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import delete_accounting_dimension
+
+test_dependencies = ['Cost Center', 'Location', 'Warehouse', 'Department']
 
 class TestAccountingDimension(unittest.TestCase):
 	def setUp(self):
diff --git a/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py b/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py
index 7877abd..7f6254f 100644
--- a/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py
+++ b/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py
@@ -9,6 +9,8 @@
 from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import create_dimension, disable_dimension
 from erpnext.exceptions import InvalidAccountDimensionError, MandatoryAccountDimensionError
 
+test_dependencies = ['Location', 'Cost Center', 'Department']
+
 class TestAccountingDimensionFilter(unittest.TestCase):
 	def setUp(self):
 		create_dimension()
diff --git a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
index 10cd939..dc472c7 100644
--- a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
+++ b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
@@ -10,6 +10,8 @@
 from erpnext.accounts.doctype.accounting_period.accounting_period import OverlapError
 from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
 
+test_dependencies = ['Item']
+
 class TestAccountingPeriod(unittest.TestCase):
 	def test_overlap(self):
 		ap1 = create_accounting_period(start_date = "2018-04-01",
@@ -38,7 +40,7 @@
 	accounting_period.start_date = args.start_date or nowdate()
 	accounting_period.end_date = args.end_date or add_months(nowdate(), 1)
 	accounting_period.company = args.company or "_Test Company"
-	accounting_period.period_name =args.period_name or  "_Test_Period_Name_1"
+	accounting_period.period_name = args.period_name or "_Test_Period_Name_1"
 	accounting_period.append("closed_documents", {
 		"document_type": 'Sales Invoice', "closed": 1
 	})
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
index 4d33880..ac4a2d6 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
@@ -5,6 +5,7 @@
 
 from __future__ import unicode_literals
 import frappe
+from frappe import _
 from frappe.utils import cint
 from frappe.model.document import Document
 from frappe.custom.doctype.property_setter.property_setter import make_property_setter
@@ -24,7 +25,7 @@
 	def validate_stale_days(self):
 		if not self.allow_stale and cint(self.stale_days) <= 0:
 			frappe.msgprint(
-				"Stale Days should start from 1.", title='Error', indicator='red',
+				_("Stale Days should start from 1."), title='Error', indicator='red',
 				raise_exception=1)
 
 	def enable_payment_schedule_in_print(self):
diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py
index c5ec23c..603e21e 100644
--- a/erpnext/accounts/doctype/budget/test_budget.py
+++ b/erpnext/accounts/doctype/budget/test_budget.py
@@ -11,6 +11,8 @@
 from erpnext.accounts.doctype.budget.budget import get_actual_expense, BudgetError
 from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
 
+test_dependencies = ['Monthly Distribution']
+
 class TestBudget(unittest.TestCase):
 	def test_monthly_budget_crossed_ignore(self):
 		set_total_expense_zero(nowdate(), "cost_center")
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
index f96f591..ef44626 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
@@ -22,7 +22,7 @@
 		'allow_account_creation_against_child_company'])
 
 	if parent_company and (not allow_account_creation_against_child_company):
-		msg = _("{} is a child company. ").format(frappe.bold(company))
+		msg = _("{} is a child company.").format(frappe.bold(company)) + " "
 		msg += _("Please import accounts against parent company or enable {} in company master.").format(
 			frappe.bold('Allow Account Creation Against Child Company'))
 		frappe.throw(msg, title=_('Wrong Company'))
@@ -56,7 +56,7 @@
 	extension = extension.lstrip(".")
 
 	if extension not in ('csv',  'xlsx', 'xls'):
-		frappe.throw("Only CSV and Excel files can be used to for importing data. Please check the file format you are trying to upload")
+		frappe.throw(_("Only CSV and Excel files can be used to for importing data. Please check the file format you are trying to upload"))
 
 	return  file_doc, extension
 
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index c5ce514..e2d4d82 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -29,7 +29,7 @@
 		self.assertEqual(round(amounts.get('interest_amount'), 2), 0.44)
 		self.assertEqual(round(amounts.get('dunning_amount'), 2), 20.44)
 		self.assertEqual(round(amounts.get('grand_total'), 2), 120.44)
-	
+
 	def test_gl_entries(self):
 		dunning = create_dunning()
 		dunning.submit()
diff --git a/erpnext/accounts/doctype/journal_entry/regional/india.js b/erpnext/accounts/doctype/journal_entry/regional/india.js
new file mode 100644
index 0000000..75a69ac
--- /dev/null
+++ b/erpnext/accounts/doctype/journal_entry/regional/india.js
@@ -0,0 +1,17 @@
+frappe.ui.form.on("Journal Entry", {
+	refresh: function(frm) {
+		frm.set_query('company_address', function(doc) {
+			if(!doc.company) {
+				frappe.throw(__('Please set Company'));
+			}
+
+			return {
+				query: 'frappe.contacts.doctype.address.address.address_query',
+				filters: {
+					link_doctype: 'Company',
+					link_name: doc.company
+				}
+			};
+		});
+	}
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index aedf1c6..556f49d 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -152,7 +152,7 @@
 			frappe.throw(_("Valid from date must be less than valid upto date"))
 
 	def validate_condition(self):
-		if self.condition and ("=" in self.condition) and re.match("""[\w\.:_]+\s*={1}\s*[\w\.@'"]+""", self.condition):
+		if self.condition and ("=" in self.condition) and re.match(r'[\w\.:_]+\s*={1}\s*[\w\.@\'"]+', self.condition):
 			frappe.throw(_("Invalid condition expression"))
 
 #--------------------------------------------------------------------------------
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
index 6dc4643..088c190 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
@@ -19,7 +19,7 @@
 							frappe.show_alert({message: __('Emails Queued'), indicator: 'blue'});
 						}
 						else{
-							frappe.msgprint('No Records for these settings.')
+							frappe.msgprint(__('No Records for these settings.'))
 						}
 					}
 				});
@@ -33,7 +33,7 @@
 					type: 'GET',
 					success: function(result) {
 						if(jQuery.isEmptyObject(result)){
-							frappe.msgprint('No Records for these settings.');
+							frappe.msgprint(__('No Records for these settings.'));
 						}
 						else{
 							window.location = url;
@@ -92,7 +92,7 @@
 							frm.refresh_field('customers');
 						}
 						else{
-							frappe.throw('No Customers found with selected options.');
+							frappe.throw(__('No Customers found with selected options.'));
 						}
 					}
 				}
@@ -129,4 +129,4 @@
 			}
 		})
 	}
-});
\ No newline at end of file
+});
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
index 2ad455c..0b0ee90 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
@@ -94,7 +94,7 @@
 			continue
 
 		html = frappe.render_template(template_path, \
-			{"filters": filters, "data": res, "ageing": ageing[0] if doc.include_ageing else None,
+			{"filters": filters, "data": res, "ageing": ageing[0] if (doc.include_ageing and ageing) else None,
 				"letter_head": letter_head if doc.letter_head else None,
 				"terms_and_conditions": frappe.db.get_value('Terms and Conditions', doc.terms_and_conditions, 'terms')
 					if doc.terms_and_conditions else None})
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 66be11f..53db689 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -636,8 +636,8 @@
 
 	def test_rejected_serial_no(self):
 		pi = make_purchase_invoice(item_code="_Test Serialized Item With Series", received_qty=2, qty=1,
-			rejected_qty=1, rate=500, update_stock=1,
-			rejected_warehouse = "_Test Rejected Warehouse - _TC")
+			rejected_qty=1, rate=500, update_stock=1, rejected_warehouse = "_Test Rejected Warehouse - _TC",
+			allow_zero_valuation_rate=1)
 
 		self.assertEqual(frappe.db.get_value("Serial No", pi.get("items")[0].serial_no, "warehouse"),
 			pi.get("items")[0].warehouse)
@@ -994,7 +994,8 @@
 		"project": args.project,
 		"rejected_warehouse": args.rejected_warehouse or "",
 		"rejected_serial_no": args.rejected_serial_no or "",
-		"asset_location": args.location or ""
+		"asset_location": args.location or "",
+		"allow_zero_valuation_rate": args.get("allow_zero_valuation_rate") or 0
 	})
 
 	if args.get_taxes_and_charges:
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 30a270c..3cd4b80 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -566,7 +566,7 @@
 		doc = make_invoice(pr.name)
 
 		self.assertEqual('Asset Received But Not Billed - _TC', doc.items[0].expense_account)
-	
+
 	def test_asset_cwip_toggling_cases(self):
 		cwip = frappe.db.get_value("Asset Category", "Computers", "enable_cwip_accounting")
 		name = frappe.db.get_value("Asset Category Account", filters={"parent": "Computers"}, fieldname=["name"])
diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
index 6900938..c1fc6fb 100644
--- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
+++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
@@ -9,12 +9,12 @@
 from erpnext.buying.report.subcontracted_raw_materials_to_be_transferred.subcontracted_raw_materials_to_be_transferred import execute
 import json, frappe, unittest
 
-class TestSubcontractedItemToBeReceived(unittest.TestCase):
+class TestSubcontractedItemToBeTransferred(unittest.TestCase):
 
-	def test_pending_and_received_qty(self):
+	def test_pending_and_transferred_qty(self):
 		po = create_purchase_order(item_code='_Test FG Item', is_subcontracted='Yes')
-		make_stock_entry(item_code='_Test Item', target='_Test Warehouse 1 - _TC', qty=100, basic_rate=100)
-		make_stock_entry(item_code='_Test Item Home Desktop 100', target='_Test Warehouse 1 - _TC', qty=100, basic_rate=100)
+		make_stock_entry(item_code='_Test Item', target='_Test Warehouse - _TC', qty=100, basic_rate=100)
+		make_stock_entry(item_code='_Test Item Home Desktop 100', target='_Test Warehouse - _TC', qty=100, basic_rate=100)
 		transfer_subcontracted_raw_materials(po.name)
 		col, data = execute(filters=frappe._dict({'supplier': po.supplier,
 		   'from_date': frappe.utils.get_datetime(frappe.utils.add_to_date(po.transaction_date, days=-10)),
@@ -38,7 +38,8 @@
 		'warehouse': '_Test Warehouse - _TC', 'rate': 100, 'amount': 200, 'stock_uom': 'Nos'}]
 	rm_item_string = json.dumps(rm_item)
 	se = frappe.get_doc(make_rm_stock_entry(po, rm_item_string))
+	se.from_warehouse = '_Test Warehouse 1 - _TC'
 	se.to_warehouse = '_Test Warehouse 1 - _TC'
 	se.stock_entry_type = 'Send to Subcontractor'
 	se.save()
-	se.submit()
\ No newline at end of file
+	se.submit()
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 544e624..f88e8df 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1011,7 +1011,6 @@
 				else:
 					grand_total -= self.get("total_advance")
 					base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total"))
-
 			if total != flt(grand_total, self.precision("grand_total")) or \
 				base_total != flt(base_grand_total, self.precision("base_grand_total")):
 				frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total"))
diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py
index 2009ebf..df73f09 100644
--- a/erpnext/crm/doctype/appointment/appointment.py
+++ b/erpnext/crm/doctype/appointment/appointment.py
@@ -38,7 +38,7 @@
 		number_of_agents = frappe.db.get_single_value('Appointment Booking Settings', 'number_of_agents')
 		if not number_of_agents == 0:
 			if (number_of_appointments_in_same_slot >= number_of_agents):
-				frappe.throw('Time slot is not available')
+				frappe.throw(_('Time slot is not available'))
 		# Link lead
 		if not self.party:
 			lead = self.find_lead_by_email()
@@ -75,10 +75,10 @@
 						subject=_('Appointment Confirmation'))
 		if frappe.session.user == "Guest":
 			frappe.msgprint(
-				'Please check your email to confirm the appointment')
+				_('Please check your email to confirm the appointment'))
 		else :
 			frappe.msgprint(
-				'Appointment was created. But no lead was found. Please check the email to confirm')
+				_('Appointment was created. But no lead was found. Please check the email to confirm'))
 
 	def on_change(self):
 		# Sync Calendar
@@ -91,7 +91,7 @@
 
 	def set_verified(self, email):
 		if not email == self.customer_email:
-			frappe.throw('Email verification failed.')
+			frappe.throw(_('Email verification failed.'))
 		# Create new lead
 		self.create_lead_and_link()
 		# Remove unverified status
@@ -184,7 +184,7 @@
 		appointment_event.insert(ignore_permissions=True)
 		self.calendar_event = appointment_event.name
 		self.save(ignore_permissions=True)
-	
+
 	def _get_verify_url(self):
 		verify_route = '/book_appointment/verify'
 		params = {
diff --git a/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py b/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py
index 6a0dcf4..0f2ea96 100644
--- a/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py
+++ b/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py
@@ -75,7 +75,7 @@
 		"""Validates if Course Start Date is greater than Course End Date"""
 		if self.course_start_date > self.course_end_date:
 			frappe.throw(
-				"Course Start Date cannot be greater than Course End Date.")
+				_("Course Start Date cannot be greater than Course End Date."))
 
 	def delete_course_schedule(self, rescheduled, reschedule_errors):
 		"""Delete all course schedule within the Date range and specified filters"""
diff --git a/erpnext/education/doctype/fees/test_fees.py b/erpnext/education/doctype/fees/test_fees.py
index eedc2ae..c6bb704 100644
--- a/erpnext/education/doctype/fees/test_fees.py
+++ b/erpnext/education/doctype/fees/test_fees.py
@@ -9,8 +9,7 @@
 from frappe.utils.make_random import get_random
 from erpnext.education.doctype.program.test_program import make_program_and_linked_courses
 
-# test_records = frappe.get_test_records('Fees')
-
+test_dependencies = ['Company']
 class TestFees(unittest.TestCase):
 
 	def test_fees(self):
diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py
index 2dc0f63..6be9e71 100644
--- a/erpnext/education/doctype/student/student.py
+++ b/erpnext/education/doctype/student/student.py
@@ -74,7 +74,6 @@
 			student_user.flags.ignore_permissions = True
 			student_user.add_roles("Student")
 			student_user.save()
-			update_password_link = student_user.reset_password()
 
 	def update_applicant_status(self):
 		"""Updates Student Applicant status to Admitted"""
diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py
index d370fbc..3c2e59a 100644
--- a/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py
+++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py
@@ -81,7 +81,7 @@
 		integration_request.reload()
 		self.assertEqual(pos_invoice.mpesa_receipt_number, "LGR7OWQX0R")
 		self.assertEqual(integration_request.status, "Completed")
-		
+
 		frappe.db.set_value("Customer", "_Test Customer", "default_currency", "")
 		integration_request.delete()
 		pr.reload()
@@ -139,7 +139,7 @@
 		pr.cancel()
 		pr.delete()
 		pos_invoice.delete()
-	
+
 	def test_processing_of_only_one_succes_callback_payload(self):
 		create_mpesa_settings(payment_gateway_name="Payment")
 		mpesa_account = frappe.db.get_value("Payment Gateway Account", {"payment_gateway": 'Mpesa-Payment'}, "payment_account")
diff --git a/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
index d079bed..113fa51 100644
--- a/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
+++ b/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
@@ -29,7 +29,7 @@
 		self.assertEqual(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'Completed')
 
 		patient, medical_department, practitioner = create_healthcare_docs()
-		appointment = create_appointment(patient, practitioner, nowdate())		
+		appointment = create_appointment(patient, practitioner, nowdate())
 		session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company', appointment.name)
 		session = frappe.get_doc(session)
 		session.submit()
diff --git a/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py b/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py
index 6e151d0..03b0cf3 100644
--- a/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py
+++ b/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py
@@ -5,11 +5,18 @@
 
 import frappe
 import unittest
+import erpnext
 from frappe.utils import getdate
 from erpnext.hr.doctype.upload_attendance.upload_attendance import get_data
 from erpnext.hr.doctype.employee.test_employee import make_employee
 
+test_dependencies = ['Holiday List']
+
 class TestUploadAttendance(unittest.TestCase):
+	@classmethod
+	def setUpClass(cls):
+		frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", '_Test Holiday List')
+
 	def test_date_range(self):
 		employee = make_employee("test_employee@company.com")
 		employee_doc = frappe.get_doc("Employee", employee)
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index 230475f..69d11a8 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -264,7 +264,7 @@
 	pending_amount = amounts['pending_principal_amount']
 
 	if amount and (amount > pending_amount):
-		frappe.throw('Write Off amount cannot be greater than pending loan amount')
+		frappe.throw(_('Write Off amount cannot be greater than pending loan amount'))
 
 	if not amount:
 		amount = pending_amount
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index a6086fb..3e5a72d 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -76,9 +76,9 @@
 		frm.set_query("production_item", function() {
 			return {
 				query: "erpnext.controllers.queries.item_query",
-				filters:[
-					['is_stock_item', '=',1]
-				]
+				filters: {
+					"is_stock_item": 1,
+				}
 			};
 		});
 
diff --git a/erpnext/non_profit/doctype/member/member.py b/erpnext/non_profit/doctype/member/member.py
index efc072e..30be585 100644
--- a/erpnext/non_profit/doctype/member/member.py
+++ b/erpnext/non_profit/doctype/member/member.py
@@ -28,7 +28,7 @@
 	def setup_subscription(self):
 		non_profit_settings = frappe.get_doc('Non Profit Settings')
 		if not non_profit_settings.enable_razorpay_for_memberships:
-			frappe.throw('Please check Enable Razorpay for Memberships in {0} to setup subscription').format(
+			frappe.throw(_('Please check Enable Razorpay for Memberships in {0} to setup subscription')).format(
 				get_link_to_form('Non Profit Settings', 'Non Profit Settings'))
 
 		controller = get_payment_gateway_controller("Razorpay")
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.json b/erpnext/payroll/doctype/additional_salary/additional_salary.json
index 5e17a5c..d9efe45 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.json
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.json
@@ -7,25 +7,30 @@
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
+  "employee_details_section",
   "naming_series",
   "employee",
   "employee_name",
-  "salary_component",
-  "type",
-  "amount",
-  "ref_doctype",
-  "ref_docname",
-  "amended_from",
   "column_break_5",
   "company",
   "department",
+  "salary_details_section",
+  "salary_component",
+  "type",
   "currency",
+  "amount",
+  "column_break_13",
+  "is_recurring",
+  "payroll_date",
   "from_date",
   "to_date",
-  "payroll_date",
-  "is_recurring",
+  "properties_and_references_section",
+  "deduct_full_tax_on_selected_payroll_date",
+  "ref_doctype",
+  "ref_docname",
+  "column_break_22",
   "overwrite_salary_structure_amount",
-  "deduct_full_tax_on_selected_payroll_date"
+  "amended_from"
  ],
  "fields": [
   {
@@ -81,7 +86,7 @@
   },
   {
    "depends_on": "eval:(doc.is_recurring==0)",
-   "description": "Date on which this component is applied",
+   "description": "The date on which Salary Component with Amount will contribute for Earnings/Deduction in Salary Slip. ",
    "fieldname": "payroll_date",
    "fieldtype": "Date",
    "in_list_view": 1,
@@ -159,6 +164,7 @@
    "fieldname": "ref_docname",
    "fieldtype": "Dynamic Link",
    "label": "Reference Document",
+   "no_copy": 1,
    "options": "ref_doctype",
    "read_only": 1
   },
@@ -171,11 +177,34 @@
    "print_hide": 1,
    "read_only": 1,
    "reqd": 1
+  },
+  {
+   "fieldname": "employee_details_section",
+   "fieldtype": "Section Break",
+   "label": "Employee Details"
+  },
+  {
+   "fieldname": "column_break_13",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_22",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "salary_details_section",
+   "fieldtype": "Section Break",
+   "label": "Salary Details"
+  },
+  {
+   "fieldname": "properties_and_references_section",
+   "fieldtype": "Section Break",
+   "label": "Properties and References"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2021-03-31 22:33:59.098532",
+ "modified": "2021-05-26 11:10:00.812698",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Additional Salary",
diff --git a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
index 7528bf7..b80b320 100644
--- a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
@@ -15,7 +15,13 @@
 from erpnext.loan_management.doctype.loan.test_loan import create_loan, make_loan_disbursement_entry, create_loan_type, create_loan_accounts
 from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
 
+test_dependencies = ['Holiday List']
+
 class TestPayrollEntry(unittest.TestCase):
+	@classmethod
+	def setUpClass(cls):
+		frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", '_Test Holiday List')
+
 	def setUp(self):
 		for dt in ["Salary Slip", "Salary Component", "Salary Component Account",
 			"Payroll Entry", "Salary Structure", "Salary Structure Assignment", "Payroll Employee Detail", "Additional Salary"]:
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index e153e6c..ad1976d 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -953,15 +953,15 @@
 				(this.frm.doc.payment_schedule && this.frm.doc.payment_schedule.length)) {
 				var message1 = "";
 				var message2 = "";
-				var final_message = "Please clear the ";
+				var final_message = __("Please clear the") + " ";
 
 				if (this.frm.doc.payment_terms_template) {
-					message1 = "selected Payment Terms Template";
+					message1 = __("selected Payment Terms Template");
 					final_message = final_message + message1;
 				}
 
 				if ((this.frm.doc.payment_schedule || []).length) {
-					message2 = "Payment Schedule Table";
+					message2 = __("Payment Schedule Table");
 					if (message1.length !== 0) message2 = " and " + message2;
 					final_message = final_message + message2;
 				}
diff --git a/erpnext/public/js/help_links.js b/erpnext/public/js/help_links.js
index e789923..aa9bba1 100644
--- a/erpnext/public/js/help_links.js
+++ b/erpnext/public/js/help_links.js
@@ -644,14 +644,14 @@
 frappe.help.help_links["List/Asset"] = [
 	{
 		label: "Managing Fixed Assets",
-		url: docsUrl + "user/manual/en/accounts/managing-fixed-assets",
+		url: docsUrl + "user/manual/en/accounts/opening-balance/fixed_assets",
 	},
 ];
 
 frappe.help.help_links["List/Asset Category"] = [
 	{
 		label: "Asset Category",
-		url: docsUrl + "user/manual/en/accounts/managing-fixed-assets",
+		url: docsUrl + "user/manual/en/asset/asset-category",
 	},
 ];
 
@@ -663,7 +663,7 @@
 	{ label: "Item", url: docsUrl + "user/manual/en/stock/item" },
 	{
 		label: "Item Price",
-		url: docsUrl + "user/manual/en/stock/item/item-price",
+		url: docsUrl + "user/manual/en/stock/item-price",
 	},
 	{
 		label: "Barcode",
@@ -672,25 +672,25 @@
 	},
 	{
 		label: "Item Wise Taxation",
-		url: docsUrl + "user/manual/en/accounts/item-wise-taxation",
+		url: docsUrl + "user/manual/en/accounts/item-tax-template",
 	},
 	{
 		label: "Managing Fixed Assets",
-		url: docsUrl + "user/manual/en/accounts/managing-fixed-assets",
+		url: docsUrl + "user/manual/en/accounts/opening-balance/fixed_assets",
 	},
 	{
 		label: "Item Codification",
-		url: docsUrl + "user/manual/en/stock/item/item-codification",
+		url: docsUrl + "user/manual/en/stock/articles/item-codification",
 	},
 	{
 		label: "Item Variants",
-		url: docsUrl + "user/manual/en/stock/item/item-variants",
+		url: docsUrl + "user/manual/en/stock/item-variants",
 	},
 	{
 		label: "Item Valuation",
 		url:
 			docsUrl +
-			"user/manual/en/stock/item/item-valuation-fifo-and-moving-average",
+			"user/manual/en/stock/articles/item-valuation-fifo-and-moving-average",
 	},
 ];
 
@@ -698,7 +698,7 @@
 	{ label: "Item", url: docsUrl + "user/manual/en/stock/item" },
 	{
 		label: "Item Price",
-		url: docsUrl + "user/manual/en/stock/item/item-price",
+		url: docsUrl + "user/manual/en/stock/item-price",
 	},
 	{
 		label: "Barcode",
@@ -707,19 +707,19 @@
 	},
 	{
 		label: "Item Wise Taxation",
-		url: docsUrl + "user/manual/en/accounts/item-wise-taxation",
+		url: docsUrl + "user/manual/en/accounts/item-tax-template",
 	},
 	{
 		label: "Managing Fixed Assets",
-		url: docsUrl + "user/manual/en/accounts/managing-fixed-assets",
+		url: docsUrl + "user/manual/en/accounts/opening-balance/fixed_assets",
 	},
 	{
 		label: "Item Codification",
-		url: docsUrl + "user/manual/en/stock/item/item-codification",
+		url: docsUrl + "user/manual/en/stock/articles/item-codification",
 	},
 	{
 		label: "Item Variants",
-		url: docsUrl + "user/manual/en/stock/item/item-variants",
+		url: docsUrl + "user/manual/en/stock/item-variants",
 	},
 	{
 		label: "Item Valuation",
diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss
index 159a8a4..9402cf9 100644
--- a/erpnext/public/scss/shopping_cart.scss
+++ b/erpnext/public/scss/shopping_cart.scss
@@ -1,4 +1,3 @@
-@import "frappe/public/scss/desk/variables";
 @import "frappe/public/scss/common/mixins";
 
 body.product-page {
@@ -74,15 +73,6 @@
 		}
 	}
 
-	// .card-body {
-	// 	text-align: center;
-	// }
-
-	// .featured-item {
-	// 	.card-body {
-	// 		text-align: left;
-	// 	}
-	// }
 	.card-img-container {
 		height: 210px;
 		width: 100%;
@@ -217,12 +207,12 @@
 		border-color: var(--table-border-color) !important;
 		padding: 15px;
 
-		@include media-breakpoint-between(xs, md) {
+		@media (max-width: var(--md-width)) {
 			height: 300px;
 			width: 300px;
 		}
 
-		@include media-breakpoint-up(lg) {
+		@media (min-width: var(--lg-width)) {
 			height: 350px;
 			width: 350px;
 		}
@@ -233,11 +223,12 @@
 	}
 
 	.item-slideshow {
-		@include media-breakpoint-between(xs, md) {
+
+		@media (max-width: var(--md-width)) {
 			max-height: 320px;
 		}
 
-		@include media-breakpoint-up(lg) {
+		@media (min-width: var(--lg-width)) {
 			max-height: 430px;
 		}
 
@@ -254,7 +245,7 @@
 		cursor: pointer;
 
 		&:hover, &.active {
-			border-color: $primary;
+			border-color: var(--primary);
 		}
 	}
 
@@ -316,12 +307,9 @@
 }
 
 .item-group-slideshow {
-	.item-group-description {
-		// max-width: 900px;
-	}
 
 	.carousel-inner.rounded-carousel {
-		border-radius: $card-border-radius;
+		border-radius: var(--card-border-radius);
 	}
 }
 
diff --git a/erpnext/public/scss/website.scss b/erpnext/public/scss/website.scss
index 56b717c..f4325c0 100644
--- a/erpnext/public/scss/website.scss
+++ b/erpnext/public/scss/website.scss
@@ -1,4 +1,3 @@
-@import "frappe/public/scss/website/variables";
 
 .filter-options {
 	max-height: 300px;
@@ -14,7 +13,7 @@
 	}
 
 	&.active {
-		border-color: $primary;
+		border-color: var(--primary);
 
 		.check {
 			display: inline-flex;
@@ -25,7 +24,7 @@
 .check {
 	display: inline-flex;
 	padding: 0.25rem;
-	background: $primary;
+	background: var(--primary);
 	color: white;
 	border-radius: 50%;
 	font-size: 12px;
@@ -38,12 +37,12 @@
 }
 
 .result {
-	border-bottom: 1px solid $border-color;
+	border-bottom: 1px solid var(--border-color);
 }
 
 .transaction-list-item {
 	padding: 1rem 0;
-	border-top: 1px solid $border-color;
+	border-top: 1px solid var(--border-color);
 	position: relative;
 
 	a.transaction-item-link {
diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
index 3ddcc58..6415204 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
@@ -310,7 +310,7 @@
 								self.report_dict['sup_details']['osup_det']['txval'] += taxable_value
 
 								gst_category = self.invoice_detail_map.get(inv, {}).get('gst_category')
-								place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply', '00-Other Territory')
+								place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply') or '00-Other Territory'
 
 								if gst_category in ['Unregistered', 'Registered Composition', 'UIN Holders'] and \
 								self.gst_details.get("gst_state") != place_of_supply.split("-")[1]:
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index fc227de..075c698 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -500,7 +500,7 @@
 
 		if not isinstance(docname, list):
 			# removes characters not allowed in a filename (https://stackoverflow.com/a/38766141/4767738)
-			filename_prefix = re.sub('[^\w_.)( -]', '', docname)
+			filename_prefix = re.sub(r'[^\w_.)( -]', '', docname)
 
 	frappe.local.response.filename = '{0}_e-WayBill_Data_{1}.json'.format(filename_prefix, frappe.utils.random_string(5))
 
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 1e28a40..b7c0962 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -574,7 +574,7 @@
 def get_json(filters, report_name, data):
 	filters = json.loads(filters)
 	report_data = json.loads(data)
-	gstin = get_company_gstin_number(filters["company"])
+	gstin = get_company_gstin_number(filters["company"], filters["company_address"])
 
 	fp = "%02d%s" % (getdate(filters["to_date"]).month, getdate(filters["to_date"]).year)
 
@@ -810,23 +810,29 @@
 
 	return {"num": int(num), "itm_det": itm_det}
 
-def get_company_gstin_number(company):
-	filters = [
-		["is_your_company_address", "=", 1],
-		["Dynamic Link", "link_doctype", "=", "Company"],
-		["Dynamic Link", "link_name", "=", company],
-		["Dynamic Link", "parenttype", "=", "Address"],
-	]
+def get_company_gstin_number(company, address=None):
+	if address:
+		gstin = frappe.db.get_value("Address", address, "gstin")
 
-	gstin = frappe.get_all("Address", filters=filters, fields=["gstin"])
-
-	if gstin:
-		return gstin[0]["gstin"]
-	else:
-		frappe.throw(_("Please set valid GSTIN No. in Company Address for company {0}").format(
-			frappe.bold(company)
+	if not gstin:
+		filters = [
+			["is_your_company_address", "=", 1],
+			["Dynamic Link", "link_doctype", "=", "Company"],
+			["Dynamic Link", "link_name", "=", company],
+			["Dynamic Link", "parenttype", "=", "Address"],
+		]
+		gstin = frappe.get_all("Address", filters=filters, pluck="gstin")
+		if gstin:
+			gstin[0]
+	
+	if not gstin:
+		address = frappe.bold(address) if address else ""
+		frappe.throw(_("Please set valid GSTIN No. in Company Address {} for company {}").format(
+			address, frappe.bold(company)
 		))
 
+	return gstin
+
 @frappe.whitelist()
 def download_json_file():
 	''' download json content in a file '''
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py
index 750a1a6..cb811df 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -15,7 +15,6 @@
 	data = dict()
 	result = []
 
-	allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
 	warehouse, hide_unavailable_items = frappe.db.get_value('POS Profile', pos_profile, ['warehouse', 'hide_unavailable_items'])
 
 	if not frappe.db.exists('Item Group', item_group):
@@ -62,7 +61,6 @@
 			`tabItem` item {bin_join_selection}
 		WHERE
 			item.disabled = 0
-			AND item.is_stock_item = 1
 			AND item.has_variants = 0
 			AND item.is_sales_item = 1
 			AND item.is_fixed_asset = 0
@@ -84,6 +82,7 @@
 		), {'warehouse': warehouse}, as_dict=1)
 
 	if items_data:
+		items_data = filter_service_items(items_data)
 		items = [d.item_code for d in items_data]
 		item_prices_data = frappe.get_all("Item Price",
 			fields = ["item_code", "price_list_rate", "currency"],
@@ -96,10 +95,7 @@
 		for item in items_data:
 			item_code = item.item_code
 			item_price = item_prices.get(item_code) or {}
-			if allow_negative_stock:
-				item_stock_qty = frappe.db.sql("""select ifnull(sum(actual_qty), 0) from `tabBin` where item_code = %s""", item_code)[0][0]
-			else:
-				item_stock_qty = get_stock_availability(item_code, warehouse)
+			item_stock_qty = get_stock_availability(item_code, warehouse)
 
 			row = {}
 			row.update(item)
@@ -135,6 +131,14 @@
 
 	return {}
 
+def filter_service_items(items):
+	for item in items:
+		if not item['is_stock_item']:
+			if not frappe.db.exists('Product Bundle', item['item_code']):
+				items.remove(item)
+	
+	return items
+
 def get_conditions(item_code, serial_no, batch_no, barcode):
 	if serial_no or batch_no or barcode:
 		return "item.name = {0}".format(frappe.db.escape(item_code))
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index 4f4f1b2..ae3f9e3 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -241,10 +241,8 @@
 			events: {
 				get_frm: () => this.frm,
 
-				cart_item_clicked: (item_code, batch_no, uom) => {
-					const search_field = batch_no ? 'batch_no' : 'item_code';
-					const search_value = batch_no || item_code;
-					const item_row = this.frm.doc.items.find(i => i[search_field] === search_value && i.uom === uom);
+				cart_item_clicked: (item_code, batch_no, uom, rate) => {
+					const item_row = this.get_item_from_frm(item_code, batch_no, uom, rate);
 					this.item_details.toggle_item_details_section(item_row);
 				},
 
@@ -275,18 +273,25 @@
 					this.cart.toggle_numpad(minimize);
 				},
 
-				form_updated: async (cdt, cdn, fieldname, value) => {
+				form_updated: (cdt, cdn, fieldname, value) => {
 					const item_row = frappe.model.get_doc(cdt, cdn);
 					if (item_row && item_row[fieldname] != value) {
 
-						const { item_code, batch_no, uom } = this.item_details.current_item;
+						const { item_code, batch_no, uom, rate } = this.item_details.current_item;
 						const event = {
 							field: fieldname,
 							value,
-							item: { item_code, batch_no, uom }
+							item: { item_code, batch_no, uom, rate }
 						}
 						return this.on_cart_update(event)
 					}
+
+					return Promise.resolve();
+				},
+
+				highlight_cart_item: (item) => {
+					const cart_item = this.cart.get_cart_item(item);
+					this.cart.toggle_item_highlight(cart_item);
 				},
 
 				item_field_focused: (fieldname) => {
@@ -501,8 +506,8 @@
 		let item_row = undefined;
 		try {
 			let { field, value, item } = args;
-			const { item_code, batch_no, serial_no, uom } = item;
-			item_row = this.get_item_from_frm(item_code, batch_no, uom);
+			const { item_code, batch_no, serial_no, uom, rate } = item;
+			item_row = this.get_item_from_frm(item_code, batch_no, uom, rate);
 
 			const item_selected_from_selector = field === 'qty' && value === "+1"
 
@@ -535,7 +540,7 @@
 
 				item_selected_from_selector && (value = flt(value))
 
-				const args = { item_code, batch_no, [field]: value };
+				const args = { item_code, batch_no, rate, [field]: value };
 
 				if (serial_no) {
 					await this.check_serial_no_availablilty(item_code, this.frm.doc.set_warehouse, serial_no);
@@ -550,9 +555,11 @@
 					await this.check_stock_availability(item_row, value, this.frm.doc.set_warehouse);
 
 				await this.trigger_new_item_events(item_row);
-
-				this.check_serial_batch_selection_needed(item_row) && this.edit_item_details_of(item_row);
+				
 				this.update_cart_html(item_row);
+
+				this.item_details.$component.is(':visible') && this.edit_item_details_of(item_row);
+				this.check_serial_batch_selection_needed(item_row) && this.edit_item_details_of(item_row);
 			}
 
 		} catch (error) {
@@ -563,12 +570,13 @@
 		}
 	}
 
-	get_item_from_frm(item_code, batch_no, uom) {
+	get_item_from_frm(item_code, batch_no, uom, rate) {
 		const has_batch_no = batch_no;
 		return this.frm.doc.items.find(
 			i => i.item_code === item_code
 				&& (!has_batch_no || (has_batch_no && i.batch_no === batch_no))
 				&& (i.uom === uom)
+				&& (i.rate == rate)
 		);
 	}
 
diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js
index 11a63b3..f5019f5 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_cart.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js
@@ -184,7 +184,8 @@
 			const item_code = unescape($cart_item.attr('data-item-code'));
 			const batch_no = unescape($cart_item.attr('data-batch-no'));
 			const uom = unescape($cart_item.attr('data-uom'));
-			me.events.cart_item_clicked(item_code, batch_no, uom);
+			const rate = unescape($cart_item.attr('data-rate'));
+			me.events.cart_item_clicked(item_code, batch_no, uom, rate);
 			this.numpad_value = '';
 		});
 
@@ -520,28 +521,34 @@
 		}
 	}
 
-	get_cart_item({ item_code, batch_no, uom }) {
+	get_cart_item({ item_code, batch_no, uom, rate }) {
 		const batch_attr = `[data-batch-no="${escape(batch_no)}"]`;
 		const item_code_attr = `[data-item-code="${escape(item_code)}"]`;
 		const uom_attr = `[data-uom="${escape(uom)}"]`;
+		const rate_attr = `[data-rate="${escape(rate)}"]`;
 
 		const item_selector = batch_no ?
-			`.cart-item-wrapper${batch_attr}${uom_attr}` : `.cart-item-wrapper${item_code_attr}${uom_attr}`;
+			`.cart-item-wrapper${batch_attr}${uom_attr}${rate_attr}` : `.cart-item-wrapper${item_code_attr}${uom_attr}${rate_attr}`;
 
 		return this.$cart_items_wrapper.find(item_selector);
 	}
 
+	get_item_from_frm(item) {
+		const doc = this.events.get_frm().doc;
+		const { item_code, batch_no, uom, rate } = item;
+		const search_field = batch_no ? 'batch_no' : 'item_code';
+		const search_value = batch_no || item_code;
+
+		return doc.items.find(i => i[search_field] === search_value && i.uom === uom && i.rate === rate);
+	}
+
 	update_item_html(item, remove_item) {
 		const $item = this.get_cart_item(item);
 
 		if (remove_item) {
 			$item && $item.next().remove() && $item.remove();
 		} else {
-			const { item_code, batch_no, uom } = item;
-			const search_field = batch_no ? 'batch_no' : 'item_code';
-			const search_value = batch_no || item_code;
-			const item_row = this.events.get_frm().doc.items.find(i => i[search_field] === search_value && i.uom === uom);
-
+			const item_row = this.get_item_from_frm(item);
 			this.render_cart_item(item_row, $item);
 		}
 
@@ -559,7 +566,7 @@
 			this.$cart_items_wrapper.append(
 				`<div class="cart-item-wrapper"
 						data-item-code="${escape(item_data.item_code)}" data-uom="${escape(item_data.uom)}"
-						data-batch-no="${escape(item_data.batch_no || '')}">
+						data-batch-no="${escape(item_data.batch_no || '')}" data-rate="${escape(item_data.rate)}">
 				</div>
 				<div class="seperator"></div>`
 			)
@@ -636,13 +643,23 @@
 		function get_item_image_html() {
 			const { image, item_name } = item_data;
 			if (image) {
-				return `<div class="item-image"><img src="${image}" alt="${image}""></div>`;
+				return `
+					<div class="item-image">
+						<img
+							onerror="cur_pos.cart.handle_broken_image(this)"
+							src="${image}" alt="${frappe.get_abbr(item_name)}"">
+					</div>`;
 			} else {
 				return `<div class="item-image item-abbr">${frappe.get_abbr(item_name)}</div>`;
 			}
 		}
 	}
 
+	handle_broken_image($img) {
+		const item_abbr = $($img).attr('alt');
+		$($img).parent().replaceWith(`<div class="item-image item-abbr">${item_abbr}</div>`);
+	}
+
 	scroll_to_item($item) {
 		if ($item.length === 0) return;
 		const scrollTop = $item.offset().top - this.$cart_items_wrapper.offset().top + this.$cart_items_wrapper.scrollTop();
diff --git a/erpnext/selling/page/point_of_sale/pos_item_details.js b/erpnext/selling/page/point_of_sale/pos_item_details.js
index 32a4556..df62696 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_details.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_details.js
@@ -54,13 +54,24 @@
 		this.$dicount_section = this.$component.find('.discount-section');
 	}
 
-	toggle_item_details_section(item) {
-		const { item_code, batch_no, uom } = this.current_item;
+	has_item_has_changed(item) {
+		const { item_code, batch_no, uom, rate } = this.current_item;
 		const item_code_is_same = item && item_code === item.item_code;
 		const batch_is_same = item && batch_no == item.batch_no;
 		const uom_is_same = item && uom === item.uom;
+		const rate_is_same = item && rate === item.rate;
+		
+		if (!item)
+			return false;
 
-		this.item_has_changed = !item ? false : item_code_is_same && batch_is_same && uom_is_same ? false : true;
+		if (item_code_is_same && batch_is_same && uom_is_same && rate_is_same)
+			return false;
+
+		return true;
+	}
+
+	toggle_item_details_section(item) {
+		this.item_has_changed = this.has_item_has_changed(item);
 
 		this.events.toggle_item_selector(this.item_has_changed);
 		this.toggle_component(this.item_has_changed);
@@ -72,11 +83,12 @@
 			this.item_row = item;
 			this.currency = this.events.get_frm().doc.currency;
 
-			this.current_item = { item_code: item.item_code, batch_no: item.batch_no, uom: item.uom };
+			this.current_item = { item_code: item.item_code, batch_no: item.batch_no, uom: item.uom, rate: item.rate };
 
 			this.render_dom(item);
 			this.render_discount_dom(item);
 			this.render_form(item);
+			this.events.highlight_cart_item(item);
 		} else {
 			this.validate_serial_batch_item();
 			this.current_item = {};
@@ -198,12 +210,14 @@
 			if (this.allow_rate_change) {
 				this.rate_control.df.onchange = function() {
 					if (this.value || flt(this.value) === 0) {
+						me.events.set_value_in_current_cart_item('rate', this.value);
 						me.events.form_updated(me.doctype, me.name, 'rate', this.value).then(() => {
 							const item_row = frappe.get_doc(me.doctype, me.name);
 							const doc = me.events.get_frm().doc;
 							me.$item_price.html(format_currency(item_row.rate, doc.currency));
 							me.render_discount_dom(item_row);
 						});
+						me.current_item.rate = this.value;
 					}
 				};
 			} else {
@@ -292,11 +306,7 @@
 
 		frappe.model.on("POS Invoice Item", "*", (fieldname, value, item_row) => {
 			const field_control = this[`${fieldname}_control`];
-			const { item_code, batch_no, uom } = this.current_item;
-			const item_code_is_same = item_code === item_row.item_code;
-			const batch_is_same = batch_no == item_row.batch_no;
-			const uom_is_same = uom === item_row.uom;
-			const item_is_same = item_code_is_same && batch_is_same && uom_is_same ? true : false;
+			const item_is_same = !this.has_item_has_changed(item_row);
 
 			if (item_is_same && field_control && field_control.get_value() !== value) {
 				field_control.set_value(value);
diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js
index b8a82a9..5b48725 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_selector.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js
@@ -78,7 +78,7 @@
 	get_item_html(item) {
 		const me = this;
 		// eslint-disable-next-line no-unused-vars
-		const { item_image, serial_no, batch_no, barcode, actual_qty, stock_uom } = item;
+		const { item_image, serial_no, batch_no, barcode, actual_qty, stock_uom, price_list_rate } = item;
 		const indicator_color = actual_qty > 10 ? "green" : actual_qty <= 0 ? "red" : "orange";
 
 		let qty_to_display = actual_qty;
@@ -94,7 +94,11 @@
 							<span class="indicator-pill whitespace-nowrap ${indicator_color}">${qty_to_display}</span>
 						</div>
 						<div class="flex items-center justify-center h-32 border-b-grey text-6xl text-grey-100">
-							<img class="h-full" src="${item_image}" alt="${frappe.get_abbr(item.item_name)}" style="object-fit: cover;">
+							<img 
+								onerror="cur_pos.item_selector.handle_broken_image(this)"
+								class="h-full" src="${item_image}"
+								alt="${frappe.get_abbr(item.item_name)}"
+								style="object-fit: cover;">
 						</div>`;
 			} else {
 				return `<div class="item-qty-pill">
@@ -108,6 +112,7 @@
 			`<div class="item-wrapper"
 				data-item-code="${escape(item.item_code)}" data-serial-no="${escape(serial_no)}"
 				data-batch-no="${escape(batch_no)}" data-uom="${escape(stock_uom)}"
+				data-rate="${escape(price_list_rate)}"
 				title="${item.item_name}">
 
 				${get_item_image_html()}
@@ -116,12 +121,17 @@
 					<div class="item-name">
 						${frappe.ellipsis(item.item_name, 18)}
 					</div>
-					<div class="item-rate">${format_currency(item.price_list_rate, item.currency, 0) || 0}</div>
+					<div class="item-rate">${format_currency(price_list_rate, item.currency, 0) || 0}</div>
 				</div>
 			</div>`
 		);
 	}
 
+	handle_broken_image($img) {
+		const item_abbr = $($img).attr('alt');
+		$($img).parent().replaceWith(`<div class="item-display abbr">${item_abbr}</div>`);
+	}
+
 	make_search_bar() {
 		const me = this;
 		const doc = me.events.get_frm().doc;
@@ -213,13 +223,15 @@
 			let batch_no = unescape($item.attr('data-batch-no'));
 			let serial_no = unescape($item.attr('data-serial-no'));
 			let uom = unescape($item.attr('data-uom'));
+			let rate = unescape($item.attr('data-rate'));
 
 			// escape(undefined) returns "undefined" then unescape returns "undefined"
 			batch_no = batch_no === "undefined" ? undefined : batch_no;
 			serial_no = serial_no === "undefined" ? undefined : serial_no;
 			uom = uom === "undefined" ? undefined : uom;
+			rate = rate === "undefined" ? undefined : rate;
 
-			me.events.item_selected({ field: 'qty', value: "+1", item: { item_code, batch_no, serial_no, uom }});
+			me.events.item_selected({ field: 'qty', value: "+1", item: { item_code, batch_no, serial_no, uom, rate }});
 			me.set_search_value('');
 		});
 
diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py
index 8c97322..340d89b 100644
--- a/erpnext/setup/doctype/email_digest/email_digest.py
+++ b/erpnext/setup/doctype/email_digest/email_digest.py
@@ -249,7 +249,7 @@
 				card = cache.get(cache_key)
 
 				if card:
-					card = eval(card)
+					card = frappe.safe_eval(card)
 
 				else:
 					card = frappe._dict(getattr(self, "get_" + key)())
@@ -808,7 +808,6 @@
 			val = balance_on_to_date - balance_before_from_date
 		else:
 			last_year_closing_balance = get_balance_on(account, date=fy_start_date - timedelta(days=1))
-			print(fy_start_date - timedelta(days=1), last_year_closing_balance)
 			val = balance_on_to_date + (last_year_closing_balance - balance_before_from_date)
 
 		return val
@@ -837,4 +836,4 @@
 	elif frequency == "Monthly":
 		to_date = add_to_date(from_date, months=1)
 
-	return from_date, to_date
\ No newline at end of file
+	return from_date, to_date
diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py
index c7220cb..bbee74c 100644
--- a/erpnext/setup/install.py
+++ b/erpnext/setup/install.py
@@ -39,7 +39,7 @@
 	if cint(frappe.db.get_single_value('System Settings', 'setup_complete') or 0):
 		message = """ERPNext can only be installed on a fresh site where the setup wizard is not completed.
 You can reinstall this site (after saving your data) using: bench --site [sitename] reinstall"""
-		frappe.throw(message)
+		frappe.throw(message)   # nosemgrep
 
 
 def set_single_defaults():
diff --git a/erpnext/shopping_cart/test_shopping_cart.py b/erpnext/shopping_cart/test_shopping_cart.py
index d857bf5..ac61aeb 100644
--- a/erpnext/shopping_cart/test_shopping_cart.py
+++ b/erpnext/shopping_cart/test_shopping_cart.py
@@ -7,7 +7,7 @@
 from frappe.utils import nowdate, add_months
 from erpnext.shopping_cart.cart import _get_cart_quotation, update_cart, get_party
 from erpnext.tests.utils import create_test_contact_and_address
-
+from erpnext.accounts.doctype.tax_rule.tax_rule import  ConflictingTaxRule
 
 # test_dependencies = ['Payment Terms Template']
 
@@ -125,7 +125,7 @@
 		tax_rule = frappe.get_test_records("Tax Rule")[0]
 		try:
 			frappe.get_doc(tax_rule).insert()
-		except frappe.DuplicateEntryError:
+		except (frappe.DuplicateEntryError, ConflictingTaxRule):
 			pass
 
 	def create_quotation(self):
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index e5ef978..5095a80 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -297,6 +297,8 @@
 			item_code = "Test Extra Item 1", qty=10, basic_rate=100)
 		se2 = make_stock_entry(target="_Test Warehouse - _TC",
 			item_code = "_Test FG Item", qty=1, basic_rate=100)
+		se3 = make_stock_entry(target="_Test Warehouse - _TC",
+			item_code = "Test Extra Item 2", qty=1, basic_rate=100)
 		rm_items = [
 			{
 				"item_code": item_code,
@@ -331,6 +333,7 @@
 		se.cancel()
 		se1.cancel()
 		se2.cancel()
+		se3.cancel()
 		po.reload()
 		po.cancel()
 
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json
index 7f94591..a0b5457 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.json
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.json
@@ -59,10 +59,6 @@
   "supplier_name",
   "supplier_address",
   "address_display",
-  "column_break_39",
-  "customer",
-  "customer_name",
-  "customer_address",
   "accounting_dimensions_section",
   "project",
   "dimension_col_break",
@@ -435,13 +431,13 @@
   },
   {
    "collapsible": 1,
-   "depends_on": "eval: in_list([\"Sales Return\", \"Purchase Return\", \"Send to Subcontractor\"], doc.purpose)",
+   "depends_on": "eval:doc.purpose === \"Send to Subcontractor\"",
    "fieldname": "contact_section",
    "fieldtype": "Section Break",
-   "label": "Customer or Supplier Details"
+   "label": "Supplier Details"
   },
   {
-   "depends_on": "eval:doc.purpose==\"Purchase Return\" || doc.purpose==\"Send to Subcontractor\"",
+   "depends_on": "eval:doc.purpose === \"Send to Subcontractor\"",
    "fieldname": "supplier",
    "fieldtype": "Link",
    "label": "Supplier",
@@ -453,7 +449,7 @@
   },
   {
    "bold": 1,
-   "depends_on": "eval:doc.purpose==\"Purchase Return\" || doc.purpose==\"Send to Subcontractor\"",
+   "depends_on": "eval:doc.purpose === \"Send to Subcontractor\"",
    "fieldname": "supplier_name",
    "fieldtype": "Data",
    "label": "Supplier Name",
@@ -463,7 +459,7 @@
    "read_only": 1
   },
   {
-   "depends_on": "eval:doc.purpose==\"Purchase Return\" || doc.purpose==\"Send to Subcontractor\"",
+   "depends_on": "eval:doc.purpose === \"Send to Subcontractor\"",
    "fieldname": "supplier_address",
    "fieldtype": "Link",
    "label": "Supplier Address",
@@ -478,41 +474,6 @@
    "label": "Address"
   },
   {
-   "fieldname": "column_break_39",
-   "fieldtype": "Column Break"
-  },
-  {
-   "depends_on": "eval:doc.purpose==\"Sales Return\"",
-   "fieldname": "customer",
-   "fieldtype": "Link",
-   "label": "Customer",
-   "no_copy": 1,
-   "oldfieldname": "customer",
-   "oldfieldtype": "Link",
-   "options": "Customer",
-   "print_hide": 1
-  },
-  {
-   "bold": 1,
-   "depends_on": "eval:doc.purpose==\"Sales Return\"",
-   "fieldname": "customer_name",
-   "fieldtype": "Data",
-   "label": "Customer Name",
-   "no_copy": 1,
-   "oldfieldname": "customer_name",
-   "oldfieldtype": "Data",
-   "read_only": 1
-  },
-  {
-   "depends_on": "eval:doc.purpose==\"Sales Return\"",
-   "fieldname": "customer_address",
-   "fieldtype": "Small Text",
-   "label": "Customer Address",
-   "no_copy": 1,
-   "oldfieldname": "customer_address",
-   "oldfieldtype": "Small Text"
-  },
-  {
    "collapsible": 1,
    "fieldname": "printing_settings",
    "fieldtype": "Section Break",
@@ -657,7 +618,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-05-21 11:29:11.917161",
+ "modified": "2021-05-24 11:32:23.904307",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Entry",
diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
index 3296f5b..ba31ad7 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
@@ -15,10 +15,12 @@
 from erpnext.stock.doctype.landed_cost_voucher.test_landed_cost_voucher import create_landed_cost_voucher
 from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
 from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import BackDatedStockTransaction
+from frappe.core.page.permission_manager.permission_manager import reset
 
 class TestStockLedgerEntry(unittest.TestCase):
 	def setUp(self):
 		items = create_items()
+		reset('Stock Entry')
 
 		# delete SLE and BINs for all items
 		frappe.db.sql("delete from `tabStock Ledger Entry` where item_code in (%s)" % (', '.join(['%s']*len(items))), items)
@@ -314,10 +316,11 @@
 		# Set User with Stock User role but not Stock Manager
 		try:
 			user = frappe.get_doc("User", "test@example.com")
-			frappe.set_user(user.name)
 			user.add_roles("Stock User")
 			user.remove_roles("Stock Manager")
 
+			frappe.set_user(user.name)
+
 			stock_entry_on_today = make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
 			back_dated_se_1 = make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100,
 				posting_date=add_days(today(), -1), do_not_submit=True)
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index 8ba1f1c..8917bfe 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -194,9 +194,6 @@
 		serial_nos = frappe.db.sql("""select count(name) from `tabSerial No`
 			where item_code=%s and warehouse=%s and docstatus < 2""", (d[0], d[1]))
 
-		if serial_nos and flt(serial_nos[0][0]) != flt(d[2]):
-			print(d[0], d[1], d[2], serial_nos[0][0])
-
 		sle = frappe.db.sql("""select valuation_rate, company from `tabStock Ledger Entry`
 			where item_code = %s and warehouse = %s and is_cancelled = 0
 			order by posting_date desc limit 1""", (d[0], d[1]))
@@ -230,7 +227,7 @@
 		})
 
 		update_bin(args)
-		
+
 		create_repost_item_valuation_entry({
 			"item_code": d[0],
 			"warehouse": d[1],
diff --git a/erpnext/tests/__init__.py b/erpnext/tests/__init__.py
index e69de29..a504340 100644
--- a/erpnext/tests/__init__.py
+++ b/erpnext/tests/__init__.py
@@ -0,0 +1 @@
+global_test_dependencies = ['User', 'Company', 'Item']
diff --git a/erpnext/utilities/__init__.py b/erpnext/utilities/__init__.py
index 618cc98..0a5aa3c 100644
--- a/erpnext/utilities/__init__.py
+++ b/erpnext/utilities/__init__.py
@@ -12,7 +12,6 @@
 
 		for f in dt.fields:
 			if f.fieldname == d.fieldname and f.fieldtype in ("Text", "Small Text"):
-				print(f.parent, f.fieldname)
 				f.fieldtype = "Text Editor"
 				dt.save()
 				break
diff --git a/erpnext/www/book_appointment/index.js b/erpnext/www/book_appointment/index.js
index 377a3cc..5562cbd 100644
--- a/erpnext/www/book_appointment/index.js
+++ b/erpnext/www/book_appointment/index.js
@@ -48,7 +48,7 @@
 function hide_next_button() {
     let next_button = document.getElementById('next-button');
     next_button.disabled = true;
-    next_button.onclick = () => frappe.msgprint("Please select a date and time");
+    next_button.onclick = () => frappe.msgprint(__("Please select a date and time"));
 }
 
 function show_next_button() {
@@ -63,7 +63,7 @@
     if (date_picker.value === '') {
         clear_time_slots();
         hide_next_button();
-        frappe.throw('Please select a date');
+        frappe.throw(__('Please select a date'));
     }
     window.selected_date = date_picker.value;
     window.selected_timezone = timezone.value;