Merge branch 'stable'
diff --git a/erpnext/home/page/my_company/my_company.js b/erpnext/home/page/my_company/my_company.js
index 3070c75..58ff91e 100644
--- a/erpnext/home/page/my_company/my_company.js
+++ b/erpnext/home/page/my_company/my_company.js
@@ -416,7 +416,7 @@
 					width: 300,
 					fields: [
 						{
-							label: 'Please Enter Your Password',
+							label: 'Please Enter <b style="color: black">Your Password</b>',
 							description: "Your password is required to update the concerned user's password",
 							fieldtype: 'Password',
 							fieldname: 'sys_admin_pwd',
diff --git a/erpnext/patches/jan_mar_2012/jan_production_patches.py b/erpnext/patches/jan_mar_2012/jan_production_patches.py
new file mode 100644
index 0000000..f868cea
--- /dev/null
+++ b/erpnext/patches/jan_mar_2012/jan_production_patches.py
@@ -0,0 +1,9 @@
+import webnotes
+def execute():
+	"""
+		Patch includes:
+		* Reload of Stock Entry Detail
+	"""
+	from webnotes.modules.module_manager import reload_doc
+
+	reload_doc('stock', 'doctype', 'stock_entry_detail')	
diff --git a/erpnext/patches/jan_mar_2012/production_cleanup.py b/erpnext/patches/jan_mar_2012/production_cleanup.py
new file mode 100644
index 0000000..f50278f
--- /dev/null
+++ b/erpnext/patches/jan_mar_2012/production_cleanup.py
@@ -0,0 +1,69 @@
+def execute():
+	import webnotes
+	from webnotes.modules.module_manager import reload_doc
+	from webnotes.model import delete_doc
+	sql = webnotes.conn.sql
+	
+	# Production Planning Tool
+	#---------------------------------------------------------------
+	#delete_doc('DocType', 'PP Detail')
+	#delete_doc('DocType', 'PP SO Detail')
+	#delete_doc('DocType', 'Production Planning Tool')
+	sql("delete from `tabDocField` where parent in ('Production Planning Tool', 'PP Detail', 'PP SO Detail')")
+	
+	reload_doc('production', 'doctype', 'production_planning_tool')
+	reload_doc('production', 'doctype', 'pp_detail')
+	reload_doc('production', 'doctype', 'pp_so_detail')
+
+	# Production Order
+	#---------------------------------------------------------------
+
+	reload_doc('production', 'doctype', 'production_order')
+
+	sql("""delete from `tabDocField` where parent = 'Production Order'
+			and (label in ('Material Transfer', 'Backflush', 'Stop Production Order', 'Unstop Production Order')
+				or fieldname = 'transaction_date')
+	""")
+
+
+	# Bill Of Materials
+	#---------------------------------------------------------------
+	reload_doc('production', 'doctype', 'bill_of_materials')
+	reload_doc('production', 'doctype', 'bom_material')
+	reload_doc('production', 'doctype', 'bom_operation')
+	reload_doc('production', 'doctype', 'flat_bom_detail')
+
+	#copy values
+	sql("""update `tabBill Of Materials` set rm_cost_as_per = 'Valuation Rate', 
+		raw_material_cost = dir_mat_as_per_mar,	total_cost = cost_as_per_mar, costing_date = cost_as_on""")
+
+	sql("update `tabBOM Material` set rate = moving_avg_rate, amount = amount_as_per_mar")
+
+	sql("update `tabFlat BOM Detail` set rate = moving_avg_rate, amount = amount_as_per_mar")
+
+
+
+	# delete depricated flds from bom
+	sql("""	delete from `tabDocField` where parent = 'Bill Of Materials' 
+		and (
+			label in ('TreeView1', 'Set as Default BOM', 'Activate BOM', 'Inactivate BOM') 
+			or fieldname in ('cost_as_per_mar', 'cost_as_per_lpr', 'cost_as_per_sr', 'cost_as_on',
+				'dir_mat_as_per_mar', 'dir_mat_as_per_lpr', 'dir_mat_as_per_sr')
+		)	
+	""")
+
+	# delete depricated flds from bom operation
+	sql("delete from `tabDocField` where parent = 'BOM Operation' and fieldname in ('details', 'workstation_capacity')")
+
+	# delete depricated flds from bom material
+	sql("""delete from `tabDocField` where parent = 'BOM Material' 
+		and fieldname in ('dir_mat_as_per_mar', 'dir_mat_as_per_sr', 'dir_mat_as_per_lpr', 'operating_cost', 'value_as_per_mar', 
+			'value_as_per_sr', 'value_as_per_lpr', 'moving_avg_rate', 'standard_rate', 'last_purchase_rate', 'amount_as_per_sr', 
+			'amount_as_per_lpr', 'amount_as_per_mar')	
+	""")
+
+	# delete depricated flds from flat bom
+	sql("""delete from tabDocField where parent = 'Flat BOM Detail' 
+		and fieldname in ('moving_avg_rate', 'standard_rate', 'last_purchase_rate', 'amount_as_per_mar', 
+			'amount_as_per_sr', 'amount_as_per_lpr', 'flat_bom_no', 'bom_mat_no', 'is_pro_applicable')
+	""")
diff --git a/erpnext/patches/patch_list.py b/erpnext/patches/patch_list.py
index f3702f9..d9a8219 100644
--- a/erpnext/patches/patch_list.py
+++ b/erpnext/patches/patch_list.py
@@ -13,5 +13,15 @@
 		'patch_module': 'patches.jan_mar_2012',
 		'patch_file': 'rename_doctype_indent',
 		'description': 'Add DocType Label: Indent to Purchase Requisition'
+	},
+	{
+		'patch_module': 'patches.jan_mar_2012',
+		'patch_file': 'production_cleanup',
+		'description': 'Major changes in production module, almost rewrited the entire code'
+	},
+	{
+		'patch_module': 'patches.jan_mar_2012',
+		'patch_file': 'jan_production_patches',
+		'description': 'Fixes after Major changes in production module'
 	}
 ]
diff --git a/erpnext/production/doctype/bill_of_materials/bill_of_materials.js b/erpnext/production/doctype/bill_of_materials/bill_of_materials.js
index d458d27..1342140 100644
--- a/erpnext/production/doctype/bill_of_materials/bill_of_materials.js
+++ b/erpnext/production/doctype/bill_of_materials/bill_of_materials.js
@@ -1,123 +1,143 @@
-//$import(Production Tips Common)
-
-// ONLOAD
-cur_frm.cscript.onload = function(doc,cdt,cdn){
-
-
-}
-
 // On REFRESH
-cur_frm.cscript.refresh = function(doc,cdt,cdn){
-
-
-
-  // Hide - Un Hide Buttons
-  if (!doc.is_default && doc.__islocal!=1) unhide_field('Set as Default BOM');
-  else hide_field('Set as Default BOM');
-  if (doc.is_default && doc.__islocal!=1) unhide_field('Unset as Default BOM');
-  else hide_field('Unset as Default BOM');
-
-  if(doc.__islocal!=1){
-    set_field_permlevel('item',1);
-  }
-  if (flt(doc.docstatus) == 1){
-    if (doc.is_active == 'Yes') { unhide_field('Inactivate BOM'); hide_field('Activate BOM');}
-    else { hide_field('Inactivate BOM'); unhide_field('Activate BOM');}
-  }
+cur_frm.cscript.refresh = function(doc,dt,dn){
+	if(!doc.__islocal) {
+		set_field_permlevel('item',1);
+		unhide_field('Update Cost as on today');
+	} else {
+		hide_field('Update Cost as on today');
+	}
 }
 
+
+// Triggers
+//--------------------------------------------------------------------------------------------------
+cur_frm.cscript.item = function(doc, dt, dn) {
+	if (doc.item) {
+		get_server_fields('get_item_detail',doc.item,'',doc,dt,dn,1);
+	}
+}
+
+
+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);
+	}
+}
+
+
+cur_frm.cscript.hour_rate = function(doc, dt, dn) {
+	calculate_op_cost(doc, dt, dn);
+	calculate_total(doc);
+}
+
+
+cur_frm.cscript.time_in_mins = cur_frm.cscript.hour_rate;
+
+
+cur_frm.cscript.item_code = function(doc,dt,dn) {
+	get_bom_material_detail(doc, dt, dn);
+}
+
+
+cur_frm.cscript.bom_no  = function(doc,dt,dn) {
+	get_bom_material_detail(doc, dt, dn);
+}
+
+
+var get_bom_material_detail= function(doc,dt,dn) {
+	var d = locals[dt][dn];
+	var callback = function(doc, dt, dn) {
+		calculate_rm_cost(doc, dt, dn);
+		calculate_total(doc);
+	}
+
+	var bom_no = (d.bom_no!=null) ? d.bom_no:''
+	if (d.item_code) {
+		arg = {'item_code': d.item_code, 'bom_no': bom_no, 'qty': d.qty};
+		get_server_fields('get_bom_material_detail', JSON.stringify(arg), 'bom_materials', doc, dt, dn, 1, callback);
+	}
+}
+
+
+cur_frm.cscript.qty = function(doc, dt, dn) {
+	calculate_rm_cost(doc, dt, dn);
+	calculate_total(doc);
+}
+
+
+cur_frm.cscript.rate = cur_frm.cscript.qty;
+
+
+cur_frm.cscript.is_default = function(doc, dt, dn) {
+	if (doc.docstatus == 1)
+		$c_obj(make_doclist(dt, dn), 'manage_default_bom', '', '');
+}
+
+
+cur_frm.cscript.is_active = function(doc, dt, dn) {
+	if (!doc.__islocal)
+		$c_obj(make_doclist(dt, dn), 'manage_active_bom', '', '');
+}
+
+
+// Calculate Operating Cost
+var calculate_op_cost = function(doc, dt, dn) {  
+	var op = getchildren('BOM Operation', doc.name, 'bom_operations');
+	total_op_cost = 0;
+	for(var i=0;i<op.length;i++) {
+		op_cost =  flt(op[i].hour_rate) * flt(op[i].time_in_mins) / 60;
+		set_multiple('BOM Operation',op[i].name, {'operating_cost': op_cost}, 'bom_operations');
+		total_op_cost += op_cost;
+	}
+	doc.operating_cost = total_op_cost;
+	refresh_field('operating_cost');
+}
+
+
+// Calculate Raw Material Cost
+var calculate_rm_cost = function(doc, dt, dn) {  
+	var rm = getchildren('BOM Material', doc.name, 'bom_materials');
+	total_rm_cost = 0;
+	for(var i=0;i<rm.length;i++) {
+		amt =  flt(rm[i].rate) * flt(rm[i].qty);
+		set_multiple('BOM Material',rm[i].name, {'amount': amt}, 'bom_materials');
+		set_multiple('BOM Material',rm[i].name, {'qty_consumed_per_unit': flt(rm[i].qty)/flt(doc.quantity)}, 'bom_materials');
+		total_rm_cost += amt;
+	}
+	doc.raw_material_cost = total_rm_cost;
+	refresh_field('raw_material_cost');
+}
+
+
+// Calculate Total Cost
+var calculate_total = function(doc) {
+	doc.total_cost = flt(doc.raw_material_cost) + flt(doc.operating_cost);
+	refresh_field('total_cost');
+}
+
+
+
+// Get Query
+//-----------------------------------------------------------------------------------------------------
 cur_frm.fields_dict['item'].get_query = function(doc) {
-  return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.description FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.`%(key)s` like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
+	return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.description FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.`%(key)s` like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
 }
 
-// ---------------------- Get project name --------------------------
-cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
-  return 'SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.status = "Open" AND `tabProject`.name LIKE "%s" ORDER BY `tabProject`.name ASC LIMIT 50';
+cur_frm.fields_dict['project_name'].get_query = function(doc, dt, dn) {
+	return 'SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.status = "Open" AND `tabProject`.name LIKE "%s" ORDER BY `tabProject`.name ASC LIMIT 50';
 }
 
 cur_frm.fields_dict['bom_materials'].grid.get_field('item_code').get_query = function(doc) {
-  return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.description FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.`%(key)s` like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
+	return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.description FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.`%(key)s` like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
 }
 
 cur_frm.fields_dict['bom_materials'].grid.get_field('bom_no').get_query = function(doc) {
-   var d = locals[this.doctype][this.docname];
-   return 'SELECT DISTINCT `tabBill Of Materials`.`name`, `tabBill Of Materials`.`remarks` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`item` = "' + d.item_code + '" AND `tabBill Of Materials`.`name` like "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
+	var d = locals[this.doctype][this.docname];
+	return 'SELECT DISTINCT `tabBill Of Materials`.`name`, `tabBill Of Materials`.`remarks` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`item` = "' + d.item_code + '" AND `tabBill Of Materials`.`is_active` = "Yes" AND `tabBill Of Materials`.docstatus = 1 AND `tabBill Of Materials`.`name` like "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
 }
 
-cur_frm.cscript.item = function(doc, cdt, cdn) {
-  if (doc.item) {
-    get_server_fields('get_item_detail',doc.item,'',doc,cdt,cdn,1);
-  }
-}
-
-cur_frm.cscript.workstation = function(doc,cdt,cdn) {
-  var d = locals[cdt][cdn];
-  if (d.workstation) {
-    get_server_fields('get_workstation_details',d.workstation,'bom_operations',doc,cdt,cdn,1);
-  }
-}
-
-cur_frm.cscript.item_code =function(doc,cdt,cdn) {
-  var d = locals[cdt][cdn];
-  if (d.item_code) {
-    arg = "{'item_code' : '" + d.item_code + "', 'bom_no' : ''}";
-    get_server_fields('get_bom_material_detail',arg,'bom_materials',doc,cdt,cdn,1);
-  }
-}
-
-cur_frm.cscript.bom_no = function(doc,cdt,cdn) {
-  var d = locals[cdt][cdn];
-  if (d.item_code && d.bom_no) {
-    arg = "{'item_code' : '" + d.item_code + "', 'bom_no' : '" + d.bom_no + "'}";
-    get_server_fields('get_bom_material_detail',arg,'bom_materials',doc,cdt,cdn,1);
-  }
-}
-
-cur_frm.cscript['Set as Default BOM'] = function(doc,cdt,cdn) {
-  var check = confirm("Do you Really want to Set BOM " + doc.name + " as default for Item " + doc.item);
-  if (check) {
-    $c('runserverobj', args={'method':'set_as_default_bom', 'docs': compress_doclist([doc])}, function(r,rt) {
-    refresh_field('is_default');
-    hide_field('Set as Default BOM');unhide_field('Unset as Default BOM');
-    refresh_field('Set as Default BOM');
-    });
-  }
-}
-
-cur_frm.cscript['Unset as Default BOM'] = function(doc,cdt,cdn) {
-  var check = confirm("Do you Really want to Unset BOM " + doc.name + " as default for Item " + doc.item);
-  if (check) {
-    $c('runserverobj', args={'method':'unset_as_default_bom', 'docs': compress_doclist([doc])}, function(r,rt) {
-    refresh_field('is_default');
-    hide_field('Unset as Default BOM');unhide_field('Set as Default BOM');
-    refresh_field('Unset as Default BOM');
-    });
-  }
-}
-
-cur_frm.cscript['Activate BOM'] = function(doc,cdt,cdn) {
-  var check = confirm("DO YOU REALLY WANT TO ACTIVATE BOM : " + doc.name);
-
-  if (check) {
-    $c('runserverobj', args={'method':'activate_inactivate_bom', 'arg': 'Activate', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
-      cur_frm.refresh();
-    });
-  }
-}
-
-cur_frm.cscript['Test Flat BOM'] = function(doc,cdt,cdn) {
-
-    $c('runserverobj', args={'method':'get_current_flat_bom_items', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
-      cur_frm.refresh();
-    });
-}
-
-cur_frm.cscript['Inactivate BOM'] = function(doc,cdt,cdn) {
-  var check = confirm("DO YOU REALLY WANT TO INACTIVATE BOM : " + doc.name);
-
-  if (check) {
-    $c('runserverobj', args={'method':'activate_inactivate_bom', 'arg': 'Inactivate', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
-      cur_frm.refresh();
-    });
-  }
-}
\ No newline at end of file
diff --git a/erpnext/production/doctype/bill_of_materials/bill_of_materials.py b/erpnext/production/doctype/bill_of_materials/bill_of_materials.py
index a62e4f2..2a17817 100644
--- a/erpnext/production/doctype/bill_of_materials/bill_of_materials.py
+++ b/erpnext/production/doctype/bill_of_materials/bill_of_materials.py
@@ -1,547 +1,397 @@
-# Please edit this list and import only required elements
 import webnotes
-
-from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
-from webnotes.model import db_exists
-from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType
-from webnotes.model.doclist import getlist, copy_doclist
-from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
-from webnotes import session, form, is_testing, msgprint, errprint
+from webnotes.utils import cint, cstr, flt, get_defaults, getdate, now, nowdate
+from webnotes.model.doc import Document, addchild, getchildren, make_autoname
+from webnotes.model.doclist import getlist
+from webnotes.model.code import get_obj
+from webnotes import msgprint, errprint
 
 set = webnotes.conn.set
 sql = webnotes.conn.sql
 get_value = webnotes.conn.get_value
-in_transaction = webnotes.conn.in_transaction
-convert_to_lists = webnotes.conn.convert_to_lists
 
 # -----------------------------------------------------------------------------------------
 
-
 class DocType:
-  def __init__(self, doc, doclist=[]):
-    self.doc = doc
-    self.doclist = doclist
+	def __init__(self, doc, doclist=[]):
+		self.doc = doc
+		self.doclist = doclist
 
-  def autoname(self):
-    last_name = sql("select max(name) from `tabBill Of Materials` where name like 'BOM/%s/%%'" % self.doc.item)
-    if last_name:
-      idx = cint(cstr(last_name[0][0]).split('/')[-1]) + 1
-    else:
-      idx = 1
-    self.doc.name = 'BOM/' + self.doc.item + ('/%.3i' % idx)
+	def autoname(self):
+		last_name = sql("select max(name) from `tabBill Of Materials` where name like 'BOM/%s/%%'" % self.doc.item)
+		if last_name:
+			idx = cint(cstr(last_name[0][0]).split('/')[-1]) + 1
+		else:
+			idx = 1
+		self.doc.name = 'BOM/' + self.doc.item + ('/%.3i' % idx)
 
-  #----------- Client Trigger function ----------
-  def get_item_detail(self, item_code):
-    item = sql("select description, stock_uom from `tabItem` where (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life >  now()) and name = %s",item_code , as_dict =1)
-    ret={
-      'description'   : item and item[0]['description'] or '',
-      'uom'			  : item and item[0]['stock_uom'] or ''
-    }
-    return ret
 
-  def get_workstation_details(self,workstation):
-    ws = sql("select hour_rate, capacity from `tabWorkstation` where name = %s",workstation , as_dict = 1)
-    ret = {
-      'hour_rate'            : ws and flt(ws[0]['hour_rate']) or '',
-      'workstation_capacity' : ws and flt(ws[0]['capacity']) or ''
-    }
-    return ret
+	def get_item_det(self, item_code):
+		item = sql("""select name, is_asset_item, is_purchase_item, docstatus, is_sub_contracted_item,
+			description, stock_uom, default_bom, last_purchase_rate, standard_rate, is_manufactured_item from `tabItem` 
+			where item_code = %s""", item_code, as_dict = 1)
 
-  def get_bom_material_detail(self, arg):
-    arg = eval(arg)
-    if arg['item_code'] and arg['item_code'] == self.doc.item:
-      msgprint(" Item_code: "+arg['item_code']+" in materials tab cannot be same as main Item in BOM := " +cstr(self.doc.name))
-      raise Exception
-    if arg['item_code']:
-      item = sql("select is_asset_item, is_purchase_item, docstatus, is_sub_contracted_item, description, stock_uom, default_bom from `tabItem` where item_code = %s", (arg['item_code']), as_dict = 1)
+		return item
 
-      # Check for Asset Item
-      if item and item[0]['is_asset_item'] == 'Yes':
-        msgprint("Sorry!!! Item " + arg['item_code'] + " is an Asset of the company. Entered in BOM := " + cstr(self.doc.name))
-        raise Exception
 
-      if item and item[0]['docstatus'] == 2:
-        msgprint("Item %s does not exist in system" % cstr(args['item_code']))
+	def get_item_detail(self, item_code):
+		""" Get stock uom and description for finished good item"""
 
-      ret_item = {
-                 'description' : item and item[0]['description'] or '',
-                 'stock_uom'   : item and item[0]['stock_uom'] or '',
-                 'bom_no'      : item and item[0]['default_bom'] or ''
-      }
+		item = self.get_item_det(item_code)
+		ret={
+			'description'	 : item and item[0]['description'] or '',
+			'uom'				: item and item[0]['stock_uom'] or ''
+		}
+		return ret
 
-      # Check for Purchase Item
-      if item and (item[0]['is_purchase_item'] == 'Yes' or item[0]['is_sub_contracted_item'] == 'Yes'):
-        ret_item['moving_avg_rate'], ret_item['last_purchase_rate'], ret_item['standard_rate']  = self.get_mar_lpr_sr(arg['item_code'], mar = 1, lpr = 1, sr = 1)
-        ret_item['operating_cost'], ret_item['dir_mat_as_per_mar'], ret_item['dir_mat_as_per_lpr'], ret_item['dir_mat_as_per_sr'] = 0, 0, 0, 0
-        ret_item['value_as_per_mar'], ret_item['value_as_per_lpr'], ret_item['value_as_per_sr'] = 0, 0, 0
-        ret_item['amount_as_per_mar'], ret_item['amount_as_per_lpr'], ret_item['amount_as_per_sr'] = 0, 0, 0
 
-    if arg['bom_no'] or not ret_item['bom_no'] =='':
-      if arg['bom_no']:
-        bom = sql("select name, dir_mat_as_per_mar,dir_mat_as_per_lpr,dir_mat_as_per_sr, operating_cost, quantity from `tabBill Of Materials` where is_active = 'Yes' and name = %s", (arg['bom_no']), as_dict=1)
-      else:
-        # get recent direct material cost, operating_cost, cost from Default BOM of Item
-        bom = sql("select name, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, operating_cost, quantity from `tabBill Of Materials` where is_active = 'Yes' and name = %s", (ret_item['bom_no']), as_dict=1)
 
-      # get recent direct material cost, operating_cost, cost from Entered BOM of Item
-      ret_item['bom_no'] = bom and bom[0]['name'] or ''
+	def get_workstation_details(self,workstation):
+		""" Fetch hour rate from workstation master"""
 
-      if bom and bom[0]['name']:
-        ret_bom = {
-        'dir_mat_as_per_mar' : flt(bom[0]['dir_mat_as_per_mar']) / flt(bom[0]['quantity']) or 0.00,
-        'dir_mat_as_per_lpr' : flt(bom[0]['dir_mat_as_per_lpr']) / flt(bom[0]['quantity']) or 0.00,
-        'dir_mat_as_per_sr'  : flt(bom[0]['dir_mat_as_per_sr']) / flt(bom[0]['quantity']) or 0.00,
-        'operating_cost'     : flt(bom[0]['operating_cost']) / flt(bom[0]['quantity']) or 0.00,
-        'value_as_per_mar'   : ((flt(bom[0]['dir_mat_as_per_mar']) + flt(bom[0]['operating_cost'])) / flt(bom[0]['quantity'])) or 0.00,
-        'value_as_per_lpr'   : ((flt(bom[0]['dir_mat_as_per_lpr']) + flt(bom[0]['operating_cost'])) / flt(bom[0]['quantity'])) or 0.00,
-        'value_as_per_sr'    : ((flt(bom[0]['dir_mat_as_per_sr'])  + flt(bom[0]['operating_cost'])) / flt(bom[0]['quantity'])) or 0.00,
-        'amount_as_per_mar'  : 0,
-        'amount_as_per_lpr'  : 0,
-        'amount_as_per_sr'   : 0
-        }
-        ret_item.update(ret_bom)
-        if item and item[0]['is_sub_contracted_item'] != 'Yes':
-          ret_bom_rates = {
-            'moving_avg_rate'    : 0,
-            'last_purchase_rate' : 0,
-            'standard_rate'      : 0
-            }
-          ret_item.update(ret_bom_rates)
-    return ret_item
+		ws = sql("select hour_rate from `tabWorkstation` where name = %s",workstation , as_dict = 1)
+		ret = {
+			'hour_rate'				: ws and flt(ws[0]['hour_rate']) or '',
+		}
+		return ret
 
-  def set_as_default_bom(self):
-    # set Is Default as 1
-    set(self.doc,'is_default', flt(1))
 
-    # get previous default bom from Item Master
-    prev_def_bom = sql("select default_bom from `tabItem` where name = %s", self.doc.item,as_dict = 1)
 
-    if prev_def_bom[0]['default_bom'] and prev_def_bom[0]['default_bom'] != self.doc.name:
-      # update Is Default as 0 in Previous Default BOM
-      msgprint(cstr(prev_def_bom[0]['default_bom']) + "is no longer Default BOM for item" + cstr(self.doc.item))
-      sql("update `tabBill Of Materials` set is_default = 0 where name = '%s'" % (prev_def_bom[0]['default_bom']))
+	def validate_rm_item(self, item):
+		""" Validate raw material items"""
 
-    # update current BOM as default bom in Item Master
-    sql("update `tabItem` set default_bom = '%s' where name = '%s'" % (self.doc.name,self.doc.item))
-    msgprint(cstr(self.doc.name) + "has been set as Default BOM for Item "+cstr(self.doc.item))
+		if item[0]['name'] == self.doc.item:
+			msgprint(" Item_code: "+item[0]['name']+" in materials tab cannot be same as FG Item in BOM := " +cstr(self.doc.name), raise_exception=1)
+		
+		if item and item[0]['is_asset_item'] == 'Yes':
+			msgprint("Sorry!!! Item " + item[0]['name'] + " is an Asset of the company. Entered in BOM => " + cstr(self.doc.name), raise_exception = 1)
 
