From fe2afc643e37c0502599e1690e52851589ae4fc9 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 6 Jan 2020 11:51:43 +0530 Subject: [PATCH] fix: incorrect valuation rate for finished good entry (#20165) --- .../stock/doctype/stock_entry/stock_entry.py | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 01d54deadf..1c9d4c0cdf 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -103,9 +103,8 @@ class StockEntry(StockController): if self.work_order and self.purpose == "Material Consumption for Manufacture": self.validate_work_order_status() - else: - self.update_work_order() + self.update_work_order() self.update_stock_ledger() self.make_gl_entries_on_cancel() self.update_cost_in_project() @@ -479,10 +478,16 @@ class StockEntry(StockController): def set_basic_rate_for_finished_goods(self, raw_material_cost, scrap_material_cost): if self.purpose in ["Manufacture", "Repack"]: for d in self.get("items"): - if d.transfer_qty and (d.bom_no or d.t_warehouse) and (getattr(self, "pro_doc", frappe._dict()).scrap_warehouse != d.t_warehouse): + if (d.transfer_qty and (d.bom_no or d.t_warehouse) and raw_material_cost + and (getattr(self, "pro_doc", frappe._dict()).scrap_warehouse != d.t_warehouse)): d.basic_rate = flt((raw_material_cost - scrap_material_cost) / flt(d.transfer_qty), d.precision("basic_rate")) d.basic_amount = flt((raw_material_cost - scrap_material_cost), d.precision("basic_amount")) + if (not d.basic_rate and self.work_order and + frappe.db.get_single_value("Manufacturing Settings", "material_consumption")): + d.basic_rate = get_valuation_rate_for_finished_good_entry(self.work_order) or 0 + d.basic_amount = d.basic_rate * d.qty + def distribute_additional_costs(self): if self.purpose == "Material Issue": self.additional_costs = [] @@ -833,7 +838,6 @@ class StockEntry(StockController): (self.purpose == "Manufacture" or self.purpose == "Material Consumption for Manufacture") and frappe.db.get_single_value("Manufacturing Settings", "material_consumption")== 1): self.get_unconsumed_raw_materials() - else: if not self.fg_completed_qty: frappe.throw(_("Manufacturing Quantity is mandatory")) @@ -1152,20 +1156,17 @@ class StockEntry(StockController): se_child.s_warehouse = item_dict[d].get("from_warehouse") se_child.t_warehouse = item_dict[d].get("to_warehouse") se_child.item_code = item_dict[d].get('item_code') or cstr(d) - se_child.item_name = item_dict[d]["item_name"] - se_child.description = item_dict[d]["description"] se_child.uom = item_dict[d]["uom"] if item_dict[d].get("uom") else stock_uom se_child.stock_uom = stock_uom se_child.qty = flt(item_dict[d]["qty"], se_child.precision("qty")) - se_child.expense_account = item_dict[d].get("expense_account") se_child.cost_center = item_dict[d].get("cost_center") or cost_center se_child.allow_alternative_item = item_dict[d].get("allow_alternative_item", 0) se_child.subcontracted_item = item_dict[d].get("main_item_code") - se_child.original_item = item_dict[d].get("original_item") - se_child.po_detail = item_dict[d].get("po_detail") - if item_dict[d].get("idx"): - se_child.idx = item_dict[d].get("idx") + for field in ["idx", "po_detail", "original_item", + "expense_account", "description", "item_name"]: + if item_dict[d].get(field): + se_child.set(field, item_dict[d].get(field)) if se_child.s_warehouse==None: se_child.s_warehouse = self.from_warehouse @@ -1470,6 +1471,24 @@ def get_used_alternative_items(purchase_order=None, work_order=None): return used_alternative_items +def get_valuation_rate_for_finished_good_entry(work_order): + work_order_qty = flt(frappe.get_cached_value("Work Order", + work_order, 'material_transferred_for_manufacturing')) + + field = "(SUM(total_outgoing_value) / %s) as valuation_rate" % (work_order_qty) + + stock_data = frappe.get_all("Stock Entry", + fields = field, + filters = { + "docstatus": 1, + "purpose": "Material Transfer for Manufacture", + "work_order": work_order + } + ) + + if stock_data: + return stock_data[0].valuation_rate + @frappe.whitelist() def get_uom_details(item_code, uom, qty): """Returns dict `{"conversion_factor": [value], "transfer_qty": qty * [value]}`