Merge pull request #20087 from nextchamp-saqib/pay-reco-fix

fix: undefined dr_or_cr_notes in case of party type Employee
diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py
index 180460c..f48d6df 100644
--- a/erpnext/accounts/doctype/accounting_period/accounting_period.py
+++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py
@@ -41,8 +41,8 @@
 
 	def get_doctypes_for_closing(self):
 		docs_for_closing = []
-		doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", "Bank Reconciliation",
-			"Asset", "Purchase Order", "Sales Order", "Leave Application", "Leave Allocation", "Stock Entry"]
+		doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", \
+			"Bank Reconciliation", "Asset", "Stock Entry"]
 		closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes]
 		for closed_doctype in closed_doctypes:
 			docs_for_closing.append(closed_doctype)
diff --git a/erpnext/accounts/doctype/pos_field/__init__.py b/erpnext/accounts/doctype/pos_field/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_field/__init__.py
diff --git a/erpnext/accounts/doctype/pos_field/pos_field.json b/erpnext/accounts/doctype/pos_field/pos_field.json
new file mode 100644
index 0000000..13edabd
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_field/pos_field.json
@@ -0,0 +1,77 @@
+{
+ "creation": "2019-08-22 14:35:39.043242",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "fieldname",
+  "label",
+  "fieldtype",
+  "column_break_7",
+  "options",
+  "default_value",
+  "reqd",
+  "read_only"
+ ],
+ "fields": [
+  {
+   "fieldname": "fieldname",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Fieldname"
+  },
+  {
+   "fieldname": "fieldtype",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Fieldtype",
+   "read_only": 1
+  },
+  {
+   "fieldname": "label",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Label",
+   "read_only": 1
+  },
+  {
+   "fieldname": "options",
+   "fieldtype": "Text",
+   "in_list_view": 1,
+   "label": "Options",
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "reqd",
+   "fieldtype": "Check",
+   "label": "Mandatory"
+  },
+  {
+   "default": "0",
+   "fieldname": "read_only",
+   "fieldtype": "Check",
+   "label": "Read Only"
+  },
+  {
+   "fieldname": "column_break_7",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "default_value",
+   "fieldtype": "Data",
+   "label": "Default Value"
+  }
+ ],
+ "istable": 1,
+ "modified": "2019-08-23 13:59:34.025523",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Field",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_field/pos_field.py b/erpnext/accounts/doctype/pos_field/pos_field.py
new file mode 100644
index 0000000..b4720b3
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_field/pos_field.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class POSField(Document):
+	pass
diff --git a/erpnext/accounts/doctype/pos_settings/pos_settings.js b/erpnext/accounts/doctype/pos_settings/pos_settings.js
index 1a14618..f5b681b 100644
--- a/erpnext/accounts/doctype/pos_settings/pos_settings.js
+++ b/erpnext/accounts/doctype/pos_settings/pos_settings.js
@@ -2,7 +2,46 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('POS Settings', {
-	refresh: function() {
+	onload: function(frm) {
+		frm.trigger("get_invoice_fields");
+	},
 
+	use_pos_in_offline_mode: function(frm) {
+		frm.trigger("get_invoice_fields");
+	},
+
+	get_invoice_fields: function(frm) {
+		if (!frm.doc.use_pos_in_offline_mode) {
+			frappe.model.with_doctype("Sales Invoice", () => {
+				var fields = $.map(frappe.get_doc("DocType", "Sales Invoice").fields, function(d) {
+					if (frappe.model.no_value_type.indexOf(d.fieldtype) === -1 ||
+						d.fieldtype === 'Table') {
+						return { label: d.label + ' (' + d.fieldtype + ')', value: d.fieldname };
+					} else {
+						return null;
+					}
+				});
+
+				frappe.meta.get_docfield("POS Field", "fieldname", frm.doc.name).options = [""].concat(fields);
+			});
+		} else {
+			frappe.meta.get_docfield("POS Field", "fieldname", frm.doc.name).options = [""];
+		}
+	}
+});
+
+frappe.ui.form.on("POS Field", {
+	fieldname: function(frm, doctype, name) {
+		var doc = frappe.get_doc(doctype, name);
+		var df = $.map(frappe.get_doc("DocType", "Sales Invoice").fields, function(d) {
+			return doc.fieldname == d.fieldname ? d : null;
+		})[0];
+
+		doc.label = df.label;
+		doc.reqd = df.reqd;
+		doc.options = df.options;
+		doc.fieldtype = df.fieldtype;
+		doc.default_value = df.default;
+		frm.refresh_field("fields");
 	}
 });
diff --git a/erpnext/accounts/doctype/pos_settings/pos_settings.json b/erpnext/accounts/doctype/pos_settings/pos_settings.json
index 8f5b631..1d55880 100644
--- a/erpnext/accounts/doctype/pos_settings/pos_settings.json
+++ b/erpnext/accounts/doctype/pos_settings/pos_settings.json
@@ -1,133 +1,68 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-08-28 16:46:41.732676", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2017-08-28 16:46:41.732676",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "use_pos_in_offline_mode",
+  "section_break_2",
+  "fields"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "fieldname": "use_pos_in_offline_mode", 
-   "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": "Use POS in Offline Mode", 
-   "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, 
-   "unique": 0
+   "default": "0",
+   "fieldname": "use_pos_in_offline_mode",
+   "fieldtype": "Check",
+   "label": "Use POS in Offline Mode"
+  },
+  {
+   "fieldname": "section_break_2",
+   "fieldtype": "Section Break"
+  },
+  {
+   "depends_on": "eval:!doc.use_pos_in_offline_mode",
+   "fieldname": "fields",
+   "fieldtype": "Table",
+   "label": "POS Field",
+   "options": "POS Field"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 1, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2017-09-11 13:57:28.787023", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "POS Settings", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "issingle": 1,
+ "links": [],
+ "modified": "2019-12-26 11:50:47.122997",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Settings",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 0, 
-   "role": "System Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "System Manager",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Accounts User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Accounts User",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Sales User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Sales User",
+   "share": 1,
    "write": 1
   }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 0f4d445..9ea5a51 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -90,6 +90,7 @@
 		self.validate_account_for_change_amount()
 		self.validate_fixed_asset()
 		self.set_income_account_for_fixed_assets()
+		self.validate_item_cost_centers()
 		validate_inter_company_party(self.doctype, self.customer, self.company, self.inter_company_invoice_reference)
 
 		if cint(self.is_pos):
@@ -147,6 +148,12 @@
 					elif asset.status in ("Scrapped", "Cancelled", "Sold"):
 						frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}").format(d.idx, d.asset, asset.status))
 
+	def validate_item_cost_centers(self):
+		for item in self.items:
+			cost_center_company = frappe.get_cached_value("Cost Center", item.cost_center, "company")
+			if cost_center_company != self.company:
+				frappe.throw(_("Row #{0}: Cost Center {1} does not belong to company {2}").format(frappe.bold(item.idx), frappe.bold(item.cost_center), frappe.bold(self.company)))
+
 	def before_save(self):
 		set_account_for_mode_of_payment(self)
 
diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
index bd4b4d7..69f9907 100644
--- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
@@ -18,6 +18,10 @@
 	account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
 	gl_entry = frappe.get_doc("GL Entry", dict(account=account, voucher_type=payment_doctype, voucher_no=payment_name))
 
+	if payment_doctype == "Payment Entry" and payment_entry.unallocated_amount > transaction.unallocated_amount:
+		frappe.throw(_("The unallocated amount of Payment Entry {0} \
+			is greater than the Bank Transaction's unallocated amount").format(payment_name))
+		
 	if transaction.unallocated_amount == 0:
 		frappe.throw(_("This bank transaction is already fully reconciled"))
 
@@ -373,4 +377,4 @@
 			'start': start,
 			'page_len': page_len
 		}
