Merge pull request #25582 from deepeshgarg007/this_variable

fix: function call to update payment schedule labels
diff --git a/erpnext/accounts/doctype/party_account/party_account.json b/erpnext/accounts/doctype/party_account/party_account.json
index aa32d95..c9f15a6 100644
--- a/erpnext/accounts/doctype/party_account/party_account.json
+++ b/erpnext/accounts/doctype/party_account/party_account.json
@@ -1,87 +1,39 @@
 {
- "allow_copy": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2014-08-29 16:02:39.740505", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
+ "actions": [],
+ "creation": "2014-08-29 16:02:39.740505",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "field_order": [
+  "company",
+  "account"
+ ],
  "fields": [
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "company", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Company", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Company", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "account", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Account", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Account", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
+   "fieldname": "account",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Account",
+   "options": "Account"
   }
- ], 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
-
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2016-07-11 03:28:03.348246", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Party Account", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_seen": 0
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-04-07 18:13:08.833822",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Party Account",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index cf6ec18..6635128 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -114,7 +114,7 @@
 				'party_type': self.party_type,
 				'voucher_type': voucher_type,
 				'account': self.receivable_payable_account
-			}, as_dict=1, debug=1)
+			}, as_dict=1)
 
 	def add_payment_entries(self, entries):
 		self.set('payments', [])
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 4461f29..4de8773 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1111,7 +1111,7 @@
 			if not item.serial_no:
 				continue
 
