refactor: taxes setup

Better structure of input data.
diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json
index 9ccbdb9..6305442 100644
--- a/erpnext/setup/setup_wizard/data/country_wise_tax.json
+++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json
@@ -487,23 +487,25 @@
 					{
 						"title": "Umsatzsteuer 19%",
 						"is_default": 1,
-						"accounts": [
+						"taxes": [
 							{
-								"type": "On Net Total",
-								"account_name": "Umsatzsteuer 19%",
-								"account_number": "3806",
-								"rate": 19.00
+								"account_head": {
+									"account_name": "Umsatzsteuer 19%",
+									"account_number": "3806",
+									"tax_rate": 19.00
+								}
 							}
 						]
 					},
 					{
 						"title": "Umsatzsteuer 7%",
-						"accounts": [
+						"taxes": [
 							{
-								"type": "On Net Total",
-								"account_name": "Umsatzsteuer 7%",
-								"account_number": "3801",
-								"tax_rate": 7.00
+								"account_head": {
+									"account_name": "Umsatzsteuer 7%",
+									"account_number": "3801",
+									"tax_rate": 7.00
+								}
 							}
 						]
 					}
@@ -512,41 +514,49 @@
 					{
 						"title": "Abziehbare Vorsteuer 19%",
 						"is_default": 1,
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "Abziehbare Vorsteuer 19%",
-								"account_number": "1406",
-								"root_type": "Asset",
-								"tax_rate": 19.00
+								"account_head": {
+									"account_name": "Abziehbare Vorsteuer 19%",
+									"account_number": "1406",
+									"root_type": "Asset",
+									"tax_rate": 19.00
+								}
 							}
 						]
 					},
 					{
 						"title": "Abziehbare Vorsteuer 7%",
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "Abziehbare Vorsteuer 7%",
-								"account_number": "1401",
-								"root_type": "Asset",
-								"tax_rate": 7.00
+								"account_head": {
+									"account_name": "Abziehbare Vorsteuer 7%",
+									"account_number": "1401",
+									"root_type": "Asset",
+									"tax_rate": 7.00
+								}
 							}
 						]
 					},
 					{
 						"title": "Innergemeinschaftlicher Erwerb 19% Umsatzsteuer und 19% Vorsteuer",
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "Abziehbare Vorsteuer nach § 13b UStG 19%",
-								"account_number": "1407",
-								"root_type": "Asset",
-								"tax_rate": 19.00,
+								"account_head": {
+									"account_name": "Abziehbare Vorsteuer nach § 13b UStG 19%",
+									"account_number": "1407",
+									"root_type": "Asset",
+									"tax_rate": 19.00
+								},
 								"add_deduct_tax": "Add"
 							},
 							{
-								"account_name": "Umsatzsteuer nach § 13b UStG 19%",
-								"account_number": "3837",
-								"root_type": "Liability",
-								"tax_rate": 19.00,
+								"account_head": {
+									"account_name": "Umsatzsteuer nach § 13b UStG 19%",
+									"account_number": "3837",
+									"root_type": "Liability",
+									"tax_rate": 19.00
+								},
 								"add_deduct_tax": "Deduct"
 							}
 						]
