From ea8fab52c6ec0a272b54e61f08bd089af3eab18f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 6 Feb 2017 17:13:39 +0530 Subject: [PATCH] Get standard/historical valuation rate where missing, if item is not a sample item --- .../purchase_invoice_item.json | 30 +++++++- .../sales_invoice_item.json | 30 +++++++- erpnext/controllers/stock_controller.py | 54 +++++++++---- .../delivery_note_item.json | 30 +++++++- .../purchase_receipt_item.json | 30 +++++++- .../stock_entry_detail.json | 77 ++++++++++++++++++- erpnext/stock/stock_ledger.py | 19 +++-- 7 files changed, 238 insertions(+), 32 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 6f8e219f88..eff5df5849 100755 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -1315,6 +1315,34 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "is_sample_item", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Is Sample Item", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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, @@ -1788,7 +1816,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-11-16 16:04:52.465169", + "modified": "2017-02-06 17:05:03.737297", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index 944230b1d0..c36f001e28 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -1381,6 +1381,34 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "is_sample_item", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Is Sample Item", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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, @@ -1882,7 +1910,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-11-16 16:04:02.438952", + "modified": "2017-02-06 17:01:16.812686", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 9a3d82ee91..6e3047c3e1 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -53,9 +53,15 @@ class StockController(AccountsController): self.check_expense_account(item_row) - if not sle.stock_value_difference: - self.update_stock_ledger_entries(sle) - self.validate_negative_stock(sle) + # If item is not a sample item + # and ( valuation rate not mentioned in an incoming entry + # or incoming entry not found while delivering the item), + # try to pick valuation rate from previous sle or Item master and update in SLE + # Otherwise, throw an exception + + if not sle.stock_value_difference and sle.voucher_type != "Stock Reconciliation" \ + and not item_row.get("is_sample_item"): + sle = self.update_stock_ledger_entries(sle) gl_list.append(self.get_gl_dict({ "account": warehouse_account[sle.warehouse]["name"], @@ -90,18 +96,23 @@ class StockController(AccountsController): def update_stock_ledger_entries(self, sle): sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse, sle.voucher_type, sle.voucher_no) + sle.stock_value = flt(sle.qty_after_transaction) * flt(sle.valuation_rate) - sle.stock_value_difference = sle.stock_value + sle.stock_value_difference = flt(sle.actual_qty) * flt(sle.valuation_rate) + if sle.name: - frappe.db.sql(""" update `tabStock Ledger Entry` set stock_value = %(stock_value)s, - valuation_rate = %(valuation_rate)s, stock_value_difference = %(stock_value_difference)s - where name = %(name)s""", (sle)) - - def validate_negative_stock(self, sle): - if sle.qty_after_transaction < 0 and sle.actual_qty < 0: - frappe.throw(_("Valuation rate not found for the Item {0}, which is required to do accounting entries (for booking expenses). Please create an incoming stock transaction or mention valuation rate in Item record, and then try submiting {1} {2}") - .format(sle.item_code, sle.voucher_type, sle.voucher_no)) - + frappe.db.sql(""" + update + `tabStock Ledger Entry` + set + stock_value = %(stock_value)s, + valuation_rate = %(valuation_rate)s, + stock_value_difference = %(stock_value_difference)s + where + name = %(name)s""", (sle)) + + return sle + def get_voucher_details(self, default_expense_account, default_cost_center, sle_map): if self.doctype == "Stock Reconciliation": return [frappe._dict({ "name": voucher_detail_no, "expense_account": default_expense_account, @@ -149,11 +160,20 @@ class StockController(AccountsController): def get_stock_ledger_details(self): stock_ledger = {} - for sle in frappe.db.sql("""select name, warehouse, stock_value_difference, - voucher_detail_no, item_code, posting_date, posting_time, actual_qty, qty_after_transaction - from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s""", - (self.doctype, self.name), as_dict=True): + stock_ledger_entries = frappe.db.sql(""" + select + name, warehouse, stock_value_difference, valuation_rate + voucher_detail_no, item_code, posting_date, posting_time, + actual_qty, qty_after_transaction, voucher_type, voucher_no + from + `tabStock Ledger Entry` + where + voucher_type=%s and voucher_no=%s + """, (self.doctype, self.name), as_dict=True) + + for sle in stock_ledger_entries: stock_ledger.setdefault(sle.voucher_detail_no, []).append(sle) + return stock_ledger def make_adjustment_entry(self, expected_gle, voucher_obj): diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json index e1ac06e113..9108edd7c0 100644 --- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json +++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -1476,6 +1476,34 @@ "unique": 0, "width": "120px" }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "is_sample_item", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Is Sample Item", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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, @@ -1691,7 +1719,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-12-24 12:33:37.728117", + "modified": "2017-02-06 17:00:24.354000", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note Item", diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index d8449f1ebb..43e2f3be78 100755 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -1574,6 +1574,34 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "is_sample_item", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Is Sample Item", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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, @@ -1885,7 +1913,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-11-16 16:04:21.778869", + "modified": "2017-02-06 17:04:23.305884", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json index ed1843e75d..fadaeb09fd 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json @@ -10,6 +10,7 @@ "doctype": "DocType", "document_type": "Other", "editable_grid": 1, + "engine": "InnoDB", "fields": [ { "allow_on_submit": 0, @@ -23,6 +24,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Barcode", "length": 0, "no_copy": 0, @@ -50,6 +52,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -76,6 +79,7 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 1, + "in_standard_filter": 0, "label": "Source Warehouse", "length": 0, "no_copy": 0, @@ -105,6 +109,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -130,6 +135,7 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 1, + "in_standard_filter": 0, "label": "Target Warehouse", "length": 0, "no_copy": 0, @@ -159,6 +165,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -184,6 +191,7 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 1, + "in_standard_filter": 0, "label": "Item Code", "length": 0, "no_copy": 0, @@ -213,6 +221,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -238,6 +247,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Item Name", "length": 0, "no_copy": 0, @@ -264,6 +274,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Description", "length": 0, "no_copy": 0, @@ -291,6 +302,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Description", "length": 0, "no_copy": 0, @@ -321,6 +333,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -347,6 +360,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Image", "length": 0, "no_copy": 0, @@ -374,6 +388,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Image View", "length": 0, "no_copy": 0, @@ -402,6 +417,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Quantity and Rate", "length": 0, "no_copy": 0, @@ -420,7 +436,7 @@ "allow_on_submit": 0, "bold": 1, "collapsible": 0, - "columns": 1, + "columns": 3, "fieldname": "qty", "fieldtype": "Float", "hidden": 0, @@ -428,6 +444,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Qty", "length": 0, "no_copy": 0, @@ -448,14 +465,15 @@ "allow_on_submit": 0, "bold": 1, "collapsible": 0, - "columns": 2, + "columns": 0, "fieldname": "basic_rate", "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_list_view": 1, + "in_list_view": 0, + "in_standard_filter": 0, "label": "Basic Rate (as per Stock UOM)", "length": 0, "no_copy": 0, @@ -485,6 +503,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Basic Amount", "length": 0, "no_copy": 0, @@ -513,6 +532,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Additional Cost", "length": 0, "no_copy": 0, @@ -541,6 +561,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Amount", "length": 0, "no_copy": 0, @@ -570,6 +591,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Valuation Rate", "length": 0, "no_copy": 0, @@ -598,6 +620,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -623,6 +646,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "UOM", "length": 0, "no_copy": 0, @@ -652,6 +676,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Conversion Factor", "length": 0, "no_copy": 0, @@ -680,6 +705,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Stock UOM", "length": 0, "no_copy": 0, @@ -709,6 +735,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Qty as per Stock UOM", "length": 0, "no_copy": 0, @@ -737,6 +764,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Serial No / Batch", "length": 0, "no_copy": 0, @@ -763,6 +791,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Serial No", "length": 0, "no_copy": 1, @@ -791,6 +820,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -816,6 +846,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Batch No", "length": 0, "no_copy": 0, @@ -845,6 +876,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Accounting", "length": 0, "no_copy": 0, @@ -872,6 +904,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Difference Account", "length": 0, "no_copy": 0, @@ -899,6 +932,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -926,6 +960,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Cost Center", "length": 0, "no_copy": 0, @@ -953,6 +988,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "More Information", "length": 0, "no_copy": 0, @@ -967,6 +1003,34 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "is_sample_item", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Is Sample Item", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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": 1, "bold": 0, @@ -979,6 +1043,7 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, + "in_standard_filter": 0, "label": "Actual Qty (at source/target)", "length": 0, "no_copy": 1, @@ -1008,6 +1073,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "BOM No", "length": 0, "no_copy": 0, @@ -1035,6 +1101,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -1061,6 +1128,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Material Request", "length": 0, "no_copy": 1, @@ -1088,6 +1156,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Material Request Item", "length": 0, "no_copy": 1, @@ -1114,7 +1183,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-11-27 15:19:26.597414", + "modified": "2017-02-06 17:08:06.841514", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry Detail", diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index a4cc512c9f..c387e0f05a 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -258,11 +258,17 @@ class update_entries_after(object): if not self.valuation_rate and actual_qty > 0: self.valuation_rate = sle.incoming_rate + + # Get valuation rate from previous SLE or Item master, if item is not a sample item + if not self.valuation_rate and sle.voucher_detail_no: + ref_item_dt = sle.voucher_type + " Detail" if sle.voucher_type == "Stock Entry" else " Item" + + is_sample_item = frappe.db.get_value(ref_item_dt, sle.voucher_detail_no, "is_sample_item") + + if not is_sample_item: + self.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse, + sle.voucher_type, sle.voucher_no, self.allow_zero_rate) - if not self.valuation_rate: - self.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse, - sle.voucher_type, sle.voucher_no, self.allow_zero_rate) - def get_fifo_values(self, sle): incoming_rate = flt(sle.incoming_rate) actual_qty = flt(sle.actual_qty) @@ -287,7 +293,7 @@ class update_entries_after(object): if not self.stock_queue: # Get valuation rate from last sle if exists or from valuation rate field in item master _rate = get_valuation_rate(sle.item_code, sle.warehouse, - sle.voucher_type, sle.voucher_no, self.allow_zero_rate) + sle.voucher_type, sle.voucher_no, self.allow_zero_rate) self.stock_queue.append([0, _rate]) index = None @@ -432,7 +438,6 @@ def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no, allow_zer if not allow_zero_rate and not valuation_rate \ and cint(frappe.db.get_value("Accounts Settings", None, "auto_accounting_for_stock")): - frappe.throw(_("Valuation rate not found for the Item {0}, which is required to do accounting entries (for booking expenses). Please create an incoming stock transaction or mention valuation rate in Item record, and then try submiting {1} {2}") - .format(item_code, voucher_type, voucher_no)) + frappe.throw(_("Valuation rate not found for the Item {0}, which is required to do accounting entries. If the item is transacting as a sample item in {1} {2}, please mention that in the {1} Item table. Otherwise, please create an incoming stock transaction for the item or mention valuation rate in the Item record, and then try submiting this entry").format(item_code, voucher_type, voucher_no)) return valuation_rate