BIS issue fixes
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 541e56d..664bce4 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -678,7 +678,9 @@
 		frappe.db.sql("delete from `tabSerial No` where purchase_document_no=%s", self.name)
 
 	def validate_schedule_date(self):
-		if not self.schedule_date and self.get("items"):
+		if not self.get("items"):
+			return
+		if not self.schedule_date:
 			self.schedule_date = min([d.schedule_date for d in self.get("items")])
 
 		if self.schedule_date:
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 9bf3858..046377e 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -7,7 +7,7 @@
 from frappe import msgprint, _
 from frappe.model.document import Document
 from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
-from frappe.utils import cstr, flt, cint, nowdate, add_days, comma_and, now_datetime
+from frappe.utils import cstr, flt, cint, nowdate, add_days, comma_and, now_datetime, ceil
 from erpnext.manufacturing.doctype.work_order.work_order import get_item_details
 from six import string_types
 from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
@@ -376,13 +376,16 @@
 	for d in frappe.db.sql("""select bei.item_code, item.default_bom as bom,
 			ifnull(sum(bei.stock_qty/ifnull(bom.quantity, 1)), 0) as qty, item.item_name,
 			bei.description, bei.stock_uom, item.min_order_qty, bei.source_warehouse,
-			item.default_material_request_type, item.min_order_qty, item_default.default_warehouse
+			item.default_material_request_type, item.min_order_qty, item_default.default_warehouse,
+			item.purchase_uom, item_uom.conversion_factor
 		from
 			`tabBOM Explosion Item` bei
 			JOIN `tabBOM` bom ON bom.name = bei.parent
 			JOIN `tabItem` item ON item.name = bei.item_code
 			LEFT JOIN `tabItem Default` item_default
 				ON item_default.parent = item.name and item_default.company=%s
+			LEFT JOIN `tabUOM Conversion Detail` item_uom
+				ON item.name = item_uom.parent and item_uom.uom = item.purchase_uom
 		where
 			bei.docstatus < 2
 			and bom.name=%s and item.is_stock_item in (1, {0})
@@ -399,13 +402,15 @@
 			item.is_sub_contracted_item as is_sub_contracted, bom_item.source_warehouse,
 			item.default_bom as default_bom, bom_item.description as description,
 			bom_item.stock_uom as stock_uom, item.min_order_qty as min_order_qty,
-			item_default.default_warehouse
+			item_default.default_warehouse, item.purchase_uom, item_uom.conversion_factor
 		FROM
 			`tabBOM Item` bom_item
 			JOIN `tabBOM` bom ON bom.name = bom_item.parent
 			JOIN tabItem item ON bom_item.item_code = item.name
 			LEFT JOIN `tabItem Default` item_default
 				ON item.name = item_default.parent and item_default.company = %(company)s
+			LEFT JOIN `tabUOM Conversion Detail` item_uom
+				ON item.name = item_uom.parent and item_uom.uom = item.purchase_uom
 		where
 			bom.name = %(bom)s
 			and bom_item.docstatus < 2
@@ -431,17 +436,30 @@
 	return bom_wise_item_details
 
 def add_item_in_material_request_items(doc, planned_qty, ignore_existing_ordered_qty, item, row, data, warehouse, company):
+	print("add item in material request")
 	total_qty = row.qty * planned_qty
 	projected_qty, actual_qty = get_bin_details(row)
 
 	requested_qty = 0
 	if ignore_existing_ordered_qty:
 		requested_qty = total_qty
-	else:
+	elif total_qty > projected_qty:
 		requested_qty = total_qty - projected_qty
 	if requested_qty > 0 and requested_qty < row.min_order_qty:
 		requested_qty = row.min_order_qty
 	item_group_defaults = get_item_group_defaults(item, company)
+
+	if not row.purchase_uom:
+		row.purchase_uom = row.stock_uom
+
+	if row.purchase_uom != row.stock_uom:
+		if not row.conversion_factor:
+			frappe.throw(_("UOM Conversion factor ({0} -> {1}) not found for item: {2}").format(row.purchase_uom, row.stock_uom, item))
+
+		requested_qty = requested_qty / row.conversion_factor
+	if frappe.db.get_value("UOM", row.purchase_uom, "must_be_whole_number"):
+		requested_qty = ceil(requested_qty)
+	print(row)
 	if requested_qty > 0:
 		doc.setdefault('mr_items', []).append({
 			'item_code': item,
@@ -487,8 +505,8 @@
 			"project": self.project,
 			"item": self.item_code,
 			"company": self.company
-		}, as_dict=1)
 
+		}, as_dict=1)
 	return open_so
 
 @frappe.whitelist()
@@ -511,6 +529,7 @@
 
 @frappe.whitelist()
 def get_items_for_material_requests(doc, company=None):
+	print("get items for material request")
 	if isinstance(doc, string_types):
 		doc = frappe._dict(json.loads(doc))
 
@@ -520,34 +539,69 @@
 	for data in po_items:
 		warehouse = None
 		bom_wise_item_details = {}
-
-		if data.get('required_qty'):
-			planned_qty = data.get('required_qty')
-			bom_no = data.get('bom')
-			ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty')
-			include_non_stock_items = 1
-			warehouse = data.get('for_warehouse')
-			if data.get('include_exploded_items'):
-				include_subcontracted_items = 1
+		if data.get("bom"):
+			print(doc),print("-------------------------------------------------")
+			if data.get('required_qty'):
+				planned_qty = data.get('required_qty')
+				bom_no = data.get('bom')
+				ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty')
+				include_non_stock_items = 1
+				warehouse = data.get('for_warehouse')
+				if data.get('include_exploded_items'):
+					include_subcontracted_items = 1
+				else:
+					include_subcontracted_items = 0
 			else:
-				include_subcontracted_items = 0
-		else:
-			planned_qty = data.get('planned_qty')
-			bom_no = data.get('bom_no')
-			include_subcontracted_items = doc.get('include_subcontracted_items')
-			company = doc.get('company')
-			include_non_stock_items = doc.get('include_non_stock_items')
-			ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')
-		if not planned_qty:
-			frappe.throw(_("For row {0}: Enter Planned Qty").format(data.get('idx')))
+				planned_qty = data.get('planned_qty')
+				bom_no = data.get('bom_no')
+				include_subcontracted_items = doc.get('include_subcontracted_items')
+				company = doc.get('company')
+				include_non_stock_items = doc.get('include_non_stock_items')
+				ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')
+			if not planned_qty:
+				frappe.throw(_("For row {0}: Enter Planned Qty").format(data.get('idx')))
 
-		if data.get('include_exploded_items') and bom_no and include_subcontracted_items:
-			# fetch exploded items from BOM
-			bom_wise_item_details = get_exploded_items(bom_wise_item_details, company, bom_no, include_non_stock_items)
+			if data.get('include_exploded_items') and bom_no and include_subcontracted_items:
+				# fetch exploded items from BOM
+				bom_wise_item_details = get_exploded_items(bom_wise_item_details, company, bom_no, include_non_stock_items)
+			else:
+				bom_wise_item_details = get_subitems(doc, data, bom_wise_item_details, bom_no, company, include_non_stock_items, include_subcontracted_items, 1)
+			for item, item_details in bom_wise_item_details.items():
+				print(item),print(item_details)
+				if item_details.qty > 0:
+					add_item_in_material_request_items(doc, planned_qty, ignore_existing_ordered_qty, item, item_details, data, warehouse, company)
 		else:
-			bom_wise_item_details = get_subitems(doc, data, bom_wise_item_details, bom_no, company, include_non_stock_items, include_subcontracted_items, 1)
-		for item, item_details in bom_wise_item_details.items():
+			sales_order_item = frappe.get_doc('Sales OrderItem', data.sales_order_item).as_dict()
+			planned_qty = data.get('required_qty')
+			ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty')
+			item = doc.item_code
+			purchase_uom = sales_order_item.uom
+			stock_uom = sales_order_item.stock_uom
+			conversion_factor = sales_order_item.conversion_factor
+			qty = doc.required_qty
+			if not purchase_uom == stock_uom:
+				qty = qty / conversion_factor
+			if frappe.db.get_value("UOM", purchase_uom, "must_be_whole_number"):
+					qty = ceil(qty)
+			item_details = {
+			'item_name' = sales_order_item.item_name,
+			'default_bom' = doc.bom,
+			'purchase_uom' = purchase_uom,
+			'default_warehouse' = doc.warehouse,
+			'min_order_qty' =
+			'default_material_request_type' =
+			'qty' = qty,
+			'is_sub_contracted' = ,
+			'item_code' = doc.item_code,
+			'description' = sales_order_item.description,
+			'stock_uom' = stock_uom,
+			'conversion_factor' = conversion_factor,
+			'source_warehouse' = ,
+			}
+			warehouse = doc.warehouse
+			company =
 			if item_details.qty > 0:
 				add_item_in_material_request_items(doc, planned_qty, ignore_existing_ordered_qty, item, item_details, data, warehouse, company)
+			print(doc),print("-------------------------------------------------")
 
 	return doc['mr_items']
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 54d7654..ab2f6ee 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -344,6 +344,8 @@
 				label: __('Include Exploded Items')},
 			{fieldtype:'Check', fieldname:'ignore_existing_ordered_qty',
 				label: __('Ignore Existing Ordered Qty')},
+			{fieldtype:'Check', fieldname:'include_raw_materials_from_sales_order',
+				label: __('Include raw materials from sales order')},
 			{
 				fieldtype:'Table', fieldname: 'items',
 				description: __('Select BOM, Qty and For Warehouse'),
@@ -367,7 +369,7 @@
 			}
 		]
 		var d = new frappe.ui.Dialog({
-			title: __("Select from Items having BOM"),
+			title: __("Items for Raw Material Request"),
 			fields: fields,
 			primary_action: function() {
 				var data = d.get_values();
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 229f4f6..1460bc8 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -341,11 +341,11 @@
 
 			delivered_qty += item.delivered_qty
 			tot_qty += item.qty
-		
+
 		if tot_qty != 0:
 			self.db_set("per_delivered", flt(delivered_qty/tot_qty) * 100,
 				update_modified=False)
-		
+
 
 	def set_indicator(self):
 		"""Set indicator for portal"""
@@ -372,20 +372,19 @@
 	def get_work_order_items(self, for_raw_material_request=0):
 		'''Returns items with BOM that already do not have a linked work order'''
 		items = []
-
 		for table in [self.items, self.packed_items]:
 			for i in table:
 				bom = get_default_bom_item(i.item_code)
-				if bom:
-					stock_qty = i.qty if i.doctype == 'Packed Item' else i.stock_qty
-					if not for_raw_material_request:
-						total_work_order_qty = flt(frappe.db.sql('''select sum(qty) from `tabWork Order`
-							where production_item=%s and sales_order=%s and sales_order_item = %s and docstatus<2''', (i.item_code, self.name, i.name))[0][0])
-						pending_qty = stock_qty - total_work_order_qty
-					else:
-						pending_qty = stock_qty
+				stock_qty = i.qty if i.doctype == 'Packed Item' else i.stock_qty
+				if not for_raw_material_request:
+					total_work_order_qty = flt(frappe.db.sql('''select sum(qty) from `tabWork Order`
+						where production_item=%s and sales_order=%s and sales_order_item = %s and docstatus<2''', (i.item_code, self.name, i.name))[0][0])
+					pending_qty = stock_qty - total_work_order_qty
+				else:
+					pending_qty = stock_qty
 
-					if pending_qty:
+				if pending_qty:
+					if bom:
 						items.append(dict(
 							name= i.name,
 							item_code= i.item_code,
@@ -395,6 +394,16 @@
 							required_qty = pending_qty if for_raw_material_request else 0,
 							sales_order_item = i.name
 						))
+					else:
+						items.append(dict(
+							name= i.name,
+							item_code= i.item_code,
+							bom = '',
+							warehouse = i.warehouse,
+							pending_qty = pending_qty,
+							required_qty = pending_qty if for_raw_material_request else 0,
+							sales_order_item = i.name
+						))
 		return items
 
 	def on_recurring(self, reference_doc, auto_repeat_doc):
@@ -923,10 +932,12 @@
 	for item in items.get('items'):
 		item["include_exploded_items"] = items.get('include_exploded_items')
 		item["ignore_existing_ordered_qty"] = items.get('ignore_existing_ordered_qty')
+		item["include_raw_materials_from_sales_order"] = items.get('include_raw_materials_from_sales_order')
 
 	raw_materials = get_items_for_material_requests(items, company)
 	if not raw_materials:
 		frappe.msgprint(_("Material Request not created, as quantity for Raw Materials already available."))
+		return
 
 	material_request = frappe.new_doc('Material Request')
 	material_request.update(dict(
@@ -951,4 +962,4 @@
 	material_request.flags.ignore_permissions = 1
 	material_request.run_method("set_missing_values")
 	material_request.submit()
-	return material_request
\ No newline at end of file
+	return material_request