[bom] set fetched values at server side
diff --git a/manufacturing/doctype/bom/bom.js b/manufacturing/doctype/bom/bom.js
index 4e8fbc9..f0c15fa 100644
--- a/manufacturing/doctype/bom/bom.js
+++ b/manufacturing/doctype/bom/bom.js
@@ -59,27 +59,22 @@
 	set_operation_no(doc);
 }
 
-cur_frm.cscript.item = function(doc, dt, dn) {
-	if (doc.item) {
-		get_server_fields('get_item_details', doc.item, '', doc, dt, dn, 1);
-	}
-}
+cur_frm.add_fetch("item", "description", "description");
+cur_frm.add_fetch("item", "stock_uom", "uom");
 
 cur_frm.cscript.workstation = function(doc,dt,dn) {
 	var d = locals[dt][dn];
-	if (d.workstation) {
-		var callback = function(r, rt) {
-			calculate_op_cost(doc, dt, dn);
-			calculate_total(doc);
-		}
-		get_server_fields('get_workstation_details', d.workstation, 
-			'bom_operations', doc, dt, dn, 1, callback);
-	}
+	wn.model.with_doc("Workstation", d.workstation, function(i, v) {
+		d.hour_rate = v.hour_rate;
+		refresh_field("hour_rate");
+		calculate_op_cost(doc);
+		calculate_total(doc);
+	});
 }
 
 
 cur_frm.cscript.hour_rate = function(doc, dt, dn) {
-	calculate_op_cost(doc, dt, dn);
+	calculate_op_cost(doc);
 	calculate_total(doc);
 }
 
@@ -114,7 +109,7 @@
 				$.extend(d, r.message);
 				refresh_field("bom_materials");
 				doc = locals[doc.doctype][doc.name];
-				calculate_rm_cost(doc, cdt, cdn);
+				calculate_rm_cost(doc);
 				calculate_total(doc);
 			},
 			freeze: true
@@ -124,7 +119,7 @@
 
 
 cur_frm.cscript.qty = function(doc, cdt, cdn) {
-	calculate_rm_cost(doc, cdt, cdn);
+	calculate_rm_cost(doc);
 	calculate_total(doc);
 }
 
@@ -134,12 +129,12 @@
 		msgprint("You can not change rate if BOM mentioned agianst any item");
 		get_bom_material_detail(doc, cdt, cdn);
 	} else {
-		calculate_rm_cost(doc, cdt, cdn);
+		calculate_rm_cost(doc);
 		calculate_total(doc);
 	}
 }
 