-	)
\ No newline at end of file
+	)
diff --git a/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json b/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json
index 8a31368..1c5a195 100644
--- a/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json
+++ b/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json
@@ -1,22 +1,23 @@
 {
- "align_labels_right": 0, 
- "creation": "2017-08-08 12:33:04.773099", 
- "custom_format": 1, 
- "disabled": 0, 
- "doc_type": "Sales Invoice", 
- "docstatus": 0, 
- "doctype": "Print Format", 
- "font": "Default", 
- "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t<b>{{ _(\"GSTIN\") }}:</b>{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"<br>GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t<br>\n\t{% if doc.docstatus == 0 %}\n\t\t<b>{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }}</b><br>\n\t{% else %}\n\t\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n\t{% endif %}\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t<b>{{ _(\"Customer\") }}:</b><br>\n\t\t{{ doc.customer_name }}<br>\n\t\t{{ customer_address }}\n\t{% endif %}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t<br><b>{{ _(\"HSN/SAC\") }}:</b> {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"Serial No\") }}:</b> {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.rate }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if (not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) and row.tax_amount != 0 -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- if doc.change_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- endif -%}\n\t</tbody>\n</table>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>", 
- "idx": 0, 
- "line_breaks": 0, 
- "modified": "2019-01-24 17:09:27.190929", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "GST POS Invoice", 
- "owner": "Administrator", 
- "print_format_builder": 0, 
- "print_format_type": "Server", 
- "show_section_headings": 0, 
+ "align_labels_right": 0,
+ "creation": "2017-08-08 12:33:04.773099",
+ "custom_format": 1,
+ "disabled": 0,
+ "doc_type": "Sales Invoice",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t<b>{{ _(\"GSTIN\") }}:</b>{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"<br>GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t<br>\n\t{% if doc.docstatus == 0 %}\n\t\t<b>{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }}</b><br>\n\t{% else %}\n\t\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n\t{% endif %}\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t<b>{{ _(\"Customer\") }}:</b><br>\n\t\t{{ doc.customer_name }}<br>\n\t\t{{ customer_address }}\n\t{% endif %}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t<br><b>{{ _(\"HSN/SAC\") }}:</b> {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"Serial No\") }}:</b> {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.rate }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if (not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) and row.tax_amount != 0 -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- if doc.change_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- endif -%}\n\t</tbody>\n</table>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2019-12-09 17:39:23.356573",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "GST POS Invoice",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 0,
  "standard": "Yes"
 }
\ No newline at end of file
diff --git a/erpnext/accounts/print_format/pos_invoice/pos_invoice.json b/erpnext/accounts/print_format/pos_invoice/pos_invoice.json
index c3450d6..be69922 100644
--- a/erpnext/accounts/print_format/pos_invoice/pos_invoice.json
+++ b/erpnext/accounts/print_format/pos_invoice/pos_invoice.json
@@ -1,21 +1,22 @@
 {
- "align_labels_right": 0, 
- "creation": "2011-12-21 11:08:55", 
- "custom_format": 1, 
- "disabled": 0, 
- "doc_type": "Sales Invoice", 
- "docstatus": 0, 
- "doctype": "Print Format", 
- "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.docstatus == 0 %}\n\t\t{{ doc.status + \" \" + (doc.select_print_heading or _(\"Invoice\")) }}<br>\n\t{% else %}\n\t\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n\t{% endif %}\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"rate\") }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t\t{%- if doc.pos_total_qty -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Total Qty\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"pos_total_qty\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>", 
- "idx": 1, 
- "line_breaks": 0, 
- "modified": "2018-03-20 14:24:12.394354", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "POS Invoice", 
- "owner": "Administrator", 
- "print_format_builder": 0, 
- "print_format_type": "Server", 
- "show_section_headings": 0, 
+ "align_labels_right": 0,
+ "creation": "2011-12-21 11:08:55",
+ "custom_format": 1,
+ "disabled": 0,
+ "doc_type": "Sales Invoice",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"rate\") }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
+ "idx": 1,
+ "line_breaks": 0,
+ "modified": "2019-12-09 17:40:53.183574",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Invoice",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 0,
  "standard": "Yes"
 }
\ No newline at end of file
diff --git a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py
index 0c99f14..7854660 100644
--- a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py
+++ b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py
@@ -4,126 +4,141 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-from frappe.utils import formatdate, getdate, flt, add_days
+from frappe.utils import formatdate, flt, add_days
+
 
 def execute(filters=None):
 	filters.day_before_from_date = add_days(filters.from_date, -1)
 	columns, data = get_columns(filters), get_data(filters)
 	return columns, data
-	
+
+
 def get_data(filters):
 	data = []
-	
+
 	asset_categories = get_asset_categories(filters)
 	assets = get_assets(filters)
-	asset_costs = get_asset_costs(assets, filters)
-	asset_depreciations = get_accumulated_depreciations(assets, filters)
-	
+
 	for asset_category in asset_categories:
 		row = frappe._dict()
-		row.asset_category = asset_category
-		row.update(asset_costs.get(asset_category))
+		# row.asset_category = asset_category
+		row.update(asset_category)
 
-		row.cost_as_on_to_date = (flt(row.cost_as_on_from_date) + flt(row.cost_of_new_purchase)
-			- flt(row.cost_of_sold_asset) - flt(row.cost_of_scrapped_asset))
-			
-		row.update(asset_depreciations.get(asset_category))
-		row.accumulated_depreciation_as_on_to_date = (flt(row.accumulated_depreciation_as_on_from_date) + 
-			flt(row.depreciation_amount_during_the_period) - flt(row.depreciation_eliminated))
-		
-		row.net_asset_value_as_on_from_date = (flt(row.cost_as_on_from_date) - 
-			flt(row.accumulated_depreciation_as_on_from_date))
-		
-		row.net_asset_value_as_on_to_date = (flt(row.cost_as_on_to_date) - 
-			flt(row.accumulated_depreciation_as_on_to_date))
-	
+		row.cost_as_on_to_date = (flt(row.cost_as_on_from_date) + flt(row.cost_of_new_purchase) -
+				flt(row.cost_of_sold_asset) - flt(row.cost_of_scrapped_asset))
+
+		row.update(next(asset for asset in assets if asset["asset_category"] == asset_category.get("asset_category", "")))
+		row.accumulated_depreciation_as_on_to_date = (flt(row.accumulated_depreciation_as_on_from_date) +
+				flt(row.depreciation_amount_during_the_period) - flt(row.depreciation_eliminated))
+
+		row.net_asset_value_as_on_from_date = (flt(row.cost_as_on_from_date) -
+				flt(row.accumulated_depreciation_as_on_from_date))
+
+		row.net_asset_value_as_on_to_date = (flt(row.cost_as_on_to_date) -
+				flt(row.accumulated_depreciation_as_on_to_date))
+
 		data.append(row)
-		
+
 	return data
-	
+
+
 def get_asset_categories(filters):
-	return frappe.db.sql_list("""
-		select distinct asset_category from `tabAsset` 
-		where docstatus=1 and company=%s and purchase_date <= %s
-	""", (filters.company, filters.to_date))
-	
+	return frappe.db.sql("""
+		SELECT asset_category,
+			   ifnull(sum(case when purchase_date < %(from_date)s then
+							   case when ifnull(disposal_date, 0) = 0 or disposal_date >= %(from_date)s then
+									gross_purchase_amount
+							   else
+									0
+							   end
+						   else
+								0
+						   end), 0) as cost_as_on_from_date,
+			   ifnull(sum(case when purchase_date >= %(from_date)s then
+			   						gross_purchase_amount
+			   				   else
+			   				   		0
+			   				   end), 0) as cost_of_new_purchase,
+			   ifnull(sum(case when ifnull(disposal_date, 0) != 0
+			   						and disposal_date >= %(from_date)s
+			   						and disposal_date <= %(to_date)s then
+							   case when status = "Sold" then
+							   		gross_purchase_amount
+							   else
+							   		0
+							   end
+						   else
+								0
+						   end), 0) as cost_of_sold_asset,
+			   ifnull(sum(case when ifnull(disposal_date, 0) != 0
+			   						and disposal_date >= %(from_date)s
+			   						and disposal_date <= %(to_date)s then
+							   case when status = "Scrapped" then
+							   		gross_purchase_amount
+							   else
+							   		0
+							   end
+						   else
+								0
+						   end), 0) as cost_of_scrapped_asset
+		from `tabAsset`
+		where docstatus=1 and company=%(company)s and purchase_date <= %(to_date)s
+		group by asset_category
+	""", {"to_date": filters.to_date, "from_date": filters.from_date, "company": filters.company}, as_dict=1)
+
+
 def get_assets(filters):
 	return frappe.db.sql("""
-		select name, asset_category, purchase_date, gross_purchase_amount, disposal_date, status
-		from `tabAsset` 
-		where docstatus=1 and company=%s and purchase_date <= %s""", 
-		(filters.company, filters.to_date), as_dict=1)
-		
-def get_asset_costs(assets, filters):
-	asset_costs = frappe._dict()
-	for d in assets:
-		asset_costs.setdefault(d.asset_category, frappe._dict({
-			"cost_as_on_from_date": 0,
-			"cost_of_new_purchase": 0,
-			"cost_of_sold_asset": 0,
-			"cost_of_scrapped_asset": 0
-		}))
-		
-		costs = asset_costs[d.asset_category]
-		
-		if getdate(d.purchase_date) < getdate(filters.from_date):
-			if not d.disposal_date or getdate(d.disposal_date) >= getdate(filters.from_date):
-				costs.cost_as_on_from_date += flt(d.gross_purchase_amount)
-		else:
-			costs.cost_of_new_purchase += flt(d.gross_purchase_amount)
-			
-			if d.disposal_date and getdate(d.disposal_date) >= getdate(filters.from_date) \
-					and getdate(d.disposal_date) <= getdate(filters.to_date):
-				if d.status == "Sold":
-					costs.cost_of_sold_asset += flt(d.gross_purchase_amount)
-				elif d.status == "Scrapped":
-					costs.cost_of_scrapped_asset += flt(d.gross_purchase_amount)
-			
-	return asset_costs
-	
-def get_accumulated_depreciations(assets, filters):
-	asset_depreciations = frappe._dict()
-	for d in assets:
-		asset = frappe.get_doc("Asset", d.name)
-		
-		if d.asset_category in asset_depreciations:
-			asset_depreciations[d.asset_category]['accumulated_depreciation_as_on_from_date'] += asset.opening_accumulated_depreciation
-		else:
-			asset_depreciations.setdefault(d.asset_category, frappe._dict({
-				"accumulated_depreciation_as_on_from_date": asset.opening_accumulated_depreciation,
-				"depreciation_amount_during_the_period": 0,
-				"depreciation_eliminated_during_the_period": 0
-			}))
+		SELECT results.asset_category,
+			   sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date,
+			   sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
+			   sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
+		from (SELECT a.asset_category,
+				   ifnull(sum(a.opening_accumulated_depreciation +
+							  case when ds.schedule_date < %(from_date)s and
+										(ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s) then
+								   ds.depreciation_amount
+							  else
+								   0
+							  end), 0) as accumulated_depreciation_as_on_from_date,
+				   ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %(from_date)s
+										and a.disposal_date <= %(to_date)s and ds.schedule_date <= a.disposal_date then
+								   ds.depreciation_amount
+							  else
+								   0
+							  end), 0) as depreciation_eliminated_during_the_period,
 
-		depr = asset_depreciations[d.asset_category]
+				   ifnull(sum(case when ds.schedule_date >= %(from_date)s and ds.schedule_date <= %(to_date)s
+										and (ifnull(a.disposal_date, 0) = 0 or ds.schedule_date <= a.disposal_date) then
+								   ds.depreciation_amount
+							  else
+								   0
+							  end), 0) as depreciation_amount_during_the_period
+			from `tabAsset` a, `tabDepreciation Schedule` ds
+			where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and a.name = ds.parent
+			group by a.asset_category
+			union
+			SELECT a.asset_category,
+				   ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
+										and (a.disposal_date < %(from_date)s or a.disposal_date > %(to_date)s) then
+									0
+							   else
+									a.opening_accumulated_depreciation
+							   end), 0) as accumulated_depreciation_as_on_from_date,
+				   ifnull(sum(case when a.disposal_date >= %(from_date)s and a.disposal_date <= %(to_date)s then
+								   a.opening_accumulated_depreciation
+							  else
+								   0
+							  end), 0) as depreciation_eliminated_during_the_period,
+				   0 as depreciation_amount_during_the_period
+			from `tabAsset` a
+			where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s
+			and not exists(select * from `tabDepreciation Schedule` ds where a.name = ds.parent)
+			group by a.asset_category) as results
+		group by results.asset_category
+		""", {"to_date": filters.to_date, "from_date": filters.from_date, "company": filters.company}, as_dict=1)
 
-		if not asset.schedules: # if no schedule,
-			if asset.disposal_date:
-				# and disposal is NOT within the period, then opening accumulated depreciation not included
-				if getdate(asset.disposal_date) < getdate(filters.from_date) or getdate(asset.disposal_date) > getdate(filters.to_date):
-					asset_depreciations[d.asset_category]['accumulated_depreciation_as_on_from_date'] = 0
 
-				# if no schedule, and disposal is within period, accumulated dep is the amount eliminated
-				if getdate(asset.disposal_date) >= getdate(filters.from_date) and getdate(asset.disposal_date) <= getdate(filters.to_date):
-					depr.depreciation_eliminated_during_the_period += asset.opening_accumulated_depreciation
-		
-		for schedule in asset.get("schedules"):
-			if getdate(schedule.schedule_date) < getdate(filters.from_date):
-				if not asset.disposal_date or getdate(asset.disposal_date) >= getdate(filters.from_date):
-					depr.accumulated_depreciation_as_on_from_date += flt(schedule.depreciation_amount)
-			elif getdate(schedule.schedule_date) <= getdate(filters.to_date):
-				if not asset.disposal_date:
-					depr.depreciation_amount_during_the_period += flt(schedule.depreciation_amount)
-				else:
-					if getdate(schedule.schedule_date) <= getdate(asset.disposal_date):
-						depr.depreciation_amount_during_the_period += flt(schedule.depreciation_amount)
-
-			if asset.disposal_date and getdate(asset.disposal_date) >= getdate(filters.from_date) and getdate(asset.disposal_date) <= getdate(filters.to_date):
-				if getdate(schedule.schedule_date) <= getdate(asset.disposal_date):
-					depr.depreciation_eliminated_during_the_period += flt(schedule.depreciation_amount)
-		
-	return asset_depreciations
-	
 def get_columns(filters):
 	return [
 		{
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 08f5d8b..1712369 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -118,6 +118,73 @@
 		self.assertEqual(po.get("items")[0].amount, 1400)
 		self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3)
 
+	
+	def test_add_new_item_in_update_child_qty_rate(self):
+		po = create_purchase_order(do_not_save=1)
+		po.items[0].qty = 4
+		po.save()
+		po.submit()
+		pr = make_pr_against_po(po.name, 2)
+
+		po.load_from_db()
+		first_item_of_po = po.get("items")[0]
+
+		trans_item = json.dumps([
+			{
+				'item_code': first_item_of_po.item_code,
+				'rate': first_item_of_po.rate,
+				'qty': first_item_of_po.qty,
+				'docname': first_item_of_po.name
+			},
+			{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7}
+		])
+		update_child_qty_rate('Purchase Order', trans_item, po.name)
+
+		po.reload()
+		self.assertEquals(len(po.get('items')), 2)
+		self.assertEqual(po.status, 'To Receive and Bill')
+
+	
+	def test_remove_item_in_update_child_qty_rate(self):
+		po = create_purchase_order(do_not_save=1)
+		po.items[0].qty = 4
+		po.save()
+		po.submit()
+		pr = make_pr_against_po(po.name, 2)
+
+		po.reload()
+		first_item_of_po = po.get("items")[0]
+		# add an item
+		trans_item = json.dumps([
+			{
+				'item_code': first_item_of_po.item_code,
+				'rate': first_item_of_po.rate,
+				'qty': first_item_of_po.qty,
+				'docname': first_item_of_po.name
+			},
+			{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7}])
+		update_child_qty_rate('Purchase Order', trans_item, po.name)
+
+		po.reload()
+		# check if can remove received item
+		trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7, 'docname': po.get("items")[1].name}])
+		self.assertRaises(frappe.ValidationError, update_child_qty_rate, 'Purchase Order', trans_item, po.name)
+
+		first_item_of_po = po.get("items")[0]
+		trans_item = json.dumps([
+			{
+				'item_code': first_item_of_po.item_code,
+				'rate': first_item_of_po.rate,
+				'qty': first_item_of_po.qty,
+				'docname': first_item_of_po.name
+			}
+		])
+		update_child_qty_rate('Purchase Order', trans_item, po.name)
+
+		po.reload()
+		self.assertEquals(len(po.get('items')), 1)
+		self.assertEqual(po.status, 'To Receive and Bill')
+
 	def test_update_qty(self):
 		po = create_purchase_order()
 
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 6150516..86f5d53 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1155,6 +1155,25 @@
 	child_item.base_amount = 1 # Initiallize value will update in parent validation
 	return child_item
 
+def check_and_delete_children(parent, data):
+	deleted_children = []
+	updated_item_names = [d.get("docname") for d in data]
+	for item in parent.items:
+		if item.name not in updated_item_names:
+			deleted_children.append(item)
+
+	for d in deleted_children:
+		if parent.doctype == "Sales Order" and flt(d.delivered_qty):
+			frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been delivered").format(d.idx, d.item_code))
+
+		if parent.doctype == "Purchase Order" and flt(d.received_qty):
+			frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been received").format(d.idx, d.item_code))
+		
+		if flt(d.billed_amt):
+			frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been billed.").format(d.idx, d.item_code))
+
+		d.cancel()
+		d.delete()
 
 @frappe.whitelist()
 def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, child_docname="items"):
@@ -1163,6 +1182,8 @@
 	sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation']
 	parent = frappe.get_doc(parent_doctype, parent_doctype_name)
 
+	check_and_delete_children(parent, data)
+
 	for d in data:
 		new_child_flag = False
 		if not d.get("docname"):
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 9dbd5be..9a9f3d1 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -148,13 +148,6 @@
 		if sales_team and total != 100.0:
 			throw(_("Total allocated percentage for sales team should be 100"))
 
-	def validate_order_type(self):
-		valid_types = ["Sales", "Maintenance", "Shopping Cart"]
-		if not self.order_type:
-			self.order_type = "Sales"
-		elif self.order_type not in valid_types:
-			throw(_("Order Type must be one of {0}").format(comma_or(valid_types)))
-
 	def validate_max_discount(self):
 		for d in self.get("items"):
 			if d.item_code:
diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js
index 122e2b4..0c88d28 100644
--- a/erpnext/crm/doctype/lead/lead.js
+++ b/erpnext/crm/doctype/lead/lead.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
 frappe.provide("erpnext");
@@ -7,57 +7,54 @@
 erpnext.LeadController = frappe.ui.form.Controller.extend({
 	setup: function () {
 		this.frm.make_methods = {
+			'Customer': this.make_customer,
 			'Quotation': this.make_quotation,
-			'Opportunity': this.create_opportunity
-		}
-
-		this.frm.fields_dict.customer.get_query = function (doc, cdt, cdn) {
-			return { query: "erpnext.controllers.queries.customer_query" }
-		}
+			'Opportunity': this.make_opportunity
+		};
 
 		this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead);
 	},
 
 	onload: function () {
-		if (cur_frm.fields_dict.lead_owner.df.options.match(/^User/)) {
-			cur_frm.fields_dict.lead_owner.get_query = function (doc, cdt, cdn) {
-				return { query: "frappe.core.doctype.user.user.user_query" }
-			}
-		}
+		this.frm.set_query("customer", function (doc, cdt, cdn) {
+			return { query: "erpnext.controllers.queries.customer_query" }
+		});
 
-		if (cur_frm.fields_dict.contact_by.df.options.match(/^User/)) {
-			cur_frm.fields_dict.contact_by.get_query = function (doc, cdt, cdn) {
-				return { query: "frappe.core.doctype.user.user.user_query" }
-			}
-		}
+		this.frm.set_query("lead_owner", function (doc, cdt, cdn) {
+			return { query: "frappe.core.doctype.user.user.user_query" }
+		});
+
+		this.frm.set_query("contact_by", function (doc, cdt, cdn) {
+			return { query: "frappe.core.doctype.user.user.user_query" }
+		});
 	},
 
 	refresh: function () {
-		var doc = this.frm.doc;
+		let doc = this.frm.doc;
 		erpnext.toggle_naming_series();
 		frappe.dynamic_link = { doc: doc, fieldname: 'name', doctype: 'Lead' }
 
-		if(!doc.__islocal && doc.__onload && !doc.__onload.is_customer) {
-			this.frm.add_custom_button(__("Customer"), this.create_customer, __('Create'));
-			this.frm.add_custom_button(__("Opportunity"), this.create_opportunity, __('Create'));
-			this.frm.add_custom_button(__("Quotation"), this.make_quotation, __('Create'));
+		if (!this.frm.is_new() && doc.__onload && !doc.__onload.is_customer) {
+			this.frm.add_custom_button(__("Customer"), this.make_customer, __("Create"));
+			this.frm.add_custom_button(__("Opportunity"), this.make_opportunity, __("Create"));
+			this.frm.add_custom_button(__("Quotation"), this.make_quotation, __("Create"));
 		}
 
-		if (!this.frm.doc.__islocal) {
-			frappe.contacts.render_address_and_contact(cur_frm);
+		if (!this.frm.is_new()) {
+			frappe.contacts.render_address_and_contact(this.frm);
 		} else {
-			frappe.contacts.clear_address_and_contact(cur_frm);
+			frappe.contacts.clear_address_and_contact(this.frm);
 		}
 	},
 
-	create_customer: function () {
+	make_customer: function () {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.crm.doctype.lead.lead.make_customer",
 			frm: cur_frm
 		})
 	},
 
-	create_opportunity: function () {
+	make_opportunity: function () {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.crm.doctype.lead.lead.make_opportunity",
 			frm: cur_frm
@@ -77,7 +74,7 @@
 	},
 
 	company_name: function () {
-		if (this.frm.doc.organization_lead == 1) {
+		if (this.frm.doc.organization_lead && !this.frm.doc.lead_name) {
 			this.frm.set_value("lead_name", this.frm.doc.company_name);
 		}
 	},
@@ -85,7 +82,7 @@
 	contact_date: function () {
 		if (this.frm.doc.contact_date) {
 			let d = moment(this.frm.doc.contact_date);
-			d.add(1, "hours");
+			d.add(1, "day");
 			this.frm.set_value("ends_on", d.format(frappe.defaultDatetimeFormat));
 		}
 	}
diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json
index eb68c67..bc007b1 100644
--- a/erpnext/crm/doctype/lead/lead.json
+++ b/erpnext/crm/doctype/lead/lead.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_events_in_timeline": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
@@ -16,6 +17,8 @@
   "col_break123",
   "lead_owner",
   "status",
+  "salutation",
+  "designation",
   "gender",
   "source",
   "customer",
@@ -28,17 +31,22 @@
   "ends_on",
   "notes_section",
   "notes",
-  "contact_info",
-  "address_desc",
+  "address_info",
   "address_html",
+  "address_title",
+  "address_line1",
+  "address_line2",
+  "city",
+  "county",
   "column_break2",
   "contact_html",
+  "state",
+  "country",
+  "pincode",
+  "contact_section",
   "phone",
-  "salutation",
   "mobile_no",
   "fax",
-  "website",
-  "territory",
   "more_info",
   "type",
   "market_segment",
@@ -46,8 +54,11 @@
   "request_type",
   "column_break3",
   "company",
+  "website",
+  "territory",
   "unsubscribed",
-  "blog_subscriber"
+  "blog_subscriber",
+  "title"
  ],
  "fields": [
   {
@@ -73,7 +84,6 @@
    "set_only_once": 1
   },
   {
-   "depends_on": "eval:!doc.organization_lead",
    "fieldname": "lead_name",
    "fieldtype": "Data",
    "in_global_search": 1,
@@ -130,7 +140,13 @@
    "search_index": 1
   },
   {
-   "depends_on": "eval:!doc.organization_lead",
+   "depends_on": "eval: doc.__islocal",
+   "fieldname": "salutation",
+   "fieldtype": "Link",
+   "label": "Salutation",
+   "options": "Salutation"
+  },
+  {
    "fieldname": "gender",
    "fieldtype": "Link",
    "label": "Gender",
@@ -217,39 +233,73 @@
    "label": "Notes"
   },
   {
-   "collapsible": 1,
-   "fieldname": "contact_info",
-   "fieldtype": "Section Break",
-   "label": "Address & Contact",
-   "oldfieldtype": "Column Break",
-   "options": "fa fa-map-marker"
-  },
-  {
-   "depends_on": "eval:doc.__islocal",
-   "fieldname": "address_desc",
-   "fieldtype": "HTML",
-   "label": "Address Desc",
-   "print_hide": 1
-  },
-  {
    "fieldname": "address_html",
    "fieldtype": "HTML",
    "label": "Address HTML",
    "read_only": 1
   },
   {
+   "depends_on": "eval: doc.__islocal",
+   "fieldname": "address_title",
+   "fieldtype": "Data",
+   "label": "Address Title"
+  },
+  {
+   "depends_on": "eval: doc.__islocal",
+   "fieldname": "address_line1",
+   "fieldtype": "Data",
+   "label": "Address Line 1"
+  },
+  {
+   "depends_on": "eval: doc.__islocal",
+   "fieldname": "address_line2",
+   "fieldtype": "Data",
+   "label": "Address Line 2"
+  },
+  {
+   "depends_on": "eval: doc.__islocal",
+   "fieldname": "city",
+   "fieldtype": "Data",
+   "label": "City/Town"
+  },
+  {
+   "depends_on": "eval: doc.__islocal",
+   "fieldname": "county",
+   "fieldtype": "Data",
+   "label": "County"
+  },
+  {
+   "depends_on": "eval: doc.__islocal",
+   "fieldname": "state",
+   "fieldtype": "Data",
+   "label": "State"
+  },
+  {
+   "depends_on": "eval: doc.__islocal",
+   "fieldname": "country",
+   "fieldtype": "Link",
+   "label": "Country",
+   "options": "Country"
+  },
+  {
+   "depends_on": "eval: doc.__islocal",
+   "fieldname": "pincode",
+   "fieldtype": "Data",
+   "label": "Postal Code",
+   "options": "Country"
+  },
+  {
    "fieldname": "column_break2",
    "fieldtype": "Column Break"
   },
   {
-   "depends_on": "eval:doc.organization_lead",
    "fieldname": "contact_html",
    "fieldtype": "HTML",
    "label": "Contact HTML",
    "read_only": 1
   },
   {
-   "depends_on": "eval:!doc.organization_lead",
+   "depends_on": "eval: doc.__islocal",
    "fieldname": "phone",
    "fieldtype": "Data",
    "label": "Phone",
@@ -257,14 +307,7 @@
    "oldfieldtype": "Data"
   },
   {
-   "depends_on": "eval:!doc.organization_lead",
-   "fieldname": "salutation",
-   "fieldtype": "Link",
-   "label": "Salutation",
-   "options": "Salutation"
-  },
-  {
-   "depends_on": "eval:!doc.organization_lead",
+   "depends_on": "eval: doc.__islocal",
    "fieldname": "mobile_no",
    "fieldtype": "Data",
    "label": "Mobile No.",
@@ -272,7 +315,7 @@
    "oldfieldtype": "Data"
   },
   {
-   "depends_on": "eval:!doc.organization_lead",
+   "depends_on": "eval: doc.__islocal",
    "fieldname": "fax",
    "fieldtype": "Data",
    "label": "Fax",
@@ -280,22 +323,6 @@
    "oldfieldtype": "Data"
   },
   {
-   "fieldname": "website",
-   "fieldtype": "Data",
-   "label": "Website",
-   "oldfieldname": "website",
-   "oldfieldtype": "Data"
-  },
-  {
-   "fieldname": "territory",
-   "fieldtype": "Link",
-   "label": "Territory",
-   "oldfieldname": "territory",
-   "oldfieldtype": "Link",
-   "options": "Territory",
-   "print_hide": 1
-  },
-  {
    "collapsible": 1,
    "fieldname": "more_info",
    "fieldtype": "Section Break",
@@ -351,6 +378,22 @@
    "remember_last_selected_value": 1
   },
   {
+   "fieldname": "website",
+   "fieldtype": "Data",
+   "label": "Website",
+   "oldfieldname": "website",
+   "oldfieldtype": "Data"
+  },
+  {
+   "fieldname": "territory",
+   "fieldtype": "Link",
+   "label": "Territory",
+   "oldfieldname": "territory",
+   "oldfieldtype": "Link",
+   "options": "Territory",
+   "print_hide": 1
+  },
+  {
    "default": "0",
    "fieldname": "unsubscribed",
    "fieldtype": "Check",
@@ -361,12 +404,42 @@
    "fieldname": "blog_subscriber",
    "fieldtype": "Check",
    "label": "Blog Subscriber"
+  },
+  {
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Title",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "designation",
+   "fieldtype": "Link",
+   "label": "Designation",
+   "options": "Designation"
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "eval: doc.__islocal",
+   "fieldname": "address_info",
+   "fieldtype": "Section Break",
+   "label": "Address & Contact",
+   "oldfieldtype": "Column Break",
+   "options": "fa fa-map-marker"
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "eval: doc.__islocal",
+   "fieldname": "contact_section",
+   "fieldtype": "Section Break",
+   "label": "Contact"
   }
  ],
  "icon": "fa fa-user",
  "idx": 5,
  "image_field": "image",
- "modified": "2019-09-19 12:49:02.536647",
+ "links": [],
+ "modified": "2019-12-24 16:00:44.239168",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Lead",
@@ -438,5 +511,5 @@
  "show_name_in_global_search": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
- "title_field": "lead_name"
+ "title_field": "title"
 }
\ No newline at end of file
diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py
index 1dae4b9..6cab18dc 100644
--- a/erpnext/crm/doctype/lead/lead.py
+++ b/erpnext/crm/doctype/lead/lead.py
@@ -2,18 +2,19 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe
-from frappe import _
-from frappe.utils import (cstr, validate_email_address, cint, comma_and, has_gravatar, now, getdate, nowdate)
-from frappe.model.mapper import get_mapped_doc
 
-from erpnext.controllers.selling_controller import SellingController
-from frappe.contacts.address_and_contact import load_address_and_contact
+import frappe
 from erpnext.accounts.party import set_taxes
+from erpnext.controllers.selling_controller import SellingController
+from frappe import _
+from frappe.contacts.address_and_contact import load_address_and_contact
 from frappe.email.inbox import link_communication_to_document
+from frappe.model.mapper import get_mapped_doc
+from frappe.utils import cint, comma_and, cstr, getdate, has_gravatar, nowdate, validate_email_address
 
 sender_field = "email_id"
 
+
 class Lead(SellingController):
 	def get_feed(self):
 		return '{0}: {1}'.format(_(self.status), self.lead_name)
@@ -23,15 +24,23 @@
 		self.get("__onload").is_customer = customer
 		load_address_and_contact(self)
 
+	def before_insert(self):
+		self.address_doc = self.create_address()
+		self.contact_doc = self.create_contact()
+
+	def after_insert(self):
+		self.update_links()
+		# after the address and contact are created, flush the field values
+		# to avoid inconsistent reporting in case the documents are changed
+		self.flush_address_and_contact_fields()
+
 	def validate(self):
 		self.set_lead_name()
+		self.set_title()
 		self._prev = frappe._dict({
-			"contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if \
-				(not cint(self.get("__islocal"))) else None,
-			"ends_on": frappe.db.get_value("Lead", self.name, "ends_on") if \
-				(not cint(self.get("__islocal"))) else None,
-			"contact_by": frappe.db.get_value("Lead", self.name, "contact_by") if \
-				(not cint(self.get("__islocal"))) else None,
+			"contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if (not cint(self.is_new())) else None,
+			"ends_on": frappe.db.get_value("Lead", self.name, "ends_on") if (not cint(self.is_new())) else None,
+			"contact_by": frappe.db.get_value("Lead", self.name, "contact_by") if (not cint(self.is_new())) else None,
 		})
 
 		self.set_status()
@@ -39,7 +48,7 @@
 
 		if self.email_id:
 			if not self.flags.ignore_email_validation:
-				validate_email_address(self.email_id, True)
+				validate_email_address(self.email_id, throw=True)
 
 			if self.email_id == self.lead_owner:
 				frappe.throw(_("Lead Owner cannot be same as the Lead"))
@@ -53,8 +62,7 @@
 		if self.contact_date and getdate(self.contact_date) < getdate(nowdate()):
 			frappe.throw(_("Next Contact Date cannot be in the past"))
 
-		if self.ends_on and self.contact_date and\
-			(self.ends_on < self.contact_date):
+		if self.ends_on and self.contact_date and (self.ends_on < self.contact_date):
 			frappe.throw(_("Ends On date cannot be before Next Contact Date."))
 
 	def on_update(self):
@@ -66,23 +74,21 @@
 			"starts_on": self.contact_date,
 			"ends_on": self.ends_on or "",
 			"subject": ('Contact ' + cstr(self.lead_name)),
-			"description": ('Contact ' + cstr(self.lead_name)) + \
-				(self.contact_by and ('. By : ' + cstr(self.contact_by)) or '')
+			"description": ('Contact ' + cstr(self.lead_name)) + (self.contact_by and ('. By : ' + cstr(self.contact_by)) or '')
 		}, force)
 
 	def check_email_id_is_unique(self):
 		if self.email_id:
 			# validate email is unique
-			duplicate_leads = frappe.db.sql_list("""select name from tabLead
-				where email_id=%s and name!=%s""", (self.email_id, self.name))
+			duplicate_leads = frappe.get_all("Lead", filters={"email_id": self.email_id, "name": ["!=", self.name]})
+			duplicate_leads = [lead.name for lead in duplicate_leads]
 
 			if duplicate_leads:
 				frappe.throw(_("Email Address must be unique, already exists for {0}")
 					.format(comma_and(duplicate_leads)), frappe.DuplicateEntryError)
 
 	def on_trash(self):
-		frappe.db.sql("""update `tabIssue` set lead='' where lead=%s""",
-			self.name)
+		frappe.db.sql("""update `tabIssue` set lead='' where lead=%s""", self.name)
 
 		self.delete_events()
 
@@ -115,10 +121,101 @@
 
 			self.lead_name = self.company_name
 
+	def set_title(self):
+		if self.organization_lead:
+			self.title = self.company_name
+		else:
+			self.title = self.lead_name
+
+	def create_address(self):
+		address_fields = ["address_title", "address_line1", "address_line2",
+			"city", "county", "state", "country", "pincode"]
+		info_fields = ["email_id", "phone", "fax"]
+
+		# do not create an address if no fields are available,
+		# skipping country since the system auto-sets it from system defaults
+		if not any([self.get(field) for field in address_fields if field != "country"]):
+			return
+
+		address = frappe.new_doc("Address")
+		address.update({addr_field: self.get(addr_field) for addr_field in address_fields})
+		address.update({info_field: self.get(info_field) for info_field in info_fields})
+		address.insert()
+
+		return address
+
+	def create_contact(self):
+		if not self.lead_name:
+			self.set_lead_name()
+
+		names = self.lead_name.split(" ")
+		if len(names) > 1:
+			first_name, last_name = names[0], " ".join(names[1:])
+		else:
+			first_name, last_name = self.lead_name, None
+
+		contact = frappe.new_doc("Contact")
+		contact.update({
+			"first_name": first_name,
+			"last_name": last_name,
+			"salutation": self.salutation,
+			"gender": self.gender,
+			"designation": self.designation,
+		})
+
+		if self.email_id:
+			contact.append("email_ids", {
+				"email_id": self.email_id,
+				"is_primary": 1
+			})
+
+		if self.phone:
+			contact.append("phone_nos", {
+				"phone": self.phone,
+				"is_primary": 1
+			})
+
+		if self.mobile_no:
+			contact.append("phone_nos", {
+				"phone": self.mobile_no
+			})
+
+		contact.insert()
+
+		return contact
+
+	def update_links(self):
+		# update address links
+		if self.address_doc:
+			self.address_doc.append("links", {
+				"link_doctype": "Lead",
+				"link_name": self.name,
+				"link_title": self.lead_name
+			})
+			self.address_doc.save()
+
+		# update contact links
+		if self.contact_doc:
+			self.contact_doc.append("links", {
+				"link_doctype": "Lead",
+				"link_name": self.name,
+				"link_title": self.lead_name
+			})
+			self.contact_doc.save()
+
+	def flush_address_and_contact_fields(self):
+		fields = ['address_line1', 'address_line2', 'address_title',
+			'city', 'county', 'country', 'fax', 'pincode', 'state']
+
+		for field in fields:
+			self.set(field, None)
+
+
 @frappe.whitelist()
 def make_customer(source_name, target_doc=None):
 	return _make_customer(source_name, target_doc)
 
+
 def _make_customer(source_name, target_doc=None, ignore_permissions=False):
 	def set_missing_values(source, target):
 		if source.company_name:
@@ -143,6 +240,7 @@
 
 	return doclist
 
+
 @frappe.whitelist()
 def make_opportunity(source_name, target_doc=None):
 	def set_missing_values(source, target):
@@ -164,6 +262,7 @@
 
 	return target_doc
 
+
 @frappe.whitelist()
 def make_quotation(source_name, target_doc=None):
 	def set_missing_values(source, target):
@@ -205,7 +304,8 @@
 
 @frappe.whitelist()
 def get_lead_details(lead, posting_date=None, company=None):
-	if not lead: return {}
+	if not lead:
+		return {}
 
 	from erpnext.accounts.party import set_address_details
 	out = frappe._dict()
@@ -231,6 +331,7 @@
 
 	return out
 
+
 @frappe.whitelist()
 def make_lead_from_communication(communication, ignore_communication_links=False):
 	""" raise a issue from email """
@@ -267,4 +368,4 @@
 
 	lead = leads[0].name if leads else None
 
-	return lead
\ No newline at end of file
+	return lead
diff --git a/erpnext/education/doctype/instructor/instructor.py b/erpnext/education/doctype/instructor/instructor.py
index 0756b5f..28df2fc 100644
--- a/erpnext/education/doctype/instructor/instructor.py
+++ b/erpnext/education/doctype/instructor/instructor.py
@@ -22,3 +22,12 @@
 				self.name = self.employee
 			elif naming_method == 'Full Name':
 				self.name = self.instructor_name
+
+	def validate(self):
+		self.validate_duplicate_employee()
+
+	def validate_duplicate_employee(self):
+		if self.employee and frappe.db.get_value("Instructor", {'employee': self.employee, 'name': ['!=', self.name]}, 'name'):
+			frappe.throw(_("Employee ID is linked with another instructor"))
+
+
diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py
index 8e4b4e1..99c4c0e 100644
--- a/erpnext/education/doctype/student/student.py
+++ b/erpnext/education/doctype/student/student.py
@@ -25,6 +25,9 @@
 		if self.date_of_birth and getdate(self.date_of_birth) >= getdate(today()):
 			frappe.throw(_("Date of Birth cannot be greater than today."))
 
+		if self.joining_date and self.date_of_leaving and getdate(self.joining_date) > getdate(self.date_of_leaving):
+			frappe.throw(_("Joining Date can not be greater than Leaving Date"))
+
 	def update_student_name_in_linked_doctype(self):
 		linked_doctypes = get_linked_doctypes("Student")
 		for d in linked_doctypes:
diff --git a/erpnext/education/doctype/student_group/student_group.js b/erpnext/education/doctype/student_group/student_group.js
index c29c134..4165ce0 100644
--- a/erpnext/education/doctype/student_group/student_group.js
+++ b/erpnext/education/doctype/student_group/student_group.js
@@ -122,3 +122,15 @@
 		}
 	}
 });
+
+frappe.ui.form.on('Student Group Instructor', {
+	instructors_add: function(frm){
+		frm.fields_dict['instructors'].grid.get_field('instructor').get_query = function(doc){
+			let instructor_list = [];
+			$.each(doc.instructors, function(idx, val){
+				instructor_list.push(val.instructor);
+			});
+			return { filters: [['Instructor', 'name', 'not in', instructor_list]] };
+		};
+	}
+});
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index 242531b..4d49503 100755
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -164,6 +164,12 @@
 		if self.personal_email:
 			validate_email_address(self.personal_email, True)
 
+	def set_preferred_email(self):
+		preferred_email_field = frappe.scrub(self.prefered_contact_email)
+		if preferred_email_field:
+			preferred_email = self.get(preferred_email_field)
+			self.prefered_email = preferred_email
+
 	def validate_status(self):
 		if self.status == 'Left':
 			reports_to = frappe.db.get_all('Employee',
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py
index b9c0210..b621642 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.py
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.py
@@ -235,8 +235,8 @@
 			frappe.get_doc(dict(
 				doctype = 'Holiday List',
 				holiday_list_name = holiday_list,
-				from_date = date(date.today().year, 1, 1),
-				to_date = date(date.today().year, 12, 31),
+				from_date = add_months(today, -6),
+				to_date = add_months(today, 6),
 				holidays = [
 					dict(holiday_date = today, description = 'Test')
 				]
@@ -597,8 +597,8 @@
 		return frappe.get_doc(dict(
 				name = 'Test Leave Period',
 				doctype = 'Leave Period',
-				from_date = "{0}-12-01".format(now_datetime().year - 1),
-				to_date = "{0}-12-31".format(now_datetime().year),
+				from_date = add_months(nowdate(), -6),
+				to_date = add_months(nowdate(), 6),
 				company = "_Test Company",
 				is_active = 1
 			)).insert()
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index c4238ac..ff4ebfe 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -856,4 +856,4 @@
 
 	doc.set_item_locations()
 
-	return doc
\ No newline at end of file
+	return doc
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index e26b1c8..89be499 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -649,5 +649,7 @@
 erpnext.patches.v12_0.remove_denied_leaves_from_leave_ledger
 erpnext.patches.v12_0.update_price_or_product_discount
 erpnext.patches.v12_0.set_production_capacity_in_workstation
+erpnext.patches.v12_0.set_employee_preferred_emails
 erpnext.patches.v12_0.set_against_blanket_order_in_sales_and_purchase_order
 erpnext.patches.v12_0.set_cost_center_in_child_table_of_expense_claim
+erpnext.patches.v12_0.set_lead_title_field
diff --git a/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py b/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py
index 555d8ae..3fccbfa 100644
--- a/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py
+++ b/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py
@@ -1,7 +1,10 @@
 import frappe
 def execute():
+
+	frappe.reload_doc('selling', 'doctype', frappe.scrub('Sales Order Item'))
+	frappe.reload_doc('buying', 'doctype', frappe.scrub('Purchase Order Item'))
+
 	for doctype in ['Sales Order Item', 'Purchase Order Item']:
-		frappe.reload_doctype(doctype)
 		frappe.db.sql("""
 			UPDATE `tab{0}`
 			SET against_blanket_order = 1
diff --git a/erpnext/patches/v12_0/set_employee_preferred_emails.py b/erpnext/patches/v12_0/set_employee_preferred_emails.py
new file mode 100644
index 0000000..2763561
--- /dev/null
+++ b/erpnext/patches/v12_0/set_employee_preferred_emails.py
@@ -0,0 +1,16 @@
+import frappe

+

+

+def execute():

+	employees = frappe.get_all("Employee",

+		filters={"prefered_email": ""},

+		fields=["name", "prefered_contact_email", "company_email", "personal_email", "user_id"])

+

+	for employee in employees:

+		preferred_email_field = frappe.scrub(employee.prefered_contact_email)

+

+		if not preferred_email_field:

+			continue

+

+		preferred_email = employee.get(preferred_email_field)

+		frappe.db.set_value("Employee", employee.name, "prefered_email", preferred_email, update_modified=False)

diff --git a/erpnext/patches/v12_0/set_lead_title_field.py b/erpnext/patches/v12_0/set_lead_title_field.py
new file mode 100644
index 0000000..86e0003
--- /dev/null
+++ b/erpnext/patches/v12_0/set_lead_title_field.py
@@ -0,0 +1,11 @@
+import frappe
+
+
+def execute():
+	frappe.reload_doc("crm", "doctype", "lead")
+	frappe.db.sql("""
+		UPDATE
+			`tabLead`
+		SET
+			title = IF(organization_lead = 1, company_name, lead_name)
+	""")
diff --git a/erpnext/patches/v8_7/set_offline_in_pos_settings.py b/erpnext/patches/v8_7/set_offline_in_pos_settings.py
index b24fe37..7d2882e 100644
--- a/erpnext/patches/v8_7/set_offline_in_pos_settings.py
+++ b/erpnext/patches/v8_7/set_offline_in_pos_settings.py
@@ -5,6 +5,7 @@
 import frappe
 
 def execute():
+	frappe.reload_doc('accounts', 'doctype', 'pos_field')
 	frappe.reload_doc('accounts', 'doctype', 'pos_settings')
 
 	doc = frappe.get_doc('POS Settings')
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 6ca0958..3b907da 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1808,14 +1808,44 @@
 	}
 });
 
