fix: Delivery note creation from pick list

- Changes in serial no and batch no seletion
- Changes in warehouse overrwite logic

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 14bf9d5..f6d4eee 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -263,7 +263,7 @@
 					if self.get("is_subcontracted"):
 						args["is_subcontracted"] = self.is_subcontracted
 
-					ret = get_item_details(args, self)
+					ret = get_item_details(args, self, overwrite_warehouse=False)
 
 					for fieldname, value in ret.items():
 						if item.meta.get_field(fieldname) and value is not None:
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index b79a292..2dc3788 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -568,7 +568,7 @@
 	return doc
 
 @frappe.whitelist()
-def make_delivery_note(source_name, target_doc=None):
+def make_delivery_note(source_name, target_doc=None, skip_item_mapping=False):
 	def set_missing_values(source, target):
 		target.ignore_pricing_rule = 1
 		target.run_method("set_missing_values")
@@ -593,23 +593,13 @@
 				or item.get("buying_cost_center") \
 				or item_group.get("buying_cost_center")
 
-	target_doc = get_mapped_doc("Sales Order", source_name, {
+	mapper = {
 		"Sales Order": {
 			"doctype": "Delivery Note",
 			"validation": {
 				"docstatus": ["=", 1]
 			}
 		},
-		"Sales Order Item": {
-			"doctype": "Delivery Note Item",
-			"field_map": {
-				"rate": "rate",
-				"name": "so_detail",
-				"parent": "against_sales_order",
-			},
-			"postprocess": update_item,
-			"condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1
-		},
 		"Sales Taxes and Charges": {
 			"doctype": "Sales Taxes and Charges",
 			"add_if_empty": True
@@ -618,7 +608,21 @@
 			"doctype": "Sales Team",
 			"add_if_empty": True
 		}
-	}, target_doc, set_missing_values)
+	}
+
+	if not skip_item_mapping:
+		mapper["Sales Order Item"] = {
+			"doctype": "Delivery Note Item",
+			"field_map": {
+				"rate": "rate",
+				"name": "so_detail",
+				"parent": "against_sales_order",
+			},
+			"postprocess": update_item,
+			"condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1
+		}
+
+	target_doc = get_mapped_doc("Sales Order", source_name, mapper, target_doc, set_missing_values)
 
 	return target_doc
 
@@ -999,9 +1003,16 @@
 
 @frappe.whitelist()
 def make_pick_list(source_name, target_doc=None):
+	def update_item_quantity(source, target, source_parent):
+		target.qty = flt(source.qty) - flt(source.delivered_qty)
+		target.stock_qty = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.conversion_factor)
+
 	doc = get_mapped_doc("Sales Order", source_name, {
 		"Sales Order": {
 			"doctype": "Pick List",
+			"field_map": {
+				"doctype": "items_based_on"
+			},
 			"validation": {
 				"docstatus": ["=", 1]
 			}
@@ -1009,11 +1020,11 @@
 		"Sales Order Item": {
 			"doctype": "Pick List Reference Item",
 			"field_map": {
-				"item_code": "item",
-				"parenttype": "reference_doctype",
-				"parent": "reference_name",
-				"name": "reference_document_item"
+				"parent": "sales_order",
+				"name": "sales_order_item"
 			},
+			"postprocess": update_item_quantity,
+			"conditions": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1
 		},
 	}, target_doc)
 
diff --git a/erpnext/stock/doctype/pick_list/pick_list.json b/erpnext/stock/doctype/pick_list/pick_list.json
index 3f96630..c7a5fc8 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.json
+++ b/erpnext/stock/doctype/pick_list/pick_list.json
@@ -7,6 +7,7 @@
  "field_order": [
   "company",
   "column_break_4",
+  "items_based_on",
   "parent_warehouse",
   "section_break_4",
   "reference_items",
@@ -50,9 +51,16 @@
    "fieldtype": "Table",
    "label": "Items To Be Picked",
    "options": "Pick List Reference Item"
+  },
+  {
+   "default": "Sales Order",
+   "fieldname": "items_based_on",
+   "fieldtype": "Select",
+   "label": "Items Based On",
+   "options": "\nSales Order\nWork Order"
   }
  ],
- "modified": "2019-08-01 10:50:17.055509",
+ "modified": "2019-08-13 19:30:01.151720",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Pick List",
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index 77dacd5..20b4230 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -5,7 +5,10 @@
 from __future__ import unicode_literals
 import frappe
 from frappe.model.document import Document
-from frappe.model.mapper import get_mapped_doc
+from six import iteritems
+from frappe.model.mapper import get_mapped_doc, map_child_doc
+from frappe.utils import floor, flt, today
+from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note as make_delivery_note_from_sales_order
 
 class PickList(Document):
 	def set_item_locations(self):
@@ -17,46 +20,56 @@
 
 		# Reset
 		self.delete_key('item_locations')
-		for item in reference_items:
-			data = get_items_with_warehouse_and_quantity(item, from_warehouses)
-			for item_info in data:
-				print(self.append('item_locations', item_info))
+		for item_doc in reference_items:
+			if frappe.get_cached_value('Item', item_doc.item_code, 'has_serial_no'):
+				item_locations = get_item_locations_based_on_serial_nos(item_doc)
+			elif frappe.get_cached_value('Item', item_doc.item_code, 'has_batch_no'):
+				item_locations = get_item_locations_based_on_batch_nos(item_doc)
+			else:
+				item_locations = get_items_with_warehouse_and_quantity(item_doc, from_warehouses)
 
-		for item_doc in self.get('item_locations'):
-			if frappe.get_cached_value('Item', item_doc.item, 'has_serial_no'):
-				set_serial_nos(item_doc)
-			elif frappe.get_cached_value('Item', item_doc.item, 'has_batch_no'):
-				set_batch_no(item_doc, self)
+			for row in item_locations:
+				row.update({
+					'item_code': item_doc.item_code,
+					'sales_order': item_doc.sales_order,
+					'sales_order_item': item_doc.sales_order_item,
+					'uom': item_doc.uom,
+					'stock_uom': item_doc.stock_uom,
+					'conversion_factor': item_doc.conversion_factor,
+					'stock_qty': row.get("qty", 0) * item_doc.conversion_factor,
+					'picked_qty': row.get("qty", 0) * item_doc.conversion_factor
+				})
+				self.append('item_locations', row)
 
 def get_items_with_warehouse_and_quantity(item_doc, from_warehouses):
-	items = []
-	item_locations = get_available_items(item_doc.item, from_warehouses)
-	remaining_qty = item_doc.qty
+	item_locations = []
+	item_location_map = get_available_items(item_doc.item_code, from_warehouses)
+	remaining_stock_qty = item_doc.stock_qty
+	while remaining_stock_qty > 0 and item_location_map:
+		item_location = item_location_map.pop(0)
+		stock_qty = remaining_stock_qty if item_location.qty >= remaining_stock_qty else item_location.qty
+		qty = stock_qty / (item_doc.conversion_factor or 1)
 
-	while remaining_qty > 0 and item_locations:
-		item_location = item_locations.pop(0)
-		qty = remaining_qty if item_location.qty >= remaining_qty else item_location.qty
-		items.append({
-			'item': item_doc.item,
+		uom_must_be_whole_number = frappe.db.get_value("UOM", item_doc.uom, "must_be_whole_number")
+		if uom_must_be_whole_number:
+			qty = floor(qty)
+			stock_qty = qty * item_doc.conversion_factor
+
+		item_locations.append({
 			'qty': qty,
-			'warehouse': item_location.warehouse,
-			'reference_doctype': item_doc.reference_doctype,
-			'reference_name': item_doc.reference_name,
-			'reference_document_item': item_doc.reference_document_item,
+			'warehouse': item_location.warehouse
 		})
-		remaining_qty -= qty
+		remaining_stock_qty -= stock_qty
 
-	if remaining_qty:
-		frappe.msgprint('{} qty of {} is out of stock. Skipping...'.format(remaining_qty, item_doc.item))
-		return items
+	if remaining_stock_qty:
+		frappe.msgprint('{0} {1} of {2} is not available.'
+			.format(remaining_stock_qty / item_doc.conversion_factor, item_doc.uom, item_doc.item_code))
+	return item_locations
 
-	return items
-
-def get_available_items(item, from_warehouses):
+def get_available_items(item_code, from_warehouses):
 	# gets all items available in different warehouses
-	# FIFO
 	filters = frappe._dict({
-		'item_code': item,
+		'item_code': item_code,
 		'actual_qty': ['>', 0]
 	})
 	if from_warehouses:
@@ -71,79 +84,170 @@
 
 def set_serial_nos(item_doc):
 	serial_nos = frappe.get_all('Serial No', {
-		'item_code': item_doc.item,
+		'item_code': item_doc.item_code,
 		'warehouse': item_doc.warehouse
-	}, limit=item_doc.qty, order_by='purchase_date')
+	}, limit=item_doc.stock_qty, order_by='purchase_date')
 	item_doc.set('serial_no', '\n'.join([serial_no.name for serial_no in serial_nos]))
 
