diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 449a97522f..6e3990ac8d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -17,6 +17,7 @@ from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amou from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data from erpnext.accounts.doctype.asset.depreciation \ import get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal +from erpnext.stock.doctype.batch.batch import set_batch_nos form_grid_templates = { "items": "templates/form_grid/item_grid.html" @@ -78,6 +79,10 @@ class SalesInvoice(SellingController): if not self.is_opening: self.is_opening = 'No' + + if self._action != 'submit' and self.update_stock and not self.is_return: + set_batch_nos(self, 'warehouse', True) + self.set_against_income_account() self.validate_c_form() @@ -87,7 +92,7 @@ class SalesInvoice(SellingController): self.set_billing_hours_and_amount() self.update_timesheet_billing_for_project() self.set_status() - + def before_save(self): set_account_for_mode_of_payment(self) diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 5749afb8e7..909095ecbe 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document +from frappe.utils import flt class UnableToSelectBatchError(frappe.ValidationError): pass @@ -96,24 +97,27 @@ def set_batch_nos(doc, warehouse_field, throw = False): for d in doc.items: has_batch_no = frappe.db.get_value('Item', d.item_code, 'has_batch_no') warehouse = d.get(warehouse_field, None) - if has_batch_no and not d.batch_no and warehouse: - d.batch_no = get_batch_no(d.item_code, warehouse, d.qty, throw) + if has_batch_no and warehouse and d.qty > 0: + if not d.batch_no: + d.batch_no = get_batch_no(d.item_code, warehouse, d.qty, throw) + else: + batch_qty = get_batch_qty(batch_no=d.batch_no, warehouse=warehouse) + if flt(batch_qty) < flt(d.qty): + frappe.throw(_("Row #{0}: The batch {1} has only {2} qty. Please select another batch which has {3} qty available or split the row into multiple rows, to deliver/issue from multiple batches").format(d.idx, d.batch_no, batch_qty, d.qty)) def get_batch_no(item_code, warehouse, qty, throw=False): '''get the smallest batch with for the given item_code, warehouse and qty''' batch_no = None - batches = get_batch_qty(item_code = item_code, warehouse = warehouse) if batches: batches = sorted(batches, lambda a, b: 1 if a.qty > b.qty else -1) - for b in batches: if b.qty >= qty: batch_no = b.batch_no # found! break - + if not batch_no: frappe.msgprint(_('Please select a Batch for Item {0}. Unable to find a single batch that fulfills this requirement').format(frappe.bold(item_code))) if throw: raise UnableToSelectBatchError diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index e7bf827ae2..441b6370cc 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -106,7 +106,7 @@ class DeliveryNote(SellingController): self.validate_uom_is_integer("uom", "qty") self.validate_with_previous_doc() - if self._action != 'submit': + if self._action != 'submit' and not self.is_return: set_batch_nos(self, 'warehouse', True) from erpnext.stock.doctype.packed_item.packed_item import make_packing_list diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 35760fd7a1..18db8f9123 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -81,7 +81,7 @@ def get_item_details(args): if out.has_serial_no: out.serial_no = get_serial_no(out) - if out.has_batch_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)