Cleanup of PO schedule date pull requests
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 8134e7e..0394f74 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -1,4 +1,3 @@
-
 // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
@@ -16,6 +15,8 @@
 	},
 
 	onload: function(frm) {
+		set_schedule_date(frm);
+
 		erpnext.queries.setup_queries(frm, "Warehouse", function() {
 			return erpnext.queries.warehouse(frm.doc);
 		});
@@ -34,6 +35,17 @@
 				frm.trigger('calculate_taxes_and_totals');
 			}
 		})
+	},
+
+	schedule_date: function(frm, cdt, cdn) {
+		var row = locals[cdt][cdn];
+		if (row.schedule_date) {
+			if(!frm.doc.schedule_date) {
+				erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "schedule_date");
+			} else {
+				set_schedule_date(frm);
+			}
+		}
 	}
 });
 
@@ -120,12 +132,7 @@
 	},
 
 	validate: function() {
-		// set default schedule date as today if missing.
-		(this.frm.doc.items || []).forEach(function(d) {
-			if(!d.schedule_date) {
-				d.schedule_date = frappe.datetime.nowdate();
-			}
-		})
+		set_schedule_date(this.frm);
 	},
 
 	make_stock_entry: function() {
@@ -214,7 +221,12 @@
 
 	items_add: function(doc, cdt, cdn) {
 		var row = frappe.get_doc(cdt, cdn);
-		this.frm.script_manager.copy_from_first_row("items", row, ["schedule_date"]);
+		if(doc.schedule_date) {
+			row.schedule_date = doc.schedule_date;
+			refresh_field("schedule_date", cdn, "items");
+		} else {
+			this.frm.script_manager.copy_from_first_row("items", row, ["schedule_date"]);
+		}
 	},
 
 	unclose_purchase_order: function(){
@@ -227,8 +239,26 @@
 
 	delivered_by_supplier: function(){
 		cur_frm.cscript.update_status('Deliver', 'Delivered')
-	}
+	},
 
+	get_last_purchase_rate: function() {
+		frappe.call({
+			"method": "get_last_purchase_rate",
+			"doc": cur_frm.doc,
+			callback: function(r, rt) {
+				cur_frm.dirty();
+				cur_frm.cscript.calculate_taxes_and_totals();
+			}
+		})
+	},
+
+	items_on_form_rendered: function() {
+		set_schedule_date(this.frm);
+	},
+
+	schedule_date: function() {
+		set_schedule_date(this.frm);
+	}
 });
 
 // for backward compatibility: combine new and previous states
@@ -270,8 +300,10 @@
 	}
 }
 
-cur_frm.cscript.schedule_date = function(doc, cdt, cdn) {
-	erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "schedule_date");
+function set_schedule_date(frm) {
+	if(frm.doc.schedule_date){
+		erpnext.utils.copy_value_in_all_row(frm.doc, frm.doc.doctype, frm.doc.name, "items", "schedule_date");
+	}
 }
 
 frappe.provide("erpnext.buying");
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index af3f9a6..28b8b47 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -294,6 +294,37 @@
   },
   {
    "allow_bulk_edit": 0,
+   "allow_on_submit": 1,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "",
+   "fieldname": "schedule_date",
+   "fieldtype": "Date",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Reqd By Date",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -3427,7 +3458,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-09-22 16:11:49.856808", 
+ "modified": "2017-10-05 14:19:04.102534", 
  "modified_by": "Administrator", 
  "module": "Buying", 
  "name": "Purchase Order", 
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 36cef43..4150993 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -41,6 +41,7 @@
 		self.set_status()
 
 		self.validate_supplier()
+		self.validate_schedule_date()
 		validate_for_items(self)
 		self.check_for_closed_status()
 
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 17786aa..2af5582 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -118,6 +118,7 @@
 			"company": "_Test Company",
 			"supplier" : "_Test Supplier",
 			"is_subcontracted" : "No",
+			"schedule_date": add_days(nowdate(), 1),
 			"currency" : frappe.db.get_value("Company", "_Test Company", "default_currency"),
 			"conversion_factor" : 1,
 			"items" : get_same_items(),
@@ -149,6 +150,7 @@
 	if args.transaction_date:
 		po.transaction_date = args.transaction_date
 
+	po.schedule_date = add_days(nowdate(), 1)
 	po.company = args.company or "_Test Company"
 	po.supplier = args.customer or "_Test Supplier"
 	po.is_subcontracted = args.is_subcontracted or "No"
diff --git a/erpnext/buying/doctype/purchase_order/test_records.json b/erpnext/buying/doctype/purchase_order/test_records.json
index 2c2e792..74b8f1b 100644
--- a/erpnext/buying/doctype/purchase_order/test_records.json
+++ b/erpnext/buying/doctype/purchase_order/test_records.json
@@ -30,7 +30,8 @@
   ], 
   "supplier": "_Test Supplier", 
   "supplier_name": "_Test Supplier", 
