Merge pull request #16514 from sagarvora/changelog

docs: changelog for v11.0.4
diff --git a/.gitignore b/.gitignore
index 68272c7..1652244 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@
 *.swo
 __pycache__
 *~
+node_modules/
\ No newline at end of file
diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py
index 2ff2644..9ff8b04 100644
--- a/erpnext/accounts/deferred_revenue.py
+++ b/erpnext/accounts/deferred_revenue.py
@@ -29,7 +29,7 @@
 			if date_diff(item.service_stop_date, item.service_end_date) > 0:
 				frappe.throw(_("Service Stop Date cannot be after Service End Date"))
 
-		if old_stop_dates and old_stop_dates[item.name] and item.service_stop_date!=old_stop_dates[item.name]:
+		if old_stop_dates and old_stop_dates.get(item.name) and item.service_stop_date!=old_stop_dates[item.name]:
 			frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx)))
 
 def convert_deferred_expense_to_expense(start_date=None, end_date=None):
diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
index a00aebe..d80bc7f 100644
--- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
+++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
@@ -9,6 +9,8 @@
 
 from frappe.model.document import Document
 
+class FiscalYearIncorrectDate(frappe.ValidationError): pass
+
 class FiscalYear(Document):
 	def set_as_default(self):
 		frappe.db.set_value("Global Defaults", None, "current_fiscal_year", self.name)
@@ -35,11 +37,14 @@
 
 	def validate_dates(self):
 		if getdate(self.year_start_date) > getdate(self.year_end_date):
-			frappe.throw(_("Fiscal Year Start Date should not be greater than Fiscal Year End Date"))
+			frappe.throw(_("Fiscal Year Start Date should be one year earlier than Fiscal Year End Date"),
+				FiscalYearIncorrectDate)
 
-		if (getdate(self.year_end_date) - getdate(self.year_start_date)).days > 366:
-			date = getdate(self.year_start_date) + relativedelta(years=1) - relativedelta(days=1)
-			self.year_end_date = date.strftime("%Y-%m-%d")
+		date = getdate(self.year_start_date) + relativedelta(years=1) - relativedelta(days=1)
+
+		if getdate(self.year_end_date) != date:
+			frappe.throw(_("Fiscal Year End Date should be one year after Fiscal Year Start Date"),
+				FiscalYearIncorrectDate)
 
 	def on_update(self):
 		check_duplicate_fiscal_year(self)
diff --git a/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py
index 5f90bb3..f7b7782 100644
--- a/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py
+++ b/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py
@@ -5,6 +5,8 @@
 
 import frappe, unittest
 
+from erpnext.accounts.doctype.fiscal_year.fiscal_year import FiscalYearIncorrectDate
+
 test_records = frappe.get_test_records('Fiscal Year')
 test_ignore = ["Company"]
 
@@ -12,12 +14,12 @@
 	def test_extra_year(self):
 		if frappe.db.exists("Fiscal Year", "_Test Fiscal Year 2000"):
 			frappe.delete_doc("Fiscal Year", "_Test Fiscal Year 2000")
+
 		fy = frappe.get_doc({
 			"doctype": "Fiscal Year",
 			"year": "_Test Fiscal Year 2000",
 			"year_end_date": "2002-12-31",
 			"year_start_date": "2000-04-01"
 		})
-		fy.insert()
-		self.assertEqual(fy.year_end_date, '2001-03-31')
 
+		self.assertRaises(FiscalYearIncorrectDate, fy.insert)
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 57a1cc25..2317634 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -189,7 +189,8 @@
 						"currency": self.currency,
 						"conversion_rate": self.conversion_rate or 1,
 						"conversion_factor": arg.get("conversion_factor") or 1,
-						"plc_conversion_rate": 1
+						"plc_conversion_rate": 1,
+						"ignore_party": True
 					})
 					item_doc = frappe.get_doc("Item", arg.get("item_code"))
 					out = frappe._dict()
@@ -213,7 +214,7 @@
 		existing_bom_cost = self.total_cost
 
 		for d in self.get("items"):
-			d.rate = self.get_rm_rate({
+			rate = self.get_rm_rate({
 				"item_code": d.item_code,
 				"bom_no": d.bom_no,
 				"qty": d.qty,
@@ -221,6 +222,8 @@
 				"stock_uom": d.stock_uom,
 				"conversion_factor": d.conversion_factor
 			})
+			if rate:
+				d.rate = rate
 			d.amount = flt(d.rate) * flt(d.qty)
 
 		if self.docstatus == 1:
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 9db04cd..ec1031c 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -424,7 +424,7 @@
 				frappe.msgprint(_("Item Price added for {0} in Price List {1}").format(args.item_code,
 					args.price_list), alert=True)
 
-def get_item_price(args, item_code):
+def get_item_price(args, item_code, ignore_party=False):
 	"""
 		Get name, price_list_rate from Item Price based on conditions
 			Check if the Derised qty is within the increment of the packing list.
@@ -434,17 +434,19 @@
 	"""
 
 	args['item_code'] = item_code
-	conditions = "where (customer is null or customer = '') and (supplier is null or supplier = '')"
-	if args.get("customer"):
-		conditions = "where customer=%(customer)s"
 
-	if args.get("supplier"):
-		conditions = "where supplier=%(supplier)s"
-
-	conditions += """ and item_code=%(item_code)s
+	conditions = """where item_code=%(item_code)s
 		and price_list=%(price_list)s
 		and ifnull(uom, '') in ('', %(uom)s)"""
 
+	if not ignore_party:
+		if args.get("customer"):
+			conditions += " and customer=%(customer)s"
+		elif args.get("supplier"):
+			conditions += " and supplier=%(supplier)s"
+		else:
+			conditions += " and (customer is null or customer = '') and (supplier is null or supplier = '')"
+
 	if args.get('min_qty'):
 		conditions += " and ifnull(min_qty, 0) <= %(min_qty)s"
 
@@ -490,10 +492,10 @@
 		for field in ["customer", "supplier", "min_qty"]:
 			del item_price_args[field]
 
-		general_price_list_rate = get_item_price(item_price_args, item_code)
+		general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party"))
 		if not general_price_list_rate and args.get("uom") != args.get("stock_uom"):
 			item_price_args["args"] = args.get("stock_uom")
-			general_price_list_rate = get_item_price(item_price_args, item_code)
+			general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party"))
 
 		if general_price_list_rate:
 			item_price_data = general_price_list_rate