-erpnext.show_serial_batch_selector = function(frm, d, callback, on_close, show_dialog) {
+erpnext.show_serial_batch_selector = function (frm, d, callback, on_close, show_dialog) {
+	let warehouse, receiving_stock, existing_stock;
+	if (frm.doc.is_return) {
+		if (["Purchase Receipt", "Purchase Invoice"].includes(frm.doc.doctype)) {
+			existing_stock = true;
+			warehouse = d.warehouse;
+		} else if (["Delivery Note", "Sales Invoice"].includes(frm.doc.doctype)) {
+			receiving_stock = true;
+		}
+	} else {
+		if (frm.doc.doctype == "Stock Entry") {
+			if (frm.doc.purpose == "Material Receipt") {
+				receiving_stock = true;
+			} else {
+				existing_stock = true;
+				warehouse = d.s_warehouse;
+			}
+		} else {
+			existing_stock = true;
+			warehouse = d.warehouse;
+		}
+	}
+
+	if (!warehouse) {
+		if (receiving_stock) {
+			warehouse = ["like", ""];
+		} else if (existing_stock) {
+			warehouse = ["!=", ""];
+		}
+	}
+
 	frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js", function() {
 		new erpnext.SerialNoBatchSelector({
 			frm: frm,
 			item: d,
 			warehouse_details: {
 				type: "Warehouse",
-				name: d.warehouse
+				name: warehouse
 			},
 			callback: callback,
 			on_close: on_close
diff --git a/erpnext/public/js/templates/address_list.html b/erpnext/public/js/templates/address_list.html
index 2379ef6..0f967b6 100644
--- a/erpnext/public/js/templates/address_list.html
+++ b/erpnext/public/js/templates/address_list.html
@@ -1,23 +1,22 @@
 <div class="clearfix"></div>
 {% for(var i=0, l=addr_list.length; i<l; i++) { %}
-    <div class="address-box">
-    <p class="h6">
-        {%= i+1 %}. {%= addr_list[i].address_type!="Other" ? __(addr_list[i].address_type) : addr_list[i].address_title %}
-        {% if(addr_list[i].is_primary_address) { %}
-            <span class="text-muted">({%= __("Primary") %})</span>{% } %}
-        {% if(addr_list[i].is_shipping_address) { %}
-            <span class="text-muted">({%= __("Shipping") %})</span>{% } %}
+<div class="address-box">
+	<p class="h6">
+		{%= i+1 %}. {%= addr_list[i].address_title %}{% if(addr_list[i].address_type!="Other") { %}
+		<span class="text-muted">({%= __(addr_list[i].address_type) %})</span>{% } %}
+		{% if(addr_list[i].is_primary_address) { %}
+		<span class="text-muted">({%= __("Primary") %})</span>{% } %}
+		{% if(addr_list[i].is_shipping_address) { %}
+		<span class="text-muted">({%= __("Shipping") %})</span>{% } %}
 
-        <a href="#Form/Address/{%= encodeURIComponent(addr_list[i].name) %}"
-            class="btn btn-default btn-xs pull-right"
-				style="margin-top:-3px; margin-right: -5px;">
-            {%= __("Edit") %}</a>
-    </p>
-        <p>{%= addr_list[i].display %}</p>
-    </div>
+		<a href="#Form/Address/{%= encodeURIComponent(addr_list[i].name) %}" class="btn btn-default btn-xs pull-right"
+			style="margin-top:-3px; margin-right: -5px;">
+			{%= __("Edit") %}</a>
+	</p>
+	<p>{%= addr_list[i].display %}</p>
+</div>
 {% } %}
 {% if(!addr_list.length) { %}
 <p class="text-muted small">{%= __("No address added yet.") %}</p>
 {% } %}
-<p><button class="btn btn-xs btn-default btn-address">{{ __("New Address") }}</button></p>
-
+<p><button class="btn btn-xs btn-default btn-address">{{ __("New Address") }}</button></p>
\ No newline at end of file
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index f363999..3f444f8 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -458,7 +458,8 @@
 					fieldname:"item_code",
 					options: 'Item',
 					in_list_view: 1,
-					read_only: 1,
+					read_only: 0,
+					disabled: 0,
 					label: __('Item Code')
 				}, {
 					fieldtype:'Float',
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index 41a59d0..61a6939 100644
--- a/erpnext/public/js/utils/serial_no_batch_selector.js
+++ b/erpnext/public/js/utils/serial_no_batch_selector.js
@@ -389,12 +389,14 @@
 
 		let serial_no_filters = {
 			item_code: me.item_code,
+			batch_no: this.doc.batch_no || null,
 			delivery_document_no: ""
 		}
 
 		if (me.warehouse_details.name) {
 			serial_no_filters['warehouse'] = me.warehouse_details.name;
 		}
+
 		return [
 			{fieldtype: 'Section Break', label: __('Serial Numbers')},
 			{
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index 790b2f0..9ebef0d 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -26,7 +26,6 @@
 		super(Quotation, self).validate()
 		self.set_status()
 		self.update_opportunity()
-		self.validate_order_type()
 		self.validate_uom_is_integer("stock_uom", "qty")
 		self.validate_valid_till()
 		self.set_customer_name()
@@ -40,9 +39,6 @@
 	def has_sales_order(self):
 		return frappe.db.get_value("Sales Order Item", {"prevdoc_docname": self.name, "docstatus": 1})
 
-	def validate_order_type(self):
-		super(Quotation, self).validate_order_type()
-
 	def update_lead(self):
 		if self.quotation_to == "Lead" and self.party_name:
 			frappe.get_doc("Lead", self.party_name).set_status(update=True)
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 2112a41..94bbb79 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -34,7 +34,6 @@
 
 	def validate(self):
 		super(SalesOrder, self).validate()
-		self.validate_order_type()
 		self.validate_delivery_date()
 		self.validate_proj_cust()
 		self.validate_po()
@@ -100,9 +99,6 @@
 					frappe.msgprint(_("Quotation {0} not of type {1}")
 						.format(d.prevdoc_docname, self.order_type))
 
-	def validate_order_type(self):
-		super(SalesOrder, self).validate_order_type()
-
 	def validate_delivery_date(self):
 		if self.order_type == 'Sales' and not self.skip_delivery_note:
 			delivery_date_list = [d.delivery_date for d in self.get("items") if d.delivery_date]
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index feb6b76..d8e9a63 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -321,7 +321,12 @@
 		create_dn_against_so(so.name, 4)
 		make_sales_invoice(so.name)
 
-		trans_item = json.dumps([{'item_code' : '_Test Item 2', 'rate' : 200, 'qty' : 7}])
+		first_item_of_so = so.get("items")[0]
+		trans_item = json.dumps([
+			{'item_code' : first_item_of_so.item_code, 'rate' : first_item_of_so.rate, \
+				'qty' : first_item_of_so.qty, 'docname': first_item_of_so.name},
+			{'item_code' : '_Test Item 2', 'rate' : 200, 'qty' : 7}
+		])
 		update_child_qty_rate('Sales Order', trans_item, so.name)
 
 		so.reload()
@@ -330,6 +335,48 @@
 		self.assertEqual(so.get("items")[-1].qty, 7)
 		self.assertEqual(so.get("items")[-1].amount, 1400)
 		self.assertEqual(so.status, 'To Deliver and Bill')
+	
+	def test_remove_item_in_update_child_qty_rate(self):
+		so = make_sales_order(**{
+			"item_list": [{
+				"item_code": '_Test Item',
+				"qty": 5,
+				"rate":1000
+			}]
+		})
+		create_dn_against_so(so.name, 2)
+		make_sales_invoice(so.name)
+
+		# add an item so as to try removing items
+		trans_item = json.dumps([
+			{"item_code": '_Test Item', "qty": 5, "rate":1000, "docname": so.get("items")[0].name},
+			{"item_code": '_Test Item 2', "qty": 2, "rate":500}
+		])
+		update_child_qty_rate('Sales Order', trans_item, so.name)
+		so.reload()
+		self.assertEqual(len(so.get("items")), 2)
+
+		# check if delivered items can be removed
+		trans_item = json.dumps([{
+			"item_code": '_Test Item 2',
+			"qty": 2,
+			"rate":500,
+			"docname": so.get("items")[1].name
+		}])
+		self.assertRaises(frappe.ValidationError, update_child_qty_rate, 'Sales Order', trans_item, so.name)
+
+		#remove last added item
+		trans_item = json.dumps([{
+			"item_code": '_Test Item',
+			"qty": 5,
+			"rate":1000,
+			"docname": so.get("items")[0].name
+		}])
+		update_child_qty_rate('Sales Order', trans_item, so.name)
+		
+		so.reload()
+		self.assertEqual(len(so.get("items")), 1)
+		self.assertEqual(so.status, 'To Deliver and Bill')
 
 
 	def test_update_child_qty_rate(self):
diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
index aad37d3..4c8973e 100644
--- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json
+++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
@@ -757,11 +757,17 @@
    "fieldname": "additional_notes",
    "fieldtype": "Text",
    "label": "Additional Notes"
+  },
+  {
+   "default": "0",
+   "fieldname": "against_blanket_order",
+   "fieldtype": "Check",
+   "label": "Against Blanket Order"
   }
  ],
  "idx": 1,
  "istable": 1,
- "modified": "2019-12-11 18:06:26.238169",
+ "modified": "2019-12-12 18:06:26.238169",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Sales Order Item",
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js
index 33fbc22..1944c2d 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.js
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.js
@@ -1,5 +1,6 @@
 /* global Clusterize */
 frappe.provide('erpnext.pos');
+frappe.provide('erpnext.queries');
 
 frappe.pages['point-of-sale'].on_page_load = function(wrapper) {
 	frappe.ui.make_app_page({
@@ -556,6 +557,7 @@
 				if (this.cart) {
 					this.cart.frm = this.frm;
 					this.cart.reset();
+					this.cart.reset_pos_field_value();
 				} else {
 					this.make_items();
 					this.make_cart();
@@ -641,11 +643,6 @@
 		var me = this;
 		this.page.clear_menu();
 
-		// for mobile
-		// this.page.add_menu_item(__("Pay"), function () {
-		//
-		// }).addClass('visible-xs');
-
 		this.page.add_menu_item(__("Form View"), function () {
 			frappe.model.sync(me.frm.doc);
 			frappe.set_route("Form", me.frm.doc.doctype, me.frm.doc.name);
@@ -713,6 +710,7 @@
 	make() {
 		this.make_dom();
 		this.make_customer_field();
+		this.make_pos_fields();
 		this.make_loyalty_points();
 		this.make_numpad();
 	}
@@ -722,6 +720,13 @@
 			<div class="pos-cart">
 				<div class="customer-field">
 				</div>
+				<div class="pos-field-section" style="margin-bottom:12px; display:none">
+					<a class="h6 uppercase more-fields-section" disabled> ${__("More Information")} </a>
+					<i class="octicon octicon-chevron-down pos-fields-octicon collapse-indicator"
+						style="color:#cacaca; cursor: pointer"></i>
+					<div class="pos-fields" style ="margin-top:12px">
+					</div>
+				</div>
 				<div class="cart-wrapper">
 					<div class="list-item-table">
 						<div class="list-item list-item--head">
@@ -810,6 +815,22 @@
 		}
 	}
 
+	reset_pos_field_value() {
+		let value = '';
+		if (this.custom_pos_fields) {
+			this.custom_pos_fields.forEach(r => {
+				value = this.frm.doc[r.fieldname] || r.default_value || '';
+
+				if (this.fields) {
+					this.fields[r.fieldname].set_value(value);
+				}
+			})
+		}
+
+		this.wrapper.find('.pos-fields').toggle(false);
+		this.wrapper.find('.pos-fields-octicon').toggle(true);
+	}
+
 	get_grand_total() {
 		let total = this.get_total_template('Grand Total', 'grand-total-value');
 
@@ -948,6 +969,67 @@
 		this.customer_field.set_value(this.frm.doc.customer);
 	}
 
+	make_pos_fields() {
+		const me = this;
+
+		this.fields = {};
+		this.wrapper.find('.pos-fields-octicon, .more-fields-section').click(() => {
+			this.wrapper.find('.pos-fields').toggle();
+			this.wrapper.find('.pos-fields-octicon').toggleClass('octicon-chevron-down').toggleClass('octicon-chevron-up');
+		});
+		this.wrapper.find('.pos-fields').toggle(false);
+
+		return new Promise(res => {
+			frappe.call({
+				method: "erpnext.selling.page.point_of_sale.point_of_sale.get_pos_fields",
+				freeze: true,
+			}).then(r => {
+				if(r.message.length) {
+					this.wrapper.find('.pos-field-section').css('display','block');
+					this.custom_pos_fields = r.message;
+					if (r.message.length < 3) {
+						this.wrapper.find('.pos-fields').toggle(true);
+						this.wrapper.find('.pos-fields-octicon').toggleClass('octicon-chevron-down').toggleClass('octicon-chevron-up');
+					}
+
+					r.message.forEach(field => {
+						this.fields[field.fieldname] = frappe.ui.form.make_control({
+							df: {
+								fieldtype: field.fieldtype,
+								label: field.label,
+								fieldname: field.fieldname,
+								options: field.options,
+								reqd: field.reqd || 0,
+								read_only: field.read_only || 0,
+								default: field.default_value,
+								onchange: function() {
+									if (this.value) {
+										me.frm.set_value(this.df.fieldname, this.value);
+									}
+								},
+								get_query: () => {
+									return this.get_query_for_pos_fields(field.fieldname)
+								},
+							},
+							parent: this.wrapper.find('.pos-fields'),
+							render_input: true
+						});
+
+						if (this.frm.doc[field.fieldname]) {
+							this.fields[field.fieldname].set_value(this.frm.doc[field.fieldname]);
+						}
+					});
+				}
+			});
+		});
+	}
+
+	get_query_for_pos_fields(field) {
+		if (this.frm.fields_dict && this.frm.fields_dict[field]
+			&& this.frm.fields_dict[field].get_query) {
+			return this.frm.fields_dict[field].get_query(this.frm.doc);
+		}
+	}
 
 	make_loyalty_points() {
 		this.available_loyalty_points = frappe.ui.form.make_control({
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py
index a9d2be5..3425f8f 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -160,3 +160,8 @@
 			where {condition} and (name like %(txt)s) limit {start}, {page_len}"""
 		.format(condition = cond, start=start, page_len= page_len),
 			{'txt': '%%%s%%' % txt})
+
+@frappe.whitelist()
+def get_pos_fields():
+	return frappe.get_all("POS Field", fields=["label", "fieldname",
+		"fieldtype", "default_value", "reqd", "read_only", "options"])
\ No newline at end of file
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index 1149254..0524eee 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -270,5 +270,5 @@
 		where `tabStock Ledger Entry`.item_code = %s and `tabStock Ledger Entry`.warehouse = %s
 			and (`tabBatch`.expiry_date >= CURDATE() or `tabBatch`.expiry_date IS NULL)
 		group by batch_id
-		order by `tabBatch`.expiry_date ASC, `tabBatch`.creation ASC'
+		order by `tabBatch`.expiry_date ASC, `tabBatch`.creation ASC
 	""", (item_code, warehouse), as_dict=True)
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.js b/erpnext/stock/doctype/delivery_trip/delivery_trip.js
index 6a7eecf..a025f06 100755
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.js
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.js
@@ -79,6 +79,21 @@
 		}, () => {
 			frm.reload_doc();
 		});
+	},
+
+	driver: function (frm) {
+		if (frm.doc.driver) {
+			frappe.call({
+				method: "erpnext.stock.doctype.delivery_trip.delivery_trip.get_driver_email",
+				args: {
+					driver: frm.doc.driver
+				},
+				callback: (data) => {
+					frm.set_value("driver_email", data.message.email);
+				}
+			});
+		};
+	},
 
 	},
 
@@ -196,4 +211,4 @@
 			frappe.model.set_value(cdt, cdn, "customer_contact", "");
 		}
 	}
-});
\ No newline at end of file
+});
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.json b/erpnext/stock/doctype/delivery_trip/delivery_trip.json
index 0a52624..1bacf46 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.json
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "naming_series:",
  "creation": "2017-10-16 16:45:48.293335",
  "doctype": "DocType",
