From 091ca75fa345a814e6d02e2e6f5eb8ef26b1c219 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 24 May 2016 12:04:45 +0530 Subject: [PATCH] [enhance] warehouse browser page for warehouse tree --- erpnext/setup/doctype/company/company.py | 13 +- .../stock/page/warehouse_browser/__init__.py | 0 .../warehouse_browser/warehouse_browser.js | 158 ++++++++++++++++++ .../warehouse_browser/warehouse_browser.json | 27 +++ .../warehouse_browser/warehouse_browser.py | 35 ++++ 5 files changed, 230 insertions(+), 3 deletions(-) create mode 100644 erpnext/stock/page/warehouse_browser/__init__.py create mode 100644 erpnext/stock/page/warehouse_browser/warehouse_browser.js create mode 100644 erpnext/stock/page/warehouse_browser/warehouse_browser.json create mode 100644 erpnext/stock/page/warehouse_browser/warehouse_browser.py diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 7da7c25d13..0ed7a826ca 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -87,15 +87,22 @@ class Company(Document): .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 0000000000..e69de29bb2 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 0000000000..d123ff4548 --- /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 0000000000..3d0dcbcaf4 --- /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 0000000000..48bb8a3389 --- /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