From dcb0462d510b5006a265a9fc425b6cd27f6dc0e2 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 5 Jun 2023 16:56:29 +0530 Subject: [PATCH] fix: added validation for insufficient stock during stock transfer --- .../js/utils/serial_no_batch_selector.js | 36 ++++++++++--------- .../stock/doctype/stock_entry/stock_entry.py | 6 +++- erpnext/stock/serial_batch_bundle.py | 12 +++++++ 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 0174ecf52a..f9eec2a411 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -68,6 +68,26 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { } }); + if (this.frm.doc.doctype === 'Stock Entry' + && this.frm.doc.purpose === 'Manufacture') { + fields.push({ + fieldtype: 'Column Break', + }); + + fields.push({ + fieldtype: 'Link', + fieldname: 'work_order', + label: __('For Work Order'), + options: 'Work Order', + read_only: 1, + default: this.frm.doc.work_order, + }); + + fields.push({ + fieldtype: 'Section Break', + }); + } + fields.push({ fieldtype: 'Column Break', }); @@ -101,22 +121,6 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { }); } - if (this.frm.doc.doctype === 'Stock Entry' - && this.frm.doc.purpose === 'Manufacture') { - fields.push({ - fieldtype: 'Column Break', - }); - - fields.push({ - fieldtype: 'Link', - fieldname: 'work_order', - label: __('For Work Order'), - options: 'Work Order', - read_only: 1, - default: this.frm.doc.work_order, - }); - } - if (this.item?.outward) { fields = [...this.get_filter_fields(), ...fields]; } else { diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 2f49822e69..f19df83791 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -2351,7 +2351,11 @@ class StockEntry(StockController): return for d in self.items: - if d.is_finished_item and d.item_code == self.pro_doc.production_item: + if ( + d.is_finished_item + and d.item_code == self.pro_doc.production_item + and not d.serial_and_batch_bundle + ): serial_nos = self.get_available_serial_nos() if serial_nos: row = frappe._dict({"serial_nos": serial_nos[0 : cint(d.qty)]}) diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 9c55358da2..a75c3b0ffb 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -738,6 +738,7 @@ class SerialBatchCreation: return frappe._dict({}) doc.save() + self.validate_qty(doc) if not hasattr(self, "do_not_submit") or not self.do_not_submit: doc.flags.ignore_voucher_validation = True @@ -767,6 +768,17 @@ class SerialBatchCreation: doc.save() return doc + def validate_qty(self, doc): + if doc.type_of_transaction == "Outward": + precision = doc.precision("total_qty") + + total_qty = abs(flt(doc.total_qty, precision)) + required_qty = abs(flt(self.actual_qty, precision)) + + if required_qty - total_qty > 0: + msg = f"For the item {bold(doc.item_code)}, the Avaliable qty {bold(total_qty)} is less than the Required Qty {bold(required_qty)} in the warehouse {bold(doc.warehouse)}. Please add sufficient qty in the warehouse." + frappe.throw(msg, title=_("Insufficient Stock")) + def set_auto_serial_batch_entries_for_outward(self): from erpnext.stock.doctype.batch.batch import get_available_batches from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos_for_outward