@@ -13,6 +14,7 @@
   "section_break_3",
   "driver",
   "driver_name",
+  "driver_email",
   "driver_address",
   "total_distance",
   "uom",
@@ -167,10 +169,17 @@
    "fieldtype": "Link",
    "label": "Driver Address",
    "options": "Address"
+  },
+  {
+   "fieldname": "driver_email",
+   "fieldtype": "Data",
+   "label": "Driver Email",
+   "read_only": 1
   }
  ],
  "is_submittable": 1,
- "modified": "2019-09-27 15:43:01.975139",
+ "links": [],
+ "modified": "2019-12-06 17:06:59.681952",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Trip",
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
index 77d322e..e2c5b91 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
@@ -387,3 +387,9 @@
 		file_name="Delivery Note", print_format=dispatch_attachment)
 
 	return [attachments]
+
+@frappe.whitelist()
+def get_driver_email(driver):
+	employee = frappe.db.get_value("Driver", driver, "employee")
+	email = frappe.db.get_value("Employee", employee, "prefered_email")
+	return {"email": email}
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 1b9660e..47f6cf6 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -808,24 +808,26 @@
 
 		if self.bom_no:
 
+			backflush_based_on = frappe.db.get_single_value("Manufacturing Settings",
+				"backflush_raw_materials_based_on")
+
 			if self.purpose in ["Material Issue", "Material Transfer", "Manufacture", "Repack",
 					"Send to Subcontractor", "Material Transfer for Manufacture", "Material Consumption for Manufacture"]:
 
 				if self.work_order and self.purpose == "Material Transfer for Manufacture":