-			for serial_no in item.serial_no.split("\n"):
+			for serial_no in get_serial_nos(item.serial_no):
 				if serial_no and frappe.db.get_value('Serial No', serial_no, 'item_code') == item.item_code:
 					frappe.db.set_value('Serial No', serial_no, 'sales_invoice', invoice)
 
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 444b40e..db605f7 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -364,7 +364,7 @@
 		payment_terms_details = frappe.db.sql("""
 			select
 				si.name, si.party_account_currency, si.currency, si.conversion_rate,
-				ps.due_date, ps.payment_amount, ps.description, ps.paid_amount, ps.discounted_amount
+				ps.due_date, ps.payment_term, ps.payment_amount, ps.description, ps.paid_amount, ps.discounted_amount
 			from `tab{0}` si, `tabPayment Schedule` ps
 			where
 				si.name = ps.parent and
@@ -394,7 +394,7 @@
 			"due_date": d.due_date,
 			"invoiced": invoiced,
 			"invoice_grand_total": row.invoiced,
-			"payment_term": d.description,
+			"payment_term": d.description or d.payment_term,
 			"paid": d.paid_amount + d.discounted_amount,
 			"credit_note": 0.0,
 			"outstanding": invoiced - d.paid_amount - d.discounted_amount
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
index 0947922..1363b53 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
@@ -2,118 +2,128 @@
 // For license information, please see license.txt
 /* eslint-disable */
 
-frappe.query_reports["Consolidated Financial Statement"] = {
-	"filters": [
-		{
-			"fieldname":"company",
-			"label": __("Company"),
-			"fieldtype": "Link",
-			"options": "Company",
-			"default": frappe.defaults.get_user_default("Company"),
-			"reqd": 1
-		},
-		{
-			"fieldname":"filter_based_on",
-			"label": __("Filter Based On"),
-			"fieldtype": "Select",
-			"options": ["Fiscal Year", "Date Range"],
-			"default": ["Fiscal Year"],
-			"reqd": 1,
-			on_change: function() {
-				let filter_based_on = frappe.query_report.get_filter_value('filter_based_on');
-				frappe.query_report.toggle_filter_display('from_fiscal_year', filter_based_on === 'Date Range');
-				frappe.query_report.toggle_filter_display('to_fiscal_year', filter_based_on === 'Date Range');
-				frappe.query_report.toggle_filter_display('period_start_date', filter_based_on === 'Fiscal Year');
-				frappe.query_report.toggle_filter_display('period_end_date', filter_based_on === 'Fiscal Year');
+frappe.require("assets/erpnext/js/financial_statements.js", function() {
+	frappe.query_reports["Consolidated Financial Statement"] = {
+		"filters": [
+			{
+				"fieldname":"company",
+				"label": __("Company"),
+				"fieldtype": "Link",
+				"options": "Company",
+				"default": frappe.defaults.get_user_default("Company"),
+				"reqd": 1
+			},
+			{
+				"fieldname":"filter_based_on",
+				"label": __("Filter Based On"),
+				"fieldtype": "Select",
+				"options": ["Fiscal Year", "Date Range"],
+				"default": ["Fiscal Year"],
+				"reqd": 1,
+				on_change: function() {
+					let filter_based_on = frappe.query_report.get_filter_value('filter_based_on');
+					frappe.query_report.toggle_filter_display('from_fiscal_year', filter_based_on === 'Date Range');
+					frappe.query_report.toggle_filter_display('to_fiscal_year', filter_based_on === 'Date Range');
+					frappe.query_report.toggle_filter_display('period_start_date', filter_based_on === 'Fiscal Year');
+					frappe.query_report.toggle_filter_display('period_end_date', filter_based_on === 'Fiscal Year');
 
-				frappe.query_report.refresh();
+					frappe.query_report.refresh();
+				}
+			},
+			{
+				"fieldname":"period_start_date",
+				"label": __("Start Date"),
+				"fieldtype": "Date",
+				"hidden": 1,
+				"reqd": 1
+			},
+			{
+				"fieldname":"period_end_date",
+				"label": __("End Date"),
+				"fieldtype": "Date",
+				"hidden": 1,
+				"reqd": 1
+			},
+			{
+				"fieldname":"from_fiscal_year",
+				"label": __("Start Year"),
+				"fieldtype": "Link",
+				"options": "Fiscal Year",
+				"default": frappe.defaults.get_user_default("fiscal_year"),
+				"reqd": 1
+			},
+			{
+				"fieldname":"to_fiscal_year",
+				"label": __("End Year"),
+				"fieldtype": "Link",
+				"options": "Fiscal Year",
+				"default": frappe.defaults.get_user_default("fiscal_year"),
+				"reqd": 1
+			},
+			{
+				"fieldname":"finance_book",
+				"label": __("Finance Book"),
+				"fieldtype": "Link",
+				"options": "Finance Book"
+			},
+			{
+				"fieldname":"report",
+				"label": __("Report"),
+				"fieldtype": "Select",
+				"options": ["Profit and Loss Statement", "Balance Sheet", "Cash Flow"],
+				"default": "Balance Sheet",
+				"reqd": 1
+			},
+			{
+				"fieldname": "presentation_currency",
+				"label": __("Currency"),
+				"fieldtype": "Select",
+				"options": erpnext.get_presentation_currency_list(),
+				"default": frappe.defaults.get_user_default("Currency")
+			},
+			{
+				"fieldname":"accumulated_in_group_company",
+				"label": __("Accumulated Values in Group Company"),
+				"fieldtype": "Check",
+				"default": 0
+			},
+			{
+				"fieldname": "include_default_book_entries",
+				"label": __("Include Default Book Entries"),
+				"fieldtype": "Check",
+				"default": 1
 			}
-		},
-		{
-			"fieldname":"period_start_date",
-			"label": __("Start Date"),
-			"fieldtype": "Date",
-			"hidden": 1,
-			"reqd": 1
-		},
-		{
-			"fieldname":"period_end_date",
-			"label": __("End Date"),
-			"fieldtype": "Date",
-			"hidden": 1,
-			"reqd": 1
-		},
-		{
-			"fieldname":"from_fiscal_year",
-			"label": __("Start Year"),
-			"fieldtype": "Link",
-			"options": "Fiscal Year",
-			"default": frappe.defaults.get_user_default("fiscal_year"),
-			"reqd": 1
-		},
-		{
-			"fieldname":"to_fiscal_year",
-			"label": __("End Year"),
-			"fieldtype": "Link",
-			"options": "Fiscal Year",
-			"default": frappe.defaults.get_user_default("fiscal_year"),
-			"reqd": 1
-		},
-		{
-			"fieldname":"finance_book",
-			"label": __("Finance Book"),
-			"fieldtype": "Link",
-			"options": "Finance Book"
-		},
-		{
-			"fieldname":"report",
-			"label": __("Report"),
-			"fieldtype": "Select",
-			"options": ["Profit and Loss Statement", "Balance Sheet", "Cash Flow"],
-			"default": "Balance Sheet",
-			"reqd": 1
-		},
-		{
-			"fieldname": "presentation_currency",
-			"label": __("Currency"),
-			"fieldtype": "Select",
-			"options": erpnext.get_presentation_currency_list(),
-			"default": frappe.defaults.get_user_default("Currency")
-		},
-		{
-			"fieldname":"accumulated_in_group_company",
-			"label": __("Accumulated Values in Group Company"),
-			"fieldtype": "Check",
-			"default": 0
-		},
-		{
-			"fieldname": "include_default_book_entries",
-			"label": __("Include Default Book Entries"),
-			"fieldtype": "Check",
-			"default": 1
-		}
-	],
-	"formatter": function(value, row, column, data, default_formatter) {
-		value = default_formatter(value, row, column, data);
+		],
+		"formatter": function(value, row, column, data, default_formatter) {			
+			if (data && column.fieldname=="account") {
+				value = data.account_name || value;
+				
+				column.link_onclick =
+				"erpnext.financial_statements.open_general_ledger(" + JSON.stringify(data) + ")";
+				column.is_tree = true;
+			}
 
-		if (!data.parent_account) {
-			value = $(`<span>${value}</span>`);
+			value = default_formatter(value, row, column, data);
 
-			var $value = $(value).css("font-weight", "bold");
+			if (!data.parent_account) {
+				value = $(`<span>${value}</span>`);
 
-			value = $value.wrap("<p></p>").parent().html();
-		}
-		return value;
-	},
-	onload: function() {
-		let fiscal_year = frappe.defaults.get_user_default("fiscal_year")
+				var $value = $(value).css("font-weight", "bold");
 
-		frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
-			var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
-			frappe.query_report.set_filter_value({
-				period_start_date: fy.year_start_date,
-				period_end_date: fy.year_end_date
+				value = $value.wrap("<p></p>").parent().html();
+			}
+			return value;
+		},
+		onload: function() {
+			let fiscal_year = frappe.defaults.get_user_default("fiscal_year")
+
+			frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
+				var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
+				frappe.query_report.set_filter_value({
+					period_start_date: fy.year_start_date,
+					period_end_date: fy.year_end_date
+				});
 			});
-		});
+		}
 	}
-}
+});
\ No newline at end of file
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
index 0c4a422..094f5db 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
@@ -329,8 +329,9 @@
 		has_value = False
 		total = 0
 		row = frappe._dict({
-			"account_name": _(d.account_name),
-			"account": _(d.account_name),
+			"account_name": ('%s - %s' %(_(d.account_number), _(d.account_name))
+				if d.account_number else _(d.account_name)),
+			"account": _(d.name),
 			"parent_account": _(d.parent_account),
 			"indent": flt(d.indent),
 			"year_start_date": start_date,
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index b686dc0..3f2d339 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -838,9 +838,10 @@
 		if not self.get("items"):
 			return
 
-		earliest_schedule_date = min([d.schedule_date for d in self.get("items")])
-		if earliest_schedule_date:
-			self.schedule_date = earliest_schedule_date
+		if any(d.schedule_date for d in self.get("items")):
+			# Select earliest schedule_date.
+			self.schedule_date = min(d.schedule_date for d in self.get("items")
+							if d.schedule_date is not None)
 
 		if self.schedule_date:
 			for d in self.get('items'):
diff --git a/erpnext/hr/doctype/designation/designation.json b/erpnext/hr/doctype/designation/designation.json
index 4c3888b..bab6b90 100644
--- a/erpnext/hr/doctype/designation/designation.json
+++ b/erpnext/hr/doctype/designation/designation.json
@@ -182,6 +182,10 @@
    "share": 1,
    "submit": 0,
    "write": 1
+  },
+  {
+   "read": 1,
+   "role": "Sales User"
   }
  ],
  "quick_entry": 1,
@@ -191,4 +195,4 @@
  "track_changes": 0,
  "track_seen": 0,
  "track_views": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index de9f6e3..23f9fd8 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -774,3 +774,5 @@
 erpnext.patches.v13_0.make_non_standard_user_type #13-04-2021
 erpnext.patches.v13_0.update_shipment_status
 erpnext.patches.v13_0.remove_attribute_field_from_item_variant_setting
+erpnext.patches.v13_0.germany_make_custom_fields
+erpnext.patches.v13_0.germany_fill_debtor_creditor_number
diff --git a/erpnext/patches/v13_0/germany_fill_debtor_creditor_number.py b/erpnext/patches/v13_0/germany_fill_debtor_creditor_number.py
new file mode 100644
index 0000000..11e1e9b
--- /dev/null
+++ b/erpnext/patches/v13_0/germany_fill_debtor_creditor_number.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+
+
+def execute():
+	"""Move account number into the new custom field debtor_creditor_number.
+
+	German companies used to use a dedicated payable/receivable account for
+	every party to mimick party accounts in the external accounting software
+	"DATEV". This is no longer necessary. The reference ID for DATEV will be
+	stored in a new custom field "debtor_creditor_number". 
+	"""
+	company_list = frappe.get_all('Company', filters={'country': 'Germany'})
+
+	for company in company_list:
+		party_account_list = frappe.get_all('Party Account', filters={'company': company.name}, fields=['name', 'account', 'debtor_creditor_number'])
+		for party_account in party_account_list:
+			if (not party_account.account) or party_account.debtor_creditor_number:
+				# account empty or debtor_creditor_number already filled
+				continue
+
+			account_number = frappe.db.get_value('Account', party_account.account, 'account_number')
+			if not account_number:
+				continue
+
+			frappe.db.set_value('Party Account', party_account.name, 'debtor_creditor_number', account_number)
+			frappe.db.set_value('Party Account', party_account.name, 'account', '')
diff --git a/erpnext/patches/v13_0/germany_make_custom_fields.py b/erpnext/patches/v13_0/germany_make_custom_fields.py
new file mode 100644
index 0000000..41ab945
--- /dev/null
+++ b/erpnext/patches/v13_0/germany_make_custom_fields.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+from erpnext.regional.germany.setup import make_custom_fields
+
+
+def execute():
+	"""Execute the make_custom_fields method for german companies.
+
+	It is usually run once at setup of a new company. Since it's new, run it
+	once for existing companies as well.
+	"""
+	company_list = frappe.get_all('Company', filters = {'country': 'Germany'})
+	if not company_list:
+		return
+
+	make_custom_fields()
diff --git a/erpnext/regional/germany/setup.py b/erpnext/regional/germany/setup.py
index ac1f543..c1fa6e4 100644
--- a/erpnext/regional/germany/setup.py
+++ b/erpnext/regional/germany/setup.py
@@ -1,11 +1,24 @@
 import os
 import frappe
+from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
 
 
 def setup(company=None, patch=True):
+	make_custom_fields()
 	add_custom_roles_for_reports()
 
 
+def make_custom_fields():
+	custom_fields = {
+		'Party Account': [
+			dict(fieldname='debtor_creditor_number', label='Debtor/Creditor Number',
+			fieldtype='Data', insert_after='account', translatable=0)
+		]
+	}
+
+	create_custom_fields(custom_fields)
+
+
 def add_custom_roles_for_reports():
 	"""Add Access Control to UAE VAT 201."""
 	if not frappe.db.get_value('Custom Role', dict(report='DATEV')):
@@ -16,4 +29,4 @@
 				dict(role='Accounts User'),
 				dict(role='Accounts Manager')
 			]
-		)).insert()
\ No newline at end of file
+		)).insert()
diff --git a/erpnext/regional/germany/utils/datev/datev_csv.py b/erpnext/regional/germany/utils/datev/datev_csv.py
index f138a80..826d51f 100644
--- a/erpnext/regional/germany/utils/datev/datev_csv.py
+++ b/erpnext/regional/germany/utils/datev/datev_csv.py
@@ -56,10 +56,10 @@
 	)
 
 	if not six.PY2:
-		data = data.encode('latin_1')
+		data = data.encode('latin_1', errors='replace')
 
 	header = get_header(filters, csv_class)
-	header = ';'.join(header).encode('latin_1')
+	header = ';'.join(header).encode('latin_1', errors='replace')
 
 	# 1st Row: Header with meta data
 	# 2nd Row: Data heading (Überschrift der Nutzdaten), included in `data` here.
diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py
index cbc9478..a5ca7ee 100644
--- a/erpnext/regional/report/datev/datev.py
+++ b/erpnext/regional/report/datev/datev.py
@@ -3,9 +3,9 @@
 Provide a report and downloadable CSV according to the German DATEV format.
 
 - Query report showing only the columns that contain data, formatted nicely for
-  dispay to the user.
+	dispay to the user.
 - CSV download functionality `download_datev_csv` that provides a CSV file with
-  all required columns. Used to import the data into the DATEV Software.
+	all required columns. Used to import the data into the DATEV Software.
 """
 from __future__ import unicode_literals
 
@@ -88,6 +88,32 @@
 		"fieldtype": "Dynamic Link",
 		"options": "Beleginfo - Art 2",
 		"width": 150
+	},
+	{
+		"label": "Beleginfo - Art 3",
+		"fieldname": "Beleginfo - Art 3",
+		"fieldtype": "Link",
+		"options": "DocType",
+		"width": 100
+	},
+	{
+		"label": "Beleginfo - Inhalt 3",
+		"fieldname": "Beleginfo - Inhalt 3",
+		"fieldtype": "Dynamic Link",
+		"options": "Beleginfo - Art 3",
+		"width": 150
+	},
+	{
+		"label": "Beleginfo - Art 4",
+		"fieldname": "Beleginfo - Art 4",
+		"fieldtype": "Data",
+		"width": 100
+	},
+	{
+		"label": "Beleginfo - Inhalt 4",
+		"fieldname": "Beleginfo - Inhalt 4",
+		"fieldtype": "Data",
+		"width": 150
 	}
 ]
 
