Merge branch 'develop' of https://github.com/frappe/erpnext.git into Brand-Item-Defaults-V12

# Conflicts:
#	erpnext/stock/doctype/item/test_item.py
diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py
index acaa096..1c33750 100644
--- a/erpnext/accounts/doctype/account/test_account.py
+++ b/erpnext/accounts/doctype/account/test_account.py
@@ -129,6 +129,8 @@
 		["_Test Write Off", "Indirect Expenses", 0, None, None],
 		["_Test Exchange Gain/Loss", "Indirect Expenses", 0, None, None],
 
+		["_Test Account Sales", "Direct Income", 0, None, None],
+
 		# related to Account Inventory Integration
 		["_Test Account Stock In Hand", "Current Assets", 0, None, None],
 		
diff --git a/erpnext/setup/doctype/brand/brand.json b/erpnext/setup/doctype/brand/brand.json
index 920c9cf..a8f0674 100644
--- a/erpnext/setup/doctype/brand/brand.json
+++ b/erpnext/setup/doctype/brand/brand.json
@@ -15,7 +15,7 @@
  "fields": [
   {
    "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
+   "allow_in_quick_entry": 1, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -79,6 +79,71 @@
    "translatable": 0, 
    "unique": 0, 
    "width": "300px"
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "defaults", 
+   "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Defaults", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "brand_defaults", 
+   "fieldtype": "Table", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Brand Defaults", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Item Default", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
   }
  ], 
  "has_web_view": 0, 
@@ -92,7 +157,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2019-01-07 16:52:05.945810", 
+ "modified": "2018-10-23 23:18:06.067612", 
  "modified_by": "Administrator", 
  "module": "Setup", 
  "name": "Brand", 
@@ -202,4 +267,4 @@
  "track_changes": 0, 
  "track_seen": 0, 
  "track_views": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/setup/doctype/brand/brand.py b/erpnext/setup/doctype/brand/brand.py
index d90aa5a..12839d1 100644
--- a/erpnext/setup/doctype/brand/brand.py
+++ b/erpnext/setup/doctype/brand/brand.py
@@ -3,8 +3,22 @@
 
 from __future__ import unicode_literals
 import frappe
+import copy
 
 from frappe.model.document import Document
 
 class Brand(Document):
-	pass
\ No newline at end of file
+	pass
+
+def get_brand_defaults(item, company):
+	item = frappe.get_cached_doc("Item", item)
+	if item.brand:
+		brand = frappe.get_cached_doc("Brand", item.brand)
+
+		for d in brand.brand_defaults or []:
+			if d.company == company:
+				row = copy.deepcopy(d.as_dict())
+				row.pop("name")
+				return row
+
+	return frappe._dict()
\ No newline at end of file
diff --git a/erpnext/setup/doctype/brand/test_records.json b/erpnext/setup/doctype/brand/test_records.json
index d2a4ad4..17b5a6b 100644
--- a/erpnext/setup/doctype/brand/test_records.json
+++ b/erpnext/setup/doctype/brand/test_records.json
@@ -2,5 +2,16 @@
  {
   "brand": "_Test Brand", 
   "doctype": "Brand"
+ },
+ {
+  "brand": "_Test Brand With Item Defaults",
+  "doctype": "Brand",
+  "brand_defaults": [{
+    "company": "_Test Company",
+    "expense_account": "_Test Account Cost for Goods Sold - _TC",
+    "income_account": "_Test Account Sales - _TC",
+    "buying_cost_center": "_Test Cost Center - _TC",
+    "selling_cost_center": "_Test Cost Center - _TC"
+  }]
  }
 ]
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 5669552..c6ec451 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -86,7 +86,7 @@
 	def after_insert(self):
 		'''set opening stock and item price'''
 		if self.standard_rate:
-			for default in self.item_defaults:
+			for default in self.item_defaults or [frappe._dict()]:
 				self.add_price(default.default_price_list)
 
 		if self.opening_stock:
@@ -127,7 +127,6 @@
 		self.validate_retain_sample()
 		self.validate_uom_conversion_factor()
 		self.validate_item_defaults()
-		self.update_defaults_from_item_group()
 		self.validate_customer_provided_part()
 
 		if not self.get("__islocal"):
@@ -185,7 +184,7 @@
 		from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
 
 		# default warehouse, or Stores