@@ -558,23 +568,25 @@
 					{
 						"title": "Umsatzsteuer 19%",
 						"is_default": 1,
-						"accounts": [
+						"taxes": [
 							{
-								"type": "On Net Total",
-								"account_name": "Umsatzsteuer 19%",
-								"account_number": "1776",
-								"rate": 19.00
+								"account_head": {
+									"account_name": "Umsatzsteuer 19%",
+									"account_number": "1776",
+									"tax_rate": 19.00
+								}
 							}
 						]
 					},
 					{
 						"title": "Umsatzsteuer 7%",
-						"accounts": [
+						"taxes": [
 							{
-								"type": "On Net Total",
-								"account_name": "Umsatzsteuer 7%",
-								"account_number": "1771",
-								"tax_rate": 7.00
+								"account_head": {
+									"account_name": "Umsatzsteuer 7%",
+									"account_number": "1771",
+									"tax_rate": 7.00
+								}
 							}
 						]
 					}
@@ -583,23 +595,27 @@
 					{
 						"title": "Abziehbare Vorsteuer 19%",
 						"is_default": 1,
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "Abziehbare Vorsteuer 19%",
-								"account_number": "1576",
-								"root_type": "Asset",
-								"tax_rate": 19.00
+								"account_head": {
+									"account_name": "Abziehbare Vorsteuer 19%",
+									"account_number": "1576",
+									"root_type": "Asset",
+									"tax_rate": 19.00
+								}
 							}
 						]
 					},
 					{
 						"title": "Abziehbare Vorsteuer 7%",
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "Abziehbare Vorsteuer 7%",
-								"account_number": "1571",
-								"root_type": "Asset",
-								"tax_rate": 7.00
+								"account_head": {
+									"account_name": "Abziehbare Vorsteuer 7%",
+									"account_number": "1571",
+									"root_type": "Asset",
+									"tax_rate": 7.00
+								}
 							}
 						]
 					}
@@ -610,23 +626,25 @@
 					{
 						"title": "Umsatzsteuer 19%",
 						"is_default": 1,
-						"accounts": [
+						"taxes": [
 							{
-								"type": "On Net Total",
-								"account_name": "Umsatzsteuer 19%",
-								"account_number": "2301",
-								"rate": 19.00
+								"account_head": {
+									"account_name": "Umsatzsteuer 19%",
+									"account_number": "2301",
+									"tax_rate": 19.00
+								}
 							}
 						]
 					},
 					{
 						"title": "Umsatzsteuer 7%",
-						"accounts": [
+						"taxes": [
 							{
-								"type": "On Net Total",
-								"account_name": "Umsatzsteuer 7%",
-								"account_number": "2302",
-								"tax_rate": 7.00
+								"account_head": {
+									"account_name": "Umsatzsteuer 7%",
+									"account_number": "2302",
+									"tax_rate": 7.00
+								}
 							}
 						]
 					}
@@ -635,23 +653,27 @@
 					{
 						"title": "Abziehbare Vorsteuer 19%",
 						"is_default": 1,
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "Abziehbare Vorsteuer 19%",
-								"account_number": "1501",
-								"root_type": "Asset",
-								"tax_rate": 19.00
+								"account_head": {
+									"account_name": "Abziehbare Vorsteuer 19%",
+									"account_number": "1501",
+									"root_type": "Asset",
+									"tax_rate": 19.00
+								}
 							}
 						]
 					},
 					{
 						"title": "Abziehbare Vorsteuer 7%",
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "Abziehbare Vorsteuer 7%",
-								"account_number": "1502",
-								"root_type": "Asset",
-								"tax_rate": 7.00
+								"account_head": {
+									"account_name": "Abziehbare Vorsteuer 7%",
+									"account_number": "1502",
+									"root_type": "Asset",
+									"tax_rate": 7.00
+								}
 							}
 						]
 					}
@@ -662,21 +684,23 @@
 					{
 						"title": "Umsatzsteuer 19%",
 						"is_default": 1,
-						"accounts": [
+						"taxes": [
 							{
-								"type": "On Net Total",
-								"account_name": "Umsatzsteuer 19%",
-								"rate": 19.00
+								"account_head": {
+									"account_name": "Umsatzsteuer 19%",
+									"tax_rate": 19.00
+								}
 							}
 						]
 					},
 					{
 						"title": "Umsatzsteuer 7%",
-						"accounts": [
+						"taxes": [
 							{
-								"type": "On Net Total",
-								"account_name": "Umsatzsteuer 7%",
-								"tax_rate": 7.00
+								"account_head": {
+									"account_name": "Umsatzsteuer 7%",
+									"tax_rate": 7.00
+								}
 							}
 						]
 					}
@@ -685,21 +709,25 @@
 					{
 						"title": "Abziehbare Vorsteuer 19%",
 						"is_default": 1,
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "Abziehbare Vorsteuer 19%",
-								"root_type": "Asset",
-								"tax_rate": 19.00
+								"account_head": {
+									"account_name": "Abziehbare Vorsteuer 19%",
+									"tax_rate": 19.00,
+									"root_type": "Asset"
+								}
 							}
 						]
 					},
 					{
 						"title": "Abziehbare Vorsteuer 7%",
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "Abziehbare Vorsteuer 7%",
-								"root_type": "Asset",
-								"tax_rate": 7.00
+								"account_head": {
+									"account_name": "Abziehbare Vorsteuer 7%",
+									"root_type": "Asset",
+									"tax_rate": 7.00
+								}
 							}
 						]
 					}
