feat: BOM template (#21262)

Co-authored-by: Marica <maricadsouza221197@gmail.com>
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index d946591..9bba71d 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -188,12 +188,6 @@
 		# scan description only if items are less than 50000
 		description_cond = 'or tabItem.description LIKE %(txt)s'
 
-	extra_cond = " and tabItem.has_variants=0"
-	if (filters and isinstance(filters, dict)
-		and filters.get("doctype") == "BOM"):
-		extra_cond = ""
-		del filters["doctype"]
-
 	return frappe.db.sql("""select tabItem.name,
 		if(length(tabItem.item_name) > 40,
 			concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
@@ -204,10 +198,10 @@
 		from tabItem
 		where tabItem.docstatus < 2
 			and tabItem.disabled=0
+			and tabItem.has_variants=0
 			and (tabItem.end_of_life > %(today)s or ifnull(tabItem.end_of_life, '0000-00-00')='0000-00-00')
 			and ({scond} or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
 				{description_cond})
-			{extra_cond}
 			{fcond} {mcond}
 		order by
 			if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
@@ -218,7 +212,6 @@
 			key=searchfield,
 			columns=columns,
 			scond=searchfields,
-			extra_cond=extra_cond,
 			fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
 			mcond=get_match_cond(doctype).replace('%', '%%'),
 			description_cond = description_cond),
diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js
index 898955e..47b4207 100644
--- a/erpnext/manufacturing/doctype/bom/bom.js
+++ b/erpnext/manufacturing/doctype/bom/bom.js
@@ -29,10 +29,7 @@
 
 		frm.set_query("item", function() {
 			return {
-				query: "erpnext.controllers.queries.item_query",
-				filters: {
-					"doctype": "BOM"
-				}
+				query: "erpnext.manufacturing.doctype.bom.bom.item_query"
 			};
 		});
 
@@ -44,9 +41,12 @@
 			};
 		});
 
-		frm.set_query("item_code", "items", function() {
+		frm.set_query("item_code", "items", function(doc) {
 			return {
-				query: "erpnext.controllers.queries.item_query"
+				query: "erpnext.manufacturing.doctype.bom.bom.item_query",
+				filters: {
+					"item_code": doc.item
+				}
 			};
 		});
 
@@ -96,6 +96,12 @@
 				frm.trigger("make_work_order");
 			}, __("Create"));
 
+			if (frm.doc.has_variants) {
+				frm.add_custom_button(__("Variant BOM"), function() {
+					frm.trigger("make_variant_bom");
+				}, __("Create"));
+			}
+
 			if (frm.doc.inspection_required) {
 				frm.add_custom_button(__("Quality Inspection"), function() {
 					frm.trigger("make_quality_inspection");
@@ -124,7 +130,7 @@
 		}
 
 
-		if (frm.doc.__onload && frm.doc.__onload["has_variants"]) {
+		if (frm.doc.has_variants) {
 			frm.set_intro(__('This is a Template BOM and will be used to make the work order for {0} of the item {1}',
 				[
 					`<a class="variants-intro">variants</a>`,
@@ -138,9 +144,52 @@
 	},
 
 	make_work_order: function(frm) {
+		frm.events.setup_variant_prompt(frm, "Work Order", (frm, item, data, variant_items) => {
+			frappe.call({
+				method: "erpnext.manufacturing.doctype.work_order.work_order.make_work_order",
+				args: {
+					bom_no: frm.doc.name,
+					item: item,
+					qty: data.qty || 0.0,
+					project: frm.doc.project,
+					variant_items: variant_items
+				},
+				freeze: true,
+				callback: function(r) {
+					if(r.message) {
+						let doc = frappe.model.sync(r.message)[0];
+						frappe.set_route("Form", doc.doctype, doc.name);
+					}
+				}
+			});
+		});
+	},
+
+	make_variant_bom: function(frm) {
+		frm.events.setup_variant_prompt(frm, "Variant BOM", (frm, item, data, variant_items) => {
+			frappe.call({
+				method: "erpnext.manufacturing.doctype.bom.bom.make_variant_bom",
+				args: {
+					source_name: frm.doc.name,
+					bom_no: frm.doc.name,
+					item: item,
+					variant_items: variant_items
+				},
+				freeze: true,
+				callback: function(r) {
+					if(r.message) {
+						let doc = frappe.model.sync(r.message)[0];
+						frappe.set_route("Form", doc.doctype, doc.name);
+					}
+				}
+			});
+		}, true);
+	},
+
+	setup_variant_prompt: function(frm, title, callback, skip_qty_field) {
 		const fields = [];
 
-		if (frm.doc.__onload && frm.doc.__onload["has_variants"]) {
+		if (frm.doc.has_variants) {
 			fields.push({
 				fieldtype: 'Link',
 				label: __('Variant Item'),
@@ -158,34 +207,106 @@
 			});
 		}
 
-		fields.push({
-			fieldtype: 'Float',
-			label: __('Qty To Manufacture'),
-			fieldname: 'qty',
-			reqd: 1,
-			default: 1
+		if (!skip_qty_field) {
+			fields.push({
+				fieldtype: 'Float',
+				label: __('Qty To Manufacture'),
+				fieldname: 'qty',
+				reqd: 1,
+				default: 1
+			});
+		}
+
+		var has_template_rm = frm.doc.items.filter(d => d.has_variants === 1) || [];
+		if (has_template_rm && has_template_rm.length > 0) {
+			fields.push({
+				fieldname: "items",
+				fieldtype: "Table",
+				label: __("Raw Materials"),
+				fields: [
+					{
+						fieldname: "item_code",
+						options: "Item",
+						label: __("Template Item"),
+						fieldtype: "Link",
+						in_list_view: 1,
+						reqd: 1,
+					},
+					{
+						fieldname: "varint_item_code",
+						options: "Item",
+						label: __("Variant Item"),
+						fieldtype: "Link",
+						in_list_view: 1,
+						reqd: 1,
+						get_query: function(data) {
+							if (!data.item_code) {
+								frappe.throw(__("Select template item"));
+							}
+
+							return {
+								query: "erpnext.controllers.queries.item_query",
+								filters: {
+									"variant_of": data.item_code
+								}
+							};
+						}
+					},
+					{
+						fieldname: "qty",
+						label: __("Quantity"),
+						fieldtype: "Float",
+						in_list_view: 1,
+						reqd: 1,
+					},
+					{
+						fieldname: "source_warehouse",
+						label: __("Source Warehouse"),
+						fieldtype: "Link",
+						options: "Warehouse"
+					},
+					{
+						fieldname: "operation",
+						label: __("Operation"),
+						fieldtype: "Data",
+						hidden: 1,
+					}
+				],
+				in_place_edit: true,
+				data: [],
+				get_data: function () {
+					return [];
+				},
+			});
+		}
+
+		let dialog = frappe.prompt(fields, data => {
+			let item = data.item || frm.doc.item;
+			let variant_items = data.items || [];
+
+			variant_items.forEach(d => {
+				if (!d.varint_item_code) {
+					frappe.throw(__("Select variant item code for the template item {0}", [d.item_code]));
+				}
+			})
+
+			callback(frm, item, data, variant_items);
+
+		}, __(title), __("Create"));
+
+		has_template_rm.forEach(d => {
+			dialog.fields_dict.items.df.data.push({
+				"item_code": d.item_code,
+				"varint_item_code": "",
+				"qty": d.qty,
+				"source_warehouse": d.source_warehouse,
+				"operation": d.operation
+			});
 		});
 
-		frappe.prompt(fields, data => {
-			let item = data.item || frm.doc.item;
-
-			frappe.call({
-				method: "erpnext.manufacturing.doctype.work_order.work_order.make_work_order",
-				args: {
-					bom_no: frm.doc.name,
-					item: item,
-					qty: data.qty || 0.0,
-					project: frm.doc.project
-				},
-				freeze: true,
-				callback: function(r) {
-					if(r.message) {
-						var doc = frappe.model.sync(r.message)[0];
-						frappe.set_route("Form", doc.doctype, doc.name);
-					}
-				}
-			});
-		}, __("Enter Value"), __("Create"));
+		if (has_template_rm) {
+			dialog.fields_dict.items.grid.refresh();
+		}
 	},
 
 	make_quality_inspection: function(frm) {
diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json
index 4ce0ecf..f551b91 100644
--- a/erpnext/manufacturing/doctype/bom/bom.json
+++ b/erpnext/manufacturing/doctype/bom/bom.json
@@ -53,6 +53,7 @@
   "section_break_25",
   "description",
   "column_break_27",
+  "has_variants",
   "section_break0",
   "exploded_items",
   "website_section",
@@ -498,6 +499,17 @@
    "options": "Currency",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "default": "0",
+   "fetch_from": "item.has_variants",
+   "fieldname": "has_variants",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Has Variants",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "icon": "fa fa-sitemap",
@@ -505,7 +517,7 @@
  "image_field": "image",
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-05 14:29:32.634952",
+ "modified": "2020-05-21 12:29:32.634952",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "BOM",
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 6ac653e..1bdac57 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -3,13 +3,16 @@
 
 from __future__ import unicode_literals
 import frappe, erpnext
-from frappe.utils import cint, cstr, flt
+from frappe.utils import cint, cstr, flt, today
 from frappe import _
 from erpnext.setup.utils import get_exchange_rate
 from frappe.website.website_generator import WebsiteGenerator
 from erpnext.stock.get_item_details import get_conversion_factor
 from erpnext.stock.get_item_details import get_price_list_rate
 from frappe.core.doctype.version.version import get_diff
+from erpnext.controllers.queries import get_match_cond
+from erpnext.stock.doctype.item.item import get_item_details
+from frappe.model.mapper import get_mapped_doc
 
 import functools
 
@@ -59,11 +62,6 @@
 
 		self.name = name
 
-	def onload(self):
-		super(BOM, self).onload()
-		if self.get("item") and cint(frappe.db.get_value("Item", self.item, "has_variants")):
-			self.set_onload("has_variants", True)
-
 	def validate(self):
 		self.route = frappe.scrub(self.name).replace('_', '-')
 		self.clear_operations()
@@ -103,9 +101,7 @@
 		self.manage_default_bom()
 
 	def get_item_det(self, item_code):
-		item = frappe.db.sql("""select name, item_name, docstatus, description, image,
-			is_sub_contracted_item, stock_uom, default_bom, last_purchase_rate, include_item_in_manufacturing
-			from `tabItem` where name=%s""", item_code, as_dict = 1)
+		item = get_item_details(item_code)
 
 		if not item:
 			frappe.throw(_("Item: {0} does not exist in the system").format(item_code))
@@ -150,10 +146,10 @@
 
 		item = self.get_item_det(args['item_code'])
 
-		args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or ''
+		args['bom_no'] = args['bom_no'] or item and cstr(item['default_bom']) or ''
 		args['transfer_for_manufacture'] = (cstr(args.get('include_item_in_manufacturing', '')) or
-			item and item[0].include_item_in_manufacturing or 0)
-		args.update(item[0])
+			item and item.include_item_in_manufacturing or 0)
+		args.update(item)
 
 		rate = self.get_rm_rate(args)
 		ret_item = {
@@ -185,40 +181,14 @@
 			self.rm_cost_as_per = "Valuation Rate"
 
 		if arg.get('scrap_items'):
-			rate = self.get_valuation_rate(arg)
+			rate = get_valuation_rate(arg)
 		elif arg:
 			#Customer Provided parts will have zero rate
 			if not frappe.db.get_value('Item', arg["item_code"], 'is_customer_provided_item'):
 				if arg.get('bom_no') and self.set_rate_of_sub_assembly_item_based_on_bom:
 					rate = flt(self.get_bom_unitcost(arg['bom_no'])) * (arg.get("conversion_factor") or 1)
 				else:
-					if self.rm_cost_as_per == 'Valuation Rate':
-						rate = self.get_valuation_rate(arg) * (arg.get("conversion_factor") or 1)
-					elif self.rm_cost_as_per == 'Last Purchase Rate':
-						rate = flt(arg.get('last_purchase_rate') \
-							or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")) \
-								* (arg.get("conversion_factor") or 1)
-					elif self.rm_cost_as_per == "Price List":
-						if not self.buying_price_list:
-							frappe.throw(_("Please select Price List"))
-						args = frappe._dict({
-							"doctype": "BOM",
-							"price_list": self.buying_price_list,
-							"qty": arg.get("qty") or 1,
-							"uom": arg.get("uom") or arg.get("stock_uom"),
-							"stock_uom": arg.get("stock_uom"),
-							"transaction_type": "buying",
-							"company": self.company,
-							"currency": self.currency,
-							"conversion_rate": 1, # Passed conversion rate as 1 purposefully, as conversion rate is applied at the end of the function
-							"conversion_factor": arg.get("conversion_factor") or 1,
-							"plc_conversion_rate": 1,
-							"ignore_party": True
-						})
-						item_doc = frappe.get_doc("Item", arg.get("item_code"))
-						out = frappe._dict()
-						get_price_list_rate(args, item_doc, out)
-						rate = out.price_list_rate
+					rate = get_bom_item_rate(arg, self)
 
 					if not rate:
 						if self.rm_cost_as_per == "Price List":
@@ -286,31 +256,6 @@
 			where is_active = 1 and name = %s""", bom_no, as_dict=1)
 		return bom and bom[0]['unit_cost'] or 0
 
-	def get_valuation_rate(self, args):
-		""" Get weighted average of valuation rate from all warehouses """
-
-		total_qty, total_value, valuation_rate = 0.0, 0.0, 0.0
-		for d in frappe.db.sql("""select actual_qty, stock_value from `tabBin`
-			where item_code=%s""", args['item_code'], as_dict=1):
-				total_qty += flt(d.actual_qty)
-				total_value += flt(d.stock_value)
-
-		if total_qty:
-			valuation_rate =  total_value / total_qty
-
-		if valuation_rate <= 0:
-			last_valuation_rate = frappe.db.sql("""select valuation_rate
-				from `tabStock Ledger Entry`
-				where item_code = %s and valuation_rate > 0
-				order by posting_date desc, posting_time desc, creation desc limit 1""", args['item_code'])
-
-			valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
-
-		if not valuation_rate:
-			valuation_rate = frappe.db.get_value("Item", args['item_code'], "valuation_rate")
-
-		return flt(valuation_rate)
-
 	def manage_default_bom(self):
 		""" Uncheck others if current one is selected as default or
 			check the current one as default if it the only bom for the selected item,
@@ -624,6 +569,62 @@
 				if not d.batch_size or d.batch_size <= 0:
 					d.batch_size = 1
 
+def get_bom_item_rate(args, bom_doc):
+	if bom_doc.rm_cost_as_per == 'Valuation Rate':
+		rate = get_valuation_rate(args) * (args.get("conversion_factor") or 1)
+	elif bom_doc.rm_cost_as_per == 'Last Purchase Rate':
+		rate = ( flt(args.get('last_purchase_rate')) \
+			or frappe.db.get_value("Item", args['item_code'], "last_purchase_rate")) \
+				* (args.get("conversion_factor") or 1)
+	elif bom_doc.rm_cost_as_per == "Price List":
+		if not bom_doc.buying_price_list:
+			frappe.throw(_("Please select Price List"))
+		bom_args = frappe._dict({
+			"doctype": "BOM",
+			"price_list": bom_doc.buying_price_list,
+			"qty": args.get("qty") or 1,
+			"uom": args.get("uom") or args.get("stock_uom"),
+			"stock_uom": args.get("stock_uom"),
+			"transaction_type": "buying",
+			"company": bom_doc.company,
+			"currency": bom_doc.currency,
+			"conversion_rate": 1, # Passed conversion rate as 1 purposefully, as conversion rate is applied at the end of the function
+			"conversion_factor": args.get("conversion_factor") or 1,
+			"plc_conversion_rate": 1,
+			"ignore_party": True
+		})
+		item_doc = frappe.get_cached_doc("Item", args.get("item_code"))
+		out = frappe._dict()
+		get_price_list_rate(bom_args, item_doc, out)
+		rate = out.price_list_rate
+
+	return rate
+
+def get_valuation_rate(args):
+	""" Get weighted average of valuation rate from all warehouses """
+
+	total_qty, total_value, valuation_rate = 0.0, 0.0, 0.0
+	for d in frappe.db.sql("""select actual_qty, stock_value from `tabBin`
+		where item_code=%s""", args['item_code'], as_dict=1):
+			total_qty += flt(d.actual_qty)
+			total_value += flt(d.stock_value)
+
+	if total_qty:
+		valuation_rate =  total_value / total_qty
+
+	if valuation_rate <= 0:
+		last_valuation_rate = frappe.db.sql("""select valuation_rate
+			from `tabStock Ledger Entry`
+			where item_code = %s and valuation_rate > 0
+			order by posting_date desc, posting_time desc, creation desc limit 1""", args['item_code'])
+
+		valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
+
+	if not valuation_rate:
+		valuation_rate = frappe.db.get_value("Item", args['item_code'], "valuation_rate")
+
+	return flt(valuation_rate)
+
 def get_list_context(context):
 	context.title = _("Bill of Materials")
 	# context.introduction = _('Boms')
@@ -639,6 +640,8 @@
 				sum(bom_item.{qty_field}/ifnull(bom.quantity, 1)) * %(qty)s as qty,
 				item.image,
 				bom.project,
+				bom_item.rate,
+				bom_item.amount,
 				item.stock_uom,
 				item.item_group,
 				item.allow_alternative_item,
@@ -655,6 +658,7 @@
 			where
 				bom_item.docstatus < 2
 				and bom.name = %(bom)s
+				and ifnull(item.has_variants, 0) = 0
 				and item.is_stock_item in (1, {is_stock_item})
 				{where_conditions}
 				group by item_code, stock_uom
@@ -897,3 +901,84 @@
 					out.removed.append([df.fieldname, d.as_dict()])
 
 	return out
+
+def item_query(doctype, txt, searchfield, start, page_len, filters):
+	meta = frappe.get_meta("Item", cached=True)
+	searchfields = meta.get_search_fields()
+
+	order_by = "idx desc, name, item_name"
+
+	fields = ["name", "item_group", "item_name", "description"]
+	fields.extend([field for field in searchfields
+		if not field in ["name", "item_group", "description"]])
+
+	searchfields = searchfields + [field for field in [searchfield or "name", "item_code", "item_group", "item_name"]
+		if not field in searchfields]
+
+	query_filters = {
+		"disabled": 0,
+		"ifnull(end_of_life, '5050-50-50')": (">", today())
+	}
+
+	or_cond_filters = {}
+	if txt:
+		for s_field in searchfields:
+			or_cond_filters[s_field] = ("like", "%{0}%".format(txt))
+
+		barcodes = frappe.get_all("Item Barcode",
+			fields=["distinct parent as item_code"],
+			filters = {"barcode": ("like", "%{0}%".format(txt))})
+
+		barcodes = [d.item_code for d in barcodes]
+		if barcodes:
+			or_cond_filters["name"] = ("in", barcodes)
+
+	for cond in get_match_cond(doctype, as_condition=False):
+		for key, value in cond.items():
+			if key == doctype:
+				key = "name"
+
+			query_filters[key] = ("in", value)
+
+	if filters and filters.get("item_code"):
+		has_variants = frappe.get_cached_value("Item", filters.get("item_code"), "has_variants")
+		if not has_variants:
+			query_filters["has_variants"] = 0
+
+	return frappe.get_all("Item",
+		fields = fields, filters=query_filters,
+		or_filters = or_cond_filters, order_by=order_by,
+		limit_start=start, limit_page_length=page_len, as_list=1)
+
+@frappe.whitelist()
+def make_variant_bom(source_name, bom_no, item, variant_items, target_doc=None):
+	from erpnext.manufacturing.doctype.work_order.work_order import add_variant_item
+
+	def postprocess(source, doc):
+		doc.item = item
+		doc.quantity = 1
+
+		item_data = get_item_details(item)
+		doc.update({
+			"item_name": item_data.item_name,
+			"description": item_data.description,
+			"uom": item_data.stock_uom,
+			"allow_alternative_item": item_data.allow_alternative_item
+		})
+
+		add_variant_item(variant_items, doc, source_name)
+
+	doc = get_mapped_doc('BOM', source_name, {
+		'BOM': {
+			'doctype': 'BOM',
+			'validation': {
+				'docstatus': ['=', 1]
+			}
+		},
+		'BOM Item': {
+			'doctype': 'BOM Item',
+			'condition': lambda doc: doc.has_variants == 0
+		},
+	}, target_doc, postprocess)
+
+	return doc
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom/bom_list.js b/erpnext/manufacturing/doctype/bom/bom_list.js
index 2b06ed7..94cb466 100644
--- a/erpnext/manufacturing/doctype/bom/bom_list.js
+++ b/erpnext/manufacturing/doctype/bom/bom_list.js
@@ -1,7 +1,9 @@
 frappe.listview_settings['BOM'] = {
-	add_fields: ["is_active", "is_default", "total_cost"],
+	add_fields: ["is_active", "is_default", "total_cost", "has_variants"],
 	get_indicator: function(doc) {
-		if(doc.is_default) {
+		if(doc.is_active && doc.has_variants) {
+			return [__("Template"), "orange", "has_variants,=,Yes"];
+		} else if(doc.is_default) {
 			return [__("Default"), "green", "is_default,=,Yes"];
 		} else if(doc.is_active) {
 			return [__("Active"), "blue", "is_active,=,Yes"];
diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json
index f094be4..e34be61 100644
--- a/erpnext/manufacturing/doctype/bom_item/bom_item.json
+++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json
@@ -1,8 +1,10 @@
 {
+ "actions": [],
  "creation": "2013-02-22 01:27:49",
  "doctype": "DocType",
  "document_type": "Setup",
  "editable_grid": 1,
+ "engine": "InnoDB",
  "field_order": [
   "item_code",
   "item_name",
@@ -33,6 +35,7 @@
   "scrap",
   "qty_consumed_per_unit",
   "section_break_27",
+  "has_variants",
   "include_item_in_manufacturing",
   "original_item"
  ],
@@ -57,6 +60,7 @@
    "label": "Item Name"
   },
   {
+   "depends_on": "eval:parent.with_operations == 1",
    "fieldname": "operation",
    "fieldtype": "Link",
    "label": "Item operation",
@@ -258,11 +262,22 @@
    "label": "Original Item",
    "options": "Item",
    "read_only": 1
+  },
+  {
+   "default": "0",
+   "fetch_from": "item_code.has_variants",
+   "fieldname": "has_variants",
+   "fieldtype": "Check",
+   "label": "Has Variants",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
- "modified": "2019-11-22 11:38:52.087303",
+ "links": [],
+ "modified": "2020-04-09 14:30:26.535546",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "BOM Item",
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index c125571..a244f58 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -449,6 +449,32 @@
 				}
 			});
 		}
+	},
+
+	item_code: function(frm, cdt, cdn) {
+		let row = locals[cdt][cdn];
+
+		if (row.item_code) {
+			frappe.call({
+				method: "erpnext.stock.doctype.item.item.get_item_details",
+				args: {
+					item_code: row.item_code,
+					company: frm.doc.company
+				},
+				callback: function(r) {
+					if (r.message) {
+						frappe.model.set_value(cdt, cdn, {
+							"required_qty": 1,
+							"item_name": r.message.item_name,
+							"description": r.message.description,
+							"source_warehouse": r.message.default_warehouse,
+							"allow_alternative_item": r.message.allow_alternative_item,
+							"include_item_in_manufacturing": r.message.include_item_in_manufacturing
+						});
+					}
+				}
+			});
+		}
 	}
 });
 
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index c278955..e2233a3 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -8,9 +8,9 @@
 from frappe import _
 from frappe.utils import flt, get_datetime, getdate, date_diff, cint, nowdate, get_link_to_form, time_diff_in_hours
 from frappe.model.document import Document
-from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_bom_items_as_dict
+from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_bom_items_as_dict, get_bom_item_rate
 from dateutil.relativedelta import relativedelta
-from erpnext.stock.doctype.item.item import validate_end_of_life
+from erpnext.stock.doctype.item.item import validate_end_of_life, get_item_defaults
 from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError
 from erpnext.projects.doctype.timesheet.timesheet import OverlapError
 from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
@@ -541,6 +541,8 @@
 				# For instance in BOM Explosion Item child table, the items coming from sub assembly items
 				for item in sorted(item_dict.values(), key=lambda d: d['idx'] or 9999):
 					self.append('required_items', {
+						'rate': item.rate,
+						'amount': item.amount,
 						'operation': item.operation,
 						'item_code': item.item_code,
 						'item_name': item.item_name,
@@ -637,9 +639,10 @@
 		filters = filters, fields = ['operation'], as_list=1)
 
 @frappe.whitelist()
-def get_item_details(item, project = None):
+def get_item_details(item, project = None, skip_bom_info=False):
 	res = frappe.db.sql("""
-		select stock_uom, description
+		select stock_uom, description, item_name, allow_alternative_item,
+			include_item_in_manufacturing
 		from `tabItem`
 		where disabled=0
 			and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)
