Merge branch 'staging-fixes' into company_address
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 4197d54..b9b5347 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
 from erpnext.hooks import regional_overrides
 from frappe.utils import getdate
 
-__version__ = '10.1.76'
+__version__ = '10.1.77'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js
index c18057e..779cd61 100644
--- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js
+++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js
@@ -39,6 +39,8 @@
 					});
 					frm.events.get_total_gain_loss(frm);
 					refresh_field("accounts");
+				} else {
+					frappe.msgprint(__("No records found"));
 				}
 			}
 		});
diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py
index ae77516..cdfe34b 100644
--- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py
+++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py
@@ -67,17 +67,19 @@
 				and account_currency != %s
 			order by name""",(self.company, company_currency))
 
-		account_details = frappe.db.sql("""
-			select 
-				account, party_type, party, account_currency,
-				sum(debit_in_account_currency) - sum(credit_in_account_currency) as balance_in_account_currency,
-				sum(debit) - sum(credit) as balance
-			from `tabGL Entry`
-			where account in (%s)
-			group by account, party_type, party
-			having sum(debit) != sum(credit)
-			order by account
-		""" % ', '.join(['%s']*len(accounts)), tuple(accounts), as_dict=1)
+		account_details = []
+		if accounts:
+			account_details = frappe.db.sql("""
+				select
+					account, party_type, party, account_currency,
+					sum(debit_in_account_currency) - sum(credit_in_account_currency) as balance_in_account_currency,
+					sum(debit) - sum(credit) as balance
+				from `tabGL Entry`
+				where account in (%s)
+				group by account, party_type, party
+				having sum(debit) != sum(credit)
+				order by account
+			""" % ', '.join(['%s']*len(accounts)), tuple(accounts), as_dict=1)
 
 		return account_details
 
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index e6fe6ca..810b6f7 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -18,15 +18,14 @@
 		self.flags.ignore_submit_comment = True
 		self.check_mandatory()
 		self.validate_and_set_fiscal_year()
+		self.pl_must_have_cost_center()
+		self.validate_cost_center()
 
 		if not self.flags.from_repost:
-			self.pl_must_have_cost_center()
 			self.check_pl_account()
-			self.validate_cost_center()
 			self.validate_party()
 			self.validate_currency()
 
-
 	def on_update_with_args(self, adv_adj, update_outstanding = 'Yes', from_repost=False):
 		if not from_repost:
 			self.validate_account_details(adv_adj)
diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py
index 2ed664c..7ecc695 100644
--- a/erpnext/accounts/report/gross_profit/gross_profit.py
+++ b/erpnext/accounts/report/gross_profit/gross_profit.py
@@ -200,7 +200,7 @@
 
 	def skip_row(self, row, product_bundles):
 		if self.filters.get("group_by") != "Invoice":
-			if not row.get(scrub(self.filters.get("group_by"))):
+			if not row.get(scrub(self.filters.get("group_by", ""))):
 				return True
 		elif row.get("is_return") == 1:
 			return True
@@ -316,7 +316,7 @@
 					on `tabSales Invoice Item`.parent = `tabSales Invoice`.name
 				{sales_team_table}
 			where
-				`tabSales Invoice`.docstatus=1 {conditions} {match_cond}
+				`tabSales Invoice`.docstatus=1 and `tabSales Invoice`.is_opening!='Yes' {conditions} {match_cond}
 			order by
 				`tabSales Invoice`.posting_date desc, `tabSales Invoice`.posting_time desc"""
 			.format(conditions=conditions, sales_person_cols=sales_person_cols,
diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json
index 5296e22..6b3c3cc73 100644
--- a/erpnext/assets/doctype/asset/asset.json
+++ b/erpnext/assets/doctype/asset/asset.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_events_in_timeline": 0,
  "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 1, 
@@ -154,7 +155,7 @@
    "columns": 0, 
    "fetch_from": "item_code.asset_category", 
    "fieldname": "asset_category", 
-   "fieldtype": "Read Only", 
+   "fieldtype": "Link",
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
@@ -165,12 +166,12 @@
    "label": "Asset Category", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "", 
+   "options": "Asset Category",
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
    "print_hide_if_no_value": 0, 
-   "read_only": 0, 
+   "read_only": 1,
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -1881,7 +1882,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-08-21 14:44:24.507215", 
+ "modified": "2019-01-15 16:12:48.314196",
  "modified_by": "Administrator", 
  "module": "Assets", 
  "name": "Asset", 
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 24ce7d4..9bf3858 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -499,7 +499,8 @@
 	conditions = ""
 	warehouse = row.source_warehouse or row.default_warehouse or row.warehouse
 	if warehouse:
-		conditions = " and warehouse='{0}'".format(frappe.db.escape(warehouse))
+		lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"])
+		conditions = " and exists(select name from `tabWarehouse` where lft >= {0} and rgt <= {1} and name=`tabBin`.warehouse)".format(lft, rgt)
 
 	item_projected_qty = frappe.db.sql(""" select ifnull(sum(projected_qty),0) as projected_qty,
 		ifnull(sum(actual_qty),0) as actual_qty from `tabBin`
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index af2463f..082f887 100755
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -1,9 +1,9 @@
 execute:import unidecode # new requirement
 erpnext.patches.v8_0.move_perpetual_inventory_setting
+erpnext.patches.v11_0.rename_production_order_to_work_order
 erpnext.patches.v11_0.refactor_naming_series
 erpnext.patches.v11_0.refactor_autoname_naming
 erpnext.patches.v10_0.rename_schools_to_education
-erpnext.patches.v11_0.rename_production_order_to_work_order
 erpnext.patches.v4_0.validate_v3_patch
 erpnext.patches.v4_0.fix_employee_user_id
 erpnext.patches.v4_0.remove_employee_role_if_no_employee
diff --git a/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py b/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py
index 8313096..52d4621 100644
--- a/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py
+++ b/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py
@@ -1,3 +1,4 @@
+from __future__ import unicode_literals
 import frappe
 from frappe.model.rename_doc import rename_doc
 from frappe.model.utils.rename_field import rename_field
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 649d73a..371fc5c 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -12,6 +12,7 @@
 
 
 class CircularReferenceError(frappe.ValidationError): pass
+class EndDateCannotBeGreaterThanProjectEndDateError(frappe.ValidationError): pass
 
 class Task(NestedSet):
 	nsm_parent_field = 'parent_task'
@@ -43,6 +44,12 @@
 		if self.act_start_date and self.act_end_date and getdate(self.act_start_date) > getdate(self.act_end_date):
 			frappe.throw(_("'Actual Start Date' can not be greater than 'Actual End Date'"))
 
+		if(self.project):
+			if frappe.db.exists("Project", self.project):
+				expected_end_date = frappe.db.get_value("Project", self.project, "expected_end_date")
+				if  self.exp_end_date and expected_end_date and getdate(self.exp_end_date) > getdate(expected_end_date) :
+					frappe.throw(_("Expected end date cannot be after Project: <b>'{0}'</b> Expected end date").format(self.project), EndDateCannotBeGreaterThanProjectEndDateError)
+
 	def validate_status(self):
 		if self.status!=self.get_db_value("status") and self.status == "Closed":
 			for d in self.depends_on:
diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py
index 0966b76..6fb5412 100644
--- a/erpnext/projects/doctype/task/test_task.py
+++ b/erpnext/projects/doctype/task/test_task.py
@@ -5,11 +5,11 @@
 import unittest
 from frappe.utils import getdate, nowdate, add_days
 
-from erpnext.projects.doctype.task.task import CircularReferenceError
+from erpnext.projects.doctype.task.task import CircularReferenceError, EndDateCannotBeGreaterThanProjectEndDateError
 
 class TestTask(unittest.TestCase):
 	def test_circular_reference(self):
-		task1 = create_task("_Test Task 1", nowdate(), add_days(nowdate(), 10))
+		task1 = create_task("_Test Task 1", add_days(nowdate(), -15), add_days(nowdate(), -10))
 		task2 = create_task("_Test Task 2", add_days(nowdate(), 11), add_days(nowdate(), 15), task1.name)
 		task3 = create_task("_Test Task 3", add_days(nowdate(), 11), add_days(nowdate(), 15), task2.name)
 
@@ -97,7 +97,16 @@
 
 		self.assertEqual(frappe.db.get_value("Task", task.name, "status"), "Overdue")
 
-def create_task(subject, start=None, end=None, depends_on=None, project=None):
+	def test_end_date_validation(self):
+		task_end = create_task("Testing_Enddate_validation", add_days(nowdate(), 35), add_days(nowdate(), 45), save=False)
+		pro = frappe.get_doc("Project", task_end.project)
+		pro.expected_end_date = add_days(nowdate(), 40)
+		pro.save()
+		self.assertRaises(EndDateCannotBeGreaterThanProjectEndDateError, task_end.save)
+
+
+
+def create_task(subject, start=None, end=None, depends_on=None, project=None, save=True):
 	if not frappe.db.exists("Task", subject):
 		task = frappe.new_doc('Task')
 		task.status = "Open"
@@ -105,7 +114,8 @@
 		task.exp_start_date = start or nowdate()
 		task.exp_end_date = end or nowdate()
 		task.project = project or "_Test Project"
-		task.save()
+		if save:
+			task.save()
 	else:
 		task = frappe.get_doc("Task", subject)
 
@@ -113,6 +123,7 @@
 		task.append("depends_on", {
 			"task": depends_on
 		})
-		task.save()
+		if save:
+			task.save()
 
 	return task
\ No newline at end of file
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 035c58d..9dd9beb 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -416,6 +416,7 @@
 							item_code: item.item_code,
 							barcode: item.barcode,
 							serial_no: item.serial_no,
+							set_warehouse: me.frm.doc.set_warehouse,
 							warehouse: item.warehouse,
 							customer: me.frm.doc.customer,
 							supplier: me.frm.doc.supplier,
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index ea600e4..78aeee7 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -11,22 +11,49 @@
 	if not hasattr(doc, 'gstin'):
 		return
 
-	if doc.gstin:
-		doc.gstin = doc.gstin.upper()
-		if doc.gstin not in ["NA", "na"]:
-			p = re.compile("[0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9a-zA-Z]{1}")
-			if not p.match(doc.gstin):
-				frappe.throw(_("Invalid GSTIN or Enter NA for Unregistered"))
+	doc.gstin = doc.gstin.upper().strip()
+	if not doc.gstin or doc.gstin == 'NA':
+		return
+
+	if len(doc.gstin) != 15:
+		frappe.throw(_("Invalid GSTIN! A GSTIN must have 15 characters."))
+
+	p = re.compile("^[0-9]{2}[A-Z]{4}[0-9A-Z]{1}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[1-9A-Z]{1}[0-9A-Z]{1}$")
+	if not p.match(doc.gstin):
+		frappe.throw(_("Invalid GSTIN! The input you've entered doesn't match the format of GSTIN."))
+
+	validate_gstin_check_digit(doc.gstin)
 
 	if not doc.gst_state:
-		if doc.state in states:
-			doc.gst_state = doc.state
+		if not doc.state:
+			return
+		state = doc.state.lower()
+		states_lowercase = {s.lower():s for s in states}
+		if state in states_lowercase:
+			doc.gst_state = states_lowercase[state]
+		else:
+			return
 
-	if doc.gst_state:
-		doc.gst_state_number = state_numbers[doc.gst_state]
-		if doc.gstin and doc.gstin != "NA" and doc.gst_state_number != doc.gstin[:2]:
-			frappe.throw(_("First 2 digits of GSTIN should match with State number {0}")
-				.format(doc.gst_state_number))
+	doc.gst_state_number = state_numbers[doc.gst_state]
+	if doc.gst_state_number != doc.gstin[:2]:
+		frappe.throw(_("Invalid GSTIN! First 2 digits of GSTIN should match with State number {0}.")
+			.format(doc.gst_state_number))
+
+def validate_gstin_check_digit(gstin):
+	''' Function to validate the check digit of the GSTIN.'''
+	factor = 1
+	total = 0
+	code_point_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+	mod = len(code_point_chars)
+	input_chars = gstin[:-1]
+	for char in input_chars:
+		digit = factor * code_point_chars.find(char)
+		digit = (digit // mod) + (digit % mod)
+		total += digit
+		factor = 2 if factor == 1 else 1
+	if gstin[-1] != code_point_chars[((mod - (total % mod)) % mod)]:
+		frappe.throw(_("Invalid GSTIN! The check digit validation has failed. " +
+			"Please ensure you've typed the GSTIN correctly."))
 
 def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
 	if frappe.get_meta(item_doctype).has_field('gst_hsn_code'):
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 0da8272..2970d7a 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -177,6 +177,11 @@
 				frappe.throw(_("""New credit limit is less than current outstanding amount for the customer. Credit limit has to be atleast {0}""").format(outstanding_amt))
 
 	def on_trash(self):
+		if self.customer_primary_contact:
+			frappe.db.sql("""update `tabCustomer`
+				set customer_primary_contact=null, mobile_no=null, email_id=null
+				where name=%s""", self.name)
+
 		delete_contact_and_address('Customer', self.name)
 		if self.lead_name:
 			frappe.db.sql("update `tabLead` set status='Interested' where name=%s", self.lead_name)
diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py
index cc2fc59..fa4f835 100644
--- a/erpnext/selling/doctype/customer/test_customer.py
+++ b/erpnext/selling/doctype/customer/test_customer.py
@@ -98,6 +98,15 @@
 
 		so.save()
 
+	def test_delete_customer_contact(self):
+		customer = frappe.get_doc(
+			get_customer_dict('_Test Customer for delete')).insert(ignore_permissions=True)
+
+		customer.mobile_no = "8989889890"
+		customer.save()
+		self.assertTrue(customer.customer_primary_contact)
+		frappe.delete_doc('Customer', customer.name)
+
 	def test_disabled_customer(self):
 		make_test_records("Item")
 
diff --git a/erpnext/selling/report/sales_analytics/sales_analytics.py b/erpnext/selling/report/sales_analytics/sales_analytics.py
index c078a08..3239fc6 100644
--- a/erpnext/selling/report/sales_analytics/sales_analytics.py
+++ b/erpnext/selling/report/sales_analytics/sales_analytics.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _, scrub
-from frappe.utils import getdate, flt
+from frappe.utils import getdate, flt, add_to_date, add_days
 from six import iteritems
 from erpnext.accounts.utils import get_fiscal_year
 
@@ -40,7 +40,7 @@
 				"fieldtype": "Data",
 				"width": 140
 			})
-		for dummy, end_date in self.periodic_daterange:
+		for end_date in self.periodic_daterange:
 			period = self.get_period(end_date)
 			self.columns.append({
 				"label": _(period),
@@ -169,7 +169,7 @@
 				"entity_name": self.entity_names.get(entity)
 			}
 			total = 0
-			for dummy, end_date in self.periodic_daterange:
+			for end_date in self.periodic_daterange:
 				period = self.get_period(end_date)
 				amount = flt(period_data.get(period, 0.0))
 				row[scrub(period)] = amount
@@ -188,7 +188,7 @@
 				"indent": self.depth_map.get(d.name)
 			}
 			total = 0
-			for dummy, end_date in self.periodic_daterange:
+			for end_date in self.periodic_daterange:
 				period = self.get_period(end_date)
 				amount = flt(self.entity_periodic_data.get(d.name, {}).get(period, 0.0))
 				row[scrub(period)] = amount
@@ -219,12 +219,11 @@
 			period = "Quarter " + str(((posting_date.month-1)//3)+1) +" " + str(posting_date.year)
 		else:
 			year = get_fiscal_year(posting_date, company=self.filters.company)
-			period = str(year[2])
-
+			period = str(year[0])
 		return period
 
 	def get_period_date_ranges(self):
-		from dateutil.relativedelta import relativedelta
+		from dateutil.relativedelta import relativedelta, MO
 		from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date)
 
 		increment = {
@@ -234,18 +233,26 @@
 			"Yearly": 12
 		}.get(self.filters.range, 1)
 
+		if self.filters.range in ['Monthly', 'Quarterly']:
+			from_date = from_date.replace(day = 1)
+		elif self.filters.range == "Yearly":
+			from_date = get_fiscal_year(from_date)[1]
+		else:
+			from_date = from_date + relativedelta(from_date, weekday=MO(-1))
+
 		self.periodic_daterange = []
-		for dummy in range(1, 53, increment):
+		for dummy in range(1, 53):
 			if self.filters.range == "Weekly":
-				period_end_date = from_date + relativedelta(days=6)
+				period_end_date = add_days(from_date, 6)
 			else:
-				period_end_date = from_date + relativedelta(months=increment, days=-1)
+				period_end_date = add_to_date(from_date, months=increment, days=-1)
 
 			if period_end_date > to_date:
 				period_end_date = to_date
-			self.periodic_daterange.append([from_date, period_end_date])
 
-			from_date = period_end_date + relativedelta(days=1)
+			self.periodic_daterange.append(period_end_date)
+
+			from_date = add_days(period_end_date, 1)
 			if period_end_date == to_date:
 				break
 
diff --git a/erpnext/setup/default_success_action.py b/erpnext/setup/default_success_action.py
index e8494a1..6c2a97a 100644
--- a/erpnext/setup/default_success_action.py
+++ b/erpnext/setup/default_success_action.py
@@ -1,3 +1,4 @@
+from __future__ import unicode_literals
 from frappe import _
 
 doctype_list = [
diff --git a/erpnext/setup/doctype/company/company_dashboard.py b/erpnext/setup/doctype/company/company_dashboard.py
index 6133226..5efcf38 100644
--- a/erpnext/setup/doctype/company/company_dashboard.py
+++ b/erpnext/setup/doctype/company/company_dashboard.py
@@ -13,7 +13,7 @@
 			'goal_doctype_link': 'company',
 			'goal_field': 'base_grand_total',
 			'date_field': 'posting_date',
-			'filter_str': 'docstatus = 1',
+			'filter_str': "docstatus = 1 and is_opening != 'Yes'",
 			'aggregation': 'sum'
 		},
 
diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py
index 6bc9036..f258f7d 100644
--- a/erpnext/setup/doctype/item_group/item_group.py
+++ b/erpnext/setup/doctype/item_group/item_group.py
@@ -136,7 +136,10 @@
 			rgt = ('<', item_group.rgt),
 		),
 		or_filters = search_filters,
-		order_by = 'weightage desc, name asc')
+		order_by = 'weightage desc, name asc',
+		start = start,
+		limit = limit
+	)
 
 	return [get_item_for_list_in_html(r) for r in data]
 
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index 212bb51..bc991b4 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -10,7 +10,9 @@
 from erpnext.accounts.utils import get_stock_and_account_difference
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
 from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after
-from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError
+from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError, get_items
+from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
+from erpnext.stock.doctype.item.test_item import make_item
 
 class TestStockReconciliation(unittest.TestCase):
 	def setUp(self):
@@ -79,6 +81,17 @@
 
 			set_perpetual_inventory(0)
 
+	def test_get_items(self):
+		create_warehouse("_Test Warehouse Group 1", {"is_group": 1})
+		create_warehouse("_Test Warehouse Ledger 1", {"is_group": 0, "parent_warehouse": "_Test Warehouse Group 1 - _TC"})
+		make_item("_Test Stock Reco Item", {"default_warehouse": "_Test Warehouse Ledger 1 - _TC",
+			"is_stock_item": 1, "opening_stock": 100, "valuation_rate": 100})
+
+		items = get_items("_Test Warehouse Group 1 - _TC", nowdate(), nowtime())
+
+		self.assertEqual(["_Test Stock Reco Item", "_Test Warehouse Ledger 1 - _TC", 100],
+			[items[0]["item_code"], items[0]["warehouse"], items[0]["qty"]])
+
 	def insert_existing_sle(self):
 		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
 
diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.py b/erpnext/stock/doctype/warehouse/test_warehouse.py
index 006945e..b033f86 100644
--- a/erpnext/stock/doctype/warehouse/test_warehouse.py
+++ b/erpnext/stock/doctype/warehouse/test_warehouse.py
@@ -90,7 +90,7 @@
 		self.assertTrue(frappe.db.get_value("Warehouse",
 			filters={"account": "Test Warehouse for Merging 2 - _TC"}))
 
-def create_warehouse(warehouse_name):
+def create_warehouse(warehouse_name, properties=None):
 	if not frappe.db.exists("Warehouse", warehouse_name + " - _TC"):
 		w = frappe.new_doc("Warehouse")
 		w.warehouse_name = warehouse_name
@@ -98,11 +98,13 @@
 		w.company = "_Test Company"
 		make_account_for_warehouse(warehouse_name, w)
 		w.account = warehouse_name + " - _TC"
+		if properties:
+			w.update(properties)
 		w.save()
 
 def make_account_for_warehouse(warehouse_name, warehouse_obj):
 	if not frappe.db.exists("Account", warehouse_name + " - _TC"):
-		parent_account = frappe.db.get_value('Account', 
+		parent_account = frappe.db.get_value('Account',
 			{'company': warehouse_obj.company, 'is_group':1, 'account_type': 'Stock'},'name')
 		account = create_account(account_name=warehouse_name, \
 				account_type="Stock", parent_account= parent_account, company=warehouse_obj.company)
\ No newline at end of file
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 692fe5d..bbea904 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -36,6 +36,7 @@
 			"is_subcontracted": "Yes" / "No",
 			"ignore_pricing_rule": 0/1
 			"project": ""
+			"set_warehouse": ""
 		}
 	"""
 	args = process_args(args)
@@ -189,7 +190,6 @@
 			"project": "",
 			barcode: "",
 			serial_no: "",
-			warehouse: "",
 			currency: "",
 			update_stock: "",
 			price_list: "",
@@ -219,7 +219,7 @@
 	item_defaults = get_item_defaults(item.name, args.company)
 	item_group_defaults = get_item_group_defaults(item.name, args.company)
 
-	warehouse = user_default_warehouse or item_defaults.get("default_warehouse") or\
+	warehouse = args.get("set_warehouse") or user_default_warehouse or item_defaults.get("default_warehouse") or\
 		item_group_defaults.get("default_warehouse") or args.warehouse
 
 	if args.get('doctype') == "Material Request" and not args.get('material_request_type'):
@@ -273,7 +273,7 @@
 		"transaction_date": args.get("transaction_date")
 	})
 