@@ -798,54 +826,130 @@
 	"India": {
 		"chart_of_accounts": {
 			"*": {
-				"*": [
+				"item_tax_templates": [
 					{
 						"title": "In State GST",
 						"is_default": 1,
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "SGST",
-								"tax_rate": 9.00
+								"tax_type": {
+									"account_name": "SGST",
+									"tax_rate": 9.00
+								}
 							},
 							{
-								"account_name": "CGST",
-								"tax_rate": 9.00
+								"tax_type": {
+									"account_name": "CGST",
+									"tax_rate": 9.00
+								}
 							}
 						]
 					},
 					{
 						"title": "Out of State GST",
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "IGST",
-								"tax_rate": 18.00
+								"tax_type": {
+									"account_name": "IGST",
+									"tax_rate": 18.00
+								}
 							}
 						]
 					},
 					{
 						"title": "VAT 5%",
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "VAT 5%",
-								"tax_rate": 5.00
+								"tax_type": {
+									"account_name": "VAT 5%",
+									"tax_rate": 5.00
+								}
 							}
 						]
 					},
 					{
 						"title": "VAT 4%",
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "VAT 4%",
-								"tax_rate": 4.00
+								"tax_type": {
+									"account_name": "VAT 4%",
+									"tax_rate": 4.00
+								}
 							}
 						]
 					},
 					{
 						"title": "VAT 14%",
-						"accounts": [
+						"taxes": [
 							{
-								"account_name": "VAT 14%",
-								"tax_rate": 14.00
+								"tax_type": {
+									"account_name": "VAT 14%",
+									"tax_rate": 14.00
+								}
+							}
+						]
+					}
+				],
+				"*": [
+					{
+						"title": "In State GST",
+						"is_default": 1,
+						"taxes": [
+							{
+								"account_head": {
+									"account_name": "SGST",
+									"tax_rate": 9.00
+								}
+							},
+							{
+								"account_head": {
+									"account_name": "CGST",
+									"tax_rate": 9.00
+								}
+							}
+						]
+					},
+					{
+						"title": "Out of State GST",
+						"taxes": [
+							{
+								"account_head": {
+									"account_name": "IGST",
+									"tax_rate": 18.00
+								}
+							}
+						]
+					},
+					{
+						"title": "VAT 5%",
+						"taxes": [
+							{
+								"account_head": {
+									"account_name": "VAT 5%",
+									"tax_rate": 5.00
+								}
+							}
+						]
+					},
+					{
+						"title": "VAT 4%",
+						"taxes": [
+							{
+								"account_head": {
+									"account_name": "VAT 4%",
+									"tax_rate": 4.00
+								}
+							}
+						]
+					},
+					{
+						"title": "VAT 14%",
+						"taxes": [
+							{
+								"account_head": {
+									"account_name": "VAT 14%",
+									"tax_rate": 14.00
+								}
 							}
 						]
 					}
diff --git a/erpnext/setup/setup_wizard/operations/taxes_setup.py b/erpnext/setup/setup_wizard/operations/taxes_setup.py
index 81506c4..429a558 100644
--- a/erpnext/setup/setup_wizard/operations/taxes_setup.py
+++ b/erpnext/setup/setup_wizard/operations/taxes_setup.py
@@ -17,40 +17,62 @@
 
 	country_wise_tax = tax_data.get(country)
 
-	if country_wise_tax:
-		if 'chart_of_accounts' in country_wise_tax:
-			from_detailed_data(company_name, country_wise_tax.get('chart_of_accounts'))
-		else:
-			from_simple_data(company_name, country_wise_tax)
+	if not country_wise_tax:
+		return
+
+	if 'chart_of_accounts' not in country_wise_tax:
+		country_wise_tax = simple_to_detailed(country_wise_tax)
+
+	from_detailed_data(company_name, country_wise_tax.get('chart_of_accounts'))
 
 
-def from_detailed_data(company_name, data):
+def simple_to_detailed(templates):
 	"""
-	Create Taxes and Charges Templates from detailed data like this:
+	Convert a simple taxes object into a more detailed data structure.
+
+	Example input:
 
 	{
-		"chart_of_accounts": {
-			coa_name: {
-				"sales_tax_templates": [
-					{
-						'title': '',
-						'is_default': 1,
-						'accounts': [
-							{
-								'account_name': '',
-								'account_number': '',
-								'root_type': '',
-							}
-						]
-					}
-				],
-				"purchase_tax_templates": [ ... ],
-				"item_tax_templates": [ ... ],
-				"*": [ ... ]
-			}
+		"France VAT 20%": {
+			"account_name": "VAT 20%",
+			"tax_rate": 20,
+			"default": 1
+		},
+		"France VAT 10%": {
+			"account_name": "VAT 10%",
+			"tax_rate": 10
 		}
 	}
 	"""
+	return {
+		'chart_of_accounts': {
+			'*': {
+				'item_tax_templates': [{
+					'title': title,
+					'taxes': [{
+						'tax_type': {
+							'account_name': data.get('account_name'),
+							'tax_rate': data.get('tax_rate')
+						}
+					}]
+				} for title, data in templates.items()],
+				'*': [{
+					'title': title,
+					'is_default': data.get('default', 0),
+					'taxes': [{
+						'account_head': {
+							'account_name': data.get('account_name'),
+							'tax_rate': data.get('tax_rate')
+						}
+					}]
+				} for title, data in templates.items()]
+			}
+		}
+	}
+
+
+def from_detailed_data(company_name, data):
+	"""Create Taxes and Charges Templates from detailed data."""
 	coa_name = frappe.db.get_value('Company', company_name, 'chart_of_accounts')
 	tax_templates = data.get(coa_name) or data.get('*')
 	sales_tax_templates = tax_templates.get('sales_tax_templates') or tax_templates.get('*')
@@ -59,85 +81,44 @@
 
 	if sales_tax_templates:
 		for template in sales_tax_templates:
-			make_tax_template(company_name, 'Sales Taxes and Charges Template', template)
+			make_taxes_and_charges_template(company_name, 'Sales Taxes and Charges Template', template)
 
 	if purchase_tax_templates:
 		for template in purchase_tax_templates:
-			make_tax_template(company_name, 'Purchase Taxes and Charges Template', template)
+			make_taxes_and_charges_template(company_name, 'Purchase Taxes and Charges Template', template)
 
 	if item_tax_templates:
 		for template in item_tax_templates:
 			make_item_tax_template(company_name, template)
 
 
-def from_simple_data(company_name, data):
-	"""
-	Create Taxes and Charges Templates from simple data like this:
+def make_taxes_and_charges_template(company_name, doctype, template):
+	template['company'] = company_name
+	template['doctype'] = doctype
 
-	"Austria Tax": {
-		"account_name": "VAT",
-		"tax_rate": 20.00
-	}
-	"""
-	for template_name, tax_data in data.items():
-		template = {
-			'title': template_name,
-			'is_default': tax_data.get('default'),
-			'accounts': [
-				{
-					'account_name': tax_data.get('account_name'),
-					'tax_rate': tax_data.get('tax_rate')
-				}
-			]
-		}
-		make_tax_template(company_name, 'Sales Taxes and Charges Template', template)
-		make_tax_template(company_name, 'Purchase Taxes and Charges Template', template)
-		make_item_tax_template(company_name, template)
-
-
-def make_tax_template(company_name, doctype, template):
 	if frappe.db.exists(doctype, {'title': template.get('title'), 'company': company_name}):
 		return
 
-	accounts = get_or_create_accounts(company_name, template.get('accounts'))
-
-	# Get all fields of the Taxes and Charges Template
-	tax_template = {'doctype': doctype}
-	tax_template_fields = frappe.get_meta(doctype).fields
-	tax_template_fieldnames = [field.fieldname for field in tax_template_fields]
-
-	# Get all fields of the taxes child table
-	table_doctype = [field.options for field in tax_template_fields if field.fieldname=='taxes'][0]
-	table_fields = frappe.get_meta(table_doctype).fields
-	table_field_names = [field.fieldname for field in table_fields]
-
-	# Check if field exists as a key in the import data and, if yes, set the
-	# value accordingly
-	for field in tax_template_fieldnames:
-		if field in template:
-			tax_template[field] = template.get(field)
-
-	# However, company always fixed and taxes table must be empty to start with
-	tax_template['company'] = company_name
-	tax_template['taxes'] = []
-
-	for account in accounts:
-		row = {
+	for tax_row in template.get('taxes'):
+		account_data = tax_row.get('account_head')
+		tax_row_defaults = {
 			'category': 'Total',
-			'charge_type': 'On Net Total',
-			'account_head': account.get('name'),
-			'description': '{0} @ {1}'.format(account.get('account_name'), account.get('tax_rate')),
-			'rate': account.get('tax_rate')
+			'charge_type': 'On Net Total'
 		}
-		# Check if field exists as a key in the import data and, if yes, set the
-		# value accordingly
-		for field in table_field_names:
-			if field in account:
-				row[field] = account.get(field)
 
-		tax_template['taxes'].append(row)
+		# if account_head is a dict, search or create the account and get it's name
+		if isinstance(account_data, dict):
+			tax_row_defaults['description'] = '{0} @ {1}'.format(account_data.get('account_name'), account_data.get('tax_rate'))
+			tax_row_defaults['rate'] = account_data.get('tax_rate')
+			account = get_or_create_account(company_name, account_data)
+			tax_row['account_head'] = account.name
 
-	return frappe.get_doc(tax_template).insert(ignore_permissions=True)
+		# use the default value if nothing other is specified
+		for fieldname, default_value in tax_row_defaults.items():
+			if fieldname not in tax_row:
+				tax_row[fieldname] = default_value
+
+	return frappe.get_doc(template).insert(ignore_permissions=True)
 
 
 def make_item_tax_template(company_name, template):
@@ -147,111 +128,105 @@
 	differently from Sales and Purchase Tax Templates.
 	"""
 	doctype = 'Item Tax Template'
+	template['company'] = company_name
+	template['doctype'] = doctype
+
 	if frappe.db.exists(doctype, {'title': template.get('title'), 'company': company_name}):
 		return
 
-	accounts = get_or_create_accounts(company_name, template.get('accounts'))
+	for tax_row in template.get('taxes'):
+		account_data = tax_row.get('tax_type')
 
-	item_tax_template = {
-		'doctype': doctype,
-		'title': template.get('title'),
-		'company': company_name,
-		'taxes': [{
-			'tax_type': account.get('name'),
-			'tax_rate': account.get('tax_rate')
-		} for account in accounts]
-	}
+		# if tax_type is a dict, search or create the account and get it's name
+		if isinstance(account_data, dict):
+			account = get_or_create_account(company_name, account_data)
+			tax_row['tax_type'] = account.name
+			if 'tax_rate' not in tax_row:
+				tax_row['tax_rate'] = account_data.get('tax_rate')
 
-	return frappe.get_doc(item_tax_template).insert(ignore_permissions=True)
+	return frappe.get_doc(template).insert(ignore_permissions=True)
 
 
-def get_or_create_accounts(company: str, account_data: list):
-	for account in account_data:
-		if 'creation' in account:
-			# Hack to check if account already contains a real Account doc
-			# or just the attibutes from country_wise_tax.json
-			continue
-
-		# tax_rate should survive the following lines because it might not be
-		# specified in an existing account or different rates might get booked
-		# onto the same account.
-		tax_rate = account.get('tax_rate')
-		doc = get_or_create_account(company, account)
-		account.update(doc.as_dict())
-		account['tax_rate'] = tax_rate
-
-	return account_data
-
-
-def get_or_create_account(company, account_data):
+def get_or_create_account(company_name, account):
 	"""
 	Check if account already exists. If not, create it.
 	Return a tax account or None.
 	"""
-	root_type = account_data.get('root_type', 'Liability')
-	account_name = account_data.get('account_name')
-	account_number = account_data.get('account_number')
+	default_root_type = 'Liability'
+	root_type = account.get('root_type', default_root_type)
 
 	existing_accounts = frappe.get_list('Account',
 		filters={
-			'company': company,
+			'company': company_name,
 			'root_type': root_type
 		},
 		or_filters={
-			'account_name': account_name,
-			'account_number': account_number
+			'account_name': account.get('account_name'),
+			'account_number': account.get('account_number')
 		}
 	)
 
 	if existing_accounts:
 		return frappe.get_doc('Account', existing_accounts[0].name)
 
-	tax_group = get_or_create_tax_account_group(company, root_type)
-	full_account_data = {
-		'doctype': 'Account',
-		'account_name': account_name,
-		'account_number': account_number,
-		'tax_rate': account_data.get('tax_rate'),
-		'company': company,
-		'parent_account': tax_group,
-		'is_group': 0,
-		'report_type': 'Balance Sheet',
-		'root_type': root_type,
-		'account_type': 'Tax'
-	}
-	return frappe.get_doc(full_account_data).insert(ignore_permissions=True, ignore_mandatory=True)
+	tax_group = get_or_create_tax_group(company_name, root_type)
+
+	account['doctype'] = 'Account'
+	account['company'] = company_name
+	account['parent_account'] = tax_group
+	account['report_type'] = 'Balance Sheet'
+	account['account_type'] = 'Tax'
+	account['root_type'] = root_type
+	account['is_group'] = 0
+
+	return frappe.get_doc(account).insert(ignore_permissions=True, ignore_mandatory=True)
 
 
-def get_or_create_tax_account_group(company, root_type):
-	tax_group = frappe.db.get_value('Account', {
+def get_or_create_tax_group(company_name, root_type):
+	# Look for a group account of type 'Tax'
+	tax_group_name = frappe.db.get_value('Account', {
 		'is_group': 1,
 		'root_type': root_type,
 		'account_type': 'Tax',
-		'company': company
+		'company': company_name
 	})
 
-	if tax_group:
-		return tax_group
+	if tax_group_name:
+		return tax_group_name
 
-	root = frappe.get_list('Account', {
+	# Look for a group account named 'Duties and Taxes' or 'Tax Assets'
+	account_name = _('Duties and Taxes') if root_type == 'Liability' else _('Tax Assets')
+	tax_group_name = frappe.db.get_value('Account', {
 		'is_group': 1,
 		'root_type': root_type,
-		'company': company,
+		'account_name': account_name,
+		'company': company_name
+	})
+
+	if tax_group_name:
+		return tax_group_name
+
+	# Create a new group account named 'Duties and Taxes' or 'Tax Assets' just
+	# below the root account
+	root_account = frappe.get_list('Account', {
+		'is_group': 1,
+		'root_type': root_type,
+		'company': company_name,
 		'report_type': 'Balance Sheet',
 		'parent_account': ('is', 'not set')
-	}, limit=1)[0].name
+	}, limit=1)[0]
 
-	doc = frappe.get_doc({
+	tax_group_account = frappe.get_doc({
 		'doctype': 'Account',
-		'company': company,
+		'company': company_name,
 		'is_group': 1,
 		'report_type': 'Balance Sheet',
 		'root_type': root_type,
 		'account_type': 'Tax',
-		'account_name': _('Duties and Taxes') if root_type == 'Liability' else _('Tax Assets'),
-		'parent_account': root
+		'account_name': account_name,
+		'parent_account': root_account.name
 	}).insert(ignore_permissions=True)
 
-	tax_group = doc.name
+	tax_group_name = tax_group_account.name
 
-	return tax_group
+	return tax_group_name