Merge pull request #28054 from deepeshgarg007/tax_withholding_category_filters

fix(minor): Filters and validations in Tax Withholding Category
diff --git a/.github/helper/semgrep_rules/README.md b/.github/helper/semgrep_rules/README.md
deleted file mode 100644
index 670d8d2..0000000
--- a/.github/helper/semgrep_rules/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Semgrep linting
-
-## What is semgrep?
-Semgrep or "semantic grep" is language agnostic static analysis tool. In simple terms semgrep is syntax-aware `grep`, so unlike regex it doesn't get confused by different ways of writing same thing or whitespaces or code split in multiple lines etc.
-
-Example:
-
-To check if a translate function is using f-string or not the regex would be `r"_\(\s*f[\"']"` while equivalent rule in semgrep would be `_(f"...")`. As semgrep knows grammer of language it takes care of unnecessary whitespace, type of quotation marks etc.
-
-You can read more such examples in `.github/helper/semgrep_rules` directory.
-
-# Why/when to use this?
-We want to maintain quality of contributions, at the same time remembering all the good practices can be pain to deal with while evaluating contributions. Using semgrep if you can translate "best practice" into a rule then it can automate the task for us.
-
-## Running locally
-
-Install semgrep using homebrew `brew install semgrep` or pip `pip install semgrep`.
-
-To run locally use following command:
-
-`semgrep --config=.github/helper/semgrep_rules [file/folder names]`
-
-## Testing
-semgrep allows testing the tests. Refer to this page: https://semgrep.dev/docs/writing-rules/testing-rules/
-
-When writing new rules you should write few positive and few negative cases as shown in the guide and current tests.
-
-To run current tests: `semgrep --test --test-ignore-todo .github/helper/semgrep_rules`
-
-
-## Reference
-
-If you are new to Semgrep read following pages to get started on writing/modifying rules:
-
-- https://semgrep.dev/docs/getting-started/
-- https://semgrep.dev/docs/writing-rules/rule-syntax
-- https://semgrep.dev/docs/writing-rules/pattern-examples/
-- https://semgrep.dev/docs/writing-rules/rule-ideas/#common-use-cases
diff --git a/.github/helper/semgrep_rules/frappe_correctness.py b/.github/helper/semgrep_rules/frappe_correctness.py
deleted file mode 100644
index 83d4acf..0000000
--- a/.github/helper/semgrep_rules/frappe_correctness.py
+++ /dev/null
@@ -1,64 +0,0 @@
-import frappe
-from frappe import _
-
-from frappe.model.document import Document
-
-
-# ruleid: frappe-modifying-but-not-comitting
-def on_submit(self):
-	if self.value_of_goods == 0:
-		frappe.throw(_('Value of goods cannot be 0'))
-	self.status = 'Submitted'
-
-
-# ok: frappe-modifying-but-not-comitting
-def on_submit(self):
-	if self.value_of_goods == 0:
-		frappe.throw(_('Value of goods cannot be 0'))
-	self.status = 'Submitted'
-	self.db_set('status', 'Submitted')
-
-# ok: frappe-modifying-but-not-comitting
-def on_submit(self):
-	if self.value_of_goods == 0:
-		frappe.throw(_('Value of goods cannot be 0'))
-	x = "y"
-	self.status = x
-	self.db_set('status', x)
-
-
-# ok: frappe-modifying-but-not-comitting
-def on_submit(self):
-	x = "y"
-	self.status = x
-	self.save()
-
-# ruleid: frappe-modifying-but-not-comitting-other-method
-class DoctypeClass(Document):
-	def on_submit(self):
-		self.good_method()
-		self.tainted_method()
-
-	def tainted_method(self):
-		self.status = "uptate"
-
-
-# ok: frappe-modifying-but-not-comitting-other-method
-class DoctypeClass(Document):
-	def on_submit(self):
-		self.good_method()
-		self.tainted_method()
-
-	def tainted_method(self):
-		self.status = "update"
-		self.db_set("status", "update")
-
-# ok: frappe-modifying-but-not-comitting-other-method
-class DoctypeClass(Document):
-	def on_submit(self):
-		self.good_method()
-		self.tainted_method()
-		self.save()
-
-	def tainted_method(self):
-		self.status = "uptate"
diff --git a/.github/helper/semgrep_rules/frappe_correctness.yml b/.github/helper/semgrep_rules/frappe_correctness.yml
deleted file mode 100644
index 0cf4e78..0000000
--- a/.github/helper/semgrep_rules/frappe_correctness.yml
+++ /dev/null
@@ -1,163 +0,0 @@
-# This file specifies rules for correctness according to how frappe doctype data model works.
-
-rules:
-- id: frappe-modifying-but-not-comitting
-  patterns:
-    - pattern: |
-        def $METHOD(self, ...):
-          ...
-          self.$ATTR = ...
-    - pattern-not: |
-        def $METHOD(self, ...):
-          ...
-          self.$ATTR = ...
-          ...
-          self.db_set(..., self.$ATTR, ...)
-    - pattern-not: |
-        def $METHOD(self, ...):
-          ...
-          self.$ATTR = $SOME_VAR
-          ...
-          self.db_set(..., $SOME_VAR, ...)
-    - pattern-not: |
-        def $METHOD(self, ...):
-          ...
-          self.$ATTR = $SOME_VAR
-          ...
-          self.save()
-    - metavariable-regex:
-        metavariable: '$ATTR'
-        # this is negative look-ahead, add more attrs to ignore like (ignore|ignore_this_too|ignore_me)
-        regex: '^(?!ignore_linked_doctypes|status_updater)(.*)$'
-    - metavariable-regex:
-        metavariable: "$METHOD"
-        regex: "(on_submit|on_cancel)"
-  message: |
-    DocType modified in self.$METHOD. Please check if modification of self.$ATTR is commited to database.
-  languages: [python]
-  severity: ERROR
-
-- id: frappe-modifying-but-not-comitting-other-method
-  patterns:
-  - pattern: |
-      class $DOCTYPE(...):
-        def $METHOD(self, ...):
-          ...
-          self.$ANOTHER_METHOD()
-          ...
-
-        def $ANOTHER_METHOD(self, ...):
-          ...
-          self.$ATTR = ...
-  - pattern-not: |
-      class $DOCTYPE(...):
-        def $METHOD(self, ...):
-          ...
-          self.$ANOTHER_METHOD()
-          ...
-
-        def $ANOTHER_METHOD(self, ...):
-          ...
-          self.$ATTR = ...
-          ...
-          self.db_set(..., self.$ATTR, ...)
-  - pattern-not: |
-      class $DOCTYPE(...):
-        def $METHOD(self, ...):
-          ...
-          self.$ANOTHER_METHOD()
-          ...
-
-        def $ANOTHER_METHOD(self, ...):
-          ...
-          self.$ATTR = $SOME_VAR
-          ...
-          self.db_set(..., $SOME_VAR, ...)
-  - pattern-not: |
-      class $DOCTYPE(...):
-        def $METHOD(self, ...):
-          ...
-          self.$ANOTHER_METHOD()
-          ...
-          self.save()
-        def $ANOTHER_METHOD(self, ...):
-          ...
-          self.$ATTR = ...
-  - metavariable-regex:
-      metavariable: "$METHOD"
-      regex: "(on_submit|on_cancel)"
-  message: |
-    self.$ANOTHER_METHOD is called from self.$METHOD, check if changes to self.$ATTR are commited to database.
-  languages: [python]
-  severity: ERROR
-
-- id: frappe-print-function-in-doctypes
-  pattern: print(...)
-  message: |
-      Did you mean to leave this print statement in? Consider using msgprint or logger instead of print statement.
-  languages: [python]
-  severity: WARNING
-  paths:
-      include:
-        - "*/**/doctype/*"
-
-- id: frappe-modifying-child-tables-while-iterating
-  pattern-either:
-    - pattern: |
-        for $ROW in self.$TABLE:
-            ...
-            self.remove(...)
-    - pattern: |
-        for $ROW in self.$TABLE:
-            ...
-            self.append(...)
-  message: |
-      Child table being modified while iterating on it.
-  languages: [python]
-  severity: ERROR
-  paths:
-      include:
-        - "*/**/doctype/*"
-
-- id: frappe-same-key-assigned-twice
-  pattern-either:
-    - pattern: |
-        {..., $X: $A, ..., $X: $B, ...}
-    - pattern: |
-        dict(..., ($X, $A), ..., ($X, $B), ...)
-    - pattern: |
-        _dict(..., ($X, $A), ..., ($X, $B), ...)
-  message: |
-      key `$X` is uselessly assigned twice. This could be a potential bug.
-  languages: [python]
-  severity: ERROR
-
-- id: frappe-manual-commit
-  patterns:
-    - pattern: frappe.db.commit()
-    - pattern-not-inside: |
-        try:
-          ...
-        except ...:
-          ...
-  message: |
-    Manually commiting a transaction is highly discouraged. Read about the transaction model implemented by Frappe Framework before adding manual commits: https://frappeframework.com/docs/user/en/api/database#database-transaction-model If you think manual commit is required then add a comment explaining why and `// nosemgrep` on the same line.
-  paths:
-      exclude:
-        - "**/patches/**"
-        - "**/demo/**"
-  languages: [python]
-  severity: ERROR
-
-- id: frappe-using-db-sql
-  pattern-either:
-    - pattern: frappe.db.sql(...)
-    - pattern: frappe.db.sql_ddl(...)
-    - pattern: frappe.db.sql_list(...)
-  paths:
-    exclude:
-      - "test_*.py"
-  message: |
-    The PR contains a SQL query that may be re-written with frappe.qb (https://frappeframework.com/docs/user/en/api/query-builder) or the Database API (https://frappeframework.com/docs/user/en/api/database)
-  languages: [python]
-  severity: ERROR
\ No newline at end of file
diff --git a/.github/helper/semgrep_rules/report.py b/.github/helper/semgrep_rules/report.py
deleted file mode 100644
index ff27840..0000000
--- a/.github/helper/semgrep_rules/report.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from frappe import _
-
-
-# ruleid: frappe-missing-translate-function-in-report-python
-{"label": "Field Label"}
-
-# ruleid: frappe-missing-translate-function-in-report-python
-dict(label="Field Label")
-
-
-# ok: frappe-missing-translate-function-in-report-python
-{"label": _("Field Label")}
-
-# ok: frappe-missing-translate-function-in-report-python
-dict(label=_("Field Label"))
diff --git a/.github/helper/semgrep_rules/report.yml b/.github/helper/semgrep_rules/report.yml
deleted file mode 100644
index f2a9b16..0000000
--- a/.github/helper/semgrep_rules/report.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-rules:
-- id: frappe-missing-translate-function-in-report-python
-  paths:
-    include:
-    - "**/report"
-    exclude:
-    - "**/regional"
-  pattern-either:
-  - patterns:
-      - pattern: |
-          {..., "label": "...", ...}
-      - pattern-not: |
-          {..., "label": _("..."), ...}
-  - patterns:
-      - pattern: dict(..., label="...", ...)
-      - pattern-not: dict(..., label=_("..."), ...)
-  message: |
-      All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations
-  languages: [python]
-  severity: ERROR
-
-- id: frappe-translated-values-in-business-logic
-  paths:
-    include:
-    - "**/report"
-  patterns:
-    - pattern-inside: |
-        {..., filters: [...], ...}
-    - pattern: |
-        {..., options: [..., __("..."), ...], ...}
-  message: |
-      Using translated values in options field will require you to translate the values while comparing in business logic. Instead of passing translated labels provide objects that contain both label and value. e.g. { label: __("Option value"), value: "Option value"}
-  languages: [javascript]
-  severity: ERROR
diff --git a/.github/helper/semgrep_rules/security.py b/.github/helper/semgrep_rules/security.py
deleted file mode 100644
index f477d7c..0000000
--- a/.github/helper/semgrep_rules/security.py
+++ /dev/null
@@ -1,6 +0,0 @@
-def function_name(input):
-	# ruleid: frappe-codeinjection-eval
-	eval(input)
-
-# ok: frappe-codeinjection-eval
-eval("1 + 1")
diff --git a/.github/helper/semgrep_rules/security.yml b/.github/helper/semgrep_rules/security.yml
deleted file mode 100644
index 8b21979..0000000
--- a/.github/helper/semgrep_rules/security.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-rules:
-- id: frappe-codeinjection-eval
-  patterns:
-  - pattern-not: eval("...")
-  - pattern: eval(...)
-  message: |
-    Detected the use of eval(). eval() can be dangerous if used to evaluate
-    dynamic content. Avoid it or use safe_eval().
-  languages: [python]
-  severity: ERROR
diff --git a/.github/helper/semgrep_rules/translate.js b/.github/helper/semgrep_rules/translate.js
deleted file mode 100644
index 9cdfb75..0000000
--- a/.github/helper/semgrep_rules/translate.js
+++ /dev/null
@@ -1,44 +0,0 @@
-// ruleid: frappe-translation-empty-string
-__("")
-// ruleid: frappe-translation-empty-string
-__('')
-
-// ok: frappe-translation-js-formatting
-__('Welcome {0}, get started with ERPNext in just a few clicks.', [full_name]);
-
-// ruleid: frappe-translation-js-formatting
-__(`Welcome ${full_name}, get started with ERPNext in just a few clicks.`);
-
-// ok: frappe-translation-js-formatting
-__('This is fine');
-
-
-// ok: frappe-translation-trailing-spaces
-__('This is fine');
-
-// ruleid: frappe-translation-trailing-spaces
-__(' this is not ok ');
-// ruleid: frappe-translation-trailing-spaces
-__('this is not ok ');
-// ruleid: frappe-translation-trailing-spaces
-__(' this is not ok');
-
-// ok: frappe-translation-js-splitting
-__('You have {0} subscribers in your mailing list.', [subscribers.length])
-
-// todoruleid: frappe-translation-js-splitting
-__('You have') + subscribers.length + __('subscribers in your mailing list.')
-
-// ruleid: frappe-translation-js-splitting
-__('You have' + 'subscribers in your mailing list.')
-
-// ruleid: frappe-translation-js-splitting
-__('You have {0} subscribers' +
-    'in your mailing list', [subscribers.length])
-
-// ok: frappe-translation-js-splitting
-__("Ctrl+Enter to add comment")
-
-// ruleid: frappe-translation-js-splitting
-__('You have {0} subscribers \
-    in your mailing list', [subscribers.length])
diff --git a/.github/helper/semgrep_rules/translate.py b/.github/helper/semgrep_rules/translate.py
deleted file mode 100644
index 9de6aa9..0000000
--- a/.github/helper/semgrep_rules/translate.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# Examples taken from https://frappeframework.com/docs/user/en/translations
-# This file is used for testing the tests.
-
-from frappe import _
-
-full_name = "Jon Doe"
-# ok: frappe-translation-python-formatting
-_('Welcome {0}, get started with ERPNext in just a few clicks.').format(full_name)
-
-# ruleid: frappe-translation-python-formatting
-_('Welcome %s, get started with ERPNext in just a few clicks.' % full_name)
-# ruleid: frappe-translation-python-formatting
-_('Welcome %(name)s, get started with ERPNext in just a few clicks.' % {'name': full_name})
-
-# ruleid: frappe-translation-python-formatting
-_('Welcome {0}, get started with ERPNext in just a few clicks.'.format(full_name))
-
-
-subscribers = ["Jon", "Doe"]
-# ok: frappe-translation-python-formatting
-_('You have {0} subscribers in your mailing list.').format(len(subscribers))
-
-# ruleid: frappe-translation-python-splitting
-_('You have') + len(subscribers) + _('subscribers in your mailing list.')
-
-# ruleid: frappe-translation-python-splitting
-_('You have {0} subscribers \
-    in your mailing list').format(len(subscribers))
-
-# ok: frappe-translation-python-splitting
-_('You have {0} subscribers') \
-    + 'in your mailing list'
-
-# ruleid: frappe-translation-trailing-spaces
-msg = _(" You have {0} pending invoice ")
-# ruleid: frappe-translation-trailing-spaces
-msg = _("You have {0} pending invoice ")
-# ruleid: frappe-translation-trailing-spaces
-msg = _(" You have {0} pending invoice")
-
-# ok: frappe-translation-trailing-spaces
-msg = ' ' + _("You have {0} pending invoices") + ' '
-
-# ruleid: frappe-translation-python-formatting
-_(f"can not format like this - {subscribers}")
-# ruleid: frappe-translation-python-splitting
-_(f"what" + f"this is also not cool")
-
-
-# ruleid: frappe-translation-empty-string
-_("")
-# ruleid: frappe-translation-empty-string
-_('')
-
-
-class Test:
-	# ok: frappe-translation-python-splitting
-	def __init__(
-			args
-			):
-		pass
diff --git a/.github/helper/semgrep_rules/translate.yml b/.github/helper/semgrep_rules/translate.yml
deleted file mode 100644
index 5f03fb9..0000000
--- a/.github/helper/semgrep_rules/translate.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-rules:
-- id: frappe-translation-empty-string
-  pattern-either:
-  - pattern: _("")
-  - pattern: __("")
-  message: |
-    Empty string is useless for translation.
-    Please refer: https://frappeframework.com/docs/user/en/translations
-  languages: [python, javascript, json]
-  severity: ERROR
-
-- id: frappe-translation-trailing-spaces
-  pattern-either:
-    - pattern: _("=~/(^[ \t]+|[ \t]+$)/")
-    - pattern: __("=~/(^[ \t]+|[ \t]+$)/")
-  message: |
-    Trailing or leading whitespace not allowed in translate strings.
-    Please refer: https://frappeframework.com/docs/user/en/translations
-  languages: [python, javascript, json]
-  severity: ERROR
-
-- id: frappe-translation-python-formatting
-  pattern-either:
-  - pattern: _("..." % ...)
-  - pattern: _("...".format(...))
-  - pattern: _(f"...")
-  message: |
-    Only positional formatters are allowed and formatting should not be done before translating.
-    Please refer: https://frappeframework.com/docs/user/en/translations
-  languages: [python]
-  severity: ERROR
-
-- id: frappe-translation-js-formatting
-  patterns:
-  - pattern: __(`...`)
-  - pattern-not: __("...")
-  message: |
-    Template strings are not allowed for text formatting.
-    Please refer: https://frappeframework.com/docs/user/en/translations
-  languages: [javascript, json]
-  severity: ERROR
-
-- id: frappe-translation-python-splitting
-  pattern-either:
-  - pattern: _(...) + _(...)
-  - pattern: _("..." + "...")
-  - pattern-regex: '[\s\.]_\([^\)]*\\\s*'    # lines broken by `\`
-  - pattern-regex: '[\s\.]_\(\s*\n'          # line breaks allowed by python for using ( )
-  message: |
-    Do not split strings inside translate function. Do not concatenate using translate functions.
-    Please refer: https://frappeframework.com/docs/user/en/translations
-  languages: [python]
-  severity: ERROR
-
-- id: frappe-translation-js-splitting
-  pattern-either:
-  - pattern-regex: '__\([^\)]*[\\]\s+'
-  - pattern: __('...' + '...', ...)
-  - pattern: __('...') + __('...')
-  message: |
-    Do not split strings inside translate function. Do not concatenate using translate functions.
-    Please refer: https://frappeframework.com/docs/user/en/translations
-  languages: [javascript, json]
-  severity: ERROR
diff --git a/.github/helper/semgrep_rules/ux.js b/.github/helper/semgrep_rules/ux.js
deleted file mode 100644
index ae73f9c..0000000
--- a/.github/helper/semgrep_rules/ux.js
+++ /dev/null
@@ -1,9 +0,0 @@
-
-// ok: frappe-missing-translate-function-js
-frappe.msgprint('{{ _("Both login and password required") }}');
-
-// ruleid: frappe-missing-translate-function-js
-frappe.msgprint('What');
-
-// ok: frappe-missing-translate-function-js
-frappe.throw('  {{ _("Both login and password required") }}.  ');
diff --git a/.github/helper/semgrep_rules/ux.py b/.github/helper/semgrep_rules/ux.py
deleted file mode 100644
index a00d3cd..0000000
--- a/.github/helper/semgrep_rules/ux.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import frappe
-from frappe import msgprint, throw, _
-
-
-# ruleid: frappe-missing-translate-function-python
-throw("Error Occured")
-
-# ruleid: frappe-missing-translate-function-python
-frappe.throw("Error Occured")
-
-# ruleid: frappe-missing-translate-function-python
-frappe.msgprint("Useful message")
-
-# ruleid: frappe-missing-translate-function-python
-msgprint("Useful message")
-
-
-# ok: frappe-missing-translate-function-python
-translatedmessage = _("Hello")
-
-# ok: frappe-missing-translate-function-python
-throw(translatedmessage)
-
-# ok: frappe-missing-translate-function-python
-msgprint(translatedmessage)
-
-# ok: frappe-missing-translate-function-python
-msgprint(_("Helpful message"))
-
-# ok: frappe-missing-translate-function-python
-frappe.throw(_("Error occured"))
diff --git a/.github/helper/semgrep_rules/ux.yml b/.github/helper/semgrep_rules/ux.yml
deleted file mode 100644
index dd667f3..0000000
--- a/.github/helper/semgrep_rules/ux.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-rules:
-- id: frappe-missing-translate-function-python
-  pattern-either:
-  - patterns:
-      - pattern: frappe.msgprint("...", ...)
-      - pattern-not: frappe.msgprint(_("..."), ...)
-  - patterns:
-      - pattern: frappe.throw("...", ...)
-      - pattern-not: frappe.throw(_("..."), ...)
-  message: |
-      All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations
-  languages: [python]
-  severity: ERROR
-
-- id: frappe-missing-translate-function-js
-  pattern-either:
-  - patterns:
-      - pattern: frappe.msgprint("...", ...)
-      - pattern-not: frappe.msgprint(__("..."), ...)
-      # ignore microtemplating e.g. msgprint("{{ _("server side translation") }}")
-      - pattern-not: frappe.msgprint("=~/\{\{.*\_.*\}\}/i", ...)
-  - patterns:
-      - pattern: frappe.throw("...", ...)
-      - pattern-not: frappe.throw(__("..."), ...)
-      # ignore microtemplating
-      - pattern-not: frappe.throw("=~/\{\{.*\_.*\}\}/i", ...)
-  message: |
-      All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations
-  languages: [javascript]
-  severity: ERROR
diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml
index 9389eaa..ebb88c9 100644
--- a/.github/workflows/linters.yml
+++ b/.github/workflows/linters.yml
@@ -19,10 +19,13 @@
       - name: Install and Run Pre-commit
         uses: pre-commit/action@v2.0.3
 
+      - name: Download Semgrep rules
+        run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
+
       - uses: returntocorp/semgrep-action@v1
         env:
             SEMGREP_TIMEOUT: 120
         with:
             config: >-
               r/python.lang.correctness
-              .github/helper/semgrep_rules
+              ./frappe-semgrep-rules/rules
diff --git a/README.md b/README.md
index 6fad8f4..1105a97 100644
--- a/README.md
+++ b/README.md
@@ -55,14 +55,6 @@
 
 New passwords will be created for the ERPNext "Administrator" user, the MariaDB root user, and the frappe user (the script displays the passwords and saves them to ~/frappe_passwords.txt).
 
-### Virtual Image
-
-You can download a virtual image to run ERPNext in a virtual machine on your local system.
-
-- [ERPNext Download](http://erpnext.com/download)
-
-System and user credentials are listed on the download page.
-
 ---
 
 ## License
diff --git a/erpnext/accounts/custom/address.py b/erpnext/accounts/custom/address.py
index a6d08d8..551048e 100644
--- a/erpnext/accounts/custom/address.py
+++ b/erpnext/accounts/custom/address.py
@@ -10,6 +10,7 @@
 class ERPNextAddress(Address):
 	def validate(self):
 		self.validate_reference()
+		self.update_compnay_address()
 		super(ERPNextAddress, self).validate()
 
 	def link_address(self):
@@ -19,6 +20,11 @@
 
 		return super(ERPNextAddress, self).link_address()
 
+	def update_compnay_address(self):
+		for link in self.get('links'):
+			if link.link_doctype == 'Company':
+				self.is_your_company_address = 1
+
 	def validate_reference(self):
 		if self.is_your_company_address and not [
 			row for row in self.links if row.link_doctype == "Company"
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index 6f362c1..ee2e319 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -27,10 +27,12 @@
   "payment_accounts_section",
   "party_balance",
   "paid_from",
+  "paid_from_account_type",
   "paid_from_account_currency",
   "paid_from_account_balance",
   "column_break_18",
   "paid_to",
+  "paid_to_account_type",
   "paid_to_account_currency",
   "paid_to_account_balance",
   "payment_amounts_section",
@@ -440,7 +442,8 @@
    "depends_on": "eval:(doc.paid_from && doc.paid_to)",
    "fieldname": "reference_no",
    "fieldtype": "Data",
-   "label": "Cheque/Reference No"
+   "label": "Cheque/Reference No",
+   "mandatory_depends_on": "eval:(doc.paid_from_account_type == 'Bank' || doc.paid_to_account_type == 'Bank')"
   },
   {
    "fieldname": "column_break_23",
@@ -452,6 +455,7 @@
    "fieldname": "reference_date",
    "fieldtype": "Date",
    "label": "Cheque/Reference Date",
+   "mandatory_depends_on": "eval:(doc.paid_from_account_type == 'Bank' || doc.paid_to_account_type == 'Bank')",
    "search_index": 1
   },
   {
@@ -707,15 +711,30 @@
    "label": "Received Amount After Tax (Company Currency)",
    "options": "Company:company:default_currency",
    "read_only": 1
+  },
+  {
+   "fetch_from": "paid_from.account_type",
+   "fieldname": "paid_from_account_type",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Paid From Account Type"
+  },
+  {
+   "fetch_from": "paid_to.account_type",
+   "fieldname": "paid_to_account_type",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Paid To Account Type"
   }
  ],
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-07-09 08:58:15.008761",
+ "modified": "2021-10-22 17:50:24.632806",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Entry",
+ "naming_rule": "By \"Naming Series\" field",
  "owner": "Administrator",
  "permissions": [
   {
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json
index 4d6e4a2..d6e35c6 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json
@@ -180,8 +180,7 @@
    "fieldname": "pos_transactions",
    "fieldtype": "Table",
    "label": "POS Transactions",
-   "options": "POS Invoice Reference",
-   "reqd": 1
+   "options": "POS Invoice Reference"
   },
   {
    "fieldname": "pos_opening_entry",
@@ -229,7 +228,7 @@
    "link_fieldname": "pos_closing_entry"
   }
  ],
- "modified": "2021-05-05 16:59:49.723261",
+ "modified": "2021-10-20 16:19:25.340565",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "POS Closing Entry",
diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
index 9dae3a7..4f26ed4 100644
--- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
+++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
@@ -246,7 +246,10 @@
 	return pos_invoice_customer_map
 
 def consolidate_pos_invoices(pos_invoices=None, closing_entry=None):
-	invoices = pos_invoices or (closing_entry and closing_entry.get('pos_transactions')) or get_all_unconsolidated_invoices()
+	invoices = pos_invoices or (closing_entry and closing_entry.get('pos_transactions'))
+	if frappe.flags.in_test and not invoices:
+		invoices = get_all_unconsolidated_invoices()
+
 	invoice_by_customer = get_invoice_customer_map(invoices)
 
 	if len(invoices) >= 10 and closing_entry:
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 6c74d2b..3526e48 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -590,5 +590,11 @@
 
 	company: function(frm) {
 		erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
+
+		if (frm.doc.company) {
+			frappe.db.get_value('Company', frm.doc.company, 'default_payable_account', (r) => {
+				frm.set_value('credit_to', r.default_payable_account);
+			});
+		}
 	},
 })
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 73e1284..bee153b 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -12,6 +12,13 @@
 	}
 	company() {
 		erpnext.accounts.dimensions.update_dimension(this.frm, this.frm.doctype);
+
+		let me = this;
+		if (this.frm.doc.company) {
+			frappe.db.get_value('Company', this.frm.doc.company, 'default_receivable_account', (r) => {
+				me.frm.set_value('debit_to', r.default_receivable_account);
+			});
+		}
 	}
 	onload() {
 		var me = this;
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
index 621b697..6a7f2e5 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
@@ -44,16 +44,16 @@
 
 		if rate and tds_deducted:
 			row = {
-				'pan' if frappe.db.has_column('Supplier', 'pan') else 'tax_id': supplier_map.get(supplier).pan,
-				'supplier': supplier_map.get(supplier).name
+				'pan' if frappe.db.has_column('Supplier', 'pan') else 'tax_id': supplier_map.get(supplier, {}).get('pan'),
+				'supplier': supplier_map.get(supplier, {}).get('name')
 			}
 
 			if filters.naming_series == 'Naming Series':
-				row.update({'supplier_name': supplier_map.get(supplier).supplier_name})
+				row.update({'supplier_name': supplier_map.get(supplier, {}).get('supplier_name')})
 
 			row.update({
 				'section_code': tax_withholding_category,
-				'entity_type': supplier_map.get(supplier).supplier_type,
+				'entity_type': supplier_map.get(supplier, {}).get('supplier_type'),
 				'tds_rate': rate,
 				'total_amount_credited': total_amount_credited,
 				'tds_deducted': tds_deducted,
diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json
index 12a09cd..a57d9a9 100644
--- a/erpnext/buying/doctype/supplier/supplier.json
+++ b/erpnext/buying/doctype/supplier/supplier.json
@@ -25,7 +25,6 @@
   "column_break0",
   "supplier_group",
   "supplier_type",
-  "pan",
   "allow_purchase_invoice_creation_without_purchase_order",
   "allow_purchase_invoice_creation_without_purchase_receipt",
   "disabled",
@@ -177,11 +176,6 @@
    "reqd": 1
   },
   {
-   "fieldname": "pan",
-   "fieldtype": "Data",
-   "label": "PAN"
-  },
-  {
    "fieldname": "language",
    "fieldtype": "Link",
    "label": "Print Language",
@@ -438,11 +432,12 @@
    "link_fieldname": "party"
   }
  ],
- "modified": "2021-09-06 17:37:56.522233",
+ "modified": "2021-10-20 22:03:33.147249",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Supplier",
  "name_case": "Title Case",
+ "naming_rule": "By \"Naming Series\" field",
  "owner": "Administrator",
  "permissions": [
   {
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index e446d6b..20e54e0 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -310,3 +310,4 @@
 erpnext.patches.v13_0.requeue_failed_reposts
 erpnext.patches.v13_0.healthcare_deprecation_warning
 erpnext.patches.v14_0.delete_healthcare_doctypes
+erpnext.patches.v13_0.create_pan_field_for_india #2
diff --git a/erpnext/patches/v13_0/create_pan_field_for_india.py b/erpnext/patches/v13_0/create_pan_field_for_india.py
new file mode 100644
index 0000000..c37651a
--- /dev/null
+++ b/erpnext/patches/v13_0/create_pan_field_for_india.py
@@ -0,0 +1,28 @@
+import frappe
+from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
+
+
+def execute():
+	frappe.reload_doc('buying', 'doctype', 'supplier', force=True)
+	frappe.reload_doc('selling', 'doctype', 'customer', force=True)
+
+	custom_fields = {
+		'Supplier': [
+			{
+				'fieldname': 'pan',
+				'label': 'PAN',
+				'fieldtype': 'Data',
+				'insert_after': 'supplier_type'
+			}
+		],
+		'Customer': [
+			{
+				'fieldname': 'pan',
+				'label': 'PAN',
+				'fieldtype': 'Data',
+				'insert_after': 'customer_type'
+			}
+		]
+	}
+
+	create_custom_fields(custom_fields, update=True)
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index 65a8566..f615f05 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -283,7 +283,9 @@
 		calculate_time_and_amount(frm);
 	},
 
-	activity_type: function(frm, cdt, cdn) {
+	activity_type: function (frm, cdt, cdn) {
+		if (!frappe.get_doc(cdt, cdn).activity_type) return;
+
 		frappe.call({
 			method: "erpnext.projects.doctype.timesheet.timesheet.get_activity_cost",
 			args: {
@@ -291,10 +293,10 @@
 				activity_type: frm.selected_doc.activity_type,
 				currency: frm.doc.currency
 			},
-			callback: function(r){
-				if(r.message){
-					frappe.model.set_value(cdt, cdn, 'billing_rate', r.message['billing_rate']);
-					frappe.model.set_value(cdt, cdn, 'costing_rate', r.message['costing_rate']);
+			callback: function (r) {
+				if (r.message) {
+					frappe.model.set_value(cdt, cdn, "billing_rate", r.message["billing_rate"]);
+					frappe.model.set_value(cdt, cdn, "costing_rate", r.message["costing_rate"]);
 					calculate_billing_costing_amount(frm, cdt, cdn);
 				}
 			}
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index afb1b07..1cbb154 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -615,10 +615,16 @@
 		],
 		'Supplier': [
 			{
+				'fieldname': 'pan',
+				'label': 'PAN',
+				'fieldtype': 'Data',
+				'insert_after': 'supplier_type'
+			},
+			{
 				'fieldname': 'gst_transporter_id',
 				'label': 'GST Transporter ID',
 				'fieldtype': 'Data',
-				'insert_after': 'supplier_type',
+				'insert_after': 'pan',
 				'depends_on': 'eval:doc.is_transporter'
 			},
 			{
@@ -641,10 +647,16 @@
 		],
 		'Customer': [
 			{
+				'fieldname': 'pan',
+				'label': 'PAN',
+				'fieldtype': 'Data',
+				'insert_after': 'customer_type'
+			},
+			{
 				'fieldname': 'gst_category',
 				'label': 'GST Category',
 				'fieldtype': 'Select',
-				'insert_after': 'customer_type',
+				'insert_after': 'pan',
 				'options': 'Registered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nConsumer\nDeemed Export\nUIN Holders',
 				'default': 'Unregistered'
 			},
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 0e41280..1733220 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -62,7 +62,7 @@
 				.format(doc.gst_state_number), title=_("Invalid GSTIN"))
 
 def validate_pan_for_india(doc, method):
-	if doc.get('country') != 'India' or not doc.pan:
+	if doc.get('country') != 'India' or not doc.get('pan'):
 		return
 
 	if not PAN_NUMBER_FORMAT.match(doc.pan):
diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json
index e811435..ae40630 100644
--- a/erpnext/selling/doctype/customer/customer.json
+++ b/erpnext/selling/doctype/customer/customer.json
@@ -16,7 +16,6 @@
   "customer_name",
   "gender",
   "customer_type",
-  "pan",
   "tax_withholding_category",
   "default_bank_account",
   "lead_name",
@@ -487,11 +486,6 @@
    "label": "Allow Sales Invoice Creation Without Delivery Note"
   },
   {
-   "fieldname": "pan",
-   "fieldtype": "Data",
-   "label": "PAN"
-  },
-  {
    "fieldname": "tax_withholding_category",
    "fieldtype": "Link",
    "label": "Tax Withholding Category",
@@ -517,11 +511,12 @@
    "link_fieldname": "party"
   }
  ],
- "modified": "2021-09-06 17:38:54.196663",
+ "modified": "2021-10-20 22:07:52.485809",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Customer",
  "name_case": "Title Case",
+ "naming_rule": "By \"Naming Series\" field",
  "owner": "Administrator",
  "permissions": [
   {
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index fc5d5c1..bb53c55 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -202,7 +202,9 @@
 
 		value_diff = flt(d.stock_value_difference)
 
-		if d.posting_date < from_date:
+		if d.posting_date < from_date or (d.posting_date == from_date
+			and d.voucher_type == "Stock Reconciliation" and
+			frappe.db.get_value("Stock Reconciliation", d.voucher_no, "purpose") == "Opening Stock"):
 			qty_dict.opening_qty += qty_diff
 			qty_dict.opening_val += value_diff
 
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index 1ea58fe..4e20b47 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -21,7 +21,7 @@
 	items = get_items(filters)
 	sl_entries = get_stock_ledger_entries(filters, items)
 	item_details = get_item_details(items, sl_entries, include_uom)
-	opening_row = get_opening_balance(filters, columns)
+	opening_row = get_opening_balance(filters, columns, sl_entries)
 	precision = cint(frappe.db.get_single_value("System Settings", "float_precision"))
 
 	data = []
@@ -218,7 +218,7 @@
 	return "and {}".format(" and ".join(conditions)) if conditions else ""
 
 
-def get_opening_balance(filters, columns):
+def get_opening_balance(filters, columns, sl_entries):
 	if not (filters.item_code and filters.warehouse and filters.from_date):
 		return
 
@@ -230,6 +230,15 @@
 		"posting_time": "00:00:00"
 	})
 
+	# check if any SLEs are actually Opening Stock Reconciliation
+	for sle in sl_entries:
+		if (sle.get("voucher_type") == "Stock Reconciliation"
+			and sle.get("date").split()[0] == filters.from_date
+			and frappe.db.get_value("Stock Reconciliation", sle.voucher_no, "purpose") == "Opening Stock"
+		):
+			last_entry = sle
+			sl_entries.remove(sle)
+
 	row = {
 		"item_code": _("'Opening'"),
 		"qty_after_transaction": last_entry.get("qty_after_transaction", 0),