-	if item.enable_deferred_revenue:
+	if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
 		out.update(calculate_service_end_date(args, item))
 
 	# calculate conversion factor
@@ -310,9 +310,15 @@
 	if not item:
 		item = frappe.get_cached_doc("Item", args.item_code)
 
-	enable_deferred = "enable_deferred_revenue" if args.doctype=="Sales Invoice" else "enable_deferred_expense"
-	no_of_months = "no_of_months" if args.doctype=="Sales Invoice" else "no_of_months_exp"
-	account = "deferred_revenue_account" if args.doctype=="Sales Invoice" else "deferred_expense_account"
+	doctype = args.get("parenttype") or args.get("doctype")
+	if doctype == "Sales Invoice":
+		enable_deferred = "enable_deferred_revenue"
+		no_of_months = "no_of_months"
+		account = "deferred_revenue_account"
+	else:
+		enable_deferred = "enable_deferred_expense"
+		no_of_months = "no_of_months_exp"
+		account = "deferred_expense_account"
 
 	service_start_date = args.service_start_date if args.service_start_date else args.transaction_date
 	service_end_date = add_months(service_start_date, item.get(no_of_months))
@@ -336,7 +342,7 @@
 		or args.expense_account)
 
 def get_default_deferred_account(args, item, fieldname=None):
-	if item.enable_deferred_revenue:
+	if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
 		return (item.get(fieldname)
 			or args.get(fieldname)
 			or frappe.get_cached_value('Company',  args.company,  "default_"+fieldname))
@@ -370,16 +376,16 @@
 
 		price_list_rate = get_price_list_rate_for(args, item_doc.name) or 0
 
+		# variant
+		if not price_list_rate and item_doc.variant_of:
+			price_list_rate = get_price_list_rate_for(args, item_doc.variant_of)
+
 		# insert in database
 		if not price_list_rate:
 			if args.price_list and args.rate:
 				insert_item_price(args)
 			return {}
 
-		# variant
-		if not price_list_rate and item_doc.variant_of:
-			price_list_rate = get_price_list_rate_for(args, item_doc.variant_of)
-
 		out.price_list_rate = flt(price_list_rate) * flt(args.plc_conversion_rate) \
 			/ flt(args.conversion_rate)