Merge branch 'develop' into customer-doctype-issue
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 0fade8c..7e9211a 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -317,13 +317,13 @@
 			"payment_request_type": args.get("payment_request_type"),
 			"currency": ref_doc.currency,
 			"grand_total": grand_total,
-			"email_to": args.recipient_id or "",
+			"email_to": args.recipient_id or ref_doc.owner,
 			"subject": _("Payment Request for {0}").format(args.dn),
 			"message": gateway_account.get("message") or get_dummy_message(ref_doc),
 			"reference_doctype": args.dt,
 			"reference_name": args.dn,
-			"party_type": args.get("party_type"),
-			"party": args.get("party"),
+			"party_type": args.get("party_type") or "Customer",
+			"party": args.get("party") or ref_doc.customer,
 			"bank_account": bank_account
 		})
 
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index a3264a4..3111a3a 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -499,7 +499,8 @@
 						reference_doctype: me.frm.doctype,
 						reference_name: me.frm.docname,
 						content: __('Reason for hold: ')+data.reason_for_hold,
-						comment_email: frappe.session.user
+						comment_email: frappe.session.user,
+						comment_by: frappe.session.user_fullname
 					},
 					callback: function(r) {
 						if(!r.exc) {
diff --git a/erpnext/communication/desk_page/communication/communication.json b/erpnext/communication/desk_page/communication/communication.json
deleted file mode 100644
index 59318fb..0000000
--- a/erpnext/communication/desk_page/communication/communication.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "cards": [],
- "charts": [],
- "creation": "2020-01-28 11:49:55.003637",
- "developer_mode_only": 0,
- "disable_user_customization": 0,
- "docstatus": 0,
- "doctype": "Desk Page",
- "extends_another_page": 0,
- "icon": "",
- "idx": 0,
- "is_standard": 1,
- "label": "Communication",
- "modified": "2020-03-12 16:30:40.534226",
- "modified_by": "Administrator",
- "module": "Communication",
- "name": "Communication",
- "owner": "Administrator",
- "pin_to_bottom": 0,
- "pin_to_top": 0,
- "shortcuts": []
-}
\ No newline at end of file
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 88c8dba..fcc9098 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -672,19 +672,32 @@
 					# If asset has to be auto created
 					# Check for asset naming series
 					if item_data.get('asset_naming_series'):
+						created_assets = []
+
 						for qty in range(cint(d.qty)):
-							self.make_asset(d)
-						is_plural = 's' if cint(d.qty) != 1 else ''
-						messages.append(_('{0} Asset{2} Created for <b>{1}</b>').format(cint(d.qty), d.item_code, is_plural))
+							asset = self.make_asset(d)
+							created_assets.append(asset)
+						
+						if len(created_assets) > 5:
+							# dont show asset form links if more than 5 assets are created
+							messages.append(_('{} Asset{} created for {}').format(len(created_assets), is_plural, frappe.bold(d.item_code)))
+						else:
+							assets_link = list(map(lambda d: frappe.utils.get_link_to_form('Asset', d), created_assets))
+							assets_link = frappe.bold(','.join(assets_link))
+
+							is_plural = 's' if len(created_assets) != 1 else ''
+							messages.append(
+								_('Asset{} {assets_link} created for {}').format(is_plural, frappe.bold(d.item_code), assets_link=assets_link)
+							)
 					else:
-						frappe.throw(_("Row {1}: Asset Naming Series is mandatory for the auto creation for item {0}")
-							.format(d.item_code, d.idx))
+						frappe.throw(_("Row {}: Asset Naming Series is mandatory for the auto creation for item {}")
+							.format(d.idx, frappe.bold(d.item_code)))
 				else:
-					messages.append(_("Assets not created for <b>{0}</b>. You will have to create asset manually.")
-						.format(d.item_code))
+					messages.append(_("Assets not created for {0}. You will have to create asset manually.")
+						.format(frappe.bold(d.item_code)))
 
 		for message in messages:
-			frappe.msgprint(message, title="Success")
+			frappe.msgprint(message, title="Success", indicator="green")
 
 	def make_asset(self, row):
 		if not row.asset_location:
@@ -716,6 +729,8 @@
 		asset.set_missing_values()
 		asset.insert()
 
+		return asset.name
+
 	def update_fixed_asset(self, field, delete_asset = False):
 		for d in self.get("items"):
 			if d.is_fixed_asset:
@@ -1026,4 +1041,4 @@
 			available_batches.append({'batch': batch, 'qty': available_qty})
 			required_qty -= available_qty
 
-	return available_batches
\ No newline at end of file
+	return available_batches
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index d18f8e5..163ef72 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -3,6 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe
+import erpnext
 from frappe.desk.reportview import get_match_cond, get_filters_cond
 from frappe.utils import nowdate, getdate
 from collections import defaultdict
@@ -129,23 +130,26 @@
 		})
 
 def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
