Merge pull request #4040 from nabinhait/dn_target_warehouse

Delivery to target warehouse
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 33fa4e3..940f754 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -422,7 +422,7 @@
 	def update_packing_list(self):
 		if cint(self.update_stock) == 1:
 			from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
-			make_packing_list(self, 'items')
+			make_packing_list(self)
 		else:
 			self.set('packed_items', [])
 
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 0eae7cb..fc8ca63 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -8,6 +8,8 @@
 from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
 from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
+from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
+from frappe.model.naming import make_autoname
 
 class TestSalesInvoice(unittest.TestCase):
 	def make(self):
@@ -688,7 +690,6 @@
 		si.insert()
 		si.submit()
 
-		self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Delivered")
 		self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"))
 		self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0],
 			"delivery_document_no"), si.name)
@@ -702,33 +703,26 @@
 
 		serial_nos = get_serial_nos(si.get("items")[0].serial_no)
 
-		self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Available")
 		self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"), "_Test Warehouse - _TC")
 		self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0],
 			"delivery_document_no"))
 
 	def test_serialize_status(self):
-		from erpnext.stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos, SerialNoDuplicateError
-		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
-
-		se = make_serialized_item()
-		serial_nos = get_serial_nos(se.get("items")[0].serial_no)
-
-		sr = frappe.get_doc("Serial No", serial_nos[0])
-		sr.status = "Not Available"
-		sr.save()
+		serial_no = frappe.get_doc({
+			"doctype": "Serial No",
+			"item_code": "_Test Serialized Item With Series",
+			"serial_no": make_autoname("SR", "Serial No")
+		})
+		serial_no.save()
 
 		si = frappe.copy_doc(test_records[0])
 		si.update_stock = 1
 		si.get("items")[0].item_code = "_Test Serialized Item With Series"
 		si.get("items")[0].qty = 1
-		si.get("items")[0].serial_no = serial_nos[0]
+		si.get("items")[0].serial_no = serial_no.name
 		si.insert()
 
-		self.assertRaises(SerialNoStatusError, si.submit)
-
-		# hack! because stock ledger entires are already inserted and are not rolled back!
-		self.assertRaises(SerialNoDuplicateError, si.cancel)
+		self.assertRaises(SerialNoWarehouseError, si.submit)
 
 	def test_invoice_due_date_against_customers_credit_days(self):
 		# set customer's credit days
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index 2a14b8c..49b5b10 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -847,6 +847,29 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "target_warehouse", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Target Warehouse", 
+   "no_copy": 0, 
+   "options": "Warehouse", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "fieldname": "serial_no", 
    "fieldtype": "Small Text", 
    "hidden": 0, 
@@ -1259,7 +1282,7 @@
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 1, 
- "modified": "2015-08-20 17:18:52.752064", 
+ "modified": "2015-09-20 21:26:46.279615", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Sales Invoice Item", 
diff --git a/erpnext/change_log/current/delivery_to_target_warehouse.md b/erpnext/change_log/current/delivery_to_target_warehouse.md
new file mode 100644
index 0000000..f369efa
--- /dev/null
+++ b/erpnext/change_log/current/delivery_to_target_warehouse.md
@@ -0,0 +1,2 @@
+- Delivery to Target Warehouse: Now you can deliver items to customer's warehouse or rented warehouse. Sponsored by: **[Startrack](http://www.gps.gt/)**
+- Serial No **Status** deprecated
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 4b44932..b087b8a 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -173,7 +173,8 @@
 							'uom': p.uom,
 							'batch_no': cstr(p.batch_no).strip(),
 							'serial_no': cstr(p.serial_no).strip(),
-							'name': d.name
+							'name': d.name,
+							'target_warehouse': p.target_warehouse
 						}))
 			else:
 				il.append(frappe._dict({
@@ -184,7 +185,8 @@
 					'stock_uom': d.stock_uom,
 					'batch_no': cstr(d.get("batch_no")).strip(),
 					'serial_no': cstr(d.get("serial_no")).strip(),
-					'name': d.name
+					'name': d.name,
+					'target_warehouse': d.target_warehouse
 				}))
 		return il
 
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index eccceb0..4b58b3c 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -7,6 +7,7 @@
 from frappe import msgprint, _
 import frappe.defaults
 from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map
+from erpnext.stock.utils import get_incoming_rate
 
 from erpnext.controllers.accounts_controller import AccountsController
 
@@ -184,7 +185,7 @@
 			"voucher_no": self.name,
 			"voucher_detail_no": d.name,
 			"actual_qty": (self.docstatus==1 and 1 or -1)*flt(d.get("stock_qty")),
-			"stock_uom": d.get("stock_uom"),
+			"stock_uom": frappe.db.get_value("Item", args.get("item_code") or d.get("item_code"), "stock_uom"),
 			"incoming_rate": 0,
 			"company": self.company,
 			"fiscal_year": self.fiscal_year,
@@ -217,13 +218,14 @@
 
 		return serialized_items
 
