[enhance] warehouse browser page for warehouse tree
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 7da7c25..0ed7a82 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -87,15 +87,22 @@
 				.format(self.country.lower()))(self)
 
 	def create_default_warehouses(self):
-		for whname in (_("Stores"), _("Work In Progress"), _("Finished Goods")):
-			if not frappe.db.exists("Warehouse", whname + " - " + self.abbr):
+		for wh_detail in [{"warehouse_name": _("All Warehouses"), "is_group": "Yes"},
+			{"warehouse_name": _("Stores"), "is_group": "No"},
+			{"warehouse_name": _("Work In Progress"), "is_group": "No"},
+			{"warehouse_name": _("Finished Goods"), "is_group": "No"}]:
+			
+			if not frappe.db.exists("Warehouse", "{0} - {1}".format(wh_detail["warehouse_name"], self.abbr)):
 				stock_group = frappe.db.get_value("Account", {"account_type": "Stock",
 					"is_group": 1, "company": self.name})
 				if stock_group:
 					warehouse = frappe.get_doc({
 						"doctype":"Warehouse",
-						"warehouse_name": whname,
+						"warehouse_name": wh_detail["warehouse_name"],
+						"is_group": wh_detail["is_group"],
 						"company": self.name,
+						"parent_warehouse": "" if wh_detail["is_group"] == "Yes" \
+							else "{0} - {1}".format(_("All Warehouses"), self.abbr),
 						"create_account_under": stock_group
 					})
 					warehouse.flags.ignore_permissions = True