-  def unset_as_default_bom(self):
-    # set Is Default as 1
-    set(self.doc,'is_default', flt(0))
+		if not item or item[0]['docstatus'] == 2:
+			msgprint("Item %s does not exist in system" % item[0]['item_code'], raise_exception = 1)
 
-    # update current BOM as default bom in Item Master
-    sql("update `tabItem` set default_bom = null where name = '%s'" % (self.doc.item))
-    msgprint(cstr(self.doc.name) + "has been unset as Default BOM for Item "+cstr(self.doc.item))
 
-  def check_active_parent_boms(self):
-    act_pbom = sql("select distinct t1.parent from `tabBOM Material` t1, `tabBill Of Materials` t2 where t1.bom_no ='%s' and t2.name = t1.parent and t2.is_active = 'Yes' and t2.docstatus = 1 and t1.docstatus =1 " % self.doc.name )
-    if act_pbom and act_pbom[0][0]:
-      msgprint("Sorry cannot Inactivate as BOM %s is child of one or many other active parent BOMs" % self.doc.name)
-      raise Exception
 
-  def activate_inactivate_bom(self, action):
-    if cstr(action) == 'Activate':
-      self.validate()
-      set(self.doc, 'is_active', 'Yes')
-    elif cstr(action) == 'Inactivate':
-      self.check_active_parent_boms()
-      set(self.doc, 'is_active', 'No')
+	def get_bom_material_detail(self, arg):
+		""" Get raw material details like uom, desc and rate"""
 
-  #------ On Validation Of Document ----------
-  def validate_main_item(self):
-    item = sql("select is_manufactured_item, is_sub_contracted_item from `tabItem` where name = %s and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life >  now())", self.doc.item, as_dict = 1)
+		arg = eval(arg)
+		item = self.get_item_det(arg['item_code'])
 
-    if not item:
-      msgprint("Item %s do not exists in the system. Entered in BOM := %s" % (cstr(self.doc.item), cstr(self.doc.name)))
-      raise Exception
+		self.validate_rm_item(item)
+		
+		arg['bom_no'] = arg['bom_no'] or item and cstr(item[0]['default_bom']) or ''
+		arg.update(item[0])
 
-    elif not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item'] == 'Yes':
-      msgprint("Sorry cannot make Bill Of Materials for Item %s. As it is not a manufactured / sub-contracted item. Entered in BOM := %s " % (cstr(self.doc.item), cstr(self.doc.name)))
-      raise Exception
+		rate = self.get_rm_rate(arg)
 
-  # validate operations
-  #------------------------------------------------------
-  def validate_operations(self,o,validate = "0"):
-    if not o.operation_no:
-      msgprint("Please Enter Operation No at Row " + cstr(o.idx)+" in BOM := " +cstr(self.doc.name))
-      raise Exception
+		ret_item = {
+					 'description'  : item and arg['description'] or '',
+					 'stock_uom'	: item and arg['stock_uom'] or '',
+					 'bom_no'		: arg['bom_no'],
+					 'rate'			: rate
+		}
+		return ret_item
 
-    if not o.workstation:
-      msgprint("Please Enter Workstation for Operation No. " + cstr(o.operation_no) + " in BOM NO. " + self.doc.name)
-      raise Exception
 
-    if not o.time_in_mins:
-      msgprint("Please Enter Operation Time of Operation No. " + cstr(o.operation_no)  + " in BOM NO. " + self.doc.name)
-      raise Exception
 
-    # Operation No should not repeat.
-    if o.operation_no in self.op:
-      msgprint("Operation No " + cstr(o.operation_no) + "is repeated in Operations Table of BOM NO. " + self.doc.name)
-      raise Exception
+	def get_rm_rate(self, arg):
+		"""	Get raw material rate as per selected method, if bom exists takes bom cost """
 
-      # add operation in op list
-    self.op.append(cstr(o.operation_no))
+		if arg['bom_no']:
+			bom = sql("""select name, total_cost/quantity as unit_cost from `tabBill Of Materials`
+				where is_active = 'Yes' and name = %s""", arg['bom_no'], as_dict=1)
+			rate = bom and bom[0]['unit_cost'] or 0
+		elif arg and (arg['is_purchase_item'] == 'Yes' or arg['is_sub_contracted_item'] == 'Yes'):
+			if self.doc.rm_cost_as_per == 'Valuation Rate':
+				rate = self.get_valuation_rate(arg)
+			elif self.doc.rm_cost_as_per == 'Last Purchase Rate':
+				rate = arg['last_purchase_rate']
+			elif self.doc.rm_cost_as_per == 'Standard Rate':
+				rate = arg['standard_rate']
 
-  # Validate materials
-  #-------------------------------------------------
+		return rate
 
-  def validate_materials(self,m):
+	
 
-    # check for operation no
-    if not self.op:
-      msgprint("Please Enter Operations in operation table of BOM NO. " + self.doc.name)
-      raise Exception
+	def get_valuation_rate(self, arg):
+		""" Get average valuation rate of relevant warehouses 
+			as per valuation method (MAR/FIFO) 
+			as on costing date	
+		"""
 
-    # check if operation no not in op list
-    if m.operation_no not in self.op:
-      msgprint("Operation no "+ cstr(m.operation_no) + " for item code " + cstr(m.item_code) +" is not present in BOM Operations of BOM NO. " + self.doc.name)
-      raise Exception
+		dt = self.doc.costing_date or nowdate()
+		time = self.doc.costing_date == nowdate() and now().split()[1] or '23:59'
+		warehouse = sql("select warehouse from `tabBin` where item_code = %s", arg['item_code'])
+		rate = []
+		for wh in warehouse:
+			r = get_obj('Valuation Control').get_incoming_rate(dt, time, arg['item_code'], wh[0], qty = arg.get('qty', 0))
+			if r:
+				rate.append(r)
 
-    if not m.item_code:
-      msgprint("Please Enter Item Code at Row " + cstr(m.idx) + "of BOM Material in BOM NO. " + self.doc.name)
-      raise Exception
+		return rate and flt(sum(rate))/len(rate) or 0
 
-    item = sql("select is_manufactured_item, is_sub_contracted_item from`tabItem` where item_code = %s and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life >  now())", m.item_code, as_dict = 1)
-    if not item:
-      msgprint("Item %s is not present in Item Master." % m.item_code)
-      raise Exception
 
-    if item[0]['is_manufactured_item'] == 'Yes' or item[0]['is_sub_contracted_item'] == 'Yes':
-      bom = sql("select name, is_active, docstatus from `tabBill Of Materials` where item = %s", m.item_code, as_dict =1)
-      if bom and bom[0]['name']:
-        if not m.bom_no:
-          msgprint("Please Enter BOM No for Item " + cstr(m.item_code) + " in Materials at Row No. " + cstr(m.idx)  + " in BOM NO. " + self.doc.name)
-          raise Exception
-        else:
-          match = 0
-          for b in bom:
-            if cstr(m.bom_no) == cstr(b['name']):
-              if b['is_active'] != 'Yes':
-                msgprint("BOM %s NOT ACTIVE BOM. Entered in BOM := %s at row no := %s" % (cstr(m.bom_no), cstr(self.doc.name), m.idx))
-                raise Exception
 
-              #if flt(b['docstatus']) != 1:
-              #  msgprint("BOM %s is NOT SUBMITTED."% cstr(m.bom_no))
-              #  raise Exception
+	def manage_default_bom(self):
+		""" Uncheck others if current one is selected as default, update default bom in item master"""
 
-              match = 1
-          if not match:
-            msgprint("Item %s does not belongs to Bill Of Material %s or Bill Of Material %s is NOT ACTIVE BOM. Entered in BOM := %s at row no := %s" % (cstr(m.item_code),cstr(m.bom_no), cstr(m.bom_no), self.doc.name, m.idx))
-            raise Exception
+		if self.doc.is_default and self.doc.is_active == 'Yes':
+			sql("update `tabBill Of Materials` set is_default = 0 where name != %s", self.doc.name)
 
-    if not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item']== 'Yes':
-      if m.bom_no:
-        msgprint("As in Item Master of Item %s Is Manufactured Item / Is Sub-Contracted Item  is not 'Yes' hence there should be no BOM.In BOm := %s at row no := %s" % (m.item_code, cstr(self.doc.name), m.idx))
-        raise Exception
+			# update default bom in Item Master
+			sql("update `tabItem` set default_bom = %s where name = %s", (self.doc.name, self.doc.item))
+		else:
+			sql("update `tabItem` set default_bom = '' where name = %s and default_bom = %s", (self.doc.item, self.doc.name))
+	
 
-    if not m.qty or m.qty <= 0:
-      msgprint("Please Enter Qty value greater than 0(Zero) at Row " + cstr(m.idx) + " in BOM NO. " + self.doc.name)
-      raise Exception
 
-    if m.scrap and m.scrap < 0:
-      msgprint("Please Enter Scrap value Greater than 0(Zero) at Row " + cstr(m.idx)  + " in BOM NO. " + self.doc.name)
-      raise Exception
+	def manage_active_bom(self):
+		""" Manage active/inactive """
+		if self.doc.is_active == 'Yes':
+			self.validate()
+		else:
+			self.check_active_parent_boms()
 
-  # Calculate Cost
-  #-----------------------------------------------
 
-  def calculate_cost(self, validate = 0):
-    self.op, op_cost, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, count_mat = [], 0.0, 0.0,0.0,0.0, 0
-    # --------  Calculate Cost Of BOM  -------------
-    # --- calculate operating cost from BOM Operations ----
-    for o in getlist(self.doclist, 'bom_operations'):
-      # --- Validation for enteries in BOM Operations ----
-      if validate:
-        self.validate_operations(o)
 
-      o.operating_cost = flt(flt(o.time_in_mins)/60) * flt(o.hour_rate)
-      if validate != 1:
-        o.save()
-        msgprint('Operation saved')
+	def check_active_parent_boms(self):
+		""" Check parent BOM before making it inactive """
+		act_pbom = sql("""select distinct t1.parent from `tabBOM Material` t1, `tabBill Of Materials` t2 
+			where t1.bom_no =%s and t2.name = t1.parent and t2.is_active = 'Yes' 
+			and t2.docstatus = 1 and t1.docstatus =1 """, self.doc.name)
+		if act_pbom and act_pbom[0][0]:
+			msgprint("""Sorry cannot inactivate as BOM: %s is child 
+				of one or many other active parent BOMs""" % self.doc.name, raise_exception=1)
 
-      op_cost = flt(op_cost) + flt(o.operating_cost)
 
-    # --- calculate operating cost and direct material cost from BOM Material ---
-    for m in getlist(self.doclist, 'bom_materials'):
-      # --- Validation for enteries in BOM Material --- '''
-      count_mat = count_mat + 1
-      if validate:
-        self.validate_materials(m)
 
-      if m.bom_no:
-        # add operating cost of child boms
-        op_cost += flt(m.operating_cost)
+	def calculate_cost(self):
+		"""Calculate bom totals"""
+		self.doc.costing_date = nowdate()
+		self.calculate_op_cost()
+		self.calculate_rm_cost()
+		self.doc.total_cost = self.doc.raw_material_cost + self.doc.operating_cost
+		self.doc.modified = now()
+		self.doc.save()
+
+		self.update_flat_bom_engine(is_submit = self.doc.docstatus)
+
+
+	
+
+	def calculate_op_cost(self):
+		"""Update workstation rate and calculates totals"""
+		total_op_cost = 0
+		for d in getlist(self.doclist, 'bom_operations'):
+			hour_rate = sql("select hour_rate from `tabWorkstation` where name = %s", d.workstation)
+			d.hour_rate = hour_rate and flt(hour_rate[0][0]) or 0
+			d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60
+			total_op_cost += d.operating_cost
+		self.doc.operating_cost = total_op_cost
+
+
+
+	def calculate_rm_cost(self):
+		"""Fetch RM rate as per today's valuation rate and calculate totals"""
+		total_rm_cost = 0
+		for d in getlist(self.doclist, 'bom_materials'):
+			if self.doc.rm_cost_as_per == 'Valuation Rate':
+				arg = {'item_code': d.item_code, 'qty': d.qty, 'bom_no': d.bom_no}
+				ret = self.get_bom_material_detail(cstr(arg))
+				for k in ret:
+					d.fields[k] = ret[k]
+
+			d.amount = flt(d.rate) * flt(d.qty)
+			total_rm_cost += d.amount
+		self.doc.raw_material_cost = total_rm_cost
+
+
+
+	def validate_main_item(self):
+		""" Validate main FG item"""
+		item = self.get_item_det(self.doc.item)
+		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)
+
+
 
-        # update dir_mat, op_cost, value from child bom
-        self.update_childs_dir_op_value(m, child_bom_cost = 1)
+	def validate_operations(self):
+		""" Check duplicate operation no"""
+		self.op = []
+		for d in getlist(self.doclist, 'bom_operations'):
+			if cstr(d.operation_no) in self.op:
+				msgprint("Operation no: %s is repeated in Operations Table"% d.operation_no, raise_exception=1)
+			else:
+				# add operation in op list
+				self.op.append(cstr(d.operation_no))
 
-        # check for is_sub_contracted_item
-        item = sql("select is_sub_contracted_item from `tabItem` where name = '%s'" % m.item_code, as_dict =1)
-        if item and item[0]['is_sub_contracted_item'] == 'Yes':
-          # update recent mar,lpr,sr
-          self.update_mar_lpr_sr(m, mar =1, lpr =1, sr =1)
-          # calculate amount for sub contracted item
-          self.calculate_amount( m, has_bom = 1, is_sub_cont = 1)
-          # calculate Direct Material
-          dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr = self.calculate_dir_mat(m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom = 1, is_sub_cont =1)
-        else:
-          # update mar,lpr,sr as 0
-          self.update_mar_lpr_sr( m, mar = 0, lpr = 0, sr = 0)
-          # calculate amount
-          self.calculate_amount( m, has_bom = 1, is_sub_cont = 0)
-          # calculate Direct Material
-          dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr = self.calculate_dir_mat(m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom = 1, is_sub_cont =0)
 
-      else :
-        # update dir_mat,op_cost, value as 0
-        self.update_childs_dir_op_value(m, child_bom_cost = 0)
-        # update recent mar,lpr,sr
-        self.update_mar_lpr_sr(m, mar =1, lpr =1, sr =1)
-        # calculate amount
-        self.calculate_amount(m, has_bom = 0, is_sub_cont = 0)
-        # calculate Direct Material
-        dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr = self.calculate_dir_mat(m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom =0, is_sub_cont =0)
 
-      # update qty_consumed_per_unit
-      m.qty_consumed_per_unit = flt(m.qty) / flt(self.doc.quantity)
-      m.save()
-      #msgprint("dir_mat_as_per_mar < ==> " + cstr(dir_mat_as_per_mar) + "***" + "dir_mat_as_per_lpr < ==> " + cstr(dir_mat_as_per_lpr) + "***" + "dir_mat_as_per_sr < ==> " + cstr(dir_mat_as_per_sr) + "***")
-    if not count_mat:
-      msgprint("There should at least one Item in BOM Material. In BOM := " +cstr(self.doc.name))
-      raise Exception
+	def validate_materials(self):
+		""" Validate raw material entries """
+		check_list = []
+		for m in getlist(self.doclist, 'bom_materials'):
+			# check if operation no not in op table
+			if m.operation_no not in self.op:
+				msgprint("""Operation no: %s against item: %s at row no: %s is not present 
+					at Operations table"""% (m.operation_no, m.item_code, m.idx), raise_exception = 1)
+		
+			item = self.get_item_det(m.item_code)
+			if item[0]['is_manufactured_item'] == 'Yes' or item[0]['is_sub_contracted_item'] == 'Yes':
+				if not m.bom_no:
+					msgprint("Please enter BOM No aginst item: %s at row no: %s"% (m.item_code, m.idx), raise_exception=1)
+				else:
+					self.validate_bom_no(m.item_code, m.bom_no, m.idx)
 
-    set(self.doc, 'operating_cost' ,op_cost)
-    set(self.doc, 'cost_as_on' ,now())
-    # update dir_mat
-    set(self.doc, 'dir_mat_as_per_mar' ,dir_mat_as_per_mar)
-    set(self.doc, 'dir_mat_as_per_lpr' ,dir_mat_as_per_lpr)
-    set(self.doc, 'dir_mat_as_per_sr'  ,dir_mat_as_per_sr)
-    # update cost
-    set(self.doc, 'cost_as_per_mar' ,flt(dir_mat_as_per_mar + op_cost))
-    set(self.doc, 'cost_as_per_lpr' ,flt(dir_mat_as_per_lpr + op_cost))
-    set(self.doc, 'cost_as_per_sr' ,flt(dir_mat_as_per_sr + op_cost))
+			elif m.bom_no:
+				msgprint("""As Item %s is not a manufactured / sub-contracted item, 
+					you can enter BOM against it (Row No: %s)."""% (m.item_code, m.idx), raise_excepiton = 1)
 
-  def update_childs_dir_op_value(self, m, child_bom_cost = 0):
-    #msgprint("IN UPDATE CHILDS DIR OP VALUE")
-    if child_bom_cost:
-      # get recent direct material cost, operating cost, cost from child bom
-      child_bom_cost = sql("select dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, operating_cost, cost_as_per_mar, cost_as_per_lpr, cost_as_per_sr, quantity from `tabBill Of Materials` where  name = %s", m.bom_no, as_dict = 1)
+			if flt(m.qty) <= 0:
+				msgprint("Please enter qty against raw material: %s at row no: %s"% (m.item_code, m.idx), raise_exception = 1)
 
-    # operating_cost
-    m.operating_cost = child_bom_cost and flt(child_bom_cost[0]['operating_cost']) / flt(child_bom_cost[0]['quantity']) or 0.00
+			self.check_if_item_repeated(m.item_code, m.operation_no, check_list)
 
-    val_dir_dict = {'value_as_per_mar': 'cost_as_per_mar', 'dir_mat_as_per_mar': 'dir_mat_as_per_mar',
-                    'value_as_per_lpr': 'cost_as_per_lpr', 'dir_mat_as_per_lpr': 'dir_mat_as_per_lpr',
-                    'value_as_per_sr' : 'cost_as_per_sr' , 'dir_mat_as_per_sr' : 'dir_mat_as_per_sr'  }
-    for d in val_dir_dict:
-      # Set Value and Dir MAt
-      m.fields[d] = child_bom_cost and flt(child_bom_cost[0][val_dir_dict[d]])/flt(child_bom_cost[0]['quantity']) or 0.00
 
-  def update_mar_lpr_sr(self, m, mar = 0, lpr = 0, sr = 0):
-    m.moving_avg_rate, m.last_purchase_rate, m.standard_rate = self.get_mar_lpr_sr(cstr(m.item_code), mar, lpr, sr, m.qty)
 
-  def calculate_amount(self, m, has_bom = 0, is_sub_cont = 0):
-    #msgprint("IN CALCULATE AMOUNT")
-    if has_bom :
-      m.amount_as_per_mar = flt(m.qty) * (is_sub_cont and flt(m.moving_avg_rate)  or flt(m.value_as_per_mar)) * flt(1.00 + (flt(m.scrap)/100)) or 0
-      m.amount_as_per_lpr = flt(m.qty) * (is_sub_cont and (flt(m.value_as_per_lpr) + flt(m.last_purchase_rate)) or flt(m.value_as_per_lpr)) * flt(1.00 + (flt(m.scrap)/100)) or 0
-      m.amount_as_per_sr  = flt(m.qty) * (is_sub_cont and (flt(m.value_as_per_sr)  + flt(m.standard_rate))      or flt(m.value_as_per_mar)) * flt(1.00 + (flt(m.scrap)/100)) or 0
+	def validate_bom_no(self, item, bom_no, idx):
+		"""Validate BOM No of sub-contracted items"""
+		bom = sql("""select name from `tabBill Of Materials` where name = %s and item = %s 
+			and ifnull(is_active, 'No') = 'Yes'	and docstatus < 2 """, (bom_no, item), as_dict =1)
+		if not bom:
+			msgprint("""Incorrect BOM No: %s against item: %s at row no: %s.
+				It may be inactive or cancelled or for some other item."""% (bom_no, item, idx), raise_exception = 1)
+				
 
-    else:
-      m.amount_as_per_mar = flt(m.qty) * flt(m.moving_avg_rate)    * flt(1.00 + (flt(m.scrap)/100)) or 0
-      m.amount_as_per_lpr = flt(m.qty) * flt(m.last_purchase_rate) * flt(1.00 + (flt(m.scrap)/100)) or 0
-      m.amount_as_per_sr = flt(m.qty)  * flt(m.standard_rate)      * flt(1.00 + (flt(m.scrap)/100)) or 0
-    #msgprint(cstr(m.item_code))
-    #msgprint("amount_as_per_mar < ==> " + cstr(m.amount_as_per_mar) + "***" + "amount_as_per_lpr < ==> " + cstr(m.amount_as_per_lpr) + "***" + "amount_as_per_sr < ==> " + cstr(m.amount_as_per_sr) + "***")
-  def calculate_dir_mat(self, m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom = 0, is_sub_cont =0):
-    #msgprint("IN CALCULATE DIR MAT")
-    if has_bom:
-      dir_mat_as_per_mar +=  flt(m.qty) * (is_sub_cont and   flt(m.moving_avg_rate) or flt(m.dir_mat_as_per_mar)) * flt(1.00 + (flt(m.scrap)/100)) or 0
-      dir_mat_as_per_lpr +=  flt(m.qty) * (is_sub_cont and ( flt(m.dir_mat_as_per_lpr)+ flt(m.last_purchase_rate)) or flt(m.dir_mat_as_per_lpr)) * flt(1.00 + (flt(m.scrap)/100)) or 0
-      dir_mat_as_per_sr  +=  flt(m.qty) * (is_sub_cont and ( flt(m.dir_mat_as_per_sr)+ flt(m.standard_rate)     ) or flt(m.dir_mat_as_per_sr)) * flt(1.00 + (flt(m.scrap)/100)) or 0
-    else:
-      dir_mat_as_per_mar += flt(m.amount_as_per_mar)
-      dir_mat_as_per_lpr += flt(m.amount_as_per_lpr)
-      dir_mat_as_per_sr  += flt(m.amount_as_per_sr)
-    #msgprint(cstr(m.item_code))
-    #msgprint("dir_mat_as_per_mar < ==> " + cstr(dir_mat_as_per_mar) + "***" + "dir_mat_as_per_lpr < ==> " + cstr(dir_mat_as_per_lpr) + "***" + "dir_mat_as_per_sr < ==> " + cstr(dir_mat_as_per_sr) + "***")
-    return dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr
 
+	def check_if_item_repeated(self, item, op, check_list):
+		if [cstr(item), cstr(op)] in check_list:
+			msgprint("Item %s has been entered twice against same operation" % d.item_code, raise_exception = 1)
+		else:
+			check_list.append([cstr(item), cstr(op)])
 
-  # Get FIFO Rate from Stack
-  # -------------------------
-  def get_fifo_rate(self, fcfs_bal, qty):
-    if qty:
-      fcfs_val = 0
-      withdraw = flt(qty)
-      while withdraw:
-        if not fcfs_bal:
-          break # nothing in store
 
-        batch = fcfs_bal[0]
 
-        if batch[0] < withdraw:
-          # not enough in current batch, clear batch
-          withdraw -= batch[0]
-          fcfs_val += (flt(batch[0]) * flt(batch[1]))
-          fcfs_bal.pop(0)
-        else:
-          # all from current batch
-          fcfs_val += (flt(withdraw) * flt(batch[1]))
-          batch[0] -= withdraw
-          withdraw = 0
-      fcfs_rate = flt(fcfs_val) / flt(qty)
-      return fcfs_rate
-    else:
-      return fcfs_bal and fcfs_bal[0][1] or 0
+	#----- Document on Save function------
+	def validate(self):
+		self.validate_main_item()
+		self.validate_operations()
+		self.validate_materials()
+		self.validate_operations()
 
 
-  # Get valuation rate
-  # --------------------
-  def get_valuation_rate(self, item_code, qty):
-    # get default warehouse
-    warehouse = sql("select default_warehouse from tabItem where name = %s", item_code)
-    warehouse = warehouse and warehouse[0][0] or ''
-    in_rate = 0
 
-    # get default valuation method
-    val_method = sql("select valuation_method from tabItem where name = %s", item_code)
-    val_method = val_method and val_method[0][0] or ''
-    if not val_method: val_method = get_defaults().has_key('valuation_method') and get_defaults()['valuation_method'] or 'FIFO'
+	def check_recursion(self):
+		""" Check whether reqursion occurs in any bom"""
 
-    if val_method == 'FIFO':
-      if warehouse:
-        bin_obj = get_obj('Warehouse',warehouse).get_bin(item_code)
-        prev_sle = bin_obj.get_prev_sle(nowdate(), (now().split(' ')[1])[:-3])
-        fcfs_stack = prev_sle and prev_sle['fcfs_stack'] and eval(prev_sle['fcfs_stack']) or []
-      else:
-        prev_sle = sql("select fcfs_stack from `tabStock Ledger Entry` where item_code = '%s' and posting_date <= '%s' order by posting_date DESC, posting_time DESC, name DESC limit 1" % (item_code, nowdate()))
-        fcfs_stack = prev_sle and (prev_sle[0][0] and eval(prev_sle[0][0]) or []) or []
-      in_rate = fcfs_stack and self.get_fifo_rate(fcfs_stack, qty) or 0
-    elif val_method == 'Moving Average':
-      in_rate = sql("select ifnull(sum(valuation_rate), 0)/ ifnull(count(*),1) from `tabBin` where item_code = '%s' and ifnull(ma_rate, 0) > 0" % cstr(item_code))
-      in_rate = in_rate and flt(in_rate[0][0]) or 0
-    return in_rate
+		check_list = [['parent', 'bom_no', 'parent'], ['bom_no', 'parent', 'child']]
+		for d in check_list:
+			bom_list, count = [self.doc.name], 0
+			while (len(bom_list) > count ):
+				boms = sql(" select %s from `tabBOM Material` where %s = '%s' " % (d[0], d[1], cstr(bom_list[count])))
+				count = count + 1
+				for b in boms:
+					if b[0] == self.doc.name:
+						msgprint("""Recursion Occured => '%s' cannot be '%s' of '%s'.
+							""" % (cstr(b), cstr(d[2]), self.doc.name), raise_exception = 1)
+					if b[0]:
+						bom_list.append(b[0])
 
 
-  # Get valuation, Last Purchase and Standard Rate
-  # ------------------------------------------------
-  def get_mar_lpr_sr(self, item_code, mar = 0, lpr = 0, sr = 0, qty = 1.00):
-    # get list of warehouse having
-    ma_rate, lpr_rate, sr_rate = 0,0,0
-    if mar:
-      # get recent moving average rate
-      #ma_rate = sql("select ifnull(sum(ma_rate), 0)/ ifnull(count(*),1) from `tabBin` where item_code = '%s' and ifnull(ma_rate, 0) > 0" % cstr(item_code))
-      #ma_rate = flt(ma_rate and ma_rate[0][0]) or 0
-      ma_rate = self.get_valuation_rate(item_code, qty)
 
