Merge branch 'develop' into UAE-VAT-Format
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 394883d..f743d70 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -52,7 +52,7 @@
 						frappe.throw(_("Row #{0}: Serial No {1} does not belong to Batch {2}")
 							.format(d.idx, serial_no_data.name, d.batch_no))
 
-			if d.qty > 0 and d.get("batch_no") and self.get("posting_date") and self.docstatus < 2:
+			if flt(d.qty) > 0.0 and d.get("batch_no") and self.get("posting_date") and self.docstatus < 2:
 				expiry_date = frappe.get_cached_value("Batch", d.get("batch_no"), "expiry_date")
 
 				if expiry_date and getdate(expiry_date) < getdate(self.posting_date):
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index a244f58..9ce465c 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -636,7 +636,7 @@
 				description: __('Max: {0}', [max]),
 				default: max
 			}, data => {
-				max += (max * (frm.doc.__onload.overproduction_percentage || 0.0)) / 100;
+				max += (frm.doc.qty * (frm.doc.__onload.overproduction_percentage || 0.0)) / 100;
 
 				if (data.qty > max) {
 					frappe.msgprint(__('Quantity must not be more than {0}', [max]));
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index a92d04f..d456f98 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -96,7 +96,7 @@
 		self.update_quality_inspection()
 		if self.work_order and self.purpose == "Manufacture":
 			self.update_so_in_serial_number()
-		
+
 		if self.purpose == 'Material Transfer' and self.add_to_transit:
 			self.set_material_request_transfer_status('In Transit')
 		if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
@@ -849,6 +849,8 @@
 			frappe.throw(_("Posting date and posting time is mandatory"))
 
 		self.set_work_order_details()
+		self.flags.backflush_based_on = frappe.db.get_single_value("Manufacturing Settings",
+			"backflush_raw_materials_based_on")
 
 		if self.bom_no:
 
@@ -865,14 +867,16 @@
 							item["to_warehouse"] = self.pro_doc.wip_warehouse
 					self.add_to_stock_entry_detail(item_dict)
 
-				elif (self.work_order and (self.purpose == "Manufacture" or self.purpose == "Material Consumption for Manufacture")
-					and not self.pro_doc.skip_transfer and backflush_based_on == "Material Transferred for Manufacture"):
+				elif (self.work_order and (self.purpose == "Manufacture"
+						or self.purpose == "Material Consumption for Manufacture") and not self.pro_doc.skip_transfer
+					and self.flags.backflush_based_on == "Material Transferred for Manufacture"):
 					self.get_transfered_raw_materials()
 
-				elif (self.work_order and backflush_based_on== "BOM" and
-					(self.purpose == "Manufacture" or self.purpose == "Material Consumption for Manufacture")
+				elif (self.work_order and (self.purpose == "Manufacture" or
+					self.purpose == "Material Consumption for Manufacture") and self.flags.backflush_based_on== "BOM"
 					and frappe.db.get_single_value("Manufacturing Settings", "material_consumption")== 1):
 					self.get_unconsumed_raw_materials()
+
 				else:
 					if not self.fg_completed_qty:
 						frappe.throw(_("Manufacturing Quantity is mandatory"))
@@ -1111,7 +1115,6 @@
 				for d in backflushed_materials.get(item.item_code):
 					if d.get(item.warehouse):
 						if (qty > req_qty):
-							qty = req_qty
 							qty-= d.get(item.warehouse)
 
 			if qty > 0:
@@ -1137,12 +1140,24 @@
 		item_dict = self.get_pro_order_required_items(backflush_based_on)
 
 		max_qty = flt(self.pro_doc.qty)
+
+		allow_overproduction = False
+		overproduction_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
+			"overproduction_percentage_for_work_order"))
+
+		to_transfer_qty = flt(self.pro_doc.material_transferred_for_manufacturing) + flt(self.fg_completed_qty)
+		transfer_limit_qty = max_qty + ((max_qty * overproduction_percentage) / 100)
+
+		if transfer_limit_qty >= to_transfer_qty:
+			allow_overproduction = True
+
 		for item, item_details in iteritems(item_dict):
 			pending_to_issue = flt(item_details.required_qty) - flt(item_details.transferred_qty)
 			desire_to_transfer = flt(self.fg_completed_qty) * flt(item_details.required_qty) / max_qty
 
-			if (desire_to_transfer <= pending_to_issue or
-				(desire_to_transfer > 0 and backflush_based_on == "Material Transferred for Manufacture")):
+			if (desire_to_transfer <= pending_to_issue
+				or (desire_to_transfer > 0 and backflush_based_on == "Material Transferred for Manufacture")
+				or allow_overproduction):
 				item_dict[item]["qty"] = desire_to_transfer
 			elif pending_to_issue > 0:
 				item_dict[item]["qty"] = pending_to_issue
@@ -1370,7 +1385,7 @@
 		if self.outgoing_stock_entry:
 			parent_se = frappe.get_value("Stock Entry", self.outgoing_stock_entry, 'add_to_transit')
 
-		for item in self.items: 
+		for item in self.items:
 			material_request = item.material_request or None
 			if self.purpose == "Material Transfer" and material_request not in material_requests:
 				if self.outgoing_stock_entry and parent_se:
@@ -1430,7 +1445,7 @@
 			if add_to_transit:
 				warehouse = frappe.get_value('Material Request Item', source_doc.material_request_item, 'warehouse')
 				target_doc.t_warehouse = warehouse
-		
+
 		target_doc.s_warehouse = source_doc.t_warehouse
 		target_doc.qty = source_doc.qty - source_doc.transferred_qty