Fixed logic and tests
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index a43c30d..5af3078 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -292,6 +292,13 @@
 			if d.rm_item_code:
 				stock_bin = get_bin(d.rm_item_code, d.reserve_warehouse)
 				stock_bin.update_reserved_qty_for_sub_contracting()
+	
+	def update_receiving_percentage(self):
+		total_qty, received_qty = 0.0, 0.0
+		for item in self.items:
+			received_qty += item.received_qty
+			total_qty += item.qty
+		self.db_set("per_received", flt(received_qty/total_qty) * 100, update_modified=False)
 
 def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor= 1.0):
 	"""get last purchase rate for an item"""
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 32f8ee8..c67d4e5 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -9,6 +9,8 @@
 from frappe.utils import flt, add_days, nowdate
 from erpnext.stock.doctype.item.test_item import make_item
 from erpnext.buying.doctype.purchase_order.purchase_order import (make_purchase_receipt, make_purchase_invoice, make_rm_stock_entry as make_subcontract_transfer_entry)
+from erpnext.stock.doctype.material_request.test_material_request import make_material_request
+from erpnext.stock.doctype.material_request.material_request import make_purchase_order
 from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
 from erpnext.controllers.accounts_controller import update_child_qty_rate
 import json
@@ -78,18 +80,34 @@
 		self.assertEqual(po.get("items")[0].received_qty, 0)
 
 	def test_update_child_qty_rate(self):
-		po = create_purchase_order(item_code= "_Test Item", qty=4)
+		mr = make_material_request(qty=10)
+		po = make_purchase_order(mr.name)
+		po.supplier = "_Test Supplier"
+		po.items[0].qty = 4
+		po.save()
+		po.submit()
 
 		create_pr_against_po(po.name)
 
 		make_purchase_invoice(po.name)
 
-		trans_item = {'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7}
+		existing_ordered_qty = get_ordered_qty()
+		existing_requested_qty = get_requested_qty()
+
+		trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7, 'docname': po.items[0].name}])
 		update_child_qty_rate('Purchase Order', trans_item, po.name)
 
+		mr.reload()
+		self.assertEqual(mr.items[0].ordered_qty, 7)
+		self.assertEqual(mr.per_ordered, 70)
+		self.assertEqual(get_requested_qty(), existing_requested_qty - 3)
+
+		po.reload()
 		self.assertEqual(po.get("items")[0].rate, 200)
 		self.assertEqual(po.get("items")[0].qty, 7)
 		self.assertEqual(po.get("items")[0].amount, 1400)
+		self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3)
+
 
 	def test_make_purchase_invoice(self):
 		po = create_purchase_order(do_not_submit=True)
@@ -536,6 +554,10 @@
 	return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
 		"ordered_qty"))
 
+def get_requested_qty(item_code="_Test Item", warehouse="_Test Warehouse - _TC"):
+	return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
+		"indented_qty"))
+
 test_dependencies = ["BOM", "Item Price"]
 
 test_records = frappe.get_test_records('Purchase Order')
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 9751e83..fe8e34e 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -783,7 +783,6 @@
 		else:
 			return frappe.db.get_single_value("Global Defaults", "disable_rounded_total")
 
-
 @frappe.whitelist()
 def get_tax_rate(account_head):
 	return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)
@@ -1045,13 +1044,13 @@
 	data = json.loads(trans_items)
 	for d in data:
 		child_item = frappe.get_doc(parent_doctype + ' Item', d.get("docname"))
-		child_item.qty = float(d.get("qty"))
+		child_item.qty = flt(d.get("qty"))
 
-		if child_item.billed_amt > (float(d.get("rate")) * float(d.get("qty"))):
+		if child_item.billed_amt > (flt(d.get("rate")) * flt(d.get("qty"))):
 			frappe.throw(_("Row #{0}: Cannot set Rate if amount is greater than billed amount for Item {1}.")
 						 .format(child_item.idx, child_item.item_code))
 		else:
-			child_item.rate = float(d.get("rate"))
+			child_item.rate = flt(d.get("rate"))
 		child_item.flags.ignore_validate_update_after_submit = True
 		child_item.save()
 
@@ -1059,28 +1058,36 @@
 
 	p_doctype.flags.ignore_validate_update_after_submit = True
 	p_doctype.set_qty_as_per_stock_uom()