@@ -650,6 +653,7 @@
 		return {}
 
 	res = res[0]
+	if skip_bom_info: return res
 
 	filters = {"item": item, "is_default": 1}
 
@@ -681,7 +685,7 @@
 	return res
 
 @frappe.whitelist()
-def make_work_order(bom_no, item, qty=0, project=None):
+def make_work_order(bom_no, item, qty=0, project=None, variant_items=None):
 	if not frappe.has_permission("Work Order", "write"):
 		frappe.throw(_("Not permitted"), frappe.PermissionError)
 
@@ -696,8 +700,44 @@
 		wo_doc.qty = flt(qty)
 		wo_doc.get_items_and_operations_from_bom()
 
+	if variant_items:
+		add_variant_item(variant_items, wo_doc, bom_no, "required_items")
+
 	return wo_doc
 
+def add_variant_item(variant_items, wo_doc, bom_no, table_name="items"):
+	if isinstance(variant_items, string_types):
+		variant_items = json.loads(variant_items)
+
+	for item in variant_items:
+		args = frappe._dict({
+			"item_code": item.get("varint_item_code"),
+			"required_qty": item.get("qty"),
+			"qty": item.get("qty"), # for bom
+			"source_warehouse": item.get("source_warehouse"),
+			"operation": item.get("operation")
+		})
+
+		bom_doc = frappe.get_cached_doc("BOM", bom_no)
+		item_data = get_item_details(args.item_code, skip_bom_info=True)
+		args.update(item_data)
+
+		args["rate"] = get_bom_item_rate({
+			"item_code": args.get("item_code"),
+			"qty": args.get("required_qty"),
+			"uom": args.get("stock_uom"),
+			"stock_uom": args.get("stock_uom"),
+			"conversion_factor": 1
+		}, bom_doc)
+
+		if not args.source_warehouse:
+			args["source_warehouse"] = get_item_defaults(item.get("varint_item_code"),
+				wo_doc.company).default_warehouse
+
+		args["amount"] = flt(args.get("required_qty")) * flt(args.get("rate"))
+		args["uom"] = item_data.stock_uom
+		wo_doc.append(table_name, args)
+
 @frappe.whitelist()
 def check_if_scrap_warehouse_mandatory(bom_no):
 	res = {"set_scrap_wh_mandatory": False }