-	# should we assume that all serialized item available in stock will have serial no?
+	# should we assume that all serialized item_code available in stock will have serial no?
 
-def set_batch_no(item_doc, parent_doc):
-	batches = frappe.db.sql("""
+def get_item_locations_based_on_serial_nos(item_doc):
+	serial_nos = frappe.get_all('Serial No',
+		fields = ['name', 'warehouse'],
+		filters = {
+			'item_code': item_doc.item_code,
+			'warehouse': ['!=', '']
+		}, limit=item_doc.stock_qty, order_by='purchase_date', as_list=1)
+
+	remaining_stock_qty = flt(item_doc.stock_qty) - len(serial_nos)
+	if remaining_stock_qty:
+		frappe.msgprint('{0} {1} of {2} is not available.'
+			.format(remaining_stock_qty, item_doc.stock_uom, item_doc.item_code))
+
+	warehouse_serial_nos_map = frappe._dict()
+	for serial_no, warehouse in serial_nos:
+		warehouse_serial_nos_map.setdefault(warehouse, []).append(serial_no)
+
+	item_locations = []
+	for warehouse, serial_nos in iteritems(warehouse_serial_nos_map):
+		item_locations.append({
+			'qty': len(serial_nos),
+			'warehouse': warehouse,
+			'serial_no': '\n'.join(serial_nos)
+		})
+
+	return item_locations
+
+def get_item_locations_based_on_batch_nos(item_doc):
+	batch_qty = frappe.db.sql("""
 		SELECT
-			`batch_no`,
-			SUM(`actual_qty`) AS `qty`
+			sle.`warehouse`,
+			sle.`batch_no`,
+			SUM(sle.`actual_qty`) AS `qty`
 		FROM
-			`tabStock Ledger Entry`
+			`tabStock Ledger Entry` sle, `tabBatch` batch
 		WHERE
-			`item_code`=%(item_code)s
-			AND `warehouse`=%(warehouse)s
+			sle.batch_no = batch.name
+			and sle.`item_code`=%(item_code)s
+			and IFNULL(batch.expiry_date, '2200-01-01') > %(today)s
 		GROUP BY
 			`warehouse`,
 			`batch_no`,
 			`item_code`
 		HAVING `qty` > 0
+		ORDER BY IFNULL(batch.expiry_date, '2200-01-01')
 	""", {
-		'item_code': item_doc.item,
-		'warehouse': item_doc.warehouse,
+		'item_code': item_doc.item_code,
+		'today': today()
 	}, as_dict=1)
 
+	item_locations = []
 	required_qty = item_doc.qty
-	while required_qty > 0 and batches:
-		batch = batches.pop()
-		batch_expiry = frappe.get_value('Batch', batch.batch_no, 'expiry_date')
-		if batch_expiry and batch_expiry <= frappe.utils.getdate():
-			frappe.msgprint('Skipping expired Batch {}'.format(batch.batch_no))
-			continue
-		item_doc.batch_no = batch.batch_no
-		if batch.qty >= item_doc.qty:
-			required_qty = 0
-			break
+	for d in batch_qty:
+		if d.qty > required_qty:
+			d.qty = required_qty
 		else:
-			# split item if quantity of item in batch is less that required
-			# Look for another batch
+			required_qty -= d.qty
 
-			required_qty -= batch.qty
-			# set quantity of current item equal to batch quantity
-			item_doc.set('qty', batch.qty)
-			item_doc = parent_doc.append('items', {
-				'item': item_doc.item,
-				'qty': required_qty,
-				'warehouse': item_doc.warehouse,
-				'reference_doctype': item_doc.reference_doctype,
-				'reference_name': item_doc.reference_name,
-				'reference_document_item': item_doc.reference_document_item,
-			})
+		item_locations.append(d)
+
+		if required_qty <= 0:
+			break
+
+	# required_qty = item_doc.qty
+	# while required_qty > 0 and batches:
+	# 	batch = batches.pop()
+	# 	batch_expiry = frappe.get_value('Batch', batch.batch_no, 'expiry_date')
+	# 	if batch_expiry and batch_expiry <= frappe.utils.getdate():
+	# 		frappe.msgprint('Skipping expired Batch {}'.format(batch.batch_no))
+	# 		continue
+	# 	item_doc.batch_no = batch.batch_no
+	# 	if batch.qty >= item_doc.qty:
+	# 		required_qty = 0
+	# 		break
+	# 	else:
+	# 		# split item_code if quantity of item_code in batch is less that required
+	# 		# Look for another batch
+
+	# 		required_qty -= batch.qty
+	# 		# set quantity of current item_code equal to batch quantity
+	# 		item_doc.set('qty', batch.qty)
+	# 		item_doc = parent_doc.append('items', {
+	# 			'item_code': item_doc.item_code,
+	# 			'qty': required_qty,
+	# 			'warehouse': item_doc.warehouse,
+	# 			'sales_order': item_doc.sales_order,
+	# 			'sales_order_item': item_doc.sales_order_item,
+	# 			'uom': item_doc.uom,
+	# 			'stock_uom': item_doc.stock_uom,
+	# 			'conversion_factor': item_doc.conversion_factor,
+	# 			'stock_qty': qty * item_doc.conversion_factor,
+	# 		})
+
 	if required_qty:
-		frappe.msgprint('No batches found for {} qty of {}. Skipping...'.format(required_qty, item_doc.item))
-		parent_doc.remove(item_doc)
+		frappe.msgprint('No batches found for {} qty of {}.'.format(required_qty, item_doc.item_code))
+
+	return item_locations
 
 @frappe.whitelist()
 def make_delivery_note(source_name, target_doc=None):
-	target_doc = get_mapped_doc("Pick List", source_name, {
-		"Pick List": {
-			"doctype": "Delivery Note",
-			# "validation": {
-			# 	"docstatus": ["=", 1]
-			# }
-		},
-		"Pick List Item": {
+	pick_list = frappe.get_doc('Pick List', source_name)
+	sales_orders = [d.sales_order for d in pick_list.item_locations]
+	sales_orders = set(sales_orders)
+
+	delivery_note = None
+	for sales_order in sales_orders:
+		delivery_note = make_delivery_note_from_sales_order(sales_order,
+			delivery_note, skip_item_mapping=True)
+
+	for location in pick_list.item_locations:
+		sales_order_item = frappe.get_cached_doc('Sales Order Item', location.sales_order_item)
+		item_table_mapper = {
 			"doctype": "Delivery Note Item",
 			"field_map": {
-				"item": "item_code",
-				"reference_docname": "against_sales_order",
+				"rate": "rate",
+				"name": "so_detail",
+				"parent": "against_sales_order",
 			},
-		},
-	}, target_doc)
+			"condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1
+		}
 
-	return target_doc
\ No newline at end of file
+		dn_item = map_child_doc(sales_order_item, delivery_note, item_table_mapper)
+
+		if dn_item:
+			dn_item.warehouse = location.warehouse
+			dn_item.qty = location.qty
+
+			update_delivery_note_item(sales_order_item, dn_item, delivery_note)
+
+	set_delivery_note_missing_values(delivery_note)
+
+	return delivery_note
+
+
+def set_delivery_note_missing_values(target):
+	target.run_method("set_missing_values")
+	target.run_method("set_po_nos")
+	target.run_method("calculate_taxes_and_totals")
+
+def update_delivery_note_item(source, target, delivery_note):
+	cost_center = frappe.db.get_value("Project", delivery_note.project, "cost_center")
+	if not cost_center:
+		cost_center = frappe.db.get_value('Item Default',
+			fieldname=['buying_cost_center'],
+			filters={
+				'parent': source.item_code,
+				'parenttype': 'Item',
+				'company': delivery_note.company
+			})
+
+	if not cost_center:
+		cost_center = frappe.db.get_value('Item Default',
+			fieldname=['buying_cost_center'],
+			filters={
+				'parent': source.item_group,
+				'parenttype': 'Item Group',
+				'company': delivery_note.company
+			})
+
+	target.cost_center = cost_center
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_list_item/pick_list_item.json b/erpnext/stock/doctype/pick_list_item/pick_list_item.json
index c83b696..9ee806a 100644
--- a/erpnext/stock/doctype/pick_list_item/pick_list_item.json
+++ b/erpnext/stock/doctype/pick_list_item/pick_list_item.json
@@ -4,33 +4,30 @@
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
-  "item",
+  "item_code",
   "item_name",
   "column_break_2",
   "description",
-  "has_batch_no",
-  "has_serial_no",
   "section_break_5",
   "warehouse",
+  "quantity_section",
   "qty",
+  "stock_qty",
   "picked_qty",
+  "column_break_11",
+  "uom",
+  "stock_uom",
+  "conversion_factor",
+  "serial_no_and_batch_section",
   "serial_no",
+  "column_break_20",
   "batch_no",
-  "reference_section",
-  "reference_doctype",
-  "reference_name",
-  "reference_document_item"
+  "column_break_15",
+  "sales_order",
+  "sales_order_item"
  ],
  "fields": [
   {
-   "fieldname": "item",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Item",
-   "options": "Item",
-   "read_only": 1
-  },
-  {
    "fieldname": "qty",
    "fieldtype": "Float",
    "in_list_view": 1,
@@ -52,72 +49,31 @@
    "read_only": 1
   },
   {
-   "fetch_from": "item.item_name",
+   "fetch_from": "item_code.item_name",
    "fieldname": "item_name",
    "fieldtype": "Data",
    "label": "Item Name",
    "read_only": 1
   },
   {
-   "fetch_from": "item.description",
+   "fetch_from": "item_code.description",
    "fieldname": "description",
    "fieldtype": "Text",
    "label": "Description",
    "read_only": 1
   },
   {
-   "fieldname": "reference_document_item",
-   "fieldtype": "Data",
-   "label": "Reference Document Item",
-   "read_only": 1
-  },
-  {
+   "depends_on": "serial_no",
    "fieldname": "serial_no",
    "fieldtype": "Small Text",
-   "label": "Serial No",
-   "read_only": 1
+   "label": "Serial No"
   },
   {
+   "depends_on": "batch_no",
    "fieldname": "batch_no",
    "fieldtype": "Link",
    "label": "Batch No",
-   "options": "Batch",
-   "read_only": 1
-  },
-  {
-   "default": "0",
-   "fetch_from": "item.has_serial_no",
-   "fieldname": "has_serial_no",
-   "fieldtype": "Check",
-   "label": "Has Serial No",
-   "read_only": 1
-  },
-  {
-   "default": "0",
-   "fetch_from": "item.has_batch_no",
-   "fieldname": "has_batch_no",
-   "fieldtype": "Check",
-   "label": "Has Batch No",
-   "read_only": 1
-  },
-  {
-   "fieldname": "reference_section",
-   "fieldtype": "Section Break",
-   "label": "Reference"
-  },
-  {
-   "fieldname": "reference_doctype",
-   "fieldtype": "Select",
-   "label": "Reference Document Type",
-   "options": "Sales Order\nWork Order",
-   "read_only": 1
-  },
-  {
-   "fieldname": "reference_name",
-   "fieldtype": "Dynamic Link",
-   "label": "Reference Document",
-   "options": "reference_doctype",
-   "read_only": 1
+   "options": "Batch"
   },
   {
    "fieldname": "column_break_2",
@@ -126,10 +82,80 @@
   {
    "fieldname": "section_break_5",
    "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "stock_uom",
+   "fieldtype": "Link",
+   "label": "Stock UOM",
+   "options": "UOM",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_11",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "uom",
+   "fieldtype": "Link",
+   "label": "UOM",
+   "options": "UOM",
+   "read_only": 1
+  },
+  {
+   "fieldname": "conversion_factor",
+   "fieldtype": "Float",
+   "label": "UOM Conversion Factor",
+   "read_only": 1
+  },
+  {
+   "fieldname": "stock_qty",
+   "fieldtype": "Float",
+   "label": "Qty as per Stock UOM",
+   "read_only": 1
+  },
+  {
+   "fieldname": "item_code",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Item",
+   "options": "Item",
+   "read_only": 1
+  },
+  {
+   "fieldname": "quantity_section",
+   "fieldtype": "Section Break",
+   "label": "Quantity"
+  },
+  {
+   "fieldname": "column_break_15",
+   "fieldtype": "Section Break",
+   "label": "Reference"
+  },
+  {
+   "fieldname": "sales_order",
+   "fieldtype": "Link",
+   "label": "Sales Order",
+   "options": "Sales Order",
+   "read_only": 1
+  },
+  {
+   "fieldname": "sales_order_item",
+   "fieldtype": "Data",
+   "label": "Sales Order Item",
+   "read_only": 1
+  },
+  {
+   "fieldname": "serial_no_and_batch_section",
+   "fieldtype": "Section Break",
+   "label": "Serial No and Batch"
+  },
+  {
+   "fieldname": "column_break_20",
+   "fieldtype": "Column Break"
   }
  ],
  "istable": 1,
- "modified": "2019-07-30 23:47:53.566473",
+ "modified": "2019-08-14 18:41:37.727388",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Pick List Item",
diff --git a/erpnext/stock/doctype/pick_list_reference_item/pick_list_reference_item.json b/erpnext/stock/doctype/pick_list_reference_item/pick_list_reference_item.json
index 23ef255..0aa94fe 100644
--- a/erpnext/stock/doctype/pick_list_reference_item/pick_list_reference_item.json
+++ b/erpnext/stock/doctype/pick_list_reference_item/pick_list_reference_item.json
@@ -4,46 +4,82 @@
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
-  "item",
+  "item_code",
+  "quantity_section",
   "qty",
-  "reference_doctype",
-  "reference_name",
-  "reference_document_item"
+  "stock_qty",
+  "column_break_5",
+  "uom",
+  "stock_uom",
+  "conversion_factor",
+  "reference_section",
+  "sales_order",
+  "sales_order_item"
  ],
  "fields": [
   {
-   "fieldname": "item",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Item",
-   "options": "Item"
-  },
-  {
-   "fieldname": "reference_doctype",
-   "fieldtype": "Link",
-   "label": "Reference Document type",
-   "options": "DocType"
-  },
-  {
-   "fieldname": "reference_name",
-   "fieldtype": "Dynamic Link",
-   "label": "Reference Name",
-   "options": "reference_doctype"
-  },
-  {
    "fieldname": "qty",
    "fieldtype": "Float",
    "in_list_view": 1,
    "label": "Qty"
   },
   {
-   "fieldname": "reference_document_item",
+   "fieldname": "quantity_section",
+   "fieldtype": "Section Break",
+   "label": "Quantity"
+  },
+  {
+   "fieldname": "stock_qty",
+   "fieldtype": "Float",
+   "label": "Stock Qty"
+  },
+  {
+   "fieldname": "uom",
+   "fieldtype": "Link",
+   "label": "UOM",
+   "options": "UOM"
+  },
+  {
+   "fieldname": "stock_uom",
+   "fieldtype": "Link",
+   "label": "Stock UOM",
+   "options": "UOM"
+  },
+  {
+   "fieldname": "item_code",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Item",
+   "options": "Item"
+  },
+  {
+   "fieldname": "column_break_5",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "reference_section",
+   "fieldtype": "Section Break",
+   "label": "Reference"
+  },
+  {
+   "fieldname": "sales_order",
+   "fieldtype": "Link",
+   "label": "Sales Order",
+   "options": "Sales Order"
+  },
+  {
+   "fieldname": "sales_order_item",
    "fieldtype": "Data",
-   "label": "Reference Document Item"
+   "label": "Sales Order Item"
+  },
+  {
+   "fieldname": "conversion_factor",
+   "fieldtype": "Float",
+   "label": "UOM Conversion Factor"
   }
  ],
  "istable": 1,
- "modified": "2019-07-30 23:43:30.901151",
+ "modified": "2019-08-14 18:38:28.867113",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Pick List Reference Item",
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index f1d784c..41101f4 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -22,7 +22,7 @@
 purchase_doctypes = ['Material Request', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
 
 @frappe.whitelist()
-def get_item_details(args, doc=None):
+def get_item_details(args, doc=None, overwrite_warehouse=True):
 	"""
 		args = {
 			"item_code": "",
@@ -44,11 +44,15 @@
 			"set_warehouse": ""
 		}
 	"""
+
 	args = process_args(args)
+	print('warehouse', args.warehouse, '========')
 	item = frappe.get_cached_doc("Item", args.item_code)
 	validate_item_details(args, item)
 
-	out = get_basic_details(args, item)
+	out = get_basic_details(args, item, overwrite_warehouse)
+
+	print('warehouse2', out.warehouse, '========')
 
 	get_item_tax_template(args, item, out)
 	out["item_tax_rate"] = get_item_tax_map(args.company, args.get("item_tax_template") if out.get("item_tax_template") is None \
@@ -178,7 +182,7 @@
 			throw(_("Item {0} must be a Sub-contracted Item").format(item.name))
 
 
-def get_basic_details(args, item):
+def get_basic_details(args, item, overwrite_warehouse=True):
 	"""
 	:param args: {
 			"item_code": "",
@@ -225,14 +229,26 @@
 	item_group_defaults = get_item_group_defaults(item.name, args.company)
 	brand_defaults = get_brand_defaults(item.name, args.company)
 
-	warehouse = (args.get("set_warehouse") or item_defaults.get("default_warehouse") or
-		item_group_defaults.get("default_warehouse") or brand_defaults.get("default_warehouse") or args.warehouse)
+	if overwrite_warehouse or not args.warehouse:
+		warehouse = (
+			args.get("set_warehouse") or
+			item_defaults.get("default_warehouse") or
+			item_group_defaults.get("default_warehouse") or
+			brand_defaults.get("default_warehouse") or
+			args.warehouse
+		)
 
-	if not warehouse:
-		defaults = frappe.defaults.get_defaults() or {}
-		if defaults.get("default_warehouse") and frappe.db.exists("Warehouse",
-			{'name': defaults.default_warehouse, 'company': args.company}):
-			warehouse = defaults.default_warehouse
+		if not warehouse:
+			defaults = frappe.defaults.get_defaults() or {}
+			warehouse_exists = frappe.db.exists("Warehouse", {
+				'name': defaults.default_warehouse,
+				'company': args.company
+			})
+			if defaults.get("default_warehouse") and warehouse_exists:
+				warehouse = defaults.default_warehouse
+
+	else:
+		warehouse = args.warehouse
 
 	if args.get('doctype') == "Material Request" and not args.get('material_request_type'):
 		args['material_request_type'] = frappe.db.get_value('Material Request',
@@ -784,6 +800,7 @@
 
 @frappe.whitelist()
 def get_bin_details(item_code, warehouse):
+	print(item_code, warehouse, '---------------------------')
 	return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
 		["projected_qty", "actual_qty", "reserved_qty"], as_dict=True, cache=True) \
 			or {"projected_qty": 0, "actual_qty": 0, "reserved_qty": 0}