-					item_dict = self.get_pending_raw_materials()
+					item_dict = self.get_pending_raw_materials(backflush_based_on)
 					if self.to_warehouse and self.pro_doc:
 						for item in itervalues(item_dict):
 							item["to_warehouse"] = self.pro_doc.wip_warehouse
 					self.add_to_stock_entry_detail(item_dict)
 
 				elif (self.work_order and (self.purpose == "Manufacture" or self.purpose == "Material Consumption for Manufacture")
-					and not self.pro_doc.skip_transfer and frappe.db.get_single_value("Manufacturing Settings",
-					"backflush_raw_materials_based_on")== "Material Transferred for Manufacture"):
+					and not self.pro_doc.skip_transfer and backflush_based_on == "Material Transferred for Manufacture"):
 					self.get_transfered_raw_materials()
 
-				elif self.work_order and (self.purpose == "Manufacture" or self.purpose == "Material Consumption for Manufacture") and \
-					frappe.db.get_single_value("Manufacturing Settings", "backflush_raw_materials_based_on")== "BOM" and \
-					frappe.db.get_single_value("Manufacturing Settings", "material_consumption")== 1:
+				elif (self.work_order and backflush_based_on== "BOM" and
+					(self.purpose == "Manufacture" or self.purpose == "Material Consumption for Manufacture")
+					and frappe.db.get_single_value("Manufacturing Settings", "material_consumption")== 1):
 					self.get_unconsumed_raw_materials()
 
 				else:
