Merge branch 'develop' into exit-interview
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index c145291..0000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,47 +0,0 @@
----
-name: Bug report
-about: Report a bug encountered while using ERPNext
-labels: bug
----
-
-<!--
-Welcome to ERPNext issue tracker! Before creating an issue, please heed the following:
-
-1. This tracker should only be used to report bugs and request features / enhancements to ERPNext
-    - For questions and general support, checkout the manual https://erpnext.com/docs/user/manual/en or use https://discuss.erpnext.com
-    - For documentation issues, refer to https://github.com/frappe/erpnext_com
-2. Use the search function before creating a new issue. Duplicates will be closed and directed to
-   the original discussion.
-3. When making a bug report, make sure you provide all required information. The easier it is for
-   maintainers to reproduce, the faster it'll be fixed.
-4. If you think you know what the reason for the bug is, share it with us. Maybe put in a PR 😉
--->
-
-## Description of the issue
-
-## Context information (for bug reports)
-
-**Output of `bench version`**
-```
-(paste here)
-```
-
-## Steps to reproduce the issue
-
-1.
-2.
-3.
-
-### Observed result
-
-### Expected result
-
-### Stacktrace / full error message
-
-```
-(paste here)
-```
-
-## Additional information
-
-OS version / distribution, `ERPNext` install method, etc.
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
new file mode 100644
index 0000000..a6e16a0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -0,0 +1,106 @@
+name: Bug Report
+description: Report a bug encountered while using ERPNext
+labels: ["bug"]
+
+body:
+  - type: markdown
+    attributes:
+      value: |
+        Welcome to ERPNext issue tracker! Before creating an issue, please heed the following:
+
+        1. This tracker should only be used to report bugs and request features / enhancements to ERPNext
+            - For questions and general support, checkout the [user manual](https://docs.erpnext.com/) or use [forum](https://discuss.erpnext.com)
+            - For documentation issues, propose edit on [documentation site](https://docs.erpnext.com/) directly.
+        2. When making a bug report, make sure you provide all required information. The easier it is for
+           maintainers to reproduce, the faster it'll be fixed.
+        3. If you think you know what the reason for the bug is, share it with us. Maybe put in a PR 😉
+
+  - type: textarea
+    id: bug-info
+    attributes:
+      label: Information about bug
+      description: Also tell us, what did you expect to happen?
+      placeholder: Please provide as much information as possible.
+    validations:
+      required: true
+
+  - type: dropdown
+    id: version
+    attributes:
+      label: Version
+      description: Affected versions.
+      multiple: true
+      options:
+        - v12
+        - v13
+        - v14
+        - develop
+    validations:
+      required: true
+
+  - type: dropdown
+    id: module
+    attributes:
+      label: Module
+      description: Select affected module of ERPNext.
+      multiple: true
+      options:
+        - accounts
+        - stock
+        - buying
+        - selling
+        - ecommerce
+        - manufacturing
+        - HR
+        - projects
+        - support
+        - assets
+        - integrations
+        - quality
+        - regional
+        - portal
+        - agriculture
+        - education
+        - non-profit
+    validations:
+      required: true
+
+  - type: textarea
+    id: exact-version
+    attributes:
+      label: Version
+      description: Share exact version number of Frappe and ERPNext you are using.
+      placeholder: |
+        Frappe version -
+        ERPNext Verion -
+    validations:
+      required: true
+
+  - type: dropdown
+    id: install-method
+    attributes:
+      label: Installation method
+      options:
+        - docker
+        - easy-install
+        - manual install
+        - FrappeCloud
+    validations:
+      required: true
+
+  - type: textarea
+    id: logs
+    attributes:
+      label: Relevant log output / Stack trace / Full Error Message.
+      description: Please copy and paste any relevant log output. This will be automatically formatted.
+      render: shell
+
+
+  - type: checkboxes
+    id: terms
+    attributes:
+      label: Code of Conduct
+      description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/frappe/erpnext/blob/develop/CODE_OF_CONDUCT.md)
+      options:
+        - label: I agree to follow this project's Code of Conduct
+          required: true
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 6cdad35..418bf3c 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -1,7 +1,10 @@
 ---
 name: Feature request
 about: Suggest an idea to improve ERPNext
+title: ''
 labels: feature-request
+assignees: ''
+
 ---
 
 <!--
diff --git a/.github/ISSUE_TEMPLATE/question-about-using-erpnext.md b/.github/ISSUE_TEMPLATE/question-about-using-erpnext.md
deleted file mode 100644
index 2016bcc..0000000
--- a/.github/ISSUE_TEMPLATE/question-about-using-erpnext.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-name: Question about using ERPNext
-about: This is not the appropriate channel
-labels: invalid
----
-
-Please post on our forums:
-
-for questions about using `ERPNext`: https://discuss.erpnext.com
-
-for questions about using the `Frappe Framework`: ~~https://discuss.frappe.io~~ => [stackoverflow](https://stackoverflow.com/questions/tagged/frappe) tagged under `frappe`
-
-for questions about using `bench`, probably the best place to start is the [bench repo](https://github.com/frappe/bench)
-
-For documentation issues, use the [ERPNext Documentation](https://erpnext.com/docs/) or [Frappe Framework Documentation](https://frappe.io/docs/user/en) or the [developer cheetsheet](https://github.com/frappe/frappe/wiki/Developer-Cheatsheet)
-
-> **Posts that are not bug reports or feature requests will not be addressed on this issue tracker.**
\ No newline at end of file
diff --git a/.github/stale.yml b/.github/stale.yml
index 9322ae8..8b7cb9b 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -1,34 +1,36 @@
 # Configuration for probot-stale - https://github.com/probot/stale
 
-# Number of days of inactivity before an Issue or Pull Request becomes stale
-daysUntilStale: 15
+# Label to use when marking as stale
+staleLabel: inactive
 
-# Number of days of inactivity before a stale Issue or Pull Request is closed.
-# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
-daysUntilClose: 3
-
-# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
-exemptLabels:
-  - hotfix
+# Limit the number of actions per hour, from 1-30. Default is 30
+limitPerRun: 10
 
 # Set to true to ignore issues in a project (defaults to false)
-exemptProjects: false
+exemptProjects: true
 
 # Set to true to ignore issues in a milestone (defaults to false)
 exemptMilestones: true
 
-# Label to use when marking as stale
-staleLabel: inactive
+pulls:
+  daysUntilStale: 15
+  daysUntilClose: 3
+  exemptLabels:
+    - hotfix
+  markComment: >
+    This pull request has been automatically marked as inactive because it has
+    not had recent activity. It will be closed within 3 days if no further
+    activity occurs, but it only takes a comment to keep a contribution alive
+    :) Also, even if it is closed, you can always reopen the PR when you're
+    ready. Thank you for contributing.
 
-# Comment to post when marking as stale. Set to `false` to disable
-markComment: >
-  This pull request has been automatically marked as stale because it has not had
-  recent activity. It will be closed within a week if no further activity occurs, but it
-  only takes a comment to keep a contribution alive :) Also, even if it is closed,
-  you can always reopen the PR when you're ready. Thank you for contributing.
-  
-# Limit the number of actions per hour, from 1-30. Default is 30
-limitPerRun: 30
-
-# Limit to only `issues` or `pulls`
-only: pulls
+issues:
+  daysUntilStale: 60
+  daysUntilClose: 7
+  exemptLabels:
+    - valid
+    - to-validate
+  markComment: >
+    This issue has been automatically marked as inactive because it has not had
+    recent activity and it wasn't validated by maintainer team. It will be
+    closed within a week if no further activity occurs.
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
index 7451917..4839207 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
@@ -10,6 +10,8 @@
 from frappe.model.document import Document
 from frappe.utils import cint
 
+from erpnext.stock.utils import check_pending_reposting
+
 
 class AccountsSettings(Document):
 	def on_update(self):
@@ -25,6 +27,7 @@
 		self.validate_stale_days()
 		self.enable_payment_schedule_in_print()
 		self.toggle_discount_accounting_fields()
+		self.validate_pending_reposts()
 
 	def validate_stale_days(self):
 		if not self.allow_stale and cint(self.stale_days) <= 0:
@@ -56,3 +59,8 @@
 				make_property_setter(doctype, "additional_discount_account", "mandatory_depends_on", "", "Code", validate_fields_for_doctype=False)
 
 		make_property_setter("Item", "default_discount_account", "hidden", not(enable_discount_accounting), "Check", validate_fields_for_doctype=False)
+
+
+	def validate_pending_reposts(self):
+		if self.acc_frozen_upto:
+			check_pending_reposting(self.acc_frozen_upto)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 48b5cb9..f4fd1bf 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -114,6 +114,9 @@
 		self.set_status()
 		self.validate_purchase_receipt_if_update_stock()
 		validate_inter_company_party(self.doctype, self.supplier, self.company, self.inter_company_invoice_reference)
+		self.reset_default_field_value("set_warehouse", "items", "warehouse")
+		self.reset_default_field_value("rejected_warehouse", "items", "rejected_warehouse")
+		self.reset_default_field_value("set_from_warehouse", "items", "from_warehouse")
 
 	def validate_release_date(self):
 		if self.release_date and getdate(nowdate()) >= getdate(self.release_date):
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index c4d59f1..64712b5 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -155,6 +155,8 @@
 		if self.redeem_loyalty_points and self.loyalty_program and self.loyalty_points and not self.is_consolidated:
 			validate_loyalty_points(self, self.loyalty_points)
 
+		self.reset_default_field_value("set_warehouse", "items", "warehouse")
+
 	def validate_fixed_asset(self):
 		for d in self.get("items"):
 			if d.is_fixed_asset and d.meta.get_field("asset") and d.asset:
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 353f908..a990f23 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -545,7 +545,9 @@
 
 	def set_ageing(self, row):
 		if self.filters.ageing_based_on == "Due Date":
-			entry_date = row.due_date
+			# use posting date as a fallback for advances posted via journal and payment entry
+			# when ageing viewed by due date
+			entry_date = row.due_date or row.posting_date
 		elif self.filters.ageing_based_on == "Supplier Invoice Date":
 			entry_date = row.bill_date
 		else:
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 a3a45d1..caee1a1 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
@@ -36,12 +36,16 @@
 			posting_date = entry.posting_date
 			voucher_type = entry.voucher_type
 
+			if not tax_withholding_category:
+				tax_withholding_category = supplier_map.get(supplier, {}).get('tax_withholding_category')
+				rate = tax_rate_map.get(tax_withholding_category)
+
 			if entry.account in tds_accounts:
 				tds_deducted += (entry.credit - entry.debit)
 
 			total_amount_credited += (entry.credit - entry.debit)
 
-		if rate and tds_deducted:
+		if tds_deducted:
 			row = {
 				'pan' if frappe.db.has_column('Supplier', 'pan') else 'tax_id': supplier_map.get(supplier, {}).get('pan'),
 				'supplier': supplier_map.get(supplier, {}).get('name')
@@ -67,7 +71,7 @@
 
 def get_supplier_pan_map():
 	supplier_map = frappe._dict()
-	suppliers = frappe.db.get_all('Supplier', fields=['name', 'pan', 'supplier_type', 'supplier_name'])
+	suppliers = frappe.db.get_all('Supplier', fields=['name', 'pan', 'supplier_type', 'supplier_name', 'tax_withholding_category'])
 
 	for d in suppliers:
 		supplier_map[d.name] = d
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 5eab21b..1b5f35e 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -72,6 +72,7 @@
 		self.create_raw_materials_supplied("supplied_items")
 		self.set_received_qty_for_drop_ship_items()
 		validate_inter_company_party(self.doctype, self.supplier, self.company, self.inter_company_order_reference)
+		self.reset_default_field_value("set_warehouse", "items", "warehouse")
 
 	def validate_with_previous_doc(self):
 		super(PurchaseOrder, self).validate_with_previous_doc({
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index 0a51a8e..023c95d 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -17,6 +17,7 @@
   "company",
   "transaction_date",
   "valid_till",
+  "quotation_number",
   "amended_from",
   "address_section",
   "supplier_address",
@@ -797,6 +798,11 @@
    "fieldtype": "Date",
    "in_list_view": 1,
    "label": "Valid Till"
+  },
+  {
+   "fieldname": "quotation_number",
+   "fieldtype": "Data",
+   "label": "Quotation Number"
   }
  ],
  "icon": "fa fa-shopping-cart",
@@ -804,10 +810,11 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-04-19 00:58:20.995491",
+ "modified": "2021-12-11 06:43:20.924080",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Supplier Quotation",
+ "naming_rule": "By \"Naming Series\" field",
  "owner": "Administrator",
  "permissions": [
   {
diff --git a/erpnext/controllers/tests/test_transaction_base.py b/erpnext/controllers/tests/test_transaction_base.py
new file mode 100644
index 0000000..13aa697
--- /dev/null
+++ b/erpnext/controllers/tests/test_transaction_base.py
@@ -0,0 +1,22 @@
+import unittest
+
+import frappe
+
+
+class TestUtils(unittest.TestCase):
+    def test_reset_default_field_value(self):
+        doc = frappe.get_doc({
+            "doctype": "Purchase Receipt",
+            "set_warehouse": "Warehouse 1",
+        })
+
+        # Same values
+        doc.items = [{"warehouse": "Warehouse 1"}, {"warehouse": "Warehouse 1"}, {"warehouse": "Warehouse 1"}]
+        doc.reset_default_field_value("set_warehouse", "items", "warehouse")
+        self.assertEqual(doc.set_warehouse, "Warehouse 1")
+
+        # Mixed values
+        doc.items = [{"warehouse": "Warehouse 1"}, {"warehouse": "Warehouse 2"}, {"warehouse": "Warehouse 1"}]
+        doc.reset_default_field_value("set_warehouse", "items", "warehouse")
+        self.assertEqual(doc.set_warehouse, None)
+
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 05c46c5..63530ea 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -265,6 +265,9 @@
 			"erpnext.regional.india.utils.update_taxable_values"
 		]
 	},
+	"POS Invoice": {
+		"on_submit": ["erpnext.regional.saudi_arabia.utils.create_qr_code"]
+	},
 	"Purchase Invoice": {
 		"validate": [
 			"erpnext.regional.india.utils.validate_reverse_charge_transaction",
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
index 7f98354..6f6ca61 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
@@ -43,14 +43,11 @@
 				}
 			});
 		}
