Merge pull request #3714 from nabinhait/fix4

[fix] gross profit report
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.js b/erpnext/accounts/doctype/cost_center/cost_center.js
index 6946bcb..fb649e6 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.js
+++ b/erpnext/accounts/doctype/cost_center/cost_center.js
@@ -17,7 +17,7 @@
 				return {
 					filters:[
 						['Account', 'company', '=', me.frm.doc.company],
-						['Account', 'report_type', '=', 'Profit and Loss'],
+						['Account', 'root_type', '=', 'Expense'],
 						['Account', 'is_group', '=', '0'],
 					]
 				}
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.py b/erpnext/accounts/doctype/cost_center/cost_center.py
index f26c80b..0f51a00 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.py
+++ b/erpnext/accounts/doctype/cost_center/cost_center.py
@@ -3,9 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe
-
-from frappe import msgprint, _
-
+from frappe import _
 from frappe.utils.nestedset import NestedSet
 
 class CostCenter(NestedSet):
@@ -14,18 +12,46 @@
 	def autoname(self):
 		self.name = self.cost_center_name.strip() + ' - ' + \
 			frappe.db.get_value("Company", self.company, "abbr")
+			
+
+	def validate(self):
+		self.validate_mandatory()
+		self.validate_accounts()
 
 	def validate_mandatory(self):
 		if self.cost_center_name != self.company and not self.parent_cost_center:
-			msgprint(_("Please enter parent cost center"), raise_exception=1)
+			frappe.throw(_("Please enter parent cost center"))
 		elif self.cost_center_name == self.company and self.parent_cost_center:
-			msgprint(_("Root cannot have a parent cost center"), raise_exception=1)
+			frappe.throw(_("Root cannot have a parent cost center"))
+			
+	def validate_accounts(self):
+		if self.is_group==1 and self.get("budgets"):
+			frappe.throw(_("Budget cannot be set for Group Cost Center"))
+			
+		check_acc_list = []
+		for d in self.get('budgets'):
+			if d.account:
+				account_details = frappe.db.get_value("Account", d.account, 
+					["is_group", "company", "root_type"], as_dict=1)
+				if account_details.is_group:
+					frappe.throw(_("Budget cannot be assigned against Group Account {0}").format(d.account))
+				elif account_details.company != self.company:
+					frappe.throw(_("Account {0} does not belongs to company {1}").format(d.account, self.company))
+				elif account_details.root_type != "Expense":
+					frappe.throw(_("Budget cannot be assigned against {0}, as it's not an Expense account")
+						.format(d.account))
+
+				if [d.account, d.fiscal_year] in check_acc_list:
+					frappe.throw(_("Account {0} has been entered more than once for fiscal year {1}")
+						.format(d.account, d.fiscal_year))
+				else:
+					check_acc_list.append([d.account, d.fiscal_year])
 
 	def convert_group_to_ledger(self):
 		if self.check_if_child_exists():
-			msgprint(_("Cannot convert Cost Center to ledger as it has child nodes"), raise_exception=1)
+			frappe.throw(_("Cannot convert Cost Center to ledger as it has child nodes"))
 		elif self.check_gle_exists():
-			msgprint(_("Cost Center with existing transactions can not be converted to ledger"), raise_exception=1)
+			frappe.throw(_("Cost Center with existing transactions can not be converted to ledger"))
 		else:
 			self.is_group = 0
 			self.save()
@@ -33,7 +59,7 @@
 
 	def convert_ledger_to_group(self):
 		if self.check_gle_exists():
-			msgprint(_("Cost Center with existing transactions can not be converted to group"), raise_exception=1)
+			frappe.throw(_("Cost Center with existing transactions can not be converted to group"))
 		else:
 			self.is_group = 1
 			self.save()
@@ -46,21 +72,6 @@
 		return frappe.db.sql("select name from `tabCost Center` where \
 			parent_cost_center = %s and docstatus != 2", self.name)
 
-	def validate_budget_details(self):
-		check_acc_list = []
-		for d in self.get('budgets'):
-			if self.is_group==1:
-				msgprint(_("Budget cannot be set for Group Cost Centers"), raise_exception=1)
-
-			if [d.account, d.fiscal_year] in check_acc_list:
-				msgprint(_("Account {0} has been entered more than once for fiscal year {1}").format(d.account, d.fiscal_year), raise_exception=1)
-			else:
-				check_acc_list.append([d.account, d.fiscal_year])
-
-	def validate(self):
-		self.validate_mandatory()
-		self.validate_budget_details()
-
 	def before_rename(self, olddn, newdn, merge=False):
 		# Add company abbr if not provided
 		from erpnext.setup.doctype.company.company import get_name_with_abbr
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.js b/erpnext/manufacturing/doctype/production_order/production_order.js
index 17fa202..151854c 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.js
+++ b/erpnext/manufacturing/doctype/production_order/production_order.js
@@ -262,7 +262,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 26af40a..c2cbbfd 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
@@ -325,22 +328,27 @@
 	
 	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):
 	res = frappe.db.sql("""select stock_uom, description
 		from `tabItem` where (ifnull(end_of_life, "0000-00-00")="0000-00-00" or end_of_life > now())
 		and name=%s""", item, as_dict=1)
-
 	if not res:
 		return {}
 
 	res = res[0]
 	res["bom_no"] = frappe.db.get_value("BOM", filters={"item": item, "is_default": 1})
+	if not res["bom_no"]:
+		variant_of= frappe.db.get_value("Item", item, "variant_of")
+		if variant_of:
+			res["bom_no"] = frappe.db.get_value("BOM", filters={"item": variant_of, "is_default": 1})
 	return res
 
 @frappe.whitelist()
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/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py
index 86a14d8..271abac 100644
--- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py
+++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py
@@ -9,6 +9,7 @@
 
 from frappe.model.document import Document
 from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
+from erpnext.manufacturing.doctype.production_order.production_order import get_item_details
 
 class ProductionPlanningTool(Document):
 	def __init__(self, arg1, arg2=None):
@@ -27,16 +28,7 @@
 		return ret
 
 	def get_item_details(self, item_code):
-		""" Pull other item details from item master"""
-
-		item = frappe.db.sql("""select description, stock_uom, default_bom
-			from `tabItem` where name = %s""", item_code, as_dict =1)
-		ret = {
-			'description'	: item and item[0]['description'],
-			'stock_uom'		: item and item[0]['stock_uom'],
-			'bom_no'		: item and item[0]['default_bom']
-		}
-		return ret
+		return get_item_details(item_code)
 
 	def clear_so_table(self):
 		self.set('sales_orders', [])
@@ -142,15 +134,14 @@
 		self.clear_item_table()
 
 		for p in items:
-			item_details = frappe.db.sql("""select description, stock_uom, default_bom
-				from tabItem where name=%s""", p['item_code'])
+			item_details = get_item_details(p['item_code'])
 			pi = self.append('items', {})
 			pi.sales_order				= p['parent']
 			pi.warehouse				= p['warehouse']
 			pi.item_code				= p['item_code']
-			pi.description				= item_details and item_details[0][0] or ''
-			pi.stock_uom				= item_details and item_details[0][1] or ''
-			pi.bom_no					= item_details and item_details[0][2] or ''
+			pi.description				= item_details and item_details.description or ''
+			pi.stock_uom				= item_details and item_details.stock_uom or ''
+			pi.bom_no					= item_details and item_details.bom_no or ''
 			pi.so_pending_qty			= flt(p['pending_qty'])
 			pi.planned_qty				= flt(p['pending_qty'])
 
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