@@ -120,10 +146,8 @@
 	validate_fiscal_year(from_date, to_date, company)
 
 	if not frappe.db.exists('DATEV Settings', filters.get('company')):
-		frappe.log_error(_('Please create {} for Company {}.').format(
-			'<a href="desk#List/DATEV%20Settings/List">{}</a>'.format(_('DATEV Settings')),
-			frappe.bold(filters.get('company'))
-		))
+		msg = 'Please create DATEV Settings for Company {}'.format(filters.get('company'))
+		frappe.log_error(msg, title='DATEV Settings missing')
 		return False
 
 	return True
@@ -169,7 +193,11 @@
 			gl.voucher_type as 'Beleginfo - Art 1',
 			gl.voucher_no as 'Beleginfo - Inhalt 1',
 			gl.against_voucher_type as 'Beleginfo - Art 2',
-			gl.against_voucher as 'Beleginfo - Inhalt 2'
+			gl.against_voucher as 'Beleginfo - Inhalt 2',
+			gl.party_type as 'Beleginfo - Art 3',
+			gl.party as 'Beleginfo - Inhalt 3',
+			case gl.party_type when 'Customer' then 'Debitorennummer' when 'Supplier' then 'Kreditorennummer' else NULL end as 'Beleginfo - Art 4',
+			par.debtor_creditor_number as 'Beleginfo - Inhalt 4'
 
 		FROM `tabGL Entry` gl
 
