[item-variants] get table values from template if not set in variant #2224
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index e274690..b05ce25 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -12,6 +12,9 @@
 	cur_frm.set_intro();
 	if (cur_frm.doc.has_variants) {
 		cur_frm.set_intro(__("This Item is a Template and cannot be used in transactions. Item attributes will be copied over into the variants unless 'No Copy' is set"));
+		cur_frm.add_custom_button(__("Show Variants"), function() {
+			frappe.set_route("List", "Item", {"variant_of": cur_frm.doc.name});
+		}, "icon-list", "btn-default");
 	}
 	if (cur_frm.doc.variant_of) {
 		cur_frm.set_intro(__("This Item is a Variant of {0} (Template). Attributes will be copied over from the template unless 'No Copy' is set", [cur_frm.doc.variant_of]));
@@ -33,7 +36,7 @@
 
 	if (!doc.__islocal && doc.show_in_website) {
 		cur_frm.set_intro(__("Published on website at: {0}",
-			[repl('<a href="/%(website_route)s" target="_blank">/%(website_route)s</a>', doc.__onload)]));
+			[repl('<a href="/%(website_route)s" target="_blank">/%(website_route)s</a>', doc.__onload)]), true);
 	}
 
 	erpnext.item.toggle_reqd(cur_frm);
@@ -78,7 +81,7 @@
 cur_frm.cscript.edit_prices_button = function() {
 	cur_frm.add_custom_button(__("Add / Edit Prices"), function() {
 		frappe.set_route("Report", "Item Price", {"item_code": cur_frm.doc.name});
-	}, "icon-money");
+	}, "icon-money", "btn-default");
 }
 
 cur_frm.cscript.item_code = function(doc) {
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index c1a1fe9..12ff900 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -390,6 +390,7 @@
    "read_only": 0
   }, 
   {
+   "description": "Will also apply for variants unless overrridden", 
    "fieldname": "item_reorder", 
    "fieldtype": "Table", 
    "label": "Warehouse-wise Item Reorder", 
@@ -487,6 +488,7 @@
   }, 
   {
    "depends_on": "eval:doc.is_purchase_item==\"Yes\"", 
+   "description": "Will also apply for variants", 
    "fieldname": "uom_conversion_details", 
    "fieldtype": "Table", 
    "label": "UOM Conversion Details", 
@@ -619,6 +621,7 @@
    "read_only": 0
   }, 
   {
+   "description": "Will also apply for variants", 
    "fieldname": "item_tax", 
    "fieldtype": "Table", 
    "label": "Item Tax1", 
@@ -652,7 +655,7 @@
   }, 
   {
    "depends_on": "eval:doc.inspection_required==\"Yes\"", 
-   "description": "Quality Inspection Parameters", 
+   "description": "Will also apply to variants", 
    "fieldname": "item_specification_details", 
    "fieldtype": "Table", 
    "label": "Item Quality Inspection Parameter", 
@@ -862,7 +865,7 @@
  "icon": "icon-tag", 
  "idx": 1, 
  "max_attachments": 1, 
- "modified": "2014-10-03 04:58:39.278047", 
+ "modified": "2014-10-07 05:25:19.921651", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Item", 
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index c7d9375..cf46372 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -42,6 +42,8 @@
 		if self.image and not self.website_image:
 			self.website_image = self.image
 
+		if self.variant_of:
+			self.copy_attributes_to_variant(frappe.get_doc("Item", self.variant_of), self)
 		self.check_warehouse_is_set_for_stock_item()
 		self.check_stock_uom_with_bin()
 		self.add_default_uom_in_conversion_factor_table()
@@ -211,32 +213,54 @@
 
 	def make_variant(self, item_code):
 		item = frappe.new_doc("Item")
-		self.copy_attributes_to_variant(item, item_code, insert=True)
 		item.item_code = item_code
+		self.copy_attributes_to_variant(self, item, insert=True)
 		item.insert()
 
 	def update_variant(self, item_code):
 		item = frappe.get_doc("Item", item_code)
-		self.copy_attributes_to_variant(item, item_code)
+		item.item_code = item_code
+		self.copy_attributes_to_variant(self, item)
 		item.save()
 
-	def copy_attributes_to_variant(self, variant, item_code, insert=False):
+	def copy_attributes_to_variant(self, template, variant, insert=False):
 		from frappe.model import no_value_fields
 		for field in self.meta.fields:
-			if field.fieldtype not in no_value_fields and (insert or not field.no_copy):
-				if variant.get(field.fieldname) != self.get(field.fieldname):
-					variant.set(field.fieldname, self.get(field.fieldname))
+			if field.fieldtype not in no_value_fields and (insert or not field.no_copy)\
+				and field.fieldname != "item_code":
+				if variant.get(field.fieldname) != template.get(field.fieldname):
+					variant.set(field.fieldname, template.get(field.fieldname))
 					variant.__dirty = True
 
 		variant.description += "\n"
-		for attr in self.variant_attributes[item_code]:
+
+		if not getattr(template, "variant_attributes", None):
+			template.get_variant_item_codes()
+
+		for attr in template.variant_attributes[variant.item_code]:
 			variant.description += "\n" + attr[0] + ": " + attr[1]
 			if variant.description_html:
 				variant.description_html += "<div style='margin-top: 4px; font-size: 80%'>" + attr[0] + ": " + attr[1] + "</div>"
-		variant.variant_of = self.name
+		variant.variant_of = template.name
 		variant.has_variants = 0
 		variant.show_in_website = 0
 
+	def update_template_tables(self):
+		template = frappe.get_doc("Item", self.variant_of)
+
+		# add item taxes from template
+		for d in template.get("item_tax"):
+			self.append("item_tax", {"tax_type": d.tax_type, "tax_rate": d.tax_rate})
+
+		# copy re-order table if empty
+		if not self.get("item_reorder"):
+			for d in template.get("item_reorder"):
+				n = {}
+				for k in ("warehouse", "warehouse_reorder_level",
+					"warehouse_reorder_qty", "material_request_type"):
+					n[k] = d.get(k)
+				self.append("item_reorder", n)
+
 	def validate_conversion_factor(self):
 		check_list = []
 		for d in self.get('uom_conversion_details'):
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index 2807ca8..803913f 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -34,7 +34,7 @@
 		se.purpose = "Material Receipt"
 		se.append("mtn_details", {
 			"item_code": item.name,
-			"t_warehouse": "Stores - WP",
+			"t_warehouse": "Stores - _TC",
 			"qty": 1,
 			"incoming_rate": 1
 		})
diff --git a/erpnext/stock/doctype/item/test_records.json b/erpnext/stock/doctype/item/test_records.json
index 01c4e4f..531f1a7 100644
--- a/erpnext/stock/doctype/item/test_records.json
+++ b/erpnext/stock/doctype/item/test_records.json
@@ -275,6 +275,14 @@
 	  {"item_attribute": "Test Size", "item_attribute_value": "Small"},
 	  {"item_attribute": "Test Size", "item_attribute_value": "Medium"},
 	  {"item_attribute": "Test Size", "item_attribute_value": "Large"}
+  ],
+  "item_reorder": [
+      {
+       "material_request_type": "Purchase",
+       "warehouse": "_Test Warehouse - _TC",
+       "warehouse_reorder_level": 20,
+       "warehouse_reorder_qty": 20
+      }
   ]
  }
 
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 028fff9..fb4493a 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -11,7 +11,7 @@
 from erpnext.stock.utils import get_incoming_rate
 from erpnext.stock.stock_ledger import get_previous_sle
 from erpnext.controllers.queries import get_match_cond
