From 0f0b1216699e7ea279f1eb220e506172d95bc50c Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Tue, 23 May 2017 15:15:17 -0700 Subject: [PATCH 1/9] Added BOM UOM selection for items Added patch for BOM Item UOM Fixed scrap qty issue Added Scrap Qty update to patch Reverted test record for production order --- erpnext/controllers/buying_controller.py | 2 +- erpnext/manufacturing/doctype/bom/bom.js | 17 ++ erpnext/manufacturing/doctype/bom/bom.py | 39 ++- .../doctype/bom/test_records.json | 16 +- .../doctype/bom_item/bom_item.json | 260 +++++++++++++----- .../bom_replace_tool/bom_replace_tool.py | 2 +- .../bom_scrap_item/bom_scrap_item.json | 49 +++- .../production_planning_tool.py | 2 +- .../test_production_planning_tool.py | 26 +- .../production_order_stock_report.py | 2 +- erpnext/patches.txt | 3 +- .../update_stock_qty_value_in_bom_item.py | 10 + 12 files changed, 325 insertions(+), 103 deletions(-) create mode 100644 erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 5bc8bb38f8..3e35cdd471 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -252,7 +252,7 @@ class BuyingController(StockController): def get_items_from_bom(self, item_code, bom): bom_items = frappe.db.sql("""select t2.item_code, - t2.qty / ifnull(t1.quantity, 1) as qty_consumed_per_unit, + t2.stock_qty / ifnull(t1.quantity, 1) as qty_consumed_per_unit, t2.rate, t2.stock_uom, t2.name, t2.description from `tabBOM` t1, `tabBOM Item` t2, tabItem t3 where t2.parent = t1.name and t1.item = %s diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 576e46df50..42970803af 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -70,6 +70,15 @@ erpnext.bom.BomController = erpnext.TransactionController.extend({ get_bom_material_detail(doc, cdt, cdn, scrap_items); }, + conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) { + if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) { + var item = frappe.get_doc(cdt, cdn); + frappe.model.round_floats_in(item, ["qty", "conversion_factor"]); + item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item)); + refresh_field("stock_qty", item.name, item.parentfield); + this.toggle_conversion_factor(item); + } + }, }) $.extend(cur_frm.cscript, new erpnext.bom.BomController({frm: cur_frm})); @@ -296,6 +305,14 @@ frappe.ui.form.on("BOM Operation", "workstation", function(frm, cdt, cdn) { }) }); +frappe.ui.form.on("BOM Item", "qty", function(frm, cdt, cdn) { + var d = locals[cdt][cdn]; + + d.stock_qty = d.qty * d.conversion_factor + refresh_field("items"); + }); + + frappe.ui.form.on("BOM Operation", "operations_remove", function(frm) { erpnext.bom.calculate_op_cost(frm.doc); erpnext.bom.calculate_total(frm.doc); diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index b8a8ae8aea..5c45e5d5b6 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -7,6 +7,7 @@ from frappe.utils import cint, cstr, flt from frappe import _ from erpnext.setup.utils import get_exchange_rate from frappe.website.website_generator import WebsiteGenerator +from erpnext.stock.get_item_details import get_conversion_factor from operator import itemgetter @@ -48,7 +49,7 @@ class BOM(WebsiteGenerator): self.set_conversion_rate() from erpnext.utilities.transaction_base import validate_uom_is_integer - validate_uom_is_integer(self, "stock_uom", "qty", "BOM Item") + validate_uom_is_integer(self, "stock_uom", "stock_qty", "BOM Item") self.validate_materials() self.set_bom_material_details() @@ -60,6 +61,7 @@ class BOM(WebsiteGenerator): def on_update(self): self.check_recursion() + self.update_stock_qty() self.update_exploded_items() def on_submit(self): @@ -94,7 +96,7 @@ class BOM(WebsiteGenerator): def set_bom_material_details(self): for item in self.get("items"): ret = self.get_bom_material_detail({"item_code": item.item_code, "item_name": item.item_name, "bom_no": item.bom_no, - "qty": item.qty}) + "stock_qty": item.stock_qty}) for r in ret: if not item.get(r): item.set(r, ret[r]) @@ -122,6 +124,8 @@ class BOM(WebsiteGenerator): 'description' : item and args['description'] or '', 'image' : item and args['image'] or '', 'stock_uom' : item and args['stock_uom'] or '', + 'uom' : item and args['stock_uom'] or '', + 'conversion_factor' : 1, 'bom_no' : args['bom_no'], 'rate' : rate, 'base_rate' : rate if self.company_currency() == self.currency else rate * self.conversion_rate @@ -159,7 +163,7 @@ class BOM(WebsiteGenerator): for d in self.get("items"): rate = self.get_bom_material_detail({'item_code': d.item_code, 'bom_no': d.bom_no, - 'qty': d.qty})["rate"] + 'stock_qty': d.stock_qty})["rate"] if rate: d.rate = rate @@ -239,6 +243,19 @@ class BOM(WebsiteGenerator): frappe.db.get_value('Price List', self.buying_price_list, 'currency') != self.currency: frappe.throw(_("Currency of the price list {0} is not similar with the selected currency {1}").format(self.buying_price_list, self.currency)) + + def update_stock_qty(self): + for m in self.get('items'): + + if not m.conversion_factor: + m.conversion_factor = flt(get_conversion_factor(m.item_code, m.uom)['conversion_factor']) + if m.uom and m.qty: + m.stock_qty = flt(m.conversion_factor)*flt(m.qty) + if not m.uom and m.stock_uom: + m.uom = m.stock_uom + m.qty = m.stock_qty + + def set_conversion_rate(self): self.conversion_rate = get_exchange_rate(self.currency, self.company_currency()) @@ -250,7 +267,7 @@ class BOM(WebsiteGenerator): for m in self.get('items'): if m.bom_no: validate_bom_no(m.item_code, m.bom_no) - if flt(m.qty) <= 0: + if flt(m.stock_qty) <= 0: frappe.throw(_("Quantity required for Item {0} in row {1}").format(m.item_code, m.idx)) check_list.append(cstr(m.item_code)) unique_chk_list = set(check_list) @@ -336,9 +353,9 @@ class BOM(WebsiteGenerator): d.rate = self.get_bom_unitcost(d.bom_no) d.base_rate = flt(d.rate) * flt(self.conversion_rate) - d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.qty, self.precision("qty", d)) + d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.stock_qty, self.precision("stock_qty", d)) d.base_amount = d.amount * flt(self.conversion_rate) - d.qty_consumed_per_unit = flt(d.qty, self.precision("qty", d)) / flt(self.quantity, self.precision("quantity")) + d.qty_consumed_per_unit = flt(d.stock_qty, self.precision("stock_qty", d)) / flt(self.quantity, self.precision("quantity")) total_rm_cost += d.amount base_total_rm_cost += d.base_amount @@ -352,7 +369,7 @@ class BOM(WebsiteGenerator): for d in self.get('scrap_items'): d.base_rate = d.rate * self.conversion_rate - d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.qty, self.precision("qty", d)) + d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.stock_qty, self.precision("stock_qty", d)) d.base_amount = d.amount * self.conversion_rate total_sm_cost += d.amount base_total_sm_cost += d.base_amount @@ -370,7 +387,7 @@ class BOM(WebsiteGenerator): self.cur_exploded_items = {} for d in self.get('items'): if d.bom_no: - self.get_child_exploded_items(d.bom_no, d.qty) + self.get_child_exploded_items(d.bom_no, d.stock_qty) else: self.add_to_cur_exploded_items(frappe._dict({ 'item_code' : d.item_code, @@ -378,7 +395,7 @@ class BOM(WebsiteGenerator): 'description' : d.description, 'image' : d.image, 'stock_uom' : d.stock_uom, - 'qty' : flt(d.qty), + 'qty' : flt(d.stock_qty), 'rate' : d.base_rate, })) @@ -453,7 +470,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite query = """select bom_item.item_code, item.item_name, - sum(bom_item.qty/ifnull(bom.quantity, 1)) * %(qty)s as qty, + sum(bom_item.stock_qty/ifnull(bom.quantity, 1)) * %(qty)s as qty, item.description, item.image, item.stock_uom, @@ -521,7 +538,7 @@ def get_children(): return frappe.db.sql("""select bom_item.item_code, bom_item.bom_no as value, - bom_item.qty, + bom_item.stock_qty, if(ifnull(bom_item.bom_no, "")!="", 1, 0) as expandable, item.image, item.description diff --git a/erpnext/manufacturing/doctype/bom/test_records.json b/erpnext/manufacturing/doctype/bom/test_records.json index 5baa0cbf1d..0f1143ef7d 100644 --- a/erpnext/manufacturing/doctype/bom/test_records.json +++ b/erpnext/manufacturing/doctype/bom/test_records.json @@ -6,7 +6,7 @@ "doctype": "BOM Item", "item_code": "_Test Serialized Item With Series", "parentfield": "items", - "qty": 1.0, + "stock_qty": 1.0, "rate": 5000.0, "stock_uom": "_Test UOM" }, @@ -15,7 +15,7 @@ "doctype": "BOM Item", "item_code": "_Test Item 2", "parentfield": "items", - "qty": 2.0, + "stock_qty": 2.0, "rate": 1000.0, "stock_uom": "_Test UOM" } @@ -35,7 +35,7 @@ "doctype": "BOM Item", "item_code": "_Test Item Home Desktop 100", "parentfield": "items", - "qty": 1.0, + "stock_qty": 1.0, "rate": 2000.0, "stock_uom": "_Test UOM" } @@ -46,7 +46,7 @@ "doctype": "BOM Item", "item_code": "_Test Item", "parentfield": "items", - "qty": 1.0, + "stock_qty": 1.0, "rate": 5000.0, "stock_uom": "_Test UOM" }, @@ -55,7 +55,7 @@ "doctype": "BOM Item", "item_code": "_Test Item Home Desktop 100", "parentfield": "items", - "qty": 2.0, + "stock_qty": 2.0, "rate": 1000.0, "stock_uom": "_Test UOM" } @@ -84,7 +84,7 @@ "doctype": "BOM Item", "item_code": "_Test Item", "parentfield": "items", - "qty": 1.0, + "stock_qty": 1.0, "rate": 5000.0, "stock_uom": "_Test UOM" }, @@ -94,7 +94,7 @@ "doctype": "BOM Item", "item_code": "_Test Item Home Desktop Manufactured", "parentfield": "items", - "qty": 3.0, + "stock_qty": 3.0, "rate": 1000.0, "stock_uom": "_Test UOM" } @@ -124,7 +124,7 @@ "doctype": "BOM Item", "item_code": "_Test Item", "parentfield": "items", - "qty": 2.0, + "stock_qty": 2.0, "rate": 3000.0, "stock_uom": "_Test UOM" } diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json index 2fc29a883b..56af7a10d3 100644 --- a/erpnext/manufacturing/doctype/bom_item/bom_item.json +++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -11,6 +12,7 @@ "editable_grid": 1, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -20,7 +22,8 @@ "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, - "in_filter": 1, + "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Item Code", @@ -41,6 +44,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -51,6 +55,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Item Name", @@ -69,6 +74,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -79,6 +85,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -96,6 +103,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -105,7 +113,8 @@ "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, - "in_filter": 1, + "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "BOM No", @@ -128,6 +137,7 @@ "width": "150px" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -138,6 +148,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -155,6 +166,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -165,6 +177,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Item Description", @@ -186,6 +199,7 @@ "width": "250px" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -196,6 +210,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -212,6 +227,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -222,6 +238,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Image", @@ -240,6 +257,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -250,6 +268,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Image View", @@ -269,6 +288,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -279,6 +299,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Quantity and Rate", @@ -296,6 +317,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -306,6 +328,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Qty", @@ -319,16 +342,168 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 1, + "fieldname": "uom", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "UOM", + "length": 0, + "no_copy": 0, + "options": "UOM", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "col_break2", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "stock_qty", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Stock Qty", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, "reqd": 1, "search_index": 0, "set_only_once": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "columns": 2, + "columns": 0, + "fieldname": "conversion_factor", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Conversion Factor", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "stock_uom", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Stock UOM", + "length": 0, + "no_copy": 0, + "oldfieldname": "stock_uom", + "oldfieldtype": "Data", + "options": "UOM", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, "description": "See \"Rate Of Materials Based On\" in Costing Section", "fieldname": "rate", "fieldtype": "Currency", @@ -336,7 +511,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_list_view": 1, + "in_global_search": 0, + "in_list_view": 0, "in_standard_filter": 0, "label": "Rate", "length": 0, @@ -354,6 +530,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -364,6 +541,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Amount", @@ -386,62 +564,7 @@ "width": "150px" }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "col_break2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "stock_uom", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Stock UOM", - "length": 0, - "no_copy": 0, - "oldfieldname": "stock_uom", - "oldfieldtype": "Data", - "options": "UOM", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -452,6 +575,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Basic Rate (Company Currency)", @@ -471,6 +595,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -481,6 +606,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Amount (Company Currency)", @@ -500,6 +626,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -510,6 +637,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -527,6 +655,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -537,6 +666,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Scrap %", @@ -556,6 +686,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -566,6 +697,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Qty Consumed Per Unit", @@ -585,18 +717,18 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-12-20 12:54:34.859076", - "modified_by": "rmehta@gmail.com", + "modified": "2017-05-23 15:59:37.946963", + "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Item", "owner": "Administrator", @@ -604,7 +736,9 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", + "track_changes": 0, "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py b/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py index d4d5329ace..f0a834c37b 100644 --- a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py +++ b/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py @@ -33,7 +33,7 @@ class BOMReplaceTool(Document): from `tabBOM` where name = %s""", self.current_bom) current_bom_unitcost = current_bom_unitcost and flt(current_bom_unitcost[0][0]) or 0 frappe.db.sql("""update `tabBOM Item` set bom_no=%s, - rate=%s, amount=qty*%s where bom_no = %s and docstatus < 2""", + rate=%s, amount=stock_qty*%s where bom_no = %s and docstatus < 2""", (self.new_bom, current_bom_unitcost, current_bom_unitcost, self.current_bom)) def get_parent_boms(self): diff --git a/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json b/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json index fe81592769..e9aebfe39c 100644 --- a/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json +++ b/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -11,6 +12,7 @@ "editable_grid": 1, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -21,7 +23,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Item Code", "length": 0, "no_copy": 0, @@ -31,6 +35,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 0, @@ -38,6 +43,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -48,7 +54,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Item Name", "length": 0, "no_copy": 0, @@ -57,6 +65,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -64,6 +73,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -74,7 +84,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Quantity and Rate", "length": 0, "no_copy": 0, @@ -83,6 +95,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -90,17 +103,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "qty", + "fieldname": "stock_qty", "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Qty", "length": 0, "no_copy": 0, @@ -109,6 +125,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 0, @@ -116,6 +133,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -126,7 +144,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Rate", "length": 0, "no_copy": 0, @@ -136,6 +156,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -143,6 +164,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -153,7 +175,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Amount", "length": 0, "no_copy": 0, @@ -163,6 +187,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 1, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -170,6 +195,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -180,7 +206,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -188,6 +216,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -195,6 +224,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -205,7 +235,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Stock UOM", "length": 0, "no_copy": 0, @@ -215,6 +247,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 1, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -222,6 +255,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -232,7 +266,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Basic Rate (Company Currency)", "length": 0, "no_copy": 0, @@ -242,6 +278,7 @@ "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 1, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -249,6 +286,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -259,7 +297,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Basic Amount (Company Currency)", "length": 0, "no_copy": 0, @@ -269,6 +309,7 @@ "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 1, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -276,17 +317,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 0, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-10-25 00:27:53.712140", + "modified": "2017-05-23 16:04:32.442287", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Scrap Item", @@ -296,7 +337,9 @@ "quick_entry": 1, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", + "track_changes": 1, "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py index dd4b2b69ab..798e17486c 100644 --- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -348,7 +348,7 @@ class ProductionPlanningTool(Document): SELECT bom_item.item_code, default_material_request_type, - ifnull(%(parent_qty)s * sum(bom_item.qty/ifnull(bom.quantity, 1)), 0) as qty, + ifnull(%(parent_qty)s * sum(bom_item.stock_qty/ifnull(bom.quantity, 1)), 0) as qty, item.is_sub_contracted_item as is_sub_contracted, item.default_bom as default_bom, bom_item.description as description, diff --git a/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py index ea4da0cb94..f656b2c905 100644 --- a/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py +++ b/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py @@ -235,9 +235,9 @@ def create_test_records(): "is_active": 1, "is_default": 1, "docstatus": 1, - "with_operations": 0}, [{"item_code": "_Test PPT Item Raw B", "doctype":"BOM Item", "qty":1, + "with_operations": 0}, [{"item_code": "_Test PPT Item Raw B", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100, "stock_uom": "_Test UOM"}, - {"item_code": "_Test PPT Item Raw C", "doctype":"BOM Item", "qty":4, "rate":100, + {"item_code": "_Test PPT Item Raw C", "doctype":"BOM Item", "stock_qty":4, "rate":100, "amount": 400,"stock_uom": "_Test UOM"}]) bom_subC = make_bom("BOM-_Test PPT Item Sub C-001",{"quantity":1, @@ -247,9 +247,9 @@ def create_test_records(): "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Raw A","item_name": "_Test PPT Item Raw A", - "doctype":"BOM Item", "qty":6, "rate":100, "amount": 600}, + "doctype":"BOM Item", "stock_qty":6, "rate":100, "amount": 600}, {"item_code": "_Test PPT Item Sub B","item_name": "_Test PPT Item Sub B", - "bom_no":"BOM-_Test PPT Item Sub B-001", "doctype":"BOM Item", "qty":2, + "bom_no":"BOM-_Test PPT Item Sub B-001", "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}]) bom_sCA = make_bom("BOM-_Test PPT Item SC A-001",{"quantity":1, @@ -259,7 +259,7 @@ def create_test_records(): "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Raw D","item_name": "_Test PPT Item Raw D", - "doctype":"BOM Item", "qty":1, "rate":100, "amount": 100}]) + "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}]) bom_sCB = make_bom("BOM-_Test PPT Item SC B-001",{"quantity":1, "item": "_Test PPT Item SC B", @@ -268,9 +268,9 @@ def create_test_records(): "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Raw B","item_name": "_Test PPT Item Raw B", - "doctype":"BOM Item", "qty":1, "rate":100, "amount": 100}, + "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item Raw C","item_name": "_Test PPT Item Raw C", - "doctype":"BOM Item", "qty":4, "rate":100, "amount": 400}]) + "doctype":"BOM Item", "stock_qty":4, "rate":100, "amount": 400}]) bom_subA = make_bom("BOM-_Test PPT Item Sub A-001",{"quantity":1, "item": "_Test PPT Item Sub A", @@ -280,9 +280,9 @@ def create_test_records(): "with_operations": 0}, [ {"item_code": "_Test PPT Item Sub C","item_name": "_Test PPT Item Sub C", "bom_no":"BOM-_Test PPT Item Sub C-001", "doctype":"BOM Item", - "qty":1, "rate":100, "amount": 100}, + "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item SC B","item_name": "_Test PPT Item SC B", - "bom_no":"BOM-_Test PPT Item SC B-001", "doctype":"BOM Item", "qty":2, + "bom_no":"BOM-_Test PPT Item SC B-001", "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}]) bom_master = make_bom("BOM-_Test PPT Item Master-001",{"quantity":1, @@ -293,16 +293,16 @@ def create_test_records(): "with_operations": 0}, [ {"item_code": "_Test PPT Item Sub A","item_name": "_Test PPT Item Sub A", "bom_no":"BOM-_Test PPT Item Sub A-001", - "doctype":"BOM Item", "qty":2, "rate":100, "amount": 200}, + "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}, {"item_code": "_Test PPT Item Sub B","item_name": "_Test PPT Item Sub B", "bom_no":"BOM-_Test PPT Item Sub B-001", - "doctype":"BOM Item", "qty":1, "rate":100, "amount": 100}, + "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item Raw A","item_name": "_Test PPT Item Raw A", - "doctype":"BOM Item", "qty":2, "rate":100, + "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}, {"item_code": "_Test PPT Item SC A","item_name": "_Test PPT Item SC A", "bom_no":"BOM-_Test PPT Item SC A-001", - "doctype":"BOM Item", "qty":1, "rate":100, "amount": 100} + "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100} ]) diff --git a/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py b/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py index 6d586ddb22..bb79a49159 100644 --- a/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py +++ b/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py @@ -23,7 +23,7 @@ def get_item_list(prod_list, filters): item_list = frappe.db.sql("""SELECT bom_item.item_code as item_code, - ifnull(ledger.actual_qty*bom.quantity/bom_item.qty,0) as build_qty + ifnull(ledger.actual_qty*bom.quantity/bom_item.stock_qty,0) as build_qty FROM `tabBOM` as bom, `tabBOM Item` AS bom_item LEFT JOIN `tabBin` AS ledger diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 0faf98e688..5d2d2f0517 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -396,4 +396,5 @@ erpnext.patches.v8_0.merge_student_batch_and_student_group erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017 erpnext.patches.v8_0.fix_status_for_invoices_with_negative_outstanding erpnext.patches.v8_0.make_payments_table_blank_for_non_pos_invoice -erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note \ No newline at end of file +erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note +erpnext.patches.v8_0.update_stock_qty_value_in_bom_item \ No newline at end of file diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py new file mode 100644 index 0000000000..bc69815fa2 --- /dev/null +++ b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc('manufacturing', 'doctype', 'bom_item') + frappe.db.sql("update `tabBOM Item` set stock_qty = qty, uom = stock_uom") + frappe.db.sql("update `tabBOM Scrap Item` set stock_qty = qty") \ No newline at end of file From a3aa6a4449b6f2a2e9ae4bcc01e41301f7521cb2 Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Fri, 2 Jun 2017 16:54:03 -0700 Subject: [PATCH 2/9] Changed Explosion Item as well --- erpnext/manufacturing/doctype/bom/bom.py | 24 +++++++++---------- .../bom_explosion_item.json | 24 +++++++++++++++---- .../doctype/bom_item/bom_item.json | 2 ++ .../production_planning_tool.py | 2 +- .../update_stock_qty_value_in_bom_item.py | 1 + 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 5c45e5d5b6..ca4a9bc125 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -395,7 +395,7 @@ class BOM(WebsiteGenerator): 'description' : d.description, 'image' : d.image, 'stock_uom' : d.stock_uom, - 'qty' : flt(d.stock_qty), + 'stock_qty' : flt(d.stock_qty), 'rate' : d.base_rate, })) @@ -404,16 +404,16 @@ class BOM(WebsiteGenerator): def add_to_cur_exploded_items(self, args): if self.cur_exploded_items.get(args.item_code): - self.cur_exploded_items[args.item_code]["qty"] += args.qty + self.cur_exploded_items[args.item_code]["stock_qty"] += args.stock_qty else: self.cur_exploded_items[args.item_code] = args - def get_child_exploded_items(self, bom_no, qty): + def get_child_exploded_items(self, bom_no, stock_qty): """ Add all items from Flat BOM of child BOM""" # Did not use qty_consumed_per_unit in the query, as it leads to rounding loss child_fb_items = frappe.db.sql("""select bom_item.item_code, bom_item.item_name, bom_item.description, - bom_item.stock_uom, bom_item.qty, bom_item.rate, - bom_item.qty / ifnull(bom.quantity, 1) as qty_consumed_per_unit + bom_item.stock_uom, bom_item.stock_qty, bom_item.rate, + bom_item.stock_qty / ifnull(bom.quantity, 1) as qty_consumed_per_unit from `tabBOM Explosion Item` bom_item, tabBOM bom where bom_item.parent = bom.name and bom.name = %s and bom.docstatus = 1""", bom_no, as_dict = 1) @@ -423,7 +423,7 @@ class BOM(WebsiteGenerator): 'item_name' : d['item_name'], 'description' : d['description'], 'stock_uom' : d['stock_uom'], - 'qty' : d['qty_consumed_per_unit']*qty, + 'stock_qty' : d['qty_consumed_per_unit']*stock_qty, 'rate' : flt(d['rate']), })) @@ -435,8 +435,8 @@ class BOM(WebsiteGenerator): ch = self.append('exploded_items', {}) for i in self.cur_exploded_items[d].keys(): ch.set(i, self.cur_exploded_items[d][i]) - ch.amount = flt(ch.qty) * flt(ch.rate) - ch.qty_consumed_per_unit = flt(ch.qty) / flt(self.quantity) + ch.amount = flt(ch.stock_qty) * flt(ch.rate) + ch.qty_consumed_per_unit = flt(ch.stock_qty) / flt(self.quantity) ch.docstatus = self.docstatus ch.db_insert() @@ -480,13 +480,13 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite from `tab{table}` bom_item, `tabBOM` bom, `tabItem` item where - bom_item.parent = bom.name - and bom_item.docstatus < 2 - and bom_item.parent = %(bom)s + bom_item.docstatus < 2 + and bom.name = %(bom)s + and bom_item.parent = bom.name and item.name = bom_item.item_code and is_stock_item = 1 {conditions} - group by item_code, stock_uom""" + group by item_code, stock_uom""" if fetch_exploded: query = query.format(table="BOM Explosion Item", diff --git a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json index f075840806..e1a3d4da53 100644 --- a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json +++ b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "autoname": "hash", @@ -13,6 +14,7 @@ "engine": "InnoDB", "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -44,6 +46,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -72,6 +75,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -101,6 +105,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -129,6 +134,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -161,6 +167,7 @@ "width": "300px" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -189,6 +196,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -218,6 +226,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -248,6 +257,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -276,11 +286,12 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "qty", + "fieldname": "stock_qty", "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, @@ -289,7 +300,7 @@ "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, - "label": "Qty", + "label": "Stock Qty", "length": 0, "no_copy": 0, "oldfieldname": "qty", @@ -306,6 +317,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -337,6 +349,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -365,6 +378,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -393,6 +407,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -424,6 +439,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -455,17 +471,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-02-17 17:27:43.757983", + "modified": "2017-06-02 19:29:34.498719", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Explosion Item", diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json index 56af7a10d3..966b89bd4c 100644 --- a/erpnext/manufacturing/doctype/bom_item/bom_item.json +++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json @@ -424,6 +424,8 @@ "label": "Stock Qty", "length": 0, "no_copy": 0, + "oldfieldname": "stock_qty", + "oldfieldtype": "Currency", "permlevel": 0, "precision": "", "print_hide": 0, diff --git a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py index 798e17486c..050c3c1c33 100644 --- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -321,7 +321,7 @@ class ProductionPlanningTool(Document): # get all raw materials with sub assembly childs # Did not use qty_consumed_per_unit in the query, as it leads to rounding loss for d in frappe.db.sql("""select fb.item_code, - ifnull(sum(fb.qty/ifnull(bom.quantity, 1)), 0) as qty, + ifnull(sum(fb.stock_qty/ifnull(bom.quantity, 1)), 0) as qty, fb.description, fb.stock_uom, item.min_order_qty from `tabBOM Explosion Item` fb, `tabBOM` bom, `tabItem` item where bom.name = fb.parent and item.name = fb.item_code diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py index bc69815fa2..9d227877ce 100644 --- a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py +++ b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py @@ -7,4 +7,5 @@ import frappe def execute(): frappe.reload_doc('manufacturing', 'doctype', 'bom_item') frappe.db.sql("update `tabBOM Item` set stock_qty = qty, uom = stock_uom") + frappe.db.sql("update `tabBOM Explosion Item` set stock_qty = qty") frappe.db.sql("update `tabBOM Scrap Item` set stock_qty = qty") \ No newline at end of file From 70fe968f02f9d9c482862d921ff452142115f9ba Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Sun, 4 Jun 2017 20:19:59 -0700 Subject: [PATCH 3/9] Fixed some errors --- .../doctype/production_order/test_production_order.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.py b/erpnext/manufacturing/doctype/production_order/test_production_order.py index 40e839323c..c736ae2555 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.py +++ b/erpnext/manufacturing/doctype/production_order/test_production_order.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import unittest import frappe +from pprint import pprint from frappe.utils import flt, time_diff_in_hours, now, add_days, cint from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory from erpnext.manufacturing.doctype.production_order.production_order \ @@ -266,9 +267,9 @@ class TestProductionOrder(unittest.TestCase): def get_scrap_item_details(bom_no): scrap_items = {} - for item in frappe.db.sql("""select item_code, qty from `tabBOM Scrap Item` + for item in frappe.db.sql("""select item_code, stock_qty from `tabBOM Scrap Item` where parent = %s""", bom_no, as_dict=1): - scrap_items[item.item_code] = item.qty + scrap_items[item.item_code] = item.stock_qty return scrap_items @@ -287,8 +288,7 @@ def make_prod_order_test_record(**args): pro_order.stock_uom = args.stock_uom or "_Test UOM" pro_order.use_multi_level_bom=0 pro_order.set_production_order_operations() - - + if args.source_warehouse: pro_order.source_warehouse = args.source_warehouse @@ -297,6 +297,7 @@ def make_prod_order_test_record(**args): if not args.do_not_save: pro_order.insert() + if not args.do_not_submit: pro_order.submit() return pro_order From a35839aa4798d04cfcb0105cdcc59279c916de90 Mon Sep 17 00:00:00 2001 From: bcornwellmott Date: Fri, 9 Jun 2017 07:36:15 -0700 Subject: [PATCH 4/9] Removing unused pprint --- .../doctype/production_order/test_production_order.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.py b/erpnext/manufacturing/doctype/production_order/test_production_order.py index c736ae2555..cdadba4825 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.py +++ b/erpnext/manufacturing/doctype/production_order/test_production_order.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals import unittest import frappe -from pprint import pprint from frappe.utils import flt, time_diff_in_hours, now, add_days, cint from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory from erpnext.manufacturing.doctype.production_order.production_order \ From fed9816213f2237590e04ee6f22ff6c0beb1bedb Mon Sep 17 00:00:00 2001 From: bcornwellmott Date: Fri, 9 Jun 2017 07:37:27 -0700 Subject: [PATCH 5/9] Removed trailing whitespace --- .../test_production_planning_tool.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py index f656b2c905..4f80b6a626 100644 --- a/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py +++ b/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py @@ -235,9 +235,9 @@ def create_test_records(): "is_active": 1, "is_default": 1, "docstatus": 1, - "with_operations": 0}, [{"item_code": "_Test PPT Item Raw B", "doctype":"BOM Item", "stock_qty":1, + "with_operations": 0}, [{"item_code": "_Test PPT Item Raw B", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100, "stock_uom": "_Test UOM"}, - {"item_code": "_Test PPT Item Raw C", "doctype":"BOM Item", "stock_qty":4, "rate":100, + {"item_code": "_Test PPT Item Raw C", "doctype":"BOM Item", "stock_qty":4, "rate":100, "amount": 400,"stock_uom": "_Test UOM"}]) bom_subC = make_bom("BOM-_Test PPT Item Sub C-001",{"quantity":1, @@ -249,7 +249,7 @@ def create_test_records(): {"item_code": "_Test PPT Item Raw A","item_name": "_Test PPT Item Raw A", "doctype":"BOM Item", "stock_qty":6, "rate":100, "amount": 600}, {"item_code": "_Test PPT Item Sub B","item_name": "_Test PPT Item Sub B", - "bom_no":"BOM-_Test PPT Item Sub B-001", "doctype":"BOM Item", "stock_qty":2, + "bom_no":"BOM-_Test PPT Item Sub B-001", "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}]) bom_sCA = make_bom("BOM-_Test PPT Item SC A-001",{"quantity":1, @@ -278,11 +278,11 @@ def create_test_records(): "is_default": 1, "docstatus": 1, "with_operations": 0}, [ - {"item_code": "_Test PPT Item Sub C","item_name": "_Test PPT Item Sub C", + {"item_code": "_Test PPT Item Sub C","item_name": "_Test PPT Item Sub C", "bom_no":"BOM-_Test PPT Item Sub C-001", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item SC B","item_name": "_Test PPT Item SC B", - "bom_no":"BOM-_Test PPT Item SC B-001", "doctype":"BOM Item", "stock_qty":2, + "bom_no":"BOM-_Test PPT Item SC B-001", "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}]) bom_master = make_bom("BOM-_Test PPT Item Master-001",{"quantity":1, @@ -298,7 +298,7 @@ def create_test_records(): "bom_no":"BOM-_Test PPT Item Sub B-001", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item Raw A","item_name": "_Test PPT Item Raw A", - "doctype":"BOM Item", "stock_qty":2, "rate":100, + "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}, {"item_code": "_Test PPT Item SC A","item_name": "_Test PPT Item SC A", "bom_no":"BOM-_Test PPT Item SC A-001", @@ -388,4 +388,4 @@ def get_requested_types(item_code): where item.item_code = %(item_code)s and item.parent = mat_req.name""", {"item_code":item_code}, as_dict=1): types.append(d.type) return types - \ No newline at end of file + From 70554465089dd6cbd904062f4264de7d33a662b8 Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Thu, 15 Jun 2017 08:52:55 -0700 Subject: [PATCH 6/9] Reload explosion and scrap items docs --- erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py index 9d227877ce..c872177e1f 100644 --- a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py +++ b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py @@ -6,6 +6,8 @@ import frappe def execute(): frappe.reload_doc('manufacturing', 'doctype', 'bom_item') + frappe.reload_doc('manufacturing', 'doctype', 'bom_explosion_item') + frappe.reload_doc('manufacturing', 'doctype', 'bom_scrap_item') frappe.db.sql("update `tabBOM Item` set stock_qty = qty, uom = stock_uom") frappe.db.sql("update `tabBOM Explosion Item` set stock_qty = qty") frappe.db.sql("update `tabBOM Scrap Item` set stock_qty = qty") \ No newline at end of file From 2c77165fc61a885b15bbff37756fbcaf1e9c2426 Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Fri, 16 Jun 2017 13:47:40 -0700 Subject: [PATCH 7/9] Fixed small code issues (codecy) --- erpnext/manufacturing/doctype/bom/bom.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index a6703907b2..d3c3379850 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -5,7 +5,7 @@ frappe.provide("erpnext.bom"); frappe.ui.form.on("BOM", { setup: function(frm) { - frm.add_fetch('buying_price_list', 'currency', 'currency') + frm.add_fetch('buying_price_list', 'currency', 'currency'); frm.fields_dict["items"].grid.get_field("bom_no").get_query = function(doc, cdt, cdn){ return { filters: {'currency': frm.doc.currency} @@ -306,11 +306,10 @@ frappe.ui.form.on("BOM Operation", "workstation", function(frm, cdt, cdn) { }); frappe.ui.form.on("BOM Item", "qty", function(frm, cdt, cdn) { - var d = locals[cdt][cdn]; - - d.stock_qty = d.qty * d.conversion_factor - refresh_field("items"); - }); + var d = locals[cdt][cdn]; + d.stock_qty = d.qty * d.conversion_factor; + refresh_field("items"); +}); frappe.ui.form.on("BOM Operation", "operations_remove", function(frm) { From 1e96b7bbe55579dcd5973eaf63490c13139c974e Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Wed, 21 Jun 2017 10:16:50 -0700 Subject: [PATCH 8/9] Added conversion_factor update in patch --- erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py index c872177e1f..9e95eb0c23 100644 --- a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py +++ b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py @@ -8,6 +8,6 @@ def execute(): frappe.reload_doc('manufacturing', 'doctype', 'bom_item') frappe.reload_doc('manufacturing', 'doctype', 'bom_explosion_item') frappe.reload_doc('manufacturing', 'doctype', 'bom_scrap_item') - frappe.db.sql("update `tabBOM Item` set stock_qty = qty, uom = stock_uom") + frappe.db.sql("update `tabBOM Item` set stock_qty = qty, uom = stock_uom, conversion_factor = 1") frappe.db.sql("update `tabBOM Explosion Item` set stock_qty = qty") frappe.db.sql("update `tabBOM Scrap Item` set stock_qty = qty") \ No newline at end of file From 5b7028c7bb167e4cf83ae3054ea28af9ef1e0187 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 28 Jun 2017 15:35:53 +0530 Subject: [PATCH 9/9] stock qty not changed if item change --- erpnext/manufacturing/doctype/bom/bom.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 0f9fe8b8ad..41eec8d933 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -128,6 +128,7 @@ class BOM(WebsiteGenerator): 'conversion_factor' : 1, 'bom_no' : args['bom_no'], 'rate' : rate, + 'stock_qty' : args.get("qty") or args.get("stock_qty") or 1, 'base_rate' : rate if self.company_currency() == self.currency else rate * self.conversion_rate } return ret_item