@@ -1034,10 +1036,6 @@
 				filters={'parent': self.work_order, 'item_code': item_code},
 				fields=["required_qty", "consumed_qty"]
 				)
-			if not req_items:
-				frappe.msgprint(_("Did not found transfered item {0} in Work Order {1}, the item not added in Stock Entry")
-					.format(item_code, self.work_order))
-				continue
 
 			req_qty = flt(req_items[0].required_qty)
 			req_qty_each = flt(req_qty / manufacturing_qty)
@@ -1085,18 +1083,20 @@
 					}
 				})
 
-	def get_pending_raw_materials(self):
+	def get_pending_raw_materials(self, backflush_based_on=None):
 		"""
 			issue (item quantity) that is pending to issue or desire to transfer,
 			whichever is less
 		"""
-		item_dict = self.get_pro_order_required_items()
+		item_dict = self.get_pro_order_required_items(backflush_based_on)
+
 		max_qty = flt(self.pro_doc.qty)
 		for item, item_details in iteritems(item_dict):
 			pending_to_issue = flt(item_details.required_qty) - flt(item_details.transferred_qty)
 			desire_to_transfer = flt(self.fg_completed_qty) * flt(item_details.required_qty) / max_qty
 
-			if desire_to_transfer <= pending_to_issue:
+			if (desire_to_transfer <= pending_to_issue or
+				(desire_to_transfer > 0 and backflush_based_on == "Material Transferred for Manufacture")):
 				item_dict[item]["qty"] = desire_to_transfer
 			elif pending_to_issue > 0:
 				item_dict[item]["qty"] = pending_to_issue