-	def get_incoming_rate_for_sales_return(self, item_code, against_document):
+	def get_incoming_rate_for_sales_return(self, item_code, warehouse, against_document):
 		incoming_rate = 0.0
 		if against_document and item_code:
 			incoming_rate = frappe.db.sql("""select abs(ifnull(stock_value_difference, 0) / actual_qty)
 				from `tabStock Ledger Entry`
-				where voucher_type = %s and voucher_no = %s and item_code = %s limit 1""",
-				(self.doctype, against_document, item_code))
+				where voucher_type = %s and voucher_no = %s 
+					and item_code = %s and warehouse=%s limit 1""",
+				(self.doctype, against_document, item_code, warehouse))
 			incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
 
 		return incoming_rate
@@ -252,19 +254,54 @@
 
 		sl_entries = []
 		for d in self.get_item_list():
-			if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 \
-					and d.warehouse and flt(d['qty']):
-
-				incoming_rate = 0
+			if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 and flt(d.qty):
+				return_rate = 0
 				if cint(self.is_return) and self.return_against and self.docstatus==1:
-					incoming_rate = self.get_incoming_rate_for_sales_return(d.item_code, self.return_against)
+					return_rate = self.get_incoming_rate_for_sales_return(d.item_code, 
+						d.warehouse, self.return_against)
+				
+				# On cancellation or if return entry submission, make stock ledger entry for
+				# target warehouse first, to update serial no values properly
 
-				sl_entries.append(self.get_sl_entries(d, {
-					"actual_qty": -1*flt(d['qty']),
-					"stock_uom": frappe.db.get_value("Item", d.item_code, "stock_uom"),
-					"incoming_rate": incoming_rate
-				}))
-
+				if d.warehouse and ((not cint(self.is_return) and self.docstatus==1) 
+					or (cint(self.is_return) and self.docstatus==2)):
+						sl_entries.append(self.get_sl_entries(d, {
+							"actual_qty": -1*flt(d.qty),
+							"incoming_rate": return_rate
+						}))
+				
+				if d.target_warehouse:
+					target_warehouse_sle = self.get_sl_entries(d, {
+						"actual_qty": flt(d.qty),
+						"warehouse": d.target_warehouse
+					})
+					
+					if self.docstatus == 1:
+						if not cint(self.is_return):
+							args = frappe._dict({
+								"item_code": d.item_code,
+								"warehouse": d.warehouse,
+								"posting_date": self.posting_date,
+								"posting_time": self.posting_time,
+								"qty": -1*flt(d.qty),
+								"serial_no": d.serial_no
+							})
+							target_warehouse_sle.update({
+								"incoming_rate": get_incoming_rate(args)
+							})
+						else:
+							target_warehouse_sle.update({
+								"outgoing_rate": return_rate
+							})
+					sl_entries.append(target_warehouse_sle)
+					
+				if d.warehouse and ((not cint(self.is_return) and self.docstatus==2) 
+					or (cint(self.is_return) and self.docstatus==1)):
+						sl_entries.append(self.get_sl_entries(d, {
+							"actual_qty": -1*flt(d.qty),
+							"incoming_rate": return_rate
+						}))
+				
 		self.make_sl_entries(sl_entries)
 
 def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 732867f..6cc12c5 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -33,7 +33,7 @@
 		self.validate_warehouse()
 
 		from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
-		make_packing_list(self,'items')
+		make_packing_list(self)
 
 		self.validate_with_previous_doc()
 		self.set_status()
diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
index 8533ffa..a699a26 100644
--- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json
+++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
@@ -734,6 +734,29 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "target_warehouse", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Target Warehouse", 
+   "no_copy": 0, 
+   "options": "Warehouse", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "fieldname": "prevdoc_docname", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -1072,7 +1095,7 @@
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 1, 
- "modified": "2015-08-27 02:29:20.603580", 
+ "modified": "2015-09-20 21:26:22.732109", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Sales Order Item", 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 51d4e40..6339752 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -113,7 +113,7 @@
 		self.validate_with_previous_doc()
 
 		from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
-		make_packing_list(self, 'items')
+		make_packing_list(self)
 
 		self.update_current_stock()
 
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index e41aab7..af52c7a 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -15,7 +15,7 @@
 from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
 from erpnext.stock.doctype.stock_entry.test_stock_entry \
 	import make_stock_entry, make_serialized_item, get_qty_after_transaction
-from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, SerialNoStatusError
+from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, SerialNoWarehouseError
 from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
 
 class TestDeliveryNote(unittest.TestCase):
@@ -152,7 +152,6 @@
 		dn = create_delivery_note(item_code="_Test Serialized Item With Series", serial_no=serial_no)
 
 		self.check_serial_no_values(serial_no, {
-			"status": "Delivered",
 			"warehouse": "",
 			"delivery_document_no": dn.name
 		})
@@ -160,21 +159,23 @@
 		dn.cancel()
 
 		self.check_serial_no_values(serial_no, {
-			"status": "Available",
 			"warehouse": "_Test Warehouse - _TC",
 			"delivery_document_no": ""
 		})
 
 	def test_serialize_status(self):
-		se = make_serialized_item()
-		serial_no = get_serial_nos(se.get("items")[0].serial_no)[0]
-
-		frappe.db.set_value("Serial No", serial_no, "status", "Not Available")
+		from frappe.model.naming import make_autoname
+		serial_no = frappe.get_doc({
+			"doctype": "Serial No",
+			"item_code": "_Test Serialized Item With Series",
+			"serial_no": make_autoname("SR", "Serial No")
+		})
+		serial_no.save()
 
 		dn = create_delivery_note(item_code="_Test Serialized Item With Series",
-			serial_no=serial_no, do_not_submit=True)
+			serial_no=serial_no.name, do_not_submit=True)
 
-		self.assertRaises(SerialNoStatusError, dn.submit)
+		self.assertRaises(SerialNoWarehouseError, dn.submit)
 
 	def check_serial_no_values(self, serial_no, field_values):
 		serial_no = frappe.get_doc("Serial No", serial_no)
@@ -295,7 +296,6 @@
 		dn = create_delivery_note(item_code="_Test Serialized Item With Series", rate=500, serial_no=serial_no)
 
 		self.check_serial_no_values(serial_no, {
-			"status": "Delivered",
 			"warehouse": "",
 			"delivery_document_no": dn.name
 		})
@@ -305,7 +305,6 @@
 			is_return=1, return_against=dn.name, qty=-1, rate=500, serial_no=serial_no)
 
 		self.check_serial_no_values(serial_no, {
-			"status": "Sales Returned",
 			"warehouse": "_Test Warehouse - _TC",
 			"delivery_document_no": ""
 		})
@@ -313,7 +312,6 @@
 		dn1.cancel()
 		
 		self.check_serial_no_values(serial_no, {
-			"status": "Delivered",
 			"warehouse": "",
 			"delivery_document_no": dn.name
 		})
@@ -321,12 +319,58 @@
 		dn.cancel()
 		
 		self.check_serial_no_values(serial_no, {
-			"status": "Available",
 			"warehouse": "_Test Warehouse - _TC",
 			"delivery_document_no": "",
 			"purchase_document_no": se.name
 		})
+		
+	def test_delivery_of_bundled_items_to_target_warehouse(self):
+		set_perpetual_inventory()
+		
+		create_stock_reconciliation(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, rate=100)
+		create_stock_reconciliation(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", 
+			qty=50, rate=100)
+			
+		opening_qty_test_warehouse_1 = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC")
+	
+		dn = create_delivery_note(item_code="_Test Product Bundle Item", 
+			qty=5, rate=500, target_warehouse="_Test Warehouse 1 - _TC")
+	
+		# qty after delivery
+		actual_qty = get_qty_after_transaction(warehouse="_Test Warehouse - _TC")
+		self.assertEquals(actual_qty, 25)
+		
+		actual_qty = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC")
+		self.assertEquals(actual_qty, opening_qty_test_warehouse_1 + 25)
+	
+		# stock value diff for source warehouse
+		stock_value_difference = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", 
+			"voucher_no": dn.name, "item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, 
+			"stock_value_difference")
+			
+		# stock value diff for target warehouse
+		stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", 
+			"voucher_no": dn.name, "item_code": "_Test Item", "warehouse": "_Test Warehouse 1 - _TC"}, 
+			"stock_value_difference")
+		self.assertEquals(abs(stock_value_difference), stock_value_difference1)
 
+		# Check gl entries
+		gl_entries = get_gl_entries("Delivery Note", dn.name)
+		self.assertTrue(gl_entries)
+
+		stock_value_difference = abs(frappe.db.sql("""select sum(stock_value_difference) 
+			from `tabStock Ledger Entry` where voucher_type='Delivery Note' and voucher_no=%s 
+			and warehouse='_Test Warehouse - _TC'""", dn.name)[0][0])
+
+		expected_values = {
+			"_Test Warehouse - _TC": [0.0, stock_value_difference],
+			"_Test Warehouse 1 - _TC": [stock_value_difference, 0.0]
+		}
+		for i, gle in enumerate(gl_entries):
+			self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account))
+		
+		set_perpetual_inventory(0)
+	
 def create_delivery_note(**args):
 	dn = frappe.new_doc("Delivery Note")
 	args = frappe._dict(args)
@@ -349,7 +393,8 @@
 		"conversion_factor": 1.0,
 		"expense_account": "Cost of Goods Sold - _TC",
 		"cost_center": "_Test Cost Center - _TC",
-		"serial_no": args.serial_no
+		"serial_no": args.serial_no,
+		"target_warehouse": args.target_warehouse
 	})
 
 	if not args.do_not_save:
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
index bdf771e..ea2e9a3 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -755,6 +755,29 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "target_warehouse", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Target Warehouse", 
+   "no_copy": 0, 
+   "options": "Warehouse", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "fieldname": "serial_no", 
    "fieldtype": "Text", 
    "hidden": 0, 
@@ -1137,7 +1160,7 @@
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 1, 
- "modified": "2015-08-26 08:33:03.676574", 
+ "modified": "2015-09-20 21:26:33.043965", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Delivery Note Item", 
diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
index af569f8..89f3ad5 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
@@ -65,9 +65,8 @@
 		self.submit_landed_cost_voucher(pr)
 
 		serial_no = frappe.db.get_value("Serial No", "SN001",
-			["status", "warehouse", "purchase_rate"], as_dict=1)
+			["warehouse", "purchase_rate"], as_dict=1)
 
-		self.assertEquals(serial_no.status, "Available")
 		self.assertEquals(serial_no.purchase_rate - serial_no_rate, 5.0)
 		self.assertEquals(serial_no.warehouse, "_Test Warehouse - _TC")
 
diff --git a/erpnext/stock/doctype/packed_item/packed_item.json b/erpnext/stock/doctype/packed_item/packed_item.json
index 330e6cf..0250c30 100644
--- a/erpnext/stock/doctype/packed_item/packed_item.json
+++ b/erpnext/stock/doctype/packed_item/packed_item.json
@@ -64,7 +64,7 @@
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "in_filter": 1, 
-   "in_list_view": 1, 
+   "in_list_view": 0, 
    "label": "Item Name", 
    "no_copy": 0, 
    "oldfieldname": "item_name", 
@@ -82,29 +82,6 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "parent_detail_docname", 
-   "fieldtype": "Data", 
-   "hidden": 1, 
-   "ignore_user_permissions": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "Parent Detail docname", 
-   "no_copy": 1, 
-   "oldfieldname": "parent_detail_docname", 
-   "oldfieldtype": "Data", 
-   "permlevel": 0, 
-   "print_hide": 1, 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
    "fieldname": "column_break_5", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -151,12 +128,33 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "section_break_6", 
+   "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "fieldname": "warehouse", 
    "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "in_filter": 0, 
-   "in_list_view": 1, 
+   "in_list_view": 0, 
    "label": "Warehouse", 
    "no_copy": 0, 
    "oldfieldname": "warehouse", 
@@ -175,6 +173,50 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "target_warehouse", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Target Warehouse", 
+   "no_copy": 0, 
+   "options": "Warehouse", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "column_break_9", 
+   "fieldtype": "Column Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "fieldname": "qty", 
    "fieldtype": "Float", 
    "hidden": 0, 
@@ -324,20 +366,19 @@
    "unique": 0
   }, 
   {
-   "allow_on_submit": 0, 
+   "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "uom", 
-   "fieldtype": "Link", 
+   "fieldname": "projected_qty", 
+   "fieldtype": "Float", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "UOM", 
-   "no_copy": 0, 
-   "oldfieldname": "uom", 
-   "oldfieldtype": "Link", 
-   "options": "UOM", 
+   "label": "Projected Qty", 
+   "no_copy": 1, 
+   "oldfieldname": "projected_qty", 
+   "oldfieldtype": "Currency", 
    "permlevel": 0, 
    "print_hide": 0, 
    "read_only": 1, 
@@ -369,19 +410,43 @@
    "unique": 0
   }, 
   {
-   "allow_on_submit": 1, 
+   "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "projected_qty", 
-   "fieldtype": "Float", 
+   "fieldname": "uom", 
+   "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Projected Qty", 
-   "no_copy": 1, 
-   "oldfieldname": "projected_qty", 
-   "oldfieldtype": "Currency", 
+   "label": "UOM", 
+   "no_copy": 0, 
+   "oldfieldname": "uom", 
+   "oldfieldtype": "Link", 
+   "options": "UOM", 
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "read_only": 1, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 1, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "page_break", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Page Break", 
+   "no_copy": 0, 
+   "oldfieldname": "page_break", 
+   "oldfieldtype": "Check", 
    "permlevel": 0, 
    "print_hide": 0, 
    "read_only": 1, 
@@ -415,21 +480,21 @@
    "unique": 0
   }, 
   {
-   "allow_on_submit": 1, 
+   "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "page_break", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
+   "fieldname": "parent_detail_docname", 
+   "fieldtype": "Data", 
+   "hidden": 1, 
    "ignore_user_permissions": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Page Break", 
-   "no_copy": 0, 
-   "oldfieldname": "page_break", 
-   "oldfieldtype": "Check", 
+   "label": "Parent Detail docname", 
+   "no_copy": 1, 
+   "oldfieldname": "parent_detail_docname", 
+   "oldfieldtype": "Data", 
    "permlevel": 0, 
-   "print_hide": 0, 
+   "print_hide": 1, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -446,7 +511,7 @@
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 1, 
- "modified": "2015-08-19 12:45:53.583367", 
+ "modified": "2015-09-21 08:29:43.704286", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Packed Item", 
diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py
index e7a75fe..4d0d7c5 100644
--- a/erpnext/stock/doctype/packed_item/packed_item.py
+++ b/erpnext/stock/doctype/packed_item/packed_item.py
@@ -25,67 +25,67 @@
 def get_bin_qty(item, warehouse):
 	det = frappe.db.sql("""select actual_qty, projected_qty from `tabBin`
 		where item_code = %s and warehouse = %s""", (item, warehouse), as_dict = 1)
-	return det and det[0] or ''
+	return det and det[0] or frappe._dict()
 
-def update_packing_list_item(obj, packing_item_code, qty, warehouse, line):
-	bin = get_bin_qty(packing_item_code, warehouse)
+def update_packing_list_item(doc, packing_item_code, qty, main_item_row):
+	bin = get_bin_qty(packing_item_code, main_item_row.warehouse)
 	item = get_packing_item_details(packing_item_code)
 
 	# check if exists
 	exists = 0
-	for d in obj.get("packed_items"):
-		if d.parent_item == line.item_code and d.item_code == packing_item_code and d.parent_detail_docname == line.name:
+	for d in doc.get("packed_items"):
+		if d.parent_item == main_item_row.item_code and d.item_code == packing_item_code and d.parent_detail_docname == main_item_row.name:
 			pi, exists = d, 1
 			break
 
 	if not exists:
-		pi = obj.append('packed_items', {})
+		pi = doc.append('packed_items', {})
 
-	pi.parent_item = line.item_code
+	pi.parent_item = main_item_row.item_code
 	pi.item_code = packing_item_code
-	pi.item_name = item['item_name']
-	pi.parent_detail_docname = line.name
-	pi.description = item['description']
-	pi.uom = item['stock_uom']
+	pi.item_name = item.item_name
+	pi.parent_detail_docname = main_item_row.name
+	pi.description = item.description
+	pi.uom = item.stock_uom
 	pi.qty = flt(qty)
-	pi.actual_qty = bin and flt(bin['actual_qty']) or 0
-	pi.projected_qty = bin and flt(bin['projected_qty']) or 0
+	pi.actual_qty = flt(bin.get("actual_qty"))
+	pi.projected_qty = flt(bin.get("projected_qty"))
 	if not pi.warehouse:
-		pi.warehouse = warehouse
+		pi.warehouse = main_item_row.warehouse
 	if not pi.batch_no:
-		pi.batch_no = cstr(line.get("batch_no"))
+		pi.batch_no = cstr(main_item_row.get("batch_no"))
+	if not pi.target_warehouse:
+		pi.target_warehouse = main_item_row.get("target_warehouse")
 
-
-
-def make_packing_list(obj, item_table_fieldname):
+def make_packing_list(doc):
 	"""make packing list for Product Bundle item"""
 
-	if obj.get("_action") and obj._action == "update_after_submit": return
+	if doc.get("_action") and doc._action == "update_after_submit": return
 
 	parent_items = []
-	for d in obj.get(item_table_fieldname):
+	for d in doc.get("items"):
 		if frappe.db.get_value("Product Bundle", {"new_item_code": d.item_code}):
 			for i in get_product_bundle_items(d.item_code):
-				update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty), d.warehouse, d)
+				update_packing_list_item(doc, i.item_code, flt(i.qty)*flt(d.qty), d)
 
 			if [d.item_code, d.name] not in parent_items:
 				parent_items.append([d.item_code, d.name])
 
-	cleanup_packing_list(obj, parent_items)
+	cleanup_packing_list(doc, parent_items)
 
-def cleanup_packing_list(obj, parent_items):
+def cleanup_packing_list(doc, parent_items):
 	"""Remove all those child items which are no longer present in main item table"""
 	delete_list = []
-	for d in obj.get("packed_items"):
+	for d in doc.get("packed_items"):
 		if [d.parent_item, d.parent_detail_docname] not in parent_items:
 			# mark for deletion from doclist
 			delete_list.append(d)
 
 	if not delete_list:
-		return obj
+		return doc
 
-	packed_items = obj.get("packed_items")
-	obj.set("packed_items", [])
+	packed_items = doc.get("packed_items")
+	doc.set("packed_items", [])
 	for d in packed_items:
 		if d not in delete_list:
-			obj.append("packed_items", d)
+			doc.append("packed_items", d)
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 5017964..7ad6489 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -163,7 +163,6 @@
 		serial_no = get_serial_nos(pr.get("items")[0].serial_no)[0]
 		
 		_check_serial_no_values(serial_no, {
-			"status": "Available",
 			"warehouse": "_Test Warehouse - _TC",
 			"purchase_document_no": pr.name
 		})
@@ -172,7 +171,6 @@
 			is_return=1, return_against=pr.name, serial_no=serial_no)
 			
 		_check_serial_no_values(serial_no, {
-			"status": "Purchase Returned",
 			"warehouse": "",
 			"purchase_document_no": pr.name,
 			"delivery_document_no": return_pr.name
diff --git a/erpnext/stock/doctype/serial_no/serial_no.js b/erpnext/stock/doctype/serial_no/serial_no.js
index eea652b..9d5555e 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.js
+++ b/erpnext/stock/doctype/serial_no/serial_no.js
@@ -17,10 +17,4 @@
 
 frappe.ui.form.on("Serial No", "refresh", function(frm) {
 	frm.toggle_enable("item_code", frm.doc.__islocal);
-
-	if(frm.doc.status == "Sales Returned" && frm.doc.warehouse)
-		cur_frm.add_custom_button(__('Set Status as Available'), function() {
-			cur_frm.set_value("status", "Available");
-			cur_frm.save();
-		}, "icon-ok", "btn-default");
 });
diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json
index 2823e39..78f1fec 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.json
+++ b/erpnext/stock/doctype/serial_no/serial_no.json
@@ -103,32 +103,6 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "default": "Not Available", 
-   "description": "Only Serial Nos with status \"Available\" can be delivered.", 
-   "fieldname": "status", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "in_filter": 1, 
-   "in_list_view": 1, 
-   "label": "Status", 
-   "no_copy": 1, 
-   "oldfieldname": "status", 
-   "oldfieldtype": "Select", 
-   "options": "Not Available\nAvailable\nDelivered\nPurchase Returned\nSales Returned", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 1, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
    "description": "Warehouse can only be changed via Stock Entry / Delivery Note / Purchase Receipt", 
    "fieldname": "warehouse", 
    "fieldtype": "Link", 
@@ -917,7 +891,7 @@
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 0, 
- "modified": "2015-09-07 15:51:26", 
+ "modified": "2015-09-20 20:39:40.751888", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Serial No", 
@@ -986,7 +960,7 @@
  ], 
  "read_only": 0, 
  "read_only_onload": 0, 
- "search_fields": "item_code,status", 
+ "search_fields": "item_code", 
  "sort_field": "modified", 
  "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 0df0ba2..07ac326 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -16,7 +16,6 @@
 class SerialNoQtyError(ValidationError): pass
 class SerialNoItemError(ValidationError): pass
 class SerialNoWarehouseError(ValidationError): pass
-class SerialNoStatusError(ValidationError): pass
 class SerialNoNotExistsError(ValidationError): pass
 class SerialNoDuplicateError(ValidationError): pass
 
@@ -54,7 +53,7 @@
 		if not self.get("__islocal"):
 			item_code, warehouse = frappe.db.get_value("Serial No",
 				self.name, ["item_code", "warehouse"])
-			if item_code != self.item_code:
+			if not self.via_stock_ledger and item_code != self.item_code:
 				frappe.throw(_("Item Code cannot be changed for Serial No."),
 					SerialNoCannotCannotChangeError)
 			if not self.via_stock_ledger and warehouse != self.warehouse:
@@ -75,28 +74,6 @@
 		self.brand = item.brand
 		self.warranty_period = item.warranty_period
 
-	def set_status(self, last_sle):
-		if last_sle:
-			if last_sle.voucher_type == "Stock Entry":
-				document_type = frappe.db.get_value("Stock Entry", last_sle.voucher_no, "purpose")
-			else:
-				document_type = last_sle.voucher_type
-
-			if last_sle.actual_qty > 0:
-				if document_type in ("Delivery Note", "Sales Invoice", "Sales Return"):
-					self.status = "Sales Returned"
-				else:
-					self.status = "Available"
-			else:
-				if document_type in ("Purchase Receipt", "Purchase Invoice", "Purchase Return"):
-					self.status = "Purchase Returned"
-				elif document_type in ("Delivery Note", "Sales Invoice"):
-					self.status = "Delivered"
-				else:
-					self.status = "Not Available"
-		else:
-			self.status = "Not Available"
-
 	def set_purchase_details(self, purchase_sle):
 		if purchase_sle:
 			self.purchase_document_type = purchase_sle.voucher_type
@@ -162,10 +139,19 @@
 		return sle_dict
 
 	def on_trash(self):
-		if self.status == 'Delivered':
-			frappe.throw(_("Delivered Serial No {0} cannot be deleted").format(self.name))
-		if self.warehouse:
-			frappe.throw(_("Cannot delete Serial No {0} in stock. First remove from stock, then delete.").format(self.name))
+		sl_entries = frappe.db.sql("""select serial_no from `tabStock Ledger Entry` 
+			where serial_no like %s and item_code=%s and ifnull(is_cancelled, 'No')='No'""", 
+			("%%%s%%" % self.name, self.item_code), as_dict=True)
+
+		# Find the exact match
+		sle_exists = False
+		for d in sl_entries:
+			if self.name.upper() in get_serial_nos(d.serial_no):
+				sle_exists = True
+				break
+			
+		if sle_exists:
+			frappe.throw(_("Cannot delete Serial No {0}, as it is used in stock transactions").format(self.name))
 
 	def before_rename(self, old, new, merge=False):
 		if merge:
@@ -187,7 +173,6 @@
 	def on_stock_ledger_entry(self):
 		if self.via_stock_ledger and not self.get("__islocal"):
 			last_sle = self.get_last_sle()
-			self.set_status(last_sle.get("last_sle"))
 			self.set_purchase_details(last_sle.get("purchase_sle"))
 			self.set_sales_details(last_sle.get("delivery_sle"))
 			self.set_maintenance_status()
@@ -220,9 +205,10 @@
 					sr = frappe.get_doc("Serial No", serial_no)
 
 					if sr.item_code!=sle.item_code:
-						frappe.throw(_("Serial No {0} does not belong to Item {1}").format(serial_no,
-							sle.item_code), SerialNoItemError)
-
+						if not allow_serial_nos_with_different_item(serial_no, sle):
+							frappe.throw(_("Serial No {0} does not belong to Item {1}").format(serial_no,
+								sle.item_code), SerialNoItemError)
+								
 					if sr.warehouse and sle.actual_qty > 0:
 						frappe.throw(_("Serial No {0} has already been received").format(sr.name),
 							SerialNoDuplicateError)
@@ -232,10 +218,10 @@
 							frappe.throw(_("Serial No {0} does not belong to Warehouse {1}").format(serial_no,
 								sle.warehouse), SerialNoWarehouseError)
 
-						if sle.voucher_type in ("Delivery Note", "Sales Invoice") and sle.is_cancelled=="No" \
-							and sr.status != "Available":
-								frappe.throw(_("Serial No {0} status must be 'Available' to Deliver").format(serial_no),
-									SerialNoStatusError)
+						if sle.voucher_type in ("Delivery Note", "Sales Invoice") \
+							and sle.is_cancelled=="No" and not sr.warehouse:
+								frappe.throw(_("Serial No {0} does not belong to any Warehouse")
+									.format(serial_no), SerialNoWarehouseError)
 
 				elif sle.actual_qty < 0:
 					# transfer out
@@ -243,7 +229,24 @@
 		elif sle.actual_qty < 0 or not item_det.serial_no_series:
 			frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
 				SerialNoRequiredError)
-
+				
+def allow_serial_nos_with_different_item(sle_serial_no, sle):
+	"""
+		Allows same serial nos for raw materials and finished goods 
+		in Manufacture / Repack type Stock Entry
+	"""
+	allow_serial_nos = False
+	if sle.voucher_type=="Stock Entry" and sle.actual_qty > 0:
+		stock_entry = frappe.get_doc("Stock Entry", sle.voucher_no)
+		if stock_entry.purpose in ("Repack", "Manufacture"):
+			for d in stock_entry.get("items"):
+				if d.serial_no and (d.s_warehouse if sle.is_cancelled=="No" else d.t_warehouse):
+					serial_nos = get_serial_nos(d.serial_no)
+					if sle_serial_no in serial_nos:
+						allow_serial_nos = True
+	
+	return allow_serial_nos
+			
 def update_serial_nos(sle, item_det):
 	if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 \
 			and item_det.has_serial_no == 1 and item_det.serial_no_series:
@@ -260,6 +263,7 @@
 			if frappe.db.exists("Serial No", serial_no):
 				sr = frappe.get_doc("Serial No", serial_no)
 				sr.via_stock_ledger = True
+				sr.item_code = sle.item_code
 				sr.warehouse = sle.warehouse if sle.actual_qty > 0 else None
 				sr.save(ignore_permissions=True)
 			elif sle.actual_qty > 0:
@@ -287,7 +291,6 @@
 	sr.insert()
 
 	sr.warehouse = sle.warehouse
-	sr.status = "Available"
 	sr.save()
 	frappe.msgprint(_("Serial No {0} created").format(sr.name))
 	return sr.name
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 18d600d..868053e 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -359,14 +359,17 @@
 
 	def update_stock_ledger(self):
 		sl_entries = []
+		
+		# make sl entries for source warehouse first, then do for target warehouse
 		for d in self.get('items'):
-			if cstr(d.s_warehouse) and self.docstatus == 1:
+			if cstr(d.s_warehouse):
 				sl_entries.append(self.get_sl_entries(d, {
 					"warehouse": cstr(d.s_warehouse),
 					"actual_qty": -flt(d.transfer_qty),
 					"incoming_rate": 0
 				}))
-
+				
+		for d in self.get('items'):
 			if cstr(d.t_warehouse):
 				sl_entries.append(self.get_sl_entries(d, {
 					"warehouse": cstr(d.t_warehouse),
@@ -374,15 +377,18 @@
 					"incoming_rate": flt(d.valuation_rate)
 				}))
 
-			# On cancellation, make stock ledger entry for
-			# target warehouse first, to update serial no values properly
+		# On cancellation, make stock ledger entry for
+		# target warehouse first, to update serial no values properly
 
-			if cstr(d.s_warehouse) and self.docstatus == 2:
-				sl_entries.append(self.get_sl_entries(d, {
-					"warehouse": cstr(d.s_warehouse),
-					"actual_qty": -flt(d.transfer_qty),
-					"incoming_rate": 0
-				}))
+			# if cstr(d.s_warehouse) and self.docstatus == 2:
+			# 	sl_entries.append(self.get_sl_entries(d, {
+			# 		"warehouse": cstr(d.s_warehouse),
+			# 		"actual_qty": -flt(d.transfer_qty),
+			# 		"incoming_rate": 0
+			# 	}))
+
+		if self.docstatus == 2:
+			sl_entries.reverse()
 
 		self.make_sl_entries(sl_entries, self.amended_from and 'Yes' or 'No')
 
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 62c55fd..252deaa 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -566,6 +566,27 @@
 		stock_entry = frappe.get_doc(make_stock_entry(production_order.name, "Manufacture", 1))
 		stock_entry.insert()
 		self.assertTrue("_Test Variant Item-S" in [d.item_code for d in stock_entry.items])
+		
+	def test_same_serial_nos_in_repack_or_manufacture_entries(self):
+		s1 = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
+		serial_nos = s1.get("items")[0].serial_no
+		
+		s2 = make_stock_entry(item_code="_Test Serialized Item With Series", source="_Test Warehouse - _TC", 
+			qty=2, basic_rate=100, purpose="Repack", serial_no=serial_nos, do_not_save=True)
+			
+		s2.append("items", {
+			"item_code": "_Test Serialized Item",
+			"t_warehouse": "_Test Warehouse - _TC",
+			"qty": 2,
+			"basic_rate": 120,
+			"expense_account": "Stock Adjustment - _TC",
+			"conversion_factor": 1.0,
+			"cost_center": "_Test Cost Center - _TC",
+			"serial_no": serial_nos
+		})
+		
+		s2.submit()
+		s2.cancel()
 
 def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
 	se = frappe.copy_doc(test_records[0])
@@ -616,7 +637,8 @@
 		"basic_rate": args.basic_rate,
 		"expense_account": args.expense_account or "Stock Adjustment - _TC",
 		"conversion_factor": 1.0,
-		"cost_center": "_Test Cost Center - _TC"
+		"cost_center": "_Test Cost Center - _TC",
+		"serial_no": args.serial_no
 	})
 
 	if not args.do_not_save:
diff --git a/erpnext/stock/report/serial_no_status/serial_no_status.json b/erpnext/stock/report/serial_no_status/serial_no_status.json
index ecfa3a0..917d26f 100644
--- a/erpnext/stock/report/serial_no_status/serial_no_status.json
+++ b/erpnext/stock/report/serial_no_status/serial_no_status.json
@@ -1,12 +1,14 @@
 {
+ "add_total_row": 0, 
  "apply_user_permissions": 1, 
  "creation": "2013-01-14 10:52:58", 
+ "disabled": 0, 
  "docstatus": 0, 
  "doctype": "Report", 
  "idx": 1, 
  "is_standard": "Yes", 
- "json": "{\"sort_by\": \"Serial No.name\", \"sort_order\": \"desc\", \"sort_by_next\": \"\", \"filters\": [], \"sort_order_next\": \"desc\", \"columns\": [[\"name\", \"Serial No\"], [\"item_code\", \"Serial No\"], [\"warehouse\", \"Serial No\"], [\"status\", \"Serial No\"], [\"item_name\", \"Serial No\"], [\"description\", \"Serial No\"], [\"item_group\", \"Serial No\"], [\"brand\", \"Serial No\"], [\"purchase_document_no\", \"Serial No\"], [\"purchase_date\", \"Serial No\"], [\"customer\", \"Serial No\"], [\"customer_name\", \"Serial No\"], [\"purchase_rate\", \"Serial No\"], [\"delivery_document_no\", \"Serial No\"], [\"delivery_date\", \"Serial No\"], [\"supplier\", \"Serial No\"], [\"supplier_name\", \"Serial No\"]]}", 
- "modified": "2014-06-03 07:18:17.327622", 
+ "json": "{\"filters\":[],\"columns\":[[\"name\",\"Serial No\"],[\"item_code\",\"Serial No\"],[\"warehouse\",\"Serial No\"],[\"status\",\"Serial No\"],[\"item_name\",\"Serial No\"],[\"description\",\"Serial No\"],[\"item_group\",\"Serial No\"],[\"brand\",\"Serial No\"],[\"purchase_document_no\",\"Serial No\"],[\"purchase_date\",\"Serial No\"],[\"customer\",\"Serial No\"],[\"customer_name\",\"Serial No\"],[\"purchase_rate\",\"Serial No\"],[\"delivery_document_no\",\"Serial No\"],[\"delivery_date\",\"Serial No\"],[\"supplier\",\"Serial No\"],[\"supplier_name\",\"Serial No\"]],\"sort_by\":\"Serial No.name\",\"sort_order\":\"desc\",\"sort_by_next\":null,\"sort_order_next\":\"desc\"}", 
+ "modified": "2015-09-20 21:09:49.441973", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Serial No Status", 
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index cba2464..dd62e15 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -214,8 +214,7 @@
 
 def reset_serial_no_status_and_warehouse(serial_nos=None):
 	if not serial_nos:
-		serial_nos = frappe.db.sql_list("""select name from `tabSerial No` where status != 'Not in Use'
-			and docstatus = 0""")
+		serial_nos = frappe.db.sql_list("""select name from `tabSerial No` where docstatus = 0""")
 		for serial_no in serial_nos:
 			try:
 				sr = frappe.get_doc("Serial No", serial_no)
@@ -228,8 +227,6 @@
 			except:
 				pass
 
-		frappe.db.sql("""update `tabSerial No` set warehouse='' where status in ('Delivered', 'Purchase Returned')""")
-
 def repost_all_stock_vouchers():
 	warehouses_with_account = frappe.db.sql_list("""select master_name from tabAccount
 		where ifnull(account_type, '') = 'Warehouse'""")
diff --git a/sponsors.md b/sponsors.md
index 8e10081..d3fbc21 100644
--- a/sponsors.md
+++ b/sponsors.md
@@ -45,5 +45,13 @@
 				For Mandrill Integration <a href="https://github.com/frappe/erpnext/issues/3546">#3546</a>
 			</td>
 		</tr>
+		<tr>
+			<td style="width: 30%">
+				<a href="http://www.gps.gt">Startrack</a>
+			</td>
+			<td>
+				For Delivery to Target Warehouse <a href="https://github.com/frappe/erpnext/issues/3970">#3546</a>
+			</td>
+		</tr>
 	</tbody>
 </table>