Merge pull request #3704 from nabinhait/fix2

[fix] SMS status and log
diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.json b/erpnext/accounts/report/accounts_payable/accounts_payable.json
index 71537a8..9be8d68 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.json
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.json
@@ -6,12 +6,12 @@
  "doctype": "Report", 
  "idx": 1, 
  "is_standard": "Yes", 
- "modified": "2014-06-03 07:18:10.985354", 
+ "modified": "2015-07-23 01:08:20.996267", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Accounts Payable", 
  "owner": "Administrator", 
  "ref_doctype": "Purchase Invoice", 
  "report_name": "Accounts Payable", 
- "report_type": "Report Builder"
+ "report_type": "Query Report"
 }
\ No newline at end of file
diff --git a/erpnext/contacts/__init__.py b/erpnext/contacts/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/contacts/__init__.py
+++ /dev/null
diff --git a/erpnext/contacts/doctype/__init__.py b/erpnext/contacts/doctype/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/contacts/doctype/__init__.py
+++ /dev/null
diff --git a/erpnext/contacts/doctype/party_type/__init__.py b/erpnext/contacts/doctype/party_type/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/contacts/doctype/party_type/__init__.py
+++ /dev/null
diff --git a/erpnext/contacts/doctype/party_type/party_type.json b/erpnext/contacts/doctype/party_type/party_type.json
deleted file mode 100644
index 19ffefb..0000000
--- a/erpnext/contacts/doctype/party_type/party_type.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "allow_rename": 1, 
- "autoname": "field:party_type_name", 
- "creation": "2014-04-07 12:32:18.010384", 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Master", 
- "fields": [
-  {
-   "fieldname": "party_type_name", 
-   "fieldtype": "Data", 
-   "in_list_view": 1, 
-   "label": "Party Type Name", 
-   "permlevel": 0, 
-   "reqd": 1
-  }, 
-  {
-   "fieldname": "parent_party_type", 
-   "fieldtype": "Link", 
-   "label": "Parent Party Type", 
-   "options": "Party Type", 
-   "permlevel": 0
-  }, 
-  {
-   "default": "Yes", 
-   "fieldname": "allow_children", 
-   "fieldtype": "Select", 
-   "label": "Allow Children", 
-   "options": "Yes\nNo", 
-   "permlevel": 0
-  }, 
-  {
-   "fieldname": "default_price_list", 
-   "fieldtype": "Link", 
-   "ignore_user_permissions": 1, 
-   "label": "Default Price List", 
-   "options": "Price List", 
-   "permlevel": 0
-  }, 
-  {
-   "fieldname": "lft", 
-   "fieldtype": "Int", 
-   "hidden": 1, 
-   "label": "LFT", 
-   "permlevel": 0, 
-   "read_only": 1, 
-   "search_index": 1
-  }, 
-  {
-   "fieldname": "rgt", 
-   "fieldtype": "Int", 
-   "hidden": 1, 
-   "label": "RGT", 
-   "permlevel": 0, 
-   "read_only": 1, 
-   "search_index": 1
-  }, 
-  {
-   "fieldname": "old_parent", 
-   "fieldtype": "Data", 
-   "hidden": 1, 
-   "label": "Old Parent", 
-   "permlevel": 0, 
-   "read_only": 1
-  }
- ], 
- "modified": "2015-02-05 05:11:42.046004", 
- "modified_by": "Administrator", 
- "module": "Contacts", 
- "name": "Party Type", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "apply_user_permissions": 1, 
-   "create": 1, 
-   "permlevel": 0, 
-   "read": 1, 
-   "role": "Sales User", 
-   "share": 1, 
-   "write": 1
-  }, 
-  {
-   "apply_user_permissions": 1, 
-   "create": 1, 
-   "permlevel": 0, 
-   "read": 1, 
-   "role": "Purchase User", 
-   "share": 1, 
-   "write": 1
-  }
- ]
-}
\ No newline at end of file
diff --git a/erpnext/contacts/doctype/party_type/party_type.py b/erpnext/contacts/doctype/party_type/party_type.py
deleted file mode 100644
index d21216f..0000000
--- a/erpnext/contacts/doctype/party_type/party_type.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils.nestedset import NestedSet
-
-class PartyType(NestedSet):
-	nsm_parent_field = 'parent_party_type';
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index a87c8f0..91ba19a 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -1,11 +1,34 @@
 from __future__ import unicode_literals
 app_name = "erpnext"
 app_title = "ERPNext"
