Merge branch 'master' into develop
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 135814d..abd3be6 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__ = '11.1.5'
+__version__ = '11.1.6'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py
index 8a8e81b..e305652 100644
--- a/erpnext/accounts/deferred_revenue.py
+++ b/erpnext/accounts/deferred_revenue.py
@@ -60,7 +60,7 @@
 	deferred_account = "deferred_revenue_account" if doc.doctype=="Sales Invoice" else "deferred_expense_account"
 	last_gl_entry, skip = False, False
 
-	booking_end_date = getdate(add_days(today(), -1)) if not end_date else end_date
+	booking_end_date = getdate(add_days(today(), -1) if not end_date else end_date)
 	if booking_end_date < item.service_start_date or \
 		(item.service_stop_date and booking_end_date.month > item.service_stop_date.month):
 		return None, None, None, True
@@ -71,7 +71,7 @@
 		last_gl_entry = True
 		booking_end_date = item.service_stop_date
 
-	booking_start_date = getdate(add_months(today(), -1)) if not start_date else start_date
+	booking_start_date = getdate(add_months(today(), -1) if not start_date else start_date)
 	booking_start_date = booking_start_date \
 		if booking_start_date > item.service_start_date else item.service_start_date
 
@@ -113,7 +113,6 @@
 			group by voucher_detail_no
 		'''.format(total_credit_debit, total_credit_debit_currency),
 			(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
-
 		already_booked_amount = gl_entries_details[0].total_credit if gl_entries_details else 0
 		base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
 		if account_currency==doc.company_currency:
@@ -140,7 +139,7 @@
 			get_booking_dates(doc, item, start_date, end_date)
 
 		if skip: continue
-		total_days = date_diff(item.service_end_date, item.service_start_date)
+		total_days = date_diff(item.service_end_date, item.service_start_date) + 1
 		total_booking_days = date_diff(booking_end_date, booking_start_date) + 1
 
 		account_currency = get_account_currency(item.expense_account)
@@ -179,6 +178,10 @@
 				'project': project
 			}, account_currency)
 		)
-
 	if gl_entries:
-		make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True)
+		try:
+			make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True)
+			frappe.db.commit()
+		except:
+			frappe.db.rollback()
+			frappe.log_error(message = frappe.get_traceback(), title = _("Error while processing deferred accounting for {0}").format(doc.name))
\ No newline at end of file
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 8c3deaf..be66332 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -101,7 +101,7 @@
 					frappe.db.get_value(filters.party_type, filters.party[0], "default_currency"))
 
 		filters["account_currency"] = account_currency or filters.company_currency
-		if filters.account_currency != filters.company_currency:
+		if filters.account_currency != filters.company_currency and not filters.presentation_currency:
 			filters.presentation_currency = filters.account_currency
 
 	return filters
diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py
index a8ae94f..8a39744 100644
--- a/erpnext/accounts/report/utils.py
+++ b/erpnext/accounts/report/utils.py
@@ -104,7 +104,7 @@
 		credit_in_account_currency = flt(entry['credit_in_account_currency'])
 		account_currency = entry['account_currency']
 
-		if account_currency != presentation_currency or (account_currency == presentation_currency and not is_p_or_l_account(account)):
+		if account_currency != presentation_currency:
 			value = debit or credit
 
 			date = currency_info['report_date'] if not is_p_or_l_account(account) else entry['posting_date']
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index a9fcff8..1c9d977 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -615,7 +615,7 @@
 	return held_invoices
 
 
-def get_outstanding_invoices(party_type, party, account, condition=None, limit=1000):
+def get_outstanding_invoices(party_type, party, account, condition=None, limit=None):
 	outstanding_invoices = []
 	precision = frappe.get_precision("Sales Invoice", "outstanding_amount") or 2
 
@@ -628,7 +628,7 @@
 
 	invoice = 'Sales Invoice' if erpnext.get_party_account_type(party_type) == 'Receivable' else 'Purchase Invoice'
 	held_invoices = get_held_invoices(party_type, party)
-	limit_cond = "limit %s" % (limit or 1000)
+	limit_cond = "limit %s" % limit if limit else ""
 
 	invoice_list = frappe.db.sql("""
 		select
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index e72f59a..e79a2ac 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -459,7 +459,7 @@
 					items_dict = {
 						rm_item_code: {
 							"item_name": rm_item_data["item_name"],
-							"description": item_wh[rm_item_code].get('description'),
+							"description": item_wh.get(rm_item_code, {}).get('description', ""),
 							'qty': rm_item_data["qty"],
 							'from_warehouse': rm_item_data["warehouse"],
 							'stock_uom': rm_item_data["stock_uom"],
diff --git a/erpnext/buying/report/purchase_analytics/purchase_analytics.json b/erpnext/buying/report/purchase_analytics/purchase_analytics.json
index 996e3ee..7ce779d 100644
--- a/erpnext/buying/report/purchase_analytics/purchase_analytics.json
+++ b/erpnext/buying/report/purchase_analytics/purchase_analytics.json
@@ -1,12 +1,13 @@
 {
- "add_total_row": 0, 
+ "add_total_row": 1, 
  "creation": "2018-10-05 16:08:24.156448", 
+ "disable_prepared_report": 0, 
  "disabled": 0, 
  "docstatus": 0, 
  "doctype": "Report", 
  "idx": 0, 
  "is_standard": "Yes", 
- "modified": "2018-10-05 16:08:33.272201", 
+ "modified": "2019-02-12 14:32:29.107109", 
  "modified_by": "Administrator", 
  "module": "Buying", 
  "name": "Purchase Analytics", 
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 50d8ed2..f439588 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -276,8 +276,8 @@
 				item_dict[(d.item_code, d.material_request_item, d.warehouse)] = item_details
 			else:
 				item_details.update({
-					"qty":flt(item_dict.get((d.item_code, d.sales_order, d.warehouse),{})
-						.get("qty")) + flt(d.planned_qty)
+					"qty": flt(item_dict.get((d.item_code, d.sales_order, d.warehouse),{})
+						.get("qty")) + (flt(d.planned_qty) - flt(d.ordered_qty))
 				})
 				item_dict[(d.item_code, d.sales_order, d.warehouse)] = item_details
 
diff --git a/erpnext/manufacturing/report/production_analytics/production_analytics.json b/erpnext/manufacturing/report/production_analytics/production_analytics.json
index 023e0a8..946cd33 100644
--- a/erpnext/manufacturing/report/production_analytics/production_analytics.json
+++ b/erpnext/manufacturing/report/production_analytics/production_analytics.json
@@ -1,13 +1,14 @@
 {
- "add_total_row": 0, 
+ "add_total_row": 1, 
  "creation": "2018-10-11 19:28:37.085066", 
+ "disable_prepared_report": 0, 
  "disabled": 0, 
  "docstatus": 0, 
  "doctype": "Report", 
  "idx": 0, 
  "is_standard": "Yes", 
  "letter_head": "", 
- "modified": "2018-10-11 19:28:37.085066", 
+ "modified": "2019-02-12 14:32:16.392521", 
  "modified_by": "Administrator", 
  "module": "Manufacturing", 
  "name": "Production Analytics", 
diff --git a/erpnext/patches/v11_0/update_total_qty_field.py b/erpnext/patches/v11_0/update_total_qty_field.py
index fcb76af..992454a 100644
--- a/erpnext/patches/v11_0/update_total_qty_field.py
+++ b/erpnext/patches/v11_0/update_total_qty_field.py
@@ -19,9 +19,10 @@
 			SELECT
 				parent, SUM(qty) as qty
 			FROM
-				`tab%s Item`
+				`tab{0} Item`
+			where parenttype = '{0}'
 			GROUP BY parent
-		''' % (doctype), as_dict = True)
+		'''.format(doctype), as_dict = True)
 
 		# Query to update total_qty might become too big, Update in batches
 		# batch_size is chosen arbitrarily, Don't try too hard to reason about it
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index 8692440..3757315 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -18,7 +18,7 @@
 			return{
 				filters: {
 					'project': child.project,
-					'status': ["!=", "Closed"]
+					'status': ["!=", "Cancelled"]
 				}
 			}
 		}
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 3db5632..5da7e73 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -276,13 +276,11 @@
 	scan_barcode: function() {
 		let scan_barcode_field = this.frm.fields_dict["scan_barcode"];
 
-		let show_description = function(idx, item_code, exist=null) {
-			if(exist) {
-				scan_barcode_field.set_new_description(__('Row : ') + idx + ' ' +
-					item_code + __(' Qty increased by 1'));
+		let show_description = function(idx, exist = null) {
+			if (exist) {
+				scan_barcode_field.set_new_description(__('Row #{0}: Qty increased by 1', [idx]));
 			} else {
-				scan_barcode_field.set_new_description(__('New row : ') + idx + ' ' +
-					item_code + __('  Created'));
+				scan_barcode_field.set_new_description(__('Row #{0}: Item added', [idx]));
 			}
 		}
 
@@ -291,39 +289,39 @@
 				method: "erpnext.selling.page.point_of_sale.point_of_sale.search_serial_or_batch_or_barcode_number",
 				args: { search_value: this.frm.doc.scan_barcode }
 			}).then(r => {
-
-				if(r && r.message && r.message.item_code) {
-					let child = "";
-					let add_row_index = -1;
-					let cur_grid= this.frm.fields_dict["items"].grid;
-
-					this.frm.doc.items.map(d => {
-						if(d.item_code==r.message.item_code){
-							add_row_index = d.idx;
-							return;
-						} else if(!d.item_code && add_row_index==-1) {
-							add_row_index = d.idx;
-						}
-					});
-
-					if(add_row_index == -1) {
-						child = frappe.model.add_child(this.frm.doc, cur_grid.doctype, "items", add_row_index);
-					} else {
-						child = cur_grid.get_grid_row(add_row_index-1).doc;
-					}
-					show_description(child.idx, r.message.item_code, child.item_code);
-
-					frappe.model.set_value(child.doctype, child.name, {
-						item_code: r.message.item_code,
-						qty: (child.qty || 0) + 1,
-						barcode: r.message.barcode
-					});
+				const data = r && r.message;
+				if (!data) {
+					scan_barcode_field.set_new_description(__('Cannot find Item with this barcode'));
+					return;
 				}
-				else{
-					scan_barcode_field.set_new_description(this.frm.doc.scan_barcode +__(' does not exist!'));
+
+				let cur_grid = this.frm.fields_dict.items.grid;
+
+				let row_to_modify = null;
+				const existing_item_row = this.frm.doc.items.find(d => d.item_code === data.item_code);
+				const blank_item_row = this.frm.doc.items.find(d => !d.item_code);
+
+				if (existing_item_row) {
+					row_to_modify = existing_item_row;
+				} else if (blank_item_row) {
+					row_to_modify = blank_item_row;
 				}
+
+				if (!row_to_modify) {
+					// add new row
+					row_to_modify = frappe.model.add_child(this.frm.doc, cur_grid.doctype, 'items');
+				}
+
+				show_description(row_to_modify.idx, row_to_modify.item_code);
+
+				frappe.model.set_value(row_to_modify.doctype, row_to_modify.name, {
+					item_code: data.item_code,
+					qty: (row_to_modify.qty || 0) + 1
+				});
+
+				this.frm.refresh_field('items');
 			});
-			scan_barcode_field.set_value("");
+			scan_barcode_field.set_value('');
 		}
 		return false;
 	},
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index a6d723a..c5498c7 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -345,13 +345,14 @@
 	if company and tds_account:
 		accounts = [dict(company=company, account=tds_account)]
 
-	fiscal_year = get_fiscal_year(today(), company=accounts[0].get('company'))[0]
+	fiscal_year = get_fiscal_year(today(), company=company)[0]
 	docs = get_tds_details(accounts, fiscal_year)
 
 	for d in docs:
 		try:
 			doc = frappe.get_doc(d)
 			doc.flags.ignore_permissions = True
+			doc.flags.ignore_mandatory = True
 			doc.insert()
 		except frappe.DuplicateEntryError:
 			doc = frappe.get_doc("Tax Withholding Category", d.get("name"))
diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.py b/erpnext/selling/report/address_and_contacts/address_and_contacts.py
index a9e4303..eb242d0 100644
--- a/erpnext/selling/report/address_and_contacts/address_and_contacts.py
+++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.py
@@ -102,7 +102,8 @@
 	records = frappe.get_list(doctype, filters=filters, fields=fields, as_list=True)
 	for d in records:
 		details = party_details.get(d[0])
-		details.setdefault(frappe.scrub(doctype), []).append(d[1:])
+		if details:
+			details.setdefault(frappe.scrub(doctype), []).append(d[1:])
 
 	return party_details
 
diff --git a/erpnext/selling/report/sales_analytics/sales_analytics.json b/erpnext/selling/report/sales_analytics/sales_analytics.json
index 5c95f28..bd82302 100644
--- a/erpnext/selling/report/sales_analytics/sales_analytics.json
+++ b/erpnext/selling/report/sales_analytics/sales_analytics.json
@@ -1,12 +1,13 @@
 {
- "add_total_row": 0, 
+ "add_total_row": 1, 
  "creation": "2018-09-21 12:46:29.451048", 
+ "disable_prepared_report": 0, 
  "disabled": 0, 
  "docstatus": 0, 
  "doctype": "Report", 
  "idx": 0, 
  "is_standard": "Yes", 
- "modified": "2018-09-21 12:46:29.451048", 
+ "modified": "2019-02-12 14:30:40.043652", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Sales Analytics", 
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index a0d94bf..5669552 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -703,15 +703,14 @@
                         frappe.db.get_single_value('Item Variant Settings', 'do_not_update_variants'):
 			return
 		if self.has_variants:
-			updated = []
 			variants = frappe.db.get_all("Item", fields=["item_code"], filters={"variant_of": self.name})
-			for d in variants:
-				variant = frappe.get_doc("Item", d)
-				copy_attributes_to_variant(self, variant)
-				variant.save()
-				updated.append(d.item_code)
-			if updated:
-				frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))
+			if variants:
+				if len(variants) <= 30:
+					update_variants(variants, self, publish_progress=False)
+					frappe.msgprint(_("Item Variants updated"))
+				else:
+					frappe.enqueue("erpnext.stock.doctype.item.item.update_variants",
+						variants=variants, template=self, now=frappe.flags.in_test, timeout=600)
 
 	def validate_has_variants(self):
 		if not self.has_variants and frappe.db.get_value("Item", self.name, "has_variants"):
@@ -1000,3 +999,13 @@
 
 	return frappe.get_all("Item Attribute Value", fields = ["attribute_value"],
 		filters = {'parent': parent, 'attribute_value': ("like", "%%%s%%" % attribute_value)})
+
+def update_variants(variants, template, publish_progress=True):
+	count=0
+	for d in variants:
+		variant = frappe.get_doc("Item", d)
+		copy_attributes_to_variant(template, variant)
+		variant.save()
+		count+=1
+		if publish_progress:
+				frappe.publish_progress(count*100/len(variants), title = _("Updating Variants..."))
\ No newline at end of file
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 2a1a63e..3012d0b 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -297,8 +297,9 @@
 			total_completed_qty = flt(self.fg_completed_qty) + flt(prod_order.produced_qty)
 			completed_qty = d.completed_qty + (allowance_percentage/100 * d.completed_qty)
 			if total_completed_qty > flt(completed_qty):
-				frappe.throw(_("Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order # {3}. Please update operation status via Time Logs")
-					.format(d.idx, d.operation, total_completed_qty, self.work_order), OperationsNotCompleteError)
+				job_card = frappe.db.get_value('Job Card', {'operation_id': d.name}, 'name')
+				frappe.throw(_("Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order # {3}. Please update operation status via Job Card # {4}")
+					.format(d.idx, d.operation, total_completed_qty, self.work_order, job_card), OperationsNotCompleteError)
 
 	def check_duplicate_entry_for_work_order(self):
 		other_ste = [t[0] for t in frappe.db.get_values("Stock Entry",  {
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 3051d31..4561592 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -16,6 +16,9 @@
 
 from six import string_types, iteritems
 
+sales_doctypes = ['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']
+purchase_doctypes = ['Material Request', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
+
 @frappe.whitelist()
 def get_item_details(args):
 	"""
@@ -232,7 +235,7 @@
 
 	#Set the UOM to the Default Sales UOM or Default Purchase UOM if configured in the Item Master
 	if not args.uom:
-		if args.get('doctype') in ['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']:
+		if args.get('doctype') in sales_doctypes:
 			args.uom = item.sales_uom if item.sales_uom else item.stock_uom
 		elif (args.get('doctype') in ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']) or \
 			(args.get('doctype') == 'Material Request' and args.get('material_request_type') == 'Purchase'):
@@ -283,14 +286,15 @@
 		out.conversion_factor = 1.0
 	else:
 		out.conversion_factor = args.conversion_factor or \
-			get_conversion_factor(item.item_code, args.uom).get("conversion_factor")
+			get_conversion_factor(item.name, args.uom).get("conversion_factor")
 
 	args.conversion_factor = out.conversion_factor
 	out.stock_qty = out.qty * out.conversion_factor
 
 	# calculate last purchase rate
-	from erpnext.buying.doctype.purchase_order.purchase_order import item_last_purchase_rate
-	out.last_purchase_rate = item_last_purchase_rate(args.name, args.conversion_rate, item.item_code, out.conversion_factor)
+	if args.get('doctype') in purchase_doctypes:
+		from erpnext.buying.doctype.purchase_order.purchase_order import item_last_purchase_rate
+		out.last_purchase_rate = item_last_purchase_rate(args.name, args.conversion_rate, item.name, out.conversion_factor)
 
 	# if default specified in item is for another company, fetch from company
 	for d in [
diff --git a/erpnext/stock/report/stock_analytics/stock_analytics.json b/erpnext/stock/report/stock_analytics/stock_analytics.json
index efd5e99..7a2ed2b 100644
--- a/erpnext/stock/report/stock_analytics/stock_analytics.json
+++ b/erpnext/stock/report/stock_analytics/stock_analytics.json
@@ -1,12 +1,13 @@
 {
- "add_total_row": 0, 
+ "add_total_row": 1, 
  "creation": "2018-10-08 12:11:32.133020", 
+ "disable_prepared_report": 0, 
  "disabled": 0, 
  "docstatus": 0, 
  "doctype": "Report", 
  "idx": 0, 
  "is_standard": "Yes", 
- "modified": "2018-10-08 12:18:42.834270", 
+ "modified": "2019-02-12 14:32:22.874082", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Stock Analytics",