diff --git a/erpnext/stock/page/warehouse_browser/__init__.py b/erpnext/stock/page/warehouse_browser/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/page/warehouse_browser/__init__.py
diff --git a/erpnext/stock/page/warehouse_browser/warehouse_browser.js b/erpnext/stock/page/warehouse_browser/warehouse_browser.js
new file mode 100644
index 0000000..d123ff4
--- /dev/null
+++ b/erpnext/stock/page/warehouse_browser/warehouse_browser.js
@@ -0,0 +1,158 @@
+frappe.pages['warehouse-browser'].on_page_load = function(wrapper) {
+	var page = frappe.ui.make_app_page({
+		parent: wrapper,
+		single_column: true
+	});
+	
+	wrapper.page.add_menu_item(__('Refresh'), function() {
+			wrapper.make_tree();
+		});
+		
+	wrapper.make_tree = function() {
+		var ctype = frappe.get_route()[1] || 'Warehouse';
+		return frappe.call({
+			method: 'erpnext.stock.page.warehouse_browser.warehouse_browser.get_children',
+			args: {ctype: ctype},
+			callback: function(r) {
+				var root = r.message[0]["value"];
+				erpnext.warehouse_chart = new erpnext.WarehouseChart(ctype, root, page,
+					page.main.css({
+						"min-height": "300px",
+						"padding-bottom": "25px"
+					}));
+			}
+		});
+	}
+
+	wrapper.make_tree();
+}
+
+frappe.pages['warehouse-browser'].on_page_show = function(wrapper){
+	// set route
+	var ctype = frappe.get_route()[1] || 'Warehouse';
+
+	wrapper.page.set_title(__('{0} Tree',[__(ctype)]));
+
+	if(erpnext.warehouse_chart && erpnext.warehouse_chart.ctype != ctype) {
+		wrapper.make_tree();
+	}
+
+	frappe.breadcrumbs.add(frappe.breadcrumbs.last_module || "Stock");
+};
+
+erpnext.WarehouseChart = Class.extend({
+	init: function(ctype, root, page, parent){
+		$(parent).empty();
+		var me = this;
+		me.ctype = ctype;
+		me.page = page;
+		me.can_read = frappe.model.can_read(this.ctype);
+		me.can_create = frappe.boot.user.can_create.indexOf(this.ctype) !== -1 ||
+					frappe.boot.user.in_create.indexOf(this.ctype) !== -1;
+		me.can_write = frappe.model.can_write(this.ctype);
+		me.can_delete = frappe.model.can_delete(this.ctype);
+
+		me.page.set_primary_action(__("New"), function() {
+			me.new_node();
+		}, "octicon octicon-plus");
+
+		this.tree = new frappe.ui.Tree({
+			parent: $(parent),
+			label: __(root),
+			args: {ctype: ctype},
+			method: 'erpnext.stock.page.warehouse_browser.warehouse_browser.get_children',
+			toolbar: [
+				{toggle_btn: true},
+				{
+					label:__("Edit"),
+					condition: function(node) {
+						return !node.root && me.can_read;
+					},
+					click: function(node) {
+						frappe.set_route("Form", me.ctype, node.label);
+					}
+				},
+				{
+					label:__("Add Child"),
+					condition: function(node) { return me.can_create && node.expandable; },
+					click: function(node) {
+						me.new_node();
+					},
+					btnClass: "hidden-xs"
+				},
+				{
+					label:__("Rename"),
+					condition: function(node) { return !node.root && me.can_write; },
+					click: function(node) {
+						frappe.model.rename_doc(me.ctype, node.label, function(new_name) {
+							node.$a.html(new_name);
+						});
+					},
+					btnClass: "hidden-xs"
+				},
+				{
+					label:__("Delete"),
+					condition: function(node) { return !node.root && me.can_delete; },
+					click: function(node) {
+						frappe.model.delete_doc(me.ctype, node.label, function() {
+							node.parent.remove();
+						});
+					},
+					btnClass: "hidden-xs"
+				}
+
+			]
+		});
+	},
+	new_node: function() {
+		var me = this;
+		var node = me.tree.get_selected_node();
+
+		if(!(node && node.expandable)) {
+			frappe.msgprint(__("Select a group node first."));
+			return;
+		}
+
+		var fields = [
+			{fieldtype:'Data', fieldname: 'name_field',
+				label:__('New {0} Name',[__(me.ctype)]), reqd:true},
+			{fieldtype:'Select', fieldname:'is_group', label:__('Group Node'), options:'No\nYes',
+				description: __("Further nodes can be only created under 'Group' type nodes")}
+		]
+
+		// the dialog
+		var d = new frappe.ui.Dialog({
+			title: __('New {0}',[__(me.ctype)]),
+			fields: fields
+		})
+
+		d.set_value("is_group", "No");
+		// create
+		d.set_primary_action(__("Create New"), function() {
+			var btn = this;
+			var v = d.get_values();
+			if(!v) return;
+
+			var node = me.tree.get_selected_node();
+
+			v.parent = node.label;
+			v.ctype = me.ctype;
+
+			return frappe.call({
+				method: 'erpnext.stock.page.warehouse_browser.warehouse_browser.add_node',
+				args: v,
+				callback: function(r) {
+					if(!r.exc) {
+						d.hide();
+						if(node.expanded) {
+							node.toggle_node();
+						}
+						node.reload();
+					}
+				}
+			});
+		});
+
+		d.show();
+	},
+})
\ No newline at end of file
diff --git a/erpnext/stock/page/warehouse_browser/warehouse_browser.json b/erpnext/stock/page/warehouse_browser/warehouse_browser.json
new file mode 100644
index 0000000..3d0dcbc
--- /dev/null
+++ b/erpnext/stock/page/warehouse_browser/warehouse_browser.json
@@ -0,0 +1,27 @@
+{
+ "content": null, 
+ "creation": "2016-05-24 11:01:06.887660", 
+ "docstatus": 0, 
+ "doctype": "Page", 
+ "idx": 0, 
+ "modified": "2016-05-24 11:11:32.317342", 
+ "modified_by": "Administrator", 
+ "module": "Stock", 
+ "name": "warehouse-browser", 
+ "owner": "Administrator", 
+ "page_name": "Warehouse Browser", 
+ "roles": [
+  {
+   "role": "Stock Manager"
+  }, 
+  {
+   "role": "Stock User"
+  }, 
+  {
+   "role": "System Manager"
+  }
+ ], 
+ "script": null, 
+ "standard": "Yes", 
+ "style": null
+}
\ No newline at end of file
diff --git a/erpnext/stock/page/warehouse_browser/warehouse_browser.py b/erpnext/stock/page/warehouse_browser/warehouse_browser.py
new file mode 100644
index 0000000..48bb8a3
--- /dev/null
+++ b/erpnext/stock/page/warehouse_browser/warehouse_browser.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+@frappe.whitelist()
+def get_children():
+	ctype = frappe.local.form_dict.get('ctype')
+	parent_field = 'parent_' + ctype.lower().replace(' ', '_')
+	parent = frappe.form_dict.get("parent") or ""
+
+	return frappe.db.sql("""select name as value,
+		if(is_group='Yes', 1, 0) as expandable
+		from `tab{ctype}`
+		where docstatus < 2
+		and ifnull(`{parent_field}`,'') = %s
+		order by name""".format(ctype=frappe.db.escape(ctype), parent_field=frappe.db.escape(parent_field)),
+		parent, as_dict=1)
+
+@frappe.whitelist()
+def add_node():
+	ctype = frappe.form_dict.get('ctype')
+	parent_field = 'parent_' + ctype.lower().replace(' ', '_')
+	name_field = ctype.lower().replace(' ', '_') + '_name'
+
+	doc = frappe.new_doc(ctype)
+	
+	doc.update({
+		name_field: frappe.form_dict['name_field'],
+		parent_field: frappe.form_dict['parent'],
+		"is_group": frappe.form_dict['is_group']
+	})
+
+	doc.save()
\ No newline at end of file