@@ -1114,7 +1114,7 @@
 
 		return item_dict
 
-	def get_pro_order_required_items(self):
+	def get_pro_order_required_items(self, backflush_based_on=None):
 		item_dict = frappe._dict()
 		pro_order = frappe.get_doc("Work Order", self.work_order)
 		if not frappe.db.get_value("Warehouse", pro_order.wip_warehouse, "is_group"):
@@ -1123,7 +1123,8 @@
 			wip_warehouse = None
 
 		for d in pro_order.get("required_items"):
-			if (flt(d.required_qty) > flt(d.transferred_qty) and
+			if ( ((flt(d.required_qty) > flt(d.transferred_qty)) or
+				(backflush_based_on == "Material Transferred for Manufacture")) and
 				(d.include_item_in_manufacturing or self.purpose != "Material Transfer for Manufacture")):
 				item_row = d.as_dict()
 				if d.source_warehouse and not frappe.db.get_value("Warehouse", d.source_warehouse, "is_group"):
diff --git a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.js b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.js
index b23c908..23700c9 100644
--- a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.js
+++ b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.js
@@ -16,6 +16,29 @@
 			"fieldtype": "Date",
 			"width": "80",
 			"default": frappe.datetime.get_today()
+		},
+		{
+			"fieldname": "item",
+			"label": __("Item"),
+			"fieldtype": "Link",
+			"options": "Item",
+			"width": "80"
 		}
-	]
+	],
+	"formatter": function (value, row, column, data, default_formatter) {
+		if (column.fieldname == "Batch" && data && !!data["Batch"]) {
+			value = data["Batch"];
+			column.link_onclick = "frappe.query_reports['Batch-Wise Balance History'].set_batch_route_to_stock_ledger(" + JSON.stringify(data) + ")";
+		}
+
+		value = default_formatter(value, row, column, data);
+		return value;
+	},
+	"set_batch_route_to_stock_ledger": function (data) {
+		frappe.route_options = {
+			"batch_no": data["Batch"]
+		};
+
+		frappe.set_route("query-report", "Stock Ledger");
+	}
 }
\ No newline at end of file
diff --git a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py
index 7f7835f..2c95084 100644
--- a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py
+++ b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py
@@ -2,9 +2,11 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
+
 import frappe
 from frappe import _
-from frappe.utils import flt, cint, getdate
+from frappe.utils import cint, flt, getdate
+
 
 def execute(filters=None):
 	if not filters: filters = {}
@@ -17,29 +19,31 @@
 
 	data = []
 	for item in sorted(iwb_map):
-		for wh in sorted(iwb_map[item]):
-			for batch in sorted(iwb_map[item][wh]):
-				qty_dict = iwb_map[item][wh][batch]
-				if qty_dict.opening_qty or qty_dict.in_qty or qty_dict.out_qty or qty_dict.bal_qty:
-					data.append([item, item_map[item]["item_name"], item_map[item]["description"], wh, batch,
-						flt(qty_dict.opening_qty, float_precision), flt(qty_dict.in_qty, float_precision),
-						flt(qty_dict.out_qty, float_precision), flt(qty_dict.bal_qty, float_precision),
-						 item_map[item]["stock_uom"]
-					])
+		if not filters.get("item") or filters.get("item") == item:
+			for wh in sorted(iwb_map[item]):
+				for batch in sorted(iwb_map[item][wh]):
+					qty_dict = iwb_map[item][wh][batch]
+					if qty_dict.opening_qty or qty_dict.in_qty or qty_dict.out_qty or qty_dict.bal_qty:
+						data.append([item, item_map[item]["item_name"], item_map[item]["description"], wh, batch,
+							flt(qty_dict.opening_qty, float_precision), flt(qty_dict.in_qty, float_precision),
+							flt(qty_dict.out_qty, float_precision), flt(qty_dict.bal_qty, float_precision),
+							item_map[item]["stock_uom"]
+						])
 
 	return columns, data
 
+
 def get_columns(filters):
 	"""return columns based on filters"""
 
 	columns = [_("Item") + ":Link/Item:100"] + [_("Item Name") + "::150"] + [_("Description") + "::150"] + \
