feat: Get item location from reference items

- Add option to get items from multiple sales order
- Add some required fiels to Pick TIcket Reference Item
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 1f889ab..97a9739 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -998,6 +998,22 @@
 	return make_inter_company_transaction("Sales Order", source_name, target_doc)
 
 @frappe.whitelist()
-def make_pick_ticket(source_name, target_doc=None, offset=None):
-	from erpnext.stock.doctype.pick_ticket.pick_ticket import get_pick_list
-	return get_pick_list('Sales Order', source_name, 'items')
+def make_pick_ticket(source_name, target_doc=None):
+	doc = get_mapped_doc("Sales Order", source_name, {
+		"Sales Order": {
+			"doctype": "Pick Ticket",
+			"validation": {
+				"docstatus": ["=", 1]
+			}
+		},
+		"Sales Order Item": {
+			"doctype": "Pick Ticket Reference Item",
+			"field_map": {
+				"item_code": "item",
+				"parenttype": "reference_doctype",
+				"parent": "reference_name"
+			},
+		},
+	}, target_doc)
+
+	return doc
diff --git a/erpnext/stock/doctype/pick_ticket/pick_ticket.js b/erpnext/stock/doctype/pick_ticket/pick_ticket.js
index f9ae38a..a2d6cd7 100644
--- a/erpnext/stock/doctype/pick_ticket/pick_ticket.js
+++ b/erpnext/stock/doctype/pick_ticket/pick_ticket.js
@@ -2,7 +2,28 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Pick Ticket', {
-	// onload: function(frm) {
+	refresh: (frm) => {
+		this.frm.add_custom_button(__('Sales Order'), function() {
+			erpnext.utils.map_current_doc({
+				method: "erpnext.selling.doctype.sales_order.sales_order.make_pick_ticket",
+				source_doctype: "Sales Order",
+				target: frm,
+				setters: {
+					company: frm.doc.company || undefined,
+				},
+				get_query_filters: {
+					docstatus: 1,
+				}
+			});
+		}, __("Get items from"));
 
-	// }
+		frm.add_custom_button(__('Get Item Locations'), () => {
+			frm.trigger('set_item_locations');
+		});
+	},
+
+	set_item_locations: (frm) => {
+		frm.call('set_item_locations')
+	}
+
 });
diff --git a/erpnext/stock/doctype/pick_ticket/pick_ticket.json b/erpnext/stock/doctype/pick_ticket/pick_ticket.json
index fe331ac..9351925 100644
--- a/erpnext/stock/doctype/pick_ticket/pick_ticket.json
+++ b/erpnext/stock/doctype/pick_ticket/pick_ticket.json
@@ -43,7 +43,6 @@
    "fieldtype": "Section Break"
   },
   {
-   "collapsible": 1,
    "fieldname": "section_break_4",
    "fieldtype": "Section Break",
    "label": "Reference Items"
@@ -55,7 +54,7 @@
    "options": "Pick Ticket Reference Item"
   }
  ],
- "modified": "2019-07-24 16:13:51.668880",
+ "modified": "2019-07-26 12:06:08.941760",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Pick Ticket",
diff --git a/erpnext/stock/doctype/pick_ticket/pick_ticket.py b/erpnext/stock/doctype/pick_ticket/pick_ticket.py
index 4c5fdb8..eb54730 100644
--- a/erpnext/stock/doctype/pick_ticket/pick_ticket.py
+++ b/erpnext/stock/doctype/pick_ticket/pick_ticket.py
@@ -7,16 +7,20 @@
 from frappe.model.document import Document
 
 class PickTicket(Document):
-	pass
+	def set_item_locations(self):
+		reference_items = self.reference_document_items
+		self.delete_key('items')
+		for item in reference_items:
+			data = get_items_with_warehouse_and_quantity(item)
 
-def get_pick_list(reference_doctype, reference_name, items_field):
-	doc = frappe.new_doc('Pick Ticket')
-	reference_doc = frappe.get_doc(reference_doctype, reference_name)
-	doc.company = reference_doc.company
-	items = reference_doc.get(items_field)
-	add_picklist_items(items, doc, reference_doc)
-	doc.save()
-	return doc
+			for item_info in data:
+				self.append('items', item_info)
+
+		for item in self.get('items'):
+			if frappe.get_cached_value('Item', item.item, 'has_serial_no'):
+				set_serial_nos(item)
+			elif frappe.get_cached_value('Item', item.item, 'has_batch_no'):
+				set_batch_no(item, self)
 
 def get_available_items(item):
 	# gets all items available in different warehouses
@@ -28,44 +32,30 @@
 
 	return available_items
 
-def get_items_with_warehouse_and_quantity(item_doc, reference_doc):
+def get_items_with_warehouse_and_quantity(item_doc):
 	items = []
-	item_locations = get_available_items(item_doc.item_code)
+	item_locations = get_available_items(item_doc.item)
 	remaining_qty = item_doc.qty
 
-	if not item_locations:
-		print('{} qty of {} is out of stock. Skipping...'.format(remaining_qty, item_doc.item))
-		return items
 
 	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_code,
+			'item': item_doc.item,
 			'qty': qty,
 			'warehouse': item_location.warehouse,
-			'reference_doctype': reference_doc.doctype,
-			'reference_name': reference_doc.name
+			'reference_doctype': item_doc.reference_doctype,
+			'reference_name': item_doc.reference_name
 		})
 		remaining_qty -= qty
 
+	if remaining_qty:
+		print('---------- {} qty of {} is out of stock. Skipping... -------------'.format(remaining_qty, item_doc.item))
+		return items
+
 	return items
 
-def add_picklist_items(reference_items, doc, reference_doc):
-	for item in reference_items:
-		data = get_items_with_warehouse_and_quantity(item, reference_doc)
-
-		for item_info in data:
-			doc.append('items', item_info)
-
-	doc.insert()
-
-	for item in doc.get('items'):
-		if item.has_serial_no:
-			set_serial_nos(item)
-		elif item.has_batch_no:
-			set_batch_no(item, doc)
-
 def set_serial_nos(item):
 	serial_nos = frappe.get_all('Serial No', {
 		'item_code': item.item,
diff --git a/erpnext/stock/doctype/pick_ticket_reference_item/pick_ticket_reference_item.json b/erpnext/stock/doctype/pick_ticket_reference_item/pick_ticket_reference_item.json
index 446e075..ae7ea35 100644
--- a/erpnext/stock/doctype/pick_ticket_reference_item/pick_ticket_reference_item.json
+++ b/erpnext/stock/doctype/pick_ticket_reference_item/pick_ticket_reference_item.json
@@ -4,7 +4,10 @@
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
-  "item"
+  "item",
+  "qty",
+  "reference_doctype",
+  "reference_name"
  ],
  "fields": [
   {
@@ -13,10 +16,28 @@
    "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"
   }
  ],
  "istable": 1,
- "modified": "2019-07-24 16:12:58.000378",
+ "modified": "2019-07-26 12:17:52.142186",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Pick Ticket Reference Item",