-		for default in self.item_defaults:
+		for default in self.item_defaults or [frappe._dict({'company': frappe.defaults.get_defaults().company})]:
 			default_warehouse = (default.default_warehouse
 					or frappe.db.get_single_value('Stock Settings', 'default_warehouse')
 					or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')}))
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index de702ff..1a94d5a 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -164,6 +164,61 @@
 			self.assertEqual(details.item_tax_template, data['item_tax_template'])
 			self.assertEqual(json.loads(details.item_tax_rate), expected_item_tax_map[details.item_tax_template])
 
+	def test_item_defaults(self):
+		frappe.delete_doc_if_exists("Item", "Test Item With Defaults", force=1)
+		make_item("Test Item With Defaults", {
+			"item_group": "_Test Item Group",
+			"brand": "_Test Brand With Item Defaults",
+			"item_defaults": [{
+				"company": "_Test Company",
+				"default_warehouse": "_Test Warehouse 2 - _TC",  # no override
+				"expense_account": "_Test Account Stock Expenses - _TC",  # override brand default
+				"buying_cost_center": "_Test Write Off Cost Center - _TC",  # override item group default
+			}]
+		})
+
+		sales_item_check = {
+			"item_code": "Test Item With Defaults",
+			"warehouse": "_Test Warehouse 2 - _TC",  # from item
+			"income_account": "_Test Account Sales - _TC",  # from brand
+			"expense_account": "_Test Account Stock Expenses - _TC",  # from item
+			"cost_center": "_Test Cost Center 2 - _TC",  # from item group
+		}
+		sales_item_details = get_item_details({
+			"item_code": "Test Item With Defaults",
+			"company": "_Test Company",
+			"price_list": "_Test Price List",
+			"currency": "_Test Currency",
+			"doctype": "Sales Invoice",
+			"conversion_rate": 1,
+			"price_list_currency": "_Test Currency",
+			"plc_conversion_rate": 1,
+			"customer": "_Test Customer",
+		})
+		for key, value in iteritems(sales_item_check):
+			self.assertEqual(value, sales_item_details.get(key))
+
+		purchase_item_check = {
+			"item_code": "Test Item With Defaults",
+			"warehouse": "_Test Warehouse 2 - _TC",  # from item
+			"expense_account": "_Test Account Stock Expenses - _TC",  # from item
+			"income_account": "_Test Account Sales - _TC",  # from brand
+			"cost_center": "_Test Write Off Cost Center - _TC"  # from item
+		}
+		purchase_item_details = get_item_details({
+			"item_code": "Test Item With Defaults",
+			"company": "_Test Company",
+			"price_list": "_Test Price List",
+			"currency": "_Test Currency",
+			"doctype": "Purchase Invoice",
+			"conversion_rate": 1,
+			"price_list_currency": "_Test Currency",
+			"plc_conversion_rate": 1,
+			"supplier": "_Test Supplier",
+		})
+		for key, value in iteritems(purchase_item_check):
+			self.assertEqual(value, purchase_item_details.get(key))
+
 	def test_item_attribute_change_after_variant(self):
 		frappe.delete_doc_if_exists("Item", "_Test Variant Item-L", force=1)
 
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 3012d0b..4a4fee7 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -10,6 +10,7 @@
 from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError, get_valuation_rate
 from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor, get_reserved_qty_for_so
 from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
+from erpnext.setup.doctype.brand.brand import get_brand_defaults
 from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_batch_qty
 from erpnext.stock.doctype.item.item import get_item_defaults
 from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, add_additional_cost
@@ -636,6 +637,7 @@
 
 		item = item[0]
 		item_group_defaults = get_item_group_defaults(item.name, self.company)
+		brand_defaults = get_brand_defaults(item.name, self.company)
 
 		ret = frappe._dict({
 			'uom'			      	: item.stock_uom,
@@ -644,7 +646,7 @@
 			'image'				: item.image,
 			'item_name' 		  	: item.item_name,
 			'expense_account'		: args.get("expense_account"),
-			'cost_center'			: get_default_cost_center(args, item, item_group_defaults),
+			'cost_center'			: get_default_cost_center(args, item, item_group_defaults, brand_defaults),
 			'qty'				: args.get("qty"),
 			'transfer_qty'			: args.get('qty'),
 			'conversion_factor'		: 1,
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index a0f3ac2..1f1b389 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -13,6 +13,7 @@
 from erpnext import get_company_currency
 from erpnext.stock.doctype.item.item import get_item_defaults, get_uom_conv_factor
 from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
+from erpnext.setup.doctype.brand.brand import get_brand_defaults
 
 from six import string_types, iteritems
 
@@ -225,9 +226,10 @@
 
 	item_defaults = get_item_defaults(item.name, args.company)
 	item_group_defaults = get_item_group_defaults(item.name, args.company)
+	brand_defaults = get_brand_defaults(item.name, args.company)
 
 	warehouse = args.get("set_warehouse") or user_default_warehouse or item_defaults.get("default_warehouse") or\
-		item_group_defaults.get("default_warehouse") or args.warehouse
+		item_group_defaults.get("default_warehouse") or brand_defaults.get("default_warehouse") or args.warehouse
 
 	if args.get('doctype') == "Material Request" and not args.get('material_request_type'):
 		args['material_request_type'] = frappe.db.get_value('Material Request',
@@ -249,9 +251,9 @@
 		"description": cstr(item.description).strip(),
 		"image": cstr(item.image).strip(),
 		"warehouse": warehouse,
-		"income_account": get_default_income_account(args, item_defaults, item_group_defaults),
-		"expense_account": get_default_expense_account(args, item_defaults, item_group_defaults),
-		"cost_center": get_default_cost_center(args, item_defaults, item_group_defaults),
+		"income_account": get_default_income_account(args, item_defaults, item_group_defaults, brand_defaults),
+		"expense_account": get_default_expense_account(args, item_defaults, item_group_defaults, brand_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,
 		"batch_no": None,
@@ -268,7 +270,7 @@
 		"net_rate": 0.0,
 		"net_amount": 0.0,
 		"discount_percentage": 0.0,
-		"supplier": get_default_supplier(args, item_defaults, item_group_defaults),
+		"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,
 		"is_fixed_asset": item.is_fixed_asset,
@@ -390,14 +392,16 @@
 
 	return deferred_detail
 
-def get_default_income_account(args, item, item_group):
+def get_default_income_account(args, item, item_group, brand):
 	return (item.get("income_account")
 		or item_group.get("income_account")
+		or brand.get("income_account")
 		or args.income_account)
 
-def get_default_expense_account(args, item, item_group):
+def get_default_expense_account(args, item, item_group, brand):
 	return (item.get("expense_account")
 		or item_group.get("expense_account")
+		or brand.get("expense_account")
 		or args.expense_account)
 
 def get_default_deferred_account(args, item, fieldname=None):
@@ -408,22 +412,23 @@
 	else:
 		return None
 
-def get_default_cost_center(args, item, item_group):
+def get_default_cost_center(args, item, item_group, brand):
 	cost_center = None
 	if args.get('project'):
 		cost_center = frappe.db.get_value("Project", args.get("project"), "cost_center", cache=True)
 
 	if not cost_center:
 		if args.get('customer'):
-			cost_center = item.get('selling_cost_center') or item_group.get('selling_cost_center')
+			cost_center = item.get('selling_cost_center') or item_group.get('selling_cost_center') or brand.get('selling_cost_center')
 		else:
-			cost_center = item.get('buying_cost_center') or item_group.get('buying_cost_center')
+			cost_center = item.get('buying_cost_center') or item_group.get('buying_cost_center') or brand.get('buying_cost_center')
 
 	return cost_center or args.get("cost_center")
 
-def get_default_supplier(args, item, item_group):
+def get_default_supplier(args, item, item_group, brand):
 	return (item.get("default_supplier")
-		or item_group.get("default_supplier"))
+		or item_group.get("default_supplier")
+		or brand.get("default_supplier"))
 
 def get_price_list_rate(args, item_doc, out):
 	meta = frappe.get_meta(args.parenttype or args.doctype)
@@ -898,10 +903,11 @@
 def get_valuation_rate(item_code, company, warehouse=None):
 	item = get_item_defaults(item_code, company)
 	item_group = get_item_group_defaults(item_code, company)
+	brand = get_brand_defaults(item_code, company)
 	# item = frappe.get_doc("Item", item_code)
 	if item.get("is_stock_item"):
 		if not warehouse:
-			warehouse = item.get("default_warehouse") or item_group.get("default_warehouse")
+			warehouse = item.get("default_warehouse") or item_group.get("default_warehouse") or brand.get("default_warehouse")
 
 		return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
 			["valuation_rate"], as_dict=True) or {"valuation_rate": 0}