+	company_currency = erpnext.get_company_currency(filters.get('company'))
+
 	tax_accounts = frappe.db.sql("""select name, parent_account	from tabAccount
 		where tabAccount.docstatus!=2
 			and account_type in (%s)
 			and is_group = 0
 			and company = %s
+			and account_currency = %s
 			and `%s` LIKE %s
 		order by idx desc, name
 		limit %s, %s""" %
-		(", ".join(['%s']*len(filters.get("account_type"))), "%s", searchfield, "%s", "%s", "%s"),
-		tuple(filters.get("account_type") + [filters.get("company"), "%%%s%%" % txt,
+		(", ".join(['%s']*len(filters.get("account_type"))), "%s", "%s", searchfield, "%s", "%s", "%s"),
+		tuple(filters.get("account_type") + [filters.get("company"), company_currency, "%%%s%%" % txt,
 			start, page_len]))
 	if not tax_accounts:
 		tax_accounts = frappe.db.sql("""select name, parent_account	from tabAccount
 			where tabAccount.docstatus!=2 and is_group = 0
-				and company = %s and `%s` LIKE %s limit %s, %s"""
-			% ("%s", searchfield, "%s", "%s", "%s"),
-			(filters.get("company"), "%%%s%%" % txt, start, page_len))
+				and company = %s and account_currency = %s and `%s` LIKE %s limit %s, %s""" #nosec
+			% ("%s", "%s", searchfield, "%s", "%s", "%s"),
+			(filters.get("company"), company_currency, "%%%s%%" % txt, start, page_len))
 
 	return tax_accounts
 
diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json
index bc007b1..5299368 100644
--- a/erpnext/crm/doctype/lead/lead.json
+++ b/erpnext/crm/doctype/lead/lead.json
@@ -171,7 +171,6 @@
    "options": "Customer"
   },
   {
-   "depends_on": "eval: doc.source==\"Campaign\"",
    "fieldname": "campaign_name",
    "fieldtype": "Link",
    "label": "Campaign Name",
@@ -512,4 +511,4 @@
  "sort_field": "modified",
  "sort_order": "DESC",
  "title_field": "title"
-}
\ No newline at end of file
+}
diff --git a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
index 4aad142..3c9758e 100644
--- a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
+++ b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
@@ -4,11 +4,12 @@
 def execute():
 	frappe.reload_doc('accounts', 'doctype', 'bank', force=1)
 
-	frappe.db.sql("""
-		UPDATE `tabBank` b, `tabBank Account` ba
-		SET b.swift_number = ba.swift_number, b.branch_code = ba.branch_code
-		WHERE b.name = ba.bank
-	""")
+	if frappe.db.table_exists('Bank') and frappe.db.table_exists('Bank Account'):
+		frappe.db.sql("""
+			UPDATE `tabBank` b, `tabBank Account` ba
+			SET b.swift_number = ba.swift_number, b.branch_code = ba.branch_code
+			WHERE b.name = ba.bank
+		""")
 
 	frappe.reload_doc('accounts', 'doctype', 'bank_account')
 	frappe.reload_doc('accounts', 'doctype', 'payment_request')
\ No newline at end of file
diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js
index 3570a0f..5862963 100644
--- a/erpnext/projects/doctype/project/project.js
+++ b/erpnext/projects/doctype/project/project.js
@@ -18,7 +18,7 @@
 		};
 	},
 	onload: function (frm) {
-		var so = frappe.meta.get_docfield("Project", "sales_order");
+		var so = frm.get_docfield("Project", "sales_order");
 		so.get_route_options_for_new_doc = function (field) {
 			if (frm.is_new()) return;
 			return {
@@ -135,4 +135,4 @@
 		frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
 	});
 
-}
\ No newline at end of file
+}
diff --git a/erpnext/regional/report/datev/datev.js b/erpnext/regional/report/datev/datev.js
index 1e000b6..d8638ab 100644
--- a/erpnext/regional/report/datev/datev.js
+++ b/erpnext/regional/report/datev/datev.js
@@ -21,6 +21,12 @@
 			"default": frappe.datetime.now_date(),
 			"fieldtype": "Date",
 			"reqd": 1
+		},
+		{
+			"fieldname": "voucher_type",
+			"label": __("Voucher Type"),
+			"fieldtype": "Select",
+			"options": "\nSales Invoice\nPurchase Invoice\nPayment Entry\nExpense Claim\nPayroll Entry\nBank Reconciliation\nAsset\nStock Entry"
 		}
 	],
 	onload: function(query_report) {
diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py
index e9b4235..a657912 100644
--- a/erpnext/regional/report/datev/datev.py
+++ b/erpnext/regional/report/datev/datev.py
@@ -62,6 +62,7 @@
 	filters -- dict of filters to be passed to the sql query
 	as_dict -- return as list of dicts [0,1]
 	"""
+	filter_by_voucher = 'AND gl.voucher_type = %(voucher_type)s' if filters.get('voucher_type') else ''
 	gl_entries = frappe.db.sql("""
 		SELECT
 
@@ -80,8 +81,10 @@
 			gl.posting_date as 'Belegdatum',
 			gl.voucher_no as 'Belegfeld 1',
 			gl.remarks as 'Buchungstext',
-			gl.against_voucher_type as 'Beleginfo - Art 1',
-			gl.against_voucher as 'Beleginfo - Inhalt 1'
+			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'
 
 		FROM `tabGL Entry` gl
 
@@ -109,7 +112,8 @@
 		WHERE gl.company = %(company)s 
 		AND DATE(gl.posting_date) >= %(from_date)s
 		AND DATE(gl.posting_date) <= %(to_date)s
-		ORDER BY 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict)
+		{}
+		ORDER BY 'Belegdatum', gl.voucher_no""".format(filter_by_voucher), filters, as_dict=as_dict)
 
 	return gl_entries
 
@@ -281,24 +285,24 @@
 
 def get_header(filters, csv_class):
 	coa = frappe.get_value("Company", filters.get("company"), "chart_of_accounts")
-	coa_used = "SKR04" if "SKR04" in coa else ("SKR03" if "SKR03" in coa else "")
+	coa_used = "04" if "SKR04" in coa else ("03" if "SKR03" in coa else "")
 
 	header = [
 		# DATEV format
-		#   "DTVF" = created by DATEV software,
-		#   "EXTF" = created by other software
+		#	"DTVF" = created by DATEV software,
+		#	"EXTF" = created by other software
 		'"EXTF"',
 		# version of the DATEV format
-		#   141 = 1.41, 
-		#   510 = 5.10,
-		#   720 = 7.20
+		#	141 = 1.41, 
+		#	510 = 5.10,
+		#	720 = 7.20
 		'700',
 		csv_class.DATA_CATEGORY,
 		'"%s"' % csv_class.FORMAT_NAME,
 		# Format version (regarding format name)
 		csv_class.FORMAT_VERSION,
 		# Generated on
-		datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
+		datetime.datetime.now().strftime("%Y%m%d%H%M%S") + '000',
 		# Imported on -- stays empty
 		'',
 		# Origin. Any two symbols, will be replaced by "SV" on import.
@@ -328,13 +332,21 @@
 		# R = Diktatkürzel
 		'',
 		# S = Buchungstyp
-		#   1 = Transaction batch (Finanzbuchführung),
-		#   2 = Annual financial statement (Jahresabschluss)
+		#	1 = Transaction batch (Finanzbuchführung),
+		#	2 = Annual financial statement (Jahresabschluss)
 		'1' if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
 		# T = Rechnungslegungszweck
-		'',
+		#	0 oder leer = vom Rechnungslegungszweck unabhängig
+		#	50 = Handelsrecht
+		#	30 = Steuerrecht
+		#	64 = IFRS
+		#	40 = Kalkulatorik
+		#	11 = Reserviert
+		#	12 = Reserviert
+		'0',
 		# U = Festschreibung
-		'',
+		# TODO: Filter by Accounting Period. In export for closed Accounting Period, this will be "1"
+		'0',
 		# V = Default currency, for example, "EUR"
 		'"%s"' % frappe.get_value("Company", filters.get("company"), "default_currency"),
 		# reserviert
diff --git a/erpnext/regional/report/datev/datev_constants.py b/erpnext/regional/report/datev/datev_constants.py
index a4cd5fc..a059ed3 100644
--- a/erpnext/regional/report/datev/datev_constants.py
+++ b/erpnext/regional/report/datev/datev_constants.py
@@ -498,13 +498,27 @@
 	},
 	{
 		"label": "Beleginfo - Art 1",
-		"fieldname": "Beleginfo - Art 2",
-		"fieldtype": "Data",
+		"fieldname": "Beleginfo - Art 1",
+		"fieldtype": "Link",
+		"options": "DocType"
 	},
 	{
 		"label": "Beleginfo - Inhalt 1",
+		"fieldname": "Beleginfo - Inhalt 1",
+		"fieldtype": "Dynamic Link",
+		"options": "Beleginfo - Art 1"
+	},
+	{
+		"label": "Beleginfo - Art 2",
+		"fieldname": "Beleginfo - Art 2",
+		"fieldtype": "Link",
+		"options": "DocType"
+	},
+	{
+		"label": "Beleginfo - Inhalt 2",
 		"fieldname": "Beleginfo - Inhalt 2",
-		"fieldtype": "Data",
+		"fieldtype": "Dynamic Link",
+		"options": "Beleginfo - Art 2"
 	}
 ]
 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index fa765df..61aa608 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -664,7 +664,8 @@
 						reference_doctype: me.frm.doctype,
 						reference_name: me.frm.docname,
 						content: __('Reason for hold: ')+data.reason_for_hold,
-						comment_email: frappe.session.user
+						comment_email: frappe.session.user,
+						comment_by: frappe.session.user_fullname
 					},
 					callback: function(r) {
 						if(!r.exc) {
diff --git a/erpnext/setup/desk_page/getting_started/getting_started.json b/erpnext/setup/desk_page/getting_started/getting_started.json
index 00236ba..b045b5d 100644
--- a/erpnext/setup/desk_page/getting_started/getting_started.json
+++ b/erpnext/setup/desk_page/getting_started/getting_started.json
@@ -41,8 +41,7 @@
  "charts": [
   {
    "chart_name": "Bank Balance",
-   "label": "All Your Money",
-   "size": "Full"
+   "label": "Bank Balance"
   }
  ],
  "creation": "2020-01-23 13:46:38.833076",
@@ -55,7 +54,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Getting Started",
- "modified": "2020-03-12 16:30:37.821762",
+ "modified": "2020-03-23 11:20:49.161823",
  "modified_by": "Administrator",
  "module": "Setup",
  "name": "Getting Started",
@@ -82,6 +81,16 @@
    "is_query_report": 0,
    "link_to": "Sales Invoice",
    "type": "DocType"
+  },
+  {
+   "is_query_report": 0,
+   "link_to": "dashboard",
+   "type": "Page"
+  },
+  {
+   "is_query_report": 0,
+   "link_to": "leaderboard",
+   "type": "Page"
   }
  ]
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
index d97b699..5ad0e13 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -8,6 +8,7 @@
 from frappe.model.meta import get_field_precision
 from frappe.model.document import Document
 from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
+from erpnext.accounts.doctype.account.account import get_account_currency
 
 class LandedCostVoucher(Document):
 	def get_items_from_purchase_receipts(self):
@@ -43,6 +44,7 @@
 		else:
 			self.validate_applicable_charges_for_item()
 		self.validate_purchase_receipts()
+		self.validate_expense_accounts()
 		self.set_total_taxes_and_charges()
 
 	def check_mandatory(self):
@@ -71,6 +73,14 @@
 				frappe.throw(_("Row {0}: Cost center is required for an item {1}")
 					.format(item.idx, item.item_code))
 
+	def validate_expense_accounts(self):
+		company_currency = erpnext.get_company_currency(self.company)
+		for account in self.taxes:
+			if get_account_currency(account.expense_account) != company_currency:
+				frappe.throw(msg=_(""" Row {0}: Expense account currency should be same as company's default currency.
+					Please select expense account with account currency as {1}""")
+					.format(account.idx, frappe.bold(company_currency)), title=_("Invalid Account Currency"))
+
 	def set_total_taxes_and_charges(self):
 		self.total_taxes_and_charges = sum([flt(d.amount) for d in self.get("taxes")])