Merge branch 'staging-fixes' into staging
diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py
new file mode 100644
index 0000000..61fc211
--- /dev/null
+++ b/erpnext/accounts/deferred_revenue.py
@@ -0,0 +1,179 @@
+from __future__ import unicode_literals
+
+import frappe
+from frappe import _
+from frappe.utils import date_diff, add_months, today, getdate, add_days, flt
+from erpnext.accounts.utils import get_account_currency
+from erpnext.accounts.general_ledger import make_gl_entries
+
+def validate_service_stop_date(doc):
+	''' Validates service_stop_date for Purchase Invoice and Sales Invoice '''
+
+	enable_check = "enable_deferred_revenue" \
+		if doc.doctype=="Sales Invoice" else "enable_deferred_expense"
+
+	old_stop_dates = {}
+	old_doc = frappe.db.get_all("{0} Item".format(doc.doctype),
+		{"parent": doc.name}, ["name", "service_stop_date"])
+
+	for d in old_doc:
+		old_stop_dates[d.name] = d.service_stop_date or ""
+
+	for item in doc.items:
+		if not item.get(enable_check): continue
+
+		if item.service_stop_date:
+			if date_diff(item.service_stop_date, item.service_start_date) < 0:
+				frappe.throw(_("Service Stop Date cannot be before Service Start Date"))
+
+			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]:
+			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):
+	# check for the purchase invoice for which GL entries has to be done
+	invoices = frappe.db.sql_list('''
+		select parent from `tabPurchase Invoice Item` where service_start_date<=%s and service_end_date>=%s
+		and enable_deferred_expense = 1 and docstatus = 1
+	''', (end_date or today(), start_date or add_months(today(), -1)))
+
+	# For each invoice, book deferred expense
+	for invoice in invoices:
+		doc = frappe.get_doc("Purchase Invoice", invoice)
+		book_deferred_income_or_expense(doc, start_date, end_date)
+
+def convert_deferred_revenue_to_income(start_date=None, end_date=None):
+	# check for the sales invoice for which GL entries has to be done
+	invoices = frappe.db.sql_list('''
+		select parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s
+		and enable_deferred_revenue = 1 and docstatus = 1
+	''', (end_date or today(), start_date or add_months(today(), -1)))
+
+	# For each invoice, book deferred revenue
+	for invoice in invoices:
+		doc = frappe.get_doc("Sales Invoice", invoice)
+		book_deferred_income_or_expense(doc, start_date, end_date)
+
+def get_booking_dates(doc, item, start_date=None, end_date=None):
+	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
+	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
+	elif booking_end_date >= item.service_end_date:
+		last_gl_entry = True
+		booking_end_date = item.service_end_date
+	elif item.service_stop_date and item.service_stop_date <= booking_end_date:
+		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 = booking_start_date \
+		if booking_start_date > item.service_start_date else item.service_start_date
+
+	prev_gl_entry = frappe.db.sql('''
+		select name, posting_date from `tabGL Entry` where company=%s and account=%s and
+		voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
+		order by posting_date desc limit 1
+	''', (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
+
+	if not prev_gl_entry and item.service_start_date < booking_start_date:
+		booking_start_date = item.service_start_date
+	elif prev_gl_entry:
+		booking_start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
+		skip = True if booking_start_date > booking_end_date else False
+
+	return last_gl_entry, booking_start_date, booking_end_date, skip
+
+def calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total_booking_days):
+	account_currency = get_account_currency(item.expense_account)
+
+	if doc.doctype == "Sales Invoice":
+		total_credit_debit, total_credit_debit_currency = "debit", "debit_in_account_currency"
+		deferred_account = "deferred_revenue_account"
+	else:
+		total_credit_debit, total_credit_debit_currency = "credit", "credit_in_account_currency"
+		deferred_account = "deferred_expense_account"
+
+	amount, base_amount = 0, 0
+	if not last_gl_entry:
+		base_amount = flt(item.base_net_amount*total_booking_days/flt(total_days), item.precision("base_net_amount"))
+		if account_currency==doc.company_currency:
+			amount = base_amount
+		else:
+			amount = flt(item.net_amount*total_booking_days/flt(total_days), item.precision("net_amount"))
+	else:
+		gl_entries_details = frappe.db.sql('''
+			select sum({0}) as total_credit, sum({1}) as total_credit_in_account_currency, voucher_detail_no
+			from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
+			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:
+			amount = base_amount
+		else:
+			already_booked_amount_in_account_currency = gl_entries_details[0].total_credit_in_account_currency if gl_entries_details else 0
+			amount = flt(item.net_amount - already_booked_amount_in_account_currency, item.precision("net_amount"))
+
+	return amount, base_amount
+
+def book_deferred_income_or_expense(doc, start_date=None, end_date=None):
+	# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
+	# start_date: 1st of the last month or the start date
+	# end_date: end_date or today-1
+
+	gl_entries = []
+	for item in doc.get('items'):
+		skip = False
+		last_gl_entry, booking_start_date, booking_end_date, skip = \
+			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_booking_days = date_diff(booking_end_date, booking_start_date) + 1
+
+		account_currency = get_account_currency(item.expense_account)
+		amount, base_amount = calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total_booking_days)
+
+		if doc.doctype == "Sales Invoice":
+			against, project = doc.customer, doc.project
+			credit_account, debit_account = item.income_account, item.deferred_revenue_account
+		else:
+			against, project = doc.supplier, item.project
+			credit_account, debit_account = item.deferred_expense_account, item.expense_account
+
+		# GL Entry for crediting the amount in the deferred expense
+		gl_entries.append(
+			doc.get_gl_dict({
+				"account": credit_account,
+				"against": against,
+				"credit": base_amount,
+				"credit_in_account_currency": amount,
+				"cost_center": item.cost_center,
+				'posting_date': booking_end_date,
+				'project': project
+			}, account_currency)
+		)
+		# GL Entry to debit the amount from the expense
+		gl_entries.append(
+			doc.get_gl_dict({
+				"account": debit_account,
+				"against": against,
+				"debit": base_amount,
+				"debit_in_account_currency": amount,
+				"cost_center": item.cost_center,
+				"voucher_detail_no": item.name,
+				'posting_date': booking_end_date,
+				'project': project
+			}, account_currency)
+		)
+
+	if gl_entries:
+		make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 5154b90..c37fd15 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -496,6 +496,16 @@
 			'Purchase Invoice': 'Debit Note',
 			'Payment Entry': 'Payment'
 		}
+
+		frm.fields_dict['items'].grid.get_field('deferred_expense_account').get_query = function(doc) {
+			return {
+				filters: {
+					'root_type': 'Asset',
+					'company': doc.company,
+					"is_group": 0
+				}
+			}
+		}
 	},
 
 	onload: function(frm) {
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 273a6e4..11e48db 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -22,6 +22,7 @@
 from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_invoice,\
 	unlink_inter_company_invoice
 from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
+from erpnext.accounts.deferred_revenue import validate_service_stop_date
 
 form_grid_templates = {
 	"items": "templates/form_grid/item_grid.html"
@@ -74,6 +75,9 @@
 		if (self.is_paid == 1):
 			self.validate_cash()
 
+		# validate service stop date to lie in between start and end date
+		validate_service_stop_date(self)
+
 		if self._action=="submit" and self.update_stock:
 			self.make_batches('warehouse')
 
@@ -448,7 +452,7 @@
 				elif not item.is_fixed_asset:
 					gl_entries.append(
 						self.get_gl_dict({
-							"account": item.expense_account,
+							"account": item.expense_account if not item.enable_deferred_expense else item.deferred_expense_account,
 							"against": self.supplier,
 							"debit": flt(item.base_net_amount, item.precision("base_net_amount")),
 							"debit_in_account_currency": (flt(item.base_net_amount,
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index eaafdc0..936be10 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -1680,8 +1680,229 @@
    "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
+   "collapsible": 1,
+   "columns": 0,
+   "fieldname": "deferred_expense_section",
+   "fieldtype": "Section Break",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Deferred Expense",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "depends_on": "enable_deferred_expense",
+   "fieldname": "deferred_expense_account",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Deferred Expense Account",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Account",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "depends_on": "enable_deferred_expense",
+   "fieldname": "service_stop_date",
+   "fieldtype": "Date",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Service Stop Date",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "enable_deferred_expense",
+   "fieldtype": "Check",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Enable Deferred Expense",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "column_break_58",
+   "fieldtype": "Column Break",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "depends_on": "enable_deferred_expense",
+   "fieldname": "service_start_date",
+   "fieldtype": "Date",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Service Start Date",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "depends_on": "enable_deferred_expense",
+   "fieldname": "service_end_date",
+   "fieldtype": "Date",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Service End Date",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
    "fieldname": "reference", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -2323,7 +2544,7 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2018-08-06 05:18:38.205356", 
+ "modified": "2018-09-04 10:11:28.246395",
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Purchase Invoice Item", 
@@ -2336,5 +2557,6 @@
  "sort_field": "modified", 
  "sort_order": "DESC", 
  "track_changes": 0, 
- "track_seen": 0
-}
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 216d3e6..ca74d4d 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -786,39 +786,6 @@
 	}
 })
 
-frappe.ui.form.on('Sales Invoice Item', {
-	service_stop_date: function(frm, cdt, cdn) {
-		var child = locals[cdt][cdn];
-
-		if(child.service_stop_date) {
-			let start_date = Date.parse(child.service_start_date);
-			let end_date = Date.parse(child.service_end_date);
-			let stop_date = Date.parse(child.service_stop_date);
-
-			if(stop_date < start_date) {
-				frappe.model.set_value(cdt, cdn, "service_stop_date", "");
-				frappe.throw(__("Service Stop Date cannot be before Service Start Date"));
-			} else if (stop_date > end_date) {
-				frappe.model.set_value(cdt, cdn, "service_stop_date", "");
-				frappe.throw(__("Service Stop Date cannot be after Service End Date"));
-			}
-		}
-	},
-	service_start_date: function(frm, cdt, cdn) {
-		var child = locals[cdt][cdn];
-
-		if(child.service_start_date) {
-			frappe.call({
-				"method": "erpnext.stock.get_item_details.calculate_service_end_date",
-				args: {"args": child},
-				callback: function(r) {
-					frappe.model.set_value(cdt, cdn, "service_end_date", r.message.service_end_date);
-				}
-			})
-		}
-	}
-})
-
 var calculate_total_billing_amount =  function(frm) {
 	var doc = frm.doc;
 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 4708edf..d085d2a 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -23,6 +23,7 @@
 from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
 from erpnext.accounts.doctype.loyalty_program.loyalty_program import \
 	get_loyalty_program_details_with_points, get_loyalty_details, validate_loyalty_points
+from erpnext.accounts.deferred_revenue import validate_service_stop_date
 
 from erpnext.healthcare.utils import manage_invoice_submit_cancel
 
@@ -92,7 +93,7 @@
 			self.validate_delivery_note()
 
 		# validate service stop date to lie in between start and end date
-		self.validate_service_stop_date()
+		validate_service_stop_date(self)
 
 		if not self.is_opening:
 			self.is_opening = 'No'
@@ -558,24 +559,6 @@
 				if frappe.db.get_value("Sales Order Item", item.so_detail, "delivered_by_supplier"):
 					frappe.throw(_("Could not update stock, invoice contains drop shipping item."))
 
-	def validate_service_stop_date(self):
-		old_doc = frappe.db.get_all("Sales Invoice Item", {"parent": self.name}, ["name", "service_stop_date"])
-		old_stop_dates = {}
-		for d in old_doc:
-			old_stop_dates[d.name] = d.service_stop_date or ""
-
-		for item in self.items:
-			if item.enable_deferred_revenue:
-				if item.service_stop_date:
-					if date_diff(item.service_stop_date, item.service_start_date) < 0:
-						frappe.throw(_("Service Stop Date cannot be before Service Start Date"))
-
-					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]:
-					frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx)))
-
 	def update_current_stock(self):
 		for d in self.get('items'):
 			if d.item_code and d.warehouse:
@@ -1059,9 +1042,11 @@
 	# valdite the redemption and then delete the loyalty points earned on cancel of the invoice
 	def delete_loyalty_point_entry(self):
 		lp_entry = frappe.db.sql("select name from `tabLoyalty Point Entry` where sales_invoice=%s",
-			(self.name), as_dict=1)[0]
+			(self.name), as_dict=1)
+
+		if not lp_entry: return
 		against_lp_entry = frappe.db.sql('''select name, sales_invoice from `tabLoyalty Point Entry`
-			where redeem_against=%s''', (lp_entry.name), as_dict=1)
+			where redeem_against=%s''', (lp_entry[0].name), as_dict=1)
 		if against_lp_entry:
 			invoice_list = ", ".join([d.sales_invoice for d in against_lp_entry])
 			frappe.throw(_('''Sales Invoice can't be cancelled since the Loyalty Points earned has been redeemed.
@@ -1119,92 +1104,6 @@
 			if points_to_redeem < 1: # since points_to_redeem is integer
 				break
 
-	def book_income_for_deferred_revenue(self, start_date=None, end_date=None):
-		# book the income on the last day, but it will be trigger on the 1st of month at 12:00 AM
-		# start_date: 1st of the last month or the start date
-		# end_date: end_date or today-1
-
-		gl_entries = []
-		for item in self.get('items'):
-			last_gl_entry = False
-
-			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):
-				continue
-			elif booking_end_date>=item.service_end_date:
-				last_gl_entry = True
-				booking_end_date = item.service_end_date
-			elif item.service_stop_date and item.service_stop_date<=booking_end_date:
-				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 = booking_start_date if booking_start_date>item.service_start_date else item.service_start_date
-
-			if item.service_start_date < booking_start_date:
-				prev_gl_entry = frappe.db.sql('''
-					select name, posting_date from `tabGL Entry` where company=%s and account=%s and
-					voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
-					order by posting_date desc limit 1
-				''', (self.company, item.deferred_revenue_account, "Sales Invoice", self.name, item.name), as_dict=True)
-
-				if not prev_gl_entry:
-					booking_start_date = item.service_start_date
-				else:
-					booking_start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
-
-			total_days = date_diff(item.service_end_date, item.service_start_date)
-			total_booking_days = date_diff(booking_end_date, booking_start_date) + 1
-
-			account_currency = get_account_currency(item.income_account)
-			if not last_gl_entry:
-				base_amount = flt(item.base_net_amount*total_booking_days/flt(total_days), item.precision("base_net_amount"))
-				if account_currency==self.company_currency:
-					amount = base_amount
-				else:
-					amount = flt(item.net_amount*total_booking_days/flt(total_days), item.precision("net_amount"))
-			else:
-				gl_entries_details = frappe.db.sql('''
-					select sum(debit) as total_debit, sum(debit_in_account_currency) as total_debit_in_account_currency, voucher_detail_no
-					from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
-					group by voucher_detail_no
-				''', (self.company, item.deferred_revenue_account, "Sales Invoice", self.name, item.name), as_dict=True)
-				already_booked_amount = gl_entries_details[0].total_debit if gl_entries_details else 0
-				base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
-				if account_currency==self.company_currency:
-					amount = base_amount
-				else:
-					already_booked_amount_in_account_currency = gl_entries_details[0].total_debit_in_account_currency if gl_entries_details else 0
-					amount = flt(item.net_amount - already_booked_amount_in_account_currency, item.precision("net_amount"))
-
-			# GL Entry for crediting the amount in the income
-			gl_entries.append(
-				self.get_gl_dict({
-					"account": item.income_account,
-					"against": self.customer,
-					"credit": base_amount,
-					"credit_in_account_currency": amount,
-					"cost_center": item.cost_center,
-					'posting_date': booking_end_date
-				}, account_currency)
-			)
-			# GL Entry to debit the amount from the deferred account
-			gl_entries.append(
-				self.get_gl_dict({
-					"account": item.deferred_revenue_account,
-					"against": self.customer,
-					"debit": base_amount,
-					"debit_in_account_currency": amount,
-					"cost_center": item.cost_center,
-					"voucher_detail_no": item.name,
-					'posting_date': booking_end_date
-				}, account_currency)
-			)
-
-		if gl_entries:
-			from erpnext.accounts.general_ledger import make_gl_entries
-			make_gl_entries(gl_entries, cancel=(self.docstatus == 2), merge_entries=True)
-
 	# Healthcare
 	def set_healthcare_services(self, checked_values):
 		self.set("items", [])
@@ -1243,19 +1142,6 @@
 
 		self.set_missing_values(for_validate = True)
 
-def booked_deferred_revenue(start_date=None, end_date=None):
-	# check for the sales invoice for which GL entries has to be done
-	invoices = frappe.db.sql_list('''
-		select parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s
-		and enable_deferred_revenue = 1 and docstatus = 1
-	''', (end_date or today(), start_date or add_months(today(), -1)))
-
-	# ToDo also find the list on the basic of the GL entry, and make another list
-	for invoice in invoices:
-		doc = frappe.get_doc("Sales Invoice", invoice)
-		doc.book_income_for_deferred_revenue(start_date, end_date)
-
-
 def validate_inter_company_party(doctype, party, company, inter_company_invoice_reference):
 	if doctype == "Sales Invoice":
 		partytype, ref_partytype, internal = "Customer", "Supplier", "is_internal_customer"
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index d944874..22c9257 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -12,7 +12,7 @@
 source_link = "https://github.com/frappe/erpnext"
 
 develop_version = '11.x.x-develop'
-staging_version = '11.0.1'
+staging_version = '11.0.2'
 
 error_report_email = "support@erpnext.com"
 
@@ -250,7 +250,8 @@
 		"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"
 	],
 	"monthly": [
-		"erpnext.accounts.doctype.sales_invoice.sales_invoice.booked_deferred_revenue",
+		"erpnext.accounts.deferred_revenue.convert_deferred_revenue_to_income",
+		"erpnext.accounts.deferred_revenue.convert_deferred_expense_to_expense",
 		"erpnext.hr.utils.allocate_earned_leaves"
 	]
 }
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index cd4a7b2..3b6f169 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -796,6 +796,38 @@
 		this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true);
 	},
 
+	service_stop_date: function(frm, cdt, cdn) {
+		var child = locals[cdt][cdn];
+
+		if(child.service_stop_date) {
+			let start_date = Date.parse(child.service_start_date);
+			let end_date = Date.parse(child.service_end_date);
+			let stop_date = Date.parse(child.service_stop_date);
+
+			if(stop_date < start_date) {
+				frappe.model.set_value(cdt, cdn, "service_stop_date", "");
+				frappe.throw(__("Service Stop Date cannot be before Service Start Date"));
+			} else if (stop_date > end_date) {
+				frappe.model.set_value(cdt, cdn, "service_stop_date", "");
+				frappe.throw(__("Service Stop Date cannot be after Service End Date"));
+			}
+		}
+	},
+
+	service_start_date: function(frm, cdt, cdn) {
+		var child = locals[cdt][cdn];
+
+		if(child.service_start_date) {
+			frappe.call({
+				"method": "erpnext.stock.get_item_details.calculate_service_end_date",
+				args: {"args": child},
+				callback: function(r) {
+					frappe.model.set_value(cdt, cdn, "service_end_date", r.message.service_end_date);
+				}
+			})
+		}
+	},
+
 	calculate_net_weight: function(){
 		/* Calculate Total Net Weight then further applied shipping rule to calculate shipping charges.*/
 		var me = this;
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index 9a245e2..9377cad 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -837,7 +837,7 @@
    "label": "Create Chart Of Accounts Based On", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "\nStandard Template\nExisting Company", 
+   "options": "\nStandard Template\nExisting Company",
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -871,7 +871,7 @@
    "label": "Chart Of Accounts Template", 
    "length": 0, 
    "no_copy": 1, 
-   "options": "", 
+   "options": "",
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -1158,6 +1158,39 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "round_off_cost_center",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Round Off Cost Center",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Cost Center",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
    "fieldname": "write_off_account", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -1458,7 +1491,7 @@
    "collapsible": 0, 
    "columns": 0, 
    "depends_on": "eval:!doc.__islocal", 
-   "fieldname": "default_payroll_payable_account", 
+   "fieldname": "default_deferred_expense_account",
    "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 1, 
@@ -1467,7 +1500,7 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Default Payroll Payable Account", 
+   "label": "Default Deferred Expense Account",
    "length": 0, 
    "no_copy": 1, 
    "options": "Account", 
@@ -1492,7 +1525,7 @@
    "collapsible": 0, 
    "columns": 0, 
    "depends_on": "eval:!doc.__islocal", 
-   "fieldname": "default_expense_claim_payable_account", 
+   "fieldname": "default_payroll_payable_account",
    "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 1, 
@@ -1501,7 +1534,7 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Default Expense Claim Payable Account", 
+   "label": "Default Payroll Payable Account",
    "length": 0, 
    "no_copy": 1, 
    "options": "Account", 
@@ -1525,19 +1558,20 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "round_off_cost_center", 
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "default_expense_claim_payable_account",
    "fieldtype": "Link", 
    "hidden": 0, 
-   "ignore_user_permissions": 0, 
+   "ignore_user_permissions": 1,
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Round Off Cost Center", 
+   "label": "Default Expense Claim Payable Account",
    "length": 0, 
-   "no_copy": 0, 
-   "options": "Cost Center", 
+   "no_copy": 1,
+   "options": "Account",
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -2836,8 +2870,8 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2018-09-07 16:03:30.716918", 
- "modified_by": "cave@aperture.com", 
+ "modified": "2018-09-13 10:00:47.915706",
+ "modified_by": "Administrator",
  "module": "Setup", 
  "name": "Company", 
  "owner": "Administrator", 
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index e78e8d5..7d1bb6d 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -2690,18 +2690,20 @@
    "bold": 0,
    "collapsible": 0,
    "columns": 0,
-   "fieldname": "enable_deferred_revenue",
-   "fieldtype": "Check",
+   "depends_on": "enable_deferred_revenue",
+   "fieldname": "deferred_revenue_account",
+   "fieldtype": "Link",
    "hidden": 0,
-   "ignore_user_permissions": 0,
+   "ignore_user_permissions": 1,
    "ignore_xss_filter": 0,
    "in_filter": 0,
    "in_global_search": 0,
    "in_list_view": 0,
    "in_standard_filter": 0,
-   "label": "Enable Deferred Revenue",
+   "label": "Deferred Revenue Account",
    "length": 0,
    "no_copy": 0,
+   "options": "Account",
    "permlevel": 0,
    "precision": "",
    "print_hide": 0,
@@ -2722,20 +2724,18 @@
    "bold": 0,
    "collapsible": 0,
    "columns": 0,
-   "depends_on": "enable_deferred_revenue",
-   "fieldname": "deferred_revenue_account",
-   "fieldtype": "Link",
+   "fieldname": "enable_deferred_revenue",
+   "fieldtype": "Check",
    "hidden": 0,
-   "ignore_user_permissions": 1,
+   "ignore_user_permissions": 0,
    "ignore_xss_filter": 0,
    "in_filter": 0,
    "in_global_search": 0,
    "in_list_view": 0,
    "in_standard_filter": 0,
-   "label": "Deferred Revenue Account",
+   "label": "Enable Deferred Revenue",
    "length": 0,
    "no_copy": 0,
-   "options": "Account",
    "permlevel": 0,
    "precision": "",
    "print_hide": 0,
@@ -2820,6 +2820,168 @@
    "bold": 0,
    "collapsible": 1,
    "columns": 0,
+   "fieldname": "deferred_expense_section",
+   "fieldtype": "Section Break",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Deferred Expense",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "depends_on": "enable_deferred_expense",
+   "fieldname": "deferred_expense_account",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 1,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Deferred Expense Account",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Account",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "enable_deferred_expense",
+   "fieldtype": "Check",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Enable Deferred Expense",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "column_break_88",
+   "fieldtype": "Column Break",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "depends_on": "enable_deferred_expense",
+   "fieldname": "no_of_months_exp",
+   "fieldtype": "Int",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "No of Months",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 1,
+   "columns": 0,
    "fieldname": "customer_details",
    "fieldtype": "Section Break",
    "hidden": 0,
@@ -3951,7 +4113,7 @@
  "issingle": 0,
  "istable": 0,
  "max_attachments": 1,
- "modified": "2018-09-19 16:17:41.039657",
+ "modified": "2018-09-20 11:14:21.031369",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item",
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index be138d7..d90db56 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -310,14 +310,18 @@
 	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"
+
 	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.no_of_months)
+	service_end_date = add_months(service_start_date, item.get(no_of_months))
 	deferred_detail = {
-		"enable_deferred_revenue": item.enable_deferred_revenue,
-		"deferred_revenue_account": get_default_deferred_revenue_account(args, item),
 		"service_start_date": service_start_date,
 		"service_end_date": service_end_date
 	}
+	deferred_detail[enable_deferred] = item.get(enable_deferred)
+	deferred_detail[account] = get_default_deferred_account(args, item, fieldname=account)
 
 	return deferred_detail
 
@@ -331,11 +335,11 @@
 		or item_group.get("expense_account")
 		or args.expense_account)
 
-def get_default_deferred_revenue_account(args, item):
+def get_default_deferred_account(args, item, fieldname=None):
 	if item.enable_deferred_revenue:
-		return (item.deferred_revenue_account
-			or args.deferred_revenue_account
-			or frappe.get_cached_value('Company',  args.company,  "default_deferred_revenue_account"))
+		return (item.get(fieldname)
+			or args.get(fieldname)
+			or frappe.get_cached_value('Company',  args.company,  "default_"+fieldname))
 	else:
 		return None