-    # get recent last purchase rate
-    lpr_rate = lpr and flt(sql("select last_purchase_rate from `tabItem` where name = '%s'" % item_code)[0][0]) or 0.00
-    # get recent standard rate
-    sr_rate = sr and flt(sql("select standard_rate from `tabItem` where name = '%s'" % item_code)[0][0]) or 0.00
-    return ma_rate, lpr_rate, sr_rate
+	def on_update(self):
+		if self.doc.item != cstr(self.doc.name.split('/')[1]):
+			msgprint("Cannot change Item once the Bill Of Material is created.")
+			raise Exception
+		self.check_recursion()
 
-  #checking for duplicate items i.e items that may be entered twice
-  def validate_duplicate_items(self):
-    check_list = []
-    for d in getlist(self.doclist, 'bom_materials'):
-      if cstr(d.item_code) in check_list:
-        msgprint("Item %s has been entered twice. In BOM %s" % (d.item_code, self.doc.name))
-        raise Exception
-      else:
-        check_list.append(cstr(d.item_code))
 
-  #----- Document on Save function------
-  def validate(self):
-    #msgprint(len(getlist(self.doclist, 'bom_materials')))
-    self.validate_main_item()
-    self.validate_duplicate_items()
-    self.calculate_cost(validate = 1)
 
-  def check_recursion(self):
-    check_list = [['parent', 'bom_no', 'parent'], ['bom_no', 'parent', 'child']]
-    for d in check_list:
-      bom_list, count = [self.doc.name], 0
-      while ( len(bom_list) > count ):
-        boms = sql(" select %s from `tabBOM Material` where %s = '%s' " % ( d[0], d[1], cstr(bom_list[count])))
-        count = count + 1
-        for b in boms:
-          if b[0] == self.doc.name:
-            msgprint("Recursion Occured:=>  '%s' cannot be '%s' of '%s'." % ( cstr(b), cstr(d[2]), cstr(self.doc.name)))
-            raise Exception
-          if b[0]:
-            bom_list.append(b[0])
+	def add_to_flat_bom_detail(self, is_submit = 0):
+		"Add items to Flat BOM table"
+		self.doc.clear_table(self.doclist, 'flat_bom_details', 1)
+		for d in self.cur_flat_bom_items:
+			ch = addchild(self.doc, 'flat_bom_details', 'Flat BOM Detail', 1, self.doclist)
+			for i in d.keys():
+				ch.fields[i] = d[i]
+			ch.docstatus = is_submit
+			ch.save(1)
 
-  def on_update(self):
-    if self.doc.item != cstr(self.doc.name.split('/')[1]):
-      msgprint("Cannot change Item once the Bill Of Material is created.")
-      raise Exception
-    self.check_recursion()
+		self.doc.save()
 
 
-# ********************************************** Submit *************************************************************
 
-  # Add Flat BOM Details
-  # -----------------------
-  def add_to_flat_bom_detail(self, is_submit = 0):
-    self.doc.clear_table(self.doclist, 'flat_bom_details', 1)
-    fb_lbl = {'item_code': 0, 'description': 1, 'qty': 2, 'stock_uom': 3, 'moving_avg_rate': 4,'amount_as_per_mar': 5, 'last_purchase_rate': 6, 'amount_as_per_lpr':7,'standard_rate':8,'amount_as_per_sr':9,'qty_consumed_per_unit': 10, 'parent_bom': 11, 'bom_mat_no': 12, 'is_pro_applicable': 13}
-    for d in self.cur_flat_bom_items:
-      fb_child = addchild(self.doc, 'flat_bom_details', 'Flat BOM Detail', 1, self.doclist)
-      for i in fb_lbl:
-        fb_child.fields[i] = d[fb_lbl[i]]
-      fb_child.docstatus = is_submit
-      fb_child.save(1)
-    self.doc.save()
+	def get_child_flat_bom_items(self, bom_no, qty):
+		""" Add all items from Flat BOM of child BOM"""
 
+		child_fb_items = sql("""select item_code, description, stock_uom, qty, rate, amount, parent_bom, mat_detail_no, qty_consumed_per_unit 
+			from `tabFlat BOM Detail` where parent = '%s' and docstatus = 1""" % bom_no, as_dict = 1)
+		for d in child_fb_items:
+			self.cur_flat_bom_items.append({
+				'item_code'				: d['item_code'], 
+				'description'			: d['description'], 
+				'stock_uom'				: d['stock_uom'], 
+				'qty'					: flt(d['qty_consumed_per_unit'])*qty,
+				'rate'					: flt(d['rate']), 
+				'amount'				: flt(d['amount']),
+				'parent_bom'			: d['parent_bom'],
+				'mat_detail_no'			: d['mat_detail_no'],
+				'qty_consumed_per_unit' : flt(d['qty_consumed_per_unit'])*qty/flt(self.doc.quantity)
 
-  #Get Child Flat BOM Items
-  #----------------------------------------
-  def get_child_flat_bom_items(self, item, d):
+			})
 
-    child_flat_bom_items=[]
 
-    child_flat_bom_items = sql("select fbom.item_code, fbom.description, fbom.qty_consumed_per_unit, fbom.stock_uom, fbom.moving_avg_rate, fbom.last_purchase_rate, fbom.standard_rate, '%s' as parent_bom, fbom.bom_mat_no, 'No' as is_pro_applicable from `tabFlat BOM Detail` fbom,`tabBill Of Materials` bom where fbom.parent=bom.name and fbom.parent = '%s' and fbom.is_pro_applicable = 'No' and bom.docstatus = 1" % ( d.bom_no, cstr(d.bom_no)))
-    self.cur_flat_bom_items.append([d.item_code, d.description, flt(d.qty), d.stock_uom, flt(d.moving_avg_rate), flt(d.amount_as_per_mar), flt(d.last_purchase_rate), flt(d.amount_as_per_lpr), flt(d.standard_rate), flt(d.amount_as_per_sr), flt(d.qty_consumed_per_unit), (item[0]['is_sub_contracted_item'] == 'Yes') and d.parent or d.bom_no, d.name, (item[0]['is_sub_contracted_item'] == 'Yes') and 'No' or 'Yes'])
-    return child_flat_bom_items
 
 
-  # Get Current Flat BOM Items
-  # -----------------------------
-  def get_current_flat_bom_items(self):
+	# Get Current Flat BOM Items
+	# -----------------------------
+	def get_current_flat_bom_items(self):
+		""" Get all raw materials including items from child bom"""
+		self.cur_flat_bom_items = []
+		for d in getlist(self.doclist, 'bom_materials'):
+			item = {}
+			if d.bom_no:
+				item = sql("select is_sub_contracted_item from `tabItem` where name = '%s'" % d.item_code)
 
-    self.cur_flat_bom_items = []
+			self.cur_flat_bom_items.append({
+				'item_code'				: d.item_code, 
+				'description'			: d.description, 
+				'stock_uom'				: d.stock_uom, 
+				'qty'					: flt(d.qty),
+				'rate'					: flt(d.rate), 
+				'amount'				: flt(d.amount),
+				'parent_bom'			: d.parent, #item and item[0][0]=='No' and d.bom_no or d.parent, 
+				'mat_detail_no'			: d.name,
+				'qty_consumed_per_unit' : flt(d.qty_consumed_per_unit)
+			})
+			if d.bom_no:
+				self.get_child_flat_bom_items(d.bom_no, d.qty)
 
-    cfb_lbl = {'item_code': 0, 'description': 1, 'qty_consumed_per_unit': 2, 'stock_uom': 3, 'moving_avg_rate': 4, 'last_purchase_rate': 5, 'standard_rate': 6, 'parent_bom': 7, 'bom_mat_no': 8, 'is_pro_applicable': 9}
 
-    for d in getlist(self.doclist, 'bom_materials'):
 
-      if d.bom_no:
-        item = sql("select is_sub_contracted_item, is_pro_applicable from `tabItem` where name = '%s'" % d.item_code, as_dict = 1)
-        child_flat_bom_items = self.get_child_flat_bom_items(item,d)
+	def update_flat_bom_engine(self, is_submit = 0):
+		""" Update Flat BOM, following will be correct data"""
+		self.get_current_flat_bom_items()
+		self.add_to_flat_bom_detail(is_submit)
 
-        for c in child_flat_bom_items:
-          self.cur_flat_bom_items.append([c[cfb_lbl['item_code']], c[cfb_lbl['description']], flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]), c[cfb_lbl['stock_uom']], flt(c[cfb_lbl['moving_avg_rate']]), flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]) * flt(c[cfb_lbl['moving_avg_rate']]) ,flt(c[cfb_lbl['last_purchase_rate']]), flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]) * flt(c[cfb_lbl['last_purchase_rate']]), flt(c[cfb_lbl['standard_rate']]), flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]) * flt(c[cfb_lbl['standard_rate']]), flt(d.qty_consumed_per_unit) * flt(c[cfb_lbl['qty_consumed_per_unit']]), c[cfb_lbl['parent_bom']], c[cfb_lbl['bom_mat_no']], c[cfb_lbl['is_pro_applicable']]])
-      else:
-        # add purchase_items from bom material to the child_flat_bom_items
-        self.cur_flat_bom_items.append([d.item_code, d.description, flt(d.qty), d.stock_uom, flt(d.moving_avg_rate), flt(d.amount_as_per_mar), flt(d.last_purchase_rate), flt(d.amount_as_per_lpr), flt(d.standard_rate), flt(d.amount_as_per_sr), flt(d.qty_consumed_per_unit), d.parent, d.name, 'No' ])
 
-  # Update Flat BOM Engine
-  # ------------------------
-  def update_flat_bom_engine(self, is_submit = 0):
-    # following will be correct data
-    # get correct / updated flat bom data
-    self.get_current_flat_bom_items()
-    # insert to curr flat bom data
-    self.add_to_flat_bom_detail(is_submit)
+	def get_parent_bom_list(self, bom_no):
+		p_bom = sql("select parent from `tabBOM Material` where bom_no = '%s'" % bom_no)
+		return p_bom and [i[0] for i in p_bom] or []
 
 
-  # On Submit
-  # -----------
-  def on_submit(self):
-    self.update_flat_bom_engine(1)
+	def on_submit(self):
+		self.manage_default_bom()
+		self.update_flat_bom_engine(1)
 
 
-  def get_parent_bom_list(self, bom_no):
-    p_bom = sql("select parent from `tabBOM Material` where bom_no = '%s'" % bom_no)
-    return p_bom and [i[0] for i in p_bom] or []
+	def on_cancel(self):
+		# check if used in any other bom
+		par = sql("""select t1.parent from `tabBOM Material` t1, `tabBill Of Materials` t2 
+			where t1.parent = t2.name and t1.bom_no = %s and t1.docstatus = 1 and t2.is_active = 'Yes'""", self.doc.name)
+		if par:
+			msgprint("BOM can not be cancelled, as it is a child item in following active BOM %s"% [d[0] for d in par])
+			raise Exception
diff --git a/erpnext/production/doctype/bill_of_materials/bill_of_materials.txt b/erpnext/production/doctype/bill_of_materials/bill_of_materials.txt
index 3713667..bbb1cd9 100644
--- a/erpnext/production/doctype/bill_of_materials/bill_of_materials.txt
+++ b/erpnext/production/doctype/bill_of_materials/bill_of_materials.txt
@@ -5,14 +5,14 @@
 	{
 		'creation': '2010-08-08 17:08:52',
 		'docstatus': 0,
-		'modified': '2011-11-09 12:47:50',
+		'modified': '2012-01-11 14:33:04',
 		'modified_by': 'Administrator',
 		'owner': 'Administrator'
 	},
 
 	# These values are common for all DocType
 	{
-		'_last_update': '1319016431',
+		'_last_update': '1326272478',
 		'allow_attach': 0,
 		'allow_copy': 0,
 		'allow_email': 0,
@@ -32,11 +32,11 @@
 		'name': '__common__',
 		'read_only': 0,
 		'search_fields': 'item',
-		'section_style': 'Tabbed',
+		'section_style': 'Simple',
 		'server_code_error': ' ',
 		'show_in_menu': 0,
 		'subject': '%(item)s',
-		'version': 171
+		'version': 194
 	},
 
 	# These values are common for all DocField
@@ -134,86 +134,10 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'trash_reason',
-		'fieldtype': 'Small Text',
-		'label': 'Trash Reason',
-		'oldfieldname': 'trash_reason',
-		'oldfieldtype': 'Small Text',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'HTML',
-		'label': 'TreeView1',
-		'oldfieldtype': 'HTML',
-		'options': '<div style=\'border: 1px solid #CCF; padding: 8px;margin-bottom: 8px;\'><div class=\'link_type\' onclick=\'loadpage("Bill of Materials"); \'>Go To BOM Tree View</div></div>',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'Section Break',
-		'oldfieldtype': 'Section Break',
-		'options': 'Simple',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'allow_on_submit': 1,
-		'colour': 'White:FFF',
-		'doctype': 'DocField',
-		'fieldtype': 'Button',
-		'label': 'Set as Default BOM',
-		'oldfieldtype': 'Button',
-		'permlevel': 0,
-		'trigger': 'Client'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldtype': 'Column Break',
 		'oldfieldtype': 'Column Break',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'allow_on_submit': 1,
-		'colour': 'White:FFF',
-		'doctype': 'DocField',
-		'fieldtype': 'Button',
-		'hidden': 1,
-		'label': 'Activate BOM',
-		'oldfieldtype': 'Button',
 		'permlevel': 0,
-		'trigger': 'Client'
-	},
-
-	# DocField
-	{
-		'allow_on_submit': 1,
-		'colour': 'White:FFF',
-		'doctype': 'DocField',
-		'fieldtype': 'Button',
-		'hidden': 1,
-		'label': 'Inactivate BOM',
-		'oldfieldtype': 'Button',
-		'permlevel': 0,
-		'trigger': 'Client'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'Section Break',
-		'label': 'Details',
-		'oldfieldtype': 'Section Break',
-		'permlevel': 0
+		'width': '50%'
 	},
 
 	# DocField
@@ -236,18 +160,6 @@
 
 	# DocField
 	{
-		'doctype': 'DocField',
-		'fieldname': 'description',
-		'fieldtype': 'Text',
-		'label': 'Description',
-		'oldfieldname': 'description',
-		'oldfieldtype': 'Text',
-		'permlevel': 0,
-		'width': '300px'
-	},
-
-	# DocField
-	{
 		'colour': 'White:FFF',
 		'description': 'Total quantity of items for which raw materials required and operations done will be defined',
 		'doctype': 'DocField',
@@ -272,30 +184,22 @@
 
 	# DocField
 	{
-		'colour': 'White:FFF',
 		'doctype': 'DocField',
-		'fieldname': 'is_active',
-		'fieldtype': 'Select',
-		'label': 'Is Active',
-		'no_copy': 1,
-		'oldfieldname': 'is_active',
-		'oldfieldtype': 'Select',
-		'options': '\nYes\nNo',
+		'fieldname': 'description',
+		'fieldtype': 'Text',
+		'label': 'Description',
+		'oldfieldname': 'description',
+		'oldfieldtype': 'Text',
 		'permlevel': 0,
-		'reqd': 1
+		'width': '300px'
 	},
 
 	# DocField
 	{
-		'colour': 'White:FFF',
 		'doctype': 'DocField',
-		'fieldname': 'is_default',
-		'fieldtype': 'Check',
-		'label': 'Is Default',
-		'no_copy': 1,
-		'oldfieldname': 'is_default',
-		'oldfieldtype': 'Check',
-		'permlevel': 1
+		'fieldtype': 'Column Break',
+		'permlevel': 0,
+		'width': '50%'
 	},
 
 	# DocField
@@ -315,6 +219,61 @@
 
 	# DocField
 	{
+		'allow_on_submit': 1,
+		'colour': 'White:FFF',
+		'doctype': 'DocField',
+		'fieldname': 'is_active',
+		'fieldtype': 'Select',
+		'hidden': 0,
+		'label': 'Is Active',
+		'no_copy': 1,
+		'oldfieldname': 'is_active',
+		'oldfieldtype': 'Select',
+		'options': '\nYes\nNo',
+		'permlevel': 0,
+		'reqd': 1
+	},
+
+	# DocField
+	{
+		'allow_on_submit': 1,
+		'colour': 'White:FFF',
+		'doctype': 'DocField',
+		'fieldname': 'is_default',
+		'fieldtype': 'Check',
+		'label': 'Is Default',
+		'no_copy': 1,
+		'oldfieldname': 'is_default',
+		'oldfieldtype': 'Check',
+		'permlevel': 0
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldname': 'maintained_by',
+		'fieldtype': 'Data',
+		'label': 'Maintained By',
+		'oldfieldname': 'maintained_by',
+		'oldfieldtype': 'Data',
+		'permlevel': 0
+	},
+
+	# DocField
+	{
+		'colour': 'White:FFF',
+		'doctype': 'DocField',
+		'fieldname': 'remarks',
+		'fieldtype': 'Text',
+		'label': 'Remarks',
+		'no_copy': 1,
+		'oldfieldname': 'remarks',
+		'oldfieldtype': 'Text',
+		'permlevel': 0
+	},
+
+	# DocField
+	{
 		'doctype': 'DocField',
 		'fieldtype': 'Section Break',
 		'label': 'Operations',
@@ -325,7 +284,7 @@
 	# DocField
 	{
 		'colour': 'White:FFF',
-		'description': 'Specify the operations performed and give a unique Operation no to your operations. Select the workstation which is nothing but machinery where this operation would be performed on raw materials. Hour rate will be fetched from the Workstation master. Operation time will be entered manually. Operating cost will be calculated once the Bill of Material is saved.',
+		'description': 'Specify the operations, operating cost and give a unique Operation no to your operations.',
 		'doctype': 'DocField',
 		'fieldname': 'bom_operations',
 		'fieldtype': 'Table',
@@ -370,92 +329,55 @@
 
 	# DocField
 	{
-		'colour': 'White:FFF',
 		'doctype': 'DocField',
-		'fieldname': 'remarks',
-		'fieldtype': 'Text',
-		'label': 'Remarks',
-		'no_copy': 1,
-		'oldfieldname': 'remarks',
-		'oldfieldtype': 'Text',
+		'fieldtype': 'Column Break',
+		'permlevel': 0,
+		'width': '50%'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldname': 'rm_cost_as_per',
+		'fieldtype': 'Select',
+		'label': 'Consider Raw Material Cost As Per',
+		'options': 'Valuation Rate\nLast Purchase Rate\nStandard Rate',
 		'permlevel': 0
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'cost_as_per_mar',
-		'fieldtype': 'Currency',
-		'label': 'Cost As Per Valuation Rate',
-		'oldfieldname': 'cost_as_per_mar',
-		'oldfieldtype': 'Currency',
+		'fieldname': 'costing_date',
+		'fieldtype': 'Date',
+		'label': 'Costing Date',
 		'permlevel': 1
 	},
 
 	# DocField
 	{
+		'allow_on_submit': 1,
 		'doctype': 'DocField',
-		'fieldname': 'cost_as_per_lpr',
-		'fieldtype': 'Currency',
-		'label': 'Cost As Per LPR',
-		'oldfieldname': 'cost_as_per_lpr',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
+		'fieldtype': 'Button',
+		'label': 'Update Cost as on today',
+		'options': 'calculate_cost',
+		'permlevel': 0
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'cost_as_per_sr',
-		'fieldtype': 'Currency',
-		'label': 'Cost As Per SR',
-		'oldfieldname': 'cost_as_per_sr',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'colour': 'White:FFF',
-		'doctype': 'DocField',
-		'fieldname': 'cost_as_on',
-		'fieldtype': 'Data',
-		'label': 'Cost as on',
-		'oldfieldname': 'cost_as_on',
-		'oldfieldtype': 'Data',
-		'permlevel': 1
+		'fieldtype': 'Column Break',
+		'permlevel': 0,
+		'width': '50%'
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'dir_mat_as_per_mar',
-		'fieldtype': 'Currency',
-		'label': 'Direct Material As Per Valuation',
-		'oldfieldname': 'dir_mat_as_per_mar',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'dir_mat_as_per_lpr',
-		'fieldtype': 'Currency',
-		'label': 'Direct Material As Per LPR',
-		'oldfieldname': 'dir_mat_as_per_lpr',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'dir_mat_as_per_sr',
-		'fieldtype': 'Currency',
-		'label': 'Direct Material As Per SR',
-		'oldfieldname': 'dir_mat_as_per_sr',
-		'oldfieldtype': 'Currency',
+		'fieldname': 'raw_material_cost',
+		'fieldtype': 'Float',
+		'label': 'Raw Material Cost',
 		'permlevel': 1
 	},
 
@@ -463,22 +385,18 @@
 	{
 		'doctype': 'DocField',
 		'fieldname': 'operating_cost',
-		'fieldtype': 'Currency',
+		'fieldtype': 'Float',
 		'label': 'Operating Cost',
-		'oldfieldname': 'operating_cost',
-		'oldfieldtype': 'Currency',
 		'permlevel': 1
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'maintained_by',
-		'fieldtype': 'Data',
-		'label': 'Maintained By',
-		'oldfieldname': 'maintained_by',
-		'oldfieldtype': 'Data',
-		'permlevel': 0
+		'fieldname': 'total_cost',
+		'fieldtype': 'Float',
+		'label': 'Total Cost',
+		'permlevel': 1
 	},
 
 	# DocField
@@ -486,19 +404,9 @@
 		'doctype': 'DocField',
 		'fieldtype': 'Section Break',
 		'hidden': 1,
-		'label': 'BOM Report',
-		'oldfieldtype': 'Section Break',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'Section Break',
-		'hidden': 0,
-		'label': 'Flat BOM',
-		'oldfieldtype': 'Section Break',
-		'permlevel': 0
+		'options': 'Simple',
+		'permlevel': 0,
+		'print_hide': 0
 	},
 
 	# DocField
@@ -508,12 +416,25 @@
 		'doctype': 'DocField',
 		'fieldname': 'flat_bom_details',
 		'fieldtype': 'Table',
-		'hidden': 0,
+		'hidden': 1,
 		'label': 'Flat BOM Detail',
 		'no_copy': 1,
 		'oldfieldname': 'flat_bom_details',
 		'oldfieldtype': 'Table',
 		'options': 'Flat BOM Detail',
-		'permlevel': 0
+		'permlevel': 0,
+		'print_hide': 1
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldname': 'trash_reason',
+		'fieldtype': 'Small Text',
+		'hidden': 1,
+		'label': 'Trash Reason',
+		'oldfieldname': 'trash_reason',
+		'oldfieldtype': 'Small Text',
+		'permlevel': 1
 	}
 ]
\ No newline at end of file
diff --git a/erpnext/production/doctype/bom_control/bom_control.py b/erpnext/production/doctype/bom_control/bom_control.py
index 6b0987b..a880d72 100644
--- a/erpnext/production/doctype/bom_control/bom_control.py
+++ b/erpnext/production/doctype/bom_control/bom_control.py
@@ -16,87 +16,90 @@
 
 # -----------------------------------------------------------------------------------------
 
-
+	
 class DocType:
