fix: Fetch warehouse location from Bin
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 39dda92..89739cc 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -102,6 +102,7 @@
 erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({
 	onload: function(doc, dt, dn) {
 		this._super();
+		this.frm.add_custom_button(__('Pick Ticket'), () => this.make_pick_ticket(), __('Create'));
 	},
 
 	refresh: function(doc, dt, dn) {
@@ -233,6 +234,13 @@
 		this.order_type(doc);
 	},
 
+	make_pick_ticket() {
+		frappe.model.open_mapped_doc({
+			method: "erpnext.selling.doctype.sales_order.sales_order.make_pick_ticket",
+			frm: this.frm
+		})
+	},
+
 	make_work_order() {
 		var me = this;
 		this.frm.call({
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 09dc9a9..181ac33 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -996,3 +996,80 @@
 def make_inter_company_purchase_order(source_name, target_doc=None):
 	from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction
 	return make_inter_company_transaction("Sales Order", source_name, target_doc)
+
+@frappe.whitelist()
+def make_pick_ticket(source_name, target_doc=None, offset=None):
+
+	doc = get_mapped_doc("Sales Order", source_name, {
+		"Sales Order": {
+			"doctype": "Pick Ticket",
+			"validation": {
+				"docstatus": ["=", 1]
+			},
+			"field_map": {
+				"name": "reference_name",
+			},
+		},
+		"Sales Order Item": {
+			"doctype": 'Pick Ticket Item',
+			"field_map": {
+				'item_code': 'item'
+			},
+		}
+	}, target_doc, postprocess)
+
+	return doc
+
+def get_available_items(item):
+	# gets all items available in different warehouses
+	# FIFO
+	available_items = frappe.get_all('Bin', filters={
+		'item_code': item,
+		'actual_qty': ['>', 0]
+	}, fields=['warehouse', 'actual_qty as qty'], order_by='creation')
+
+	return available_items
+
+def get_items_with_warehouse_and_quantity(item_doc):
+	items = []
+	item_locations = get_available_items(item_doc.item)
+	if not item_locations: return
+
+	remaining_qty = item_doc.qty
+
+	while remaining_qty > 0 and item_locations:
+		item_location = item_locations.pop(0)
+		qty = item_doc.qty if item_location.qty >= item_doc.qty else item_location.qty
+		items.append({
+			'qty': qty,
+			'warehouse': item_location.warehouse
+		})
+		remaining_qty -= qty
+
+	return items
+
+def postprocess(source, doc):
+	for item in doc.items:
+		data = get_items_with_warehouse_and_quantity(item)
+		item.delete()
+
+		for item_info in data:
+			print(item_info)
+			pick_item = frappe.new_doc('Pick Ticket Item', doc, 'items')
+			pick_item.update(item_info)
+			print(pick_item.qty)
+
+	for item in doc.items:
+		if item.has_serial_no:
+			serial_nos = frappe.get_all('Serial No', {
+				'item_code': item.item,
+				'warehouse': item.warehouse
+			}, limit=item.qty, order_by='purchase_date')
+			item.serial_no = '\n'.join([serial_no.name for serial_no in serial_nos])
+
+		if item.has_batch_no:
+			serial_nos = frappe.get_all('Serial No', {
+				'item_code': item.item,
+				'warehouse': item.warehouse
+			}, limit=item.qty, order_by='purchase_date')
+			item.serial_no = '\n'.join([serial_no.name for serial_no in serial_nos])
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_ticket_item/pick_ticket_item.json b/erpnext/stock/doctype/pick_ticket_item/pick_ticket_item.json
index 7051725..cba0743 100644
--- a/erpnext/stock/doctype/pick_ticket_item/pick_ticket_item.json
+++ b/erpnext/stock/doctype/pick_ticket_item/pick_ticket_item.json
@@ -10,7 +10,11 @@
   "reference_document_item",
   "warehouse",
   "qty",
-  "picked_qty"
+  "picked_qty",
+  "has_serial_no",
+  "has_batch_no",
+  "serial_no",
+  "batch_no"
  ],
  "fields": [
   {
@@ -56,10 +60,39 @@
    "fieldtype": "Data",
    "hidden": 1,
    "label": "Reference Document Item"
+  },
+  {
+   "depends_on": "has_serial_no",
+   "fieldname": "serial_no",
+   "fieldtype": "Small Text",
+   "label": "Serial No"
+  },
+  {
+   "depends_on": "has_batch_no",
+   "fieldname": "batch_no",
+   "fieldtype": "Link",
+   "label": "Batch No",
+   "options": "Batch"
+  },
+  {
+   "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
   }
  ],
  "istable": 1,
- "modified": "2019-07-11 16:34:52.853146",
+ "modified": "2019-07-24 11:05:27.407791",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Pick Ticket Item",