-		else {
-			frm.clear_table("purposes");
-		}
-
 		if (!frm.doc.status) {
 			frm.set_value({ status: 'Draft' });
 		}
 		if (frm.doc.__islocal) {
+			frm.clear_table("purposes");
 			frm.set_value({ mntc_date: frappe.datetime.get_today() });
 		}
 	},
diff --git a/erpnext/manufacturing/doctype/job_card/job_card_dashboard.py b/erpnext/manufacturing/doctype/job_card/job_card_dashboard.py
index acaa895..2c48872 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card_dashboard.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card_dashboard.py
@@ -4,10 +4,17 @@
 def get_data():
 	return {
 		'fieldname': 'job_card',
+		'non_standard_fieldnames': {
+			'Quality Inspection': 'reference_name'
+		},
 		'transactions': [
 			{
 				'label': _('Transactions'),
 				'items': ['Material Request', 'Stock Entry']
+			},
+			{
+				'label': _('Reference'),
+				'items': ['Quality Inspection']
 			}
 		]
 	}
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index b280247..7b7629f 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -314,4 +314,6 @@
 erpnext.patches.v14_0.delete_hub_doctypes
 erpnext.patches.v13_0.create_ksa_vat_custom_fields
 erpnext.patches.v14_0.migrate_crm_settings
-erpnext.patches.v14_0.add_default_exit_questionnaire_notification_template
+erpnext.patches.v13_0.rename_ksa_qr_field
+erpnext.patches.v13_0.disable_ksa_print_format_for_others
+erpnext.patches.v14_0.add_default_exit_questionnaire_notification_template
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/disable_ksa_print_format_for_others.py b/erpnext/patches/v13_0/disable_ksa_print_format_for_others.py
new file mode 100644
index 0000000..c815b3b
--- /dev/null
+++ b/erpnext/patches/v13_0/disable_ksa_print_format_for_others.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2020, Wahni Green Technologies and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe
+
+
+def execute():
+	company = frappe.get_all('Company', filters = {'country': 'Saudi Arabia'})
+	if company:
+		return
+
+	if frappe.db.exists('DocType', 'Print Format'):
+		frappe.reload_doc("regional", "print_format", "ksa_vat_invoice", force=True)
+		frappe.reload_doc("regional", "print_format", "ksa_pos_invoice", force=True)
+		for d in ('KSA VAT Invoice', 'KSA POS Invoice'):
+			frappe.db.set_value("Print Format", d, "disabled", 1)
diff --git a/erpnext/patches/v13_0/rename_ksa_qr_field.py b/erpnext/patches/v13_0/rename_ksa_qr_field.py
new file mode 100644
index 0000000..0bb86e0
--- /dev/null
+++ b/erpnext/patches/v13_0/rename_ksa_qr_field.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2020, Wahni Green Technologies and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe
+from frappe.model.utils.rename_field import rename_field
+
+
+def execute():
+	company = frappe.get_all('Company', filters = {'country': 'Saudi Arabia'})
+	if not company:
+		return
+
+	if frappe.db.exists('DocType', 'Sales Invoice'):
+		frappe.reload_doc('accounts', 'doctype', 'sales_invoice', force=True)
+		if frappe.db.has_column('Sales Invoice', 'qr_code'):
+			rename_field('Sales Invoice', 'qr_code', 'ksa_einv_qr')
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index f0facdd..cad1659 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -84,6 +84,10 @@
 		});
 	},
 
