From 577e4c4e28f8be111fe0ab255aae485504e582a6 Mon Sep 17 00:00:00 2001 From: pratu16x7 Date: Fri, 23 Jun 2017 11:39:03 +0530 Subject: [PATCH] Add in transaction.js, cleanups --- erpnext/public/js/controllers/transaction.js | 25 +++++++- .../js/utils/serial_no_batch_selector.js | 59 +++++++++++++------ .../doctype/delivery_note/delivery_note.js | 43 +------------- .../doctype/delivery_note/delivery_note.py | 18 ------ .../stock/doctype/stock_entry/stock_entry.js | 21 +++---- erpnext/stock/get_item_details.py | 14 ++++- 6 files changed, 86 insertions(+), 94 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 8ad64d275e0..09773616894 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -265,6 +265,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ item_code: function(doc, cdt, cdn, from_barcode) { var me = this; var item = frappe.get_doc(cdt, cdn); + var update_stock = 0, show_batch_dialog = 1; + + if(['Sales Invoice', 'Purchase Invoice'].includes(me.frm.doc.doctype)) { + update_stock = cint(me.frm.doc.update_stock); + show_batch_dialog = update_stock; + } else { + update_stock = 0; + show_batch_dialog = 1; + } // clear barcode if setting item (else barcode will take priority) if(!from_barcode) { @@ -272,7 +281,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } if(item.item_code || item.barcode || item.serial_no) { if(!this.validate_company_and_party()) { - cur_frm.fields_dict["items"].grid.grid_rows[item.idx - 1].remove(); + this.frm.fields_dict["items"].grid.grid_rows[item.idx - 1].remove(); } else { return this.frm.call({ method: "erpnext.stock.get_item_details.get_item_details", @@ -286,7 +295,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ customer: me.frm.doc.customer, supplier: me.frm.doc.supplier, currency: me.frm.doc.currency, - update_stock: in_list(['Sales Invoice', 'Purchase Invoice'], me.frm.doc.doctype) ? cint(me.frm.doc.update_stock) : 0, + update_stock: update_stock, conversion_rate: me.frm.doc.conversion_rate, price_list: me.frm.doc.selling_price_list || me.frm.doc.buying_price_list, price_list_currency: me.frm.doc.price_list_currency, @@ -310,6 +319,18 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ if(!r.exc) { me.frm.script_manager.trigger("price_list_rate", cdt, cdn); me.toggle_conversion_factor(item); + if(show_batch_dialog) { + let d = r.message; + let serial_no_batch_selector = new erpnext.SerialNoBatchSelector({ + frm: me.frm, + item: d, + warehouse_details: { + type: "Warehouse", + name: d.warehouse + }, + }); + refresh_field("items"); + } } } }); diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index dd47f20946a..c1ec6d4376d 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -3,7 +3,16 @@ erpnext.SerialNoBatchSelector = Class.extend({ init: function(opts) { $.extend(this, opts); // frm, item, warehouse_details, has_batch, oldest - this.setup(); + let d = this.item; + + // Don't show dialog if batch no or serial no already set + if(d && d.has_batch_no && !d.batch_no) { + this.has_batch = 1; + this.setup(); + } else if(d && d.has_serial_no && !d.serial_no) { + this.has_batch = 0; + this.setup(); + } }, setup: function() { @@ -60,7 +69,6 @@ erpnext.SerialNoBatchSelector = Class.extend({ me.values = me.dialog.get_values(); if(me.validate()) { me.set_items(); - refresh_field("items"); me.dialog.hide(); } }); @@ -100,33 +108,47 @@ erpnext.SerialNoBatchSelector = Class.extend({ }, set_items: function() { + var me = this; + + function get_row_fields(index) { + index += me.item.idx - 1; + console.log(index, me.frm.fields_dict.items.grid.grid_rows); + return me.frm.fields_dict.items.grid + .grid_rows[index].on_grid_fields_dict; + } + if(this.has_batch) { this.values.batches.map((batch, i) => { - if(i === 0) { - this.map_item_values(this.item, batch, 'batch_no', - 'selected_qty', this.values.warehouse); - } else { - let row = this.frm.add_child("items"); - row.item_code = this.item_code; - this.map_item_values(row, batch, 'batch_no', - 'selected_qty', this.values.warehouse); - } + let row = (i !== 0) ? this.frm.add_child("items") : this.item; + refresh_field("items"); + let fields = (i !== 0) ? get_row_fields(i) : null; + this.map_row_values(fields, row, batch, 'batch_no', + 'selected_qty', this.values.warehouse); }); } else { - this.map_item_values(this.item, this.values, 'serial_no', 'qty'); + this.map_row_values(null, this.item, this.values, 'serial_no', 'qty'); } }, - map_item_values: function(item, values, attribute, qty_field, warehouse) { - item[attribute] = values[attribute]; + map_row_values: function(row_fields, row, values, number, qty_field, warehouse) { + row.qty = values[qty_field]; + if(this.warehouse_details.type === 'Source Warehouse') { - item.s_warehouse = values.warehouse || warehouse; + row.s_warehouse = values.warehouse || warehouse; } else if(this.warehouse_details.type === 'Target Warehouse') { - item.t_warehouse = values.warehouse || warehouse; + row.t_warehouse = values.warehouse || warehouse; } else { - item.warehouse = values.warehouse || warehouse; + row.warehouse = values.warehouse || warehouse; + } + + row[number] = values[number]; + refresh_field("items"); + + // Set item_code after setting batch + // so that dialog does not fire for inserted rows + if(row_fields) { + row_fields.item_code.set_value(this.item_code); } - item.qty = values[qty_field]; }, bind_qty: function() { @@ -208,6 +230,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ return {filters: {item: me.item_code }}; }, onchange: function(e) { + console.log(this); if(this.get_value().length === 0) { this.grid_row.on_grid_fields_dict .available_qty.set_value(0); diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index 4b52f2feec5..c441df22374 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -38,7 +38,7 @@ frappe.ui.form.on("Delivery Note", { } }); - + frm.set_query('expense_account', 'items', function(doc, cdt, cdn) { if (erpnext.is_perpetual_inventory_enabled(doc.company)) { return { @@ -61,7 +61,7 @@ frappe.ui.form.on("Delivery Note", { } } }); - + $.extend(frm.cscript, new erpnext.stock.DeliveryNoteController({frm: frm})); }, @@ -83,43 +83,6 @@ frappe.ui.form.on("Delivery Note Item", { cost_center: function(frm, dt, dn) { var d = locals[dt][dn]; frm.update_in_all_rows('items', 'cost_center', d.cost_center); - }, - item_code: function(frm, dt, dn) { - var d = locals[dt][dn]; - if(d.item_code) { - var args = { - 'item_code': d.item_code, - }; - frappe.call({ - doc: frm.doc, - method: "get_batched_serialized_details", - args: args, - callback: function(r) { - if(r.message) { - $.each(r.message, function(k, v) { - d[k] = v; - }); - let opts = { - frm: frm, - item: d, - warehouse_details: { - type: "From Warehouse", - name: d.warehouse - }, - } - if(d && d.has_batch_no && !d.batch_no) { - opts.has_batch = 1; - } else if(d && d.has_serial_no && !d.serial_no) { - opts.has_batch = 0; - } - if(opts.hasOwnProperty("has_batch")) { - let serial_no_batch_selector = new erpnext.SerialNoBatchSelector(opts); - } - refresh_field("items"); - } - } - }); - } } }); @@ -272,7 +235,7 @@ frappe.ui.form.on('Delivery Note', { company: function(frm) { frm.trigger("unhide_account_head"); }, - + unhide_account_head: function(frm) { // unhide expense_account and cost_center if perpetual inventory is enabled in the company var aii_enabled = erpnext.is_perpetual_inventory_enabled(frm.doc.company) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index e1761173eb5..75234099507 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -301,24 +301,6 @@ class DeliveryNote(SellingController): self.load_from_db() - def get_batched_serialized_details(self, item_code): - item = frappe.db.sql(""" - select - has_serial_no, - has_batch_no - from - `tabItem` - where - name = %s""", - (item_code), as_dict = 1) - - item = item[0] - - return frappe._dict({ - 'has_serial_no' : item.has_serial_no, - 'has_batch_no' : item.has_batch_no - }) - def update_billed_amount_based_on_so(so_detail, update_modified=True): # Billed against Sales Order directly billed_against_so = frappe.db.sql("""select sum(amount) from `tabSales Invoice Item` diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 34f5cb75b51..3cc7cd10386 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -564,21 +564,14 @@ erpnext.stock.select_batch_and_serial_no = (frm, item) => { } } - let opts = { + if(item && item.has_serial_no + && frm.doc.purpose === 'Material Receipt') { + return; + } + + let serial_no_batch_selector = new erpnext.SerialNoBatchSelector({ frm: frm, item: item, warehouse_details: get_warehouse_type_and_name(item), - } - - if(item && item.has_batch_no && !item.batch_no) { - opts.has_batch = 1; - } else if(item && item.has_serial_no && !item.serial_no - && frm.doc.purpose !== 'Material Receipt') { - - opts.has_batch = 0; - } - - if(opts.hasOwnProperty("has_batch")) { - let serial_no_batch_selector = new erpnext.SerialNoBatchSelector(opts); - } + }); } diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 18db8f91237..a3ae0eb121e 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -74,10 +74,10 @@ def get_item_details(args): out.update(get_pricing_rule_for_item(args)) - if (args.get("doctype") == "Delivery Note" or + if (args.get("doctype") == "Delivery Note" or (args.get("doctype") == "Sales Invoice" and args.get('update_stock'))) \ and out.warehouse and out.stock_qty > 0: - + if out.has_serial_no: out.serial_no = get_serial_no(out) @@ -96,6 +96,16 @@ def get_item_details(args): return out + # print(frappe._dict({ + # 'has_serial_no' : out.has_serial_no, + # 'has_batch_no' : out.has_batch_no + # })) + + # return frappe._dict({ + # 'has_serial_no' : out.has_serial_no, + # 'has_batch_no' : out.has_batch_no + # }) + def process_args(args): if isinstance(args, basestring): args = json.loads(args)