-	if parent_doctype == 'Purchase Order':
-		p_doctype.validate_minimum_order_qty()
-		update_last_purchase_rate(p_doctype, is_submit = 1)
-		if p_doctype.is_against_so():
-			p_doctype.update_status_updater()
-		p_doctype.update_prevdoc_status()
-		p_doctype.update_requested_qty()
-		p_doctype.update_ordered_qty()
-		p_doctype.validate_budget()
-		p_doctype.update_ordered_and_reserved_qty()
-		if p_doctype.is_subcontracted == "Yes":
-			p_doctype.update_reserved_qty_for_subcontract()
-	else:
-		p_doctype.check_credit_limit()
-		p_doctype.update_reserved_qty()
-		p_doctype.update_project()
-		p_doctype.update_prevdoc_status('submit')
-	p_doctype.update_blanket_order()
-	p_doctype.set_status()
+	p_doctype.calculate_taxes_and_totals()
 	frappe.get_doc('Authorization Control').validate_approving_authority(p_doctype.doctype,
 		p_doctype.company, p_doctype.base_grand_total)
 
-	p_doctype.calculate_taxes_and_totals()
 	p_doctype.set_payment_schedule()
+	if parent_doctype == 'Purchase Order':
+		p_doctype.validate_minimum_order_qty()
+		p_doctype.validate_budget()
+		if p_doctype.is_against_so():
+			p_doctype.update_status_updater()
+	else:
+		p_doctype.check_credit_limit()
+
 	p_doctype.save()
+
+	if parent_doctype == 'Purchase Order':
+		update_last_purchase_rate(p_doctype, is_submit = 1)
+		p_doctype.update_prevdoc_status()
+		p_doctype.update_requested_qty()
+		p_doctype.update_ordered_qty()
+		p_doctype.update_ordered_and_reserved_qty()
+		p_doctype.update_receiving_percentage()
+		if p_doctype.is_subcontracted == "Yes":
+			p_doctype.update_reserved_qty_for_subcontract()
+	else:
+		p_doctype.update_reserved_qty()
+		p_doctype.update_project()
+		p_doctype.update_prevdoc_status('submit')
+		p_doctype.update_delivery_status()
+
+	p_doctype.update_blanket_order()
+	p_doctype.update_billing_percentage()
+	p_doctype.set_status()
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 410510b..a3993b8 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -256,17 +256,21 @@
 
 	def test_update_child_qty_rate(self):
 		so = make_sales_order(item_code= "_Test Item", qty=4)
-
-		make_delivery_note(so.name)
-
+		create_dn_against_so(so.name, 4)
 		make_sales_invoice(so.name)
 
-		trans_item = {'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7}
+		existing_reserved_qty = get_reserved_qty()
+		
+		trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7, 'docname': so.items[0].name}])
 		update_child_qty_rate('Sales Order', trans_item, so.name)
-
+		
+		so.reload()
 		self.assertEqual(so.get("items")[0].rate, 200)
 		self.assertEqual(so.get("items")[0].qty, 7)
 		self.assertEqual(so.get("items")[0].amount, 1400)
+		self.assertEqual(so.status, 'To Deliver and Bill')
+
+		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 3)
 
 	def test_warehouse_user(self):
 		frappe.permissions.add_user_permission("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com")
diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py
index 6b0b7bb..c9bb169 100644
--- a/erpnext/stock/doctype/material_request/test_material_request.py
+++ b/erpnext/stock/doctype/material_request/test_material_request.py
@@ -601,5 +601,21 @@
 		mr = frappe.get_doc("Material Request", mr.name)
 		self.assertEqual(mr.per_ordered, 100)
 
+def make_material_request(**args):
+	args = frappe._dict(args)
+	mr = frappe.new_doc("Material Request")
+	mr.material_request_type = args.material_request_type or "Purchase"
+	mr.company = args.company or "_Test Company"
+	mr.append("items", {
+		"item_code": args.item_code or "_Test Item",
+		"qty": args.qty or 10,
+		"schedule_date": args.schedule_date or today(),
+		"warehouse": args.warehouse or "_Test Warehouse - _TC"
+	})
+	mr.insert()
+	if not args.do_not_submit:
+		mr.submit()
+	return mr
+
 test_dependencies = ["Currency Exchange", "BOM"]
 test_records = frappe.get_test_records('Material Request')