-app_publisher = "Frappe Technologies Pvt. Ltd. and Contributors"
-app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
+app_publisher = "Frappe Technologies Pvt. Ltd."
+app_description = """## ERPNext
+
+ERPNext is a fully featured ERP system designed for Small and Medium Sized
+business. ERPNext covers a wide range of features including Accounting, CRM,
+Inventory management, Selling, Purchasing, Manufacturing, Projects, HR &
+Payroll, Website, E-Commerce and much more.
+
+ERPNext is based on the Frappe Framework is highly customizable and extendable.
+You can create Custom Form, Fields, Scripts and can also create your own Apps
+to extend ERPNext functionality.
+
+ERPNext is Open Source under the GNU General Public Licence v3 and has been
+listed as one of the Best Open Source Softwares in the world by my online
+blogs.
+
+### Links
+
+- Website: [https://erpnext.com](https://erpnext.com)
+- GitHub: [https://github.com/frappe/erpnext](https://github.com/frappe/erpnext)
+- Forum: [https://discuss.erpnext.com](https://discuss.erpnext.com)
+- Frappe Framework: [https://frappe.io](https://frappe.io)
+
+"""
 app_icon = "icon-th"
 app_color = "#e74c3c"
 app_version = "5.2.1"
+github_link = "https://github.com/frappe/erpnext"
 
 error_report_email = "support@erpnext.com"
 
diff --git a/erpnext/modules.txt b/erpnext/modules.txt
index 67c856d..dfca2f2 100644
--- a/erpnext/modules.txt
+++ b/erpnext/modules.txt
@@ -9,6 +9,5 @@
 Stock
 Support
 Utilities
-Contacts
 Shopping Cart
 Hub Node
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 269dcba..c735507 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -177,3 +177,4 @@
 execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=True)
 erpnext.patches.v5_1.rename_roles
 erpnext.patches.v5_1.default_bom
+execute:frappe.delete_doc("DocType", "Party Type")
\ No newline at end of file
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/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index 413f820..efa6a8a 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -11,6 +11,7 @@
 from erpnext.stock.utils import get_stock_balance
 
 class OpeningEntryAccountError(frappe.ValidationError): pass
+class EmptyStockReconciliationItemsError(frappe.ValidationError): pass
 
 class StockReconciliation(StockController):
 	def __init__(self, arg1, arg2=None):
@@ -51,7 +52,11 @@
 
 		items = filter(lambda d: _changed(d), self.items)
 
-		if len(items) != len(self.items):
+		if not items:
+			frappe.throw(_("None of the items have any change in quantity or value."),
+				EmptyStockReconciliationItemsError)
+
+		elif len(items) != len(self.items):
 			self.items = items
 			for i, item in enumerate(self.items):
 				item.idx = i + 1
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
diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html
index 0967e97..6748a5e 100644
--- a/erpnext/templates/includes/macros.html
+++ b/erpnext/templates/includes/macros.html
@@ -1,6 +1,6 @@
 {% macro product_image_square(website_image, css_class="") %}
 <div class="product-image product-image-square {% if not website_image -%} missing-image {%- endif %} {{ css_class }}"
-	{% if website_image -%} style="background-image: url('{{ frappe.utils.quoted(website_image) }}');" {%- endif %}>
+	{% if website_image -%} style="background-image: url('{{ frappe.utils.quoted(website_image) | abs_url }}');" {%- endif %}>
 	{% if not website_image -%}<i class="centered octicon octicon-device-camera"></i>{%- endif %}
 </div>
 {% endmacro %}
@@ -8,7 +8,7 @@
 {% macro product_image(website_image, css_class="") %}
 <div class="product-image {% if not website_image -%} missing-image {%- endif %} {{ css_class }}">
 	{% if website_image -%}
-		<img src="{{ frappe.utils.quoted(website_image) }}" class="img-responsive">
+		<img src="{{ frappe.utils.quoted(website_image) | abs_url }}" class="img-responsive">
 	{%- else -%}
 		<i class="centered octicon octicon-device-camera"></i>
 	{%- endif %}