Merge branch 'develop' into payment-terms
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 259c0f0..8535365 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -4,7 +4,7 @@
 import frappe
 from erpnext.hooks import regional_overrides
 
-__version__ = '9.1.1'
+__version__ = '9.1.2'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js
index 97bbc122..cb52627 100755
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.js
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js
@@ -37,10 +37,10 @@
 			return { filters: { doc_type: "Sales Invoice", print_format_type: "Js"} };
 		});
 
-		frappe.db.get_value('POS Settings', {name: 'POS Settings'}, 'is_online', (r) => {
-			is_online = r && cint(r.is_online)
-			frm.toggle_display('offline_pos_section', !is_online);
-			frm.toggle_display('print_format_for_online', is_online);
+		frappe.db.get_value('POS Settings', {name: 'POS Settings'}, 'use_pos_in_offline_mode', (r) => {
+			is_offline = r && cint(r.use_pos_in_offline_mode)
+			frm.toggle_display('offline_pos_section', is_offline);
+			frm.toggle_display('print_format_for_online', !is_offline);
 		});
 	},
 
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index dd10977..ccf8a84 100644
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -88,7 +88,7 @@
 	doc.naming_series = pos_profile.get('naming_series') or 'SINV-'
 	doc.letter_head = pos_profile.get('letter_head') or company_data.default_letter_head
 	doc.ignore_pricing_rule = pos_profile.get('ignore_pricing_rule') or 0
-	doc.apply_discount_on = pos_profile.get('apply_discount_on') if pos_profile.get('apply_discount') else ''
+	doc.apply_discount_on = pos_profile.get('apply_discount_on') or ''
 	doc.customer_group = pos_profile.get('customer_group') or get_root('Customer Group')
 	doc.territory = pos_profile.get('territory') or get_root('Territory')
 	doc.terms = frappe.db.get_value('Terms and Conditions', pos_profile.get('tc_name'), 'terms') or doc.terms or ''
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
index 86b1884..2532ed1 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
@@ -183,16 +183,20 @@
 
 var btn_update_status = function(frm, status){
 	var doc = frm.doc;
-	frappe.call({
-		method:
-		"erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_status",
-		args: {appointmentId: doc.name, status:status},
-		callback: function(data){
-			if(!data.exc){
-				cur_frm.reload_doc();
-			}
+	frappe.confirm(__('Are you sure you want to cancel this appointment?'),
+		function() {
+			frappe.call({
+				method:
+				"erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_status",
+				args: {appointmentId: doc.name, status:status},
+				callback: function(data){
+					if(!data.exc){
+						frm.reload_doc();
+					}
+				}
+			});
 		}
-	});
+	);
 };
 
 var btn_invoice_consultation = function(frm){
diff --git a/erpnext/hub_node/data_migration_mapping/company_to_hub_company/__init__.py b/erpnext/hub_node/data_migration_mapping/company_to_hub_company/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hub_node/data_migration_mapping/company_to_hub_company/__init__.py
diff --git a/erpnext/hub_node/data_migration_mapping/company_to_hub_company/company_to_hub_company.json b/erpnext/hub_node/data_migration_mapping/company_to_hub_company/company_to_hub_company.json
index dac8fe6..0a916da 100644
--- a/erpnext/hub_node/data_migration_mapping/company_to_hub_company/company_to_hub_company.json
+++ b/erpnext/hub_node/data_migration_mapping/company_to_hub_company/company_to_hub_company.json
@@ -35,7 +35,7 @@
  "mapping_name": "Company to Hub Company", 
  "mapping_type": "Push", 
  "migration_id_field": "hub_sync_id", 
- "modified": "2017-09-22 15:32:12.459172", 
+ "modified": "2017-10-09 17:30:17.853929", 
  "modified_by": "Administrator", 
  "name": "Company to Hub Company", 
  "owner": "Administrator", 
diff --git a/erpnext/hub_node/data_migration_mapping/hub_message_to_lead/hub_message_to_lead.json b/erpnext/hub_node/data_migration_mapping/hub_message_to_lead/hub_message_to_lead.json
index a0194ad..cd9fb69 100644
--- a/erpnext/hub_node/data_migration_mapping/hub_message_to_lead/hub_message_to_lead.json
+++ b/erpnext/hub_node/data_migration_mapping/hub_message_to_lead/hub_message_to_lead.json
@@ -21,8 +21,8 @@
  "mapping_name": "Hub Message to Lead", 
  "mapping_type": "Pull", 
  "migration_id_field": "hub_sync_id", 
- "modified": "2017-09-28 13:21:41.575155", 
- "modified_by": "faris@erpnext.com", 
+ "modified": "2017-10-09 17:30:17.908830", 
+ "modified_by": "Administrator", 
  "name": "Hub Message to Lead", 
  "owner": "frappetest@gmail.com", 
  "page_length": 10, 
diff --git a/erpnext/hub_node/data_migration_mapping/item_to_hub_item/__init__.py b/erpnext/hub_node/data_migration_mapping/item_to_hub_item/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hub_node/data_migration_mapping/item_to_hub_item/__init__.py
diff --git a/erpnext/hub_node/data_migration_mapping/item_to_hub_item/item_to_hub_item.json b/erpnext/hub_node/data_migration_mapping/item_to_hub_item/item_to_hub_item.json
index ef90918..e4168c7 100644
--- a/erpnext/hub_node/data_migration_mapping/item_to_hub_item/item_to_hub_item.json
+++ b/erpnext/hub_node/data_migration_mapping/item_to_hub_item/item_to_hub_item.json
@@ -1,4 +1,5 @@
 {
+ "condition": "{\"publish_in_hub\": 1}", 
  "creation": "2017-09-07 13:27:52.726350", 
  "docstatus": 0, 
  "doctype": "Data Migration Mapping", 
@@ -44,7 +45,7 @@
  "mapping_name": "Item to Hub Item", 
  "mapping_type": "Push", 
  "migration_id_field": "hub_sync_id", 
- "modified": "2017-09-22 15:32:12.674169", 
+ "modified": "2017-10-09 17:30:17.890337", 
  "modified_by": "Administrator", 
  "name": "Item to Hub Item", 
  "owner": "Administrator", 
diff --git a/erpnext/hub_node/data_migration_plan/hub_sync/hub_sync.json b/erpnext/hub_node/data_migration_plan/hub_sync/hub_sync.json
index 9edbac9..40513cd2 100644
--- a/erpnext/hub_node/data_migration_plan/hub_sync/hub_sync.json
+++ b/erpnext/hub_node/data_migration_plan/hub_sync/hub_sync.json
@@ -1,26 +1,26 @@
 {
- "creation": "2017-09-07 11:39:38.445902",
- "docstatus": 0,
- "doctype": "Data Migration Plan",
- "idx": 1,
+ "creation": "2017-09-07 11:39:38.445902", 
+ "docstatus": 0, 
+ "doctype": "Data Migration Plan", 
+ "idx": 1, 
  "mappings": [
   {
-   "enabled": 1,
+   "enabled": 1, 
    "mapping": "Company to Hub Company"
-  },
+  }, 
   {
-   "enabled": 1,
+   "enabled": 1, 
    "mapping": "Item to Hub Item"
-  },
+  }, 
   {
-   "enabled": 1,
+   "enabled": 1, 
    "mapping": "Hub Message to Lead"
   }
- ],
- "modified": "2017-09-28 15:37:17.616828",
- "modified_by": "faris@erpnext.com",
- "module": "Hub Node",
- "name": "Hub Sync",
- "owner": "Administrator",
+ ], 
+ "modified": "2017-10-09 17:30:17.680059", 
+ "modified_by": "Administrator", 
+ "module": "Hub Node", 
+ "name": "Hub Sync", 
+ "owner": "Administrator", 
  "plan_name": "Hub Sync"
 }
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 93a41f3..ead5d33 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -128,7 +128,7 @@
 			 'uom'			: item and args['stock_uom'] or '',
  			 'conversion_factor': 1,
 			 'bom_no'		: args['bom_no'],
-			 'rate'			: rate / self.conversion_rate,
+			 'rate'			: rate / self.conversion_rate if self.conversion_rate else rate,
 			 'qty'			: args.get("qty") or args.get("stock_qty") or 1,
 			 'stock_qty'	: args.get("qty") or args.get("stock_qty") or 1,
 			 'base_rate'	: rate
@@ -374,7 +374,7 @@
 			if d.workstation:
 				if not d.hour_rate:
 					hour_rate = flt(frappe.db.get_value("Workstation", d.workstation, "hour_rate"))
-					d.hour_rate = hour_rate / flt(self.conversion_rate)
+					d.hour_rate = hour_rate / flt(self.conversion_rate) if self.conversion_rate else hour_rate
 
 			if d.hour_rate and d.time_in_mins:
 				d.base_hour_rate = flt(d.hour_rate) * flt(self.conversion_rate)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 7bc947e..8aa7aa5 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -451,6 +451,7 @@
 erpnext.patches.v9_0.fix_subscription_next_date
 erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
 erpnext.patches.v9_0.student_admission_childtable_migrate
+erpnext.patches.v9_0.add_healthcare_domain
 erpnext.patches.v8_10.add_due_date_to_gle
 erpnext.patches.v8_10.update_gl_due_date_for_pi_and_si
 erpnext.patches.v8_10.add_payment_terms_field_to_supplier
diff --git a/erpnext/patches/v9_0/add_healthcare_domain.py b/erpnext/patches/v9_0/add_healthcare_domain.py
new file mode 100644
index 0000000..45fceb1
--- /dev/null
+++ b/erpnext/patches/v9_0/add_healthcare_domain.py
@@ -0,0 +1,14 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+
+def execute():
+	domain = _('Healthcare')
+	if not frappe.db.exists('Domain', domain):
+		frappe.get_doc({
+			'doctype': 'Domain',
+			'domain': domain
+		}).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/public/js/communication.js b/erpnext/public/js/communication.js
index 5ce57b6..bb2eaef 100644
--- a/erpnext/public/js/communication.js
+++ b/erpnext/public/js/communication.js
@@ -1,39 +1,45 @@
 frappe.ui.form.on("Communication", {
-	refresh: function(frm) {
+	refresh: (frm) => {
+		// setup custom Make button only if Communication is Email
+		if(frm.doc.communication_medium == "Email" && frm.doc.sent_or_received == "Received") {
+			frm.events.setup_custom_buttons(frm);
+		}
+	},
+
+	setup_custom_buttons: (frm) => {
+		let confirm_msg = "Are you sure you want to create {0} from this email";
 		if(frm.doc.reference_doctype !== "Issue") {
-			frm.add_custom_button(__("Issue"), function() {
-				frappe.confirm("Are you sure you want to create Issue from this email", function(){
+			frm.add_custom_button(__("Issue"), () => {
+				frappe.confirm(__(confirm_msg, [__("Issue")]), () => {
 					frm.trigger('make_issue_from_communication');
 				})
 			}, "Make");
 		}
 
 		if(!in_list(["Lead", "Opportunity"], frm.doc.reference_doctype)) {
-			frm.add_custom_button(__("Lead"), function() {
-				frappe.confirm("Are you sure you want to create Lead from this email", function(){
+			frm.add_custom_button(__("Lead"), () => {
+				frappe.confirm(__(confirm_msg, [__("Lead")]), () => {
 					frm.trigger('make_lead_from_communication');	
 				})
 			}, "Make");
 
-			frm.add_custom_button(__("Opportunity"), function() {
-				frappe.confirm("Are you sure you want to create Opportunity from this email", function(){
+			frm.add_custom_button(__("Opportunity"), () => {
+				frappe.confirm(__(confirm_msg, [__("Opportunity")]), () => {
 					frm.trigger('make_opportunity_from_communication');
 				})
 			}, "Make");
 		}
-
-
 		frm.page.set_inner_btn_group_as_primary(__("Make"));
 	},
 
-	make_lead_from_communication: function(frm) {
+	make_lead_from_communication: (frm) => {
 		return frappe.call({
 			method: "frappe.email.inbox.make_lead_from_communication",
 			args: {
 				communication: frm.doc.name
 			},
 			freeze: true,
-			callback: function(r) {
+			callback: (r) => {
 				if(r.message) {
 					frm.reload_doc()
 				}
@@ -41,14 +47,14 @@
 		})
 	},
 
-	make_issue_from_communication: function(frm) {
+	make_issue_from_communication: (frm) => {
 		return frappe.call({
 			method: "frappe.email.inbox.make_issue_from_communication",
 			args: {
 				communication: frm.doc.name
 			},
 			freeze: true,
-			callback: function(r) {
+			callback: (r) => {
 				if(r.message) {
 					frm.reload_doc()
 				}
@@ -56,14 +62,14 @@
 		})
 	},
 
-	make_opportunity_from_communication: function(frm) {
+	make_opportunity_from_communication: (frm) => {
 		return frappe.call({
 			method: "frappe.email.inbox.make_opportunity_from_communication",
 			args: {
 				communication: frm.doc.name
 			},
 			freeze: true,
-			callback: function(r) {
+			callback: (r) => {
 				if(r.message) {
 					frm.reload_doc()
 				}
diff --git a/erpnext/public/js/pos/pos.html b/erpnext/public/js/pos/pos.html
index 485a945..1d9fd7c 100644
--- a/erpnext/public/js/pos/pos.html
+++ b/erpnext/public/js/pos/pos.html
@@ -37,7 +37,6 @@
 					<div class="cell price-cell text-right tax-table">
 					</div>
 				</div>
-				{% if (apply_discount_on) { %}
 				<div class="pos-list-row discount-amount-area">
 					<div class="cell"></div>
 					<div class="cell text-right">{%= __("Discount") %}</div>
@@ -52,7 +51,6 @@
 						</div>
 					</div>
 				</div>
-				{% } %}
 				<div class="pos-list-row grand-total-area collapse-btn" style="border-bottom:1px solid #d1d8dd;">
 					<div class="cell">
 						<a class="">
diff --git a/erpnext/schools/doctype/fees/fees.py b/erpnext/schools/doctype/fees/fees.py
index a2fcecc..42b329e 100644
--- a/erpnext/schools/doctype/fees/fees.py
+++ b/erpnext/schools/doctype/fees/fees.py
@@ -50,6 +50,7 @@
 			select g.email_address
 			from `tabGuardian` g, `tabStudent Guardian` sg
 			where g.name = sg.guardian and sg.parent = %s and sg.parenttype = 'Student'
+			and ifnull(g.email_address, '')!=''
 		""", self.student)
 
 		student_email_id = frappe.db.get_value("Student", self.student, "student_email_id")
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 726e80f..c042244 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.js
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.js
@@ -222,6 +222,11 @@
 	}
 
 	update_item_in_frm(item, field, value) {
+		if (field == 'qty' && value < 0) {
+			frappe.msgprint(__("Quantity must be positive"));
+			value = item.qty;
+		}
+
 		if (field) {
 			frappe.model.set_value(item.doctype, item.name, field, value);
 		}
@@ -518,7 +523,7 @@
 
 		// Update totals
 		this.$taxes_and_totals.find('.net-total')
-			.html(format_currency(this.frm.doc.net_total, currency));
+			.html(format_currency(this.frm.doc.total, currency));
 
 		// Update taxes
 		const taxes_html = this.frm.doc.taxes.map(tax => {
@@ -943,6 +948,7 @@
 			if (this.search_index[search_term]) {
 				const items = this.search_index[search_term];
 				this.render_items(items);
+				this.set_item_in_the_cart(items);
 				return;
 			}
 		} else if (item_group == "All Item Groups") {
@@ -956,19 +962,32 @@
 				}
 
 				this.render_items(items);
-				if(serial_no) {
-					this.events.update_cart(items[0].item_code,
-						'serial_no', serial_no);
-					this.reset_search_field();
-				}
-				if(batch_no) {
-					this.events.update_cart(items[0].item_code,
-						'batch_no', batch_no);
-					this.reset_search_field();
-				}
+				this.set_item_in_the_cart(items, serial_no, batch_no);
 			});
 	}
 
+	set_item_in_the_cart(items, serial_no, batch_no) {
+		if (serial_no) {
+			this.events.update_cart(items[0].item_code,
+				'serial_no', serial_no);
+			this.reset_search_field();
+			return;
+		}
+
+		if (batch_no) {
+			this.events.update_cart(items[0].item_code,
+				'batch_no', batch_no);
+			this.reset_search_field();
+			return;
+		}
+
+		if (items.length === 1) {
+			this.events.update_cart(items[0].item_code,
+				'qty', '+1');
+			this.reset_search_field();
+		}
+	}
+
 	reset_search_field() {
 		this.search_field.set_value('');
 		this.search_field.$input.trigger("input");