+	route_to_pending_reposts: (args) => {
+		frappe.set_route('List', 'Repost Item Valuation', args);
+	},
+
 	proceed_save_with_reminders_frequency_change: () => {
 		frappe.ui.hide_open_dialog();
 
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index bbca772..fd3ec3c 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -213,10 +213,11 @@
 		tax_template_by_category = get_tax_template_based_on_category(master_doctype, company, party_details)
 
 	if tax_template_by_category:
-		party_details.get['taxes_and_charges'] = tax_template_by_category
+		party_details['taxes_and_charges'] = tax_template_by_category
 		return
 
 	if not party_details.place_of_supply: return party_details
+	if not party_details.company_gstin: return party_details
 
 	if ((doctype in ("Sales Invoice", "Delivery Note", "Sales Order") and party_details.company_gstin
 		and party_details.company_gstin[:2] != party_details.place_of_supply[:2]) or (doctype in ("Purchase Invoice",
diff --git a/erpnext/regional/print_format/ksa_pos_invoice/__init__.py b/erpnext/regional/print_format/ksa_pos_invoice/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/regional/print_format/ksa_pos_invoice/__init__.py
diff --git a/erpnext/regional/print_format/ksa_pos_invoice/ksa_pos_invoice.json b/erpnext/regional/print_format/ksa_pos_invoice/ksa_pos_invoice.json
new file mode 100644
index 0000000..c2a3092
--- /dev/null
+++ b/erpnext/regional/print_format/ksa_pos_invoice/ksa_pos_invoice.json
@@ -0,0 +1,32 @@
+{
+ "absolute_value": 0,
+ "align_labels_right": 0,
+ "creation": "2021-12-07 13:25:05.424827",
+ "css": "",
+ "custom_format": 1,
+ "default_print_language": "en",
+ "disabled": 1,
+ "doc_type": "POS Invoice",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font_size": 0,
+ "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tline-height: 150%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n\n<p class=\"text-center\" style=\"margin-bottom: 1rem\">\n\t{{ doc.company }}<br>\n\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n\t<img src={{doc.ksa_einv_qr}}>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Cashier\") }}:</b> {{ doc.owner }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Time\") }}:</b> {{  doc.get_formatted(\"posting_time\") }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"35%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"SR.No\") }}:</b><br>\n\t\t\t\t\t{{ item.serial_no | replace(\"\\n\", \", \") }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"net_amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t    {% if '%' in row.description %}\n\t\t\t\t\t    {{ row.description }}\n\t\t\t\t\t{% else %}\n\t\t\t\t\t    {{ row.description }}@{{ row.rate }}%\n\t\t\t\t\t{% endif %}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
+ "idx": 0,
+ "line_breaks": 0,
+ "margin_bottom": 0.0,
+ "margin_left": 0.0,
+ "margin_right": 0.0,
+ "margin_top": 0.0,
+ "modified": "2021-12-08 10:25:01.930885",
+ "modified_by": "Administrator",
+ "module": "Regional",
+ "name": "KSA POS Invoice",
+ "owner": "Administrator",
+ "page_number": "Hide",
+ "print_format_builder": 0,
+ "print_format_builder_beta": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 0,
+ "standard": "Yes"
+}
\ No newline at end of file
diff --git a/erpnext/regional/print_format/ksa_vat_invoice/ksa_vat_invoice.json b/erpnext/regional/print_format/ksa_vat_invoice/ksa_vat_invoice.json
index 8e9a728..6b64d47 100644
--- a/erpnext/regional/print_format/ksa_vat_invoice/ksa_vat_invoice.json
+++ b/erpnext/regional/print_format/ksa_vat_invoice/ksa_vat_invoice.json
@@ -5,19 +5,19 @@
  "css": ".qr-code{\n    float:right;\n}\n\n.invoice-heading {\n  margin: 0;\n}\n\n.ksa-invoice-table {\n  border: 1px solid #888a8e;\n  border-collapse: collapse;\n  width: 100%;\n  margin: 20px 0;\n  font-size: 16px;\n}\n\n.ksa-invoice-table.two-columns td:nth-child(2) {\n  direction: rtl;\n}\n\n.ksa-invoice-table th {\n  border: 1px solid #888a8e;\n  max-width: 50%;\n  padding: 8px;\n}\n\n.ksa-invoice-table td {\n  padding: 5px;\n  border: 1px solid #888a8e;\n  max-width: 50%;\n}\n\n.ksa-invoice-table thead,\n.ksa-invoice-table tfoot {\n  text-transform: uppercase;\n}\n\n.qr-rtl {\n  direction: rtl;\n}\n\n.qr-flex{\n    display: flex;\n    justify-content: space-between;\n}",
  "custom_format": 1,
  "default_print_language": "en",
- "disabled": 0,
+ "disabled": 1,
  "doc_type": "Sales Invoice",
  "docstatus": 0,
  "doctype": "Print Format",
  "font_size": 14,
- "html": "<div class=\"ksa-vat-format\">\n    <div class=\"qr-flex\">\n        <div style=\"qr-flex: 1\">\n            <h2 class=\"invoice-heading\">TAX INVOICE</h2>\n            <h2 class=\"invoice-heading\">\u0641\u0627\u062a\u0648\u0631\u0629 \u0636\u0631\u064a\u0628\u064a\u0629</h2>\n        </div>\n        \n        <img class=\"qr-code\" src={{doc.qr_code}}>\n    </div>\n    {% set company = frappe.get_doc(\"Company\", doc.company)%}\n    {% if (doc.company_address) %}\n        {% set supplier_address_doc = frappe.get_doc('Address', doc.company_address) %}\n    {% endif %}\n    \n    {% if(doc.customer_address) %}\n        {% set customer_address = frappe.get_doc('Address', doc.customer_address ) %}\n    {% endif %}\n    \n    {% if(doc.shipping_address_name) %}\n        {% set customer_shipping_address = frappe.get_doc('Address', doc.shipping_address_name ) %}\n    {% endif %}  \n        \n    <table class=\"ksa-invoice-table two-columns\">\n      <thead>\n        <tr>\n          <th>{{ company.name }}</th>\n          <th style=\"text-align: right;\">{{ company.company_name_in_arabic }}</th>\n        </tr>\n      </thead>\n\n      <tbody>\n        <!-- Invoice Info -->\n        <tr>\n          <td>Invoice#: {{doc.name}}</td>\n          <td>\u0631\u0642\u0645 \u0627\u0644\u0641\u0627\u062a\u0648\u0631\u0629: {{doc.name}}</td>\n        </tr>\n        <tr>\n          <td>Invoice Date: {{doc.posting_date}}</td>\n          <td>\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0641\u0627\u062a\u0648\u0631\u0629: {{doc.posting_date}}</td>\n        </tr>\n        <tr>\n          <td>Date of Supply:{{doc.posting_date}}</td>\n          <td>\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u062a\u0648\u0631\u064a\u062f: {{doc.posting_date}}</td>\n        </tr>\n        \n        <!--Supplier Info -->\n        <tr>\n          <td>Supplier:</td>\n          <td>\u0627\u0644\u0645\u0648\u0631\u062f:</td>\n        </tr>\n\t\t{% if (company.tax_id) %}\n        <tr>\n          <td>Supplier Tax Identification Number:</td>\n          <td>\u0631\u0642\u0645 \u0627\u0644\u062a\u0639\u0631\u064a\u0641 \u0627\u0644\u0636\u0631\u064a\u0628\u064a \u0644\u0644\u0645\u0648\u0631\u062f:</td>\n        </tr>\n        <tr>\n          <td>{{ company.tax_id }}</td>\n          <td>{{ company.tax_id }}</td>\n        </tr>\n        {% endif %}\n        <tr>\n          <td>{{ company.name }}</td>\n          <td>{{ company.company_name_in_arabic }} </td>\n        </tr>\n        \n        \n        {% if(supplier_address_doc) %}\n        <tr>\n          <td>{{ supplier_address_doc.address_line1}} </td>\n          <td>{{ supplier_address_doc.address_in_arabic}} </td>\n        </tr>\n        <tr>\n          <td>Phone: {{ supplier_address_doc.phone }}</td>\n          <td>\u0647\u0627\u062a\u0641: {{ supplier_address_doc.phone }}</td>\n        </tr>\n        <tr>\n          <td>Email: {{ supplier_address_doc.email_id }}</td>\n          <td>\u0628\u0631\u064a\u062f \u0627\u0644\u0643\u062a\u0631\u0648\u0646\u064a: {{ supplier_address_doc.email_id }}</td>\n        </tr>\n        {% endif %}\n        \n        <!-- Customer Info -->\n        <tr>\n          <td>CUSTOMER:</td>\n          <td>\u0639\u0645\u064a\u0644:</td>\n        </tr>\n\t\t{% set customer_tax_id = frappe.db.get_value('Customer', doc.customer, 'tax_id') %}\n\t\t{% if customer_tax_id %}\n        <tr>\n          <td>Customer Tax Identification Number:</td>\n          <td>\u0631\u0642\u0645 \u0627\u0644\u062a\u0639\u0631\u064a\u0641 \u0627\u0644\u0636\u0631\u064a\u0628\u064a \u0644\u0644\u0639\u0645\u064a\u0644:</td>\n        </tr>\n        <tr>\n          <td>{{ customer_tax_id }}</td>\n          <td>{{ customer_tax_id }}</td>\n        </tr>\n        {% endif %}\n        <tr>\n          <td> {{ doc.customer }}</td>\n          <td> {{ doc.customer_name_in_arabic }} </td>\n        </tr>\n        \n        {% if(customer_address) %}\n        <tr>\n          <td>{{ customer_address.address_line1}} </td>\n          <td>{{ customer_address.address_in_arabic}} </td>\n        </tr>\n        {% endif %}\n        \n        {% if(customer_shipping_address) %}\n        <tr>\n          <td>SHIPPING ADDRESS:</td>\n          <td>\u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u0634\u062d\u0646:</td>\n        </tr>\n        \n        <tr>\n          <td>{{ customer_shipping_address.address_line1}} </td>\n          <td>{{ customer_shipping_address.address_in_arabic}} </td>\n        </tr>\n        {% endif %}\n        \n\t\t{% if(doc.po_no) %}\n        <tr>\n          <td>OTHER INFORMATION</td>\n          <td>\u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0623\u062e\u0631\u0649</td>\n        </tr>\n        \n        <tr>\n          <td>Purchase Order Number: {{ doc.po_no }}</td>\n          <td>\u0631\u0642\u0645 \u0623\u0645\u0631 \u0627\u0644\u0634\u0631\u0627\u0621: {{ doc.po_no }}</td>\n        </tr>\n        {% endif %}\n        \n        <tr>\n          <td>Payment Due Date: {{  doc.due_date}} </td>\n          <td>\u062a\u0627\u0631\u064a\u062e \u0627\u0633\u062a\u062d\u0642\u0627\u0642 \u0627\u0644\u062f\u0641\u0639: {{  doc.due_date}}</td>\n        </tr>\n      </tbody>\n    </table>\n\n    <!--Dynamic Colspan for total row columns-->\n    {% set col = namespace(one = 2, two = 1) %}\n    {% set length = doc.taxes | length %}\n    {% set length = length / 2 | round %}\n    {% set col.one = col.one + length %}\n    {% set col.two = col.two + length %}\n  \n    {%- if(doc.taxes | length % 2 > 0 ) -%}\n      {% set col.two = col.two + 1 %}\n    {% endif %}\n    \n    <!-- Items -->\n    {% set total = namespace(amount = 0) %}\n    <table class=\"ksa-invoice-table\">\n      <thead>\n        <tr>\n          <th>Nature of goods or services <br />\u0637\u0628\u064a\u0639\u0629 \u0627\u0644\u0633\u0644\u0639 \u0623\u0648 \u0627\u0644\u062e\u062f\u0645\u0627\u062a</th>\n          <th>\n            Unit price <br />\n            \u0633\u0639\u0631 \u0627\u0644\u0648\u062d\u062f\u0629\n          </th>\n          <th>\n            Quantity <br />\n            \u0627\u0644\u0643\u0645\u064a\u0629\n          </th>\n          <th>\n            Taxable Amount <br />\n            \u0627\u0644\u0645\u0628\u0644\u063a \u0627\u0644\u062e\u0627\u0636\u0639 \u0644\u0644\u0636\u0631\u064a\u0628\u0629\n          </th>\n          \n          {% for row in doc.taxes %}\n            <th style=\"min-width: 130px\">{{row.description}}</th>\n          {% endfor %}\n          \n          <th>\n            Total <br />\n            \u0627\u0644\u0645\u062c\u0645\u0648\u0639\n          </th>\n        </tr>\n      </thead>\n      <tbody>\n        {%- for item in doc.items -%}\n        {% set total.amount = item.amount %}\n        <tr>\n          <td>{{ item.item_code or item.item_name }}</td>\n          <td>{{ item.get_formatted(\"rate\") }}</td>\n          <td>{{ item.qty }}</td>\n          <td>{{ item.get_formatted(\"amount\") }}</td>\n           {% for row in doc.taxes %}\n                {% set data_object = json.loads(row.item_wise_tax_detail) %}\n                {% set key = item.item_code or item.item_name %}\n                {% set tax_amount = frappe.utils.flt(data_object[key][1]/doc.conversion_rate, row.precision('tax_amount')) %}\n                <td>\n                   <div class=\"qr-flex\">\n                    {%- if(data_object[key][0])-%}\n                    <span>{{ frappe.format(data_object[key][0], {'fieldtype': 'Percent'}) }}</span>\n                    {%- endif -%}\n                    <span>\n                    {%- if(data_object[key][1])-%}\n                        {{ frappe.format_value(tax_amount, currency=doc.currency) }}</span>\n                        {% set total.amount = total.amount + tax_amount %}\n                    {%- endif -%}\n                    </div>\n                </td>\n            {% endfor %}\n          <td>{{  frappe.format_value(frappe.utils.flt(total.amount, doc.precision('total_taxes_and_charges')), currency=doc.currency) }}</td>\n        </tr>\n        {%- endfor -%}\n      </tbody>\n      <tfoot>\n        <tr>\n          <td>\n            {{ doc.get_formatted(\"total\") }} <br />\n            {{ doc.get_formatted(\"total_taxes_and_charges\") }}\n          </td>\n          \n          <td colspan={{ col.one }} class=\"qr-rtl\">\n            \u0627\u0644\u0625\u062c\u0645\u0627\u0644\u064a \u0628\u0627\u0633\u062a\u062b\u0646\u0627\u0621 \u0636\u0631\u064a\u0628\u0629 \u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0645\u0636\u0627\u0641\u0629\n            <br />\n            \u0625\u062c\u0645\u0627\u0644\u064a \u0636\u0631\u064a\u0628\u0629 \u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0645\u0636\u0627\u0641\u0629\n          </td>\n          <td colspan={{ col.two }}>\n            Total (Excluding VAT)\n            <br />\n            Total VAT\n          </td>\n          <td>\n            {{ doc.get_formatted(\"total\") }} <br />\n            {{ doc.get_formatted(\"total_taxes_and_charges\") }}\n          </td>\n        </tr>\n        <tr>\n          <td>{{ doc.get_formatted(\"grand_total\") }}</td>\n          <td  colspan={{  col.one }} class=\"qr-rtl\">\n              \u0625\u062c\u0645\u0627\u0644\u064a \u0627\u0644\u0645\u0628\u0644\u063a \u0627\u0644\u0645\u0633\u062a\u062d\u0642</td>\n          <td  colspan={{  col.two }}>Total Amount Due</td>\n          <td>{{ doc.get_formatted(\"grand_total\") }}</td>\n        </tr>\n      </tfoot>\n    </table>\n\n\t{%- if doc.terms -%}\n    <p>\n      {{doc.terms}}\n    </p>\n\t{%- endif -%}\n</div>\n",
+ "html": "<div class=\"ksa-vat-format\">\n    <div class=\"qr-flex\">\n        <div style=\"qr-flex: 1\">\n            <h2 class=\"invoice-heading\">TAX INVOICE</h2>\n            <h2 class=\"invoice-heading\">\u0641\u0627\u062a\u0648\u0631\u0629 \u0636\u0631\u064a\u0628\u064a\u0629</h2>\n        </div>\n        \n        <img class=\"qr-code\" src={{doc.ksa_einv_qr}}>\n    </div>\n    {% set company = frappe.get_doc(\"Company\", doc.company)%}\n    {% if (doc.company_address) %}\n        {% set supplier_address_doc = frappe.get_doc('Address', doc.company_address) %}\n    {% endif %}\n    \n    {% if(doc.customer_address) %}\n        {% set customer_address = frappe.get_doc('Address', doc.customer_address ) %}\n    {% endif %}\n    \n    {% if(doc.shipping_address_name) %}\n        {% set customer_shipping_address = frappe.get_doc('Address', doc.shipping_address_name ) %}\n    {% endif %}  \n        \n    <table class=\"ksa-invoice-table two-columns\">\n      <thead>\n        <tr>\n          <th>{{ company.name }}</th>\n          <th style=\"text-align: right;\">{{ company.company_name_in_arabic }}</th>\n        </tr>\n      </thead>\n\n      <tbody>\n        <!-- Invoice Info -->\n        <tr>\n          <td>Invoice#: {{doc.name}}</td>\n          <td>\u0631\u0642\u0645 \u0627\u0644\u0641\u0627\u062a\u0648\u0631\u0629: {{doc.name}}</td>\n        </tr>\n        <tr>\n          <td>Invoice Date: {{doc.posting_date}}</td>\n          <td>\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0641\u0627\u062a\u0648\u0631\u0629: {{doc.posting_date}}</td>\n        </tr>\n        <tr>\n          <td>Date of Supply:{{doc.posting_date}}</td>\n          <td>\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u062a\u0648\u0631\u064a\u062f: {{doc.posting_date}}</td>\n        </tr>\n        \n        <!--Supplier Info -->\n        <tr>\n          <td>Supplier:</td>\n          <td>\u0627\u0644\u0645\u0648\u0631\u062f:</td>\n        </tr>\n\t\t{% if (company.tax_id) %}\n        <tr>\n          <td>Supplier Tax Identification Number:</td>\n          <td>\u0631\u0642\u0645 \u0627\u0644\u062a\u0639\u0631\u064a\u0641 \u0627\u0644\u0636\u0631\u064a\u0628\u064a \u0644\u0644\u0645\u0648\u0631\u062f:</td>\n        </tr>\n        <tr>\n          <td>{{ company.tax_id }}</td>\n          <td>{{ company.tax_id }}</td>\n        </tr>\n        {% endif %}\n        <tr>\n          <td>{{ company.name }}</td>\n          <td>{{ company.company_name_in_arabic }} </td>\n        </tr>\n        \n        \n        {% if(supplier_address_doc) %}\n        <tr>\n          <td>{{ supplier_address_doc.address_line1}} </td>\n          <td>{{ supplier_address_doc.address_in_arabic}} </td>\n        </tr>\n        <tr>\n          <td>Phone: {{ supplier_address_doc.phone }}</td>\n          <td>\u0647\u0627\u062a\u0641: {{ supplier_address_doc.phone }}</td>\n        </tr>\n        <tr>\n          <td>Email: {{ supplier_address_doc.email_id }}</td>\n          <td>\u0628\u0631\u064a\u062f \u0627\u0644\u0643\u062a\u0631\u0648\u0646\u064a: {{ supplier_address_doc.email_id }}</td>\n        </tr>\n        {% endif %}\n        \n        <!-- Customer Info -->\n        <tr>\n          <td>CUSTOMER:</td>\n          <td>\u0639\u0645\u064a\u0644:</td>\n        </tr>\n\t\t{% set customer_tax_id = frappe.db.get_value('Customer', doc.customer, 'tax_id') %}\n\t\t{% if customer_tax_id %}\n        <tr>\n          <td>Customer Tax Identification Number:</td>\n          <td>\u0631\u0642\u0645 \u0627\u0644\u062a\u0639\u0631\u064a\u0641 \u0627\u0644\u0636\u0631\u064a\u0628\u064a \u0644\u0644\u0639\u0645\u064a\u0644:</td>\n        </tr>\n        <tr>\n          <td>{{ customer_tax_id }}</td>\n          <td>{{ customer_tax_id }}</td>\n        </tr>\n        {% endif %}\n        <tr>\n          <td> {{ doc.customer }}</td>\n          <td> {{ doc.customer_name_in_arabic }} </td>\n        </tr>\n        \n        {% if(customer_address) %}\n        <tr>\n          <td>{{ customer_address.address_line1}} </td>\n          <td>{{ customer_address.address_in_arabic}} </td>\n        </tr>\n        {% endif %}\n        \n        {% if(customer_shipping_address) %}\n        <tr>\n          <td>SHIPPING ADDRESS:</td>\n          <td>\u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u0634\u062d\u0646:</td>\n        </tr>\n        \n        <tr>\n          <td>{{ customer_shipping_address.address_line1}} </td>\n          <td>{{ customer_shipping_address.address_in_arabic}} </td>\n        </tr>\n        {% endif %}\n        \n\t\t{% if(doc.po_no) %}\n        <tr>\n          <td>OTHER INFORMATION</td>\n          <td>\u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0623\u062e\u0631\u0649</td>\n        </tr>\n        \n        <tr>\n          <td>Purchase Order Number: {{ doc.po_no }}</td>\n          <td>\u0631\u0642\u0645 \u0623\u0645\u0631 \u0627\u0644\u0634\u0631\u0627\u0621: {{ doc.po_no }}</td>\n        </tr>\n        {% endif %}\n        \n        <tr>\n          <td>Payment Due Date: {{  doc.due_date}} </td>\n          <td>\u062a\u0627\u0631\u064a\u062e \u0627\u0633\u062a\u062d\u0642\u0627\u0642 \u0627\u0644\u062f\u0641\u0639: {{  doc.due_date}}</td>\n        </tr>\n      </tbody>\n    </table>\n\n    <!--Dynamic Colspan for total row columns-->\n    {% set col = namespace(one = 2, two = 1) %}\n    {% set length = doc.taxes | length %}\n    {% set length = length / 2 | round %}\n    {% set col.one = col.one + length %}\n    {% set col.two = col.two + length %}\n  \n    {%- if(doc.taxes | length % 2 > 0 ) -%}\n      {% set col.two = col.two + 1 %}\n    {% endif %}\n    \n    <!-- Items -->\n    {% set total = namespace(amount = 0) %}\n    <table class=\"ksa-invoice-table\">\n      <thead>\n        <tr>\n          <th>Nature of goods or services <br />\u0637\u0628\u064a\u0639\u0629 \u0627\u0644\u0633\u0644\u0639 \u0623\u0648 \u0627\u0644\u062e\u062f\u0645\u0627\u062a</th>\n          <th>\n            Unit price <br />\n            \u0633\u0639\u0631 \u0627\u0644\u0648\u062d\u062f\u0629\n          </th>\n          <th>\n            Quantity <br />\n            \u0627\u0644\u0643\u0645\u064a\u0629\n          </th>\n          <th>\n            Taxable Amount <br />\n            \u0627\u0644\u0645\u0628\u0644\u063a \u0627\u0644\u062e\u0627\u0636\u0639 \u0644\u0644\u0636\u0631\u064a\u0628\u0629\n          </th>\n          \n          {% for row in doc.taxes %}\n            <th style=\"min-width: 130px\">{{row.description}}</th>\n          {% endfor %}\n          \n          <th>\n            Total <br />\n            \u0627\u0644\u0645\u062c\u0645\u0648\u0639\n          </th>\n        </tr>\n      </thead>\n      <tbody>\n        {%- for item in doc.items -%}\n        {% set total.amount = item.amount %}\n        <tr>\n          <td>{{ item.item_code or item.item_name }}</td>\n          <td>{{ item.get_formatted(\"rate\") }}</td>\n          <td>{{ item.qty }}</td>\n          <td>{{ item.get_formatted(\"amount\") }}</td>\n           {% for row in doc.taxes %}\n                {% set data_object = json.loads(row.item_wise_tax_detail) %}\n                {% set key = item.item_code or item.item_name %}\n                {% set tax_amount = frappe.utils.flt(data_object[key][1]/doc.conversion_rate, row.precision('tax_amount')) %}\n                <td>\n                   <div class=\"qr-flex\">\n                    {%- if(data_object[key][0])-%}\n                    <span>{{ frappe.format(data_object[key][0], {'fieldtype': 'Percent'}) }}</span>\n                    {%- endif -%}\n                    <span>\n                    {%- if(data_object[key][1])-%}\n                        {{ frappe.format_value(tax_amount, currency=doc.currency) }}</span>\n                        {% set total.amount = total.amount + tax_amount %}\n                    {%- endif -%}\n                    </div>\n                </td>\n            {% endfor %}\n          <td>{{  frappe.format_value(frappe.utils.flt(total.amount, doc.precision('total_taxes_and_charges')), currency=doc.currency) }}</td>\n        </tr>\n        {%- endfor -%}\n      </tbody>\n      <tfoot>\n        <tr>\n          <td>\n            {{ doc.get_formatted(\"total\") }} <br />\n            {{ doc.get_formatted(\"total_taxes_and_charges\") }}\n          </td>\n          \n          <td colspan={{ col.one }} class=\"qr-rtl\">\n            \u0627\u0644\u0625\u062c\u0645\u0627\u0644\u064a \u0628\u0627\u0633\u062a\u062b\u0646\u0627\u0621 \u0636\u0631\u064a\u0628\u0629 \u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0645\u0636\u0627\u0641\u0629\n            <br />\n            \u0625\u062c\u0645\u0627\u0644\u064a \u0636\u0631\u064a\u0628\u0629 \u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0645\u0636\u0627\u0641\u0629\n          </td>\n          <td colspan={{ col.two }}>\n            Total (Excluding VAT)\n            <br />\n            Total VAT\n          </td>\n          <td>\n            {{ doc.get_formatted(\"total\") }} <br />\n            {{ doc.get_formatted(\"total_taxes_and_charges\") }}\n          </td>\n        </tr>\n        <tr>\n          <td>{{ doc.get_formatted(\"grand_total\") }}</td>\n          <td  colspan={{  col.one }} class=\"qr-rtl\">\n              \u0625\u062c\u0645\u0627\u0644\u064a \u0627\u0644\u0645\u0628\u0644\u063a \u0627\u0644\u0645\u0633\u062a\u062d\u0642</td>\n          <td  colspan={{  col.two }}>Total Amount Due</td>\n          <td>{{ doc.get_formatted(\"grand_total\") }}</td>\n        </tr>\n      </tfoot>\n    </table>\n\n\t{%- if doc.terms -%}\n    <p>\n      {{doc.terms}}\n    </p>\n\t{%- endif -%}\n</div>\n",
  "idx": 0,
  "line_breaks": 0,
  "margin_bottom": 15.0,
  "margin_left": 15.0,
  "margin_right": 15.0,
  "margin_top": 15.0,
- "modified": "2021-11-29 13:47:37.870818",
+ "modified": "2021-12-07 13:43:38.018593",
  "modified_by": "Administrator",
  "module": "Regional",
  "name": "KSA VAT Invoice",
diff --git a/erpnext/regional/saudi_arabia/setup.py b/erpnext/regional/saudi_arabia/setup.py
index 38a089c..2e31c03 100644
--- a/erpnext/regional/saudi_arabia/setup.py
+++ b/erpnext/regional/saudi_arabia/setup.py
@@ -3,7 +3,7 @@
 
 import frappe
 from frappe.permissions import add_permission, update_permission_property
-from erpnext.regional.united_arab_emirates.setup import make_custom_fields as uae_custom_fields, add_print_formats
+from erpnext.regional.united_arab_emirates.setup import make_custom_fields as uae_custom_fields
 from erpnext.regional.saudi_arabia.wizard.operations.setup_ksa_vat_setting import create_ksa_vat_setting
 from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
 
@@ -13,6 +13,16 @@
 	add_permissions()
 	make_custom_fields()
 
+def add_print_formats():
+	frappe.reload_doc("regional", "print_format", "detailed_tax_invoice", force=True)
+	frappe.reload_doc("regional", "print_format", "simplified_tax_invoice", force=True)
+	frappe.reload_doc("regional", "print_format", "tax_invoice", force=True)
+	frappe.reload_doc("regional", "print_format", "ksa_vat_invoice", force=True)
+	frappe.reload_doc("regional", "print_format", "ksa_pos_invoice", force=True)
+
+	for d in ('Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice', 'KSA VAT Invoice', 'KSA POS Invoice'):
+		frappe.db.set_value("Print Format", d, "disabled", 0)
+
 def add_permissions():
 	"""Add Permissions for KSA VAT Setting."""
 	add_permission('KSA VAT Setting', 'All', 0)
@@ -33,8 +43,16 @@
 	custom_fields = {
 		'Sales Invoice': [
 			dict(
-				fieldname='qr_code',
-				label='QR Code',
+				fieldname='ksa_einv_qr',
+				label='KSA E-Invoicing QR',
+				fieldtype='Attach Image',
+				read_only=1, no_copy=1, hidden=1
+			)
+		],
+		'POS Invoice': [
+			dict(
+				fieldname='ksa_einv_qr',
+				label='KSA E-Invoicing QR',
 				fieldtype='Attach Image',
 				read_only=1, no_copy=1, hidden=1
 			)
diff --git a/erpnext/regional/saudi_arabia/utils.py b/erpnext/regional/saudi_arabia/utils.py
index 7d00d8b..a03c3f0 100644
--- a/erpnext/regional/saudi_arabia/utils.py
+++ b/erpnext/regional/saudi_arabia/utils.py
@@ -4,144 +4,146 @@
 
 import frappe
 from frappe import _
+from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
 from frappe.utils.data import add_to_date, get_time, getdate
 from pyqrcode import create as qr_create
 
 from erpnext import get_region
 
 
-def create_qr_code(doc, method):
-	"""Create QR Code after inserting Sales Inv
-	"""
-
+def create_qr_code(doc, method=None):
 	region = get_region(doc.company)
 	if region not in ['Saudi Arabia']:
 		return
 
-	# if QR Code field not present, do nothing
-	if not hasattr(doc, 'qr_code'):
-		return
+	# if QR Code field not present, create it. Invoices without QR are invalid as per law.
+	if not hasattr(doc, 'ksa_einv_qr'):
+		create_custom_fields({
+			doc.doctype: [
+				dict(
+					fieldname='ksa_einv_qr',
+					label='KSA E-Invoicing QR',
+					fieldtype='Attach Image',
+					read_only=1, no_copy=1, hidden=1
+				)
+			]
+		})
 
 	# Don't create QR Code if it already exists
-	qr_code = doc.get("qr_code")
+	qr_code = doc.get("ksa_einv_qr")
 	if qr_code and frappe.db.exists({"doctype": "File", "file_url": qr_code}):
 		return
 
-	meta = frappe.get_meta('Sales Invoice')
+	meta = frappe.get_meta(doc.doctype)
 
-	for field in meta.get_image_fields():
-		if field.fieldname == 'qr_code':
-			''' TLV conversion for
-			1. Seller's Name
-			2. VAT Number
-			3. Time Stamp
-			4. Invoice Amount
-			5. VAT Amount
-			'''
-			tlv_array = []
-			# Sellers Name
+	if "ksa_einv_qr" in [d.fieldname for d in meta.get_image_fields()]:
+		''' TLV conversion for
+		1. Seller's Name
+		2. VAT Number
+		3. Time Stamp
+		4. Invoice Amount
+		5. VAT Amount
+		'''
+		tlv_array = []
+		# Sellers Name
 
-			seller_name = frappe.db.get_value(
-				'Company',
-				doc.company,
-				'company_name_in_arabic')
+		seller_name = frappe.db.get_value(
+			'Company',
+			doc.company,
+			'company_name_in_arabic')
 
-			if not seller_name:
-				frappe.throw(_('Arabic name missing for {} in the company document').format(doc.company))
+		if not seller_name:
+			frappe.throw(_('Arabic name missing for {} in the company document').format(doc.company))
 
-			tag = bytes([1]).hex()
-			length = bytes([len(seller_name.encode('utf-8'))]).hex()
-			value = seller_name.encode('utf-8').hex()
-			tlv_array.append(''.join([tag, length, value]))
+		tag = bytes([1]).hex()
+		length = bytes([len(seller_name.encode('utf-8'))]).hex()
+		value = seller_name.encode('utf-8').hex()
+		tlv_array.append(''.join([tag, length, value]))
 
-			# VAT Number
-			tax_id = frappe.db.get_value('Company', doc.company, 'tax_id')
-			if not tax_id:
-				frappe.throw(_('Tax ID missing for {} in the company document').format(doc.company))
+		# VAT Number
+		tax_id = frappe.db.get_value('Company', doc.company, 'tax_id')
+		if not tax_id:
+			frappe.throw(_('Tax ID missing for {} in the company document').format(doc.company))
 
-			tag = bytes([2]).hex()
-			length = bytes([len(tax_id)]).hex()
-			value = tax_id.encode('utf-8').hex()
-			tlv_array.append(''.join([tag, length, value]))
+		tag = bytes([2]).hex()
+		length = bytes([len(tax_id)]).hex()
+		value = tax_id.encode('utf-8').hex()
+		tlv_array.append(''.join([tag, length, value]))
 
-			# Time Stamp
-			posting_date = getdate(doc.posting_date)
-			time = get_time(doc.posting_time)
-			seconds = time.hour * 60 * 60 + time.minute * 60 + time.second
-			time_stamp = add_to_date(posting_date, seconds=seconds)
-			time_stamp = time_stamp.strftime('%Y-%m-%dT%H:%M:%SZ')
+		# Time Stamp
+		posting_date = getdate(doc.posting_date)
+		time = get_time(doc.posting_time)
+		seconds = time.hour * 60 * 60 + time.minute * 60 + time.second
+		time_stamp = add_to_date(posting_date, seconds=seconds)
+		time_stamp = time_stamp.strftime('%Y-%m-%dT%H:%M:%SZ')
 
-			tag = bytes([3]).hex()
-			length = bytes([len(time_stamp)]).hex()
-			value = time_stamp.encode('utf-8').hex()
-			tlv_array.append(''.join([tag, length, value]))
+		tag = bytes([3]).hex()
+		length = bytes([len(time_stamp)]).hex()
+		value = time_stamp.encode('utf-8').hex()
+		tlv_array.append(''.join([tag, length, value]))
 
-			# Invoice Amount
-			invoice_amount = str(doc.grand_total)
-			tag = bytes([4]).hex()
-			length = bytes([len(invoice_amount)]).hex()
-			value = invoice_amount.encode('utf-8').hex()
-			tlv_array.append(''.join([tag, length, value]))
+		# Invoice Amount
+		invoice_amount = str(doc.grand_total)
+		tag = bytes([4]).hex()
+		length = bytes([len(invoice_amount)]).hex()
+		value = invoice_amount.encode('utf-8').hex()
+		tlv_array.append(''.join([tag, length, value]))
 
-			# VAT Amount
-			vat_amount = str(doc.total_taxes_and_charges)
+		# VAT Amount
+		vat_amount = str(doc.total_taxes_and_charges)
 
-			tag = bytes([5]).hex()
-			length = bytes([len(vat_amount)]).hex()
-			value = vat_amount.encode('utf-8').hex()
-			tlv_array.append(''.join([tag, length, value]))
+		tag = bytes([5]).hex()
+		length = bytes([len(vat_amount)]).hex()
+		value = vat_amount.encode('utf-8').hex()
+		tlv_array.append(''.join([tag, length, value]))
 
-			# Joining bytes into one
-			tlv_buff = ''.join(tlv_array)
+		# Joining bytes into one
+		tlv_buff = ''.join(tlv_array)
 
-			# base64 conversion for QR Code
-			base64_string = b64encode(bytes.fromhex(tlv_buff)).decode()
+		# base64 conversion for QR Code
+		base64_string = b64encode(bytes.fromhex(tlv_buff)).decode()
 
-			qr_image = io.BytesIO()
-			url = qr_create(base64_string, error='L')
-			url.png(qr_image, scale=2, quiet_zone=1)
+		qr_image = io.BytesIO()
+		url = qr_create(base64_string, error='L')
+		url.png(qr_image, scale=2, quiet_zone=1)
 
-			name = frappe.generate_hash(doc.name, 5)
+		name = frappe.generate_hash(doc.name, 5)
 
-			# making file
-			filename = f"QRCode-{name}.png".replace(os.path.sep, "__")
-			_file = frappe.get_doc({
-				"doctype": "File",
-				"file_name": filename,
-				"is_private": 0,
-				"content": qr_image.getvalue(),
-				"attached_to_doctype": doc.get("doctype"),
-				"attached_to_name": doc.get("name"),
-				"attached_to_field": "qr_code"
-			})
+		# making file
+		filename = f"QRCode-{name}.png".replace(os.path.sep, "__")
+		_file = frappe.get_doc({
+			"doctype": "File",
+			"file_name": filename,
+			"is_private": 0,
+			"content": qr_image.getvalue(),
+			"attached_to_doctype": doc.get("doctype"),
+			"attached_to_name": doc.get("name"),
+			"attached_to_field": "ksa_einv_qr"
+		})
 
-			_file.save()
+		_file.save()
 
-			# assigning to document
-			doc.db_set('qr_code', _file.file_url)
-			doc.notify_update()
-
-			break
+		# assigning to document
+		doc.db_set('ksa_einv_qr', _file.file_url)
+		doc.notify_update()
 
 
-def delete_qr_code_file(doc, method):
-	"""Delete QR Code on deleted sales invoice"""
-
+def delete_qr_code_file(doc, method=None):
 	region = get_region(doc.company)
 	if region not in ['Saudi Arabia']:
 		return
 
-	if hasattr(doc, 'qr_code'):
-		if doc.get('qr_code'):
+	if hasattr(doc, 'ksa_einv_qr'):
+		if doc.get('ksa_einv_qr'):
 			file_doc = frappe.get_list('File', {
-				'file_url': doc.get('qr_code')
+				'file_url': doc.get('ksa_einv_qr')
 			})
 			if len(file_doc):
 				frappe.delete_doc('File', file_doc[0].name)
 
-def delete_vat_settings_for_company(doc, method):
+def delete_vat_settings_for_company(doc, method=None):
 	if doc.country != 'Saudi Arabia':
 		return
 
-	settings_doc = frappe.get_doc('KSA VAT Setting', {'company': doc.name})
-	settings_doc.delete()
\ No newline at end of file
+	if frappe.db.exists('KSA VAT Setting', doc.name):
+		frappe.delete_doc('KSA VAT Setting', doc.name)
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 1c24825..cc95185 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -63,6 +63,8 @@
 		if not self.billing_status: self.billing_status = 'Not Billed'
 		if not self.delivery_status: self.delivery_status = 'Not Delivered'
 
+		self.reset_default_field_value("set_warehouse", "items", "warehouse")
+
 	def validate_po(self):
 		# validate p.o date v/s delivery date
 		if self.po_date and not self.skip_delivery_note:
@@ -978,6 +980,7 @@
 			description=i['description']
 		)).insert()
 		work_order.set_work_order_operations()
+		work_order.flags.ignore_mandatory = True
 		work_order.save()
 		out.append(work_order)
 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 5268460..70d48a4 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -138,6 +138,7 @@
 		self.update_current_stock()
 
 		if not self.installation_status: self.installation_status = 'Not Installed'
+		self.reset_default_field_value("set_warehouse", "items", "warehouse")
 
 	def validate_with_previous_doc(self):
 		super(DeliveryNote, self).validate_with_previous_doc({
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index d717c50..103e8d6 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -80,6 +80,9 @@
 		# NOTE: Since Item BOM and FG quantities are combined, using current data, it cannot be validated
 		# Though the creation of Material Request from a Production Plan can be rethought to fix this
 
+		self.reset_default_field_value("set_warehouse", "items", "warehouse")
+		self.reset_default_field_value("set_from_warehouse", "items", "from_warehouse")
+
 	def set_title(self):
 		'''Set title as comma separated list of items'''
 		if not self.title:
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 762f45f..c97b306 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -118,6 +118,10 @@
 		if getdate(self.posting_date) > getdate(nowdate()):
 			throw(_("Posting Date cannot be future date"))
 
+		self.reset_default_field_value("set_warehouse", "items", "warehouse")
+		self.reset_default_field_value("rejected_warehouse", "items", "rejected_warehouse")
+		self.reset_default_field_value("set_from_warehouse", "items", "from_warehouse")
+
 
 	def validate_cwip_accounts(self):
 		for item in self.get('items'):
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index 01cceb1..b2ad07f 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -168,8 +168,8 @@
 	for row in riv_entries:
 		doc = frappe.get_doc('Repost Item Valuation', row.name)
 		if doc.status in ('Queued', 'In Progress'):
-			doc.deduplicate_similar_repost()
 			repost(doc)
+			doc.deduplicate_similar_repost()
 
 	riv_entries = get_repost_item_valuation_entries()
 	if riv_entries:
diff --git a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py
index de79316..78b432d 100644
--- a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py
@@ -4,12 +4,14 @@
 import unittest
 
 import frappe
+from frappe.utils import nowdate
 
 from erpnext.controllers.stock_controller import create_item_wise_repost_entries
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
 from erpnext.stock.doctype.repost_item_valuation.repost_item_valuation import (
 	in_configured_timeslot,
 )
+from erpnext.stock.utils import PendingRepostingError
 
 
 class TestRepostItemValuation(unittest.TestCase):
@@ -138,3 +140,25 @@
 		# to avoid breaking other tests accidentaly
 		riv4.set_status("Skipped")
 		riv3.set_status("Skipped")
+
+	def test_stock_freeze_validation(self):
+
+		today = nowdate()
+
+		riv = frappe.get_doc(
+			doctype="Repost Item Valuation",
+			item_code="_Test Item",
+			warehouse="_Test Warehouse - _TC",
+			based_on="Item and Warehouse",
+			posting_date=today,
+			posting_time="00:01:00",
+		)
+		riv.flags.dont_run_in_test = True # keep it queued
+		riv.submit()
+
+		stock_settings = frappe.get_doc("Stock Settings")
+		stock_settings.stock_frozen_upto = today
+
+		self.assertRaises(PendingRepostingError, stock_settings.save)
+
+		riv.set_status("Skipped")
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index a38dfa5..a00d63e 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -103,6 +103,8 @@
 		self.set_actual_qty()
 		self.calculate_rate_and_amount()
 		self.validate_putaway_capacity()
+		self.reset_default_field_value("from_warehouse", "items", "s_warehouse")
+		self.reset_default_field_value("to_warehouse", "items", "t_warehouse")
 
 	def on_submit(self):
 		self.update_stock_ledger()
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 5ef0770..5a9e77e 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -24,7 +24,8 @@
 from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
 	create_stock_reconciliation,
 )
-from erpnext.stock.stock_ledger import get_previous_sle
+from erpnext.stock.stock_ledger import NegativeStockError, get_previous_sle
+from erpnext.tests.utils import ERPNextTestCase, change_settings
 
 
 def get_sle(**args):
@@ -38,7 +39,7 @@
 		order by timestamp(posting_date, posting_time) desc, creation desc limit 1"""% condition,
 		values, as_dict=1)
 
-class TestStockEntry(unittest.TestCase):
+class TestStockEntry(ERPNextTestCase):
 	def tearDown(self):
 		frappe.set_user("Administrator")
 		frappe.db.set_value("Manufacturing Settings", None, "material_consumption", "0")
@@ -928,6 +929,83 @@
 		distributed_costs = [d.additional_cost for d in se.items]
 		self.assertEqual([40.0, 60.0], distributed_costs)
 
+	@change_settings("Stock Settings", {"allow_negative_stock": 0})
+	def test_future_negative_sle(self):
+		# Initialize item, batch, warehouse, opening qty
+		item_code = '_Test Future Neg Item'
+		batch_no = '_Test Future Neg Batch'
+		warehouses = [
+			'_Test Future Neg Warehouse Source',
+			'_Test Future Neg Warehouse Destination'
+		]
+		warehouse_names = initialize_records_for_future_negative_sle_test(
+			item_code, batch_no, warehouses,
+			opening_qty=2, posting_date='2021-07-01'
+		)
+
+		# Executing an illegal sequence should raise an error
+		sequence_of_entries = [
+			dict(item_code=item_code,
+				qty=2,
+				from_warehouse=warehouse_names[0],
+				to_warehouse=warehouse_names[1],
+				batch_no=batch_no,
+				posting_date='2021-07-03',
+				purpose='Material Transfer'),
+			dict(item_code=item_code,
+				qty=2,
+				from_warehouse=warehouse_names[1],
+				to_warehouse=warehouse_names[0],
+				batch_no=batch_no,
+				posting_date='2021-07-04',
+				purpose='Material Transfer'),
+			dict(item_code=item_code,
+				qty=2,
+				from_warehouse=warehouse_names[0],
+				to_warehouse=warehouse_names[1],
+				batch_no=batch_no,
+				posting_date='2021-07-02',          # Illegal SE
+				purpose='Material Transfer')
+		]
+
+		self.assertRaises(NegativeStockError, create_stock_entries, sequence_of_entries)
+
+	@change_settings("Stock Settings", {"allow_negative_stock": 0})
+	def test_future_negative_sle_batch(self):
+		from erpnext.stock.doctype.batch.test_batch import TestBatch
+
+		# Initialize item, batch, warehouse, opening qty
+		item_code = '_Test MultiBatch Item'
+		TestBatch.make_batch_item(item_code)
+
+		batch_nos = [] # store generate batches
+		warehouse = '_Test Warehouse - _TC'
+
+		se1 = make_stock_entry(
+				item_code=item_code,
+				qty=2,
+				to_warehouse=warehouse,
+				posting_date='2021-09-01',
+				purpose='Material Receipt'
+			)
+		batch_nos.append(se1.items[0].batch_no)
+		se2 = make_stock_entry(
+				item_code=item_code,
+				qty=2,
+				to_warehouse=warehouse,
+				posting_date='2021-09-03',
+				purpose='Material Receipt'
+			)
+		batch_nos.append(se2.items[0].batch_no)
+
+		with self.assertRaises(NegativeStockError) as nse:
+			make_stock_entry(item_code=item_code,
+				qty=1,
+				from_warehouse=warehouse,
+				batch_no=batch_nos[1],
+				posting_date='2021-09-02', # backdated consumption of 2nd batch
+				purpose='Material Issue')
+
 def make_serialized_item(**args):
 	args = frappe._dict(args)
 	se = frappe.copy_doc(test_records[0])
@@ -998,3 +1076,31 @@
 		]
 
 test_records = frappe.get_test_records('Stock Entry')
+
+def initialize_records_for_future_negative_sle_test(
+		item_code, batch_no, warehouses, opening_qty, posting_date):
+	from erpnext.stock.doctype.batch.test_batch import TestBatch, make_new_batch
+	from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
+		create_stock_reconciliation,
+	)
+	from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
+
+	TestBatch.make_batch_item(item_code)
+	make_new_batch(item_code=item_code, batch_id=batch_no)
+	warehouse_names = [create_warehouse(w) for w in warehouses]
+	create_stock_reconciliation(
+		purpose='Opening Stock',
+		posting_date=posting_date,
+		posting_time='20:00:20',
+		item_code=item_code,
+		warehouse=warehouse_names[0],
+		valuation_rate=100,
+		qty=opening_qty,
+		batch_no=batch_no,
+	)
+	return warehouse_names
+
+
+def create_stock_entries(sequence_of_entries):
+	for entry_detail in sequence_of_entries:
+		make_stock_entry(**entry_detail)
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index 93bca7a..c538307 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -8,7 +8,7 @@
 from frappe import _
 from frappe.core.doctype.role.role import get_users
 from frappe.model.document import Document
-from frappe.utils import add_days, cint, flt, formatdate, get_datetime, getdate
+from frappe.utils import add_days, cint, formatdate, get_datetime, getdate
 
 from erpnext.accounts.utils import get_fiscal_year
 from erpnext.controllers.item_variant import ItemTemplateCannotHaveStock
@@ -43,7 +43,6 @@
 
 	def on_submit(self):
 		self.check_stock_frozen_date()
-		self.actual_amt_check()
 		self.calculate_batch_qty()
 
 		if not self.get("via_landed_cost_voucher"):
@@ -57,18 +56,6 @@
 				"sum(actual_qty)") or 0
 			frappe.db.set_value("Batch", self.batch_no, "batch_qty", batch_qty)
 
-	def actual_amt_check(self):
-		"""Validate that qty at warehouse for selected batch is >=0"""
-		if self.batch_no and not self.get("allow_negative_stock"):
-			batch_bal_after_transaction = flt(frappe.db.sql("""select sum(actual_qty)
-				from `tabStock Ledger Entry`
-				where is_cancelled =0 and warehouse=%s and item_code=%s and batch_no=%s""",
-				(self.warehouse, self.item_code, self.batch_no))[0][0])
-
-			if batch_bal_after_transaction < 0:
-				frappe.throw(_("Stock balance in Batch {0} will become negative {1} for Item {2} at Warehouse {3}")
-					.format(self.batch_no, batch_bal_after_transaction, self.item_code, self.warehouse))
-
 	def validate_mandatory(self):
 		mandatory = ['warehouse','posting_date','voucher_type','voucher_no','company']
 		for k in mandatory:
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py
index 1de48b6..c1293cb 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.py
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.py
@@ -11,6 +11,8 @@
 from frappe.utils import cint
 from frappe.utils.html_utils import clean_html
 
+from erpnext.stock.utils import check_pending_reposting
+
 
 class StockSettings(Document):
 	def validate(self):
@@ -36,6 +38,7 @@
 		self.validate_warehouses()
 		self.cant_change_valuation_method()
 		self.validate_clean_description_html()
+		self.validate_pending_reposts()
 
 	def validate_warehouses(self):
 		warehouse_fields = ["default_warehouse", "sample_retention_warehouse"]
@@ -64,6 +67,11 @@
 			# changed to text
 			frappe.enqueue('erpnext.stock.doctype.stock_settings.stock_settings.clean_all_descriptions', now=frappe.flags.in_test)
 
+	def validate_pending_reposts(self):
+		if self.stock_frozen_upto:
+			check_pending_reposting(self.stock_frozen_upto)
+
+
 	def on_update(self):
 		self.toggle_warehouse_field_for_inter_warehouse_transfer()
 
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index d78632a..e95c0fc 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -1089,17 +1089,36 @@
 	allow_negative_stock = cint(allow_negative_stock) \
 		or cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock"))
 
-	if (args.actual_qty < 0 or args.voucher_type == "Stock Reconciliation") and not allow_negative_stock:
-		sle = get_future_sle_with_negative_qty(args)
-		if sle:
-			message = _("{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction.").format(
-				abs(sle[0]["qty_after_transaction"]),
-				frappe.get_desk_link('Item', args.item_code),
-				frappe.get_desk_link('Warehouse', args.warehouse),
-				sle[0]["posting_date"], sle[0]["posting_time"],
-				frappe.get_desk_link(sle[0]["voucher_type"], sle[0]["voucher_no"]))
+	if allow_negative_stock:
+		return
+	if not (args.actual_qty < 0 or args.voucher_type == "Stock Reconciliation"):
+		return
 
-			frappe.throw(message, NegativeStockError, title='Insufficient Stock')
+	neg_sle = get_future_sle_with_negative_qty(args)
+	if neg_sle:
+		message = _("{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction.").format(
+			abs(neg_sle[0]["qty_after_transaction"]),
+			frappe.get_desk_link('Item', args.item_code),
+			frappe.get_desk_link('Warehouse', args.warehouse),
+			neg_sle[0]["posting_date"], neg_sle[0]["posting_time"],
+			frappe.get_desk_link(neg_sle[0]["voucher_type"], neg_sle[0]["voucher_no"]))
+
+		frappe.throw(message, NegativeStockError, title='Insufficient Stock')
+
+
+	if not args.batch_no:
+		return
+
+	neg_batch_sle = get_future_sle_with_negative_batch_qty(args)
+	if neg_batch_sle:
+		message = _("{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction.").format(
+			abs(neg_batch_sle[0]["cumulative_total"]),
+			frappe.get_desk_link('Batch', args.batch_no),
+			frappe.get_desk_link('Warehouse', args.warehouse),
+			neg_batch_sle[0]["posting_date"], neg_batch_sle[0]["posting_time"],
+			frappe.get_desk_link(neg_batch_sle[0]["voucher_type"], neg_batch_sle[0]["voucher_no"]))
+		frappe.throw(message, NegativeStockError, title="Insufficient Stock for Batch")
+
 
 def get_future_sle_with_negative_qty(args):
 	return frappe.db.sql("""
@@ -1118,6 +1137,29 @@
 		limit 1
 	""", args, as_dict=1)
 
+
+def get_future_sle_with_negative_batch_qty(args):
+	return frappe.db.sql("""
+		with batch_ledger as (
+			select
+				posting_date, posting_time, voucher_type, voucher_no,
+				sum(actual_qty) over (order by posting_date, posting_time, creation) as cumulative_total
+			from `tabStock Ledger Entry`
+			where
+				item_code = %(item_code)s
+				and warehouse = %(warehouse)s
+				and batch_no=%(batch_no)s
+				and is_cancelled = 0
+			order by posting_date, posting_time, creation
+		)
+		select * from batch_ledger
+		where
+			cumulative_total < 0.0
+			and timestamp(posting_date, posting_time) >= timestamp(%(posting_date)s, %(posting_time)s)
+		limit 1
+	""", args, as_dict=1)
+
+
 def _round_off_if_near_zero(number: float, precision: int = 6) -> float:
 	""" Rounds off the number to zero only if number is close to zero for decimal
 		specified in precision. Precision defaults to 6.
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 72d8098..3b1ae3b 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -12,6 +12,7 @@
 
 
 class InvalidWarehouseCompany(frappe.ValidationError): pass
+class PendingRepostingError(frappe.ValidationError): pass
 
 def get_stock_value_from_bin(warehouse=None, item_code=None):
 	values = {}
@@ -417,3 +418,28 @@
 		{'docstatus': 1, 'status': ['in', ['Queued','In Progress']]})
 	if reposting_in_progress:
 		frappe.msgprint(_("Item valuation reposting in progress. Report might show incorrect item valuation."), alert=1)
+
+def check_pending_reposting(posting_date: str, throw_error: bool = True) -> bool:
+	"""Check if there are pending reposting job till the specified posting date."""
+
+	filters = {
+		"docstatus": 1,
+		"status": ["in", ["Queued","In Progress", "Failed"]],
+		"posting_date": ["<=", posting_date],
+	}
+
+	reposting_pending =  frappe.db.exists("Repost Item Valuation", filters)
+	if reposting_pending and throw_error:
+		msg = _("Stock/Accounts can not be frozen as processing of backdated entries is going on. Please try again later.")
+		frappe.msgprint(msg,
+				raise_exception=PendingRepostingError,
+				title="Stock Reposting Ongoing",
+				indicator="red",
+				primary_action={
+					"label": _("Show pending entries"),
+					"client_action": "erpnext.route_to_pending_reposts",
+					"args": filters,
+				}
+			)
+
+	return bool(reposting_pending)
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index ca03a78..d46ffb5 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -1847,7 +1847,7 @@
 Overlap in scoring between {0} and {1},Überlappung beim Scoring zwischen {0} und {1},
 Overlapping conditions found between:,Überlagernde Bedingungen gefunden zwischen:,
 Owner,Besitzer,
-PAN,PFANNE,
+PAN,PAN,
 POS,Verkaufsstelle,
 POS Profile,Verkaufsstellen-Profil,
 POS Profile is required to use Point-of-Sale,"POS-Profil ist erforderlich, um Point-of-Sale zu verwenden",
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index 14b3afa..1d8b3a8 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -162,6 +162,28 @@
 
 		return ret
 
+	def reset_default_field_value(self, default_field: str, child_table: str, child_table_field: str):
+		""" Reset "Set default X" fields on forms to avoid confusion.
+
+			example:
+				doc = {
+					"set_from_warehouse": "Warehouse A",
+					"items": [{"from_warehouse": "warehouse B"}, {"from_warehouse": "warehouse A"}],
+				}
+				Since this has dissimilar values in child table, the default field will be erased.
+
+				doc.reset_default_field_value("set_from_warehouse", "items", "from_warehouse")
+			"""
+		child_table_values = set()
+
+		for row in self.get(child_table):
+			child_table_values.add(row.get(child_table_field))
+
+		if len(child_table_values) > 1:
+			self.set(default_field, None)
+		else:
+			self.set(default_field, list(child_table_values)[0])
+
 def delete_events(ref_type, ref_name):
 	events = frappe.db.sql_list(""" SELECT
 			distinct `tabEvent`.name