-  def __init__(self, doc, doclist):
-    self.doc = doc
-    self.doclist = doclist
-
-  def get_item_group(self):
-    ret = sql("select name from `tabItem Group` ")
-    item_group = []
-    for r in ret:
-      item =sql("select t1.name from `tabItem` t1, `tabBill Of Materials` t2 where t2.item = t1.name and t1.item_group = '%s' " % (r[0]))
-      if item and item[0][0]:
-        item_group.append(r[0])
-    return '~~~'.join([r for r in item_group])
-
-  def get_item_code(self,item_group):
-    # here Bill Of Materials docstatus = 1 and is_active ='yes' condition is not given because some bom is under construction
-    # that is it is still in saved mode and they want see till where they have reach.
-    ret = sql("select distinct t1.name from `tabItem` t1, `tabBill Of Materials` t2 where t2.item = t1.name and t1.item_group = '%s' " % (item_group))
-    return '~~~'.join([r[0] for r in ret])
-
-  def get_bom_no(self,item_code):
-    ret = sql("select name from `tabBill Of Materials` where item = '%s' " % (item_code))
-    return '~~~'.join([r[0] for r in ret])
-
-  def get_operations(self,bom_no):
-    # reply = [ 'Operation',operation_no, opn_description,BOM NO     , workstation, hour_rate,  time_in_minutes,  Total Direct Material, Total Operating Cost, Cost]
-    # reply = [ 0           ,  1         ,    2          ,3          , 4          ,  5        ,  6             ,         7            ,   8                 ,9                     , 10                  , 11  ]
-    ret = sql("select operation_no,opn_description,workstation,hour_rate,time_in_mins from `tabBOM Operation` where parent = %s", bom_no, as_dict = 1)
-    cost = sql("select dir_mat_as_per_mar , operating_cost , cost_as_per_mar from `tabBill Of Materials` where name = %s", bom_no, as_dict = 1)
-
-    # Validate the BOM ENTRIES
-    #check = get_obj('Bill Of Materials', bom_no, with_children =1).validate()
-    reply = []
-
-    if ret:
-      for r in ret:
-        reply.append(['operation',cint(r['operation_no']), r['opn_description'] or '','%s'% bom_no,r['workstation'],flt(r['hour_rate']),flt(r['time_in_mins']),0,0,0])
-
-      reply[0][7]= flt(cost[0]['dir_mat_as_per_mar'])
-      reply[0][8]=flt(cost[0]['operating_cost'])
-      reply[0][9]=flt(cost[0]['cost_as_per_mar'])
-    return reply
-
-  def get_item_bom(self,data):
-    # reply = ['item_bom',item_code,description,  BOM NO , qty, uom , scrap  ,m_avg_r  or value, 1 or 0]
-    # reply = [ 0        ,  1      ,       2   ,   3     , 4  , 5   ,  6     ,   7             ,   8   ]
-    data = eval(data)
-    reply = []
-    ret = sql("select item_code,description,bom_no,qty,scrap,stock_uom,value_as_per_mar,moving_avg_rate from `tabBOM Material` where parent = '%s' and operation_no = '%s'" % (data['bom_no'],data['op_no']), as_dict =1 )
-
-    for r in ret:
-      item = sql("select is_manufactured_item, is_sub_contracted_item from `tabItem` where name = '%s'" % r['item_code'], as_dict=1)
-      if not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item'] =='Yes':
-        #msgprint("IS_PURCHASE")
-        #if item is not manufactured or it is not sub-contracted
-        reply.append([ 'item_bom', r['item_code'] or '', r['description'] or '', r['bom_no'] or '', flt(r['qty']) or 0, r['stock_uom'] or '', flt(r['scrap']) or 0, flt(r['moving_avg_rate']) or 0, 1])
-      else:
-        #msgprint("IS_NOT_PURCHASE")
-        # if it is manufactured or sub_contracted this will be considered(here item can be purchase item)
-        reply.append([ 'item_bom', r['item_code'] or '', r['description'] or '', r['bom_no'] or '', flt(r['qty']) or 0, r['stock_uom'] or '', flt(r['scrap']) or 0, flt(r['value_as_per_mar']) or 0, 0])
-    return reply
+	def __init__(self, doc, doclist):
+		self.doc = doc
+		self.doclist = doclist
 
 
-  #------------- Wrapper Code --------------
-  # BOM TREE
-  def calculate_cost( self, bom_no):
-    main_bom_list = get_obj(dt = 'Production Control').traverse_bom_tree( bom_no = bom_no, qty = 1, calculate_cost = 1)
-    main_bom_list.reverse()
-    for bom in main_bom_list:
-      bom_obj = get_obj('Bill Of Materials', bom, with_children = 1)
-      bom_obj.calculate_cost(validate = 0)
-      bom_obj.doc.save()
-    return 'calculated'
+
+	def get_item_group(self):
+		ret = sql("select name from `tabItem Group` ")
+		item_group = []
+		for r in ret:
+			item =sql("select t1.name from `tabItem` t1, `tabBill Of Materials` t2 where t2.item = t1.name and t1.item_group = '%s' " % (r[0]))
+			if item and item[0][0]:
+				item_group.append(r[0])
+		return '~~~'.join([r for r in item_group])
 
 
-  def get_bom_tree_list(self,args):
-    arg = eval(args)
-    i =[]
-    for a in sql("select t1.name from `tabBill Of Materials` t1, `tabItem` t2 where t2.item_group like '%s' and t1.item like '%s'"%(arg['item_group'] +'%',arg['item_code'] + '%')):
-      if a[0] not in i:
-        i.append(a[0])
-    return i
-#    return [s[0] for s in sql("select t1.name from `tabBill Of Materials` t1, `tabItem` t2 where t2.item_group like '%s'  and t1.item like '%s' " %(arg['item_group']+'%',arg['item_code'+'%'])]
\ No newline at end of file
+
+	def get_item_code(self,item_group):
+		""" here Bill Of Materials docstatus = 1 and is_active ='yes' condition is not given because some bom
+			is under construction that is it is still in saved mode and they want see till where they have reach.
+		"""
+		ret = sql("select distinct t1.name from `tabItem` t1, `tabBill Of Materials` t2 where t2.item = t1.name and t1.item_group = '%s' " % (item_group))
+		return '~~~'.join([r[0] for r in ret])
+
+
+
+	def get_bom_no(self,item_code):
+		ret = sql("select name from `tabBill Of Materials` where item = '%s' " % (item_code))
+		return '~~~'.join([r[0] for r in ret])
+
+
+
+	def get_operations(self,bom_no):
+		ret = sql("select operation_no,opn_description,workstation,hour_rate,time_in_mins from `tabBOM Operation` where parent = %s", bom_no, as_dict = 1)
+		cost = sql("select dir_mat_as_per_mar , operating_cost , cost_as_per_mar from `tabBill Of Materials` where name = %s", bom_no, as_dict = 1)
+
+		# Validate the BOM ENTRIES
+		reply = []
+
+		if ret:
+			for r in ret:
+				reply.append(['operation',cint(r['operation_no']), r['opn_description'] or '','%s'% bom_no,r['workstation'],flt(r['hour_rate']),flt(r['time_in_mins']),0,0,0])
+
+			reply[0][7]= flt(cost[0]['dir_mat_as_per_mar'])
+			reply[0][8]=flt(cost[0]['operating_cost'])
+			reply[0][9]=flt(cost[0]['cost_as_per_mar'])
+		return reply
+
+
+
+	def get_item_bom(self,data):
+		data = eval(data)
+		reply = []
+		ret = sql("select item_code,description,bom_no,qty,scrap,stock_uom,value_as_per_mar,moving_avg_rate from `tabBOM Material` where parent = '%s' and operation_no = '%s'" % (data['bom_no'],data['op_no']), as_dict =1 )
+
+		for r in ret:
+			item = sql("select is_manufactured_item, is_sub_contracted_item from `tabItem` where name = '%s'" % r['item_code'], as_dict=1)
+			if not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item'] =='Yes':
+				#if item is not manufactured or it is not sub-contracted
+				reply.append([ 'item_bom', r['item_code'] or '', r['description'] or '', r['bom_no'] or '', flt(r['qty']) or 0, r['stock_uom'] or '', flt(r['scrap']) or 0, flt(r['moving_avg_rate']) or 0, 1])
+			else:
+				# if it is manufactured or sub_contracted this will be considered(here item can be purchase item)
+				reply.append([ 'item_bom', r['item_code'] or '', r['description'] or '', r['bom_no'] or '', flt(r['qty']) or 0, r['stock_uom'] or '', flt(r['scrap']) or 0, flt(r['value_as_per_mar']) or 0, 0])
+		return reply
+
+
+
+	#------------- Wrapper Code --------------
+	def calculate_cost(self, bom_no):
+		main_bom_list = get_obj('Production Control').traverse_bom_tree( bom_no = bom_no, qty = 1, calculate_cost = 1)
+		main_bom_list.reverse()
+		for bom in main_bom_list:
+			bom_obj = get_obj('Bill Of Materials', bom, with_children = 1)
+			bom_obj.calculate_cost()
+		return 'calculated'
+
+
+
+	def get_bom_tree_list(self,args):
+		arg = eval(args)
+		i =[]
+		for a in sql("select t1.name from `tabBill Of Materials` t1, `tabItem` t2 where t2.item_group like '%s' and t1.item like '%s'"%(arg['item_group'] +'%',arg['item_code'] + '%')):
+			if a[0] not in i:
+				i.append(a[0])
+		return i
diff --git a/erpnext/production/doctype/bom_material/bom_material.txt b/erpnext/production/doctype/bom_material/bom_material.txt
index 436519e..ff7c590 100644
--- a/erpnext/production/doctype/bom_material/bom_material.txt
+++ b/erpnext/production/doctype/bom_material/bom_material.txt
@@ -5,14 +5,15 @@
 	{
 		'creation': '2010-08-08 17:08:53',
 		'docstatus': 0,
-		'modified': '2010-09-20 14:06:57',
-		'modified_by': 'umair@iwebnotes.com',
+		'modified': '2011-12-27 14:49:54',
+		'modified_by': 'Administrator',
 		'owner': 'Administrator'
 	},
 
 	# These values are common for all DocType
 	{
 		'colour': 'White:FFF',
+		'default_print_format': 'Standard',
 		'doctype': 'DocType',
 		'istable': 1,
 		'module': 'Production',
@@ -20,7 +21,7 @@
 		'section_style': 'Simple',
 		'server_code_error': ' ',
 		'show_in_menu': 0,
-		'version': 22
+		'version': 26
 	},
 
 	# These values are common for all DocField
@@ -52,7 +53,6 @@
 	# DocPerm
 	{
 		'doctype': 'DocPerm',
-		'idx': 1,
 		'permlevel': 0,
 		'write': 1
 	},
@@ -60,7 +60,6 @@
 	# DocPerm
 	{
 		'doctype': 'DocPerm',
-		'idx': 2,
 		'permlevel': 1
 	},
 
@@ -69,7 +68,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'operation_no',
 		'fieldtype': 'Data',
-		'idx': 1,
 		'label': 'Operation No',
 		'oldfieldname': 'operation_no',
 		'oldfieldtype': 'Data',
@@ -82,7 +80,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'item_code',
 		'fieldtype': 'Link',
-		'idx': 2,
 		'in_filter': 1,
 		'label': 'Item Code',
 		'oldfieldname': 'item_code',
@@ -99,7 +96,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'bom_no',
 		'fieldtype': 'Link',
-		'idx': 3,
 		'in_filter': 1,
 		'label': 'BOM No',
 		'oldfieldname': 'bom_no',
@@ -115,48 +111,8 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'description',
-		'fieldtype': 'Text',
-		'idx': 4,
-		'label': 'Description',
-		'oldfieldname': 'description',
-		'oldfieldtype': 'Text',
-		'permlevel': 1,
-		'reqd': 0,
-		'width': '300px'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'scrap',
-		'fieldtype': 'Currency',
-		'idx': 6,
-		'label': 'Scrap %',
-		'oldfieldname': 'scrap',
-		'oldfieldtype': 'Currency',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'dir_mat_as_per_mar',
-		'fieldtype': 'Currency',
-		'idx': 8,
-		'label': 'Direct Material As Per Valuation Rate',
-		'oldfieldname': 'dir_mat_as_per_mar',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1,
-		'width': '150px'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldname': 'qty',
-		'fieldtype': 'Currency',
-		'idx': 9,
+		'fieldtype': 'Float',
 		'label': 'Qty',
 		'oldfieldname': 'qty',
 		'oldfieldtype': 'Currency',
@@ -168,45 +124,8 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'dir_mat_as_per_lpr',
-		'fieldtype': 'Currency',
-		'idx': 9,
-		'label': 'Direct Material As Per LPR',
-		'oldfieldname': 'dir_mat_as_per_lpr',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'dir_mat_as_per_sr',
-		'fieldtype': 'Currency',
-		'idx': 10,
-		'label': 'Direct Material As Per SR',
-		'oldfieldname': 'dir_mat_as_per_sr',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'operating_cost',
-		'fieldtype': 'Currency',
-		'idx': 11,
-		'label': 'Operating Cost',
-		'oldfieldname': 'operating_cost',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldname': 'stock_uom',
 		'fieldtype': 'Data',
-		'idx': 12,
 		'label': 'Stock UOM',
 		'oldfieldname': 'stock_uom',
 		'oldfieldtype': 'Data',
@@ -217,59 +136,18 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'value_as_per_mar',
-		'fieldtype': 'Currency',
-		'idx': 12,
-		'label': 'Value As Per Valuation Rate',
-		'oldfieldname': 'value_as_per_mar',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1,
-		'width': '150px'
+		'fieldname': 'rate',
+		'fieldtype': 'Float',
+		'label': 'Rate',
+		'permlevel': 0
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'value_as_per_lpr',
-		'fieldtype': 'Currency',
-		'idx': 13,
-		'label': 'Value As Per LPR',
-		'oldfieldname': 'value_as_per_lpr',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'value_as_per_sr',
-		'fieldtype': 'Currency',
-		'idx': 14,
-		'label': 'Value As Per SR',
-		'oldfieldname': 'value_as_per_sr',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'moving_avg_rate',
-		'fieldtype': 'Currency',
-		'idx': 15,
-		'label': 'Valuation Rate',
-		'oldfieldname': 'moving_avg_rate',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'amount_as_per_mar',
-		'fieldtype': 'Currency',
-		'idx': 16,
-		'label': 'Amount As Per Valuation Rate',
+		'fieldname': 'amount',
+		'fieldtype': 'Float',
+		'label': 'Amount',
 		'oldfieldname': 'amount_as_per_mar',
 		'oldfieldtype': 'Currency',
 		'permlevel': 1,
@@ -279,50 +157,26 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'last_purchase_rate',
+		'fieldname': 'scrap',
 		'fieldtype': 'Currency',
-		'idx': 17,
-		'label': 'Last Purchase Rate',
-		'oldfieldname': 'last_purchase_rate',
+		'label': 'Scrap %',
+		'oldfieldname': 'scrap',
 		'oldfieldtype': 'Currency',
-		'permlevel': 1,
-		'width': '150px'
+		'permlevel': 0,
+		'print_hide': 1
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'amount_as_per_lpr',
-		'fieldtype': 'Currency',
-		'idx': 18,
-		'label': 'Amount As Per LPR',
-		'oldfieldname': 'amount_as_per_lpr',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'standard_rate',
-		'fieldtype': 'Currency',
-		'idx': 19,
-		'label': 'Standard Rate',
-		'oldfieldname': 'standard_rate',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'amount_as_per_sr',
-		'fieldtype': 'Currency',
-		'idx': 20,
-		'label': 'Amount As Per SR',
-		'oldfieldname': 'amount_as_per_sr',
-		'oldfieldtype': 'Currency',
-		'permlevel': 1
+		'fieldname': 'description',
+		'fieldtype': 'Text',
+		'label': 'Item Description',
+		'oldfieldname': 'description',
+		'oldfieldtype': 'Text',
+		'permlevel': 0,
+		'reqd': 0,
+		'width': '250px'
 	},
 
 	# DocField
@@ -330,10 +184,11 @@
 		'doctype': 'DocField',
 		'fieldname': 'qty_consumed_per_unit',
 		'fieldtype': 'Float',
-		'idx': 21,
+		'hidden': 1,
 		'label': 'Qty Consumed Per Unit',
 		'oldfieldname': 'qty_consumed_per_unit',
 		'oldfieldtype': 'Float',
-		'permlevel': 1
+		'permlevel': 1,
+		'print_hide': 1
 	}
-]
+]
\ No newline at end of file
diff --git a/erpnext/production/doctype/bom_operation/bom_operation.txt b/erpnext/production/doctype/bom_operation/bom_operation.txt
index 9bc7f9e..f3cc659 100644
--- a/erpnext/production/doctype/bom_operation/bom_operation.txt
+++ b/erpnext/production/doctype/bom_operation/bom_operation.txt
@@ -5,14 +5,15 @@
 	{
 		'creation': '2010-08-08 17:08:53',
 		'docstatus': 0,
-		'modified': '2010-09-20 14:06:57',
-		'modified_by': 'umair@iwebnotes.com',
+		'modified': '2011-12-28 12:28:02',
+		'modified_by': 'Administrator',
 		'owner': 'Administrator'
 	},
 
 	# These values are common for all DocType
 	{
 		'colour': 'White:FFF',
+		'default_print_format': 'Standard',
 		'doctype': 'DocType',
 		'istable': 1,
 		'module': 'Production',
@@ -20,7 +21,7 @@
 		'section_style': 'Simple',
 		'server_code_error': ' ',
 		'show_in_menu': 0,
-		'version': 6
+		'version': 8
 	},
 
 	# These values are common for all DocField
@@ -29,7 +30,8 @@
 		'name': '__common__',
 		'parent': 'BOM Operation',
 		'parentfield': 'fields',
-		'parenttype': 'DocType'
+		'parenttype': 'DocType',
+		'permlevel': 0
 	},
 
 	# These values are common for all DocPerm
@@ -52,7 +54,6 @@
 	# DocPerm
 	{
 		'doctype': 'DocPerm',
-		'idx': 1,
 		'permlevel': 0,
 		'write': 1
 	},
@@ -60,7 +61,6 @@
 	# DocPerm
 	{
 		'doctype': 'DocPerm',
-		'idx': 2,
 		'permlevel': 1
 	},
 
@@ -69,11 +69,9 @@
 		'doctype': 'DocField',
 		'fieldname': 'operation_no',
 		'fieldtype': 'Data',
-		'idx': 1,
 		'label': 'Operation No',
 		'oldfieldname': 'operation_no',
 		'oldfieldtype': 'Data',
-		'permlevel': 0,
 		'reqd': 1
 	},
 
@@ -82,39 +80,22 @@
 		'doctype': 'DocField',
 		'fieldname': 'opn_description',
 		'fieldtype': 'Text',
-		'idx': 2,
 		'label': 'Opn Description',
 		'oldfieldname': 'opn_description',
 		'oldfieldtype': 'Text',
-		'permlevel': 0,
 		'reqd': 1
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'details',
-		'fieldtype': 'Data',
-		'idx': 3,
-		'label': 'Details',
-		'oldfieldname': 'details',
-		'oldfieldtype': 'Data',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldname': 'workstation',
 		'fieldtype': 'Link',
-		'idx': 4,
 		'label': 'Workstation',
 		'oldfieldname': 'workstation',
 		'oldfieldtype': 'Link',
 		'options': 'Workstation',
-		'permlevel': 0,
-		'reqd': 1,
-		'search_index': 0,
+		'reqd': 0,
 		'trigger': 'Client'
 	},
 
@@ -123,37 +104,20 @@
 		'doctype': 'DocField',
 		'fieldname': 'hour_rate',
 		'fieldtype': 'Currency',
-		'idx': 5,
 		'label': 'Hour Rate',
 		'oldfieldname': 'hour_rate',
 		'oldfieldtype': 'Currency',
-		'permlevel': 1,
 		'reqd': 0
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'workstation_capacity',
-		'fieldtype': 'Currency',
-		'hidden': 1,
-		'idx': 6,
-		'label': 'Workstation Capacity',
-		'oldfieldname': 'workstation_capacity',
-		'oldfieldtype': 'Currency',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldname': 'time_in_mins',
 		'fieldtype': 'Currency',
-		'idx': 7,
 		'label': 'Operation Time (mins)',
 		'oldfieldname': 'time_in_mins',
 		'oldfieldtype': 'Currency',
-		'permlevel': 0,
 		'reqd': 0
 	},
 
@@ -163,11 +127,9 @@
 		'doctype': 'DocField',
 		'fieldname': 'operating_cost',
 		'fieldtype': 'Currency',
-		'idx': 8,
 		'label': 'Operating Cost',
 		'oldfieldname': 'operating_cost',
 		'oldfieldtype': 'Currency',
-		'permlevel': 1,
 		'reqd': 0
 	}
 ]
\ No newline at end of file
diff --git a/erpnext/production/doctype/flat_bom_detail/flat_bom_detail.txt b/erpnext/production/doctype/flat_bom_detail/flat_bom_detail.txt
index f0d5d58..1c2d76e 100644
--- a/erpnext/production/doctype/flat_bom_detail/flat_bom_detail.txt
+++ b/erpnext/production/doctype/flat_bom_detail/flat_bom_detail.txt
@@ -5,7 +5,7 @@
 	{
 		'creation': '2010-08-08 17:09:02',
 		'docstatus': 0,
-		'modified': '2011-11-10 14:21:40',
+		'modified': '2012-01-11 14:32:31',
 		'modified_by': 'Administrator',
 		'owner': 'jai@webnotestech.com'
 	},
@@ -23,7 +23,7 @@
 		'section_style': 'Simple',
 		'server_code_error': ' ',
 		'show_in_menu': 0,
-		'version': 18
+		'version': 24
 	},
 
 	# These values are common for all DocField
@@ -67,48 +67,8 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'moving_avg_rate',
-		'fieldtype': 'Currency',
-		'label': 'Valuation Rate',
-		'oldfieldname': 'moving_avg_rate',
-		'oldfieldtype': 'Currency'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'amount_as_per_mar',
-		'fieldtype': 'Currency',
-		'label': 'Amount As Per Valuation Rate',
-		'oldfieldname': 'amount_as_per_mar',
-		'oldfieldtype': 'Currency'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'last_purchase_rate',
-		'fieldtype': 'Currency',
-		'label': 'Last Purchase Rate',
-		'oldfieldname': 'last_purchase_rate',
-		'oldfieldtype': 'Currency'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'amount_as_per_lpr',
-		'fieldtype': 'Currency',
-		'label': 'Amount As Per LPR',
-		'oldfieldname': 'amount_as_per_lpr',
-		'oldfieldtype': 'Currency'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldname': 'qty',
-		'fieldtype': 'Currency',
+		'fieldtype': 'Float',
 		'label': 'Qty',
 		'oldfieldname': 'qty',
 		'oldfieldtype': 'Currency'
@@ -117,9 +77,9 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'standard_rate',
-		'fieldtype': 'Currency',
-		'label': 'Standard Rate',
+		'fieldname': 'rate',
+		'fieldtype': 'Float',
+		'label': 'Rate',
 		'oldfieldname': 'standard_rate',
 		'oldfieldtype': 'Currency'
 	},
@@ -127,9 +87,9 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'amount_as_per_sr',
-		'fieldtype': 'Currency',
-		'label': 'Amount As Per SR',
+		'fieldname': 'amount',
+		'fieldtype': 'Float',
+		'label': 'Amount',
 		'oldfieldname': 'amount_as_per_sr',
 		'oldfieldtype': 'Currency'
 	},
@@ -137,16 +97,6 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'qty_consumed_per_unit',
-		'fieldtype': 'Float',
-		'label': 'Qty Consumed Per Unit',
-		'oldfieldname': 'qty_consumed_per_unit',
-		'oldfieldtype': 'Float'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldname': 'stock_uom',
 		'fieldtype': 'Link',
 		'label': 'Stock UOM',
@@ -158,45 +108,31 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'flat_bom_no',
-		'fieldtype': 'Data',
-		'hidden': 1,
-		'label': 'Flat BOM No',
-		'oldfieldname': 'flat_bom_no',
-		'oldfieldtype': 'Data'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'bom_mat_no',
-		'fieldtype': 'Data',
-		'hidden': 0,
-		'label': 'BOM Mat No',
-		'oldfieldname': 'bom_mat_no',
-		'oldfieldtype': 'Data'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldname': 'parent_bom',
 		'fieldtype': 'Link',
 		'hidden': 0,
 		'label': 'Parent BOM',
 		'oldfieldname': 'parent_bom',
-		'oldfieldtype': 'Link'
+		'oldfieldtype': 'Link',
+		'width': '250px'
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'is_pro_applicable',
-		'fieldtype': 'Select',
-		'label': 'Is PRO Applicable',
-		'oldfieldname': 'is_pro_applicable',
-		'oldfieldtype': 'Select',
-		'options': '\nYes\nNo',
-		'reqd': 0
+		'fieldname': 'mat_detail_no',
+		'fieldtype': 'Data',
+		'hidden': 1,
+		'label': 'Mat Detail No'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldname': 'qty_consumed_per_unit',
+		'fieldtype': 'Float',
+		'hidden': 0,
+		'label': 'Qty Consumed Per Unit',
+		'no_copy': 0
 	}
-]
+]
\ No newline at end of file
diff --git a/erpnext/production/doctype/pp_detail/pp_detail.txt b/erpnext/production/doctype/pp_detail/pp_detail.txt
index 482fae2..a90d59c 100644
--- a/erpnext/production/doctype/pp_detail/pp_detail.txt
+++ b/erpnext/production/doctype/pp_detail/pp_detail.txt
@@ -5,8 +5,8 @@
 	{
 		'creation': '2010-08-08 17:09:12',
 		'docstatus': 0,
-		'modified': '2010-09-20 14:06:57',
-		'modified_by': 'umair@iwebnotes.com',
+		'modified': '2012-01-09 16:25:13',
+		'modified_by': 'Administrator',
 		'owner': 'Administrator'
 	},
 
@@ -14,6 +14,7 @@
 	{
 		'autoname': 'PPID/.#####',
 		'colour': 'White:FFF',
+		'default_print_format': 'Standard',
 		'doctype': 'DocType',
 		'istable': 1,
 		'module': 'Production',
@@ -21,7 +22,7 @@
 		'section_style': 'Simple',
 		'server_code_error': ' ',
 		'show_in_menu': 0,
-		'version': 21
+		'version': 27
 	},
 
 	# These values are common for all DocField
@@ -42,22 +43,9 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'source_doctype',
+		'fieldname': 'sales_order',
 		'fieldtype': 'Data',
-		'idx': 1,
-		'label': 'Against Document ',
-		'oldfieldname': 'source_doctype',
-		'oldfieldtype': 'Data',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'source_docname',
-		'fieldtype': 'Data',
-		'idx': 2,
-		'label': 'Document No',
+		'label': 'Sales Order',
 		'oldfieldname': 'source_docname',
 		'oldfieldtype': 'Data',
 		'permlevel': 1
