Merge pull request #7533 from mbauskar/minor-fixes

[WIP] Address and Contact Fixes
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js
index 720a1dc..c03ccc8 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.js
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.js
@@ -21,20 +21,12 @@
 		if(this.frm.get_field('shipping_address')) {
 			this.frm.set_query("shipping_address", function(){
 				if(me.frm.doc.customer){
-					return{
-						filters:{
-							"customer": me.frm.doc.customer
-						}
-					}
-				}
-				else{
-					return{
-						filters:{
-							"is_your_company_address": 1,
-							"company": me.frm.doc.company
-						}
-					}
-				}
+					return {
+						query: 'frappe.geo.doctype.address.address.address_query',
+						filters: { link_doctype: 'Customer', link_name: me.frm.doc.customer }
+					};
+				} else
+					return erpnext.queries.company_address_query(me.frm.doc)
 			});
 		}
 	},
diff --git a/erpnext/buying/doctype/supplier/supplier.js b/erpnext/buying/doctype/supplier/supplier.js
index ce6f451..7e5e045 100644
--- a/erpnext/buying/doctype/supplier/supplier.js
+++ b/erpnext/buying/doctype/supplier/supplier.js
@@ -26,11 +26,11 @@
 
 		if(frm.doc.__islocal){
 	    	hide_field(['address_html','contact_html']);
-			erpnext.utils.clear_address_and_contact(frm);
+			frappe.geo.clear_address_and_contact(frm);
 		}
 		else {
 		  	unhide_field(['address_html','contact_html']);
-			erpnext.utils.render_address_and_contact(frm);
+			frappe.geo.render_address_and_contact(frm);
 
 			// custom buttons
 			frm.add_custom_button(__('Accounting Ledger'), function() {
diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py
index 9eaaad1..7f92767 100644
--- a/erpnext/buying/doctype/supplier/supplier.py
+++ b/erpnext/buying/doctype/supplier/supplier.py
@@ -6,7 +6,7 @@
 import frappe.defaults
 from frappe import msgprint, _
 from frappe.model.naming import make_autoname
-from erpnext.utilities.address_and_contact import (load_address_and_contact,
+from frappe.geo.address_and_contact import (load_address_and_contact,
 	delete_contact_and_address)
 
 from erpnext.utilities.transaction_base import TransactionBase
@@ -61,14 +61,6 @@
 		validate_party_accounts(self)
 		self.status = get_party_status(self)
 
-	def get_contacts(self,nm):
-		if nm:
-			contact_details =frappe.db.convert_to_lists(frappe.db.sql("select name, CONCAT(IFNULL(first_name,''),' ',IFNULL(last_name,'')),contact_no,email_id from `tabContact` where supplier = %s", nm))
-
-			return contact_details
-		else:
-			return ''
-
 	def on_trash(self):
 		delete_contact_and_address('Supplier', self.name)
 
diff --git a/erpnext/buying/report/supplier_addresses_and_contacts/__init__.py b/erpnext/buying/report/supplier_addresses_and_contacts/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/buying/report/supplier_addresses_and_contacts/__init__.py
+++ /dev/null
diff --git a/erpnext/buying/report/supplier_addresses_and_contacts/supplier_addresses_and_contacts.json b/erpnext/buying/report/supplier_addresses_and_contacts/supplier_addresses_and_contacts.json
deleted file mode 100644
index 128548f..0000000
--- a/erpnext/buying/report/supplier_addresses_and_contacts/supplier_addresses_and_contacts.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "apply_user_permissions": 1, 
- "creation": "2013-10-09 10:38:40", 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 1, 
- "is_standard": "Yes", 
- "modified": "2014-09-11 08:53:17.358554", 
- "modified_by": "Administrator",
- "module": "Buying", 
- "name": "Supplier Addresses and Contacts", 
- "owner": "Administrator", 
- "query": "SELECT\n    `tabSupplier`.name as \"Supplier:Link/Supplier:120\",\n\t`tabSupplier`.supplier_name as \"Supplier Name::120\",\n\t`tabSupplier`.supplier_type as \"Supplier Type:Link/Supplier Type:120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2), \n\t\ttabAddress.state, tabAddress.pincode, tabAddress.country\n\t) as 'Address::180',\n    concat_ws(', ', `tabContact`.first_name, `tabContact`.last_name) as \"Contact Name::180\",\n\t`tabContact`.phone as \"Phone\",\n\t`tabContact`.mobile_no as \"Mobile No\",\n\t`tabContact`.email_id as \"Email Address::120\",\n\t`tabContact`.is_primary_contact as \"Is Primary Contact::120\"\nFROM\n\t`tabSupplier`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.supplier=`tabSupplier`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.supplier=`tabSupplier`.name\n\t)\nWHERE\n\t`tabSupplier`.docstatus<2\nORDER BY\n\t`tabSupplier`.name asc", 
- "ref_doctype": "Supplier", 
- "report_name": "Supplier Addresses and Contacts", 
- "report_type": "Query Report"
-}
\ No newline at end of file
diff --git a/erpnext/config/buying.py b/erpnext/config/buying.py
index e246266..990ca7a 100644
--- a/erpnext/config/buying.py
+++ b/erpnext/config/buying.py
@@ -172,8 +172,12 @@
 				{
 					"type": "report",
 					"is_query_report": True,
-					"name": "Supplier Addresses and Contacts",
-					"doctype": "Supplier"
+					"name": "Addresses And Contacts",
+					"label": "Supplier Addresses And Contacts",
+					"doctype": "Address",
+					"route_options": {
+						"party_type": "Supplier"
+					}
 				},
 			]
 		},
diff --git a/erpnext/config/selling.py b/erpnext/config/selling.py
index c406d09..bbae245 100644
--- a/erpnext/config/selling.py
+++ b/erpnext/config/selling.py
@@ -120,6 +120,16 @@
 				{
 					"type": "report",
 					"is_query_report": True,
+					"name": "Addresses And Contacts",
+					"label": "Sales Partner Addresses And Contacts",
+					"doctype": "Address",
+					"route_options": {
+						"party_type": "Sales Partner"
+					}
+				},
+				{
+					"type": "report",
+					"is_query_report": True,
 					"name": "Territory Target Variance (Item Group-Wise)",
 					"route": "query-report/Territory Target Variance Item Group-Wise",
 					"doctype": "Territory"
@@ -215,8 +225,12 @@
 				{
 					"type": "report",
 					"is_query_report": True,
-					"name": "Customer Addresses And Contacts",
-					"doctype": "Contact"
+					"name": "Addresses And Contacts",
+					"label": "Customer Addresses And Contacts",
+					"doctype": "Address",
+					"route_options": {
+						"party_type": "Customer"
+					}
 				},
 				{
 					"type": "report",
diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js
index be3cd82..7e22125 100644
--- a/erpnext/crm/doctype/lead/lead.js
+++ b/erpnext/crm/doctype/lead/lead.js
@@ -25,6 +25,7 @@
 	refresh: function() {
 		var doc = this.frm.doc;
 		erpnext.toggle_naming_series();
+		frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'name', doctype: 'Lead'}
 
 		if(!this.frm.doc.__islocal && this.frm.doc.__onload && !this.frm.doc.__onload.is_customer) {
 			this.frm.add_custom_button(__("Customer"), this.create_customer, __("Make"));
@@ -34,9 +35,9 @@
 		}
 
 		if(!this.frm.doc.__islocal) {
-			erpnext.utils.render_address_and_contact(cur_frm);
+			frappe.geo.render_address_and_contact(cur_frm);
 		} else {
-			erpnext.utils.clear_address_and_contact(cur_frm);
+			frappe.geo.clear_address_and_contact(cur_frm);
 		}
 	},
 
diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py
index 4b2899d..411f597 100644
--- a/erpnext/crm/doctype/lead/lead.py
+++ b/erpnext/crm/doctype/lead/lead.py
@@ -8,7 +8,7 @@
 from frappe.model.mapper import get_mapped_doc
 
 from erpnext.controllers.selling_controller import SellingController
-from erpnext.utilities.address_and_contact import load_address_and_contact
+from frappe.geo.address_and_contact import load_address_and_contact
 from erpnext.accounts.party import set_taxes
 
 sender_field = "email_id"
@@ -127,7 +127,7 @@
 
 @frappe.whitelist()
 def make_opportunity(source_name, target_doc=None):
-	target_doc = get_mapped_doc("Lead", source_name,
+	target_doc = get_mapped_doc("Lead", source_name, 
 		{"Lead": {
 			"doctype": "Opportunity",
 			"field_map": {
diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py
index 4bb6765..301dc82 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.py
+++ b/erpnext/crm/doctype/opportunity/opportunity.py
@@ -106,30 +106,6 @@
 			lead_name, company_name = frappe.db.get_value("Lead", self.lead, ["lead_name", "company_name"])
 			self.customer_name = company_name or lead_name
 
-	def get_cust_address(self,name):
-		details = frappe.db.sql("""select customer_name, address, territory, customer_group
-			from `tabCustomer` where name = %s and docstatus != 2""", (name), as_dict = 1)
-		if details:
-			ret = {
-				'customer_name':	details and details[0]['customer_name'] or '',
-				'address'	:	details and details[0]['address'] or '',
-				'territory'			 :	details and details[0]['territory'] or '',
-				'customer_group'		:	details and details[0]['customer_group'] or ''
-			}
-			# ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query)
-
-			contact_det = frappe.db.sql("""select contact_name, contact_no, email_id
-				from `tabContact` where customer = %s and is_customer = 1
-					and is_primary_contact = 'Yes' and docstatus != 2""", name, as_dict = 1)
-
-			ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or ''
-			ret['contact_no']		 = contact_det and contact_det[0]['contact_no'] or ''
-			ret['email_id']			 = contact_det and contact_det[0]['email_id'] or ''
-
-			return ret
-		else:
-			frappe.throw(_("Customer {0} does not exist").format(name), frappe.DoesNotExistError)
-
 	def on_update(self):
 		self.add_calendar_event()
 
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 8443cdf..dac7c6b 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -126,16 +126,6 @@
 	"Discussion": "erpnext.schools.web_form.discussion.discussion.has_website_permission"
 }
 
-permission_query_conditions = {
-	"Contact": "erpnext.utilities.address_and_contact.get_permission_query_conditions_for_contact",
-	"Address": "erpnext.utilities.address_and_contact.get_permission_query_conditions_for_address"
-}
-
-has_permission = {
-	"Contact": "erpnext.utilities.address_and_contact.has_permission",
-	"Address": "erpnext.utilities.address_and_contact.has_permission"
-}
-
 dump_report_map = "erpnext.startup.report_data_map.data_map"
 
 before_tests = "erpnext.setup.utils.before_tests"
@@ -153,7 +143,7 @@
 		"after_insert": "frappe.email.doctype.contact.contact.update_contact",
 		"validate": "erpnext.hr.doctype.employee.employee.validate_employee_role",
 		"on_update": "erpnext.hr.doctype.employee.employee.update_user_permissions",
-		"on_update": "erpnext.utilities.address_and_contact.set_default_role"
+		"on_update": "frappe.geo.address_and_contact.set_default_role"
 	},
 	("Sales Taxes and Charges Template", 'Price List'): {
 		"on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings"
diff --git a/erpnext/public/js/queries.js b/erpnext/public/js/queries.js
index 1141f99..1963137 100644
--- a/erpnext/public/js/queries.js
+++ b/erpnext/public/js/queries.js
@@ -68,6 +68,13 @@
 		}
 	},
 
+	company_address_query: function(doc) {
+		return {
+			query: 'frappe.geo.doctype.address.address.address_query',
+			filters: { is_your_company_address: 1, link_doctype: 'Company', link_name: doc.company || '' }
+		};
+	},
+
 	supplier_filter: function(doc) {
 		if(!doc.supplier) {
 			frappe.throw(__("Please set {0}", __(frappe.meta.get_label(doc.doctype, "supplier", doc.name))));
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 74e9fb6..551ea51 100644
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -82,32 +82,6 @@
 
 
 $.extend(erpnext.utils, {
-	clear_address_and_contact: function(frm) {
-		$(frm.fields_dict['address_html'].wrapper).html("");
-		frm.fields_dict['contact_html'] && $(frm.fields_dict['contact_html'].wrapper).html("");
-	},
-
-	render_address_and_contact: function(frm) {
-		// render address
-		$(frm.fields_dict['address_html'].wrapper)
-			.html(frappe.render_template("address_list",
-				cur_frm.doc.__onload))
-			.find(".btn-address").on("click", function() {
-				frappe.new_doc("Address");
-			});
-
-		// render contact
-		if(frm.fields_dict['contact_html']) {
-			$(frm.fields_dict['contact_html'].wrapper)
-				.html(frappe.render_template("contact_list",
-					cur_frm.doc.__onload))
-				.find(".btn-contact").on("click", function() {
-					frappe.new_doc("Contact");
-				}
-			);
-		}
-	},
-
 	set_party_dashboard_indicators: function(frm) {
 		if(frm.doc.__onload && frm.doc.__onload.dashboard_info) {
 			var info = frm.doc.__onload.dashboard_info;
diff --git a/erpnext/selling/doctype/customer/customer.js b/erpnext/selling/doctype/customer/customer.js
index 747b31e..540ec28 100644
--- a/erpnext/selling/doctype/customer/customer.js
+++ b/erpnext/selling/doctype/customer/customer.js
@@ -37,7 +37,7 @@
 		frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
 
 		if(!frm.doc.__islocal) {
-			erpnext.utils.render_address_and_contact(frm);
+			frappe.geo.render_address_and_contact(frm);
 
 			// custom buttons
 			frm.add_custom_button(__('Accounting Ledger'), function() {
@@ -53,7 +53,7 @@
 			erpnext.utils.set_party_dashboard_indicators(frm);
 
 		} else {
-			erpnext.utils.clear_address_and_contact(frm);
+			frappe.geo.clear_address_and_contact(frm);
 		}
 
 		var grid = cur_frm.get_field("sales_team").grid;
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index d8011af..e14cde0 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -9,7 +9,7 @@
 from frappe.utils import flt, cint, cstr
 from frappe.desk.reportview import build_match_conditions
 from erpnext.utilities.transaction_base import TransactionBase
-from erpnext.utilities.address_and_contact import load_address_and_contact, delete_contact_and_address
+from frappe.geo.address_and_contact import load_address_and_contact, delete_contact_and_address
 from erpnext.accounts.party import validate_party_accounts, get_timeline_data # keep this
 from erpnext.accounts.party_status import get_party_status
 from erpnext import get_default_currency
@@ -95,9 +95,14 @@
 	def create_lead_address_contact(self):
 		if self.lead_name:
 			# assign lead address to customer (if already not set)
-			address_name = frappe.get_value('Dynamic Link', dict(parenttype='Address', link_doctype='Lead', link_name=self.name))
-			if address_name:
-				address = frappe.get_doc('Address', address_name)
+			address_names = frappe.get_all('Dynamic Link', filters={
+								"parenttype":"Address",
+								"link_doctype":"Lead",
+								"link_name":self.lead_name
+							}, fields=["parent as name"])
+
+			for address_name in address_names:
+				address = frappe.get_doc('Address', address_name.get('name'))
 				if not address.has_link('Customer', self.name):
 					address.append('links', dict(link_doctype='Customer', link_name=self.name))
 					address.save()
@@ -105,17 +110,17 @@
 			lead = frappe.db.get_value("Lead", self.lead_name, ["lead_name", "email_id", "phone", "mobile_no"], as_dict=True)
 
 			# create contact from lead
-			c = frappe.new_doc('Contact')
-			c.first_name = lead.lead_name
-			c.email_id = lead.email_id
-			c.phone = lead.phone
-			c.mobile_no = lead.mobile_no
-			c.is_primary_contact = 1
-			c.append('links', dict(link_doctype='Customer', link_name=self.name))
-			c.flags.ignore_permissions = self.flags.ignore_permissions
-			c.autoname()
-			if not frappe.db.exists("Contact", c.name):
-				c.insert()
+			contact = frappe.new_doc('Contact')
+			contact.first_name = lead.lead_name
+			contact.email_id = lead.email_id
+			contact.phone = lead.phone
+			contact.mobile_no = lead.mobile_no
+			contact.is_primary_contact = 1
+			contact.append('links', dict(link_doctype='Customer', link_name=self.name))
+			contact.flags.ignore_permissions = self.flags.ignore_permissions
+			contact.autoname()
+			if not frappe.db.exists("Contact", contact.name):
+				contact.insert()
 
 	def validate_name_with_customer_group(self):
 		if frappe.db.exists("Customer Group", self.name):
@@ -133,7 +138,7 @@
 	def on_trash(self):
 		delete_contact_and_address('Customer', self.name)
 		if self.lead_name:
-			frappe.db.sql("update `tabLead` set status='Interested' where name=%s",self.lead_name)
+			frappe.db.sql("update `tabLead` set status='Interested' where name=%s", self.lead_name)
 
 	def after_rename(self, olddn, newdn, merge=False):
 		if frappe.defaults.get_global_default('cust_master_name') == 'Customer Name':
diff --git a/erpnext/selling/page/sales_funnel/sales_funnel.py b/erpnext/selling/page/sales_funnel/sales_funnel.py
index 4d12efd..3c4d528 100644
--- a/erpnext/selling/page/sales_funnel/sales_funnel.py
+++ b/erpnext/selling/page/sales_funnel/sales_funnel.py
@@ -12,9 +12,9 @@
 		where (date(`modified`) between %s and %s)
 		and status != "Do Not Contact" """, (from_date, to_date))[0][0]
 
-	active_leads += frappe.db.sql("""select count(distinct customer) from `tabContact`
-		where (date(`modified`) between %s and %s)
-		and status != "Passive" """, (from_date, to_date))[0][0]
+	active_leads += frappe.db.sql("""select count(distinct contact.name) from `tabContact` contact
+		left join `tabDynamic Link` dl on (dl.parent=contact.name) where dl.link_doctype='Customer' 
+		and (date(contact.modified) between %s and %s) and status != "Passive" """, (from_date, to_date))[0][0]
 
 	opportunities = frappe.db.sql("""select count(*) from `tabOpportunity`
 		where (date(`creation`) between %s and %s)
diff --git a/erpnext/selling/report/customer_addresses_and_contacts/__init__.py b/erpnext/selling/report/customer_addresses_and_contacts/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/selling/report/customer_addresses_and_contacts/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/report/customer_addresses_and_contacts/customer_addresses_and_contacts.json b/erpnext/selling/report/customer_addresses_and_contacts/customer_addresses_and_contacts.json
deleted file mode 100644
index 1f6707b..0000000
--- a/erpnext/selling/report/customer_addresses_and_contacts/customer_addresses_and_contacts.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "add_total_row": 0, 
- "apply_user_permissions": 1, 
- "creation": "2012-10-04 18:45:27", 
- "disabled": 0, 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 1, 
- "is_standard": "Yes", 
- "modified": "2015-08-24 11:44:00.711112", 
- "modified_by": "Administrator", 
- "module": "Selling", 
- "name": "Customer Addresses And Contacts", 
- "owner": "Administrator", 
- "query": "SELECT\n\t`tabCustomer`.name as \"Customer ID:Link/Customer\",\n\t`tabCustomer`.customer_name as \"Customer Name\",\n\t`tabCustomer`.customer_group as \"Customer Group:Link/Customer Group\",\n\t`tabAddress`.address_line1 as \"Address Line 1\",\n\t`tabAddress`.address_line2 as \"Address Line 2\",\n\t`tabAddress`.city as \"City\",\n\t`tabAddress`.state as \"State\",\n\t`tabAddress`.pincode as \"Postal Code\",\n\t`tabAddress`.country as \"Country\",\n\t`tabAddress`.is_primary_address as \"Is Primary Address:Check\", \n\t`tabContact`.first_name as \"First Name\",\n\t`tabContact`.last_name as \"Last Name\",\n\t`tabContact`.phone as \"Phone\",\n\t`tabContact`.mobile_no as \"Mobile No\",\n\t`tabContact`.email_id as \"Email Address\",\n\t`tabContact`.is_primary_contact as \"Is Primary Contact:Check\"\nFROM\n\t`tabCustomer`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.customer=`tabCustomer`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.customer=`tabCustomer`.name\n\t)\nWHERE\n\t`tabCustomer`.docstatus<2\nORDER BY\n\t`tabCustomer`.name asc", 
- "ref_doctype": "Customer", 
- "report_name": "Customer Addresses And Contacts", 
- "report_type": "Query Report"
-}
\ No newline at end of file
diff --git a/erpnext/selling/report/lead_details/lead_details.json b/erpnext/selling/report/lead_details/lead_details.json
index 387b5f8..047b4b7 100644
--- a/erpnext/selling/report/lead_details/lead_details.json
+++ b/erpnext/selling/report/lead_details/lead_details.json
@@ -1,16 +1,18 @@
 {
+ "add_total_row": 0, 
  "apply_user_permissions": 1, 
  "creation": "2013-10-22 11:58:16", 
+ "disabled": 0, 
  "docstatus": 0, 
  "doctype": "Report", 
  "idx": 1, 
  "is_standard": "Yes", 
- "modified": "2015-02-02 11:39:57.231750", 
+ "modified": "2017-01-19 15:44:59.742195", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Lead Details", 
  "owner": "Administrator", 
- "query": "SELECT\n    `tabLead`.name as \"Lead Id:Link/Lead:120\",\n    `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Address::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n    `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.lead=`tabLead`.name\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc", 
+ "query": "SELECT\n    `tabLead`.name as \"Lead Id:Link/Lead:120\",\n    `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n    `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc", 
  "ref_doctype": "Lead", 
  "report_name": "Lead Details", 
  "report_type": "Query Report"
diff --git a/erpnext/setup/doctype/company/delete_company_transactions.py b/erpnext/setup/doctype/company/delete_company_transactions.py
index eb5c043..eef8599 100644
--- a/erpnext/setup/doctype/company/delete_company_transactions.py
+++ b/erpnext/setup/doctype/company/delete_company_transactions.py
@@ -73,11 +73,23 @@
 
 def delete_lead_addresses(company_name):
 	"""Delete addresses to which leads are linked"""
-	for lead in frappe.get_all("Lead", filters={"company": company_name}):
-		frappe.db.sql("""delete from `tabAddress`
-			where lead=%s and (customer='' or customer is null) and (supplier='' or supplier is null)""", lead.name)
+	leads = frappe.get_all("Lead", filters={"company": company_name})
+	leads = [ "'%s'"%row.get("name") for row in leads ]
+	addresses = []
+	if leads:
+		addresses = frappe.db.sql_list("""select parent from `tabDynamic Link` where link_name 
+			in ({leads})""".format(leads=",".join(leads)), debug=True)
+		addresses = ["'%s'"%addr for addr in addresses]
 
-		frappe.db.sql("""update `tabAddress` set lead=null, lead_name=null where lead=%s""", lead.name)
+		frappe.db.sql("""delete from tabAddress where name in ({addresses}) and 
+			name not in (select distinct dl1.parent from `tabDynamic Link` dl1 
+			inner join `tabDynamic Link` dl2 on dl1.parent=dl2.parent 
+			and dl1.link_doctype<>dl2.link_doctype)""".format(addresses=",".join(addresses)), debug=True)
+
+		frappe.db.sql("""delete from `tabDynamic Link` where link_doctype='Lead' and parenttype='Address' 
+			and link_name in ({leads})""".format(leads=",".join(leads)), debug=True)
+
+		frappe.db.sql("""update tabCustomer set lead_name=NULL where lead_name in ({leads})""".format(leads=",".join(leads)), debug=True)
 
 def delete_communications(doctype, company_name, company_fieldname):
 		frappe.db.sql("""
diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.js b/erpnext/setup/doctype/sales_partner/sales_partner.js
index 1bfba98..84cf749 100644
--- a/erpnext/setup/doctype/sales_partner/sales_partner.js
+++ b/erpnext/setup/doctype/sales_partner/sales_partner.js
@@ -6,12 +6,12 @@
 		frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Sales Person'}
 
 		if(frm.doc.__islocal){
-			hide_field(['address_html', 'contact_html']);
-			erpnext.utils.clear_address_and_contact(frm);
+			hide_field(['address_html', 'contact_html', 'address_contacts']);
+			frappe.geo.clear_address_and_contact(frm);
 		}
 		else{
-			unhide_field(['address_html', 'contact_html']);
-			erpnext.utils.render_address_and_contact(frm);
+			unhide_field(['address_html', 'contact_html', 'address_contacts']);
+			frappe.geo.render_address_and_contact(frm);
 		}
 	}
 });
diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.py b/erpnext/setup/doctype/sales_partner/sales_partner.py
index 5a2aa49..96211af 100644
--- a/erpnext/setup/doctype/sales_partner/sales_partner.py
+++ b/erpnext/setup/doctype/sales_partner/sales_partner.py
@@ -5,7 +5,7 @@
 import frappe
 from frappe.utils import cstr, filter_strip_join
 from frappe.website.website_generator import WebsiteGenerator
-from erpnext.utilities.address_and_contact import load_address_and_contact
+from frappe.geo.address_and_contact import load_address_and_contact
 
 class SalesPartner(WebsiteGenerator):
 	website = frappe._dict(
@@ -28,15 +28,6 @@
 		if self.partner_website and not self.partner_website.startswith("http"):
 			self.partner_website = "http://" + self.partner_website
 
-	def get_contacts(self, nm):
-		if nm:
-			return frappe.db.convert_to_lists(frappe.db.sql("""
-				select name, CONCAT(IFNULL(first_name,''),
-					' ',IFNULL(last_name,'')),contact_no,email_id
-				from `tabContact` where sales_partner = %s""", nm))
-		else:
-			return ''
-
 	def get_context(self, context):
 		address = frappe.db.get_value("Address",
 			{"sales_partner": self.name, "is_primary_address": 1},
diff --git a/erpnext/utilities/address_and_contact.py b/erpnext/utilities/address_and_contact.py
deleted file mode 100644
index 12ceb5b..0000000
--- a/erpnext/utilities/address_and_contact.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def load_address_and_contact(doc, key):
-	"""Loads address list and contact list in `__onload`"""
-	from frappe.geo.doctype.address.address import get_address_display
-
-	address_list = [frappe.get_value('Address', a.parent, '*')
-		for a in frappe.get_all('Dynamic Link', fields='parent',
-			filters=dict(parenttype='Address', link_doctype=doc.doctype, link_name=doc.name))]
-
-	address_list = [a.update({"display": get_address_display(a)})
-		for a in address_list]
-
-	address_list = sorted(address_list,
-		lambda a, b:
-			(int(a.is_primary_address - b.is_primary_address)) or
-			(1 if a.modified - b.modified else 0))
-
-	doc.set_onload('addr_list', address_list)
-
-	if doc.doctype != "Lead":
-		contact_list = [frappe.get_value('Contact', a.parent, '*')
-			for a in frappe.get_all('Dynamic Link', fields='parent',
-				filters=dict(parenttype='Contact', link_doctype=doc.doctype, link_name=doc.name))]
-
-		contact_list = sorted(contact_list,
-			lambda a, b:
-				(int(a.is_primary_contact - b.is_primary_contact)) or
-				(1 if a.modified - b.modified else 0))
-
-		doc.set_onload('contact_list', contact_list)
-
-def set_default_role(doc, method):
-	'''Set customer, supplier, student based on email'''
-	if frappe.flags.setting_role:
-		return
-	contact_name = frappe.get_value('Contact', dict(email_id=doc.email))
-	if contact_name:
-		contact = frappe.get_doc('Contact', contact_name)
-		for link in contact.links:
-			frappe.flags.setting_role = True
-			if link.link_doctype=='Customer':
-				doc.add_roles('Customer')
-			elif link.link_doctype=='Supplier':
-				doc.add_roles('Supplier')
-	elif frappe.get_value('Student', dict(student_email_id=doc.email)):
-		doc.add_roles('Student')
-
-def has_permission(doc, ptype, user):
-	links = get_permitted_and_not_permitted_links(doc.doctype)
-	if not links.get("not_permitted_links"):
-		# optimization: don't determine permissions based on link fields
-		return True
-
-	# True if any one is True or all are empty
-	names = []
-	for df in (links.get("permitted_links") + links.get("not_permitted_links")):
-		doctype = df.options
-		name = doc.get(df.fieldname)
-		names.append(name)
-
-		if name and frappe.has_permission(doctype, ptype, doc=name):
-			return True
-
-	if not any(names):
-		return True
-	return False
-
-def get_permission_query_conditions_for_contact(user):
-	return get_permission_query_conditions("Contact")
-
-def get_permission_query_conditions_for_address(user):
-	return get_permission_query_conditions("Address")
-
-def get_permission_query_conditions(doctype):
-	links = get_permitted_and_not_permitted_links(doctype)
-
-	if not links.get("not_permitted_links"):
-		# when everything is permitted, don't add additional condition
-		return ""
-
-	elif not links.get("permitted_links"):
-		conditions = []
-
-		# when everything is not permitted
-		for df in links.get("not_permitted_links"):
-			# like ifnull(customer, '')='' and ifnull(supplier, '')=''
-			conditions.append("ifnull(`tab{doctype}`.`{fieldname}`, '')=''".format(doctype=doctype, fieldname=df.fieldname))
-
-		return "( " + " and ".join(conditions) + " )"
-
-	else:
-		conditions = []
-
-		for df in links.get("permitted_links"):
-			# like ifnull(customer, '')!='' or ifnull(supplier, '')!=''
-			conditions.append("ifnull(`tab{doctype}`.`{fieldname}`, '')!=''".format(doctype=doctype, fieldname=df.fieldname))
-
-		return "( " + " or ".join(conditions) + " )"
-
-def get_permitted_and_not_permitted_links(doctype):
-	permitted_links = []
-	not_permitted_links = []
-
-	meta = frappe.get_meta(doctype)
-
-	for df in meta.get_link_fields():
-		if df.options not in ("Customer", "Supplier", "Company", "Sales Partner"):
-			continue
-
-		if frappe.has_permission(df.options):
-			permitted_links.append(df)
-		else:
-			not_permitted_links.append(df)
-
-	return {
-		"permitted_links": permitted_links,
-		"not_permitted_links": not_permitted_links
-	}
-
-def delete_contact_and_address(doctype, name):
-	for parenttype in ('Contact', 'Address'):
-		items = frappe.db.sql("""select parent from `tabDynamic Link`
-			where parenttype=%s and link_doctype=%s and link_name=%s""",
-			(parenttype, doctype, name))
-
-		for name in items:
-			doc = frappe.get_doc(parenttype, name)
-			if len(doc.links)==1:
-				doc.delete()