@@ -177,6 +205,19 @@
 			left join `tabAccount` acc 
 			on gl.account = acc.name
 
+			left join `tabCustomer` cus
+			on gl.party_type = 'Customer'
+			and gl.party = cus.name
+
+			left join `tabSupplier` sup
+			on gl.party_type = 'Supplier'
+			and gl.party = sup.name
+
+			left join `tabParty Account` par
+			on par.parent = gl.party
+			and par.parenttype = gl.party_type
+			and par.company = %(company)s
+
 		WHERE gl.company = %(company)s 
 		AND DATE(gl.posting_date) >= %(from_date)s
 		AND DATE(gl.posting_date) <= %(to_date)s
@@ -196,40 +237,56 @@
 	return frappe.db.sql("""
 		SELECT
 
-			acc.account_number as 'Konto',
-			CASE cus.customer_type WHEN 'Company' THEN cus.customer_name ELSE null END as 'Name (Adressatentyp Unternehmen)',
-			CASE cus.customer_type WHEN 'Individual' THEN con.last_name ELSE null END as 'Name (Adressatentyp natürl. Person)',
-			CASE cus.customer_type WHEN 'Individual' THEN con.first_name ELSE null END as 'Vorname (Adressatentyp natürl. Person)',
-			CASE cus.customer_type WHEN 'Individual' THEN '1' WHEN 'Company' THEN '2' ELSE '0' end as 'Adressatentyp',
+			par.debtor_creditor_number as 'Konto',
+			CASE cus.customer_type
+				WHEN 'Company' THEN cus.customer_name
+				ELSE null
+				END as 'Name (Adressatentyp Unternehmen)',
+			CASE cus.customer_type
+				WHEN 'Individual' THEN TRIM(SUBSTR(cus.customer_name, LOCATE(' ', cus.customer_name)))
+				ELSE null
+				END as 'Name (Adressatentyp natürl. Person)',
+			CASE cus.customer_type
+				WHEN 'Individual' THEN SUBSTRING_INDEX(SUBSTRING_INDEX(cus.customer_name, ' ', 1), ' ', -1)
+				ELSE null
+				END as 'Vorname (Adressatentyp natürl. Person)',
+			CASE cus.customer_type
+				WHEN 'Individual' THEN '1'
+				WHEN 'Company' THEN '2'
+				ELSE '0'
+				END as 'Adressatentyp',
 			adr.address_line1 as 'Straße',
 			adr.pincode as 'Postleitzahl',
 			adr.city as 'Ort',
 			UPPER(country.code) as 'Land',
 			adr.address_line2 as 'Adresszusatz',
-			con.email_id as 'E-Mail',
-			coalesce(con.mobile_no, con.phone) as 'Telefon',
+			adr.email_id as 'E-Mail',
+			adr.phone as 'Telefon',
+			adr.fax as 'Fax',
 			cus.website as 'Internet',
 			cus.tax_id as 'Steuernummer'
 
-		FROM `tabParty Account` par
+		FROM `tabCustomer` cus
 
-			left join `tabAccount` acc
-			on acc.name = par.account
+			left join `tabParty Account` par
+			on par.parent = cus.name
+			and par.parenttype = 'Customer'
+			and par.company = %(company)s
 
-			left join `tabCustomer` cus
-			on cus.name = par.parent
+			left join `tabDynamic Link` dyn_adr
+			on dyn_adr.link_name = cus.name
+			and dyn_adr.link_doctype = 'Customer'
+			and dyn_adr.parenttype = 'Address'
 
 			left join `tabAddress` adr
-			on adr.name = cus.customer_primary_address
+			on adr.name = dyn_adr.parent
+			and adr.is_primary_address = '1'
 
 			left join `tabCountry` country
 			on country.name = adr.country
 
-			left join `tabContact` con
-			on con.name = cus.customer_primary_contact
-
-		WHERE par.company = %(company)s
-		AND par.parenttype = 'Customer'""", filters, as_dict=1)
+		WHERE adr.is_primary_address = '1'
+		""", filters, as_dict=1)
 
 
 def get_suppliers(filters):
@@ -242,35 +299,48 @@
 	return frappe.db.sql("""
 		SELECT
 
