[fixes] validate trash condition for warehouse and related account, move existing warehouses under all warehouse group, set account parent and is group for warehouse account
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index 718ba31..f5000f4 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -179,9 +179,12 @@
self.warehouse = None
def validate_warehouse(self, warehouse):
- if frappe.db.get_value("Stock Ledger Entry", {"warehouse": warehouse}):
+ lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"])
+
+ if frappe.db.sql_list("""select sle.name from `tabStock Ledger Entry` sle where exists (select wh.name from
+ tabWarehouse wh where lft >= %s and rgt <= %s and sle.warehouse = wh.warehouse)""", (lft, rgt)):
throw(_("Stock entries exist against warehouse {0}, hence you cannot re-assign or modify Warehouse").format(warehouse))
-
+
def update_nsm_model(self):
"""update lft, rgt indices for nested set model"""
import frappe
diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js
index 3ee1c42..3252788 100644
--- a/erpnext/accounts/doctype/account/account_tree.js
+++ b/erpnext/accounts/doctype/account/account_tree.js
@@ -3,7 +3,7 @@
title: __("Chart Of Accounts"),
get_tree_root: false,
filters: [{
- fieldname: "comp",
+ fieldname: "company",
fieldtype:"Select",
options: $.map(locals[':Company'], function(c) { return c.name; }).sort(),
label: __("Company"),
diff --git a/erpnext/accounts/doctype/cost_center/cost_center_tree.js b/erpnext/accounts/doctype/cost_center/cost_center_tree.js
index 3ca5232..ac82f23 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center_tree.js
+++ b/erpnext/accounts/doctype/cost_center/cost_center_tree.js
@@ -2,7 +2,7 @@
breadcrumbs: "Accounts",
get_tree_root: false,
filters: [{
- fieldname: "comp",
+ fieldname: "company",
fieldtype:"Select",
options: $.map(locals[':Company'], function(c) { return c.name; }).sort(),
label: __("Company"),
diff --git a/erpnext/accounts/doctype/payment_tool/payment_tool.py b/erpnext/accounts/doctype/payment_tool/payment_tool.py
index 7f95ade..5c5b393 100644
--- a/erpnext/accounts/doctype/payment_tool/payment_tool.py
+++ b/erpnext/accounts/doctype/payment_tool/payment_tool.py
@@ -7,7 +7,7 @@
from frappe.utils import flt
from frappe.model.document import Document
import json
-from erpnext.accounts.doctype.account.account import get_account_currency
+from erpnext.accounts.utils import get_account_currency
from erpnext.accounts.doctype.journal_entry.journal_entry import get_exchange_rate
class PaymentTool(Document):
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 78e0761..5cccf1b 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -9,6 +9,7 @@
from frappe.utils import formatdate
# imported to enable erpnext.accounts.utils.get_account_currency
+from erpnext.accounts.doctype.account.account import get_account_currency
import frappe.defaults
from erpnext.accounts.report.financial_statements import sort_root_accounts
@@ -128,7 +129,7 @@
if not args:
args = frappe.local.form_dict
args.pop("cmd")
-
+
ac = frappe.new_doc("Account")
if args.get("ignore_permissions"):
@@ -139,7 +140,7 @@
if not ac.parent_account:
ac.parent_account = args.get("parent")
-
+
ac.old_parent = ""
ac.freeze_account = "No"
if cint(ac.get("is_root")):
@@ -447,7 +448,7 @@
@frappe.whitelist()
def get_children():
args = frappe.local.form_dict
- ctype, company = args['ctype'], args['comp']
+ ctype, company = args['ctype'], args['company']
fieldname = frappe.db.escape(ctype.lower().replace(' ','_'))
doctype = frappe.db.escape(ctype)
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index ac58e9c..e3a66a4 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -6,8 +6,7 @@
from frappe import _, throw
from frappe.utils import today, flt, cint, fmt_money, formatdate, getdate
from erpnext.setup.utils import get_company_currency, get_exchange_rate
-from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year
-from erpnext.accounts.doctype.account.account import get_account_currency
+from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
from erpnext.utilities.transaction_base import TransactionBase
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
from erpnext.controllers.sales_and_purchase_return import validate_return
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 1976cc6..1e685e5 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -321,6 +321,7 @@
warehouse_account = frappe._dict()
for d in frappe.db.sql("""select warehouse, name, account_currency from tabAccount
- where account_type = 'Warehouse' and (warehouse is not null and warehouse != '')""", as_dict=1):
+ where account_type = 'Warehouse' and (warehouse is not null and warehouse != ''
+ and is_group != 1)""", as_dict=1):
warehouse_account.setdefault(d.warehouse, d)
return warehouse_account
diff --git a/erpnext/patches/v7_0/group_warehouses.py b/erpnext/patches/v7_0/group_warehouses.py
new file mode 100644
index 0000000..8987d58
--- /dev/null
+++ b/erpnext/patches/v7_0/group_warehouses.py
@@ -0,0 +1,45 @@
+import frappe
+from frappe import _
+
+def execute():
+ frappe.reload_doc("stock", "doctype", "warehouse")
+ for company in frappe.get_all("Company", fields=["name", "abbr"]):
+ if not frappe.db.get_value("Warehouse", "{0} - {1}".format(_("All Warehouses"), company.abbr)):
+ create_default_warehouse_group(company)
+
+ for warehouse in frappe.get_all("Warehouse", {"company": company}, ["name", "create_account_under", "parent_warehouse"]):
+ set_parent_to_warehouses(warehouse, company)
+ set_parent_to_warehouse_acounts(warehouse, company)
+
+def set_parent_to_warehouses(warehouse, company):
+ warehouse = frappe.get_doc("Warehouse", warehouse.name)
+ warehouse.is_group = "No"
+
+ if not warehouse.parent_warehouse:
+ warehouse.parent_warehouse = "{0} - {1}".format(_("All Warehouses"), company.abbr)
+
+ warehouse.save()
+
+def set_parent_to_warehouse_acounts(warehouse, company):
+ account = frappe.db.get_value("Account", {"warehouse": warehouse.name})
+ stock_group = frappe.db.get_value("Account", {"account_type": "Stock",
+ "is_group": 1, "company": company.name})
+
+ if account:
+ account = frappe.get_doc("Account", account)
+
+ if warehouse.create_account_under == stock_group or not warehouse.create_account_under:
+ if not warehouse.parent_warehouse:
+ account.parent_account = "{0} - {1}".format(_("All Warehouses"), company.abbr)
+ else:
+ account.parent_account = frappe.db.get_value("Account", {"warehouse": warehouse.parent_warehouse})
+ account.save(ignore_permissions=True)
+
+def create_default_warehouse_group(company):
+ frappe.get_doc({
+ "doctype": "Warehouse",
+ "warehouse_name": _("All Warehouses"),
+ "is_group": "Yes",
+ "company": company.name,
+ "parent_warehouse": ""
+ }).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index c45c241..7d88297 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -88,6 +88,7 @@
def create_default_warehouses(self):
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"}]:
@@ -101,7 +102,8 @@
"warehouse_name": wh_detail["warehouse_name"],
"is_group": wh_detail["is_group"],
"company": self.name,
- "parent_warehouse": "",
+ "parent_warehouse": "{0} - {1}".format(_("All Warehouses"), self.abbr) \
+ if wh_detail["is_group"] == "No" else "",
"create_account_under": stock_group
})
warehouse.flags.ignore_permissions = True
diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py
index c03ceee..2378e3f 100644
--- a/erpnext/stock/doctype/bin/bin.py
+++ b/erpnext/stock/doctype/bin/bin.py
@@ -18,7 +18,7 @@
self.projected_qty = flt(self.actual_qty) + flt(self.ordered_qty) + \
flt(self.indented_qty) + flt(self.planned_qty) - flt(self.reserved_qty)
- self.validate_leaf_warehouse()
+ self.block_transactions_against_group_warehouse()
def validate_mandatory(self):
qf = ['actual_qty', 'reserved_qty', 'ordered_qty', 'indented_qty']
@@ -26,11 +26,9 @@
if (not getattr(self, f, None)) or (not self.get(f)):
self.set(f, 0.0)
- def validate_leaf_warehouse(self):
- from erpnext.stock.utils import is_leaf_warehouse
-
- if not is_leaf_warehouse(self.warehouse):
- frappe.throw(_("Group node warehouse is not allowed to select for transactions"))
+ def block_transactions_against_group_warehouse(self):
+ from erpnext.stock.utils import is_group_warehouse
+ is_group_warehouse(self.warehouse)
def update_stock(self, args, allow_negative_stock=False, via_landed_cost_voucher=False):
self.update_qty(args)
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index 1f446d2..2caabee 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -25,7 +25,7 @@
validate_warehouse_company(self.warehouse, self.company)
self.scrub_posting_time()
self.validate_and_set_fiscal_year()
- self.validate_leaf_warehouse()
+ self.block_transactions_against_group_warehouse()
from erpnext.accounts.utils import validate_fiscal_year
validate_fiscal_year(self.posting_date, self.fiscal_year, self.meta.get_label("posting_date"), self)
@@ -118,11 +118,9 @@
if not self.fiscal_year:
self.fiscal_year = get_fiscal_year(self.posting_date, company=self.company)[0]
- def validate_leaf_warehouse(self):
- from erpnext.stock.utils import is_leaf_warehouse
-
- if not is_leaf_warehouse(self.warehouse):
- frappe.throw(_("Group node warehouse is not allowed to select for transactions"))
+ def block_transactions_against_group_warehouse(self):
+ from erpnext.stock.utils import is_group_warehouse
+ is_group_warehouse(self.warehouse)
def on_doctype_update():
if not frappe.db.sql("""show index from `tabStock Ledger Entry`
diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py
index a0b7296..58f7f60 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.py
+++ b/erpnext/stock/doctype/warehouse/warehouse.py
@@ -57,8 +57,9 @@
ac_doc = frappe.get_doc({
"doctype": "Account",
'account_name': self.warehouse_name,
- 'parent_account': self.create_account_under,
- 'is_group':0,
+ 'parent_account': self.parent_warehouse if self.parent_warehouse \
+ else self.create_account_under,
+ 'is_group': 1 if self.is_group=="Yes" else 0 ,
'company':self.company,
"account_type": "Warehouse",
"warehouse": self.name,
@@ -77,6 +78,7 @@
{"account_name": "Stock Assets", "company": self.company})
if parent_account:
+ frappe.db.set_value("Warehouse", self.name, "create_account_under", parent_account)
self.create_account_under = parent_account
else:
frappe.throw(_("Please enter parent account group for warehouse {0}").format(self.name))
@@ -105,6 +107,11 @@
if frappe.db.sql("""select name from `tabStock Ledger Entry`
where warehouse = %s""", self.name):
throw(_("Warehouse can not be deleted as stock ledger entry exists for this warehouse."))
+
+ if frappe.db.sql("""select name from `tabWarehouse` where parent_warehouse = %s""", self.name):
+ throw(_("Child warehouse exists for this warehouse. You can not delete this warehouse."))
+
+ self.update_nsm_model()
def before_rename(self, olddn, newdn, merge=False):
# Add company abbr if not provided
@@ -170,7 +177,7 @@
def get_children():
from erpnext.stock.utils import get_stock_value_on
ctype = frappe.local.form_dict.get('ctype')
- company = frappe.local.form_dict.get('comp')
+ company = frappe.local.form_dict.get('company')
parent_field = 'parent_' + ctype.lower().replace(' ', '_')
parent = frappe.form_dict.get("parent") or ""
@@ -194,6 +201,7 @@
@frappe.whitelist()
def add_node():
ctype = frappe.form_dict.get('ctype')
+ company = frappe.form_dict.get('company')
parent_field = 'parent_' + ctype.lower().replace(' ', '_')
name_field = ctype.lower().replace(' ', '_') + '_name'
@@ -207,7 +215,8 @@
doc.update({
name_field: frappe.form_dict['name_field'],
parent_field: parent,
- "is_group": frappe.form_dict['is_group']
+ "is_group": frappe.form_dict['is_group'],
+ "company": company
})
doc.save()
diff --git a/erpnext/stock/doctype/warehouse/warehouse_tree.js b/erpnext/stock/doctype/warehouse/warehouse_tree.js
index d23a536..0361493 100644
--- a/erpnext/stock/doctype/warehouse/warehouse_tree.js
+++ b/erpnext/stock/doctype/warehouse/warehouse_tree.js
@@ -4,7 +4,7 @@
get_tree_root: false,
root_label: "Warehouses",
filters: [{
- fieldname: "comp",
+ fieldname: "company",
fieldtype:"Select",
options: $.map(locals[':Company'], function(c) { return c.name; }).sort(),
label: __("Company"),
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 75200b3..696f2b0 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -71,9 +71,9 @@
conditions += " and item_code = '%s'" % frappe.db.escape(filters.get("item_code"), percent=False)
if filters.get("warehouse"):
- wh = frappe.get_doc("Warehouse", filters.get("warehouse"))
- conditions += "and warehouse in (\
- select name from `tabWarehouse` wh where wh.lft >= %s and wh.rgt <= %s)"%(wh.lft, wh.rgt)
+ lft, rgt = frappe.db.get_value("Warehouse", filters.get("warehouse"), ["lft", "rgt"])
+ conditions += " and exists (select name from `tabWarehouse` wh \
+ where wh.lft >= %s and wh.rgt <= %s and sle.warehouse = wh.name)"%(lft, rgt)
return conditions
@@ -81,9 +81,9 @@
conditions = get_conditions(filters)
return frappe.db.sql("""select item_code, warehouse, posting_date, actual_qty, valuation_rate,
company, voucher_type, qty_after_transaction, stock_value_difference
- from `tabStock Ledger Entry` force index (posting_sort_index)
+ from `tabStock Ledger Entry` sle force index (posting_sort_index)
where docstatus < 2 %s order by posting_date, posting_time, name""" %
- conditions, as_dict=1)
+ conditions, as_dict=1, debug=1)
def get_item_warehouse_map(filters):
iwb_map = {}
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index a65be6d..b2e4670 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -41,7 +41,7 @@
return frappe.db.sql("""select concat_ws(" ", posting_date, posting_time) as date,
item_code, warehouse, actual_qty, qty_after_transaction, incoming_rate, valuation_rate,
stock_value, voucher_type, voucher_no, batch_no, serial_no, company
- from `tabStock Ledger Entry`
+ from `tabStock Ledger Entry` sle
where company = %(company)s and
posting_date between %(from_date)s and %(to_date)s
{sle_conditions}
@@ -99,6 +99,8 @@
return row
def get_warehouse_condition(warehouse):
- wh = frappe.get_doc("Warehouse", warehouse)
- return " warehouse in (select name from `tabWarehouse` wh\
- where wh.lft >= %s and wh.rgt <= %s)"%(wh.lft, wh.rgt)
\ No newline at end of file
+ lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"])
+
+ return " exists (select name from `tabWarehouse` wh \
+ where wh.lft >= %s and wh.rgt <= %s and sle.warehouse = wh.name)"%(lft, rgt)
+
\ No newline at end of file
diff --git a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py
index 2fb120a..409833a 100644
--- a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py
+++ b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py
@@ -63,9 +63,10 @@
conditions.append("item_code = '%s' "%filters.item_code)
if filters.warehouse:
- wh = frappe.get_doc("Warehouse", filters.warehouse)
- conditions.append(" warehouse in (select name from `tabWarehouse` wh\
- where wh.lft >= %s and wh.rgt <= %s)"%(wh.lft, wh.rgt))
+ lft, rgt = frappe.db.get_value("Warehouse", filters.warehouse, ["lft", "rgt"])
+
+ conditions.append(" exists (select name from `tabWarehouse` wh \
+ where wh.lft >= %s and wh.rgt <= %s and sle.warehouse = wh.name)"%(lft, rgt))
bin_list = frappe.db.sql("""select item_code, warehouse, actual_qty, planned_qty, indented_qty,
ordered_qty, reserved_qty, reserved_qty_for_production, projected_qty
@@ -104,6 +105,4 @@
item["reorder_levels"] = reorder_levels.get(item.name) or []
item_map[item.name] = item
-
- frappe.errprint(item_map)
return item_map
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 6e56c5c..51d82a6 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -16,10 +16,10 @@
if warehouse:
- wh = frappe.get_doc("Warehouse", warehouse)
+ lft, rgt, is_group = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt", "is_group"])
- if wh.is_group == "Yes":
- values.extend([wh.lft, wh.rgt])
+ if is_group == "Yes":
+ values.extend([lft, rgt])
condition += "and exists (\
select name from `tabWarehouse` wh where wh.name = sle.warehouse\
and wh.lft >= %s and wh.rgt <= %s)"
@@ -188,8 +188,7 @@
frappe.throw(_("Warehouse {0} does not belong to company {1}").format(warehouse, company),
InvalidWarehouseCompany)
-def is_leaf_warehouse(warehouse):
- if frappe.db.get_value("Warehouse", warehouse, "is_group") == "No":
- return True
- return False
+def is_group_warehouse(warehouse):
+ if frappe.db.get_value("Warehouse", warehouse, "is_group") == "Yes":
+ frappe.throw(_("Group node warehouse is not allowed to select for transactions"))
\ No newline at end of file