-var calculate_op_cost = function(doc, dt, dn) {	
+var calculate_op_cost = function(doc) {	
 	var op = getchildren('BOM Operation', doc.name, 'bom_operations');
 	total_op_cost = 0;
 	for(var i=0;i<op.length;i++) {
@@ -151,7 +146,7 @@
 	refresh_field('operating_cost');
 }
 
-var calculate_rm_cost = function(doc, dt, dn) {	
+var calculate_rm_cost = function(doc) {	
 	var rm = getchildren('BOM Item', doc.name, 'bom_materials');
 	total_rm_cost = 0;
 	for(var i=0;i<rm.length;i++) {
@@ -201,7 +196,7 @@
 }
 
 cur_frm.cscript.validate = function(doc, dt, dn) {
-	calculate_op_cost(doc, dt, dn);
-	calculate_rm_cost(doc, dt, dn);
+	calculate_op_cost(doc);
+	calculate_rm_cost(doc);
 	calculate_total(doc);
 }
diff --git a/manufacturing/doctype/bom/bom.py b/manufacturing/doctype/bom/bom.py
index b4eeaff..1408a3a 100644
--- a/manufacturing/doctype/bom/bom.py
+++ b/manufacturing/doctype/bom/bom.py
@@ -44,10 +44,11 @@
 		self.validate_main_item()
 		self.validate_operations()
 		self.validate_materials()
+		self.set_bom_material_details()
+		self.calculate_cost()
 		
 	def on_update(self):
 		self.check_recursion()
-		self.calculate_cost()
 		self.update_exploded_items()
 		self.doc.save()
 	
@@ -73,15 +74,7 @@
 			from `tabItem` where name=%s""", item_code, as_dict = 1)
 
 		return item
-
-	def get_item_details(self, item_code):
-		res = webnotes.conn.sql("""select description, stock_uom as uom
-			from `tabItem` where name=%s""", item_code, as_dict = 1)
-		return res and res[0] or {}
-
-	def get_workstation_details(self,workstation):
-		return {'hour_rate': webnotes.conn.get_value("Workstation", workstation, "hour_rate")}
-
+		
 	def validate_rm_item(self, item):
 		if item[0]['name'] == self.doc.item:
 			msgprint("Item_code: %s in materials tab cannot be same as FG Item", 
@@ -89,25 +82,35 @@
 		
 		if not item or item[0]['docstatus'] == 2:
 			msgprint("Item %s does not exist in system" % item[0]['item_code'], raise_exception = 1)
-
-	def get_bom_material_detail(self):
+			
+	def set_bom_material_details(self):
+		for item in self.doclist.get({"parentfield": "bom_materials"}):			
+			ret = self.get_bom_material_detail({ "item_code": item.item_code, "bom_no": item.bom_no,
+				"qty": item.qty	})
+			
+			for r in ret:
+				if not item.fields[r]:
+					item.fields[r] = ret[r]
+		
+	def get_bom_material_detail(self, args=None):
 		""" Get raw material details like uom, desc and rate"""
 
-		arg = webnotes.form_dict.get('args')
-		import json
-		arg = json.loads(arg)
-		
-		item = self.get_item_det(arg['item_code'])
+		if not args:
+			args = webnotes.form_dict.get('args')
+			import json
+			args = json.loads(args)
+			
+		item = self.get_item_det(args['item_code'])
 		self.validate_rm_item(item)
 		
-		arg['bom_no'] = arg['bom_no'] or item and cstr(item[0]['default_bom']) or ''
-		arg.update(item[0])
+		args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or ''
+		args.update(item[0])
 
-		rate = self.get_rm_rate(arg)
+		rate = self.get_rm_rate(args)
 		ret_item = {
-			 'description'  : item and arg['description'] or '',
-			 'stock_uom'	: item and arg['stock_uom'] or '',
-			 'bom_no'		: arg['bom_no'],
+			 'description'  : item and args['description'] or '',
+			 'stock_uom'	: item and args['stock_uom'] or '',
+			 'bom_no'		: args['bom_no'],
 			 'rate'			: rate
 		}
 		return ret_item
@@ -183,11 +186,14 @@
 		if not item:
 			msgprint("Item %s does not exists in the system or expired." % 
 				self.doc.item, raise_exception = 1)
-
 		elif item[0]['is_manufactured_item'] != 'Yes' \
 				and item[0]['is_sub_contracted_item'] != 'Yes':
 			msgprint("""As Item: %s is not a manufactured / sub-contracted item, \
 				you can not make BOM for it""" % self.doc.item, raise_exception = 1)
+		else:
+			ret = webnotes.conn.get_value("Item", self.doc.item, ["description", "stock_uom"])
+			self.doc.description = ret[0]
+			self.doc.uom = ret[1]
 
 	def validate_operations(self):
 		""" Check duplicate operation no"""
@@ -293,9 +299,10 @@
 		"""Update workstation rate and calculates totals"""
 		total_op_cost = 0
 		for d in getlist(self.doclist, 'bom_operations'):
+			if d.workstation and not d.hour_rate:
+				d.hour_rate = webnotes.conn.get_value("Workstation", d.workstation, "hour_rate")
 			if d.hour_rate and d.time_in_mins:
 				d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
-			d.save()
 			total_op_cost += flt(d.operating_cost)
 		self.doc.operating_cost = total_op_cost
 		
@@ -307,7 +314,6 @@
 				d.rate = self.get_bom_unitcost(d.bom_no)
 			d.amount = flt(d.rate) * flt(d.qty)
 			d.qty_consumed_per_unit = flt(d.qty) / flt(self.doc.quantity)
-			d.save()
 			total_rm_cost += d.amount
 		self.doc.raw_material_cost = total_rm_cost