-	[_("Warehouse") + ":Link/Warehouse:100"] + [_("Batch") + ":Link/Batch:100"] + [_("Opening Qty") + ":Float:90"] + \
-	[_("In Qty") + ":Float:80"] + [_("Out Qty") + ":Float:80"] + [_("Balance Qty") + ":Float:90"] + \
-	[_("UOM") + "::90"]
-
+		[_("Warehouse") + ":Link/Warehouse:100"] + [_("Batch") + ":Link/Batch:100"] + [_("Opening Qty") + ":Float:90"] + \
+		[_("In Qty") + ":Float:80"] + [_("Out Qty") + ":Float:80"] + [_("Balance Qty") + ":Float:90"] + \
+		[_("UOM") + "::90"]
 
 	return columns
 
+
 def get_conditions(filters):
 	conditions = ""
 	if not filters.get("from_date"):
@@ -52,7 +56,8 @@
 
 	return conditions
 
-#get all details
+
+# get all details
 def get_stock_ledger_entries(filters):
 	conditions = get_conditions(filters)
 	return frappe.db.sql("""
@@ -63,6 +68,7 @@
 		order by item_code, warehouse""" %
 		conditions, as_dict=1)
 
+
 def get_item_warehouse_batch_map(filters, float_precision):
 	sle = get_stock_ledger_entries(filters)
 	iwb_map = {}
@@ -90,6 +96,7 @@
 
 	return iwb_map
 
+
 def get_item_details(filters):
 	item_map = {}
 	for d in frappe.db.sql("select name, item_name, description, stock_uom from tabItem", as_dict=1):
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.js b/erpnext/stock/report/stock_ledger/stock_ledger.js
index 3fab327..df3bba5 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.js
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.js
@@ -77,7 +77,15 @@
 			"fieldtype": "Link",
 			"options": "UOM"
 		}
-	]
+	],
+	"formatter": function (value, row, column, data, default_formatter) {
+		value = default_formatter(value, row, column, data);
+		if (column.fieldname == "out_qty" && data.out_qty < 0) {
+			value = "<span style='color:red'>" + value + "</span>";
+		}
+
+		return value;
+	},
 }
 
 // $(function() {
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index d757ecb..fc49db5 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -2,9 +2,11 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
+
 import frappe
-from frappe import _
 from erpnext.stock.utils import update_included_uom_in_report
+from frappe import _
+
 
 def execute(filters=None):
 	include_uom = filters.get("include_uom")
@@ -36,9 +38,24 @@
 
 			sle.update({
 				"qty_after_transaction": actual_qty,
-				"stock_value": stock_value
+				"stock_value": stock_value,
+				"in_qty": max(sle.actual_qty, 0),
+				"out_qty": min(sle.actual_qty, 0)
 			})
 
+		# get the name of the item that was produced using this item
+		if sle.voucher_type == "Stock Entry":
+			purpose, work_order, fg_completed_qty = frappe.db.get_value(sle.voucher_type, sle.voucher_no, ["purpose", "work_order", "fg_completed_qty"])
+
+			if purpose == "Manufacture" and work_order:
+				finished_product = frappe.db.get_value("Work Order", work_order, "item_name")
+				finished_qty = fg_completed_qty
+
+				sle.update({
+					"finished_product": finished_product,
+					"finished_qty": finished_qty,
+				})
+
 		data.append(sle)
 
 		if include_uom:
@@ -47,53 +64,74 @@
 	update_included_uom_in_report(columns, data, include_uom, conversion_factors)
 	return columns, data
 
+
 def get_columns():
 	columns = [
-		{"label": _("Date"), "fieldname": "date", "fieldtype": "Datetime", "width": 95},
-		{"label": _("Item"), "fieldname": "item_code", "fieldtype": "Link", "options": "Item", "width": 130},
+		{"label": _("Date"), "fieldname": "date", "fieldtype": "Datetime", "width": 150},
+		{"label": _("Item"), "fieldname": "item_code", "fieldtype": "Link", "options": "Item", "width": 100},
 		{"label": _("Item Name"), "fieldname": "item_name", "width": 100},
+		{"label": _("Stock UOM"), "fieldname": "stock_uom", "fieldtype": "Link", "options": "UOM", "width": 90},
+		{"label": _("In Qty"), "fieldname": "in_qty", "fieldtype": "Float", "width": 80, "convertible": "qty"},
+		{"label": _("Out Qty"), "fieldname": "out_qty", "fieldtype": "Float", "width": 80, "convertible": "qty"},
+		{"label": _("Balance Qty"), "fieldname": "qty_after_transaction", "fieldtype": "Float", "width": 100, "convertible": "qty"},
+		{"label": _("Finished Product"), "fieldname": "finished_product", "width": 100},
+		{"label": _("Finished Qty"), "fieldname": "finished_qty", "fieldtype": "Float", "width": 100, "convertible": "qty"},
+		{"label": _("Voucher #"), "fieldname": "voucher_no", "fieldtype": "Dynamic Link", "options": "voucher_type", "width": 150},
+		{"label": _("Warehouse"), "fieldname": "warehouse", "fieldtype": "Link", "options": "Warehouse", "width": 150},
 		{"label": _("Item Group"), "fieldname": "item_group", "fieldtype": "Link", "options": "Item Group", "width": 100},
 		{"label": _("Brand"), "fieldname": "brand", "fieldtype": "Link", "options": "Brand", "width": 100},
 		{"label": _("Description"), "fieldname": "description", "width": 200},
-		{"label": _("Warehouse"), "fieldname": "warehouse", "fieldtype": "Link", "options": "Warehouse", "width": 100},
-		{"label": _("Stock UOM"), "fieldname": "stock_uom", "fieldtype": "Link", "options": "UOM", "width": 100},
-		{"label": _("Qty"), "fieldname": "actual_qty", "fieldtype": "Float", "width": 50, "convertible": "qty"},
-		{"label": _("Balance Qty"), "fieldname": "qty_after_transaction", "fieldtype": "Float", "width": 100, "convertible": "qty"},
-		{"label": _("Incoming Rate"), "fieldname": "incoming_rate", "fieldtype": "Currency", "width": 110,
-			"options": "Company:company:default_currency", "convertible": "rate"},
-		{"label": _("Valuation Rate"), "fieldname": "valuation_rate", "fieldtype": "Currency", "width": 110,
-			"options": "Company:company:default_currency", "convertible": "rate"},
-		{"label": _("Balance Value"), "fieldname": "stock_value", "fieldtype": "Currency", "width": 110,
-			"options": "Company:company:default_currency"},
+		{"label": _("Incoming Rate"), "fieldname": "incoming_rate", "fieldtype": "Currency", "width": 110, "options": "Company:company:default_currency", "convertible": "rate"},
+		{"label": _("Valuation Rate"), "fieldname": "valuation_rate", "fieldtype": "Currency", "width": 110, "options": "Company:company:default_currency", "convertible": "rate"},
+		{"label": _("Balance Value"), "fieldname": "stock_value", "fieldtype": "Currency", "width": 110, "options": "Company:company:default_currency"},
 		{"label": _("Voucher Type"), "fieldname": "voucher_type", "width": 110},
 		{"label": _("Voucher #"), "fieldname": "voucher_no", "fieldtype": "Dynamic Link", "options": "voucher_type", "width": 100},
 		{"label": _("Batch"), "fieldname": "batch_no", "fieldtype": "Link", "options": "Batch", "width": 100},
-		{"label": _("Serial #"), "fieldname": "serial_no", "width": 100},
+		{"label": _("Serial #"), "fieldname": "serial_no", "fieldtype": "Link", "options": "Serial No", "width": 100},
 		{"label": _("Project"), "fieldname": "project", "fieldtype": "Link", "options": "Project", "width": 100},
 		{"label": _("Company"), "fieldname": "company", "fieldtype": "Link", "options": "Company", "width": 110}
 	]
 
 	return columns
 
+
 def get_stock_ledger_entries(filters, items):
 	item_conditions_sql = ''
 	if items:
 		item_conditions_sql = 'and sle.item_code in ({})'\
 			.format(', '.join([frappe.db.escape(i) for i in items]))
 
-	return frappe.db.sql("""select concat_ws(" ", posting_date, posting_time) as date,
-			item_code, warehouse, actual_qty, qty_after_transaction, incoming_rate, valuation_rate,
-			stock_value, voucher_type, voucher_no, batch_no, serial_no, company, project, stock_value_difference
-		from `tabStock Ledger Entry` sle
-		where company = %(company)s and
-			posting_date between %(from_date)s and %(to_date)s
-			{sle_conditions}
-			{item_conditions_sql}
-			order by posting_date asc, posting_time asc, creation asc"""\
-		.format(
-			sle_conditions=get_sle_conditions(filters),
-			item_conditions_sql = item_conditions_sql
-		), filters, as_dict=1)
+	sl_entries = frappe.db.sql("""
+		SELECT
+			concat_ws(" ", posting_date, posting_time) AS date,
+			item_code,
+			warehouse,
+			actual_qty,
+			qty_after_transaction,
+			incoming_rate,
+			valuation_rate,
+			stock_value,
+			voucher_type,
+			voucher_no,
+			batch_no,
+			serial_no,
+			company,
+			project,
+			stock_value_difference
+		FROM
+			`tabStock Ledger Entry` sle
+		WHERE
+			company = %(company)s
+				AND posting_date BETWEEN %(from_date)s AND %(to_date)s
+				{sle_conditions}
+				{item_conditions_sql}
+		ORDER BY
+			posting_date asc, posting_time asc, creation asc
+		""".format(sle_conditions=get_sle_conditions(filters), item_conditions_sql=item_conditions_sql),
+		filters, as_dict=1)
+
+	return sl_entries
+
 
 def get_items(filters):
 	conditions = []
@@ -111,6 +149,7 @@
 			.format(" and ".join(conditions)), filters)
 	return items
 
+
 def get_item_details(items, sl_entries, include_uom):
 	item_details = {}
 	if not items:
@@ -140,6 +179,7 @@
 
 	return item_details
 
+
 def get_sle_conditions(filters):
 	conditions = []
 	if filters.get("warehouse"):
@@ -155,6 +195,7 @@
 
 	return "and {}".format(" and ".join(conditions)) if conditions else ""
 
+
 def get_opening_balance(filters, columns):
 	if not (filters.item_code and filters.warehouse and filters.from_date):
 		return
@@ -166,13 +207,17 @@
 		"posting_date": filters.from_date,
 		"posting_time": "00:00:00"
 	})
-	row = {}
-	row["item_code"] = _("'Opening'")
-	for dummy, v in ((9, 'qty_after_transaction'), (11, 'valuation_rate'), (12, 'stock_value')):
-			row[v] = last_entry.get(v, 0)
+
+	row = {
+		"item_code": _("'Opening'"),
+		"qty_after_transaction": last_entry.get("qty_after_transaction", 0),
+		"valuation_rate": last_entry.get("valuation_rate", 0),
+		"stock_value": last_entry.get("stock_value", 0)
+	}
 
 	return row
 
+
 def get_warehouse_condition(warehouse):
 	warehouse_details = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"], as_dict=1)
 	if warehouse_details:
@@ -182,6 +227,7 @@
 
 	return ''
 
+
 def get_item_group_condition(item_group):
 	item_group_details = frappe.db.get_value("Item Group", item_group, ["lft", "rgt"], as_dict=1)
 	if item_group_details: