Merge pull request #3708 from neilLasrado/material-request

Fetch items from Packing List if Exists in Sales Order while raising …
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/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/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 %}