From 4a2fe605b3aae7e7f6cb864759d06c32857dc141 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 13 Apr 2018 11:59:58 +0530 Subject: [PATCH 1/6] batch no field in serial no doctype --- .../stock/doctype/serial_no/serial_no.json | 77 ++++++++++++++++++- .../stock/doctype/serial_no/test_serial_no.js | 23 ++++++ 2 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 erpnext/stock/doctype/serial_no/test_serial_no.js diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json index b37713be96..1ff0332476 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.json +++ b/erpnext/stock/doctype/serial_no/serial_no.json @@ -41,6 +41,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -69,6 +70,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -100,6 +102,7 @@ "reqd": 1, "search_index": 1, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -132,6 +135,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -165,6 +169,38 @@ "reqd": 0, "search_index": 1, "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "batch_no", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Batch No", + "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": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -193,6 +229,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -222,6 +259,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -253,6 +291,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "300px" }, @@ -287,6 +326,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -319,6 +359,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -348,6 +389,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -376,6 +418,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "50%" }, @@ -407,6 +450,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -437,6 +481,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -468,6 +513,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -497,6 +543,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -529,6 +576,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -557,6 +605,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "50%" }, @@ -588,6 +637,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -617,6 +667,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -647,6 +698,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -677,6 +729,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -707,6 +760,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -738,6 +792,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -767,6 +822,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -799,6 +855,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -827,6 +884,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "50%" }, @@ -860,6 +918,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -891,6 +950,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -921,6 +981,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -952,6 +1013,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -981,6 +1043,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1009,6 +1072,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "50%" }, @@ -1042,6 +1106,7 @@ "reqd": 0, "search_index": 1, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -1074,6 +1139,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -1103,6 +1169,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "50%" }, @@ -1135,6 +1202,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -1167,6 +1235,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -1197,6 +1266,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1226,6 +1296,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1256,6 +1327,7 @@ "reqd": 1, "search_index": 1, "set_only_once": 0, + "translatable": 0, "unique": 0 } ], @@ -1270,7 +1342,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-05-15 18:22:23.685286", + "modified": "2018-04-13 11:51:38.163506", "modified_by": "Administrator", "module": "Stock", "name": "Serial No", @@ -1278,7 +1350,6 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -1298,7 +1369,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, @@ -1318,7 +1388,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, diff --git a/erpnext/stock/doctype/serial_no/test_serial_no.js b/erpnext/stock/doctype/serial_no/test_serial_no.js new file mode 100644 index 0000000000..bf8293257c --- /dev/null +++ b/erpnext/stock/doctype/serial_no/test_serial_no.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Serial No", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Serial No + () => frappe.tests.make('Serial No', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); From 7461d28ae0370116ca92bb68dffc5313f373cbb2 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 13 Apr 2018 12:00:26 +0530 Subject: [PATCH 2/6] add batch when creating serial nos --- erpnext/stock/doctype/serial_no/serial_no.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 98f15a831a..43492a3b9f 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -16,6 +16,7 @@ class SerialNoRequiredError(ValidationError): pass class SerialNoQtyError(ValidationError): pass class SerialNoItemError(ValidationError): pass class SerialNoWarehouseError(ValidationError): pass +class SerialNoBatchError(ValidationError): pass class SerialNoNotExistsError(ValidationError): pass class SerialNoDuplicateError(ValidationError): pass @@ -187,6 +188,7 @@ def process_serial_no(sle): update_serial_nos(sle, item_det) def validate_serial_no(sle, item_det): + if item_det.has_serial_no==0: if sle.serial_no: frappe.throw(_("Item {0} is not setup for Serial Nos. Column must be blank").format(sle.item_code), @@ -228,8 +230,13 @@ def validate_serial_no(sle, item_det): frappe.throw(_("Serial No {0} does not belong to Warehouse {1}").format(serial_no, sle.warehouse), SerialNoWarehouseError) - if sle.voucher_type in ("Delivery Note", "Sales Invoice") \ - and sle.is_cancelled=="No" and not sr.warehouse: + if sle.voucher_type in ("Delivery Note", "Sales Invoice"): + + if sr.batch_no and sr.batch_no != sle.batch_no: + frappe.throw(_("Serial No {0} does not belong to Batch {1}").format(serial_no, + sle.batch_no), SerialNoBatchError) + + if sle.is_cancelled=="No" and not sr.warehouse: frappe.throw(_("Serial No {0} does not belong to any Warehouse") .format(serial_no), SerialNoWarehouseError) @@ -291,6 +298,7 @@ def update_serial_nos(sle, item_det): sr.via_stock_ledger = True sr.item_code = sle.item_code sr.warehouse = sle.warehouse if sle.actual_qty > 0 else None + sr.batch_no = sle.batch_no sr.save(ignore_permissions=True) elif sle.actual_qty > 0: make_serial_no(serial_no, sle) @@ -313,6 +321,7 @@ def make_serial_no(serial_no, sle): sr.serial_no = serial_no sr.item_code = sle.item_code sr.company = sle.company + sr.batch_no = sle.batch_no sr.via_stock_ledger = True sr.insert() From a20157af172a07b20fe9487eac2c57f4dac77511 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 13 Apr 2018 12:03:42 +0530 Subject: [PATCH 3/6] on item, warehouse and batch triggers, fetch serial nos based on batch --- erpnext/public/js/controllers/transaction.js | 1 - erpnext/selling/sales_common.js | 77 +++++----- .../delivery_note_item.json | 132 +++++++++++++----- erpnext/stock/get_item_details.py | 47 ++++++- 4 files changed, 187 insertions(+), 70 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 1551b1dfc3..3da28a88cf 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -296,7 +296,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ var me = this; var item = frappe.get_doc(cdt, cdn); var update_stock = 0, show_batch_dialog = 0; - if(['Sales Invoice'].includes(this.frm.doc.doctype)) { update_stock = cint(me.frm.doc.update_stock); show_batch_dialog = update_stock; diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index aa5b3ba498..d6f4677f8e 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -186,25 +186,32 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ warehouse: function(doc, cdt, cdn) { var me = this; var item = frappe.get_doc(cdt, cdn); - - if(item.item_code && item.warehouse) { - return this.frm.call({ - method: "erpnext.stock.get_item_details.get_bin_details_and_serial_nos", - child: item, - args: { - item_code: item.item_code, - warehouse: item.warehouse, - stock_qty: item.stock_qty, - serial_no: item.serial_no || "" - }, - callback:function(r){ - if (in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) { - me.set_batch_number(cdt, cdn); - me.batch_no(doc, cdt, cdn); - } - } - }); + if (item.serial_no && !item.batch_no) { + item.serial_no = null; } + var has_batch_no; + frappe.db.get_value('Item', {'item_code': item.item_code}, 'has_batch_no', (r) => { + has_batch_no = r && r.has_batch_no; + if(item.item_code && item.warehouse) { + return this.frm.call({ + method: "erpnext.stock.get_item_details.get_bin_details_and_serial_nos", + child: item, + args: { + item_code: item.item_code, + warehouse: item.warehouse, + has_batch_no: has_batch_no, + stock_qty: item.stock_qty, + serial_no: item.serial_no || "", + }, + callback:function(r){ + if (in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) { + me.set_batch_number(cdt, cdn); + me.batch_no(doc, cdt, cdn); + } + } + }); + } + }) }, toggle_editable_price_list_rate: function() { @@ -245,19 +252,25 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ batch_no: function(doc, cdt, cdn) { var me = this; var item = frappe.get_doc(cdt, cdn); - - if(item.warehouse && item.item_code && item.batch_no) { - return this.frm.call({ - method: "erpnext.stock.get_item_details.get_batch_qty", - child: item, - args: { - "batch_no": item.batch_no, - "warehouse": item.warehouse, - "item_code": item.item_code - }, - "fieldname": "actual_batch_qty" - }); - } + item.serial_no = null; + var has_serial_no; + frappe.db.get_value('Item', {'item_code': item.item_code}, 'has_serial_no', (r) => { + has_serial_no = r && r.has_serial_no; + if(item.warehouse && item.item_code && item.batch_no) { + return this.frm.call({ + method: "erpnext.stock.get_item_details.get_batch_qty_and_serial_no", + child: item, + args: { + "batch_no": item.batch_no, + "stock_qty": item.stock_qty, + "warehouse": item.warehouse, + "item_code": item.item_code, + "has_serial_no": has_serial_no + }, + "fieldname": "actual_batch_qty" + }); + } + }) }, set_dynamic_labels: function() { @@ -348,7 +361,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ }, qty: function(doc, cdt, cdn) { - this._super(doc, cdt, cdn); + this._super(doc, cdt, cdn); this.set_batch_number(cdt, cdn); }, 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 5487193284..ebf7ea170e 100644 --- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json +++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -40,6 +40,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -73,6 +74,7 @@ "reqd": 1, "search_index": 1, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -106,6 +108,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -135,6 +138,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -164,6 +168,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -194,6 +199,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -226,6 +232,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "300px" }, @@ -256,6 +263,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -286,6 +294,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -317,6 +326,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -346,6 +356,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -378,6 +389,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "100px" }, @@ -412,6 +424,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "50px" }, @@ -441,6 +454,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -472,6 +486,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -502,6 +517,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -532,6 +548,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -561,6 +578,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -594,6 +612,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "100px" }, @@ -628,6 +647,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "100px" }, @@ -659,6 +679,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -691,6 +712,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -722,6 +744,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -754,6 +777,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -783,6 +807,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -816,6 +841,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "100px" }, @@ -849,6 +875,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -877,6 +904,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -910,6 +938,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -944,6 +973,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "100px" }, @@ -973,6 +1003,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1006,6 +1037,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -1040,6 +1072,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "100px" }, @@ -1071,6 +1104,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1100,6 +1134,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1131,6 +1166,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1162,6 +1198,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1191,6 +1228,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1222,6 +1260,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1253,6 +1292,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1283,6 +1323,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1313,6 +1354,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1343,6 +1385,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1372,6 +1415,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1403,6 +1447,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1432,6 +1477,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1465,6 +1511,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "100px" }, @@ -1499,6 +1546,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1531,6 +1579,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1560,37 +1609,7 @@ "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": "serial_no", - "fieldtype": "Text", - "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": "Serial No", - "length": 0, - "no_copy": 1, - "oldfieldname": "serial_no", - "oldfieldtype": "Text", - "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, + "translatable": 0, "unique": 0 }, { @@ -1623,6 +1642,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1655,6 +1675,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -1688,9 +1709,42 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "serial_no", + "fieldtype": "Text", + "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": "Serial No", + "length": 0, + "no_copy": 1, + "oldfieldname": "serial_no", + "oldfieldtype": "Text", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1722,6 +1776,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1755,6 +1810,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -1787,6 +1843,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1815,6 +1872,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1845,6 +1903,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "120px" }, @@ -1877,6 +1936,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "120px" }, @@ -1908,6 +1968,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1938,6 +1999,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1968,6 +2030,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -2000,6 +2063,7 @@ "reqd": 0, "search_index": 1, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -2031,6 +2095,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -2063,6 +2128,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "150px" }, @@ -2095,6 +2161,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -2126,6 +2193,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 } ], @@ -2139,7 +2207,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-11-30 14:07:12.217563", + "modified": "2018-04-11 14:05:39.905947", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note Item", diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 7e456dd3d3..e3617111bc 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -81,14 +81,14 @@ def get_item_details(args): (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, args.serial_no) - if out.has_batch_no and not args.get("batch_no"): out.batch_no = get_batch_no(out.item_code, out.warehouse, out.qty) actual_batch_qty = get_batch_qty(out.batch_no, out.warehouse, out.item_code) if actual_batch_qty: out.update(actual_batch_qty) + + if out.has_serial_no: + out.serial_no = get_serial_no(out, args.serial_no) if args.transaction_date and item.lead_time_days: out.schedule_date = out.lead_time_date = add_days(args.transaction_date, @@ -465,6 +465,17 @@ def get_serial_nos_by_fifo(args): "qty": abs(cint(args.stock_qty)) })) +def get_serial_no_batchwise(args): + if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"): + return "\n".join(frappe.db.sql_list("""select name from `tabSerial No` + where item_code=%(item_code)s and warehouse=%(warehouse)s and batch_no=%(batch_no)s + order by timestamp(purchase_date, purchase_time) asc limit %(qty)s""", { + "item_code": args.item_code, + "warehouse": args.warehouse, + "batch_no": args.batch_no, + "qty": abs(cint(args.stock_qty)) + })) + @frappe.whitelist() def get_conversion_factor(item_code, uom): variant_of = frappe.db.get_value("Item", item_code, "variant_of") @@ -492,13 +503,30 @@ def get_serial_no_details(item_code, warehouse, stock_qty, serial_no): return {'serial_no': serial_no} @frappe.whitelist() -def get_bin_details_and_serial_nos(item_code, warehouse, stock_qty=None, serial_no=None): +def get_bin_details_and_serial_nos(item_code, warehouse, has_batch_no, stock_qty=None, serial_no=None): bin_details_and_serial_nos = {} bin_details_and_serial_nos.update(get_bin_details(item_code, warehouse)) if stock_qty > 0: + if has_batch_no: + args = frappe._dict({"item_code":item_code, "warehouse":warehouse, "stock_qty":stock_qty}) + serial_no = get_serial_no(args) + bin_details_and_serial_nos.update({'serial_no': serial_no}) + return bin_details_and_serial_nos + bin_details_and_serial_nos.update(get_serial_no_details(item_code, warehouse, stock_qty, serial_no)) return bin_details_and_serial_nos +@frappe.whitelist() +def get_batch_qty_and_serial_no(batch_no, stock_qty, warehouse, item_code, has_serial_no): + batch_qty_and_serial_no = {} + batch_qty_and_serial_no.update(get_batch_qty(batch_no, warehouse, item_code)) + + if (flt(batch_qty_and_serial_no.get('actual_batch_qty')) >= flt(stock_qty)) and has_serial_no: + args = frappe._dict({"item_code":item_code, "warehouse":warehouse, "stock_qty":stock_qty, "batch_no":batch_no}) + serial_no = get_serial_no(args) + batch_qty_and_serial_no.update({'serial_no': serial_no}) + return batch_qty_and_serial_no + @frappe.whitelist() def get_batch_qty(batch_no, warehouse, item_code): from erpnext.stock.doctype.batch import batch @@ -659,8 +687,17 @@ def get_serial_no(args, serial_nos=None): return "" if args.get('warehouse') and args.get('stock_qty') and args.get('item_code'): + has_serial_no = frappe.get_value('Item', {'item_code': args.item_code}, "has_serial_no") - if frappe.get_value('Item', {'item_code': args.item_code}, "has_serial_no") == 1: + if args.get('batch_no') and has_serial_no == 1: + return get_serial_no_batchwise(args) + # elif (args.get('has_batch_no') == 1) and has_serial_no == 1 and not args.get(batch_no): + # args.batch_no = get_batch_no(args.item_code, args.warehouse, args.qty) + # actual_batch_qty = get_batch_qty(out.batch_no, out.warehouse, out.item_code) + # if actual_batch_qty: + # out.update(actual_batch_qty) + # return get_serial_no_batchwise(args) + elif has_serial_no == 1: args = json.dumps({"item_code": args.get('item_code'),"warehouse": args.get('warehouse'),"stock_qty": args.get('stock_qty')}) args = process_args(args) serial_no = get_serial_nos_by_fifo(args) From 14bd43d5eb9420b8860b87c8715d9f9524a89694 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 27 Apr 2018 16:24:05 +0530 Subject: [PATCH 4/6] minor changes --- erpnext/controllers/accounts_controller.py | 1 - erpnext/public/js/controllers/transaction.js | 1 - erpnext/public/js/utils.js | 2 +- erpnext/stock/get_item_details.py | 18 ++++++++++-------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index c70cfcd811..31a3f6c5a5 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -198,7 +198,6 @@ class AccountsController(TransactionBase): if self.get("is_subcontracted"): args["is_subcontracted"] = self.is_subcontracted - ret = get_item_details(args) for fieldname, value in ret.items(): diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 3da28a88cf..102090b812 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -304,7 +304,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ this.frm.doc.doctype === 'Delivery Note') { show_batch_dialog = 1; } - // clear barcode if setting item (else barcode will take priority) if(!from_barcode) { item.barcode = null; diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 0e6017987a..a9ac8c4e61 100644 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -69,7 +69,7 @@ $.extend(erpnext, { "get_query": function () { return { filters: { - item_code:grid_row.doc.item_code , + item_code:grid_row.doc.item_code, warehouse:cur_frm.doc.is_return ? null : grid_row.doc.warehouse } } diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index e3617111bc..bcef472785 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -76,7 +76,6 @@ def get_item_details(args): args[key] = value out.update(get_pricing_rule_for_item(args)) - 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: @@ -86,8 +85,12 @@ def get_item_details(args): actual_batch_qty = get_batch_qty(out.batch_no, out.warehouse, out.item_code) if actual_batch_qty: out.update(actual_batch_qty) - - if out.has_serial_no: + + if out.has_serial_no and args.get('batch_no'): + out.batch_no = args.get('batch_no') + out.serial_no = get_serial_no(out, args.serial_no) + + elif out.has_serial_no: out.serial_no = get_serial_no(out, args.serial_no) if args.transaction_date and item.lead_time_days: @@ -468,7 +471,7 @@ def get_serial_nos_by_fifo(args): def get_serial_no_batchwise(args): if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"): return "\n".join(frappe.db.sql_list("""select name from `tabSerial No` - where item_code=%(item_code)s and warehouse=%(warehouse)s and batch_no=%(batch_no)s + where item_code=%(item_code)s and warehouse=%(warehouse)s and (batch_no=%(batch_no)s or batch_no is NULL) order by timestamp(purchase_date, purchase_time) asc limit %(qty)s""", { "item_code": args.item_code, "warehouse": args.warehouse, @@ -688,14 +691,13 @@ def get_serial_no(args, serial_nos=None): if args.get('warehouse') and args.get('stock_qty') and args.get('item_code'): has_serial_no = frappe.get_value('Item', {'item_code': args.item_code}, "has_serial_no") - if args.get('batch_no') and has_serial_no == 1: return get_serial_no_batchwise(args) - # elif (args.get('has_batch_no') == 1) and has_serial_no == 1 and not args.get(batch_no): + # elif (args.get('has_batch_no') == 1) and has_serial_no == 1 and not args.get('batch_no'): # args.batch_no = get_batch_no(args.item_code, args.warehouse, args.qty) - # actual_batch_qty = get_batch_qty(out.batch_no, out.warehouse, out.item_code) + # actual_batch_qty = get_batch_qty(args.batch_no, args.warehouse, args.item_code) # if actual_batch_qty: - # out.update(actual_batch_qty) + # args.update(actual_batch_qty) # return get_serial_no_batchwise(args) elif has_serial_no == 1: args = json.dumps({"item_code": args.get('item_code'),"warehouse": args.get('warehouse'),"stock_qty": args.get('stock_qty')}) From 96e45902fde590e9f8a6da21b44b7c4c5365cd65 Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 30 Apr 2018 15:54:34 +0530 Subject: [PATCH 5/6] codacy --- erpnext/stock/doctype/serial_no/serial_no.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 43492a3b9f..a6d2a0b06f 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -235,7 +235,7 @@ def validate_serial_no(sle, item_det): if sr.batch_no and sr.batch_no != sle.batch_no: frappe.throw(_("Serial No {0} does not belong to Batch {1}").format(serial_no, sle.batch_no), SerialNoBatchError) - + if sle.is_cancelled=="No" and not sr.warehouse: frappe.throw(_("Serial No {0} does not belong to any Warehouse") .format(serial_no), SerialNoWarehouseError) From 0456ced796d431c40a6317496410efffdeeb0772 Mon Sep 17 00:00:00 2001 From: Shreya Date: Tue, 1 May 2018 19:00:06 +0530 Subject: [PATCH 6/6] remove unused code --- erpnext/stock/get_item_details.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index bcef472785..b36cd39ad7 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -693,12 +693,6 @@ def get_serial_no(args, serial_nos=None): has_serial_no = frappe.get_value('Item', {'item_code': args.item_code}, "has_serial_no") if args.get('batch_no') and has_serial_no == 1: return get_serial_no_batchwise(args) - # elif (args.get('has_batch_no') == 1) and has_serial_no == 1 and not args.get('batch_no'): - # args.batch_no = get_batch_no(args.item_code, args.warehouse, args.qty) - # actual_batch_qty = get_batch_qty(args.batch_no, args.warehouse, args.item_code) - # if actual_batch_qty: - # args.update(actual_batch_qty) - # return get_serial_no_batchwise(args) elif has_serial_no == 1: args = json.dumps({"item_code": args.get('item_code'),"warehouse": args.get('warehouse'),"stock_qty": args.get('stock_qty')}) args = process_args(args)