Merge pull request #3709 from nabinhait/contacts

[cleanup] Party Type deleted
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index e8a772a..d45fbba 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -272,6 +272,10 @@
 	def postprocess(source, doc):
 		doc.material_request_type = "Purchase"
 
+	so = frappe.get_doc("Sales Order", source_name)
+	
+	item_table = "Packed Item" if so.packed_items else "Sales Order Item"
+	
 	doc = get_mapped_doc("Sales Order", source_name, {
 		"Sales Order": {
 			"doctype": "Material Request",
@@ -279,7 +283,7 @@
 				"docstatus": ["=", 1]
 			}
 		},
-		"Sales Order Item": {
+		item_table: {
 			"doctype": "Material Request Item",
 			"field_map": {
 				"parent": "sales_order_no",
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 58b1adb..3bd5657 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -86,8 +86,12 @@
 	},
 	
 	manage_variants: function(frm) {
-		frappe.route_options = {"item_code": frm.doc.name };
-		frappe.set_route("List", "Manage Variants");
+		if (cur_frm.doc.__unsaved==1) {
+			frappe.throw(__("You have unsaved changes. Please save."))
+		} else {
+			frappe.route_options = {"item_code": frm.doc.name };
+			frappe.set_route("List", "Manage Variants");
+		}
 	}
 });
 
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index a2e0ade..d3d8e9c 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -325,7 +325,8 @@
 			for d in variants:
 				update_variant(self.name, d)
 				updated.append(d.item_code)
-			frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))
+			if updated:
+				frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))
 				
 	def validate_has_variants(self):
 		if not self.has_variants and frappe.db.get_value("Item", self.name, "has_variants"):
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index 0651ae8..c2c6d1a 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -9,8 +9,13 @@
 	columns = get_columns()
 	sl_entries = get_stock_ledger_entries(filters)
 	item_details = get_item_details(filters)
-
+	opening_row = get_opening_balance(filters, columns)
+	
 	data = []
+	
+	if opening_row:
+		data.append(opening_row)
+
 	for sle in sl_entries:
 		item_detail = item_details[sle.item_code]
 
@@ -20,7 +25,7 @@
 			(sle.incoming_rate if sle.actual_qty > 0 else 0.0),
 			sle.valuation_rate, sle.stock_value, sle.voucher_type, sle.voucher_no,
 			sle.batch_no, sle.serial_no, sle.company])
-
+			
 	return columns, data
 
 def get_columns():
@@ -40,7 +45,7 @@
 		where company = %(company)s and
 			posting_date between %(from_date)s and %(to_date)s
 			{sle_conditions}
-			order by posting_date desc, posting_time desc, name desc"""\
+			order by posting_date asc, posting_time asc, name asc"""\
 		.format(sle_conditions=get_sle_conditions(filters)), filters, as_dict=1)
 
 def get_item_details(filters):
@@ -73,3 +78,22 @@
 		conditions.append("voucher_no=%(voucher_no)s")
 
 	return "and {}".format(" and ".join(conditions)) if conditions else ""
+
+def get_opening_balance(filters, columns):
+	if not (filters.item_code and filters.warehouse and filters.from_date):
+		return
+
+	from erpnext.stock.stock_ledger import get_previous_sle
+	last_entry = get_previous_sle({
+		"item_code": filters.item_code,
+		"warehouse": filters.warehouse,
+		"posting_date": filters.from_date,
+		"posting_time": "00:00:00"
+	})
+	
+	row = [""]*len(columns)
+	row[1] = _("'Opening'")
+	for i, v in ((9, 'qty_after_transaction'), (11, 'valuation_rate'), (12, 'stock_value')):
+			row[i] = last_entry.get(v, 0)
+		
+	return row
\ No newline at end of file