From 2a21bc9fc209d578283c4d8d6e2e4676a88c82da Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 25 Feb 2015 15:08:42 +0530 Subject: [PATCH] [taxes and charges] refactor --- .../purchase_taxes_and_charges_master.js | 2 + .../doctype/sales_invoice/sales_invoice.js | 4 +- .../sales_taxes_and_charges.json | 4 +- .../sales_taxes_and_charges_master.js | 9 +- .../sales_taxes_and_charges_master.py | 1 + erpnext/controllers/accounts_controller.py | 9 + erpnext/patches.txt | 1 + erpnext/public/js/controllers/accounts.js | 76 +++++--- erpnext/public/js/utils.js | 10 +- .../doctype/delivery_note/delivery_note.js | 2 +- .../stock/doctype/stock_entry/stock_entry.js | 2 +- .../doctype/stock_entry/stock_entry.json | 179 ++++++++++-------- .../stock/doctype/stock_entry/stock_entry.py | 21 +- .../stock_reconciliation.py | 13 +- erpnext/stock/stock_ledger.py | 16 +- 15 files changed, 213 insertions(+), 136 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js b/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js index 09f2e8def8..f53581ab4e 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js @@ -1,6 +1,8 @@ // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt +cur_frm.cscript.tax_table = "Purchase Taxes and Charges"; + {% include "public/js/controllers/accounts.js" %} frappe.ui.form.on("Purchase Taxes and Charges", "add_deduct_tax", function(doc, cdt, cdn) { diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 4670303e2e..220e171d8e 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -199,8 +199,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte this.hide_fields(this.frm.doc); }, - items_on_form_rendered: function(doc, grid_row) { - erpnext.setup_serial_no(grid_row) + items_on_form_rendered: function() { + erpnext.setup_serial_no(); } }); diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json index 23225505e9..67f7ab4893 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json +++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json @@ -56,7 +56,7 @@ "oldfieldname": "rate", "oldfieldtype": "Currency", "permlevel": 0, - "reqd": 1 + "reqd": 0 }, { "fieldname": "col_break_1", @@ -186,7 +186,7 @@ "hide_heading": 1, "idx": 1, "istable": 1, - "modified": "2015-02-23 12:36:02.213508", + "modified": "2015-02-25 02:50:44.152307", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Taxes and Charges", diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js index b5dc38f803..3ad573a518 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js @@ -1,9 +1,10 @@ // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt +cur_frm.cscript.tax_table = "Sales Taxes and Charges"; + {% include "public/js/controllers/accounts.js" %} -cur_frm.cscript.onload = function(doc, cdt, cdn) { - if(doc.doctype === "Sales Taxes and Charges Master") - erpnext.add_applicable_territory(); -} +frappe.ui.form.on("Sales Taxes and Charges Master", "onload", function(frm) { + erpnext.add_applicable_territory(); +}); diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py index 4317f2ab8c..907c7c65e0 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py @@ -20,3 +20,4 @@ class SalesTaxesandChargesMaster(Document): validate_taxes_and_charges(tax) validate_inclusive_tax(tax, self) + diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index bbab88fe16..fd17fd6931 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -370,6 +370,15 @@ def validate_taxes_and_charges(tax): elif tax.row_id and cint(tax.row_id) >= cint(tax.idx): frappe.throw(_("Cannot refer row number greater than or equal to current row number for this Charge type")) + if tax.charge_type == "Actual": + if not tax.tax_amount: + frappe.throw(_("Amount is mandatory for charge type 'Actual'")) + tax.rate = None + else: + if not tax.rate: + frappe.throw(_("Rate is mandatory for charge type '{0}'").format(tax.charge_type)) + tax.tax_amount = None + def validate_inclusive_tax(tax, doc): def _on_previous_row_error(row_range): throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx, diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 1a88177ecf..b3745e7ce5 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -126,3 +126,4 @@ erpnext.patches.v5_0.item_patches erpnext.patches.v5_0.update_journal_entry_title erpnext.patches.v5_0.taxes_and_totals_in_party_currency erpnext.patches.v5_0.replace_renamed_fields_in_custom_scripts_and_print_formats +execute:frappe.db.sql("update `tabStock Entry` set from_bom = if(ifnull(bom_no, '')='', 0, 1)") diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js index 35d8c6698b..283ec74b53 100644 --- a/erpnext/public/js/controllers/accounts.js +++ b/erpnext/public/js/controllers/accounts.js @@ -2,6 +2,10 @@ // License: GNU General Public License v3. See license.txt // get tax rate +frappe.provide("erpnext.taxes"); +frappe.provide("erpnext.taxes.flags"); + + cur_frm.cscript.account_head = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.account_head){ @@ -82,34 +86,60 @@ cur_frm.cscript.validate_inclusive_tax = function(tax) { } } -frappe.ui.form.on(cur_frm.cscript.tax_table, "row_id", function(frm, cdt, cdn) { - cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); -}); +if(!erpnext.taxes.flags[cur_frm.cscript.tax_table]) { + erpnext.taxes.flags[cur_frm.cscript.tax_table] = true; -frappe.ui.form.on(cur_frm.cscript.tax_table, "rate", function(frm, cdt, cdn) { - cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); -}); - -frappe.ui.form.on(cur_frm.cscript.tax_table, "tax_amount", function(frm, cdt, cdn) { - cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); -}); - -frappe.ui.form.on(cur_frm.cscript.tax_table, "charge_type", function(frm, cdt, cdn) { - cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); -}); - -frappe.ui.form.on(cur_frm.cscript.tax_table, "included_in_print_rate", function(frm, cdt, cdn) { - var tax = frappe.get_doc(cdt, cdn); - try { + frappe.ui.form.on(cur_frm.cscript.tax_table, "row_id", function(frm, cdt, cdn) { cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); - cur_frm.cscript.validate_inclusive_tax(tax); - } catch(e) { - tax.included_in_print_rate = 0; - refresh_field("included_in_print_rate", tax.name, tax.parentfield); - throw e; + }); + + frappe.ui.form.on(cur_frm.cscript.tax_table, "rate", function(frm, cdt, cdn) { + cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); + }); + + frappe.ui.form.on(cur_frm.cscript.tax_table, "tax_amount", function(frm, cdt, cdn) { + cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); + }); + + frappe.ui.form.on(cur_frm.cscript.tax_table, "charge_type", function(frm, cdt, cdn) { + cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); + erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm); + }); + + frappe.ui.form.on(cur_frm.cscript.tax_table, "included_in_print_rate", function(frm, cdt, cdn) { + var tax = frappe.get_doc(cdt, cdn); + try { + cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); + cur_frm.cscript.validate_inclusive_tax(tax); + } catch(e) { + tax.included_in_print_rate = 0; + refresh_field("included_in_print_rate", tax.name, tax.parentfield); + throw e; + } + }); +} + +erpnext.taxes.set_conditional_mandatory_rate_or_amount = function(frm) { + var grid_row = frm.open_grid_row(); + if(grid_row.doc.charge_type==="Actual") { + grid_row.toggle_display("tax_amount", true); + grid_row.toggle_reqd("tax_amount", true); + grid_row.toggle_display("rate", false); + grid_row.toggle_reqd("rate", false); + } else { + grid_row.toggle_display("rate", true); + grid_row.toggle_reqd("rate", true); + grid_row.toggle_display("tax_amount", false); + grid_row.toggle_reqd("tax_amount", false); } +} + +// setup conditional mandatory for tax and rates +frappe.ui.form.on(cur_frm.doctype, "taxes_on_form_rendered", function(frm) { + erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm); }); + cur_frm.set_query("account_head", "taxes", function(doc) { if(cur_frm.cscript.tax_table == "Sales Taxes and Charges") { var account_type = ["Tax", "Chargeable", "Expense Account"]; diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 67d8eaa013..0d97a94ce7 100644 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -57,13 +57,15 @@ $.extend(erpnext, { } }, - setup_serial_no: function(grid_row) { + setup_serial_no: function() { + var grid_row = cur_frm.open_grid_row(); + if(!grid_row.fields_dict.serial_no || grid_row.fields_dict.serial_no.get_status()!=="Write") return; var $btn = $('') .appendTo($("
") - .css({"margin-bottom": "10px", "margin-left": "15px"}) + .css({"margin-bottom": "10px", "margin-top": "10px"}) .appendTo(grid_row.fields_dict.serial_no.$wrapper)); $btn.on("click", function() { @@ -99,7 +101,7 @@ $.extend(erpnext, { d.show(); }); }, - + get_letter_head: function(company) { frappe.call({ type:"GET", @@ -112,7 +114,7 @@ $.extend(erpnext, { } }); }, - + }); diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index 185c242eda..1c68339ded 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -79,7 +79,7 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend( }, items_on_form_rendered: function(doc, grid_row) { - erpnext.setup_serial_no(grid_row) + erpnext.setup_serial_no(); } }); diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 8795524c82..716b4a837b 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -274,7 +274,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ }, items_on_form_rendered: function(doc, grid_row) { - erpnext.setup_serial_no(grid_row) + erpnext.setup_serial_no(); }, customer: function() { diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json index db407084e8..5b1cce01b6 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.json +++ b/erpnext/stock/doctype/stock_entry/stock_entry.json @@ -7,6 +7,14 @@ "docstatus": 0, "doctype": "DocType", "fields": [ + { + "fieldname": "items_section", + "fieldtype": "Section Break", + "label": "", + "oldfieldtype": "Section Break", + "permlevel": 0, + "read_only": 0 + }, { "fieldname": "col1", "fieldtype": "Column Break", @@ -73,15 +81,6 @@ "reqd": 0, "search_index": 1 }, - { - "depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)", - "fieldname": "bom_no", - "fieldtype": "Link", - "label": "BOM No", - "options": "BOM", - "permlevel": 0, - "read_only": 0 - }, { "allow_on_submit": 0, "depends_on": "eval:doc.purpose==\"Sales Return\"", @@ -132,6 +131,13 @@ "reqd": 0, "search_index": 1 }, + { + "fieldname": "from_bom", + "fieldtype": "Check", + "label": "From BOM", + "permlevel": 0, + "precision": "" + }, { "fieldname": "col2", "fieldtype": "Column Break", @@ -178,13 +184,91 @@ "search_index": 0 }, { - "fieldname": "items_section", + "depends_on": "eval: doc.from_bom && (doc.purpose!==\"Sales Return\" && doc.purpose!==\"Purchase Return\")", + "fieldname": "sb1", "fieldtype": "Section Break", "label": "", - "oldfieldtype": "Section Break", "permlevel": 0, "read_only": 0 }, + { + "depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)", + "fieldname": "bom_no", + "fieldtype": "Link", + "label": "BOM No", + "options": "BOM", + "permlevel": 0, + "read_only": 0 + }, + { + "depends_on": "eval:inList([\"Manufacture\", \"Repack\"], doc.purpose)", + "fieldname": "additional_operating_cost", + "fieldtype": "Currency", + "label": "Additional Operating Cost", + "no_copy": 1, + "options": "Company:company:default_currency", + "permlevel": 0, + "read_only": 0 + }, + { + "fieldname": "cb1", + "fieldtype": "Column Break", + "permlevel": 0, + "read_only": 0 + }, + { + "allow_on_submit": 0, + "depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)", + "description": "As per Stock UOM", + "fieldname": "fg_completed_qty", + "fieldtype": "Float", + "hidden": 0, + "in_filter": 0, + "label": "Manufacturing Quantity", + "no_copy": 0, + "oldfieldname": "fg_completed_qty", + "oldfieldtype": "Currency", + "permlevel": 0, + "print_hide": 1, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0 + }, + { + "default": "1", + "depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)", + "description": "Including items for sub assemblies", + "fieldname": "use_multi_level_bom", + "fieldtype": "Check", + "label": "Use Multi-Level BOM", + "permlevel": 0, + "print_hide": 1, + "read_only": 0 + }, + { + "allow_on_submit": 0, + "depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)", + "fieldname": "get_items", + "fieldtype": "Button", + "hidden": 0, + "in_filter": 0, + "label": "Get Items", + "no_copy": 0, + "oldfieldtype": "Button", + "permlevel": 0, + "print_hide": 1, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0 + }, + { + "fieldname": "section_break_12", + "fieldtype": "Section Break", + "permlevel": 0, + "precision": "" + }, { "allow_on_submit": 0, "fieldname": "from_warehouse", @@ -301,77 +385,6 @@ "precision": "", "read_only": 1 }, - { - "depends_on": "eval:(doc.purpose!==\"Sales Return\" && doc.purpose!==\"Purchase Return\")", - "fieldname": "sb1", - "fieldtype": "Section Break", - "label": "From Bill of Materials", - "permlevel": 0, - "read_only": 0 - }, - { - "allow_on_submit": 0, - "depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)", - "description": "As per Stock UOM", - "fieldname": "fg_completed_qty", - "fieldtype": "Float", - "hidden": 0, - "in_filter": 0, - "label": "Manufacturing Quantity", - "no_copy": 0, - "oldfieldname": "fg_completed_qty", - "oldfieldtype": "Currency", - "permlevel": 0, - "print_hide": 1, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0 - }, - { - "depends_on": "eval:inList([\"Manufacture\", \"Repack\"], doc.purpose)", - "fieldname": "additional_operating_cost", - "fieldtype": "Currency", - "label": "Additional Operating Cost", - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "read_only": 0 - }, - { - "fieldname": "cb1", - "fieldtype": "Column Break", - "permlevel": 0, - "read_only": 0 - }, - { - "default": "1", - "depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)", - "description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.", - "fieldname": "use_multi_level_bom", - "fieldtype": "Check", - "label": "Use Multi-Level BOM", - "permlevel": 0, - "print_hide": 1, - "read_only": 0 - }, - { - "allow_on_submit": 0, - "depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)", - "fieldname": "get_items", - "fieldtype": "Button", - "hidden": 0, - "in_filter": 0, - "label": "Get Items", - "no_copy": 0, - "oldfieldtype": "Button", - "permlevel": 0, - "print_hide": 1, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0 - }, { "fieldname": "fold", "fieldtype": "Fold", @@ -632,7 +645,7 @@ "is_submittable": 1, "issingle": 0, "max_attachments": 0, - "modified": "2015-02-20 05:04:09.060180", + "modified": "2015-02-25 01:59:14.371042", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry", diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 6e18a91a78..2d7fc2d960 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -282,14 +282,15 @@ class StockEntry(StockController): def add_operation_cost(self, raw_material_cost, force): """Adds operating cost if Production Order is set""" # set incoming rate for fg item - if self.production_order: - number_of_fg_items = len([t.t_warehouse for t in self.get("items") if t.t_warehouse]) - for d in self.get("items"): - if d.bom_no or (d.t_warehouse and number_of_fg_items == 1): + number_of_fg_items = len([t.t_warehouse for t in self.get("items") if t.t_warehouse]) + for d in self.get("items"): + if (d.t_warehouse and number_of_fg_items == 1): + operation_cost_per_unit = 0.0 + if self.production_order: operation_cost_per_unit = self.get_operation_cost_per_unit(d.bom_no, d.qty) - d.incoming_rate = operation_cost_per_unit + (raw_material_cost / flt(d.transfer_qty)) - d.amount = flt(flt(d.transfer_qty) * flt(d.incoming_rate), self.precision("transfer_qty", d)) - break + d.incoming_rate = operation_cost_per_unit + (raw_material_cost / flt(d.transfer_qty)) + d.amount = flt(flt(d.transfer_qty) * flt(d.incoming_rate), self.precision("transfer_qty", d)) + break def get_operation_cost_per_unit(self, bom_no, qty): """Returns operating cost from Production Order for given `bom_no`""" @@ -510,10 +511,14 @@ class StockEntry(StockController): self.set('items', []) self.validate_production_order() + if not getattr(self, "pro_doc", None): + self.pro_doc = None + if self.production_order: # common validations - if not getattr(self, "pro_doc", None): + if not self.pro_doc: self.pro_doc = frappe.get_doc('Production Order', self.production_order) + if self.pro_doc: self.bom_no = self.pro_doc.bom_no else: diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 7c81d358b5..0845a6b43b 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -10,12 +10,18 @@ from erpnext.stock.stock_ledger import update_entries_after from erpnext.controllers.stock_controller import StockController from erpnext.stock.utils import get_stock_balance +class OpeningEntryAccountError(frappe.ValidationError): pass + class StockReconciliation(StockController): def __init__(self, arg1, arg2=None): super(StockReconciliation, self).__init__(arg1, arg2) self.head_row = ["Item Code", "Warehouse", "Quantity", "Valuation Rate"] def validate(self): + if not self.expense_account: + self.expense_account = frappe.db.get_value("Company", self.company, "stock_adjustment_account") + if not self.cost_center: + self.cost_center = frappe.db.get_value("Company", self.company, "cost_center") self.validate_posting_time() self.remove_items_with_no_change() self.validate_data() @@ -215,7 +221,12 @@ class StockReconciliation(StockController): msgprint(_("Please enter Expense Account"), raise_exception=1) elif not frappe.db.sql("""select name from `tabStock Ledger Entry` limit 1"""): if frappe.db.get_value("Account", self.expense_account, "report_type") == "Profit and Loss": - frappe.throw(_("Difference Account must be a 'Liability' type account, since this Stock Reconciliation is an Opening Entry")) + frappe.throw(_("Difference Account must be a 'Liability' type account, since this Stock Reconciliation is an Opening Entry"), OpeningEntryAccountError) + + def get_items_for(self, warehouse): + self.items = [] + for item in get_items(warehouse, self.posting_date, self.posting_time): + self.append("items", item) @frappe.whitelist() def get_items(warehouse, posting_date, posting_time): diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 84743ae79b..d51a89b7ce 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -150,7 +150,7 @@ class update_entries_after(object): return if sle.serial_no: - self.valuation_rate = self.get_serialized_values(sle) + self.get_serialized_values(sle) self.qty_after_transaction += flt(sle.actual_qty) self.stock_value = flt(self.qty_after_transaction) * flt(self.valuation_rate) else: @@ -208,12 +208,14 @@ class update_entries_after(object): if incoming_rate < 0: # wrong incoming rate incoming_rate = self.valuation_rate - elif incoming_rate == 0 or flt(sle.actual_qty) < 0: - # In case of delivery/stock issue, get average purchase rate - # of serial nos of current entry - incoming_rate = flt(frappe.db.sql("""select avg(ifnull(purchase_rate, 0)) - from `tabSerial No` where name in (%s)""" % (", ".join(["%s"]*len(serial_no))), - tuple(serial_no))[0][0]) + + elif incoming_rate == 0: + if flt(sle.actual_qty) < 0: + # In case of delivery/stock issue, get average purchase rate + # of serial nos of current entry + incoming_rate = flt(frappe.db.sql("""select avg(ifnull(purchase_rate, 0)) + from `tabSerial No` where name in (%s)""" % (", ".join(["%s"]*len(serial_no))), + tuple(serial_no))[0][0]) if incoming_rate and not self.valuation_rate: self.valuation_rate = incoming_rate