-			acc.account_number as 'Konto',
-			CASE sup.supplier_type WHEN 'Company' THEN sup.supplier_name ELSE null END as 'Name (Adressatentyp Unternehmen)',
-			CASE sup.supplier_type WHEN 'Individual' THEN con.last_name ELSE null END as 'Name (Adressatentyp natürl. Person)',
-			CASE sup.supplier_type WHEN 'Individual' THEN con.first_name ELSE null END as 'Vorname (Adressatentyp natürl. Person)',
-			CASE sup.supplier_type WHEN 'Individual' THEN '1' WHEN 'Company' THEN '2' ELSE '0' end as 'Adressatentyp',
+			par.debtor_creditor_number as 'Konto',
+			CASE sup.supplier_type
+				WHEN 'Company' THEN sup.supplier_name
+				ELSE null
+				END as 'Name (Adressatentyp Unternehmen)',
+			CASE sup.supplier_type
+				WHEN 'Individual' THEN TRIM(SUBSTR(sup.supplier_name, LOCATE(' ', sup.supplier_name)))
+				ELSE null
+				END as 'Name (Adressatentyp natürl. Person)',
+			CASE sup.supplier_type
+				WHEN 'Individual' THEN SUBSTRING_INDEX(SUBSTRING_INDEX(sup.supplier_name, ' ', 1), ' ', -1)
+				ELSE null
+				END as 'Vorname (Adressatentyp natürl. Person)',
+			CASE sup.supplier_type
+				WHEN 'Individual' THEN '1'
+				WHEN 'Company' THEN '2'
+				ELSE '0'
+				END as 'Adressatentyp',
 			adr.address_line1 as 'Straße',
 			adr.pincode as 'Postleitzahl',
 			adr.city as 'Ort',
 			UPPER(country.code) as 'Land',
 			adr.address_line2 as 'Adresszusatz',
