Merge pull request #7995 from saurabh6790/restrict_negative_qty_in_pr
[fix] validate negative quantity while creating purchase receipt
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js
index 9e40156..b2c08fa 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.js
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.js
@@ -111,6 +111,9 @@
var item = frappe.get_doc(cdt, cdn);
if ((doc.doctype == "Purchase Receipt") || (doc.doctype == "Purchase Invoice" && doc.update_stock)) {
frappe.model.round_floats_in(item, ["qty", "received_qty"]);
+
+ if(!doc.is_return && this.validate_negative_quantity(cdt, cdn, item, ["qty", "received_qty"])){ return }
+
if(!item.rejected_qty && item.qty) {
item.received_qty = item.qty;
}
@@ -134,10 +137,28 @@
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["received_qty", "rejected_qty"]);
+ if(!doc.is_return && this.validate_negative_quantity(cdt, cdn, item, ["received_qty", "rejected_qty"])){ return }
+
item.qty = flt(item.received_qty - item.rejected_qty, precision("qty", item));
this.qty(doc, cdt, cdn);
},
+ validate_negative_quantity: function(cdt, cdn, item, fieldnames){
+ if(!item || !fieldnames) { return }
+
+ var is_negative_qty = false;
+ for(var i = 0; i<fieldnames.length; i++) {
+ if(item[fieldnames[i]] < 0){
+ frappe.msgprint(__("Row #{0}: {1} can not be negative for item {2}",
+ [item.idx,__(frappe.meta.get_label(cdt, fieldnames[i], cdn)), item.item_code]));
+ is_negative_qty = true;
+ break;
+ }
+ }
+
+ return is_negative_qty
+ },
+
warehouse: function(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
if(item.item_code && item.warehouse) {
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 1d1b4e2..a1c7185 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -306,6 +306,7 @@
# validate accepted and rejected qty
def validate_accepted_rejected_qty(self):
for d in self.get("items"):
+ self.validate_negative_quantity(d, ["received_qty","qty", "rejected_qty"])
if not flt(d.received_qty) and flt(d.qty):
d.received_qty = flt(d.qty) - flt(d.rejected_qty)
@@ -319,6 +320,16 @@
if ((flt(d.qty) + flt(d.rejected_qty)) != flt(d.received_qty)):
frappe.throw(_("Accepted + Rejected Qty must be equal to Received quantity for Item {0}").format(d.item_code))
+ def validate_negative_quantity(self, item_row, field_list):
+ if self.is_return:
+ return
+
+ item_row = item_row.as_dict()
+ for fieldname in field_list:
+ if flt(item_row[fieldname]) < 0:
+ frappe.throw(_("Row #{0}: {1} can not be negative for item {2}".format(item_row['idx'],
+ frappe.get_meta(item_row.doctype).get_label(fieldname), item_row['item_code'])))
+
def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
self.update_ordered_qty()