-  "transaction_date": "2013-02-12"
+  "transaction_date": "2013-02-12",
+  "schedule_date": "2013-02-13"
  },
  {
   "advance_paid": 0.0,  
@@ -63,6 +64,7 @@
   ], 
   "supplier": "_Test Supplier", 
   "supplier_name": "_Test Supplier", 
-  "transaction_date": "2013-02-12"
+  "transaction_date": "2013-02-12",
+  "schedule_date": "2013-02-13"
  }
 ]
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js
index e6529e6..6605a65 100644
--- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js
@@ -13,12 +13,21 @@
 				{items: [
 					[
 						{"item_code": 'Test Product 4'},
-						{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
+						{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 2)},
 						{"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
 						{"qty": 5},
 						{"uom": 'Unit'},
 						{"rate": 100},
 						{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
+					],
+					[
+						{"item_code": 'Test Product 1'},
+						{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
+						{"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
+						{"qty": 2},
+						{"uom": 'Unit'},
+						{"rate": 100},
+						{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
 					]
 				]},
 
@@ -30,12 +39,19 @@
 		() => {
 			// Get supplier details
 			assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
+			assert.ok(cur_frm.doc.schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 1), "Schedule Date correct");
 			assert.ok($('div.control-value.like-disabled-input.for-description').text().includes('Contact 3'), "Contact display correct");
 			assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Contact email correct");
 			// Get item details
 			assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item name correct");
 			assert.ok(cur_frm.doc.items[0].description == 'Test Product 4', "Description correct");
 			assert.ok(cur_frm.doc.items[0].qty == 5, "Quantity correct");
+			assert.ok(cur_frm.doc.items[0].schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 2), "Schedule Date correct");
+
+			assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Item name correct");
+			assert.ok(cur_frm.doc.items[1].description == 'Test Product 1', "Description correct");
+			assert.ok(cur_frm.doc.items[1].qty == 2, "Quantity correct");
+			assert.ok(cur_frm.doc.items[1].schedule_date == cur_frm.doc.schedule_date, "Schedule Date correct");
 			// Calculate total
 			assert.ok(cur_frm.doc.total == 500, "Total correct");
 			// Get terms
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js
index 9d87af2..27129fb 100644
--- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js
+++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js
@@ -11,6 +11,7 @@
 				{is_subcontracted: 'No'},
 				{buying_price_list: 'Test-Buying-USD'},
 				{currency: 'USD'},
+				{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
 				{items: [
 					[
 						{"item_code": 'Test Product 4'},
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index d56c3bd..ca1a0a7 100755
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -140,7 +140,7 @@
    "allow_on_submit": 1, 
    "bold": 1, 
    "collapsible": 0, 
-   "columns": 0, 
+   "columns": 2, 
    "fieldname": "schedule_date", 
    "fieldtype": "Date", 
    "hidden": 0, 
@@ -148,7 +148,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_global_search": 0, 
-   "in_list_view": 0,
+   "in_list_view": 1, 
    "in_standard_filter": 0, 
    "label": "Reqd By Date", 
    "length": 0, 
@@ -382,7 +382,7 @@
    "allow_on_submit": 0, 
    "bold": 1, 
    "collapsible": 0, 
-   "columns": 2, 
+   "columns": 1, 
    "fieldname": "qty", 
    "fieldtype": "Float", 
    "hidden": 0, 
@@ -749,7 +749,7 @@
    "allow_on_submit": 0, 
    "bold": 1, 
    "collapsible": 0, 
-   "columns": 3, 
+   "columns": 2, 
    "fieldname": "rate", 
    "fieldtype": "Currency", 
    "hidden": 0, 
@@ -1745,7 +1745,7 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2017-09-22 16:47:08.783546", 
+ "modified": "2017-10-05 19:47:12.433095", 
  "modified_by": "Administrator", 
  "module": "Buying", 
  "name": "Purchase Order Item", 
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
index b3d92be..c395d0c 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-from frappe.utils import flt
+from frappe.utils import flt, nowdate, add_days
 from frappe.model.mapper import get_mapped_doc
 
 from erpnext.controllers.buying_controller import BuyingController
@@ -151,5 +151,4 @@
 		}
 	}, target_doc)
 
-	return doclist
-
+	return doclist
\ No newline at end of file
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 1f9051d..d301081 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _, msgprint
-from frappe.utils import flt,cint, cstr
+from frappe.utils import flt,cint, cstr, getdate
 
 from erpnext.accounts.party import get_party_details
 from erpnext.stock.get_item_details import get_conversion_factor
@@ -408,3 +408,16 @@
 					"actual_qty": -1*flt(d.consumed_qty),
 				}))
 
+	def validate_schedule_date(self):
+		if not self.schedule_date:
+			self.schedule_date = min([d.schedule_date for d in self.get("items")])
+
+		if self.schedule_date:
+			for d in self.get('items'):
+				if not d.schedule_date:
+					d.schedule_date = self.schedule_date
+
+				if d.schedule_date and getdate(d.schedule_date) < getdate(self.transaction_date):
+					frappe.throw(_("Expected Date cannot be before Transaction Date"))
+		else:
+			frappe.throw(_("Please enter Schedule Date"))
\ No newline at end of file
diff --git a/erpnext/demo/user/purchase.py b/erpnext/demo/user/purchase.py
index 82983f0..8769b09 100644
--- a/erpnext/demo/user/purchase.py
+++ b/erpnext/demo/user/purchase.py
@@ -129,6 +129,7 @@
 		po = frappe.new_doc("Purchase Order")
 		po.is_subcontracted = "Yes"
 		po.supplier = get_random("Supplier")
+		po.schedule_date = frappe.utils.add_days(frappe.flags.current_date, 7)
 
 		item_code = get_random("Item", {"is_sub_contracted_item": 1})
 
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 70122ba..8b0f714 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -449,4 +449,4 @@
 erpnext.patches.v8_9.set_default_fields_in_variant_settings
 erpnext.patches.v8_9.update_billing_gstin_for_indian_account
 erpnext.patches.v9_0.fix_subscription_next_date
-erpnext.patches.v9_0.set_schedule_date_for_material_request
+erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
diff --git a/erpnext/patches/v9_0/set_schedule_date_for_material_request.py b/erpnext/patches/v9_0/set_schedule_date_for_material_request.py
deleted file mode 100644
index 39d4d41..0000000
--- a/erpnext/patches/v9_0/set_schedule_date_for_material_request.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
-	frappe.reload_doctype("Material Request")
-	frappe.reload_doctype("Material Request Item")
-
-	if not frappe.db.has_column("Material Request", "schedule_date"):
-		return
-
-	#Update only submitted MR
-	for mr in frappe.get_all("Material Request", filters= [["docstatus", "=", 1]], fields=["name"]):
-		material_request = frappe.get_doc("Material Request", mr)
-		if material_request.items:
-			if not material_request.schedule_date:
-				max_schedule_date = max([d.schedule_date for d in material_request.items])
-				frappe.db.set_value("Material Request", mr,
-					"schedule_date", max_schedule_date, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py b/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py
new file mode 100644
index 0000000..7ab0e2c
--- /dev/null
+++ b/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py
@@ -0,0 +1,22 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	for doctype in ("Material Request", "Purchase Order"):
+		frappe.reload_doctype(doctype)
+		frappe.reload_doctype(doctype + " Item")
+
+		if not frappe.db.has_column(doctype, "schedule_date"):
+			continue
+
+		#Update only submitted MR
+		for record in frappe.get_all(doctype, filters= [["docstatus", "=", 1]], fields=["name"]):
+			doc = frappe.get_doc(doctype, record)
+			if doc.items:
+				if not doc.schedule_date:
+					min_schedule_date = min([d.schedule_date for d in doc.items])
+					frappe.db.set_value(doctype, record,
+						"schedule_date", min_schedule_date, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 98333c4..c3e28d2 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -5,7 +5,7 @@
 import frappe
 import json
 import frappe.utils
-from frappe.utils import cstr, flt, getdate, comma_and, cint
+from frappe.utils import cstr, flt, getdate, comma_and, cint, nowdate, add_days
 from frappe import _
 from frappe.model.utils import get_fetch_values
 from frappe.model.mapper import get_mapped_doc
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 4e4b0f7..9eb2313 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -53,7 +53,7 @@
 				set_schedule_date(frm);
 			}
 		}
-	}	
+	}
 });
 
 erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.extend({
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 4e9d290..59075c5 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -7,7 +7,7 @@
 from __future__ import unicode_literals
 import frappe
 
-from frappe.utils import cstr, flt, getdate, new_line_sep
+from frappe.utils import cstr, flt, getdate, new_line_sep, nowdate, add_days
 from frappe import msgprint, _
 from frappe.model.mapper import get_mapped_doc
 from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty
@@ -53,20 +53,6 @@
 				if actual_so_qty and (flt(so_items[so_no][item]) + already_indented > actual_so_qty):
 					frappe.throw(_("Material Request of maximum {0} can be made for Item {1} against Sales Order {2}").format(actual_so_qty - already_indented, item, so_no))
 
-	def validate_schedule_date(self):
-		if not self.schedule_date:
-			self.schedule_date = max([d.schedule_date for d in self.get("items")])
-
-		if self.schedule_date:
-			for d in self.get('items'):
-				if not d.schedule_date:
-					d.schedule_date = self.schedule_date
-
-				if d.schedule_date and getdate(d.schedule_date) < getdate(self.transaction_date):
-					frappe.throw(_("Expected Date cannot be before Material Request Date"))
-		else:
-			frappe.throw(_("Please enter Schedule Date"))
-
 	# Validate
 	# ---------------------
 	def validate(self):
@@ -296,7 +282,7 @@
 
 	def postprocess(source, target_doc):
 		target_doc.supplier = source_name
-
+		target_doc.schedule_date = add_days(nowdate(), 1)
 		target_doc.set("items", [d for d in target_doc.get("items")
 			if d.get("item_code") in supplier_items and d.get("qty") > 0])
 
@@ -329,12 +315,12 @@
 		material_requests = frappe.db.sql_list("""select distinct mr.name
 			from `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
 			where mr.name = mr_item.parent
-			and mr_item.item_code in (%s)
-			and mr.material_request_type = 'Purchase'
-			and mr.per_ordered < 99.99
-			and mr.docstatus = 1
-			and mr.status != 'Stopped'
-                        order by mr_item.item_code ASC""" % ', '.join(['%s']*len(supplier_items)),
+				and mr_item.item_code in (%s)
+				and mr.material_request_type = 'Purchase'
+				and mr.per_ordered < 99.99
+				and mr.docstatus = 1
+				and mr.status != 'Stopped'
+			order by mr_item.item_code ASC""" % ', '.join(['%s']*len(supplier_items)),
 			tuple(supplier_items))
 	else:
 		material_requests = []
diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py
index 1531f40..709b8c7 100644
--- a/erpnext/stock/doctype/material_request/test_material_request.py
+++ b/erpnext/stock/doctype/material_request/test_material_request.py
@@ -206,6 +206,7 @@
 		po_doc = make_purchase_order(mr.name)
 		po_doc.supplier = "_Test Supplier"
 		po_doc.transaction_date = "2013-07-07"
+		po_doc.schedule_date = "2013-07-09"
 		po_doc.get("items")[0].qty = 27.0
 		po_doc.get("items")[1].qty = 1.5
 		po_doc.get("items")[0].schedule_date = "2013-07-09"