-			con.email_id as 'E-Mail',
-			coalesce(con.mobile_no, con.phone) as 'Telefon',
+			adr.email_id as 'E-Mail',
+			adr.phone as 'Telefon',
+			adr.fax as 'Fax',
 			sup.website as 'Internet',
 			sup.tax_id as 'Steuernummer',
 			case sup.on_hold when 1 then sup.release_date else null end as 'Zahlungssperre bis'
 
-		FROM `tabParty Account` par
+		FROM `tabSupplier` sup
 
-			left join `tabAccount` acc
-			on acc.name = par.account
-
-			left join `tabSupplier` sup
-			on sup.name = par.parent
+			left join `tabParty Account` par
+			on par.parent = sup.name
+			and par.parenttype = 'Supplier'
+			and par.company = %(company)s
 
 			left join `tabDynamic Link` dyn_adr
 			on dyn_adr.link_name = sup.name
 			and dyn_adr.link_doctype = 'Supplier'
 			and dyn_adr.parenttype = 'Address'
-			
+
 			left join `tabAddress` adr
 			on adr.name = dyn_adr.parent
 			and adr.is_primary_address = '1'
@@ -278,17 +348,8 @@
 			left join `tabCountry` country
 			on country.name = adr.country
 
-			left join `tabDynamic Link` dyn_con
-			on dyn_con.link_name = sup.name
-			and dyn_con.link_doctype = 'Supplier'
-			and dyn_con.parenttype = 'Contact'
-
-			left join `tabContact` con
-			on con.name = dyn_con.parent
-			and con.is_primary_contact = '1'
-
-		WHERE par.company = %(company)s
-		AND par.parenttype = 'Supplier'""", filters, as_dict=1)
+		WHERE adr.is_primary_address = '1'
+		""", filters, as_dict=1)
 
 
 def get_account_names(filters):
diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js
index 709fe57..9384ae5 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_selector.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js
@@ -81,13 +81,24 @@
 		const { item_image, serial_no, batch_no, barcode, actual_qty, stock_uom } = item;
 		const indicator_color = actual_qty > 10 ? "green" : actual_qty <= 0 ? "red" : "orange";
 
+		let qty_to_display = actual_qty;
+
+		if (Math.round(qty_to_display) > 999) {
+			qty_to_display = Math.round(qty_to_display)/1000;
+			qty_to_display = qty_to_display.toFixed(1) + 'K';
+		}
+
 		function get_item_image_html() {
 			if (!me.hide_images && item_image) {
-				return `<div class="flex items-center justify-center h-32 border-b-grey text-6xl text-grey-100">
+				return `<div class="flex" style="margin: 8px; justify-content: flex-end">
+						<span class="indicator-pill whitespace-nowrap ${indicator_color}" id="text">${qty_to_display}</span></div>
+						<div class="flex items-center justify-center h-32 border-b-grey text-6xl text-grey-100">
 							<img class="h-full" src="${item_image}" alt="${frappe.get_abbr(item.item_name)}" style="object-fit: cover;">
 						</div>`;
 			} else {
-				return `<div class="item-display abbr">${frappe.get_abbr(item.item_name)}</div>`;
+				return `<div class="flex" style="margin: 8px; justify-content: flex-end">
+						<span class="indicator-pill whitespace-nowrap ${indicator_color}">${qty_to_display}</span></div>
+						<div class="item-display abbr">${frappe.get_abbr(item.item_name)}</div>`;
 			}
 		}
 
@@ -95,13 +106,12 @@
 			`<div class="item-wrapper"
 				data-item-code="${escape(item.item_code)}" data-serial-no="${escape(serial_no)}"
 				data-batch-no="${escape(batch_no)}" data-uom="${escape(stock_uom)}"
-				title="Avaiable Qty: ${actual_qty}">
+				title="${item.item_name}">
 
 				${get_item_image_html()}
 
 				<div class="item-detail">
 					<div class="item-name">
-						<span class="indicator ${indicator_color}"></span>
 						${frappe.ellipsis(item.item_name, 18)}
 					</div>
 					<div class="item-rate">${format_currency(item.price_list_rate, item.currency, 0) || 0}</div>
@@ -316,4 +326,4 @@
 	toggle_component(show) {
 		show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none');
 	}
-};
\ No newline at end of file
+};
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 3fc1df7..3832415 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -470,7 +470,9 @@
 			item_tax_template = _get_item_tax_template(args, item_group_doc.taxes, out)
 			item_group = item_group_doc.parent_item_group
 