@@ -65,74 +53,18 @@
 
 	# DocField
 	{
-		'doctype': 'DocField',
-		'fieldname': 'source_detail_docname',
-		'fieldtype': 'Data',
-		'hidden': 1,
-		'idx': 3,
-		'label': 'Document Detail No',
-		'oldfieldname': 'source_detail_docname',
-		'oldfieldtype': 'Data',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'parent_item',
-		'fieldtype': 'Link',
-		'idx': 4,
-		'label': 'Parent Item',
-		'oldfieldname': 'parent_item',
-		'oldfieldtype': 'Link',
-		'options': 'Item',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
 		'colour': 'White:FFF',
 		'doctype': 'DocField',
 		'fieldname': 'item_code',
 		'fieldtype': 'Link',
-		'idx': 5,
 		'label': 'Item Code',
 		'oldfieldname': 'item_code',
 		'oldfieldtype': 'Link',
 		'options': 'Item',
 		'permlevel': 0,
-		'trigger': 'Client'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'document_date',
-		'fieldtype': 'Date',
-		'idx': 6,
-		'in_filter': 1,
-		'label': 'Document Date',
-		'oldfieldname': 'document_date',
-		'oldfieldtype': 'Date',
-		'permlevel': 0,
-		'search_index': 1,
-		'width': '150px'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'confirmation_date',
-		'fieldtype': 'Date',
-		'idx': 7,
-		'in_filter': 1,
-		'label': 'Confirmed Delivery Date',
-		'oldfieldname': 'confirmation_date',
-		'oldfieldtype': 'Date',
-		'permlevel': 0,
 		'reqd': 1,
-		'search_index': 0,
-		'width': '100px'
+		'trigger': 'Client',
+		'width': '150px'
 	},
 
 	# DocField
@@ -140,37 +72,22 @@
 		'doctype': 'DocField',
 		'fieldname': 'bom_no',
 		'fieldtype': 'Link',
-		'idx': 8,
 		'label': 'BOM No',
 		'oldfieldname': 'bom_no',
 		'oldfieldtype': 'Link',
 		'options': 'Bill Of Materials',
 		'permlevel': 0,
-		'search_index': 0,
+		'reqd': 1,
 		'width': '100px'
 	},
 
 	# DocField
 	{
-		'doctype': 'DocField',
-		'fieldname': 'description',
-		'fieldtype': 'Text',
-		'idx': 9,
-		'label': 'Description',
-		'oldfieldname': 'description',
-		'oldfieldtype': 'Text',
-		'permlevel': 1,
-		'width': '300px'
-	},
-
-	# DocField
-	{
 		'default': '0.00',
 		'doctype': 'DocField',
-		'fieldname': 'prevdoc_reqd_qty',
+		'fieldname': 'so_pending_qty',
 		'fieldtype': 'Currency',
-		'idx': 11,
-		'label': 'Total Reqd Qty',
+		'label': 'SO Pending Qty',
 		'oldfieldname': 'prevdoc_reqd_qty',
 		'oldfieldtype': 'Currency',
 		'permlevel': 1,
@@ -180,70 +97,63 @@
 
 	# DocField
 	{
-		'doctype': 'DocField',
-		'fieldname': 'stock_uom',
-		'fieldtype': 'Data',
-		'idx': 12,
-		'label': 'Stock UOM',
-		'oldfieldname': 'stock_uom',
-		'oldfieldtype': 'Data',
-		'permlevel': 1,
-		'reqd': 1
-	},
-
-	# DocField
-	{
 		'default': '0.00',
 		'doctype': 'DocField',
 		'fieldname': 'planned_qty',
 		'fieldtype': 'Currency',
-		'idx': 12,
-		'label': 'Planned Quantity',
+		'label': 'Planned Qty',
 		'oldfieldname': 'planned_qty',
 		'oldfieldtype': 'Currency',
 		'permlevel': 0,
 		'reqd': 1,
-		'width': '180px'
+		'width': '100px'
 	},
 
 	# DocField
 	{
-		'default': '0.00',
 		'doctype': 'DocField',
-		'fieldname': 'produced_qty',
-		'fieldtype': 'Currency',
-		'hidden': 1,
-		'idx': 13,
-		'label': 'Produced Qty',
-		'oldfieldname': 'produced_qty',
-		'oldfieldtype': 'Currency',
+		'fieldname': 'stock_uom',
+		'fieldtype': 'Data',
+		'label': 'UOM',
+		'oldfieldname': 'stock_uom',
+		'oldfieldtype': 'Data',
 		'permlevel': 1,
-		'width': '130px'
+		'reqd': 1,
+		'width': '80px'
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'pro_created',
-		'fieldtype': 'Check',
-		'idx': 14,
-		'label': 'PRO Created',
-		'oldfieldname': 'pro_created',
-		'oldfieldtype': 'Check',
+		'fieldname': 'description',
+		'fieldtype': 'Text',
+		'label': 'Description',
+		'oldfieldname': 'description',
+		'oldfieldtype': 'Text',
+		'permlevel': 1,
+		'width': '200px'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldname': 'parent_packing_item',
+		'fieldtype': 'Link',
+		'label': 'Parent Packing Item',
+		'oldfieldname': 'parent_item',
+		'oldfieldtype': 'Link',
+		'options': 'Item',
 		'permlevel': 1
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'mrp',
+		'fieldname': 'is_pro_created',
 		'fieldtype': 'Check',
-		'hidden': 1,
-		'idx': 15,
-		'label': 'Already MRP Considered',
-		'oldfieldname': 'mrp',
+		'label': 'Is PRO Created',
+		'oldfieldname': 'pro_created',
 		'oldfieldtype': 'Check',
-		'permlevel': 1,
-		'width': '140px'
+		'permlevel': 1
 	}
 ]
\ No newline at end of file
diff --git a/erpnext/production/doctype/pp_so_detail/pp_so_detail.txt b/erpnext/production/doctype/pp_so_detail/pp_so_detail.txt
index 0dd09dd..c07d71b 100644
--- a/erpnext/production/doctype/pp_so_detail/pp_so_detail.txt
+++ b/erpnext/production/doctype/pp_so_detail/pp_so_detail.txt
@@ -5,8 +5,8 @@
 	{
 		'creation': '2010-08-08 17:09:13',
 		'docstatus': 0,
-		'modified': '2010-09-20 14:06:57',
-		'modified_by': 'umair@iwebnotes.com',
+		'modified': '2012-01-09 17:41:37',
+		'modified_by': 'Administrator',
 		'owner': 'Administrator'
 	},
 
@@ -14,6 +14,7 @@
 	{
 		'autoname': 'PP/.SO/.#####',
 		'colour': 'White:FFF',
+		'default_print_format': 'Standard',
 		'doctype': 'DocType',
 		'istable': 1,
 		'module': 'Production',
@@ -21,7 +22,7 @@
 		'section_style': 'Simple',
 		'server_code_error': ' ',
 		'show_in_menu': 0,
-		'version': 2
+		'version': 5
 	},
 
 	# These values are common for all DocField
@@ -33,70 +34,31 @@
 		'parenttype': 'DocType'
 	},
 
-	# These values are common for all DocPerm
-	{
-		'doctype': 'DocPerm',
-		'name': '__common__',
-		'parent': 'PP SO Detail',
-		'parentfield': 'permissions',
-		'parenttype': 'DocType',
-		'read': 1,
-		'role': 'System Manager'
-	},
-
 	# DocType, PP SO Detail
 	{
 		'doctype': 'DocType',
 		'name': 'PP SO Detail'
 	},
 
-	# DocPerm
-	{
-		'doctype': 'DocPerm',
-		'idx': 1,
-		'permlevel': 0,
-		'write': 1
-	},
-
-	# DocPerm
-	{
-		'doctype': 'DocPerm',
-		'idx': 2,
-		'permlevel': 1
-	},
-
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'prevdoc',
-		'fieldtype': 'Data',
-		'idx': 1,
-		'label': 'Against Document',
-		'oldfieldname': 'prevdoc',
-		'oldfieldtype': 'Data',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'prevdoc_docname',
-		'fieldtype': 'Data',
-		'idx': 2,
-		'label': 'Document No',
+		'fieldname': 'sales_order',
+		'fieldtype': 'Link',
+		'label': 'Sales Order',
 		'oldfieldname': 'prevdoc_docname',
 		'oldfieldtype': 'Data',
-		'permlevel': 1,
+		'options': 'Sales Order',
+		'permlevel': 0,
 		'width': '150px'
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'document_date',
+		'fieldname': 'sales_order_date',
 		'fieldtype': 'Date',
-		'idx': 3,
-		'label': 'Document Date',
+		'label': 'Sales Order Date',
 		'oldfieldname': 'document_date',
 		'oldfieldtype': 'Date',
 		'permlevel': 1,
@@ -106,12 +68,20 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'confirmation_date',
-		'fieldtype': 'Date',
-		'idx': 5,
-		'label': 'Confirmation Date',
-		'oldfieldname': 'confirmation_date',
-		'oldfieldtype': 'Date',
+		'fieldname': 'customer',
+		'fieldtype': 'Link',
+		'label': 'Customer',
+		'options': 'Customer',
+		'permlevel': 1,
+		'width': '150px'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldname': 'grand_total',
+		'fieldtype': 'Currency',
+		'label': 'Grand Total',
 		'permlevel': 1,
 		'width': '100px'
 	},
@@ -121,7 +91,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'include_in_plan',
 		'fieldtype': 'Check',
-		'idx': 6,
 		'label': 'Include In Plan',
 		'oldfieldname': 'include_in_plan',
 		'oldfieldtype': 'Check',
diff --git a/erpnext/production/doctype/production_control/production_control.py b/erpnext/production/doctype/production_control/production_control.py
index 36db7dd..f3e1492 100644
--- a/erpnext/production/doctype/production_control/production_control.py
+++ b/erpnext/production/doctype/production_control/production_control.py
@@ -16,140 +16,84 @@
 	
 # -----------------------------------------------------------------------------------------
 
-
+	
 class DocType:
-  def __init__( self, doc, doclist=[]):
-    self.doc = doc
-    self.doclist = doclist
-    # pur_items = {'item_code':req_qty}
-    self.pur_items = {}
-    # bom_list = [[]]
-    self.bom_list = []
-    # list for sub assembly item
-    self.sub_assembly_items = []
-    # Item Master 
-    self.item_master = {}
+	def __init__( self, doc, doclist=[]):
+		self.doc = doc
+		self.doclist = doclist
+		self.pur_items = {}
+		self.bom_list = []
+		self.sub_assembly_items = []
+		self.item_master = {}
 
-  def traverse_bom_tree( self, bom_no, qty, ext_pur_items = 0, ext_sub_assembly_items = 0, calculate_cost = 0, maintain_item_master = 0 ):
-    count, bom_list, qty_list = 0, [bom_no], [qty]
-    while (count < len(bom_list)):
-      # get child items from BOM MAterial Table.
-      child_items = sql("select item_code, bom_no, qty, qty_consumed_per_unit from `tabBOM Material` where parent = %s", bom_list[count], as_dict = 1)
-      child_items = child_items and child_items or []
-      #msgprint(bom_list[count])
-      #msgprint(qty_list)
-      for item in child_items:
-        # Calculate qty required for FG's qty.
-        item['reqd_qty'] = flt(qty) * ((count == 0) and 1 or flt(qty_list[count]) )* flt(item['qty_consumed_per_unit'])
-        #gprint("Item Reqd : " + cstr(item['reqd_qty']))
+	def traverse_bom_tree( self, bom_no, qty, ext_pur_items = 0, ext_sub_assembly_items = 0, calculate_cost = 0, maintain_item_master = 0 ):
+		count, bom_list, qty_list = 0, [bom_no], [qty]
+		while (count < len(bom_list)):
+			# get child items from BOM MAterial Table.
+			child_items = sql("select item_code, bom_no, qty, qty_consumed_per_unit from `tabBOM Material` where parent = %s", bom_list[count], as_dict = 1)
+			child_items = child_items and child_items or []
+			for item in child_items:
+				# Calculate qty required for FG's qty.
+				item['reqd_qty'] = flt(qty) * ((count == 0) and 1 or flt(qty_list[count]) )* flt(item['qty_consumed_per_unit'])
 
-        # extracting Purchase Items
-        if ext_pur_items and not item['bom_no']:
-          # item exist in pur_items dict then just add qty with previous qty
-          if self.pur_items.has_key(item['item_code']):
-            self.pur_items[item['item_code']] = flt(self.pur_items[item['item_code']]) + flt(item['reqd_qty'])
-            # maintain item master
-            #if maintain_item_master:
-              
-          # else add item in pur_item dict with reqd qty.
-          else:
-            self.pur_items[item['item_code']] = flt(item['reqd_qty'])
-            # maintain item master
-            #if maintain_item_master:
-              
-        # For calculate cost extracting BOM Items check for duplicate boms, this optmizes the time complexity for while loop.
-        if calculate_cost and item['bom_no'] and (item['bom_no'] not in bom_list):
-          bom_list.append(item['bom_no'])
-          qty_list.append(item['reqd_qty'])
+				# extracting Purchase Items
+				if ext_pur_items and not item['bom_no']:
+					self.pur_items[item['item_code']] = flt(self.pur_items.get(item['item_code'], 0)) + flt(item['reqd_qty'])
+							
+				# For calculate cost extracting BOM Items check for duplicate boms, this optmizes the time complexity for while loop.
+				if calculate_cost and item['bom_no'] and (item['bom_no'] not in bom_list):
+					bom_list.append(item['bom_no'])
+					qty_list.append(item['reqd_qty'])
 
-        # Here repeated bom are considered to calculate total qty of raw material required
-        if not calculate_cost and item['bom_no']:
-          # append bom to bom_list
-          bom_list.append(item['bom_no'])
-          qty_list.append(item['reqd_qty'])
+				# Here repeated bom are considered to calculate total qty of raw material required
+				if not calculate_cost and item['bom_no']:
+					bom_list.append(item['bom_no'])
+					qty_list.append(item['reqd_qty'])
 
-#          # extracting Sub Assembly Items . Make Sure Sub Assembly Items have BOM No. in BOM MATERIAL
-#          if ext_sub_assembly_items:
-#            # If Production Order Applicable is 'Yes'
-#            if item['pro_applicable#'] == "Yes":
-#              # append item in sub_assembly_items
-#              self.sub_assembly_items.append([item['item_code']])
-#              # Remove current bom from bom_list
-#              bom_list.pop()
-
-      count += 1
-    return bom_list
+			count += 1
+		return bom_list
 
 
 
-  #  Raise Production Order
-  def create_production_order(self,company, fy, pp_detail = '', pro_detail = ''):
-    pro_lbl = {'production_item': 0, 'description': 1, 'qty' : 2, 'stock_uom' : 3, 'bom_no': 4, 'consider_sa_items': 5}
-           
-    default_values = { 'transaction_date'            : now(),
-                       'origin'          : pp_detail and 'MRP' or 'Direct',
-                       'wip_warehouse'   : 'MB1-Stores',
-                       'status'          : 'Draft',
-                       'company'         : company,
-                       'fiscal_year'     : fy }
-     
-    pro_list, count = pp_detail and pp_detail or pro_detail, 0
+	#	Raise Production Order
+	def create_production_order(self,company, pp_items):
+		"""Create production order. Called from Production Planning Tool"""
+					 
+		default_values = { 
+			'posting_date'		: nowdate(),
+			'origin'			: 'MRP',
+			'wip_warehouse'		: '',
+			'fg_warehouse'		: '',
+			'status'			: 'Draft',
+			'company'			: company,
+			'fiscal_year'		: get_defaults()['fiscal_year'] 
+		}
+		pro_list = []
 
-    while (count < len(pro_list)):
-      pro_doc = Document('Production Order')
+		for d in pp_items:
+			pro_doc = Document('Production Order')
+			for key in d.keys():
+				pro_doc.fields[key] = d[key]
 
-      for key in pro_lbl.keys():
-        pro_doc.fields[key] = pro_list[count][pro_lbl[key]]
-      
-      for key in default_values:
-        pro_doc.fields[key] = default_values[key]
-      
-      pro_doc.save(new = 1)
-      pro_list[count] = pro_doc.name
-      
-      # This was for adding raw materials in pro detail and get sa items
-      #sa_list = get_obj('Porduction Order', pro_doc.name, with_children = 1).get_purchase_item( get_sa_items = 1, add_child= 1)
-      #for sa_item in sa_list:
-      #  pro_list.append(sa_item)
-
-      count = count + 1
-    return pro_list
+			for key in default_values:
+				pro_doc.fields[key] = default_values[key]
+			
+			pro_doc.save(new = 1)
+			pro_list.append(pro_doc.name)
+			
+		return pro_list
 
 
-  def update_bom(self, bom_no):
-    main_bom_list = self.traverse_bom_tree(bom_no, 1)
-    main_bom_list.reverse()
-    #print('--------------')
-    msgprint(main_bom_list)
-    #print('--------------')
-    # run calculate cost and get
-    for bom in main_bom_list:
-      if bom and bom not in self.check_bom_list:
-        #print(bom)
-        bom_obj = get_obj('Bill Of Materials', bom, with_children = 1)
-        #print(bom_obj.doc.fields)
-        bom_obj.doc.save()
-        bom_obj.check_recursion()
-        bom_obj.update_flat_bom_engine()
-        bom_obj.doc.docstatus = 1
-        bom_obj.doc.save()
-        self.check_bom_list.append(bom)
-        #errprint(" " + cstr(bom) + " has been submitted successfully.")
-        
-
-  def update_all_fg(self):
-    self.check_bom_list = []
-    #pc_obj = get_obj(dt = 'Production Control')
-    cn_bom = sql("select name from `tabBill Of Materials` where item not like 'CN%' and item not like 'LDR%' and item not like 'HD%' limit 1")
-    #cn_bom = (('BOM/A012629/001',),)
-    i=1
-    #msgprint(cn_bom)
-    for d in cn_bom:
-      if not cstr(d[0]) in self.check_bom_list:
-        print('Main BOM')
-        msgprint(d[0])
-        msgprint(i)
-        #sql("start transaction")
-        #self.update_bom(d[0])
-        #sql("commit")
-        i += 1
\ No newline at end of file
+	def update_bom(self, bom_no):
+		main_bom_list = self.traverse_bom_tree(bom_no, 1)
+		main_bom_list.reverse()
+		# run calculate cost and get
+		for bom in main_bom_list:
+			if bom and bom not in self.check_bom_list:
+				bom_obj = get_obj('Bill Of Materials', bom, with_children = 1)
+				bom_obj.doc.save()
+				bom_obj.check_recursion()
+				bom_obj.update_flat_bom_engine()
+				bom_obj.doc.docstatus = 1
+				bom_obj.doc.save()
+				self.check_bom_list.append(bom)
diff --git a/erpnext/production/doctype/production_order/production_order.js b/erpnext/production/doctype/production_order/production_order.js
index bce5a15..9ff72ef 100644
--- a/erpnext/production/doctype/production_order/production_order.js
+++ b/erpnext/production/doctype/production_order/production_order.js
@@ -1,101 +1,70 @@
-$import(Production Tips Common)
 
