Merge pull request #3702 from neilLasrado/capacity-planning

Global switch to set capacity planning in manufacturing
diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py
index 8153912..75c353d 100644
--- a/erpnext/accounts/report/gross_profit/gross_profit.py
+++ b/erpnext/accounts/report/gross_profit/gross_profit.py
@@ -174,12 +174,12 @@
 			return flt(row.qty) * item_rate
 
 		else:
-			if row.update_stock or row.dn_detail:
+			my_sle = self.sle.get((item_code, row.warehouse))
+			if (row.update_stock or row.dn_detail) and my_sle:
 				parenttype, parent, item_row = row.parenttype, row.parent, row.item_row
 				if row.dn_detail:
 					parenttype, parent, item_row = "Delivery Note", row.delivery_note, row.dn_detail
-
-				my_sle = self.sle.get((item_code, row.warehouse))
+				
 				for i, sle in enumerate(my_sle):
 					# find the stock valution rate from stock ledger entry
 					if sle.voucher_type == parenttype and parent == sle.voucher_no and \
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.js b/erpnext/manufacturing/doctype/production_order/production_order.js
index f8d76ff..d366377 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.js
+++ b/erpnext/manufacturing/doctype/production_order/production_order.js
@@ -251,7 +251,8 @@
 	return {
 		filters:[
 			['Item', 'is_pro_applicable', '=', 'Yes'],
-			['Item', 'has_variants', '=', 'No']
+			['Item', 'has_variants', '=', 'No'],
+			['Item', 'end_of_life', '>=', frappe.datetime.nowdate()]
 		]
 	}
 }
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 072ad41..13cc523 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/production_order.py
@@ -9,10 +9,13 @@
 from frappe.model.document import Document
 from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
 from dateutil.relativedelta import relativedelta
+from erpnext.stock.doctype.item.item import validate_end_of_life
 
 class OverProductionError(frappe.ValidationError): pass
 class StockOverProductionError(frappe.ValidationError): pass
 class OperationTooLongError(frappe.ValidationError): pass
+class ProductionNotApplicableError(frappe.ValidationError): pass
+class ItemHasVariantError(frappe.ValidationError): pass
 
 from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError
 from erpnext.projects.doctype.time_log.time_log import OverlapError
@@ -320,10 +323,12 @@
 	
 	def validate_production_item(self):
 		if frappe.db.get_value("Item", self.production_item, "is_pro_applicable")=='No':
-			frappe.throw(_("Item is not allowed to have Production Order."))
+			frappe.throw(_("Item is not allowed to have Production Order."), ProductionNotApplicableError)
 		
 		if frappe.db.get_value("Item", self.production_item, "has_variants"):
-			frappe.throw(_("Production Order cannot be raised against a Item Template"))
+			frappe.throw(_("Production Order cannot be raised against a Item Template"), ItemHasVariantError)
+		
+		validate_end_of_life(self.production_item)
 
 @frappe.whitelist()
 def get_item_details(item):
diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.py b/erpnext/manufacturing/doctype/production_order/test_production_order.py
index 34d584a..b91b2e1 100644
--- a/erpnext/manufacturing/doctype/production_order/test_production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/test_production_order.py
@@ -7,7 +7,8 @@
 import frappe
 from frappe.utils import flt, get_datetime, time_diff_in_hours
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
-from erpnext.manufacturing.doctype.production_order.production_order import make_stock_entry, make_time_log
+from erpnext.manufacturing.doctype.production_order.production_order \
+	import make_stock_entry, make_time_log, ProductionNotApplicableError,ItemHasVariantError
 from erpnext.stock.doctype.stock_entry import test_stock_entry
 from erpnext.projects.doctype.time_log.time_log import OverProductionLoggedError
 
@@ -135,6 +136,22 @@
 		prod_order.set_production_order_operations()
 		self.assertEqual(prod_order.planned_operating_cost, cost*2)
 		
+	def test_production_item(self):
+		frappe.db.set_value("Item", "_Test FG Item", "is_pro_applicable", "No")
+
+		prod_order = make_prod_order_test_record(item="_Test FG Item", qty=1, do_not_save=True)
+		self.assertRaises(ProductionNotApplicableError, prod_order.save)
+		
+		frappe.db.set_value("Item", "_Test FG Item", "is_pro_applicable", "Yes")
+		frappe.db.set_value("Item", "_Test FG Item", "end_of_life", "2000-1-1")
+		
+		self.assertRaises(frappe.ValidationError, prod_order.save)
+		
+		frappe.db.set_value("Item", "_Test FG Item", "end_of_life", None)
+		
+		prod_order = make_prod_order_test_record(item="_Test Variant Item", qty=1, do_not_save=True)
+		self.assertRaises(ItemHasVariantError, prod_order.save)
+
 def make_prod_order_test_record(**args):
 	args = frappe._dict(args)
 
diff --git a/erpnext/setup/page/setup_wizard/sample_data.py b/erpnext/setup/page/setup_wizard/sample_data.py
index f7fb73b..d9f8343 100644
--- a/erpnext/setup/page/setup_wizard/sample_data.py
+++ b/erpnext/setup/page/setup_wizard/sample_data.py
@@ -109,9 +109,14 @@
 				"end_date": frappe.utils.add_days(current_date, 5)
 			},
 			{
-				"title": "Go Live!",
+				"title": "Import Data",
 				"start_date": frappe.utils.add_days(current_date, 5),
 				"end_date": frappe.utils.add_days(current_date, 6)
+			},
+			{
+				"title": "Go Live!",
+				"start_date": frappe.utils.add_days(current_date, 6),
+				"end_date": frappe.utils.add_days(current_date, 7)
 			}])
 
 	project.insert(ignore_permissions=True)
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index c0ae213..f833a25 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -98,3 +98,11 @@
 cur_frm.cscript.posting_date = function(doc, cdt, cdn){
 	erpnext.get_fiscal_year(doc.company, doc.posting_date);
 }
+
+cur_frm.fields_dict.items.grid.get_field('item_code').get_query = function(doc, cdt, cdn) {
+	return {
+		filters:[
+			['Item', 'end_of_life', '>=', frappe.datetime.nowdate()]
+		]
+	}
+}
\ No newline at end of file