diff --git a/erpnext/buying/doctype/supplier/supplier.js b/erpnext/buying/doctype/supplier/supplier.js index ce6f4511dd3..7e5e0458129 100644 --- a/erpnext/buying/doctype/supplier/supplier.js +++ b/erpnext/buying/doctype/supplier/supplier.js @@ -26,11 +26,11 @@ frappe.ui.form.on("Supplier", { 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 148ccdbe861..7f927672794 100644 --- a/erpnext/buying/doctype/supplier/supplier.py +++ b/erpnext/buying/doctype/supplier/supplier.py @@ -6,7 +6,7 @@ import frappe 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 diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js index fd7d9c1f6a0..7e221254ff5 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -35,9 +35,9 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({ } 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 0f3506d9327..411f59730e1 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -8,7 +8,7 @@ from frappe.utils import cstr, validate_email_add, cint, comma_and, has_gravatar 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" diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 8443cdf7e10..dac7c6bde89 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -126,16 +126,6 @@ has_website_permission = { "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 @@ doc_events = { "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/utils.js b/erpnext/public/js/utils.js index 74e9fb655c3..551ea51feb4 100644 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -82,32 +82,6 @@ $.extend(erpnext, { $.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 747b31e13dd..540ec28c941 100644 --- a/erpnext/selling/doctype/customer/customer.js +++ b/erpnext/selling/doctype/customer/customer.js @@ -37,7 +37,7 @@ frappe.ui.form.on("Customer", { 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 @@ frappe.ui.form.on("Customer", { 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 061b9c28aeb..a4548330336 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -9,7 +9,7 @@ import frappe.defaults 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 @@ -138,7 +138,7 @@ class Customer(TransactionBase): 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/setup/doctype/company/delete_company_transactions.py b/erpnext/setup/doctype/company/delete_company_transactions.py index 9b157c3a1c8..1aca24c0447 100644 --- a/erpnext/setup/doctype/company/delete_company_transactions.py +++ b/erpnext/setup/doctype/company/delete_company_transactions.py @@ -75,10 +75,16 @@ def delete_lead_addresses(company_name): """Delete addresses to which leads are linked""" leads = frappe.get_all("Lead", filters={"company": company_name}) leads = [ "'%s'"%row.get("name") for row in leads ] + addresses = [] if leads: - frappe.db.sql("""delete from tabAddress where name not in (select parent - from `tabDynamic Link` dl where dl.link_doctype<>'Lead' and - dl.parenttype='Address')""", debug=True) + 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("""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) diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.js b/erpnext/setup/doctype/sales_partner/sales_partner.js index 5da0ecc529b..84cf7495247 100644 --- a/erpnext/setup/doctype/sales_partner/sales_partner.js +++ b/erpnext/setup/doctype/sales_partner/sales_partner.js @@ -7,11 +7,11 @@ frappe.ui.form.on('Sales Partner', { if(frm.doc.__islocal){ hide_field(['address_html', 'contact_html', 'address_contacts']); - erpnext.utils.clear_address_and_contact(frm); + frappe.geo.clear_address_and_contact(frm); } else{ unhide_field(['address_html', 'contact_html', 'address_contacts']); - erpnext.utils.render_address_and_contact(frm); + 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 ae8078bb054..96211afa4d1 100644 --- a/erpnext/setup/doctype/sales_partner/sales_partner.py +++ b/erpnext/setup/doctype/sales_partner/sales_partner.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals 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( diff --git a/erpnext/utilities/address_and_contact.py b/erpnext/utilities/address_and_contact.py deleted file mode 100644 index 22910c9a977..00000000000 --- a/erpnext/utilities/address_and_contact.py +++ /dev/null @@ -1,140 +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 - - filters = [ - ["Dynamic Link", "link_doctype", "=", doc.doctype], - ["Dynamic Link", "link_name", "=", doc.name], - ["Dynamic Link", "parenttype", "=", "Address"], - ] - address_list = frappe.get_all("Address", filters=filters, fields=["*"]) - - 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": - filters = [ - ["Dynamic Link", "link_doctype", "=", doc.doctype], - ["Dynamic Link", "link_name", "=", doc.name], - ["Dynamic Link", "parenttype", "=", "Contact"], - ] - contact_list = frappe.get_all("Contact", filters=filters, fields=["*"]) - - 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()