From 3d6aecd6182b2341fa9df03a4f2887d8df6577a9 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 20 Jun 2016 17:25:45 +0530 Subject: [PATCH] [fixes] set warehouse group wise reorder level, validate ledger (leaf warehouse) on sle and bin --- erpnext/public/js/queries.js | 6 ++- erpnext/stock/doctype/bin/bin.py | 11 ++++- erpnext/stock/doctype/item/item.js | 22 ++++++++++ .../doctype/item_reorder/item_reorder.json | 43 ++++++++++++++++++- .../stock_ledger_entry/stock_ledger_entry.py | 6 +++ erpnext/stock/doctype/warehouse/warehouse.py | 12 ++++-- erpnext/stock/reorder_item.py | 21 ++++++--- erpnext/stock/utils.py | 6 +++ 8 files changed, 115 insertions(+), 12 deletions(-) diff --git a/erpnext/public/js/queries.js b/erpnext/public/js/queries.js index 12307fb9b3..acc0409038 100644 --- a/erpnext/public/js/queries.js +++ b/erpnext/public/js/queries.js @@ -71,7 +71,11 @@ $.extend(erpnext.queries, { warehouse: function(doc) { return { - filters: [["Warehouse", "company", "in", ["", cstr(doc.company)]]] + filters: [ + ["Warehouse", "company", "in", ["", cstr(doc.company)]], + ["Warehouse", "is_group", "=", "No"] + + ] } } }); diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index a1580d52f0..c03ceee69c 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import frappe +from frappe import _ from frappe.utils import flt, nowdate import frappe.defaults from frappe.model.document import Document @@ -15,13 +16,21 @@ class Bin(Document): self.validate_mandatory() self.projected_qty = flt(self.actual_qty) + flt(self.ordered_qty) + \ - flt(self.indented_qty) + flt(self.planned_qty) - flt(self.reserved_qty) + flt(self.indented_qty) + flt(self.planned_qty) - flt(self.reserved_qty) + + self.validate_leaf_warehouse() def validate_mandatory(self): qf = ['actual_qty', 'reserved_qty', 'ordered_qty', 'indented_qty'] for f in qf: 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 update_stock(self, args, allow_negative_stock=False, via_landed_cost_voucher=False): self.update_qty(args) diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index fe7e54e8e5..f35fa58508 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -160,6 +160,28 @@ $.extend(erpnext.item, { frm.fields_dict.supplier_items.grid.get_field("supplier").get_query = function(doc, cdt, cdn) { return { query: "erpnext.controllers.queries.supplier_query" } } + + frm.fields_dict['default_warehouse'].get_query = function(doc) { + return { + filters: { "is_group": "No" } + } + } + + frm.fields_dict.reorder_levels.grid.get_field("warehouse_group").get_query = function(doc, cdt, cdn) { + return { + filters: { "is_group": "Yes" } + } + } + + frm.fields_dict.reorder_levels.grid.get_field("warehouse").get_query = function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + return { + filters: { + "is_group": "No", + "parent_warehouse": d.warehouse_group + } + } + } }, diff --git a/erpnext/stock/doctype/item_reorder/item_reorder.json b/erpnext/stock/doctype/item_reorder/item_reorder.json index fea8bf039a..27a311d927 100644 --- a/erpnext/stock/doctype/item_reorder/item_reorder.json +++ b/erpnext/stock/doctype/item_reorder/item_reorder.json @@ -3,11 +3,39 @@ "allow_import": 0, "allow_rename": 0, "autoname": "hash", + "beta": 0, "creation": "2013-03-07 11:42:59", "custom": 0, "docstatus": 0, "doctype": "DocType", + "document_type": "Setup", "fields": [ + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "warehouse_group", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Warehouse Group", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -16,6 +44,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Warehouse", @@ -24,6 +53,7 @@ "options": "Warehouse", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -39,6 +69,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Re-order Level", @@ -46,6 +77,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -61,6 +93,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Re-order Qty", @@ -68,6 +101,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -83,6 +117,7 @@ "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Material Request Type", @@ -91,6 +126,7 @@ "options": "Purchase\nTransfer", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -102,18 +138,21 @@ "hide_heading": 0, "hide_toolbar": 0, "idx": 1, + "image_view": 0, "in_create": 1, "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2015-11-16 06:29:48.492627", + "modified": "2016-06-20 15:52:01.978593", "modified_by": "Administrator", "module": "Stock", "name": "Item Reorder", "owner": "Administrator", "permissions": [], + "quick_entry": 0, "read_only": 0, - "read_only_onload": 0 + "read_only_onload": 0, + "track_seen": 0 } \ No newline at end of file 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 9931ffa7a4..1f446d2be0 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -25,6 +25,7 @@ class StockLedgerEntry(Document): validate_warehouse_company(self.warehouse, self.company) self.scrub_posting_time() self.validate_and_set_fiscal_year() + self.validate_leaf_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) @@ -117,6 +118,11 @@ class StockLedgerEntry(Document): 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 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 1032fb0ed3..a0b7296056 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -196,12 +196,18 @@ 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) + + parent = frappe.form_dict['parent'] + + if cint(frappe.form_dict['is_root']): + parent = None + doc.update({ name_field: frappe.form_dict['name_field'], - parent_field: frappe.form_dict['parent'], + parent_field: parent, "is_group": frappe.form_dict['is_group'] }) - + doc.save() diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py index 45319131fa..ad810a997a 100644 --- a/erpnext/stock/reorder_item.py +++ b/erpnext/stock/reorder_item.py @@ -37,7 +37,7 @@ def _reorder_item(): item_warehouse_projected_qty = get_item_warehouse_projected_qty(items_to_consider) - def add_to_material_request(item_code, warehouse, reorder_level, reorder_qty, material_request_type): + def add_to_material_request(item_code, warehouse, reorder_level, reorder_qty, material_request_type, warehouse_group=None): if warehouse not in warehouse_company: # a disabled warehouse return @@ -46,7 +46,10 @@ def _reorder_item(): reorder_qty = flt(reorder_qty) # projected_qty will be 0 if Bin does not exist - projected_qty = flt(item_warehouse_projected_qty.get(item_code, {}).get(warehouse)) + if warehouse_group: + projected_qty = flt(item_warehouse_projected_qty.get(item_code, {}).get(warehouse_group)) + else: + projected_qty = flt(item_warehouse_projected_qty.get(item_code, {}).get(warehouse)) if (reorder_level or reorder_qty) and projected_qty < reorder_level: deficiency = reorder_level - projected_qty @@ -70,7 +73,7 @@ def _reorder_item(): if item.get("reorder_levels"): for d in item.get("reorder_levels"): add_to_material_request(item_code, d.warehouse, d.warehouse_reorder_level, - d.warehouse_reorder_qty, d.material_request_type) + d.warehouse_reorder_qty, d.material_request_type, warehouse_group=d.warehouse_group) if material_requests: return create_material_request(material_requests) @@ -82,9 +85,17 @@ def get_item_warehouse_projected_qty(items_to_consider): from tabBin where item_code in ({0}) and (warehouse != "" and warehouse is not null)"""\ .format(", ".join(["%s"] * len(items_to_consider))), items_to_consider): - + item_warehouse_projected_qty.setdefault(item_code, {})[warehouse] = flt(projected_qty) - + + warehouse_doc = frappe.get_doc("Warehouse", warehouse) + + if warehouse_doc.parent_warehouse: + if not item_warehouse_projected_qty.get(item_code, {}).get(warehouse_doc.parent_warehouse): + item_warehouse_projected_qty.setdefault(item_code, {})[warehouse_doc.parent_warehouse] = flt(projected_qty) + else: + item_warehouse_projected_qty[item_code][warehouse_doc.parent_warehouse] += flt(projected_qty) + return item_warehouse_projected_qty def create_material_request(material_requests): diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index af7dc588c1..6e56c5c7e7 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -187,3 +187,9 @@ def validate_warehouse_company(warehouse, company): if warehouse_company and warehouse_company != company: 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 + \ No newline at end of file