diff --git a/erpnext/manufacturing/doctype/work_order_item/work_order_item.json b/erpnext/manufacturing/doctype/work_order_item/work_order_item.json
index 4442162..3acf572 100644
--- a/erpnext/manufacturing/doctype/work_order_item/work_order_item.json
+++ b/erpnext/manufacturing/doctype/work_order_item/work_order_item.json
@@ -1,526 +1,144 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2016-04-18 07:38:26.314642", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2016-04-18 07:38:26.314642",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "operation",
+  "item_code",
+  "source_warehouse",
+  "column_break_3",
+  "item_name",
+  "description",
+  "allow_alternative_item",
+  "include_item_in_manufacturing",
+  "qty_section",
+  "required_qty",
+  "rate",
+  "amount",
+  "column_break_11",
+  "transferred_qty",
+  "consumed_qty",
+  "available_qty_at_source_warehouse",
+  "available_qty_at_wip_warehouse"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "operation", 
-   "fieldtype": "Link", 
-   "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": "Operation", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Operation", 
-   "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
-  }, 
+   "fieldname": "operation",
+   "fieldtype": "Link",
+   "label": "Operation",
+   "options": "Operation"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "item_code", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Item Code", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Item", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "item_code",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Item Code",
+   "options": "Item"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "source_warehouse", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 1, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Source Warehouse", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Warehouse", 
-   "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
-  }, 
+   "fieldname": "source_warehouse",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "in_list_view": 1,
+   "label": "Source Warehouse",
+   "options": "Warehouse"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_3", 
-   "fieldtype": "Column 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, 
-   "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
-  }, 
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "item_name", 
-   "fieldtype": "Data", 
-   "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": "Item Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "item_name",
+   "fieldtype": "Data",
+   "label": "Item Name",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "description", 
-   "fieldtype": "Text", 
-   "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": "Description", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "description",
+   "fieldtype": "Text",
+   "label": "Description",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "qty_section", 
-   "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": "Qty", 
-   "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
-  }, 
+   "fieldname": "qty_section",
+   "fieldtype": "Section Break",
+   "label": "Qty"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "required_qty", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Required Qty", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "required_qty",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Required Qty"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:!parent.skip_transfer", 
-   "fieldname": "transferred_qty", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Transferred Qty", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "depends_on": "eval:!parent.skip_transfer",
+   "fieldname": "transferred_qty",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Transferred Qty",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "allow_alternative_item", 
-   "fieldtype": "Check", 
-   "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": "Allow Alternative Item", 
-   "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
-  }, 
+   "default": "0",
+   "fieldname": "allow_alternative_item",
+   "fieldtype": "Check",
+   "label": "Allow Alternative Item"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "include_item_in_manufacturing", 
-   "fieldtype": "Check", 
-   "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": "Include Item In Manufacturing", 
-   "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
-  }, 
+   "default": "0",
+   "fieldname": "include_item_in_manufacturing",
+   "fieldtype": "Check",
+   "label": "Include Item In Manufacturing"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_11", 
-   "fieldtype": "Column 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, 
-   "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
-  }, 
+   "fieldname": "column_break_11",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:!parent.skip_transfer", 
-   "fieldname": "consumed_qty", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Consumed Qty", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "depends_on": "eval:!parent.skip_transfer",
+   "fieldname": "consumed_qty",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Consumed Qty",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "available_qty_at_source_warehouse", 
-   "fieldtype": "Float", 
-   "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": "Available Qty at Source Warehouse", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "available_qty_at_source_warehouse",
+   "fieldtype": "Float",
+   "label": "Available Qty at Source Warehouse",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "available_qty_at_wip_warehouse", 
-   "fieldtype": "Float", 
-   "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": "Available Qty at WIP Warehouse", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "available_qty_at_wip_warehouse",
+   "fieldtype": "Float",
+   "label": "Available Qty at WIP Warehouse",
+   "read_only": 1
+  },
+  {
+   "fieldname": "rate",
+   "fieldtype": "Currency",
+   "label": "Rate",
+   "read_only": 1
+  },
+  {
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "label": "Amount",
+   "read_only": 1
   }
- ], 
- "has_web_view": 0, 
- "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": "2018-11-20 19:04:38.508839", 
- "modified_by": "Administrator", 
- "module": "Manufacturing", 
- "name": "Work Order Item", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-13 18:46:32.966416",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Work Order Item",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 7a1c127..3436a5d 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -1144,6 +1144,17 @@
 	item.clear_cache()
 
 @frappe.whitelist()
+def get_item_details(item_code, company=None):
+	out = frappe._dict()
+	if company:
+		out = get_item_defaults(item_code, company) or frappe._dict()
+
+	doc = frappe.get_cached_doc("Item", item_code)
+	out.update(doc.as_dict())
+
+	return out
+
+@frappe.whitelist()
 def get_uom_conv_factor(uom, stock_uom):
 	uoms = [uom, stock_uom]
 	value = ""