-cur_frm.cscript.onload = function(doc, cdt, cdn) {
-
-   
-
-  if (!doc.fiscal_year && doc.__islocal){ set_default_values(doc);}
-  if (!doc.transaction_date) doc.transaction_date = dateutil.obj_to_str(new Date());
+cur_frm.cscript.onload = function(doc, dt, dn) {
+  if (!doc.posting_date) doc.transaction_date = dateutil.obj_to_str(new Date());
   if (!doc.status) doc.status = 'Draft';
-  cfn_set_fields(doc, cdt, cdn);
+
+  cfn_set_fields(doc, dt, dn);
+
   if (doc.origin != "MRP"){
-    doc.origin = "Manual"; 
-    //get_field('Production Order', 'consider_sa_items').permlevel = 0;
+    doc.origin = "Manual";
     set_field_permlevel('production_item', 0);
     set_field_permlevel('bom_no', 0);
     set_field_permlevel('consider_sa_items',0);
-    
   }
 }
+
 // ================================== Refresh ==========================================
-cur_frm.cscript.refresh = function(doc, cdt, cdn) { 
-
-   
-  cfn_set_fields(doc, cdt, cdn);
+cur_frm.cscript.refresh = function(doc, dt, dn) { 
+  cfn_set_fields(doc, dt, dn);
 }
 
-cur_frm.fields_dict['production_item'].get_query = function(doc) {
-   return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.`description` FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.%(key)s LIKE "%s" ORDER BY `tabItem`.`name` LIMIT 50';
-}
+var cfn_set_fields = function(doc, dt, dn) {
+  if (doc.docstatus == 1) {
+    if (doc.status != 'Stopped' && doc.status != 'Completed')
+	  cur_frm.add_custom_button('Stop!', cur_frm.cscript['Stop Production Order']);
+    else if (doc.status == 'Stopped')
+      cur_frm.add_custom_button('Unstop', cur_frm.cscript['Unstop Production Order']);
 
-// ---------------------- Get project name --------------------------
-cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
-  return 'SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.status = "Open" AND `tabProject`.name LIKE "%s" ORDER BY `tabProject`.name ASC LIMIT 50';
-}
-
-cur_frm.fields_dict['bom_no'].get_query = function(doc)  {
-  if (doc.production_item){
-    return 'SELECT DISTINCT `tabBill Of Materials`.`name` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`is_active` = "Yes" AND `tabBill Of Materials`.`item` = "' + cstr(doc.production_item) + '" AND`tabBill Of Materials`.%(key)s LIKE "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
-  }
-  else {
-    alert(" Please Enter Production Item First.")
-  }
-}
-
-cur_frm.cscript.production_item = function(doc, cdt, cdn) {
-  get_server_fields('get_item_detail',doc.production_item,'',doc,cdt,cdn,1);
-}
-
-var cfn_set_fields = function(doc, cdt, cdn) {
-  hide_field('Material Transfer');
-  hide_field('Stop Production Order');
-  hide_field('Unstop Production Order')
-  hide_field('Backflush');
-  if (doc.docstatus == 1){
-    unhide_field('Stop Production Order');
     if (doc.status == 'Submitted' || doc.status == 'Material Transferred' || doc.status == 'In Process'){
-      unhide_field(['Material Transfer','Backflush']);
-    }
-    else if (doc.status == 'Stopped'){
-      unhide_field('Unstop Production Order');
-      hide_field(['Stop Production Order', 'Material Transfer', 'Backflush']);
-    }
-    else if (doc.status == 'Completed'){
-      hide_field(['Stop Production Order', 'Material Transfer', 'Backflush']);
-    }
+      cur_frm.add_custom_button('Transfer Material', cur_frm.cscript['Transfer Material']);
+      cur_frm.add_custom_button('Backflush', cur_frm.cscript['Backflush']);
+    } 
   }
- 
+}
+
+
+// ==================================================================================================
+
+cur_frm.cscript.production_item = function(doc, dt, dn) {
+  get_server_fields('get_item_detail',doc.production_item,'',doc,dt,dn,1);
 }
 
 // Stop PRODUCTION ORDER
-// ==================================================================================================
-cur_frm.cscript['Stop Production Order'] = function(doc,cdt,cdn) {
-  var check = confirm("DO YOU REALLY WANT TO Stop PRODUCTION ORDER : " + doc.name);
-
+//
+cur_frm.cscript['Stop Production Order'] = function() {
+  var doc = cur_frm.doc;
+  var check = confirm("Do you really want to stop production order: " + doc.name);
   if (check) {
-    $c('runserverobj', args={'method':'update_status', 'arg': 'Stopped', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
-      cur_frm.refresh();
-    });	
-  }
+    $c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Stopped', function(r, rt) {cur_frm.refresh();});
+	}
 }
 
 // Unstop PRODUCTION ORDER
-// ==================================================================================================
-cur_frm.cscript['Unstop Production Order'] = function(doc,cdt,cdn) {
-  var check = confirm("DO YOU REALLY WANT TO Unstop PRODUCTION ORDER : " + doc.name);
-
-  if (check) {
-    $c('runserverobj', args={'method':'update_status', 'arg': 'Unstopped', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
-      cur_frm.refresh();
-    });	
-  }
+//
+cur_frm.cscript['Unstop Production Order'] = function() {
+  var doc = cur_frm.doc;
+  var check = confirm("Do really want to unstop production order: " + doc.name);
+  if (check)
+      $c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Unstopped', function(r, rt) {cur_frm.refresh();});
 }
 
-cur_frm.cscript['Material Transfer'] = function(doc,cdt,cdn) {
+cur_frm.cscript['Transfer Material'] = function() {
+  var doc = cur_frm.doc;
   cur_frm.cscript.make_se(doc, process = 'Material Transfer');
 }
 
-cur_frm.cscript['Backflush'] = function(doc,cdt,cdn) {
+cur_frm.cscript['Backflush'] = function() {
+  var doc = cur_frm.doc;
   cur_frm.cscript.make_se(doc, process = 'Backflush');
 }
 
@@ -105,9 +74,29 @@
   se.purpose = 'Production Order';
   se.process = process;
   se.posting_date = doc.posting_date;
-  se.production_order = doc.name; 
+  se.production_order = doc.name;
   se.fiscal_year = doc.fiscal_year;
   se.company = doc.company;
   
   loaddoc('Stock Entry', se.name);
 }
+
+
+// ==================================================================================================
+cur_frm.fields_dict['production_item'].get_query = function(doc) {
+   return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.`description` FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.docstatus != 2 AND `tabItem`.is_pro_applicable = "Yes" AND `tabItem`.%(key)s LIKE "%s" ORDER BY `tabItem`.`name` LIMIT 50';
+}
+
+cur_frm.fields_dict['project_name'].get_query = function(doc, dt, dn) {
+  return 'SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.status = "Open" AND `tabProject`.name LIKE "%s" ORDER BY `tabProject`.name ASC LIMIT 50';
+}
+
+cur_frm.fields_dict['bom_no'].get_query = function(doc)  {
+  if (doc.production_item){
+    return 'SELECT DISTINCT `tabBill Of Materials`.`name` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`is_active` = "Yes" AND `tabBill Of Materials`.docstatus = 1 AND `tabBill Of Materials`.`item` = "' + cstr(doc.production_item) + '" AND`tabBill Of Materials`.%(key)s LIKE "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
+  }
+  else {
+    alert(" Please Enter Production Item First.")
+  }
+}
+
diff --git a/erpnext/production/doctype/production_order/production_order.py b/erpnext/production/doctype/production_order/production_order.py
index 0cc64e5..ff9de8f 100644
--- a/erpnext/production/doctype/production_order/production_order.py
+++ b/erpnext/production/doctype/production_order/production_order.py
@@ -15,90 +15,83 @@
 convert_to_lists = webnotes.conn.convert_to_lists
 
 # -----------------------------------------------------------------------------------------
-
+	
 
 class DocType:
-  def __init__(self, doc, doclist=[]):
-    self.doc = doc
-    self.doclist = doclist
-
-  # Autoname
-  def autoname(self):
-    p = self.doc.fiscal_year
-    self.doc.name = make_autoname('PRO/' + self.doc.fiscal_year[2:5]+self.doc.fiscal_year[7:9] + '/.######')
-
-  def get_item_detail(self, production_item):
-    item = sql("select description, stock_uom, default_bom from `tabItem` where (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life >  now()) and name = %s", production_item, as_dict = 1 )
-    ret = {
-            'description' : item and item[0]['description'] or '',
-            'stock_uom'   : item and item[0]['stock_uom'] or '',
-            'default_bom' : item and item[0]['default_bom'] or ''
-    }
-    return ret
-
-  def validate(self):
-    if not self.doc.production_item :
-      msgprint("Please enter Production Item")
-      raise Exception
-    if self.doc.production_item :
-      item_detail = sql("select docstatus from `tabItem` where name = '%s'" % self.doc.production_item, as_dict = 1)
-      if not item_detail:
-        msgprint("Item '%s' do not exist in the system." % cstr(self.doc.production_item))
-        raise Exception
-      if item_detail[0]['docstatus'] == 2:
-        msgprint("Item '%s' is Trashed Item ."% self.doc.production_item)
-        raise Exception
-    if self.doc.bom_no:
-      bom_detail = sql("select item, is_active, docstatus from `tabBill Of Materials` where name = '%s'" % self.doc.bom_no, as_dict =1)
-      if not bom_detail:
-        msgprint("BOM No '%s' do not exist in the system." % cstr(self.doc.bom_no))
-        raise Exception
-      if cstr(bom_detail[0]['item']) != cstr(self.doc.production_item):
-        msgprint("The Item '%s' in BOM := '%s' do not match with Produciton Item '%s'." % (cstr(bom_detail[0]['item']), cstr(self.doc.bom_no), cstr(self.doc.production_item)))
-        raise Exception
-      if cstr(bom_detail[0]['is_active']) != 'Yes':
-        msgprint("BOM := '%s' is not Active BOM." % self.doc.bom_no)
-        raise Exception
-      if flt(bom_detail[0]['docstatus']) != 1:
-        msgprint("BOM := '%s' is not Submitted BOM." % self.doc.bom_no)
-        raise Exception
-
-  def update_status(self, status):
-    # Set Status
-    if status == 'Stopped':
-      set(self.doc, 'status', cstr(status))
-    else:
-      if flt(self.doc.qty) == flt(self.doc.produced_qty):
-        set(self.doc, 'status', 'Completed')
-      if flt(self.doc.qty) > flt(self.doc.produced_qty):
-        set(self.doc, 'status', 'In Process')
-      if flt(self.doc.produced_qty) == 0:
-        set(self.doc, 'status', 'Submitted')
-
-    # Update Planned Qty of Production Item
-    qty = (flt(self.doc.qty) - flt(self.doc.produced_qty)) * ((status == 'Stopped') and -1 or 1)
-    get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0, flt(qty), self.doc.production_item, now())
-
-    # Acknowledge user
-    msgprint(self.doc.doctype + ": " + self.doc.name + " has been %s and status has been updated as %s." % (cstr(status), cstr(self.doc.status)))
-
-  def on_submit(self):
-    # Set Status AS "Submitted"
-    set(self.doc,'status', 'Submitted')
-
-    # increase Planned Qty of Prooduction Item by Qty
-    get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0,flt(self.doc.qty), self.doc.production_item, now())
+	def __init__(self, doc, doclist=[]):
+		self.doc = doc
+		self.doclist = doclist
 
 
-  def on_cancel(self):
-    # Stock Entries Against this Production Order
-    st = sql("select name from `tabStock Entry` where production_order = '%s' and docstatus = 1" % cstr(self.doc.name))
-    if st and st[0][0]:
-      msgprint("Stock Entry "+ cstr(st[0][0]) + " has already been submitted.")
-      raise Exception
+	def autoname(self):
+		p = self.doc.fiscal_year
+		self.doc.name = make_autoname('PRO/' + self.doc.fiscal_year[2:5]+self.doc.fiscal_year[7:9] + '/.######')
 
-    # Set Status AS "Submitted"
-    set(self.doc,'status', 'Cancelled')
 
-    # decrease Planned Qty of Prooduction Item by Qty
-    get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0,-flt(self.doc.qty), self.doc.production_item, now())
+	def get_item_detail(self, prod_item):
+		item = sql("""select description, stock_uom, default_bom from `tabItem` 
+		where (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life >	now()) and name = %s""", prod_item, as_dict = 1 )
+		ret = {
+			'description'		: item and item[0]['description'] or '',
+			'stock_uom'			: item and item[0]['stock_uom'] or '',
+			'default_bom'		: item and item[0]['default_bom'] or ''
+		}
+		return ret
+
+
+	def validate(self):
+		if self.doc.production_item :
+			item_detail = sql("select name from `tabItem` where name = '%s' and docstatus != 2" % self.doc.production_item, as_dict = 1)
+			if not item_detail:
+				msgprint("Item '%s' does not exist or cancelled in the system." % cstr(self.doc.production_item))
+				raise Exception
+
+		if self.doc.bom_no:
+			bom = sql("""select name from `tabBill Of Materials`	where name = %s and docstatus = 1 
+				and is_active = 'Yes' and item = %s""", (self.doc.bom_no, self.doc.production_item), as_dict =1)
+			if not bom:
+				msgprint("""Incorrect BOM: %s entered. 
+					May be BOM not exists or inactive or not submitted or for some other item.""" % cstr(self.doc.bom_no))
+				raise Exception
+
+
+	def stop_unstop(self, status):
+		""" Called from client side on Stop/Unstop event"""
+		self.update_status(status)
+		# Update Planned Qty of Production Item
+		qty = (flt(self.doc.qty) - flt(self.doc.produced_qty)) * ((status == 'Stopped') and -1 or 1)
+		get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0, flt(qty), self.doc.production_item, now())
+		msgprint("Production Order has been %s" % status)
+
+
+
+	def update_status(self, status):
+		if status == 'Stopped':
+			set(self.doc, 'status', cstr(status))
+		else:
+			if flt(self.doc.qty) == flt(self.doc.produced_qty):
+				set(self.doc, 'status', 'Completed')
+			if flt(self.doc.qty) > flt(self.doc.produced_qty):
+				set(self.doc, 'status', 'In Process')
+			if flt(self.doc.produced_qty) == 0:
+				set(self.doc, 'status', 'Submitted')
+
+
+	def on_submit(self):
+		set(self.doc,'status', 'Submitted')
+		# increase Planned Qty of Prooduction Item by Qty
+		get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0,flt(self.doc.qty), self.doc.production_item, now())
+
+
+
+	def on_cancel(self):
+		# Check whether any stock entry exists against this Production Order
+		st = sql("select name from `tabStock Entry` where production_order = '%s' and docstatus = 1" % cstr(self.doc.name))
+		if st and st[0][0]:
+			msgprint("""Submitted Stock Entry %s exists against this production order. 
+				Hence can not be cancelled.""" % st[0][0])
+			raise Exception
+
+		set(self.doc,'status', 'Cancelled')
+		# decrease Planned Qty of Prooduction Item by Qty
+		get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0,-flt(self.doc.qty), self.doc.production_item, now())
diff --git a/erpnext/production/doctype/production_order/production_order.txt b/erpnext/production/doctype/production_order/production_order.txt
index 9226fd0..d94ccc9 100644
--- a/erpnext/production/doctype/production_order/production_order.txt
+++ b/erpnext/production/doctype/production_order/production_order.txt
@@ -5,15 +5,16 @@
 	{
 		'creation': '2010-08-08 17:09:14',
 		'docstatus': 0,
-		'modified': '2011-08-31 10:03:21',
+		'modified': '2012-01-11 17:36:23',
 		'modified_by': 'Administrator',
 		'owner': 'Administrator'
 	},
 
 	# These values are common for all DocType
 	{
-		'_last_update': '1313485457',
+		'_last_update': '1325837006',
 		'colour': 'White:FFF',
+		'default_print_format': 'Standard',
 		'doctype': 'DocType',
 		'in_create': 0,
 		'module': 'Production',
@@ -21,7 +22,7 @@
 		'section_style': 'Tabbed',
 		'server_code_error': ' ',
 		'show_in_menu': 0,
-		'version': 180
+		'version': 190
 	},
 
 	# These values are common for all DocField
@@ -95,38 +96,9 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldtype': 'Section Break',
-		'label': 'Production Order',
-		'oldfieldtype': 'Section Break',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'colour': 'White:FFF',
-		'description': 'The date on which current entry is made in system.',
-		'doctype': 'DocField',
-		'fieldname': 'transaction_date',
-		'fieldtype': 'Date',
-		'label': 'Transaction Date',
-		'oldfieldname': 'transaction_date',
-		'oldfieldtype': 'Date',
+		'fieldtype': 'Column Break',
 		'permlevel': 0,
-		'reqd': 1
-	},
-
-	# DocField
-	{
-		'colour': 'White:FFF',
-		'description': 'The date on which current entry will get or has actually executed.',
-		'doctype': 'DocField',
-		'fieldname': 'posting_date',
-		'fieldtype': 'Date',
-		'label': 'Posting Date',
-		'oldfieldname': 'posting_date',
-		'oldfieldtype': 'Date',
-		'permlevel': 0,
-		'reqd': 1
+		'width': '50%'
 	},
 
 	# DocField