-def _get_item_tax_template(args, taxes, out={}, for_validate=False):
+def _get_item_tax_template(args, taxes, out=None, for_validate=False):
+	if out is None:
+		out = {}
 	taxes_with_validity = []
 	taxes_with_no_validity = []
 
@@ -935,8 +937,8 @@
 def get_company_total_stock(item_code, company):
 	return frappe.db.sql("""SELECT sum(actual_qty) from 
 		(`tabBin` INNER JOIN `tabWarehouse` ON `tabBin`.warehouse = `tabWarehouse`.name) 
-		WHERE `tabWarehouse`.company = '{0}' and `tabBin`.item_code = '{1}'"""
-		.format(company, item_code))[0][0]
+		WHERE `tabWarehouse`.company = %s and `tabBin`.item_code = %s""",
+		(company, item_code))[0][0]
 
 @frappe.whitelist()
 def get_serial_no_details(item_code, warehouse, stock_qty, serial_no):
diff --git a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py
index 087c12e..01927c2 100644
--- a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py
+++ b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py
@@ -70,7 +70,7 @@
 	return frappe.db.sql("""
 		select item_code, batch_no, warehouse, posting_date, sum(actual_qty) as actual_qty
 		from `tabStock Ledger Entry`
-		where docstatus < 2 and ifnull(batch_no, '') != '' %s
+		where is_cancelled = 0 and docstatus < 2 and ifnull(batch_no, '') != '' %s
 		group by voucher_no, batch_no, item_code, warehouse
 		order by item_code, warehouse""" %
 		conditions, as_dict=1)
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 6dfede4..bbd73e9 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -165,7 +165,7 @@
 		select
 			sle.item_code, warehouse, sle.posting_date, sle.actual_qty, sle.valuation_rate,
 			sle.company, sle.voucher_type, sle.qty_after_transaction, sle.stock_value_difference,
-			sle.item_code as name, sle.voucher_no, sle.stock_value
+			sle.item_code as name, sle.voucher_no, sle.stock_value, sle.batch_no
 		from
 			`tabStock Ledger Entry` sle force index (posting_sort_index)
 		where sle.docstatus < 2 %s %s
@@ -193,7 +193,7 @@
 
 		qty_dict = iwb_map[(d.company, d.item_code, d.warehouse)]
 
-		if d.voucher_type == "Stock Reconciliation":
+		if d.voucher_type == "Stock Reconciliation" and not d.batch_no:
 			qty_diff = flt(d.qty_after_transaction) - flt(qty_dict.bal_qty)
 		else:
 			qty_diff = flt(d.actual_qty)