Merge branch 'develop' into invoice-discounting
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index bc2ddff..bc9c178 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -364,7 +364,7 @@
 			update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
 
 			make_gl_entries(gl_entries,  cancel=(self.docstatus == 2),
-				update_outstanding=update_outstanding, merge_entries=False)
+				update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
 
 			if update_outstanding == "No":
 				update_outstanding_amt(self.credit_to, "Supplier", self.supplier,
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index 261363c..7d4fc63 100755
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -238,7 +238,7 @@
 		customers = [frappe._dict({'name': customers})]
 
 	for data in customers:
-		contact = frappe.db.sql(""" select email_id, phone from `tabContact`
+		contact = frappe.db.sql(""" select email_id, phone, mobile_no from `tabContact`
 			where is_primary_contact=1 and name in
 			(select parent from `tabDynamic Link` where link_doctype = 'Customer' and link_name = %s
 			and parenttype = 'Contact')""", data.name, as_dict=1)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index abbac77..e1256a7 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -698,7 +698,7 @@
 				cint(self.redeem_loyalty_points)) else "Yes"
 
 			make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
-				update_outstanding=update_outstanding, merge_entries=False)
+				update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
 
 			if update_outstanding == "No":
 				from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index ff0c265..8dc00f3 100755
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -817,6 +817,7 @@
 				if(reg.test(data.name.toLowerCase())
 					|| reg.test(data.customer_name.toLowerCase())
 					|| (contact && reg.test(contact["phone"]))
+					|| (contact && reg.test(contact["mobile_no"]))
 					|| (data.customer_group && reg.test(data.customer_group.toLowerCase()))){
 						return data;
 				}
@@ -833,6 +834,7 @@
 				if(contact && !c['phone']) {
 					c["phone"] = contact["phone"];
 					c["email_id"] = contact["email_id"];
+					c["mobile_no"] = contact["mobile_no"];
 				}
 
 				me.customers_mapper.push({
@@ -842,9 +844,10 @@
 					customer_group: c.customer_group,
 					territory: c.territory,
 					phone: contact ? contact["phone"] : '',
+					mobile_no: contact ? contact["mobile_no"] : '',
 					email_id: contact ? contact["email_id"] : '',
 					searchtext: ['customer_name', 'customer_group', 'name', 'value',
-						'label', 'email_id', 'phone']
+						'label', 'email_id', 'phone', 'mobile_no']
 						.map(key => c[key]).join(' ')
 						.toLowerCase()
 				});
diff --git a/erpnext/crm/doctype/opportunity/test_opportunity.py b/erpnext/crm/doctype/opportunity/test_opportunity.py
index 8f61edf..33d9007 100644
--- a/erpnext/crm/doctype/opportunity/test_opportunity.py
+++ b/erpnext/crm/doctype/opportunity/test_opportunity.py
@@ -53,7 +53,7 @@
 				"link_name": customer.name
 			}]
 		})
-		contact.add_email(new_lead_email_id)
+		contact.add_email(new_lead_email_id, is_primary=True)
 		contact.insert(ignore_permissions=True)
 
 		opp_doc = frappe.get_doc(args).insert(ignore_permissions=True)
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 7e33a14..b165b13 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -352,3 +352,53 @@
 		'personal_fields': ['contact_mobile', 'contact_display', 'customer_name'],
 	}
 ]
+
+global_search_doctypes = [
+	{"doctype": "Customer", "index": 0},
+	{"doctype": "Supplier", "index": 1},
+	{"doctype": "Item", "index": 2},
+	{"doctype": "Warehouse", "index": 3},
+	{"doctype": "Account", "index": 4},
+	{"doctype": "Employee", "index": 5},
+	{"doctype": "BOM", "index": 6},
+	{"doctype": "Sales Invoice", "index": 7},
+	{"doctype": "Sales Order", "index": 8},
+	{"doctype": "Quotation", "index": 9},
+	{"doctype": "Work Order", "index": 10},
+	{"doctype": "Purchase Receipt", "index": 11},
+	{"doctype": "Purchase Invoice", "index": 12},
+	{"doctype": "Delivery Note", "index": 13},
+	{"doctype": "Stock Entry", "index": 14},
+	{"doctype": "Material Request", "index": 15},
+	{"doctype": "Delivery Trip", "index": 16},
+	{"doctype": "Pick List", "index": 17},
+	{"doctype": "Salary Slip", "index": 18},
+	{"doctype": "Leave Application", "index": 19},
+	{"doctype": "Expense Claim", "index": 20},
+	{"doctype": "Payment Entry", "index": 21},
+	{"doctype": "Lead", "index": 22},
+	{"doctype": "Opportunity", "index": 23},
+	{"doctype": "Item Price", "index": 24},
+	{"doctype": "Purchase Taxes and Charges Template", "index": 25},
+	{"doctype": "Sales Taxes and Charges", "index": 26},
+	{"doctype": "Asset", "index": 27},
+	{"doctype": "Project", "index": 28},
+	{"doctype": "Task", "index": 29},
+	{"doctype": "Timesheet", "index": 30},
+	{"doctype": "Issue", "index": 31},
+	{"doctype": "Serial No", "index": 32},
+	{"doctype": "Batch", "index": 33},
+	{"doctype": "Branch", "index": 34},
+	{"doctype": "Department", "index": 35},
+	{"doctype": "Employee Grade", "index": 36},
+	{"doctype": "Designation", "index": 37},
+	{"doctype": "Job Opening", "index": 38},
+	{"doctype": "Job Applicant", "index": 39},
+	{"doctype": "Job Offer", "index": 40},
+	{"doctype": "Salary Structure Assignment", "index": 41},
+	{"doctype": "Appraisal", "index": 42},
+	{"doctype": "Loan", "index": 43},
+	{"doctype": "Maintenance Schedule", "index": 44},
+	{"doctype": "Maintenance Visit", "index": 45},
+	{"doctype": "Warranty Claim", "index": 46},
+]
\ No newline at end of file
diff --git a/erpnext/hr/doctype/job_applicant/job_applicant.json b/erpnext/hr/doctype/job_applicant/job_applicant.json
index e9de393..b0cddc2 100644
--- a/erpnext/hr/doctype/job_applicant/job_applicant.json
+++ b/erpnext/hr/doctype/job_applicant/job_applicant.json
@@ -2,7 +2,7 @@
  "allow_copy": 0, 
  "allow_guest_to_view": 0, 
  "allow_import": 0, 
- "allow_rename": 0, 
+ "allow_rename": 1, 
  "autoname": "HR-APP-.YYYY.-.#####", 
  "beta": 0, 
  "creation": "2013-01-29 19:25:37", 
@@ -346,7 +346,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2019-06-21 16:15:43.552049", 
+ "modified": "2019-07-21 16:15:43.552049", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Job Applicant", 
diff --git a/erpnext/hub_node/legacy.py b/erpnext/hub_node/legacy.py
index 85eb1b2..b61b88b 100644
--- a/erpnext/hub_node/legacy.py
+++ b/erpnext/hub_node/legacy.py
@@ -73,7 +73,7 @@
 				{'link_doctype': 'Supplier', 'link_name': supplier.supplier_name}
 			]
 		})
-		contact.add_email(supplier.supplier_email)
+		contact.add_email(supplier.supplier_email, is_primary=True)
 		contact.insert()
 	else:
 		contact = frappe.get_doc('Contact', contact_name)
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index d49b9a9..a8e3ce4 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -350,8 +350,10 @@
 			'link_name': args.get('name')
 		}]
 	})
-	contact.add_email(args.get('email_id'))
-	contact.add_phone(args.get('mobile_no'))
+	if args.get('email_id'):
+		contact.add_email(args.get('email_id'), is_primary=True)
+	if args.get('mobile_no'):
+		contact.add_phone(args.get('mobile_no'), is_primary_mobile_no=True)
 	contact.insert()
 
 	return contact
diff --git a/erpnext/selling/doctype/sms_center/sms_center.py b/erpnext/selling/doctype/sms_center/sms_center.py
index 289b045..bb6ba1f 100644
--- a/erpnext/selling/doctype/sms_center/sms_center.py
+++ b/erpnext/selling/doctype/sms_center/sms_center.py
@@ -31,7 +31,7 @@
 					self.sales_partner.replace("'", "\'") or " and ifnull(dl.link_name, '') != ''"
 		if self.send_to in ['All Contact', 'All Customer Contact', 'All Supplier Contact', 'All Sales Partner Contact']:
 			rec = frappe.db.sql("""select CONCAT(ifnull(c.first_name,''), ' ', ifnull(c.last_name,'')),
-				c.phone from `tabContact` c, `tabDynamic Link` dl  where ifnull(c.phone,'')!='' and
+				c.mobile_no from `tabContact` c, `tabDynamic Link` dl  where ifnull(c.mobile_no,'')!='' and
 				c.docstatus != 2 and dl.parent = c.name%s""" % where_clause)
 
 		elif self.send_to == 'All Lead (Open)':
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index b657165..66598f4 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -9,6 +9,7 @@
 from frappe.desk.page.setup_wizard.setup_wizard import make_records
 from frappe.utils import cstr, getdate
 from erpnext.accounts.doctype.account.account import RootNotEditable
+from frappe.desk.doctype.global_search_settings.global_search_settings import update_global_search_doctypes
 
 default_lead_sources = ["Existing Customer", "Reference", "Advertisement",
 	"Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing",
@@ -274,6 +275,8 @@
 
 	set_more_defaults()
 
+	update_global_search_doctypes()
+
 	# path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(country))
 	# if os.path.exists(path.encode("utf-8")):
 	# 	frappe.get_attr("erpnext.regional.{0}.setup.setup_company_independent_fixtures".format(frappe.scrub(country)))()
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index d68f979..e5dc6b1 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -3,10 +3,10 @@
 
 from __future__ import print_function, unicode_literals
 import frappe
-
 from frappe.utils import flt, cstr, nowdate, nowtime
 from erpnext.stock.utils import update_bin
 from erpnext.stock.stock_ledger import update_entries_after
+from erpnext.controllers.stock_controller import update_gl_entries_after
 
 def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False, only_bin=False):
 	"""
@@ -18,23 +18,29 @@
 		existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
 		frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
 
-	for d in frappe.db.sql("""select distinct item_code, warehouse from
-		(select item_code, warehouse from tabBin
-		union
-		select item_code, warehouse from `tabStock Ledger Entry`) a"""):
-			try:
-				repost_stock(d[0], d[1], allow_zero_rate, only_actual, only_bin)
-				frappe.db.commit()
-			except:
-				frappe.db.rollback()
+	item_warehouses = frappe.db.sql("""
+		select distinct item_code, warehouse
+		from
+			(select item_code, warehouse from tabBin
+			union
+			select item_code, warehouse from `tabStock Ledger Entry`) a
+	""")
+	for d in item_warehouses:
+		try:
+			repost_stock(d[0], d[1], allow_zero_rate, only_actual, only_bin, allow_negative_stock)
+			frappe.db.commit()
+		except:
+			frappe.db.rollback()
 
 	if allow_negative_stock:
 		frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
 	frappe.db.auto_commit_on_many_writes = 0
 
-def repost_stock(item_code, warehouse, allow_zero_rate=False, only_actual=False, only_bin=False):
+def repost_stock(item_code, warehouse, allow_zero_rate=False,
+	only_actual=False, only_bin=False, allow_negative_stock=False):
+
 	if not only_bin:
-		repost_actual_qty(item_code, warehouse, allow_zero_rate)
+		repost_actual_qty(item_code, warehouse, allow_zero_rate, allow_negative_stock)
 
 	if item_code and warehouse and not only_actual:
 		qty_dict = {
@@ -50,11 +56,8 @@
 
 		update_bin_qty(item_code, warehouse, qty_dict)
 
-def repost_actual_qty(item_code, warehouse, allow_zero_rate=False):
-	try:
-		update_entries_after({ "item_code": item_code, "warehouse": warehouse }, allow_zero_rate)
-	except:
-		pass
+def repost_actual_qty(item_code, warehouse, allow_zero_rate=False, allow_negative_stock=False):		update_entries_after({ "item_code": item_code, "warehouse": warehouse },
+		allow_zero_rate=allow_zero_rate, allow_negative_stock=allow_negative_stock)
 
 def get_balance_qty_from_sle(item_code, warehouse):
 	balance_qty = frappe.db.sql("""select qty_after_transaction from `tabStock Ledger Entry`
@@ -227,39 +230,14 @@
 			except:
 				pass
 
-def repost_all_stock_vouchers():
-	warehouses_with_account = frappe.db.sql_list("""select warehouse from tabAccount
-		where ifnull(account_type, '') = 'Stock' and (warehouse is not null and warehouse != '')
-		and is_group=0""")
+def repost_gle_for_stock_transactions(posting_date=None, posting_time=None, for_warehouses=None):
+	frappe.db.auto_commit_on_many_writes = 1
 
-	vouchers = frappe.db.sql("""select distinct voucher_type, voucher_no
-		from `tabStock Ledger Entry` sle
-		where voucher_type != "Serial No" and sle.warehouse in (%s)
-		order by posting_date, posting_time, creation""" %
-		', '.join(['%s']*len(warehouses_with_account)), tuple(warehouses_with_account))
+	if not posting_date:
+		posting_date = "1900-01-01"
+	if not posting_time:
+		posting_time = "00:00"
 
-	rejected = []
-	i = 0
-	for voucher_type, voucher_no in vouchers:
-		i+=1
-		print(i, "/", len(vouchers), voucher_type, voucher_no)
-		try:
-			for dt in ["Stock Ledger Entry", "GL Entry"]:
-				frappe.db.sql("""delete from `tab%s` where voucher_type=%s and voucher_no=%s"""%
-					(dt, '%s', '%s'), (voucher_type, voucher_no))
+	update_gl_entries_after(posting_date, posting_time, for_warehouses=for_warehouses)
 
-			doc = frappe.get_doc(voucher_type, voucher_no)
-			if voucher_type=="Stock Entry" and doc.purpose in ["Manufacture", "Repack"]:
-				doc.calculate_rate_and_amount(force=1)
-			elif voucher_type=="Purchase Receipt" and doc.is_subcontracted == "Yes":
-				doc.validate()
-
-			doc.update_stock_ledger()
-			doc.make_gl_entries(repost_future_gle=False)
-			frappe.db.commit()
-		except Exception:
-			print(frappe.get_traceback())
-			rejected.append([voucher_type, voucher_no])
-			frappe.db.rollback()
-
-	print(rejected)
+	frappe.db.auto_commit_on_many_writes = 0
diff --git a/erpnext/templates/includes/footer/footer_powered.html b/erpnext/templates/includes/footer/footer_powered.html
index d4deaae..cf7661e 100644
--- a/erpnext/templates/includes/footer/footer_powered.html
+++ b/erpnext/templates/includes/footer/footer_powered.html
@@ -1,3 +1,18 @@
 {% set domains = frappe.get_doc("Domain Settings").active_domains %}
+{% set links = {
+	'Manufacturing': '/manufacturing',
+	'Services': '/services',
+	'Retail': '/retail',
+	'Distribution': '/distribution',
+	'Non Profit': '/non-profit',
+	'Education': '/education',
+	'Healthcare': '/healthcare',
+	'Agriculture': '/agriculture',
+	'Hospitality': ''
+} %}
+{% set link = '' %}
+{% if domains %}
+	{% set link = links[domains[0].domain] %}
+{% endif %}
 
-<a href="https://erpnext.com?source=website_footer" target="_blank" class="text-muted">Powered by ERPNext - ERP Software {{ ('for ' + domains[0].domain + ' Companies') if domains else '' }}</a>
+<a href="https://erpnext.com{{ link }}?source=website_footer" target="_blank" class="text-muted">Powered by ERPNext - {{ '' if domains else 'Open Source' }} ERP Software {{ ('for ' + domains[0].domain + ' Companies') if domains else '' }}</a>
diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py
index 7024b0d..dfd3ed7 100644
--- a/erpnext/tests/utils.py
+++ b/erpnext/tests/utils.py
@@ -10,27 +10,32 @@
 	frappe.db.sql('delete from tabAddress')
 	frappe.db.sql('delete from `tabDynamic Link`')
 
-	frappe.get_doc(dict(
-		doctype='Address',
-		address_title='_Test Address for Customer',
-		address_type='Office',
-		address_line1='Station Road',
-		city='_Test City',
-		state='Test State',
-		country='India',
-		links = [dict(
-			link_doctype='Customer',
-			link_name='_Test Customer'
-		)]
-	)).insert()
+	frappe.get_doc({
+		"doctype": "Address",
+		"address_title": "_Test Address for Customer",
+		"address_type": "Office",
+		"address_line1": "Station Road",
+		"city": "_Test City",
+		"state": "Test State",
+		"country": "India",
+		"links": [
+			{
+				"link_doctype": "Customer",
+				"link_name": "_Test Customer"
+			}
+		]
+	}).insert()
 
-	frappe.get_doc(dict(
-		doctype='Contact',
-		email_id='test_contact_customer@example.com',
-		phone='+91 0000000000',
-		first_name='_Test Contact for _Test Customer',
-		links = [dict(
-			link_doctype='Customer',
-			link_name='_Test Customer'
-		)]
-	)).insert()
+	contact = frappe.get_doc({
+		"doctype": 'Contact',
+		"first_name": "_Test Contact for _Test Customer",
+		"links": [
+			{
+				"link_doctype": "Customer",
+				"link_name": "_Test Customer"
+			}
+		]
+	})
+	contact.add_email("test_contact_customer@example.com", is_primary=True)
+	contact.add_phone("+91 0000000000", is_primary_phone=True)
+	contact.insert()