Merge branch 'develop' into crm-carry-forward-communication-comments
diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
index 5cbf00b..e7371fb 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
+++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
@@ -434,7 +434,7 @@
 
 def get_ec_matching_query(bank_account, company, amount_condition):
 	# get matching Expense Claim query
-	mode_of_payments = [x["parent"] for x in frappe.db.get_list("Mode of Payment Account",
+	mode_of_payments = [x["parent"] for x in frappe.db.get_all("Mode of Payment Account",
 			filters={"default_account": bank_account}, fields=["parent"])]
 	mode_of_payments = '(\'' + '\', \''.join(mode_of_payments) + '\' )'
 	company_currency = get_company_currency(company)
diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.js b/erpnext/assets/doctype/asset_repair/asset_repair.js
index 18a56d3..d554d52 100644
--- a/erpnext/assets/doctype/asset_repair/asset_repair.js
+++ b/erpnext/assets/doctype/asset_repair/asset_repair.js
@@ -60,6 +60,10 @@
 		if (frm.doc.repair_status == "Completed") {
 			frm.set_value('completion_date', frappe.datetime.now_datetime());
 		}
+	},
+
+	stock_items_on_form_rendered() {
+		erpnext.setup_serial_or_batch_no();
 	}
 });
 
diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py
index d780c18..36848e9 100644
--- a/erpnext/assets/doctype/asset_repair/asset_repair.py
+++ b/erpnext/assets/doctype/asset_repair/asset_repair.py
@@ -118,9 +118,10 @@
 		for stock_item in self.get('stock_items'):
 			stock_entry.append('items', {
 				"s_warehouse": self.warehouse,
-				"item_code": stock_item.item,
+				"item_code": stock_item.item_code,
 				"qty": stock_item.consumed_quantity,
-				"basic_rate": stock_item.valuation_rate
+				"basic_rate": stock_item.valuation_rate,
+				"serial_no": stock_item.serial_no
 			})
 
 		stock_entry.insert()
diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py
index 81b4f6c..7c0d057 100644
--- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py
+++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py
@@ -11,12 +11,15 @@
 	create_asset_data,
 	set_depreciation_settings_in_company,
 )
+from erpnext.stock.doctype.item.test_item import create_item
 
 
 class TestAssetRepair(unittest.TestCase):
-	def setUp(self):
+	@classmethod
+	def setUpClass(cls):
 		set_depreciation_settings_in_company()
 		create_asset_data()
+		create_item("_Test Stock Item")
 		frappe.db.sql("delete from `tabTax Rule`")
 
 	def test_update_status(self):
@@ -70,9 +73,28 @@
 
 		self.assertEqual(stock_entry.stock_entry_type, "Material Issue")
 		self.assertEqual(stock_entry.items[0].s_warehouse, asset_repair.warehouse)
-		self.assertEqual(stock_entry.items[0].item_code, asset_repair.stock_items[0].item)
+		self.assertEqual(stock_entry.items[0].item_code, asset_repair.stock_items[0].item_code)
 		self.assertEqual(stock_entry.items[0].qty, asset_repair.stock_items[0].consumed_quantity)
 
+	def test_serialized_item_consumption(self):
+		from erpnext.stock.doctype.serial_no.serial_no import SerialNoRequiredError
+		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
+
+		stock_entry = make_serialized_item()
+		serial_nos = stock_entry.get("items")[0].serial_no
+		serial_no = serial_nos.split("\n")[0]
+
+		# should not raise any error
+		create_asset_repair(stock_consumption = 1, item_code = stock_entry.get("items")[0].item_code,
+			warehouse = "_Test Warehouse - _TC", serial_no = serial_no, submit = 1)
+
+		# should raise error
+		asset_repair = create_asset_repair(stock_consumption = 1, warehouse = "_Test Warehouse - _TC",
+			item_code = stock_entry.get("items")[0].item_code)
+
+		asset_repair.repair_status = "Completed"
+		self.assertRaises(SerialNoRequiredError, asset_repair.submit)
+
 	def test_increase_in_asset_value_due_to_stock_consumption(self):
 		asset = create_asset(calculate_depreciation = 1, submit=1)
 		initial_asset_value = get_asset_value(asset)
@@ -137,11 +159,12 @@
 
 	if args.stock_consumption:
 		asset_repair.stock_consumption = 1