@@ -160,6 +132,17 @@
 
 	# DocField
 	{
+		'doctype': 'DocField',
+		'fieldname': 'stock_uom',
+		'fieldtype': 'Data',
+		'label': 'Stock UOM',
+		'oldfieldname': 'stock_uom',
+		'oldfieldtype': 'Data',
+		'permlevel': 1
+	},
+
+	# DocField
+	{
 		'colour': 'White:FFF',
 		'description': 'Bill of Material which was considered for manufacturing the production item.',
 		'doctype': 'DocField',
@@ -176,21 +159,6 @@
 
 	# DocField
 	{
-		'doctype': 'DocField',
-		'fieldname': 'origin',
-		'fieldtype': 'Select',
-		'in_filter': 1,
-		'label': 'Origin',
-		'no_copy': 1,
-		'oldfieldname': 'origin',
-		'oldfieldtype': 'Select',
-		'options': 'Manual\nMRP',
-		'permlevel': 1,
-		'reqd': 1
-	},
-
-	# DocField
-	{
 		'colour': 'White:FFF',
 		'description': 'Quantity of item for which Production Order is raised.',
 		'doctype': 'DocField',
@@ -205,78 +173,6 @@
 
 	# DocField
 	{
-		'description': 'Select name of the project if Production Order need to be created against any project',
-		'doctype': 'DocField',
-		'fieldname': 'project_name',
-		'fieldtype': 'Link',
-		'in_filter': 1,
-		'label': 'Project Name',
-		'oldfieldname': 'project_name',
-		'oldfieldtype': 'Link',
-		'options': 'Project',
-		'permlevel': 0,
-		'trigger': 'Client'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'amended_from',
-		'fieldtype': 'Data',
-		'label': 'Amended From',
-		'oldfieldname': 'amended_from',
-		'oldfieldtype': 'Data',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'amendment_date',
-		'fieldtype': 'Date',
-		'label': 'Amendment Date',
-		'oldfieldname': 'amendment_date',
-		'oldfieldtype': 'Date',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'Column Break',
-		'oldfieldtype': 'Column Break',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'stock_uom',
-		'fieldtype': 'Data',
-		'label': 'Stock UOM',
-		'oldfieldname': 'stock_uom',
-		'oldfieldtype': 'Data',
-		'permlevel': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'status',
-		'fieldtype': 'Select',
-		'in_filter': 1,
-		'label': 'Status',
-		'no_copy': 1,
-		'oldfieldname': 'status',
-		'oldfieldtype': 'Select',
-		'options': '\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled',
-		'permlevel': 1,
-		'reqd': 1,
-		'search_index': 1
-	},
-
-	# DocField
-	{
 		'colour': 'White:FFF',
 		'description': 'The warehouse for finished goods where stock of produced items will be updated.',
 		'doctype': 'DocField',
@@ -309,13 +205,60 @@
 
 	# DocField
 	{
+		'doctype': 'DocField',
+		'fieldname': 'amended_from',
+		'fieldtype': 'Data',
+		'label': 'Amended From',
+		'no_copy': 1,
+		'oldfieldname': 'amended_from',
+		'oldfieldtype': 'Data',
+		'permlevel': 1
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldname': 'amendment_date',
+		'fieldtype': 'Date',
+		'label': 'Amendment Date',
+		'no_copy': 1,
+		'oldfieldname': 'amendment_date',
+		'oldfieldtype': 'Date',
+		'permlevel': 1
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldtype': 'Column Break',
+		'oldfieldtype': 'Column Break',
+		'permlevel': 0,
+		'width': '50%'
+	},
+
+	# DocField
+	{
 		'colour': 'White:FFF',
-		'description': 'Select "Yes" if stock is maintained and tracked for sub - assembly items.',
+		'description': 'The date on which current entry will get or has actually executed.',
+		'doctype': 'DocField',
+		'fieldname': 'posting_date',
+		'fieldtype': 'Date',
+		'label': 'Posting Date',
+		'oldfieldname': 'posting_date',
+		'oldfieldtype': 'Date',
+		'permlevel': 0,
+		'reqd': 1
+	},
+
+	# DocField
+	{
+		'colour': 'White:FFF',
+		'description': 'Select "Yes" if stock is maintained and tracked for sub-assembly items. Select "No" if you want child items of sub-assembly for material transfer.',
 		'doctype': 'DocField',
 		'fieldname': 'consider_sa_items',
 		'fieldtype': 'Select',
 		'in_filter': 1,
-		'label': 'Consider SA Items',
+		'label': 'Consider SA Items as raw material',
 		'oldfieldname': 'consider_sa_items',
 		'oldfieldtype': 'Select',
 		'options': '\nYes\nNo',
@@ -325,6 +268,52 @@
 
 	# DocField
 	{
+		'description': 'Select name of the project if Production Order need to be created against any project',
+		'doctype': 'DocField',
+		'fieldname': 'project_name',
+		'fieldtype': 'Link',
+		'in_filter': 1,
+		'label': 'Project Name',
+		'oldfieldname': 'project_name',
+		'oldfieldtype': 'Link',
+		'options': 'Project',
+		'permlevel': 0,
+		'trigger': 'Client'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldname': 'origin',
+		'fieldtype': 'Select',
+		'in_filter': 1,
+		'label': 'Origin',
+		'no_copy': 1,
+		'oldfieldname': 'origin',
+		'oldfieldtype': 'Select',
+		'options': 'Manual\nMRP',
+		'permlevel': 1,
+		'reqd': 1
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldname': 'status',
+		'fieldtype': 'Select',
+		'in_filter': 1,
+		'label': 'Status',
+		'no_copy': 1,
+		'oldfieldname': 'status',
+		'oldfieldtype': 'Select',
+		'options': '\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled',
+		'permlevel': 1,
+		'reqd': 1,
+		'search_index': 1
+	},
+
+	# DocField
+	{
 		'colour': 'White:FFF',
 		'description': 'Updated after finished goods are transferred to FG Warehouse through Stock Entry',
 		'doctype': 'DocField',
@@ -361,78 +350,5 @@
 		'options': 'link:Fiscal Year',
 		'permlevel': 0,
 		'reqd': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'Section Break',
-		'label': 'Next Steps',
-		'oldfieldtype': 'Section Break',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'allow_on_submit': 1,
-		'colour': 'White:FFF',
-		'doctype': 'DocField',
-		'fieldtype': 'Button',
-		'label': 'Material Transfer',
-		'oldfieldtype': 'Button',
-		'permlevel': 0,
-		'trigger': 'Client'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'Column Break',
-		'oldfieldtype': 'Column Break',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'allow_on_submit': 1,
-		'colour': 'White:FFF',
-		'doctype': 'DocField',
-		'fieldtype': 'Button',
-		'label': 'Backflush',
-		'oldfieldtype': 'Button',
-		'permlevel': 0,
-		'trigger': 'Client'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'Column Break',
-		'oldfieldtype': 'Column Break',
-		'permlevel': 0
-	},
-
-	# DocField
-	{
-		'allow_on_submit': 1,
-		'colour': 'White:FFF',
-		'doctype': 'DocField',
-		'fieldtype': 'Button',
-		'label': 'Stop Production Order',
-		'oldfieldtype': 'Button',
-		'permlevel': 0,
-		'trigger': 'Client'
-	},
-
-	# DocField
-	{
-		'allow_on_submit': 1,
-		'colour': 'White:FFF',
-		'doctype': 'DocField',
-		'fieldtype': 'Button',
-		'label': 'Unstop Production Order',
-		'oldfieldtype': 'Button',
-		'permlevel': 0,
-		'trigger': 'Client'
 	}
 ]
\ No newline at end of file
diff --git a/erpnext/production/doctype/production_planning_tool/production_planning_tool.js b/erpnext/production/doctype/production_planning_tool/production_planning_tool.js
index 5748284..6083dcb 100644
--- a/erpnext/production/doctype/production_planning_tool/production_planning_tool.js
+++ b/erpnext/production/doctype/production_planning_tool/production_planning_tool.js
@@ -1,45 +1,34 @@
-
-cur_frm.cscript.onload = function(doc, cdt, cdn) {
-  
-  if(!doc.fiscal_year){ set_default_values(doc);}
-}
-
 cur_frm.cscript.item_code = function(doc,cdt,cdn) {
-  var d = locals[cdt][cdn];
-  if (d.item_code) {
-    temp = "{'item_code':'"+(d.item_code?d.item_code:'')+"'}";
-    get_server_fields('get_item_details', temp, 'pp_details', doc, cdt, cdn, 1);
-  }
+	var d = locals[cdt][cdn];
+	if (d.item_code) {
+		get_server_fields('get_item_details', d.item_code, 'pp_details', doc, cdt, cdn, 1);
+	}
 }
 
+cur_frm.cscript.sales_order = function(doc,cdt,cdn) {
+	var d = locals[cdt][cdn];
+	if (d.sales_order) {
+		get_server_fields('get_so_details', d.sales_order, 'pp_so_details', doc, cdt, cdn, 1);
+	}
+}
+
+
+cur_frm.cscript['Download Raw Material'] = function(doc, cdt, cdn) {
+	var callback = function(r, rt){
+		if (r.message) 
+			$c_obj_csv(make_doclist(cdt, cdn), 'download_raw_materials', '', '');
+	}
+	$c_obj(make_doclist(cdt, cdn), 'validate_data', '', callback)
+}
+
+//-------------------------------------------------------------------------------
+//
+
 cur_frm.fields_dict['pp_details'].grid.get_field('item_code').get_query = function(doc) {
-  return 'SELECT DISTINCT `tabItem`.`name`,`tabItem`.`item_name` FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life`="0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND tabItem.%(key)s like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
+  return 'SELECT DISTINCT `tabItem`.`name`,`tabItem`.`item_name` FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life`="0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.is_pro_applicable = "Yes" AND tabItem.%(key)s like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
 }
 
-// Get Query for BOM NO
-//-------------------------------------------------------------------------------
 cur_frm.fields_dict['pp_details'].grid.get_field('bom_no').get_query = function(doc) {
   var d = locals[this.doctype][this.docname];
-  return 'SELECT DISTINCT `tabBill Of Materials`.`name` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`item` = "' + d.item_code + '" AND `tabBill Of Materials`.`is_active` = "Yes" AND `tabBill Of Materials`.`name` like "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
-}
-
-cur_frm.cscript['Clear Document Table'] = function(doc, cdt, cdn){
-   $c('runserverobj', args={'method':'clear_table', 'arg': 'pp_so_details', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
-      cur_frm.refresh();
-    });	
-}
-
-cur_frm.cscript['Clear Item Table'] = function(doc, cdt, cdn){
-   $c('runserverobj', args={'method':'clear_table', 'arg': 'pp_details', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
-      cur_frm.refresh();
-    });	
-}
-
-cur_frm.cscript['Download Raw Material Report'] = function(doc, cdt, cdn) {
-  call_back = function(r, rt){
-    if (r.message) {
-      $c_obj_csv(make_doclist(cdt, cdn), 'get_raw_materials_report', '');
-    }
-  }
-  $c('runserverobj', args = {'method':'validate_data','args':'','docs':compress_doclist(make_doclist(doc.doctype, doc.name))}, call_back)
+  return 'SELECT DISTINCT `tabBill Of Materials`.`name` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`item` = "' + d.item_code + '" AND `tabBill Of Materials`.`is_active` = "Yes" AND `tabBill Of Materials`.docstatus = 1 AND `tabBill Of Materials`.`name` like "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
 }
diff --git a/erpnext/production/doctype/production_planning_tool/production_planning_tool.py b/erpnext/production/doctype/production_planning_tool/production_planning_tool.py
index d0ae05b..c2a609d 100644
--- a/erpnext/production/doctype/production_planning_tool/production_planning_tool.py
+++ b/erpnext/production/doctype/production_planning_tool/production_planning_tool.py
@@ -1,281 +1,278 @@
-# Please edit this list and import only required elements
 import webnotes
+from webnotes.utils import cint, cstr, flt, getdate, now, nowdate
+from webnotes.model.doc import addchild
+from webnotes.model.doclist import getlist
+from webnotes.model.code import get_obj
+from webnotes import msgprint, errprint
 
-from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
-from webnotes.model import db_exists
-from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType
-from webnotes.model.doclist import getlist, copy_doclist
-from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
-from webnotes import session, form, is_testing, msgprint, errprint
-
-set = webnotes.conn.set
 sql = webnotes.conn.sql
-get_value = webnotes.conn.get_value
-in_transaction = webnotes.conn.in_transaction
-convert_to_lists = webnotes.conn.convert_to_lists
 	
 # -----------------------------------------------------------------------------------------
 
 
 class DocType:
-  def __init__(self, doc, doclist=[]):
-    self.doc = doc
-    self.doclist = doclist
-    self.item_dict = {}
-    self.defaults = get_defaults()
-    
-  def get_item_details(self, args):
-    args = eval(args)
-    item = sql("select description, stock_uom, default_bom from `tabItem` where name = '%s' and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life >  now())" % args['item_code'], as_dict =1 )
-    if item:
-      ret = {'description' : item and item[0]['description'],
-             'stock_uom'   : item and item[0]['stock_uom'],
-             'bom_no'      : item and item[0]['default_bom']
-      }
-      return ret
-    else:
-      msgprint("Item %s does not exist in system." %(args['item_code']))
-      raise Exception
-    
-  def validate_data(self):
-    for d in getlist(self.doclist, 'pp_details'):
-      if not d.pro_created:
+	def __init__(self, doc, doclist=[]):
+		self.doc = doc
+		self.doclist = doclist
+		self.item_dict = {}
+		
+	def get_item_details(self, item_code):
+		""" Pull other item details from item master"""
 
-        bom = sql("select name from `tabBill Of Materials` where item = %s and docstatus < 2", d.item_code, as_dict = 1)
-        if d.bom_no and not bom:
-          msgprint("There is no Active BOM for item code " + cstr(d.item_code) + " at row no." + cstr(d.idx)+ " which is Submitted. ")
-          raise Exception
-        if bom and bom[0]['name'] and not d.bom_no:
-          msgprint("Please Enter BOM No. for item code " + cstr(d.item_code) + "at row no " + cstr(d.idx))
-          raise Exception
-        item = sql("select is_purchase_item from `tabItem` where name = %s", d.item_code,as_dict = 1)
-#        if not item[0]['is_mrp_item']:
-#          msgprint("Please Delete Row No " + cstr(d.idx) + " as Item " + cstr(d.item_code) + " is not MRP ITEM ")
-#          raise Exception
-        if not item[0]['is_purchase_item'] and not d.bom_no:
-          msgprint("Please Delete Row No. "+ cstr(d.idx)+" as Item " + cstr(d.item_code) + " is not a PURCHASE ITEM ")
-          raise Exception
-        if not flt(d.planned_qty):
-          msgprint("Please Enter Planned Qty for item code " + cstr(d.item_code) + "at row no " + cstr(d.idx))
-          raise Exception
-        if flt(d.prevdoc_reqd_qty) and flt(d.planned_qty) > flt(d.prevdoc_reqd_qty):
-          msgprint(" Planned Qty cannot be greater than total Qty at row no " + cstr(d.idx))
-          raise Exception
-          
-        item = sql("select is_manufactured_item, is_sub_contracted_item from`tabItem` where name = %s", d.item_code, as_dict = 1)
-        if not item:
-          msgprint("Item %s is not present in Item Master." % d.item_code)
-          raise Exception
+		item = sql("""select description, stock_uom, default_bom from `tabItem` where name = %s 
+			and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now())""", item_code, as_dict =1 )
+		ret = {
+			'description'	: item and item[0]['description'],
+			'stock_uom'		: item and item[0]['stock_uom'],
+			'bom_no'		: item and item[0]['default_bom']
+		}
+		return ret
+	
 
-        if item[0]['is_manufactured_item'] == 'Yes' or item[0]['is_sub_contracted_item'] == 'Yes':
-          bom = sql("select name, docstatus from `tabBill Of Materials` where item = %s", d.item_code, as_dict =1)
-          if bom and bom[0]['name']:
-            if not d.bom_no:
-              msgprint("Please Enter BOM No for Item " + cstr(d.item_code) + " in Materials at Row No. " + cstr(d.idx)  + " in BOM NO. " + self.doc.name)
-              raise Exception
-            else:
-              match = 0
-              for b in bom:
-                  if flt(b['docstatus']) > 1:
-                    msgprint("BOM %s is NOT SUBMITTED."% cstr(d.bom_no))
-                    raise Exception
-              
-                  match = 1
-              if not match:
-                msgprint("Item %s does not belong to Bill Of Material %s or Bill Of Material %s is NOT ACTIVE BOM." % (cstr(d.item_code),cstr(d.bom_no), cstr(d.bom_no)))
-                raise Exception
-    
-        if not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item']== 'Yes':
-          if d.bom_no:
-            msgprint("As in Item Master of Item %s Is Manufactured Item / Is Sub-Contracted Item  is not 'Yes' hence there should be no BOM." % d.item_code)
-            raise Exception
+	def get_so_details(self, so):
+		"""Pull other details from so"""
+		so = sql("select transaction_date, customer, grand_total from `tabSales Order` where name = %s", so, as_dict = 1)
+		ret = {
+			'sales_order_date': so and so[0]['transaction_date'] or '',
+			'customer' : so[0]['customer'] or '',
+			'grand_total': so[0]['grand_total']
+		}
+		return ret
 
-    return 1
 
-  def pull_document(self):
-    if self.doc.sales_order:
-      open_so = sql("select distinct 'Sales Order' as prevdoc, t1.name, ifnull(t1.transaction_date, ''), ifnull(t2.confirmation_date,'') from `tabSales Order` t1, `tabSales Order Detail` t2, `tabDelivery Note Packing Detail` t3 where ifnull(t3.planned_qty,0) < ifnull(t3.qty,0) and (t2.qty - ifnull(t2.delivered_qty,0)) > 0 and t3.parent_detail_docname =  t2.name and t2.parent = t1.name and t1.docstatus = 1 and t1.name = '%s' order by t1.transaction_date" % self.doc.sales_order)
-      self.add_open_documents(open_so)
-    #if self.doc.production_forecast:
-      #open_pf = sql("select distinct 'Production Forecast' as prevdoc, t1.name, ifnull(t1.transaction_date,''), ifnull(t1.forecast_due_date,'') from `tabProduction Forecast` t1, `tabPF Detail` t2 where t2.planned_qty < t2.qty and t2.parent = t1.name and t1.name = '%s' and t1.docstatus = 1  order by t1.forecast_due_date " % self.doc.production_forecast)
-      #self.add_open_documents(open_pf)
-      
-  def validate_duplicate_docname(self, check_data):
-    for d in getlist(self.doclist, 'pp_so_details'):
-      if [ d.prevdoc_docname, d.document_date, d.confirmation_date] == check_data :
-        msgprint(cstr(d.prevdoc) + ": " + cstr(d.prevdoc_docname) + " appears more than once.")
-        raise Exception
-    
-  def add_open_documents(self, open_doc):
-    for r in open_doc:
-      self.validate_duplicate_docname([r[1], r[2], r[3]])
-      pp_so = addchild(self.doc, 'pp_so_details', 'PP SO Detail', 1, self.doclist)
-      pp_so.prevdoc = r[0]
-      pp_so.prevdoc_docname = r[1] 
-      pp_so.document_date = cstr(r[2])
-      pp_so.confirmation_date = cstr(r[3])
-      pp_so.save()
- 
-  def get_open_docs(self):
-    # Step 1:=> Remove unwanted rows from PP SO DETAIL TABLE
-    self.remove_unwanted_rows_from_table(check_field ='include_in_plan', table_fname='pp_so_details')
-    
-    # Step 2:=> Check From Date should be before To Date
-    if self.doc.from_date:
-      if (getdate(self.doc.from_date) > getdate(self.doc.to_date)):
-        msgprint("From Date cannot be after To Date")
-        raise Exception
-    
-    # Step 3:=> At Least to date should be there
-    if not self.doc.to_date:
-      msgprint("To Date is Mandatory.")
-      raise Exception
+	def clear_so_table(self):
+		""" Clears sales order table"""
+		self.doc.clear_table(self.doclist, 'pp_so_details')
 
-    # Step 4:=> GEt Open Sales ORder and Production Forecasts
-    open_so = sql("select distinct 'Sales Order' as prevdoc, t1.name, t1.transaction_date, t2.confirmation_date from `tabSales Order` t1, `tabSales Order Detail` t2 where  (t2.qty - ifnull(t2.delivered_qty,0)) > 0 and t2.parent = t1.name %s and t1.transaction_date <= '%s' and t1.docstatus = 1 order by t1.transaction_date" % ((self.doc.from_date and "and t1.transaction_date >= '%s' " % self.doc.from_date or '') , self.doc.to_date))
-    #open_pf = sql("select distinct 'Production Forecast' as prevdoc, t1.name, t1.transaction_date, t1.forecast_due_date from `tabProduction Forecast` t1, `tabPF Detail` t2 where ifnull(t2.planned_qty,0) < ifnull(t2.qty,0) and t1.name = t2.parent %s and t1.forecast_due_date <= '%s' and t1.docstatus = 1  order by t1.forecast_due_date " % ( self.doc.from_date and "and t1.forecast_due_date >= '%s' " % self.doc.from_date or '', self.doc.to_date))
-    #open_doc = open_so + open_pf
-    open_doc = open_so
-    self.add_open_documents(open_doc)
-    
-  def remove_unwanted_rows_from_table(self, check_field, table_fname):
-    for d in getlist(self.doclist, table_fname):
-      if not d.fields[check_field]:
-        d.fields['__oldparent'] = d.parent
-        d.parent = 'old_parent:' + d.parent # for client to send it back while saving
-        d.docstatus = 2
-        if not d.fields.get('__islocal'):
-          d.save()
-      else:
-        d.save()
 
-  def get_packing_list_items(self, sales_order):
-    #sales_com_obj.make_packing_list(self,'sales_order_details')
-    pack_l = sql("select t2.name, t2.parent_item, t2.item_code, t0.transaction_date, t1.confirmation_date,(t1.qty - ifnull(t1.delivered_qty,0)) * (ifnull(t2.qty,0) / ifnull(t1.qty,1)) as 'pending_qty' from `tabSales Order` t0, `tabSales Order Detail` t1, `tabDelivery Note Packing Detail` t2 where ifnull(t2.planned_qty,0) < ifnull(t2.qty,0) and (t1.qty - ifnull(t1.delivered_qty,0)) > 0 and t2.parent_detail_docname = t1.name and t0.name = t1.parent and t1.parent = '%s' and t2.parent = '%s' and t1.docstatus =1 and t2.docstatus = 1" % (sales_order, sales_order), as_dict =1)
-    for p in pack_l:
-      pi = addchild(self.doc, 'pp_details', 'PP Detail', 0, self.doclist)
-      pi.source_doctype        = 'Sales Order'
-      pi.source_docname        = sales_order
-      pi.source_detail_docname = p['name']
-      pi.parent_item           = p['parent_item']
-      pi.item_code             = p['item_code']
-      pi.document_date         = cstr(p['transaction_date'])
-      pi.confirmation_date     = cstr(p['confirmation_date'])
-      item_details = sql("select description, stock_uom from tabItem where name=%s and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life >  now())", p['item_code'])
-      pi.description = item_details and item_details[0][0] or ''
-      pi.stock_uom = item_details and item_details[0][1] or ''
-      pi.prevdoc_reqd_qty = flt(p['pending_qty'])
-      pi.save()
-  
-  def get_items(self):
-    # Step 1:=> Remove unwanted rows from PP SO DETAIL TABLE
-    self.remove_unwanted_rows_from_table(check_field ='include_in_plan', table_fname='pp_so_details')
-    # Step 2:=> Remove unwanted rows from PP DETAIL TABLE
-    self.doc.clear_table(self.doclist, 'pp_details', 1)
-    # Step 3:=> Get All Details From Production Forecast and Sales Order which are marked Include In Plan in PP SO Detail
-    for d in getlist(self.doclist, 'pp_so_details'):
-      if d.include_in_plan:
-        # Step 3.a :=> Get packing List items from sales order
-        if d.prevdoc == 'Sales Order':
-          self.get_packing_list_items(d.prevdoc_docname)
-        # Step 3.b :=> Get Production Forecast items
-        if d.prevdoc == 'Production Forecast':
-          get_obj('DocType Mapper', 'Production Forecast-Production Planning Tool').dt_map('Production Forecast','Production Planning Tool', d.prevdoc_docname, self.doc, self.doclist, "[['Production Forecast','Production Planning Tool'],['PF Detail', 'PP Detail']]")
 
-    self.set_defaults_pp_detail()
+	def clear_item_table(self):
+		""" Clears item table"""
+		self.doc.clear_table(self.doclist, 'pp_details')
 
-  def clear_table(self, table_name = ''):
-    self.doc.clear_table(self.doclist, table_name, 1)
 
-  def set_defaults_pp_detail(self):
-    for d in getlist(self.doclist,'pp_details'):
-      if not d.mrp:
-        # set default BOM
-        if not d.bom_no:
-          bom = sql("select default_bom from `tabItem` where name = %s and (ifnull(end_of_life,'')='' or end_of_life ='0000-00-00' or end_of_life >  now())", d.item_code, as_dict = 1)
-          if bom and bom[0]['default_bom']:
-            d.bom_no = bom[0]['default_bom']
-        # Set planned qty as prevdoc_reqd_qty 
-        d.planned_qty = flt(d.prevdoc_reqd_qty)
-        d.save()
 
-  def make_items_dict(self, items_list):
-    # items_list = [[item_name, qty]]
-    for i in items_list:
-      if self.item_dict.has_key(i[0]):
-        self.item_dict[i[0]] = flt(self.item_dict[i[0]]) + flt(i[1])
-      else:
-        self.item_dict[i[0]] = flt(i[1])
+	def get_open_sales_orders(self):
+		""" Pull sales orders  which are pending to deliver based on criteria selected"""
+		cond = self.get_filter_condition()
+		open_so = sql("""
+			select 
+				distinct t1.name, t1.transaction_date, t1.customer, t1.grand_total 
+			from 
+				`tabSales Order` t1, `tabSales Order Detail` t2, `tabDelivery Note Packing Detail` t3, tabItem t4
+			where 
+				t1.name = t2.parent and t1.name = t3.parent and t3.parenttype = 'Sales Order' and t1.docstatus = 1 and t2.item_code = t3.parent_item 
+				and t4.name = t3.item_code and  t1.status != 'Stopped' and t1.company = '%s' and ifnull(t2.qty, 0) > ifnull(t2.delivered_qty, 0) 
+				and (ifnull(t4.is_pro_applicable, 'No') = 'Yes' or ifnull(t4.is_sub_contracted_item, 'No') = 'Yes') %s
+			order by t1.name desc
+		"""% (self.doc.company, cond), as_dict = 1)
 
-  def get_raw_materials(self, bom_dict):
-    for bom in bom_dict:
-      # get all purchase items
-      if self.doc.consider_sa_items == 'No':
-        fl_bom_items = sql("select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s' from `tabFlat BOM Detail` where parent = '%s' and is_pro_applicable = 'No' and docstatus < 2 group by item_code" % (bom_dict[bom], bom))
-        self.make_items_dict(fl_bom_items)
-      
-      # get all purchase items without sa child_items
-      if self.doc.consider_sa_items == 'Yes':
-        fl_bom_sa_items = sql("select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s' from `tabFlat BOM Detail` where parent = '%s' and parent_bom != '%s' and is_pro_applicable = 'Yes' and docstatus < 2 group by item_code" % (bom_dict[bom], bom, bom))
-        self.make_items_dict(fl_bom_sa_items)
-        fl_bom_items = sql("select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s' from `tabFlat BOM Detail` where parent = '%s' and parent_bom not in (select distinct parent_bom from `tabFlat BOM Detail` where parent = '%s' and parent_bom != '%s' and is_pro_applicable = 'Yes' and docstatus <2) and docstatus < 2 and is_pro_applicable = 'No' group by item_code" % (bom_dict[bom], bom, bom, bom) )
-        self.make_items_dict(fl_bom_items)
-        
-    return self.item_dict
-    
-  def send_csv(self, item_dict):
-    item_list = [['Item Code', 'Description', 'Stock UOM','Required Qty', 'Indented Qty', 'Ordered Qty', 'Actual Qty', ]]
-    for d in item_dict:
-      item_detail = sql("select description, stock_uom from `tabItem` where name = '%s'" % d)
-      item_qty= sql("select sum(indented_qty), sum(ordered_qty), sum(actual_qty) from `tabBin` where item_code  = '%s' " % d)
-      item_list.append([d, cstr(item_detail[0][0]), cstr(item_detail[0][1]), flt(item_dict[d]), item_qty and flt(item_qty[0][0]), item_qty and flt(item_qty[0][1]), item_qty and flt(item_qty[0][2])])
-    return item_list
-    
-  def get_raw_materials_report(self):
-    #self.validate_data()
-    bom_dict = self.check_criteria_for_same_items(check_for = 'Report')
-    item_dict = self.get_raw_materials(bom_dict)
-    #msgprint(item_dict)
-    #raise Exception
-    return self.send_csv(item_dict)
-    
-  def raise_production_order(self):
-    self.validate_data()
-    pp_detail = self.check_criteria_for_same_items(check_for = 'Raise Production Order')
-    pro = get_obj(dt = 'Production Control').create_production_order(self.doc.company, self.doc.fiscal_year, pp_detail = pp_detail)
-    if len(pro) == 1:
-      result = "Only Production Order " + cstr(pro[0]) + " has been generated."
-    elif len(pro) > 1 :
-      result = "Production Order From " + cstr(pro[0]) + " to "  + cstr(pro[len(pro) - 1]) +  " has been generated."
-    else :
-      result = " No Production Order is generated."
-    msgprint(result)
+		self.add_so_in_table(open_so)
 
-  def check_criteria_for_same_items(self, check_for):
-    pro_lbl = {'production_item': 0, 'description': 1, 'qty' : 2, 'stock_uom' : 3, 'bom_no': 4, 'consider_sa_items': 5}
-    pp_detail, appended, bom_dict = [], 0, {}
-    for d in getlist(self.doclist, 'pp_details'):
-      if check_for == 'Report':
-        if d.bom_no:
-          if bom_dict.has_key(d.bom_no):
-            bom_dict[d.bom_no] = flt(bom_dict[d.bom_no]) + flt(d.planned_qty)
-          else:
-            bom_dict[d.bom_no] = flt(d.planned_qty)
-        else:
-          self.make_items_dict([[d.item_code, d.planned_qty]])
-          
-      if check_for == 'Raise Production Order' and not d.pro_created:
-        appended = 0
-        if pp_detail:
-          for i in pp_detail:
-            # if same bom_no 
-            if d.bom_no and d.bom_no == i[pro_lbl['bom_no']]:
-              # set appended , add qty 
-              appended, i[pro_lbl['qty']], d.pro_created = 1, i[pro_lbl['qty']] + flt(d.planned_qty) , 1
-            
-        if not appended and d.bom_no:
-          pp_detail.append([d.item_code, d.description, d.planned_qty, d.stock_uom, d.bom_no, self.doc.consider_sa_items])
-          d.pro_created = 1
-        
-        d.save()
-    return (check_for =='Report') and bom_dict or pp_detail
\ No newline at end of file
+
+
+	def validate_company(self):
+		if not self.doc.company:
+			msgprint("Please enter Company", raise_exception=1)
+
+		
+
+	def get_filter_condition(self):
+		self.validate_company()
+
+		cond = ''
+		if self.doc.from_date:
+			cond += ' and t1.transaction_date >= "' + self.doc.from_date + '"'
+		if self.doc.to_date:
+			cond += ' and t1.transaction_date <= "' + self.doc.to_date + '"'
+		if self.doc.customer:
+			cond += ' and t1.customer = "' + self.doc.customer + '"'
+		if self.doc.fg_item:
+			cond += ' and t3.item_code = "' + self.doc.fg_item + '"'
+
+		return cond
+
+
+
+	def add_so_in_table(self, open_so):
+		""" Add sales orders in the table"""
+		so_list = []
+		for d in getlist(self.doclist, 'pp_so_details'):
+			so_list.append(d.sales_order)
+		for r in open_so:
+			if cstr(r['name']) not in so_list:
+				pp_so = addchild(self.doc, 'pp_so_details', 'PP SO Detail', 1, self.doclist)
+				pp_so.sales_order = r['name']
+				pp_so.sales_order_date = cstr(r['transaction_date'])
+				pp_so.customer = cstr(r['customer'])
+				pp_so.grand_total = flt(r['grand_total'])
+
+
+
+	def get_items_from_so(self):
+		""" Pull items from Sales Order, only proction item
+			and subcontracted item will be pulled from Packing item 
+			and add items in the table
+		"""
+		so = self.get_included_so()
+		items = self.get_packing_items(so)
+		self.add_items(items)
+
+
+	def get_included_so(self):
+		so = "'" + "','".join([cstr(d.sales_order) for d in getlist(self.doclist, 'pp_so_details') if d.include_in_plan]) + "'"
+		return so
+
+
+
+	def get_packing_items(self, so):
+		packing_items = sql("""
+			select 
+				t0.name, t2.parent_item, t2.item_code, 
+				(t1.qty - ifnull(t1.delivered_qty,0)) * (ifnull(t2.qty,0) / ifnull(t1.qty,1)) as 'pending_qty' 
+			from
+				`tabSales Order` t0, `tabSales Order Detail` t1, `tabDelivery Note Packing Detail` t2, `tabItem` t3
+			where 
+				t0.name = t1.parent and t0.name = t2.parent and t1.name = t2.parent_detail_docname
+				and t0.name in (%s) and t0.docstatus = 1 and t1.qty > ifnull(t1.delivered_qty,0) and t3.name = t2.item_code 
+				and (ifnull(t3.is_pro_applicable, 'No') = 'Yes' or ifnull(t3.is_sub_contracted_item, 'No') = 'Yes')
+		""" % so, as_dict=1)
+		return packing_items
+		
+
+
+	def add_items(self, packing_items):
+		for d in getlist(self.doclist, 'pp_details'):
+			if d.sales_order:
+				d.parent = ''
+
+		for p in packing_items:	
+			item_details = sql("select description, stock_uom, default_bom from tabItem where name=%s", p['item_code'])
+			pi = addchild(self.doc, 'pp_details', 'PP Detail', 1, self.doclist)
+			pi.sales_order				= p['name']
+			pi.parent_packing_item		= p['parent_item']
+			pi.item_code				= p['item_code']
+			pi.description				= item_details and item_details[0][0] or ''
+			pi.stock_uom				= item_details and item_details[0][1] or ''
+			pi.bom_no					= item_details and item_details[0][2] or ''
+			pi.so_pending_qty			= flt(p['pending_qty'])
+			pi.planned_qty				= flt(p['pending_qty'])
+	
+
+
+	def validate_data(self):
+		for d in getlist(self.doclist, 'pp_details'):
+			if not d.pro_created:
+				self.validate_bom_no(d)
+
+				if not flt(d.planned_qty):
+					msgprint("Please Enter Planned Qty for item: %s at row no: %s"% (d.item_code, d.idx), raise_exception=1)
+		return 'validated'
+
+				
+
+	def validate_bom_no(self, d):
+		if not d.bom_no:
+			msgprint("Please enter bom no for item: %s at row no: %s" % (d.item_code, d.idx), raise_exception=1)
+		else:
+			bom = sql("""select name from `tabBill Of Materials` where item = %s and docstatus = 1 
+				and name = %s and ifnull(is_active, 'No') = 'Yes'""", (d.item_code, d.bom_no), as_dict = 1)
+			if not bom:
+				msgprint("""Incorrect BOM No: %s entered for item: %s at row no: %s
+					May be BOM is inactive or for other item or does not exists in the system"""% (d.bom_no, d.item_doce, d.idx))
+
+
+
+	def download_raw_materials(self):
+		""" Create csv data for required raw material to produce finished goods"""
+		bom_dict = self.get_distinct_bom(action = 'download_rm')
+		self.get_raw_materials(bom_dict)
+		return self.get_csv()
+
+
+
+	
+	def get_raw_materials(self, bom_dict):
+		""" Get raw materials considering sub-assembly items """
+		for bom in bom_dict:
+			if self.doc.consider_sa_items == 'Yes':
+				# Get all raw materials considering SA items as raw materials, 
+				# so no childs of SA items
+				fl_bom_items = sql("""
+					select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s', description, stock_uom 
+					from `tabBOM Material` 
+					where parent = '%s' and docstatus < 2 
+					group by item_code
+				""" % (flt(bom_dict[bom]), bom))
+
+			else:
+				# get all raw materials with sub assembly childs					
+				fl_bom_items = sql("""
+					select 
+						item_code,ifnull(sum(qty_consumed_per_unit),0)*%s as qty, description, stock_uom
+					from 
+						( 
+							select distinct fb.name, fb.description, fb.item_code, fb.qty_consumed_per_unit, fb.stock_uom 
+							from `tabFlat BOM Detail` fb,`tabItem` it 
+							where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No'
+							and ifnull(it.is_sub_contracted_item, 'No') = 'No' and fb.docstatus<2 and fb.parent=%s
+						) a
+					group by item_code,stock_uom
+				""" , (flt(bom_dict[bom]), bom))
+			
+			self.make_items_dict(fl_bom_items)
+
+
+
+	def make_items_dict(self, item_list):
+		for i in item_list:
+			self.item_dict[i[0]] = [(flt(self.item_dict.get(i[1], 0)) + flt(i[1])), i[2], i[3]]
+
+
+	def get_csv(self):
+		item_list = [['Item Code', 'Description', 'Stock UOM', 'Required Qty', 'Indented Qty', 'Ordered Qty', 'Actual Qty']]
+		for d in self.item_dict:
+			item_qty= sql("select sum(indented_qty), sum(ordered_qty), sum(actual_qty) from `tabBin` where item_code = %s", d)
+			item_list.append([d, self.item_dict[d][1], self.item_dict[d][2], self.item_dict[d][0], flt(item_qty[0][0]), flt(item_qty[0][1]), flt(item_qty[0][2])])
+		return item_list
+		
+
+
+	def raise_production_order(self):
+		"""It will raise production order (Draft) for all distinct FG items"""
+		self.validate_company()
+		self.validate_data()
+
+		pp_items = self.get_distinct_bom(action = 'raise_pro_order')
+		pro = get_obj(dt = 'Production Control').create_production_order(self.doc.company, pp_items)
+		if pro:
+			for d in getlist(self.doclist, 'pp_details'):
+				d.is_pro_created = 1
+			msgprint("Following Production Order has been generated:\n" + '\n'.join(pro))
+		else :
+			msgprint("No Production Order is generated.")
+
+
+
+	def get_distinct_bom(self, action):
+		""" Club similar BOM and item for processing"""
+
+		bom_dict, item_dict, pp_items = {}, {}, []
+		for d in getlist(self.doclist, 'pp_details'):
+			if action == 'download_rm':
+				bom_dict[d.bom_no] = bom_dict.get(d.bom_no, 0) + flt(d.planned_qty)
+			elif not d.is_pro_created:
+				item_dict[d.item_code] = [(item_dict.get(d.item_code, 0) + flt(d.planned_qty)), d.bom_no, d.description, d.stock_uom]
+
+		if action == 'raise_pro_order':
+			for d in item_dict:
+				pp_items.append({
+					'production_item'	: d, 
+					'qty'				: item_dict[d][0],
+					'bom_no'			: item_dict[d][1],
+					'description'		: item_dict[d][2],
+					'stock_uom'			: item_dict[d][3],
+					'consider_sa_items' : self.doc.consider_sa_items
+				})
+
+		return action == 'download_rm' and bom_dict or pp_items
diff --git a/erpnext/production/doctype/production_planning_tool/production_planning_tool.txt b/erpnext/production/doctype/production_planning_tool/production_planning_tool.txt
index 516dba8..14b0b75 100644
--- a/erpnext/production/doctype/production_planning_tool/production_planning_tool.txt
+++ b/erpnext/production/doctype/production_planning_tool/production_planning_tool.txt
@@ -5,15 +5,16 @@
 	{
 		'creation': '2010-08-08 17:09:14',
 		'docstatus': 0,
-		'modified': '2010-12-30 14:49:58',
-		'modified_by': 'umair@iwebnotes.com',
+		'modified': '2012-01-10 16:26:10',
+		'modified_by': 'Administrator',
 		'owner': 'jai@webnotestech.com'
 	},
 
 	# These values are common for all DocType
 	{
-		'_last_update': '1294312191',
+		'_last_update': '1326188323',
 		'colour': 'White:FFF',
+		'default_print_format': 'Standard',
 		'doctype': 'DocType',
 		'in_create': 1,
 		'issingle': 1,
@@ -23,7 +24,7 @@
 		'section_style': 'Tabbed',
 		'server_code_error': ' ',
 		'show_in_menu': 1,
-		'version': 87
+		'version': 106
 	},
 
 	# These values are common for all DocField
@@ -58,32 +59,34 @@
 	# DocPerm
 	{
 		'doctype': 'DocPerm',
-		'idx': 1,
 		'role': 'System Manager'
 	},
 
 	# DocPerm
 	{
 		'doctype': 'DocPerm',
-		'idx': 2,
 		'role': 'Production User'
 	},
 
 	# DocPerm
 	{
 		'doctype': 'DocPerm',
-		'idx': 3,
 		'role': 'Production Manager'
 	},
 
 	# DocField
 	{
 		'colour': 'White:FFF',
-		'description': 'Select Sales Orders from which you want to create Production Orders. Enter the From and To Dates to get Open Orders in that period.',
 		'doctype': 'DocField',
 		'fieldtype': 'Section Break',
-		'idx': 1,
-		'label': 'Find Sales Orders'
+		'label': 'Select Sales Orders'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldtype': 'Column Break',
+		'width': '50%'
 	},
 
 	# DocField
@@ -91,7 +94,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'from_date',
 		'fieldtype': 'Date',
-		'idx': 2,
 		'label': 'From Date'
 	},
 
@@ -100,125 +102,70 @@
 		'doctype': 'DocField',
 		'fieldname': 'to_date',
 		'fieldtype': 'Date',
-		'idx': 3,
 		'label': 'To Date'
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
+		'fieldname': 'fg_item',
+		'fieldtype': 'Link',
+		'label': 'FG Item',
+		'options': 'Item'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
 		'fieldtype': 'Column Break',
-		'idx': 4,
-		'width': '40%'
+		'width': '50%'
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldtype': 'Button',
-		'idx': 5,
-		'label': 'Get Open Documents',
-		'options': 'get_open_docs'
+		'fieldname': 'customer',
+		'fieldtype': 'Link',
+		'label': 'Customer',
+		'options': 'Customer'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldname': 'company',
+		'fieldtype': 'Link',
+		'label': 'Company',
+		'options': 'Company',
+		'reqd': 1
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
 		'fieldtype': 'Section Break',
-		'idx': 6,
-		'options': 'Simple'
-	},
-
-	# DocField
-	{
-		'colour': 'White:FFF',
-		'doctype': 'DocField',
-		'fieldtype': 'Button',
-		'idx': 7,
-		'label': 'Clear Document Table',
-		'trigger': 'Client'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'pp_so_details',
-		'fieldtype': 'Table',
-		'idx': 8,
-		'label': 'PP SO Details',
-		'options': 'PP SO Detail'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'Section Break',
-		'idx': 9,
 		'options': 'Simple'
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'sales_order',
-		'fieldtype': 'Link',
-		'idx': 10,
-		'label': 'Sales Order',
-		'options': 'Sales Order'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'production_forecast',
-		'fieldtype': 'Link',
-		'hidden': 1,
-		'idx': 11,
-		'label': 'Production Forecast',
-		'options': 'Production Forecast'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldtype': 'Column Break',
-		'idx': 12,
-		'width': '40%'
+		'width': '50%'
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
 		'fieldtype': 'Button',
-		'idx': 13,
-		'label': 'Add In Plan',
-		'options': 'pull_document'
-	},
-
-	# DocField
-	{
-		'colour': 'White:FFF',
-		'description': 'Click on "Get Items" to get un-fulfilled items from your Sales Orders. After setting the quantities you can raise Production Orders or download the material requirements for analysis',
-		'doctype': 'DocField',
-		'fieldtype': 'Section Break',
-		'idx': 14,
-		'label': 'Items'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'Button',
-		'idx': 15,
-		'label': 'Get Items',
-		'options': 'get_items'
+		'label': 'Get Sales Orders',
+		'options': 'get_open_sales_orders'
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
 		'fieldtype': 'Column Break',
-		'idx': 16,
 		'width': '50%'
 	},
 
@@ -227,8 +174,8 @@
 		'colour': 'White:FFF',
 		'doctype': 'DocField',
 		'fieldtype': 'Button',
-		'idx': 17,
-		'label': 'Clear Item Table',
+		'label': 'Clear SO Table',
+		'options': 'clear_so_table',
 		'trigger': 'Client'
 	},
 