-from erpnext.stock.get_item_details import get_available_qty, get_default_cost_center
+from erpnext.stock.get_item_details import get_available_qty, get_default_cost_center, get_conversion_factor
 from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
 
 class NotUpdateStockError(frappe.ValidationError): pass
@@ -436,8 +436,7 @@
 		return ret
 
 	def get_uom_details(self, args):
-		conversion_factor = frappe.db.get_value("UOM Conversion Detail", {"parent": args.get("item_code"),
-			"uom": args.get("uom")}, "conversion_factor")
+		conversion_factor = get_conversion_factor(args.get("item_code"), args.get("uom")).get("conversion_factor")
 
 		if not conversion_factor:
 			frappe.msgprint(_("UOM coversion factor required for UOM: {0} in Item: {1}")
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 03eb9fe..6d8dc8b 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -37,8 +37,52 @@
 		mr_name = frappe.db.sql("""select parent from `tabMaterial Request Item`
 			where item_code='_Test Item'""")
 
+		frappe.db.set_value("Stock Settings", None, "auto_indent", 0)
+
 		self.assertTrue(mr_name)
 
+	def test_auto_material_request_for_variant(self):
+		item_code = "_Test Variant Item-S"
+		item = frappe.get_doc("Item", item_code)
+		template = frappe.get_doc("Item", item.variant_of)
+
+		warehouse = "_Test Warehouse - _TC"
+
+		# stock entry reqd for auto-reorder
+		se = frappe.new_doc("Stock Entry")
+		se.purpose = "Material Receipt"
+		se.company = "_Test Company"
+		se.append("mtn_details", {
+			"item_code": item_code,
+			"t_warehouse": "_Test Warehouse - _TC",
+			"qty": 1,
+			"incoming_rate": 1
+		})
+		se.insert()
+		se.submit()
+
+		frappe.db.set_value("Stock Settings", None, "auto_indent", 1)
+		projected_qty = frappe.db.get_value("Bin", {"item_code": item_code,
+			"warehouse": warehouse}, "projected_qty") or 0
+
+
+		# update re-level qty so that it is more than projected_qty
+		if projected_qty > template.item_reorder[0].warehouse_reorder_level:
+			template.item_reorder[0].warehouse_reorder_level += projected_qty
+			template.save()
+
+		from erpnext.stock.utils import reorder_item
+		mr_list = reorder_item()
+
+		frappe.db.set_value("Stock Settings", None, "auto_indent", 0)
+
+		items = []
+		for mr in mr_list:
+			for d in mr.indent_details:
+				items.append(d.item_code)
+
+		self.assertTrue(item_code in items)
+
 	def test_material_receipt_gl_entry(self):
 		self._clear_stock_account_balance()
 		set_perpetual_inventory()
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index fd728e6..2273018 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -133,13 +133,15 @@
 	if not item:
 		item = frappe.get_doc("Item", args.get("item_code"))
 
+	if item.variant_of:
+		item.update_template_tables()
+
 	from frappe.defaults import get_user_default_as_list
 	user_default_warehouse_list = get_user_default_as_list('warehouse')
 	user_default_warehouse = user_default_warehouse_list[0] \
 		if len(user_default_warehouse_list)==1 else ""
 
 	out = frappe._dict({
-
 		"item_code": item.name,
 		"item_name": item.item_name,
 		"description": item.description_html or item.description,
@@ -291,8 +293,13 @@
 
 @frappe.whitelist()
 def get_conversion_factor(item_code, uom):
+	variant_of = frappe.db.get_value("Item", item_code, "variant_of")
+	filters = {"parent": item_code, "uom": uom}
+	if variant_of:
+		filters = {"parent": ("in", (item_code, variant_of))}
+
 	return {"conversion_factor": frappe.db.get_value("UOM Conversion Detail",
-		{"parent": item_code, "uom": uom}, "conversion_factor")}
+		filters, "conversion_factor")}
 
 @frappe.whitelist()
 def get_projected_qty(item_code, warehouse):
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 2b4e368..0a4be40 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -192,14 +192,15 @@
 		frappe.local.auto_indent = cint(frappe.db.get_value('Stock Settings', None, 'auto_indent'))
 
 	if frappe.local.auto_indent:
-		_reorder_item()
+		return _reorder_item()
 
 def _reorder_item():
-	# {"Purchase": {"Company": [{"item_code": "", "warehouse": "", "reorder_qty": 0.0}]}, "Transfer": {...}}
 	material_requests = {"Purchase": {}, "Transfer": {}}
 
 	item_warehouse_projected_qty = get_item_warehouse_projected_qty()
-	warehouse_company = frappe._dict(frappe.db.sql("""select name, company from `tabWarehouse`"""))
+
+	warehouse_company = frappe._dict(frappe.db.sql("""select name, company
+		from `tabWarehouse`"""))
 	default_company = (frappe.defaults.get_defaults().get("company") or
 		frappe.db.sql("""select name from tabCompany limit 1""")[0][0])
 
@@ -227,6 +228,10 @@
 
 	for item_code in item_warehouse_projected_qty:
 		item = frappe.get_doc("Item", item_code)
+
+		if item.variant_of and not item.get("item_reorder"):
+			item.update_template_tables()
+
 		if item.get("item_reorder"):
 			for d in item.get("item_reorder"):
 				add_to_material_request(item_code, d.warehouse, d.warehouse_reorder_level,
@@ -237,7 +242,7 @@
 			add_to_material_request(item_code, item.default_warehouse, item.re_order_level, item.re_order_qty, "Purchase")
 
 	if material_requests:
-		create_material_request(material_requests)
+		return create_material_request(material_requests)
 
 def get_item_warehouse_projected_qty():
 	item_warehouse_projected_qty = {}
@@ -326,6 +331,8 @@
 	if exceptions_list:
 		notify_errors(exceptions_list)
 
+	return mr_list
+
 def send_email_notification(mr_list):
 	""" Notify user about auto creation of indent"""