-		asset_repair.warehouse = create_warehouse("Test Warehouse", company = asset.company)
+		asset_repair.warehouse = args.warehouse or create_warehouse("Test Warehouse", company = asset.company)
 		asset_repair.append("stock_items", {
-			"item": args.item or args.item_code or "_Test Item",
+			"item_code": args.item_code or "_Test Stock Item",
 			"valuation_rate": args.rate if args.get("rate") is not None else 100,
-			"consumed_quantity": args.qty or 1
+			"consumed_quantity": args.qty or 1,
+			"serial_no": args.serial_no
 		})
 
 	asset_repair.insert(ignore_if_duplicate=True)
@@ -158,7 +181,7 @@
 			})
 			stock_entry.append('items', {
 				"t_warehouse": asset_repair.warehouse,
-				"item_code": asset_repair.stock_items[0].item,
+				"item_code": asset_repair.stock_items[0].item_code,
 				"qty": asset_repair.stock_items[0].consumed_quantity
 			})
 			stock_entry.submit()
diff --git a/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json b/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json
index 528f0ec..f63add1 100644
--- a/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json
+++ b/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json
@@ -5,20 +5,14 @@
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
-  "item",
+  "item_code",
   "valuation_rate",
   "consumed_quantity",
-  "total_value"
+  "total_value",
+  "serial_no"
  ],
  "fields": [
   {
-   "fieldname": "item",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Item",
-   "options": "Item"
-  },
-  {
    "fetch_from": "item.valuation_rate",
    "fieldname": "valuation_rate",
    "fieldtype": "Currency",
@@ -38,12 +32,24 @@
    "in_list_view": 1,
    "label": "Total Value",
    "read_only": 1
+  },
+  {
+   "fieldname": "serial_no",
+   "fieldtype": "Small Text",
+   "label": "Serial No"
+  },
+  {
+   "fieldname": "item_code",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Item",
+   "options": "Item"
   }
  ],
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-05-12 03:19:55.006300",
+ "modified": "2021-11-11 18:23:00.492483",
  "modified_by": "Administrator",
  "module": "Assets",
  "name": "Asset Repair Consumed Item",
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index e8aac1d..05c46c5 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -248,20 +248,18 @@
 		"validate": "erpnext.regional.india.utils.validate_tax_category"
 	},
 	"Sales Invoice": {
-		"after_insert": "erpnext.regional.saudi_arabia.utils.create_qr_code",
 		"on_submit": [
 			"erpnext.regional.create_transaction_log",
 			"erpnext.regional.italy.utils.sales_invoice_on_submit",
+			"erpnext.regional.saudi_arabia.utils.create_qr_code",
 			"erpnext.erpnext_integrations.taxjar_integration.create_transaction"
 		],
 		"on_cancel": [
 			"erpnext.regional.italy.utils.sales_invoice_on_cancel",
-			"erpnext.erpnext_integrations.taxjar_integration.delete_transaction"
-		],
-		"on_trash": [
-			"erpnext.regional.check_deletion_permission",
+			"erpnext.erpnext_integrations.taxjar_integration.delete_transaction",
 			"erpnext.regional.saudi_arabia.utils.delete_qr_code_file"
 		],
+		"on_trash": "erpnext.regional.check_deletion_permission",
 		"validate": [
 			"erpnext.regional.india.utils.validate_document_name",
 			"erpnext.regional.india.utils.update_taxable_values"
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index 8a8e8db..7aac2b6 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -5,6 +5,7 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
+from frappe.query_builder.functions import Sum
 from frappe.utils import flt, nowdate
 
 import erpnext
@@ -41,24 +42,34 @@
 			self.status = "Cancelled"
 
 	def set_total_advance_paid(self):
-		paid_amount = frappe.db.sql("""
-			select ifnull(sum(debit), 0) as paid_amount
-			from `tabGL Entry`
-			where against_voucher_type = 'Employee Advance'
-				and against_voucher = %s
-				and party_type = 'Employee'
-				and party = %s
-		""", (self.name, self.employee), as_dict=1)[0].paid_amount
+		gle = frappe.qb.DocType("GL Entry")
 
-		return_amount = frappe.db.sql("""
-			select ifnull(sum(credit), 0) as return_amount
-			from `tabGL Entry`
-			where against_voucher_type = 'Employee Advance'
-				and voucher_type != 'Expense Claim'
-				and against_voucher = %s
-				and party_type = 'Employee'
-				and party = %s
-		""", (self.name, self.employee), as_dict=1)[0].return_amount
+		paid_amount = (
+			frappe.qb.from_(gle)
+				.select(Sum(gle.debit).as_("paid_amount"))
+				.where(
+					(gle.against_voucher_type == 'Employee Advance')
+					& (gle.against_voucher == self.name)
+					& (gle.party_type == 'Employee')
+					& (gle.party == self.employee)
+					& (gle.docstatus == 1)
+					& (gle.is_cancelled == 0)
+				)
+			).run(as_dict=True)[0].paid_amount or 0
+
+		return_amount = (
+			frappe.qb.from_(gle)
+				.select(Sum(gle.credit).as_("return_amount"))
+				.where(
+					(gle.against_voucher_type == 'Employee Advance')
+					& (gle.voucher_type != 'Expense Claim')
+					& (gle.against_voucher == self.name)
+					& (gle.party_type == 'Employee')
+					& (gle.party == self.employee)
+					& (gle.docstatus == 1)
+					& (gle.is_cancelled == 0)
+				)
+			).run(as_dict=True)[0].return_amount or 0
 
 		if paid_amount != 0:
 			paid_amount = flt(paid_amount) / flt(self.exchange_rate)
diff --git a/erpnext/hr/doctype/employee_advance/test_employee_advance.py b/erpnext/hr/doctype/employee_advance/test_employee_advance.py
index 4ecfa60..5f2e720 100644
--- a/erpnext/hr/doctype/employee_advance/test_employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/test_employee_advance.py
@@ -34,6 +34,24 @@
 		journal_entry1 = make_payment_entry(advance)
 		self.assertRaises(EmployeeAdvanceOverPayment, journal_entry1.submit)
 
+	def test_paid_amount_on_pe_cancellation(self):
+		employee_name = make_employee("_T@employe.advance")
+		advance = make_employee_advance(employee_name)
+
+		pe = make_payment_entry(advance)
+		pe.submit()
+
+		advance.reload()
+
+		self.assertEqual(advance.paid_amount, 1000)
+		self.assertEqual(advance.status, "Paid")
+
+		pe.cancel()
+		advance.reload()
+
+		self.assertEqual(advance.paid_amount, 0)
+		self.assertEqual(advance.status, "Unpaid")
+
 	def test_repay_unclaimed_amount_from_salary(self):
 		employee_name = make_employee("_T@employe.advance")
 		advance = make_employee_advance(employee_name, {"repay_unclaimed_amount_from_salary": 1})
diff --git a/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json b/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json
index 70a48f9..6edbcb5c 100644
--- a/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json
+++ b/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json
@@ -94,7 +94,6 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Sanctioned Amount",
-   "no_copy": 1,
    "oldfieldname": "sanctioned_amount",
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
@@ -120,7 +119,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-09-18 17:26:09.703215",
+ "modified": "2021-11-26 14:23:45.539922",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Expense Claim Detail",
diff --git a/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json b/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json
index 647c14b..4e1a464 100644
--- a/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json
+++ b/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json
@@ -178,8 +178,9 @@
   },
   {
    "fieldname": "batch_size",
-   "fieldtype": "Int",
-   "label": "Batch Size"
+   "fieldtype": "Float",
+   "label": "Batch Size",
+   "read_only": 1
   },
   {
    "fieldname": "sequence_id",
@@ -200,7 +201,7 @@
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-11-24 04:52:54.295168",
+ "modified": "2021-11-29 16:37:18.824489",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Work Order Operation",
diff --git a/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py b/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py
index cf19cbf..090a3e7 100644
--- a/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py
+++ b/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py
@@ -89,7 +89,7 @@
 			GROUP BY bom_item.item_code""".format(qty_field=qty_field, table=table, conditions=conditions, bom=bom), as_dict=1)
 
 def get_manufacturer_records():
-	details = frappe.get_list('Item Manufacturer', fields = ["manufacturer", "manufacturer_part_no", "parent"])
+	details = frappe.get_all('Item Manufacturer', fields = ["manufacturer", "manufacturer_part_no", "parent"])
 	manufacture_details = frappe._dict()
 	for detail in details:
 		dic = manufacture_details.setdefault(detail.get('parent'), {})
diff --git a/erpnext/manufacturing/report/work_order_consumed_materials/__init__.py b/erpnext/manufacturing/report/work_order_consumed_materials/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/manufacturing/report/work_order_consumed_materials/__init__.py
diff --git a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js
new file mode 100644
index 0000000..b2428e8
--- /dev/null
+++ b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js
@@ -0,0 +1,70 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Work Order Consumed Materials"] = {
+	"filters": [
+		{
+			label: __("Company"),
+			fieldname: "company",
+			fieldtype: "Link",
+			options: "Company",
+			default: frappe.defaults.get_user_default("Company"),
+			reqd: 1
+		},
+		{
+			label: __("From Date"),
+			fieldname:"from_date",
+			fieldtype: "Date",
+			default: frappe.datetime.add_months(frappe.datetime.get_today(), -1),
+			reqd: 1
+		},
+		{
+			fieldname:"to_date",
+			label: __("To Date"),
+			fieldtype: "Date",
+			default: frappe.datetime.get_today(),
+			reqd: 1
+		},
+		{
+			label: __("Work Order"),
+			fieldname: "name",
+			fieldtype: "Link",
+			options: "Work Order",
+			get_query: function() {
+				return {
+					filters: {
+						status: ["in", ["In Process", "Completed", "Stopped"]]
+					}
+				}
+			}
+		},
+		{
+			label: __("Production Item"),
+			fieldname: "production_item",
+			fieldtype: "Link",
+			depends_on: "eval: !doc.name",
+			options: "Item"
+		},
+		{
+			label: __("Status"),
+			fieldname: "status",
+			fieldtype: "Select",
+			options: ["In Process", "Completed", "Stopped"]
+		},
+		{
+			label: __("Excess Materials Consumed"),
+			fieldname: "show_extra_consumed_materials",
+			fieldtype: "Check"
+		}
+	],
+	"formatter": function(value, row, column, data, default_formatter) {
+		value = default_formatter(value, row, column, data);
+
+		if (column.fieldname == "raw_material_name" && data && data.extra_consumed_qty > 0 ) {
+			value = `<div style="color:red">${value}</div>`;
+		}
+
+		return value;
+	},
+};
diff --git a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.json b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.json
new file mode 100644
index 0000000..2fc986a
--- /dev/null
+++ b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2021-11-22 17:36:11.886939",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "letter_head": "Gadgets International",
+ "modified": "2021-11-22 17:36:14.999091",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Work Order Consumed Materials",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Work Order",
+ "report_name": "Work Order Consumed Materials",
+ "report_type": "Script Report",
+ "roles": [
+  {
+   "role": "Manufacturing User"
+  },
+  {
+   "role": "Stock User"
+  }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py
new file mode 100644
index 0000000..0528348
--- /dev/null
+++ b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py
@@ -0,0 +1,131 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+	columns, data = [], []
+	columns = get_columns()
+	data = get_data(filters)
+
+	return columns, data
+
+def get_data(report_filters):
+	fields = get_fields()
+	filters = get_filter_condition(report_filters)
+
+	wo_items = {}
+	for d in frappe.get_all("Work Order", filters = filters, fields=fields):
+		d.extra_consumed_qty = 0.0
+		if d.consumed_qty and d.consumed_qty > d.required_qty:
+			d.extra_consumed_qty = d.consumed_qty - d.required_qty
+
+		if d.extra_consumed_qty or not report_filters.show_extra_consumed_materials:
+			wo_items.setdefault((d.name, d.production_item), []).append(d)
+
+	data = []
+	for key, wo_data in wo_items.items():
+		for index, row in enumerate(wo_data):
+			if index != 0:
+				#If one work order has multiple raw materials then show parent data in the first row only
+				for field in ["name", "status", "production_item", "qty", "produced_qty"]:
+					row[field] = ""
+
+			data.append(row)
+
+	return data
+
+def get_fields():
+	return ["`tabWork Order Item`.`parent`", "`tabWork Order Item`.`item_code` as raw_material_item_code",
+		"`tabWork Order Item`.`item_name` as raw_material_name", "`tabWork Order Item`.`required_qty`",
+		"`tabWork Order Item`.`transferred_qty`", "`tabWork Order Item`.`consumed_qty`", "`tabWork Order`.`status`",
+		"`tabWork Order`.`name`", "`tabWork Order`.`production_item`", "`tabWork Order`.`qty`",
+		"`tabWork Order`.`produced_qty`"]
+
+def get_filter_condition(report_filters):
+	filters = {
+		"docstatus": 1, "status": ("in", ["In Process", "Completed", "Stopped"]),
+		"creation": ("between", [report_filters.from_date, report_filters.to_date])
+	}
+
+	for field in ["name", "production_item", "company", "status"]:
+		value = report_filters.get(field)
+		if value:
+			key = f"`{field}`"
+			filters.update({key: value})
+
+	return filters
+
+def get_columns():
+	return [
+		{
+			"label": _("Id"),
+			"fieldname": "name",
+			"fieldtype": "Link",
+			"options": "Work Order",
+			"width": 80
+		},
+		{
+			"label": _("Status"),
+			"fieldname": "status",
+			"fieldtype": "Data",
+			"width": 80
+		},
+		{
+			"label": _("Production Item"),
+			"fieldname": "production_item",
+			"fieldtype": "Link",
+			"options": "Item",
+			"width": 130
+		},
+		{
+			"label": _("Qty to Produce"),
+			"fieldname": "qty",
+			"fieldtype": "Float",
+			"width": 120
+		},
+		{
+			"label": _("Produced Qty"),
+			"fieldname": "produced_qty",
+			"fieldtype": "Float",
+			"width": 110
+		},
+		{
+			"label": _("Raw Material Item"),
+			"fieldname": "raw_material_item_code",
+			"fieldtype": "Link",
+			"options": "Item",
+			"width": 150
+		},
+		{
+			"label": _("Item Name"),
+			"fieldname": "raw_material_name",
+			"width": 130
+		},
+		{
+			"label": _("Required Qty"),
+			"fieldname": "required_qty",
+			"fieldtype": "Float",
+			"width": 100
+		},
+		{
+			"label": _("Transferred Qty"),
+			"fieldname": "transferred_qty",
+			"fieldtype": "Float",
+			"width": 100
+		},
+		{
+			"label": _("Consumed Qty"),
+			"fieldname": "consumed_qty",
+			"fieldtype": "Float",
+			"width": 100
+		},
+		{
+			"label": _("Extra Consumed Qty"),
+			"fieldname": "extra_consumed_qty",
+			"fieldtype": "Float",
+			"width": 100
+		}
+	]
diff --git a/erpnext/manufacturing/workspace/manufacturing/manufacturing.json b/erpnext/manufacturing/workspace/manufacturing/manufacturing.json
index cfa80f8..65b4d02 100644
--- a/erpnext/manufacturing/workspace/manufacturing/manufacturing.json
+++ b/erpnext/manufacturing/workspace/manufacturing/manufacturing.json
@@ -1,10 +1,6 @@
 {
- "charts": [
-  {
-   "chart_name": "Produced Quantity"
-  }
- ],
- "content": "[{\"type\": \"onboarding\", \"data\": {\"onboarding_name\":\"Manufacturing\", \"col\": 12}}, {\"type\": \"chart\", \"data\": {\"chart_name\": null, \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Item\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"BOM\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Work Order\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Production Plan\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Forecasting\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Work Order Summary\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"BOM Stock Report\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Production Planning Report\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Production\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Bill of Materials\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Tools\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings\", \"col\": 4}}]",
+ "charts": [],
+ "content": "[{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Plan\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Forecasting\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order Summary\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM Stock Report\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Planning Report\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports &amp; Masters\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Production\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Bill of Materials\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
  "creation": "2020-03-02 17:11:37.032604",
  "docstatus": 0,
  "doctype": "Workspace",
@@ -141,14 +137,6 @@
    "type": "Link"
   },
   {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Reports",
-   "link_count": 0,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
    "dependencies": "Work Order",
    "hidden": 0,
    "is_query_report": 1,
@@ -295,9 +283,126 @@
    "link_type": "DocType",
    "onboard": 0,
    "type": "Link"
+  },
+  {
+   "hidden": 0,
+   "is_query_report": 0,
+   "label": "Reports",
+   "link_count": 10,
+   "onboard": 0,
+   "type": "Card Break"
+  },
+  {
+   "dependencies": "Work Order",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Production Planning Report",
+   "link_count": 0,
+   "link_to": "Production Planning Report",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "dependencies": "Work Order",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Work Order Summary",
+   "link_count": 0,
+   "link_to": "Work Order Summary",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "dependencies": "Quality Inspection",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Quality Inspection Summary",
+   "link_count": 0,
+   "link_to": "Quality Inspection Summary",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "dependencies": "Downtime Entry",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Downtime Analysis",
+   "link_count": 0,
+   "link_to": "Downtime Analysis",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "dependencies": "Job Card",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Job Card Summary",
+   "link_count": 0,
+   "link_to": "Job Card Summary",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "dependencies": "BOM",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "BOM Search",
+   "link_count": 0,
+   "link_to": "BOM Search",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "dependencies": "BOM",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "BOM Stock Report",
+   "link_count": 0,
+   "link_to": "BOM Stock Report",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "dependencies": "Work Order",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Production Analytics",
+   "link_count": 0,
+   "link_to": "Production Analytics",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "dependencies": "BOM",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "BOM Operations Time",
+   "link_count": 0,
+   "link_to": "BOM Operations Time",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "hidden": 0,
+   "is_query_report": 0,
+   "label": "Work Order Consumed Materials",
+   "link_count": 0,
+   "link_to": "Work Order Consumed Materials",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
   }
  ],
- "modified": "2021-08-05 12:16:00.825742",
+ "modified": "2021-11-22 17:55:03.524496",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Manufacturing",
diff --git a/erpnext/public/scss/point-of-sale.scss b/erpnext/public/scss/point-of-sale.scss
index 1677e9b..7a3854c 100644
--- a/erpnext/public/scss/point-of-sale.scss
+++ b/erpnext/public/scss/point-of-sale.scss
@@ -495,6 +495,11 @@
 						font-size: var(--text-md);
 					}
 
+					> .item-qty-total-container {
+						@extend .net-total-container;
+						padding: 5px 0px 0px 0px;
+					}
+
 					> .taxes-container {
 						display: none;
 						flex-direction: column;
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 4bd9195..9746fde 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -569,17 +569,17 @@
 	}
 	item_data_attrs = ['sgstRate', 'cgstRate', 'igstRate', 'cessRate', 'cessNonAdvol']
 	hsn_wise_charges, hsn_taxable_amount = get_itemised_tax_breakup_data(doc, account_wise=True, hsn_wise=hsn_wise)
-	for hsn_code, taxable_amount in hsn_taxable_amount.items():
+	for item_or_hsn, taxable_amount in hsn_taxable_amount.items():
 		item_data = frappe._dict()
-		if not hsn_code:
+		if not item_or_hsn:
 			frappe.throw(_('GST HSN Code does not exist for one or more items'))
-		item_data.hsnCode = int(hsn_code)
+		item_data.hsnCode = int(item_or_hsn) if hsn_wise else item_or_hsn
 		item_data.taxableAmount = taxable_amount
 		item_data.qtyUnit = ""
 		for attr in item_data_attrs:
 			item_data[attr] = 0
 
-		for account, tax_detail in hsn_wise_charges.get(hsn_code, {}).items():
+		for account, tax_detail in hsn_wise_charges.get(item_or_hsn, {}).items():
 			account_type = gst_accounts.get(account, '')
 			for tax_acc, attrs in tax_map.items():
 				if account_type == tax_acc:
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 681f72f..8e9a728 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
@@ -10,14 +10,14 @@
  "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 }}</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 tax_amount = frappe.utils.flt(data_object[item.item_code][1]/doc.conversion_rate, row.precision('tax_amount')) %}\n                <td>\n                   <div class=\"qr-flex\">\n                    {%- if(data_object[item.item_code][0])-%}\n                    <span>{{ frappe.format(data_object[item.item_code][0], {'fieldtype': 'Percent'}) }}</span>\n                    {%- endif -%}\n                    <span>\n                    {%- if(data_object[item.item_code][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.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",
  "idx": 0,
  "line_breaks": 0,
  "margin_bottom": 15.0,
  "margin_left": 15.0,
  "margin_right": 15.0,
  "margin_top": 15.0,
- "modified": "2021-11-22 10:40:24.716932",
+ "modified": "2021-11-29 13:47:37.870818",
  "modified_by": "Administrator",
  "module": "Regional",
  "name": "KSA VAT Invoice",
diff --git a/erpnext/regional/report/eway_bill/eway_bill.py b/erpnext/regional/report/eway_bill/eway_bill.py
index 91a4767..f3fe5e8 100644
--- a/erpnext/regional/report/eway_bill/eway_bill.py
+++ b/erpnext/regional/report/eway_bill/eway_bill.py
@@ -106,14 +106,14 @@
 		row.update({'ship_to_state': row.to_state})
 
 def set_taxes(row, filters):
-	taxes = frappe.get_list("Sales Taxes and Charges",
+	taxes = frappe.get_all("Sales Taxes and Charges",
 				filters={
 					'parent': row.dn_id
 				},
 				fields=('item_wise_tax_detail', 'account_head'))
 
 	account_list = ["cgst_account", "sgst_account", "igst_account", "cess_account"]
-	taxes_list = frappe.get_list("GST Account",
+	taxes_list = frappe.get_all("GST Account",
 		filters={
 			"parent": "GST Settings",
 			"company": filters.company
diff --git a/erpnext/regional/report/vat_audit_report/vat_audit_report.py b/erpnext/regional/report/vat_audit_report/vat_audit_report.py
index 5a281a4..17e5064 100644
--- a/erpnext/regional/report/vat_audit_report/vat_audit_report.py
+++ b/erpnext/regional/report/vat_audit_report/vat_audit_report.py
@@ -41,7 +41,7 @@
 		return self.columns, self.data
 
 	def get_sa_vat_accounts(self):
-		self.sa_vat_accounts = frappe.get_list("South Africa VAT Account",
+		self.sa_vat_accounts = frappe.get_all("South Africa VAT Account",
 			filters = {"parent": self.filters.company}, pluck="account")
 		if not self.sa_vat_accounts and not frappe.flags.in_test and not frappe.flags.in_migrate:
 			link_to_settings = get_link_to_form("South Africa VAT Settings", "", label="South Africa VAT Settings")
diff --git a/erpnext/regional/saudi_arabia/utils.py b/erpnext/regional/saudi_arabia/utils.py
index a2f634e..1051315 100644
--- a/erpnext/regional/saudi_arabia/utils.py
+++ b/erpnext/regional/saudi_arabia/utils.py
@@ -1,7 +1,10 @@
 import io
 import os
+from base64 import b64encode
 
 import frappe
+from frappe import _
+from frappe.utils.data import add_to_date, get_time, getdate
 from pyqrcode import create as qr_create
 
 from erpnext import get_region
@@ -28,24 +31,74 @@
 
 	for field in meta.get_image_fields():
 		if field.fieldname == 'qr_code':
-			from urllib.parse import urlencode
+			''' TLV conversion for
+			1. Seller's Name
+			2. VAT Number
+			3. Time Stamp
+			4. Invoice Amount
+			5. VAT Amount
+			'''
+			tlv_array = []
+			# Sellers Name
 
-			# Creating public url to print format
-			default_print_format = frappe.db.get_value('Property Setter', dict(property='default_print_format', doc_type=doc.doctype), "value")
+			seller_name = frappe.db.get_value(
+				'Company',
+				doc.company,
+				'company_name_in_arabic')
 
-			# System Language
-			language = frappe.get_system_settings('language')
+			if not seller_name:
+				frappe.throw(_('Arabic name missing for {} in the company document').format(doc.company))
 
-			params = urlencode({
-				'format': default_print_format or 'Standard',
-				'_lang': language,
-				'key': doc.get_signature()
-			})
+			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]))
 
-			# creating qr code for the url
-			url = f"{ frappe.utils.get_url() }/{ doc.doctype }/{ doc.name }?{ params }"
+			# 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]))
+
+			# 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]))
+
+			# Invoice Amount
+			invoice_amount = str(doc.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)
+
+			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)
+
+			# base64 conversion for QR Code
+			base64_string = b64encode(bytes.fromhex(tlv_buff)).decode()
+
 			qr_image = io.BytesIO()
-			url = qr_create(url, error='L')
+			url = qr_create(base64_string, error='L')
 			url.png(qr_image, scale=2, quiet_zone=1)
 
 			# making file
diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js
index a5b2d50..4920584 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_cart.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js
@@ -100,6 +100,10 @@
 			`<div class="add-discount-wrapper">
 				${this.get_discount_icon()} ${__('Add Discount')}
 			</div>
+			<div class="item-qty-total-container">
+				<div class="item-qty-total-label">${__('Total Items')}</div>
+				<div class="item-qty-total-value">0.00</div>
+			</div>
 			<div class="net-total-container">
 				<div class="net-total-label">${__("Net Total")}</div>
 				<div class="net-total-value">0.00</div>
@@ -142,6 +146,7 @@
 
 		this.$numpad_section.prepend(
 			`<div class="numpad-totals">
+			<span class="numpad-item-qty-total"></span>
 				<span class="numpad-net-total"></span>
 				<span class="numpad-grand-total"></span>
 			</div>`
@@ -470,6 +475,7 @@
 		if (!frm) frm = this.events.get_frm();
 
 		this.render_net_total(frm.doc.net_total);
+		this.render_total_item_qty(frm.doc.items);
 		const grand_total = cint(frappe.sys_defaults.disable_rounded_total) ? frm.doc.grand_total : frm.doc.rounded_total;
 		this.render_grand_total(grand_total);
 
@@ -487,6 +493,21 @@
 		);
 	}
 
+	render_total_item_qty(items) {
+		var total_item_qty = 0;
+		items.map((item) => {
+			total_item_qty = total_item_qty + item.qty;
+		});
+
+		this.$totals_section.find('.item-qty-total-container').html(
+			`<div>${__('Total Quantity')}</div><div>${total_item_qty}</div>`
+		);
+
+		this.$numpad_section.find('.numpad-item-qty-total').html(
+			`<div>${__('Total Quantity')}: <span>${total_item_qty}</span></div>`
+		);
+	}
+
 	render_grand_total(value) {
 		const currency = this.events.get_frm().doc.currency;
 		this.$totals_section.find('.grand-total-container').html(
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 5daabe8..c9b8a37 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -222,10 +222,11 @@
 					'route')) + '/' + self.scrub((self.item_name or self.item_code) + '-' + random_string(5))
 
 	def validate_website_image(self):
+		"""Validate if the website image is a public file"""
+
 		if frappe.flags.in_import:
 			return
 
-		"""Validate if the website image is a public file"""
 		auto_set_website_image = False
 		if not self.website_image and self.image:
 			auto_set_website_image = True
@@ -255,10 +256,11 @@
 			self.website_image = None
 
 	def make_thumbnail(self):
+		"""Make a thumbnail of `website_image`"""
+
 		if frappe.flags.in_import:
 			return
 
-		"""Make a thumbnail of `website_image`"""
 		import requests.exceptions
 
 		if not self.is_new() and self.website_image != frappe.db.get_value(self.doctype, self.name, "website_image"):
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index 7237178..8b1224b 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -488,7 +488,7 @@
 			item_doc.save()
 
 		# Check values saved correctly
-		barcodes = frappe.get_list(
+		barcodes = frappe.get_all(
 			'Item Barcode',
 			fields=['barcode', 'barcode_type'],
 			filters={'parent': item_code})
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index e00382b..cd180a4 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -299,7 +299,7 @@
 		"warehouse": warehouse,
 		"income_account": get_default_income_account(args, item_defaults, item_group_defaults, brand_defaults),
 		"expense_account": expense_account or get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults) ,
-		"discount_account": None or get_default_discount_account(args, item_defaults),
+		"discount_account": get_default_discount_account(args, item_defaults),
 		"cost_center": get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults),
 		'has_serial_no': item.has_serial_no,
 		'has_batch_no': item.has_batch_no,
@@ -317,6 +317,7 @@
 		"net_rate": 0.0,
 		"net_amount": 0.0,
 		"discount_percentage": 0.0,
+		"discount_amount": 0.0,
 		"supplier": get_default_supplier(args, item_defaults, item_group_defaults, brand_defaults),
 		"update_stock": args.get("update_stock") if args.get('doctype') in ['Sales Invoice', 'Purchase Invoice'] else 0,
 		"delivered_by_supplier": item.delivered_by_supplier if args.get("doctype") in ["Sales Order", "Sales Invoice"] else 0,