@@ -236,20 +183,78 @@
 	{
 		'doctype': 'DocField',
 		'fieldtype': 'Section Break',
-		'idx': 18,
 		'options': 'Simple'
 	},
 
 	# DocField
 	{
+		'description': 'Select Sales Orders from which you want to create Production Orders. You can get sales orders based on above criteria.',
+		'doctype': 'DocField',
+		'fieldname': 'pp_so_details',
+		'fieldtype': 'Table',
+		'label': 'PP SO Details',
+		'options': 'PP SO Detail'
+	},
+
+	# DocField
+	{
+		'colour': 'White:FFF',
+		'doctype': 'DocField',
+		'fieldtype': 'Section Break',
+		'label': 'Items'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldtype': 'Button',
+		'label': 'Get Items from SO',
+		'options': 'get_items_from_so'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldtype': 'Column Break',
+		'width': '50%'
+	},
+
+	# DocField
+	{
+		'colour': 'White:FFF',
+		'doctype': 'DocField',
+		'fieldtype': 'Button',
+		'label': 'Clear Item Table',
+		'options': 'clear_item_table',
+		'trigger': 'Client'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
+		'fieldtype': 'Section Break',
+		'options': 'Simple'
+	},
+
+	# DocField
+	{
+		'description': 'Enter items and planned qty for which you want to raise production orders or download raw materials for analysis. You can pull items (which are pending to deliver) from SO as well by adding SO in plan.',
+		'doctype': 'DocField',
+		'fieldname': 'pp_details',
+		'fieldtype': 'Table',
+		'label': 'PP Details',
+		'options': 'PP Detail'
+	},
+
+	# DocField
+	{
 		'colour': 'White:FFF',
 		'default': 'No',
 		'description': 'Select "Yes" if stock is maintained and tracked for sub assembly items.',
 		'doctype': 'DocField',
 		'fieldname': 'consider_sa_items',
 		'fieldtype': 'Select',
-		'idx': 19,
-		'label': 'Consider Sub Assemblies',
+		'label': 'Consider Sub Assemblies as Raw Material',
 		'options': 'No\nYes',
 		'reqd': 1
 	},
@@ -257,26 +262,21 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'pp_details',
-		'fieldtype': 'Table',
-		'idx': 20,
-		'label': 'PP Details',
-		'options': 'PP Detail'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldtype': 'Section Break',
-		'idx': 21,
 		'options': 'Simple'
 	},
 
 	# DocField
 	{
 		'doctype': 'DocField',
+		'fieldtype': 'Column Break',
+		'width': '50%'
+	},
+
+	# DocField
+	{
+		'doctype': 'DocField',
 		'fieldtype': 'Button',
-		'idx': 22,
 		'label': 'Raise Production Order',
 		'options': 'raise_production_order'
 	},
@@ -285,7 +285,6 @@
 	{
 		'doctype': 'DocField',
 		'fieldtype': 'Column Break',
-		'idx': 23,
 		'width': '50%'
 	},
 
@@ -294,37 +293,7 @@
 		'colour': 'White:FFF',
 		'doctype': 'DocField',
 		'fieldtype': 'Button',
-		'idx': 24,
-		'label': 'Download Raw Material Report',
+		'label': 'Download Raw Material',
 		'trigger': 'Client'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldtype': 'Section Break',
-		'idx': 25,
-		'label': 'Company Info'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'fiscal_year',
-		'fieldtype': 'Select',
-		'idx': 26,
-		'in_filter': 1,
-		'label': 'Fiscal Year',
-		'options': 'Link:Fiscal Year'
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
-		'fieldname': 'company',
-		'fieldtype': 'Link',
-		'idx': 27,
-		'label': 'Company',
-		'options': 'Company'
 	}
 ]
\ No newline at end of file
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 9eeb11f..c94e71d 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -73,6 +73,7 @@
 		return ret
 
 		
+
 	# get stock and incoming rate on posting date
 	# ---------------------------------------------
 	def get_stock_and_rate(self, bom_no = ''):
@@ -86,8 +87,9 @@
 
 			# get incoming rate
 			if not flt(d.incoming_rate):
-				d.incoming_rate = self.get_incoming_rate(d.item_code, d.s_warehouse, self.doc.posting_date, self.doc.posting_time, d.transfer_qty, d.serial_no, d.fg_item, bom_no)
-			
+				d.incoming_rate = self.get_incoming_rate(d.item_code, d.s_warehouse, self.doc.posting_date, self.doc.posting_time, d.transfer_qty, d.serial_no, d.fg_item, d.bom_no or bom_no)
+
+
 	# Get stock qty on any date
 	# ---------------------------
 	def get_as_on_stock(self, item, wh, dt, tm):
@@ -97,29 +99,47 @@
 		qty = flt(prev_sle.get('bin_aqat', 0))
 		return qty
 
+
 	# Get incoming rate
 	# -------------------
-	def get_incoming_rate(self, item, wh, dt, tm, qty = 0, serial_no = '', fg_item = 'No', bom_no = ''):
+	def get_incoming_rate(self, item, wh, dt, tm, qty = 0, serial_no = '', fg_item = 0, bom_no = ''):
 		in_rate = 0
-		if fg_item == 'Yes':
+		if fg_item and bom_no:
 			# re-calculate cost for production item from bom
 			get_obj('BOM Control').calculate_cost(bom_no)
-			in_rate = get_value('Bill Of Materials', bom_no, 'cost_as_per_mar')
+			in_rate = flt(get_value('Bill Of Materials', bom_no, 'total_cost'))
 		elif wh:
 			in_rate = get_obj('Valuation Control').get_incoming_rate(dt, tm, item, wh, qty, serial_no)
 		
 		return in_rate
 
-	# makes dict of unique items with it's qty
-	#-----------------------------------------
+
+
 	def make_items_dict(self, items_list):
-		# items_list = [[item_name, qty]]
+		"""makes dict of unique items with it's qty"""
 		for i in items_list:
 			if self.item_dict.has_key(i[0]):
 				self.item_dict[i[0]][0] = flt(self.item_dict[i[0]][0]) + flt(i[1])
 			else:
 				self.item_dict[i[0]] = [flt(i[1]), cstr(i[2]), cstr(i[3])]
 				
+
+
+	def update_only_remaining_qty(self):
+		""" Only pending raw material to be issued to shop floor """
+		already_issued_item = {}
+		for t in sql("""select t1.item_code, sum(t1.qty) from `tabStock Entry Detail` t1, `tabStock Entry` t2
+				where t1.parent = t2.name and t2.production_order = %s and t2.process = 'Material Transfer' 
+				and t2.docstatus = 1 group by t1.item_code""", self.doc.production_order):
+			already_issued_item[t[0]] = flt(t[1])
+
+		for d in self.item_dict.keys():
+			self.item_dict[d][0] -= already_issued_item.get(d, 0)
+			if self.item_dict[d][0] <= 0:
+				del self.item_dict[d]
+
+
+
 	def get_raw_materials(self,pro_obj):
 		""" 
 			get all items from flat bom except 
@@ -130,7 +150,6 @@
 		if pro_obj.doc.consider_sa_items == 'Yes':
 			# Get all raw materials considering SA items as raw materials, 
 			# so no childs of SA items
-			
 			fl_bom_sa_items = sql("""
 				select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s', description, stock_uom 
 				from `tabBOM Material` 
@@ -138,12 +157,10 @@
 				group by item_code
 			""" % ((self.doc.process == 'Backflush') and flt(self.doc.fg_completed_qty) \
 					 or flt(pro_obj.doc.qty), cstr(pro_obj.doc.bom_no)))
-			
 			self.make_items_dict(fl_bom_sa_items)
-		
-		if pro_obj.doc.consider_sa_items == 'No':
-			# get all raw materials with sub assembly childs
-					
+
+		else:
+			# get all raw materials with sub assembly childs					
 			fl_bom_sa_child_item = sql("""
 				select 
 					item_code,ifnull(sum(qty_consumed_per_unit),0)*%s as qty,description,stock_uom 
@@ -152,17 +169,20 @@
 						select distinct fb.name, fb.description, fb.item_code, fb.qty_consumed_per_unit, fb.stock_uom 
 						from `tabFlat BOM Detail` fb,`tabItem` it 
 						where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No'
-						and ifnull(it.is_sub_contracted_item, 'No') = 'No' 
-						and fb.docstatus<2 and fb.parent=%s
+						and ifnull(it.is_sub_contracted_item, 'No') = 'No' and fb.docstatus<2 and fb.parent=%s
 					) a
 				group by item_code,stock_uom
 			""" , ((self.doc.process == 'Backflush') and flt(self.doc.fg_completed_qty) \
 					or flt(pro_obj.doc.qty), cstr(pro_obj.doc.bom_no)))
 			
-			
-			
 			self.make_items_dict(fl_bom_sa_child_item)
 
+		# Update only qty remaining to be issued for production
+		if self.doc.process == 'Material Transfer':
+			self.update_only_remaining_qty()
+
+
+
 	def add_to_stock_entry_detail(self, pro_obj, item_dict, fg_item = 0):
 		sw, tw = '', ''
 		if self.doc.process == 'Material Transfer':
@@ -174,7 +194,7 @@
 			se_child = addchild(self.doc, 'mtn_details', 'Stock Entry Detail', 0, self.doclist)
 			se_child.s_warehouse = sw
 			se_child.t_warehouse = tw
-			se_child.fg_item	= fg_item
+			se_child.fg_item = fg_item
 			se_child.item_code = cstr(d)
 			se_child.description = item_dict[d][1]
 			se_child.uom = item_dict[d][2]
@@ -183,8 +203,9 @@
 			se_child.qty = flt(item_dict[d][0])
 			se_child.transfer_qty = flt(item_dict[d][0])
 			se_child.conversion_factor = 1.00
+			if fg_item: se_child.bom_no = pro_obj.doc.bom_no
 
-	
+
 	# get items 
 	#------------------
 	def get_items(self):
@@ -201,6 +222,7 @@
 			item_dict = {cstr(pro_obj.doc.production_item) : [self.doc.fg_completed_qty, pro_obj.doc.description, pro_obj.doc.stock_uom]}
 			self.add_to_stock_entry_detail(pro_obj, item_dict, fg_item = 1)
 
+
 	def validate_transfer_qty(self):
 		for d in getlist(self.doclist, 'mtn_details'):
 			if flt(d.transfer_qty) <= 0:
@@ -210,6 +232,7 @@
 				msgprint("Transfer Quantity is more than Available Qty at Row No " + cstr(d.idx))
 				raise Exception
 
+
 	def calc_amount(self):
 		total_amount = 0
 		for d in getlist(self.doclist, 'mtn_details'):
@@ -217,6 +240,7 @@
 			total_amount += flt(d.amount)
 		self.doc.total_amount = flt(total_amount)
 
+
 	def add_to_values(self, d, wh, qty, is_cancelled):
 		self.values.append({
 				'item_code'			    : d.item_code,
@@ -269,8 +293,7 @@
 				msgprint("error:Already Produced Qty for %s is %s and maximum allowed Qty is %s" % (pro_obj.doc.production_item, cstr(pro_obj.doc.produced_qty) or 0.00 , cstr(pro_obj.doc.qty)))
 				raise Exception
 	
-	# Validate
-	# ------------------
+
 	def validate(self):
 		sl_obj = get_obj("Stock Ledger", "Stock Ledger")
 		sl_obj.scrub_serial_nos(self)
@@ -280,17 +303,29 @@
 			pro_obj = get_obj('Production Order', self.doc.production_order)
 		self.validate_for_production_order(pro_obj)
 		self.get_stock_and_rate(pro_obj and pro_obj.doc.bom_no or '')
-		self.validate_incoming_rate()
 		self.validate_warehouse(pro_obj)
+		self.validate_incoming_rate()
+		self.validate_bom_belongs_to_item()
 		self.calc_amount()
 		get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.posting_date,'Posting Date')
-				
+		
+	
 	# If target warehouse exists, incoming rate is mandatory
 	# --------------------------------------------------------
 	def validate_incoming_rate(self):
 		for d in getlist(self.doclist, 'mtn_details'):
 			if not flt(d.incoming_rate) and d.t_warehouse:
 				msgprint("Rate is mandatory for Item: %s at row %s" % (d.item_code, d.idx), raise_exception=1)
+	
+	
+	def validate_bom_belongs_to_item(self):
+		for d in getlist(self.doclist, 'mtn_details'):
+			if d.bom_no and not webnotes.conn.sql("""\
+					SELECT name FROM `tabBill Of Materials`
+					WHERE item = %s and name = %s
+				""", (d.item_code, d.bom_no)):
+				msgprint("BOM %s does not belong to Item: %s at row %s" % (d.bom_no, d.item_code, d.idx), raise_exception=1)
+
 
 	# Validate warehouse
 	# -----------------------------------
@@ -336,7 +371,7 @@
 					msgprint(" Target Warehouse should be same as WIP Warehouse %s in Production Order %s at Row No %s" % (cstr(pro_obj.doc.wip_warehouse), cstr(pro_obj.doc.name), cstr(d.idx)) )
 					raise Exception
 				if not cstr(d.s_warehouse):
-					msgprint("Please Enter Source Warehouse at Row No %s is mandatory." % (cstr(d.idx)))
+					msgprint("Please Enter Source Warehouse at Row No %s." % (cstr(d.idx)))
 					raise Exception
 			if self.doc.process == 'Backflush':
 				if flt(d.fg_item):
@@ -362,24 +397,26 @@
 			msgprint("The Total of FG Qty %s in Stock Entry Detail do not match with FG Completed Qty %s" % (flt(fg_qty), flt(self.doc.fg_completed_qty)))
 			raise Exception
 
+
 	def update_production_order(self, is_submit):
 		if self.doc.production_order:
 			pro_obj = get_obj("Production Order", self.doc.production_order)
 			if flt(pro_obj.doc.docstatus) != 1:
-				msgprint("One cannot do any transaction against Production Order : %s, as it's not submitted" % (pro_obj.doc.name))
+				msgprint("You cannot do any transaction against Production Order : %s, as it's not submitted" % (pro_obj.doc.name))
 				raise Exception
 			if pro_obj.doc.status == 'Stopped':
-				msgprint("One cannot do any transaction against Production Order : %s, as it's status is 'Stopped'" % (pro_obj.doc.name))
+				msgprint("You cannot do any transaction against Production Order : %s, as it's status is 'Stopped'" % (pro_obj.doc.name))
 				raise Exception
 			if getdate(pro_obj.doc.posting_date) > getdate(self.doc.posting_date):
 				msgprint("Posting Date of Stock Entry cannot be before Posting Date of Production Order "+ cstr(self.doc.production_order))
 				raise Exception
 			if self.doc.process == 'Backflush':
 				pro_obj.doc.produced_qty = flt(pro_obj.doc.produced_qty) + (is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty)
-				get_obj('Warehouse',	pro_obj.doc.fg_warehouse).update_bin(0, 0, 0, 0, (is_submit and 1 or -1 ) *	flt(self.doc.fg_completed_qty), pro_obj.doc.production_item, now())
-			pro_obj.doc.status = (flt(pro_obj.doc.qty) == flt(pro_obj.doc.produced_qty)) and	'Completed' or 'In Process'
+				get_obj('Warehouse', pro_obj.doc.fg_warehouse).update_bin(0, 0, 0, 0, (is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty), pro_obj.doc.production_item, now())
+			pro_obj.doc.status = (flt(pro_obj.doc.qty) == flt(pro_obj.doc.produced_qty)) and 'Completed' or 'In Process'
 			pro_obj.doc.save()
 	
+
 	# Create / Update Serial No
 	# ----------------------------------
 	def update_serial_no(self, is_submit):
@@ -400,8 +437,7 @@
 					if self.doc.purpose == 'Purchase Return':
 						delete_doc("Serial No", serial_no)
 
-	# On Submit
-	# ------------------
+
 	def on_submit(self):
 		self.validate_transfer_qty()
 		# Check for Approving Authority
@@ -411,14 +447,14 @@
 		# update Production Order
 		self.update_production_order(1)
 
-	# On Cancel
-	# -------------------
+
 	def on_cancel(self):
 		self.update_serial_no(0)
 		self.update_stock_ledger(1)
 		# update Production Order
 		self.update_production_order(0)
 		
+
 	def get_cust_values(self):
 		tbl = self.doc.delivery_note_no and 'Delivery Note' or 'Receivable Voucher'
 		record_name = self.doc.delivery_note_no or self.doc.sales_invoice_no
diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.txt b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.txt
index 50b7154..03ee1af 100644
--- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.txt
+++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.txt
@@ -5,7 +5,7 @@
 	{
 		'creation': '2010-08-08 17:09:25',
 		'docstatus': 0,
-		'modified': '2011-04-26 11:47:18',
+		'modified': '2012-01-12 11:51:57',
 		'modified_by': 'Administrator',
 		'owner': 'Administrator'
 	},
@@ -14,6 +14,7 @@
 	{
 		'autoname': 'MTND/.######',
 		'colour': 'White:FFF',
+		'default_print_format': 'Standard',
 		'doctype': 'DocType',
 		'istable': 1,
 		'module': 'Stock',
@@ -21,7 +22,7 @@
 		'section_style': 'Tray',
 		'server_code_error': ' ',
 		'show_in_menu': 0,
-		'version': 24
+		'version': 26
 	},
 
 	# These values are common for all DocField
@@ -44,13 +45,12 @@
 		'doctype': 'DocField',
 		'fieldname': 's_warehouse',
 		'fieldtype': 'Link',
-		'idx': 1,
 		'in_filter': 1,
 		'label': 'Source Warehouse',
 		'oldfieldname': 's_warehouse',
 		'oldfieldtype': 'Link',
 		'options': 'Warehouse',
-		'permlevel': 2
+		'permlevel': 0
 	},
 
 	# DocField
@@ -58,13 +58,12 @@
 		'doctype': 'DocField',
 		'fieldname': 't_warehouse',
 		'fieldtype': 'Link',
-		'idx': 2,
 		'in_filter': 1,
 		'label': 'Target Warehouse',
 		'oldfieldname': 't_warehouse',
 		'oldfieldtype': 'Link',
 		'options': 'Warehouse',
-		'permlevel': 2
+		'permlevel': 0
 	},
 
 	# DocField
@@ -72,12 +71,11 @@
 		'doctype': 'DocField',
 		'fieldname': 'fg_item',
 		'fieldtype': 'Check',
-		'idx': 3,
 		'in_filter': 1,
 		'label': 'FG Item',
 		'oldfieldname': 'fg_item',
 		'oldfieldtype': 'Check',
-		'permlevel': 2,
+		'permlevel': 0,
 		'print_hide': 1
 	},
 
@@ -86,7 +84,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'item_code',
 		'fieldtype': 'Link',
-		'idx': 4,
 		'in_filter': 1,
 		'label': 'Item Code',
 		'oldfieldname': 'item_code',
@@ -101,21 +98,8 @@
 	# DocField
 	{
 		'doctype': 'DocField',
-		'fieldname': 'item_name',
-		'fieldtype': 'Data',
-		'idx': 5,
-		'in_filter': 1,
-		'label': 'Item Name',
-		'permlevel': 0,
-		'search_index': 1
-	},
-
-	# DocField
-	{
-		'doctype': 'DocField',
 		'fieldname': 'description',
 		'fieldtype': 'Text',
-		'idx': 6,
 		'label': 'Description',
 		'oldfieldname': 'description',
 		'oldfieldtype': 'Text',
@@ -128,14 +112,12 @@
 		'doctype': 'DocField',
 		'fieldname': 'batch_no',
 		'fieldtype': 'Link',
-		'idx': 7,
 		'label': 'Batch No',
 		'oldfieldname': 'batch_no',
 		'oldfieldtype': 'Link',
 		'options': 'Batch',
 		'permlevel': 0,
 		'print_hide': 1,
-		'search_index': 0,
 		'trigger': 'Client'
 	},
 
@@ -144,7 +126,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'actual_qty',
 		'fieldtype': 'Read Only',
-		'idx': 8,
 		'in_filter': 1,
 		'label': 'Actual Qty (at source)',
 		'no_copy': 1,
@@ -153,7 +134,7 @@
 		'permlevel': 1,
 		'print_hide': 1,
 		'reqd': 0,
-		'search_index': 0
+		'search_index': 1
 	},
 
 	# DocField
@@ -161,7 +142,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'qty',
 		'fieldtype': 'Currency',
-		'idx': 9,
 		'label': 'Qty',
 		'oldfieldname': 'qty',
 		'oldfieldtype': 'Currency',
@@ -175,7 +155,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'reqd_qty',
 		'fieldtype': 'Currency',
-		'idx': 10,
 		'in_filter': 0,
 		'label': 'Reqd Qty',
 		'oldfieldname': 'reqd_qty',
@@ -190,14 +169,12 @@
 		'doctype': 'DocField',
 		'fieldname': 'uom',
 		'fieldtype': 'Link',
-		'idx': 11,
 		'label': 'UOM',
 		'oldfieldname': 'uom',
 		'oldfieldtype': 'Link',
 		'options': 'UOM',
 		'permlevel': 0,
 		'reqd': 1,
-		'search_index': 0,
 		'trigger': 'Client'
 	},
 
@@ -206,7 +183,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'conversion_factor',
 		'fieldtype': 'Currency',
-		'idx': 12,
 		'label': 'Conversion Factor',
 		'oldfieldname': 'conversion_factor',
 		'oldfieldtype': 'Currency',
@@ -219,7 +195,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'stock_uom',
 		'fieldtype': 'Link',
-		'idx': 13,
 		'in_filter': 0,
 		'label': 'Stock UOM',
 		'oldfieldname': 'stock_uom',
@@ -235,7 +210,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'transfer_qty',
 		'fieldtype': 'Currency',
-		'idx': 14,
 		'label': 'Stock Qty',
 		'oldfieldname': 'transfer_qty',
 		'oldfieldtype': 'Currency',
@@ -248,7 +222,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'serial_no',
 		'fieldtype': 'Text',
-		'idx': 15,
 		'label': 'Serial No',
 		'no_copy': 1,
 		'oldfieldname': 'serial_no',
@@ -262,7 +235,6 @@
 		'doctype': 'DocField',
 		'fieldname': 'incoming_rate',
 		'fieldtype': 'Currency',
-		'idx': 16,
 		'label': 'Incoming Rate',
 		'oldfieldname': 'incoming_rate',
 		'oldfieldtype': 'Currency',
@@ -275,10 +247,20 @@
 		'doctype': 'DocField',
 		'fieldname': 'amount',
 		'fieldtype': 'Currency',
-		'idx': 17,
 		'label': 'Amount',
 		'oldfieldname': 'amount',
 		'oldfieldtype': 'Currency',
 		'permlevel': 1
+	},
+
+	# DocField
+	{
+		'description': 'BOM No. for a Finished Good Item',
+		'doctype': 'DocField',
+		'fieldname': 'bom_no',
+		'fieldtype': 'Link',
+		'label': 'BOM No.',
+		'options': 'Bill Of Materials',
+		'permlevel': 0
 	}
-]
+]
\ No newline at end of file