diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js index 720a1dc208f..c03ccc80da3 100644 --- a/erpnext/buying/doctype/purchase_common/purchase_common.js +++ b/erpnext/buying/doctype/purchase_common/purchase_common.js @@ -21,20 +21,12 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ 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 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 9eaaad1e61f..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 @@ -61,14 +61,6 @@ class Supplier(TransactionBase): 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 e69de29bb2d..00000000000 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 128548f82a2..00000000000 --- 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 e246266b291..990ca7a8ba4 100644 --- a/erpnext/config/buying.py +++ b/erpnext/config/buying.py @@ -172,8 +172,12 @@ def get_data(): { "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 c406d09b1da..bbae2455519 100644 --- a/erpnext/config/selling.py +++ b/erpnext/config/selling.py @@ -117,6 +117,16 @@ def get_data(): "link": "Tree/Sales Person", "description": _("Manage Sales Person Tree."), }, + { + "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, @@ -215,8 +225,12 @@ def get_data(): { "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 be3cd82e7fa..7e221254ff5 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -25,6 +25,7 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({ 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 @@ 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 4b2899d08f3..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" @@ -127,7 +127,7 @@ def _make_customer(source_name, target_doc=None, ignore_permissions=False): @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 4bb6765ac8c..301dc825e0d 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -106,30 +106,6 @@ class Opportunity(TransactionBase): 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 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/queries.js b/erpnext/public/js/queries.js index 1141f99623b..1963137ba91 100644 --- a/erpnext/public/js/queries.js +++ b/erpnext/public/js/queries.js @@ -68,6 +68,13 @@ $.extend(erpnext.queries, { } }, + 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 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 d8011af20af..e14cde07dbe 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 @@ -95,9 +95,14 @@ class Customer(TransactionBase): 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 @@ class Customer(TransactionBase): 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 @@ 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/selling/page/sales_funnel/sales_funnel.py b/erpnext/selling/page/sales_funnel/sales_funnel.py index 4d12efd99b0..3c4d528bd3d 100644 --- a/erpnext/selling/page/sales_funnel/sales_funnel.py +++ b/erpnext/selling/page/sales_funnel/sales_funnel.py @@ -12,9 +12,9 @@ def get_funnel_data(from_date, to_date): 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 e69de29bb2d..00000000000 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 1f6707beb9e..00000000000 --- 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 387b5f89f61..047b4b785b6 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 eb5c043b504..eef85992900 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_bins(company_name): 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 1bfba98b270..84cf7495247 100644 --- a/erpnext/setup/doctype/sales_partner/sales_partner.js +++ b/erpnext/setup/doctype/sales_partner/sales_partner.js @@ -6,12 +6,12 @@ frappe.ui.form.on('Sales Partner', { 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 5a2aa4993b6..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( @@ -28,15 +28,6 @@ class SalesPartner(WebsiteGenerator): 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 12ceb5b61b0..00000000000 --- 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()