From 881557601e37cb02b4bb293a5836db0fcfab68ed Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 5 Aug 2019 11:41:31 +0530 Subject: [PATCH 01/26] feat: multiple emails and numbers in contact --- frappe/contacts/doctype/contact/contact.json | 36 ++++++++++------ frappe/contacts/doctype/contact/contact.py | 43 +++++++++++++++++-- .../doctype/contact_email/__init__.py | 0 .../doctype/contact_email/contact_email.js | 8 ++++ .../doctype/contact_email/contact_email.json | 37 ++++++++++++++++ .../doctype/contact_email/contact_email.py | 10 +++++ .../contact_email/test_contact_email.py | 10 +++++ .../doctype/contact_phone/__init__.py | 0 .../doctype/contact_phone/contact_phone.js | 8 ++++ .../doctype/contact_phone/contact_phone.json | 36 ++++++++++++++++ .../doctype/contact_phone/contact_phone.py | 10 +++++ .../contact_phone/test_contact_phone.py | 10 +++++ 12 files changed, 192 insertions(+), 16 deletions(-) create mode 100644 frappe/contacts/doctype/contact_email/__init__.py create mode 100644 frappe/contacts/doctype/contact_email/contact_email.js create mode 100644 frappe/contacts/doctype/contact_email/contact_email.json create mode 100644 frappe/contacts/doctype/contact_email/contact_email.py create mode 100644 frappe/contacts/doctype/contact_email/test_contact_email.py create mode 100644 frappe/contacts/doctype/contact_phone/__init__.py create mode 100644 frappe/contacts/doctype/contact_phone/contact_phone.js create mode 100644 frappe/contacts/doctype/contact_phone/contact_phone.json create mode 100644 frappe/contacts/doctype/contact_phone/contact_phone.py create mode 100644 frappe/contacts/doctype/contact_phone/test_contact_phone.py diff --git a/frappe/contacts/doctype/contact/contact.json b/frappe/contacts/doctype/contact/contact.json index 69a8cf7fcd..c831c6fe74 100644 --- a/frappe/contacts/doctype/contact/contact.json +++ b/frappe/contacts/doctype/contact/contact.json @@ -19,8 +19,10 @@ "designation", "gender", "phone", - "mobile_no", "image", + "sb_00", + "email_ids", + "contact_numbers", "contact_details", "is_primary_contact", "links", @@ -63,6 +65,7 @@ "oldfieldname": "email_id", "oldfieldtype": "Data", "options": "Email", + "read_only": 1, "search_index": 1 }, { @@ -103,16 +106,8 @@ "fieldtype": "Data", "label": "Phone", "oldfieldname": "contact_no", - "oldfieldtype": "Data" - }, - { - "bold": 1, - "fieldname": "mobile_no", - "fieldtype": "Data", - "in_global_search": 1, - "label": "Mobile No", - "oldfieldname": "mobile_no", - "oldfieldtype": "Data" + "oldfieldtype": "Data", + "read_only": 1 }, { "fieldname": "image", @@ -182,12 +177,29 @@ "fieldname": "google_contacts_description", "fieldtype": "Small Text", "label": "Google Contacts Description" + }, + { + "fieldname": "sb_00", + "fieldtype": "Section Break", + "label": "Contact Details" + }, + { + "fieldname": "email_ids", + "fieldtype": "Table", + "label": "Email IDs", + "options": "Contact Email" + }, + { + "fieldname": "contact_numbers", + "fieldtype": "Table", + "label": "Contact Numbers", + "options": "Contact Phone" } ], "icon": "fa fa-user", "idx": 1, "image_field": "image", - "modified": "2019-06-14 20:35:45.300869", + "modified": "2019-08-02 13:35:56.989751", "modified_by": "Administrator", "module": "Contacts", "name": "Contact", diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index 2018f5469e..21e6ff444d 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -29,10 +29,31 @@ class Contact(Document): break def validate(self): + if len(self.email_ids) == 1: + self.email_ids[0].is_primary = 1 + self.email_id = self.email_ids[0].email_id + else: + for email_id in self.email_ids: + if email_id.is_primary == 1: + self.email_id = email_id.email_id + break + + if len(self.contact_numbers) == 1: + self.contact_numbers[0].is_primary = 1 + self.phone = self.contact_numbers[0].phone + else: + for contact_number in self.contact_numbers: + if contact_number.is_primary == 1: + self.phone = contact_number.phone + break + if self.email_id: self.email_id = self.email_id.strip() + self.set_user() + set_link_title(self) + if self.email_id and not self.image: self.image = has_gravatar(self.email_id) @@ -61,6 +82,21 @@ class Contact(Document): if (link.link_doctype, link.link_name) in reference_links: return True + def add_email_address(self, email_id, autosave=False): + self.append("email_ids", { + "email_id": email_id + }) + + if autosave: + self.save(ignore_permissions=True) + + def add_phone_number(self, phone_number, autosave=False): + self.append("phone_numbers", { + "phone": phone_number + }) + + if autosave: + self.save(ignore_permissions=True) def get_default_contact(doctype, name): '''Returns default contact for the given doctype, name''' @@ -166,10 +202,9 @@ def contact_query(doctype, txt, searchfield, start, page_len, filters): def get_contact_with_phone_number(number): if not number: return - contacts = frappe.get_all('Contact', or_filters={ - 'phone': ['like', '%{}'.format(number)], - 'mobile_no': ['like', '%{}'.format(number)] - }, limit=1) + contacts = frappe.get_all('Contact', or_filters=[ + ['Contact Phone', 'phone', 'like' '%{}'.format(number)] + ], limit=1) contact = contacts[0].name if contacts else None diff --git a/frappe/contacts/doctype/contact_email/__init__.py b/frappe/contacts/doctype/contact_email/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/contacts/doctype/contact_email/contact_email.js b/frappe/contacts/doctype/contact_email/contact_email.js new file mode 100644 index 0000000000..ebd41f6f45 --- /dev/null +++ b/frappe/contacts/doctype/contact_email/contact_email.js @@ -0,0 +1,8 @@ +// Copyright (c) 2019, Frappe Technologies and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Contact Email', { + // refresh: function(frm) { + + // } +}); diff --git a/frappe/contacts/doctype/contact_email/contact_email.json b/frappe/contacts/doctype/contact_email/contact_email.json new file mode 100644 index 0000000000..cfcc39ca8b --- /dev/null +++ b/frappe/contacts/doctype/contact_email/contact_email.json @@ -0,0 +1,37 @@ +{ + "creation": "2019-08-02 13:08:59.291097", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "email_id", + "is_primary" + ], + "fields": [ + { + "fieldname": "email_id", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Email ID", + "options": "Email" + }, + { + "default": "0", + "fieldname": "is_primary", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Is Primary" + } + ], + "istable": 1, + "modified": "2019-08-02 13:14:22.193463", + "modified_by": "Administrator", + "module": "Contacts", + "name": "Contact Email", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/frappe/contacts/doctype/contact_email/contact_email.py b/frappe/contacts/doctype/contact_email/contact_email.py new file mode 100644 index 0000000000..04e8b22989 --- /dev/null +++ b/frappe/contacts/doctype/contact_email/contact_email.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class ContactEmail(Document): + pass diff --git a/frappe/contacts/doctype/contact_email/test_contact_email.py b/frappe/contacts/doctype/contact_email/test_contact_email.py new file mode 100644 index 0000000000..eef27ba3fe --- /dev/null +++ b/frappe/contacts/doctype/contact_email/test_contact_email.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestContactEmail(unittest.TestCase): + pass diff --git a/frappe/contacts/doctype/contact_phone/__init__.py b/frappe/contacts/doctype/contact_phone/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/contacts/doctype/contact_phone/contact_phone.js b/frappe/contacts/doctype/contact_phone/contact_phone.js new file mode 100644 index 0000000000..32e3be38b8 --- /dev/null +++ b/frappe/contacts/doctype/contact_phone/contact_phone.js @@ -0,0 +1,8 @@ +// Copyright (c) 2019, Frappe Technologies and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Contact Phone', { + // refresh: function(frm) { + + // } +}); diff --git a/frappe/contacts/doctype/contact_phone/contact_phone.json b/frappe/contacts/doctype/contact_phone/contact_phone.json new file mode 100644 index 0000000000..971dedf3d2 --- /dev/null +++ b/frappe/contacts/doctype/contact_phone/contact_phone.json @@ -0,0 +1,36 @@ +{ + "creation": "2019-08-02 13:10:37.890214", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "phone", + "is_primary" + ], + "fields": [ + { + "default": "0", + "fieldname": "is_primary", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Is Primary" + }, + { + "fieldname": "phone", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Phone" + } + ], + "istable": 1, + "modified": "2019-08-05 11:40:59.104224", + "modified_by": "Administrator", + "module": "Contacts", + "name": "Contact Phone", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/frappe/contacts/doctype/contact_phone/contact_phone.py b/frappe/contacts/doctype/contact_phone/contact_phone.py new file mode 100644 index 0000000000..fe2f86a4bd --- /dev/null +++ b/frappe/contacts/doctype/contact_phone/contact_phone.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class ContactPhone(Document): + pass diff --git a/frappe/contacts/doctype/contact_phone/test_contact_phone.py b/frappe/contacts/doctype/contact_phone/test_contact_phone.py new file mode 100644 index 0000000000..1d595127c5 --- /dev/null +++ b/frappe/contacts/doctype/contact_phone/test_contact_phone.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestContactPhone(unittest.TestCase): + pass From 0bac5bd5df07d75e75a05886d01485313670dfb8 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 7 Aug 2019 12:40:23 +0530 Subject: [PATCH 02/26] fix: get contact name from email --- frappe/contacts/doctype/contact/contact.py | 4 ++++ frappe/core/doctype/communication/communication.py | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index 21e6ff444d..38c2f0e14d 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -209,3 +209,7 @@ def get_contact_with_phone_number(number): contact = contacts[0].name if contacts else None return contact + +def get_contact_name(email_id): + contact = frappe.get_list("Contact Email", filters={"email_id": email_id}, fields=["parent"], limit=1) + return contact[0].parent \ No newline at end of file diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index c773f23cae..0bf24325ad 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -15,6 +15,7 @@ from frappe.core.doctype.comment.comment import update_comment_in_doc from email.utils import parseaddr from six.moves.urllib.parse import unquote from collections import Counter +from frappe.contacts.doctype.contact.contact import get_contact_name exclude_from_linked_with = True @@ -334,7 +335,7 @@ def get_contacts(email_strings): contacts = [] for email in email_addrs: email = get_email_without_link(email) - contact_name = frappe.db.get_value('Contact', {'email_id': email}) + contact_name = get_contact_name(email) if not contact_name: contact = frappe.get_doc({ From 365da10718e8ca9a938729eeaba26367068f1b22 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 8 Aug 2019 23:33:40 +0530 Subject: [PATCH 03/26] feat: display multiple contacts --- frappe/contacts/address_and_contact.py | 13 +++++++++++++ frappe/contacts/doctype/contact/contact.json | 9 ++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/frappe/contacts/address_and_contact.py b/frappe/contacts/address_and_contact.py index 6523b0b1e5..3c1dfcf47d 100644 --- a/frappe/contacts/address_and_contact.py +++ b/frappe/contacts/address_and_contact.py @@ -37,6 +37,19 @@ def load_address_and_contact(doc, key=None): ] contact_list = frappe.get_all("Contact", filters=filters, fields=["*"]) + for contact in contact_list: + contact["email_ids"] = frappe.get_list("Contact Email", filters={ + "parenttype": "Contact", + "parent": contact.name, + "is_primary": 0 + }, fields=["email_id"]) + + contact["phones"] = frappe.get_list("Contact Phone", filters={ + "parenttype": "Contact", + "parent": contact.name, + "is_primary": 0 + }, fields=["phone"]) + contact_list = sorted(contact_list, key = functools.cmp_to_key(lambda a, b: (int(a.is_primary_contact - b.is_primary_contact)) or diff --git a/frappe/contacts/doctype/contact/contact.json b/frappe/contacts/doctype/contact/contact.json index c831c6fe74..7acef62b1a 100644 --- a/frappe/contacts/doctype/contact/contact.json +++ b/frappe/contacts/doctype/contact/contact.json @@ -13,6 +13,7 @@ "last_name", "email_id", "user", + "address", "cb00", "status", "salutation", @@ -194,12 +195,18 @@ "fieldtype": "Table", "label": "Contact Numbers", "options": "Contact Phone" + }, + { + "fieldname": "address", + "fieldtype": "Link", + "label": "Address", + "options": "Address" } ], "icon": "fa fa-user", "idx": 1, "image_field": "image", - "modified": "2019-08-02 13:35:56.989751", + "modified": "2019-08-08 19:07:57.844491", "modified_by": "Administrator", "module": "Contacts", "name": "Contact", From fa662e1732262ee02167e44fd4d0db96f2fbaa80 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 8 Aug 2019 23:49:53 +0530 Subject: [PATCH 04/26] feat: move to newer contacts structure --- frappe/contacts/doctype/contact/contact.py | 4 ++-- .../test_addresses_and_contacts.py | 4 ++-- .../core/doctype/communication/communication.py | 9 +++++---- .../doctype/communication/test_communication.py | 13 ++++++++----- frappe/core/doctype/user/user.py | 17 ++++++++++++----- 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index 38c2f0e14d..f1aa08792f 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -82,7 +82,7 @@ class Contact(Document): if (link.link_doctype, link.link_name) in reference_links: return True - def add_email_address(self, email_id, autosave=False): + def add_email(self, email_id, autosave=False): self.append("email_ids", { "email_id": email_id }) @@ -90,7 +90,7 @@ class Contact(Document): if autosave: self.save(ignore_permissions=True) - def add_phone_number(self, phone_number, autosave=False): + def add_phone(self, phone_number, autosave=False): self.append("phone_numbers", { "phone": phone_number }) diff --git a/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py b/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py index e315019ca7..133137f69f 100644 --- a/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py +++ b/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py @@ -74,13 +74,13 @@ def create_linked_contact(link_list): contact = frappe.get_doc({ "doctype": "Contact", "salutation": "Mr", - "email_id": "test_contact@example.com", "first_name": "_Test First Name", "last_name": "_Test Last Name", "is_primary_contact": 1, - "phone": "+91 0000000000", "status": "Open" }) + contact.add_email("test_contact@example.com") + contact.add_phone("+91 0000000000") for name in link_list: contact.append("links",{ diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index 0bf24325ad..c32dfcee99 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -339,10 +339,11 @@ def get_contacts(email_strings): if not contact_name: contact = frappe.get_doc({ - "doctype": "Contact", - "first_name": frappe.unscrub(email.split("@")[0]), - "email_id": email - }).insert(ignore_permissions=True) + "doctype": "Contact", + "first_name": frappe.unscrub(email.split("@")[0]), + }) + contact.add_email(email) + contact.insert(ignore_permissions=True) contact_name = contact.name contacts.append(contact_name) diff --git a/frappe/core/doctype/communication/test_communication.py b/frappe/core/doctype/communication/test_communication.py index 3ce5646c7e..5c8dbc1284 100644 --- a/frappe/core/doctype/communication/test_communication.py +++ b/frappe/core/doctype/communication/test_communication.py @@ -101,20 +101,23 @@ class TestCommunication(unittest.TestCase): contact_sender = frappe.get_doc({ "doctype": "Contact", "first_name": frappe.generate_hash(length=10), - "email_id": "comm_sender@example.com" - }).insert(ignore_permissions=True) + }) + contact_sender.add_email("comm_sender@example.com") + contact_sender.insert(ignore_permissions=True) contact_recipient = frappe.get_doc({ "doctype": "Contact", "first_name": frappe.generate_hash(length=10), - "email_id": "comm_recipient@example.com" }).insert(ignore_permissions=True) + contact_recipient.add_email("comm_recipient@example.com") + contact_recipient.insert(ignore_permissions=True) contact_cc = frappe.get_doc({ "doctype": "Contact", "first_name": frappe.generate_hash(length=10), - "email_id": "comm_cc@example.com" - }).insert(ignore_permissions=True) + }) + contact_cc.add_email("comm_cc@example.com") + contact_cc.insert(ignore_permissions=True) comm = frappe.get_doc({ "doctype": "Communication", diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index e233285fa3..5700274b7d 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -1068,16 +1068,23 @@ def create_contact(user, ignore_links=False, ignore_mandatory=False): if user.name in ["Administrator", "Guest"]: return if not frappe.db.get_value("Contact", {"email_id": user.email}): - frappe.get_doc({ + d = frappe.get_doc({ "doctype": "Contact", "first_name": user.first_name, "last_name": user.last_name, - "email_id": user.email, "user": user.name, "gender": user.gender, - "phone": user.phone, - "mobile_no": user.mobile_no - }).insert(ignore_permissions=True, ignore_links=ignore_links, ignore_mandatory=ignore_mandatory) + }) + + if user.email: + d.add_email(user.email) + + if user.phone: + d.add_phone(user.phone) + + if user.mobile_no: + d.add_phone(user.mobile_no) + d.insert(ignore_permissions=True, ignore_links=ignore_links, ignore_mandatory=ignore_mandatory) @frappe.whitelist() From 6ba1b9c7a7f68b109776dff6c5eabfdc70c9e344 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 00:03:02 +0530 Subject: [PATCH 05/26] fix: return correct value --- frappe/contacts/doctype/contact/contact.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index f1aa08792f..b36c7fdddd 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -212,4 +212,4 @@ def get_contact_with_phone_number(number): def get_contact_name(email_id): contact = frappe.get_list("Contact Email", filters={"email_id": email_id}, fields=["parent"], limit=1) - return contact[0].parent \ No newline at end of file + return contact[0].parent if contact else None \ No newline at end of file From 779654a6213a4cb4136c7afd54e0bef26cbd44ef Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 11:04:49 +0530 Subject: [PATCH 06/26] fix: rename field in contacts --- frappe/contacts/address_and_contact.py | 2 +- frappe/contacts/doctype/contact/contact.json | 18 ++++++++++-------- frappe/contacts/doctype/contact/contact.py | 14 +++++++------- .../addresses_and_contacts.js | 7 +++++++ .../addresses_and_contacts.py | 8 ++++---- .../test_addresses_and_contacts.py | 4 ++-- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/frappe/contacts/address_and_contact.py b/frappe/contacts/address_and_contact.py index 3c1dfcf47d..73e5d6b176 100644 --- a/frappe/contacts/address_and_contact.py +++ b/frappe/contacts/address_and_contact.py @@ -44,7 +44,7 @@ def load_address_and_contact(doc, key=None): "is_primary": 0 }, fields=["email_id"]) - contact["phones"] = frappe.get_list("Contact Phone", filters={ + contact["phone_nos"] = frappe.get_list("Contact Phone", filters={ "parenttype": "Contact", "parent": contact.name, "is_primary": 0 diff --git a/frappe/contacts/doctype/contact/contact.json b/frappe/contacts/doctype/contact/contact.json index 7acef62b1a..f700411e80 100644 --- a/frappe/contacts/doctype/contact/contact.json +++ b/frappe/contacts/doctype/contact/contact.json @@ -23,7 +23,7 @@ "image", "sb_00", "email_ids", - "contact_numbers", + "phone_nos", "contact_details", "is_primary_contact", "links", @@ -62,6 +62,7 @@ "fieldname": "email_id", "fieldtype": "Data", "in_global_search": 1, + "in_list_view": 1, "label": "Email Address", "oldfieldname": "email_id", "oldfieldtype": "Data", @@ -105,6 +106,7 @@ "bold": 1, "fieldname": "phone", "fieldtype": "Data", + "in_list_view": 1, "label": "Phone", "oldfieldname": "contact_no", "oldfieldtype": "Data", @@ -190,23 +192,23 @@ "label": "Email IDs", "options": "Contact Email" }, - { - "fieldname": "contact_numbers", - "fieldtype": "Table", - "label": "Contact Numbers", - "options": "Contact Phone" - }, { "fieldname": "address", "fieldtype": "Link", "label": "Address", "options": "Address" + }, + { + "fieldname": "phone_nos", + "fieldtype": "Table", + "label": "Phone Nos", + "options": "Contact Phone" } ], "icon": "fa fa-user", "idx": 1, "image_field": "image", - "modified": "2019-08-08 19:07:57.844491", + "modified": "2019-08-09 10:23:00.486673", "modified_by": "Administrator", "module": "Contacts", "name": "Contact", diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index b36c7fdddd..f6af801d7e 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -38,11 +38,11 @@ class Contact(Document): self.email_id = email_id.email_id break - if len(self.contact_numbers) == 1: - self.contact_numbers[0].is_primary = 1 - self.phone = self.contact_numbers[0].phone + if len(self.phone_nos) == 1: + self.phone_nos[0].is_primary = 1 + self.phone = self.phone_nos[0].phone else: - for contact_number in self.contact_numbers: + for contact_number in self.phone_nos: if contact_number.is_primary == 1: self.phone = contact_number.phone break @@ -90,9 +90,9 @@ class Contact(Document): if autosave: self.save(ignore_permissions=True) - def add_phone(self, phone_number, autosave=False): - self.append("phone_numbers", { - "phone": phone_number + def add_phone(self, phone, autosave=False): + self.append("phone_nos", { + "phone": phone }) if autosave: diff --git a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js index 0f8c2361ae..2169f58365 100644 --- a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js +++ b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js @@ -9,6 +9,13 @@ frappe.query_reports["Addresses And Contacts"] = { "label": __("Entity Type"), "fieldtype": "Link", "options": "DocType", + "get_query": function() { + return { + "filters": { + "name": ["in","Contact,Address"], + } + } + } }, { "fieldname":"reference_name", diff --git a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py index f73858c8ab..fb345a4384 100644 --- a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py +++ b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py @@ -7,8 +7,8 @@ import frappe from frappe import _ field_map = { - "Contact": [ "first_name", "last_name", "phone", "mobile_no", "email_id", "is_primary_contact" ], - "Address": [ "address_line1", "address_line2", "city", "state", "pincode", "country", "is_primary_address" ] + "Contact": ["first_name", "last_name", "address", "phone", "email_id", "is_primary_contact"], + "Address": ["address_line1", "address_line2", "city", "state", "pincode", "country", "is_primary_address"] } def execute(filters=None): @@ -27,8 +27,8 @@ def get_columns(filters): "Is Primary Address:Check", "First Name", "Last Name", + "Address", "Phone", - "Mobile No", "Email Id", "Is Primary Contact:Check" ] @@ -49,7 +49,7 @@ def get_reference_addresses_and_contact(reference_doctype, reference_name): return [] if reference_name: - filters = { "name": reference_name } + filters = {"name": reference_name} reference_list = [d[0] for d in frappe.get_list(reference_doctype, filters=filters, fields=["name"], as_list=True)] diff --git a/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py b/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py index 133137f69f..224a24a9c1 100644 --- a/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py +++ b/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py @@ -88,7 +88,7 @@ def create_linked_contact(link_list): 'link_name': name }) - contact.insert() + contact.insert(ignore_permissions=True) frappe.flags.test_contact_created = True @@ -100,7 +100,7 @@ class TestAddressesAndContacts(unittest.TestCase): create_linked_address(links_list) report_data = get_data({"reference_doctype": "Test Custom Doctype"}) for idx, link in enumerate(links_list): - test_item = [link, 'test address line 1', 'test address line 2', 'Milan', None, None, 'Italy', 0, '_Test First Name', '_Test Last Name', '+91 0000000000', None, 'test_contact@example.com', 1] + test_item = [link, 'test address line 1', 'test address line 2', 'Milan', None, None, 'Italy', 0, '_Test First Name', '_Test Last Name', '_Test Address-Billing', '+91 0000000000', 'test_contact@example.com', 1] self.assertListEqual(test_item, report_data[idx]) def tearDown(self): From a915b561d3460c5758a4b035c36d52d11eeb5296 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 11:23:13 +0530 Subject: [PATCH 07/26] fix: communication test --- frappe/core/doctype/communication/test_communication.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/core/doctype/communication/test_communication.py b/frappe/core/doctype/communication/test_communication.py index 5c8dbc1284..115b711a94 100644 --- a/frappe/core/doctype/communication/test_communication.py +++ b/frappe/core/doctype/communication/test_communication.py @@ -100,21 +100,21 @@ class TestCommunication(unittest.TestCase): def test_contacts_attached(self): contact_sender = frappe.get_doc({ "doctype": "Contact", - "first_name": frappe.generate_hash(length=10), + "first_name": "contact_sender", }) contact_sender.add_email("comm_sender@example.com") contact_sender.insert(ignore_permissions=True) contact_recipient = frappe.get_doc({ "doctype": "Contact", - "first_name": frappe.generate_hash(length=10), - }).insert(ignore_permissions=True) + "first_name": "contact_recipient", + }) contact_recipient.add_email("comm_recipient@example.com") contact_recipient.insert(ignore_permissions=True) contact_cc = frappe.get_doc({ "doctype": "Contact", - "first_name": frappe.generate_hash(length=10), + "first_name": "contact_cc", }) contact_cc.add_email("comm_cc@example.com") contact_cc.insert(ignore_permissions=True) From 4715c002ced3cd831850166ab6a4bff7d3a085d5 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 11:35:33 +0530 Subject: [PATCH 08/26] fix: remove mobile_no field from hooks --- frappe/hooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/hooks.py b/frappe/hooks.py index 545ac8c3e8..7e79bc32cc 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -268,7 +268,7 @@ user_privacy_documents = [ { 'doctype': 'Contact', 'match_field': 'email_id', - 'personal_fields': ['first_name', 'last_name', 'phone', 'mobile_no'], + 'personal_fields': ['first_name', 'last_name', 'phone'], }, { 'doctype': 'Address', From 8658cecbd60fbf6e1547a96ba8e494ec923172ac Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 13:42:58 +0530 Subject: [PATCH 09/26] fix: report --- .../test_addresses_and_contacts.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py b/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py index 224a24a9c1..d87676e272 100644 --- a/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py +++ b/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py @@ -67,7 +67,9 @@ def create_linked_address(link_list): address.insert() frappe.flags.test_address_created = True -def create_linked_contact(link_list): + return address.name + +def create_linked_contact(link_list, address): if frappe.flags.test_contact_created: return @@ -77,6 +79,7 @@ def create_linked_contact(link_list): "first_name": "_Test First Name", "last_name": "_Test Last Name", "is_primary_contact": 1, + "address": address, "status": "Open" }) contact.add_email("test_contact@example.com") @@ -96,8 +99,8 @@ class TestAddressesAndContacts(unittest.TestCase): def test_get_data(self): linked_docs = [get_custom_doc_for_address_and_contacts()] links_list = [item.name for item in linked_docs] - create_linked_contact(links_list) - create_linked_address(links_list) + d = create_linked_address(links_list) + create_linked_contact(links_list, d) report_data = get_data({"reference_doctype": "Test Custom Doctype"}) for idx, link in enumerate(links_list): test_item = [link, 'test address line 1', 'test address line 2', 'Milan', None, None, 'Italy', 0, '_Test First Name', '_Test Last Name', '_Test Address-Billing', '+91 0000000000', 'test_contact@example.com', 1] From 63f59989f895a5851b3c9a81b0317585f9c960e5 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 14:02:30 +0530 Subject: [PATCH 10/26] fix: add multiple emails for google contacts --- frappe/contacts/doctype/contact/contact.py | 10 +++--- .../google_contacts/google_contacts.py | 33 ++++++++++--------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index f6af801d7e..73cf6d2f11 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -82,17 +82,19 @@ class Contact(Document): if (link.link_doctype, link.link_name) in reference_links: return True - def add_email(self, email_id, autosave=False): + def add_email(self, email_id, is_primary=0, autosave=False): self.append("email_ids", { - "email_id": email_id + "email_id": email_id, + "is_primary": is_primary }) if autosave: self.save(ignore_permissions=True) - def add_phone(self, phone, autosave=False): + def add_phone(self, phone, is_primary=0, autosave=False): self.append("phone_nos", { - "phone": phone + "phone": phone, + "is_primary": is_primary }) if autosave: diff --git a/frappe/integrations/doctype/google_contacts/google_contacts.py b/frappe/integrations/doctype/google_contacts/google_contacts.py index 6610173e3e..9878ac4a20 100644 --- a/frappe/integrations/doctype/google_contacts/google_contacts.py +++ b/frappe/integrations/doctype/google_contacts/google_contacts.py @@ -135,24 +135,27 @@ def sync(g_contact=None): for name in connection.get("names"): if name.get("metadata").get("primary"): + contact = frappe.get_doc({ + "doctype": "Contact", + "salutation": name.get("honorificPrefix") if name.get("honorificPrefix") else "", + "first_name": name.get("givenName") if name.get("givenName") else "", + "middle_name": name.get("middleName") if name.get("middleName") else "", + "last_name": name.get("familyName") if name.get("familyName") else "", + "designation": get_indexed_value(connection.get("organizations"), 0, "title"), + "source": "Google Contacts", + "google_contacts_description": get_indexed_value(connection.get("organizations"), 0, "name") + }) + if connection.get("emailAddresses"): for email in connection.get("emailAddresses"): - if not frappe.db.exists("Contact", {"email_id": email.get("value")}): - contacts_updated += 1 + contact.add_email(email_id=email.get("value"), is_primary=1 if email.get("primary") else 0) + + if connection.get("phoneNumbers"): + for phone in connection.get("phoneNumbers"): + contact.add_phone(phone=phone.get("value"), is_primary=1 if phone.get("primary") else 0) + + contact.insert(ignore_permissions=True) - frappe.get_doc({ - "doctype": "Contact", - "salutation": name.get("honorificPrefix") if name.get("honorificPrefix") else "", - "first_name": name.get("givenName") if name.get("givenName") else "", - "middle_name": name.get("middleName") if name.get("middleName") else "", - "last_name": name.get("familyName") if name.get("familyName") else "", - "email_id": email.get("value") if email.get("value") else "", - "designation": get_indexed_value(connection.get("organizations"), 0, "title"), - "phone": get_indexed_value(connection.get("phoneNumbers"), 0, "value"), - "mobile_no": get_indexed_value(connection.get("phoneNumbers"), 1, "value"), - "source": "Google Contacts", - "google_contacts_description": get_indexed_value(connection.get("organizations"), 0, "name") - }).insert(ignore_permissions=True) if g_contact: return _("{0} Google Contacts synced.").format(contacts_updated) if contacts_updated > 0 else _("No new Google Contacts synced.") From 266bb8778e595a5f893edcdd5c92e901dc4d7015 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 14:59:22 +0530 Subject: [PATCH 11/26] patch: migrate to new contact structure --- .../move_email_and_phone_to_child_table.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 frappe/patches/v12_0/move_email_and_phone_to_child_table.py diff --git a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py new file mode 100644 index 0000000000..388464efb6 --- /dev/null +++ b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py @@ -0,0 +1,33 @@ +import frappe + +def execute(): + contact_details = frappe.get_list("Contact", fields=["name", "email_id", "phone", "mobile_no", "modified_by", "creation", "modified"]) + frappe.reload_doc("contacts", "doctype", "contact_email") + frappe.reload_doc("contacts", "doctype", "contact_phone") + frappe.reload_doc("contacts", "doctype", "contact") + + name_counter = 100000000 + for contact_detail in contact_details: + if contact_detail.email_id: + frappe.db.sql(""" + INSERT INTO `tabContact Email` + (`idx`, `name`, `email_id`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) + VALUES ("1", {0}, {1}, "email_ids", "Contact Email", {2}, "1", {3}, {4}, {5}) + """.format(name_counter, contact_detail.email_id, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) + name_counter += 1 + + if contact_detail.phone: + frappe.db.sql(""" + INSERT INTO `tabContact Phone` + (`idx`, `name`, `phone`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) + VALUES ("1", {0}, {1}, "email_ids", "Contact Email", {2}, "1", {3}, {4}, {5}) + """.format(name_counter, contact_detail.phone, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) + name_counter += 1 + + if contact_detail.mobile_no: + frappe.db.sql(""" + INSERT INTO `tabContact Phone` + (`idx`, `name`, `phone`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) + VALUES ("1", {0}, {1}, "email_ids", "Contact Email", {2}, "0", {3}, {4}, {5}) + """.format(name_counter, contact_detail.mobile_no, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) + name_counter += 1 \ No newline at end of file From c9c1baa3b07ddff966110b02a52e97d5c593f811 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 16:47:05 +0530 Subject: [PATCH 12/26] patch: fix patch to escape quotes --- frappe/patches.txt | 3 ++- .../v12_0/move_email_and_phone_to_child_table.py | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/frappe/patches.txt b/frappe/patches.txt index 0d5ccfcb8e..70f6de1207 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -248,4 +248,5 @@ frappe.patches.v12_0.move_form_attachments_to_attachments_folder frappe.patches.v12_0.move_timeline_links_to_dynamic_links frappe.patches.v12_0.delete_feedback_request_if_exists #1 frappe.patches.v12_0.rename_events_repeat_on -frappe.patches.v12_0.fix_public_private_files \ No newline at end of file +frappe.patches.v12_0.fix_public_private_files +frappe.patches.v12_0.move_email_and_phone_to_child_table \ No newline at end of file diff --git a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py index 388464efb6..e29be18afc 100644 --- a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py +++ b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py @@ -8,26 +8,28 @@ def execute(): name_counter = 100000000 for contact_detail in contact_details: + contact_name = contact_detail.name.replace('"', '\\"').replace("'", "\\'") + if contact_detail.email_id: frappe.db.sql(""" INSERT INTO `tabContact Email` (`idx`, `name`, `email_id`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) - VALUES ("1", {0}, {1}, "email_ids", "Contact Email", {2}, "1", {3}, {4}, {5}) - """.format(name_counter, contact_detail.email_id, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) + VALUES (1, "{0}", "{1}", "email_ids", "Contact", "{2}", 1, "{3}", "{4}", "{5}") + """.format(str(name_counter), contact_detail.email_id, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) name_counter += 1 if contact_detail.phone: frappe.db.sql(""" INSERT INTO `tabContact Phone` (`idx`, `name`, `phone`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) - VALUES ("1", {0}, {1}, "email_ids", "Contact Email", {2}, "1", {3}, {4}, {5}) - """.format(name_counter, contact_detail.phone, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) + VALUES (1, "{0}", "{1}", "phone_nos", "Contact", "{2}", 1, "{3}", "{4}", "{5}") + """.format(str(name_counter), contact_detail.phone, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) name_counter += 1 if contact_detail.mobile_no: frappe.db.sql(""" INSERT INTO `tabContact Phone` (`idx`, `name`, `phone`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) - VALUES ("1", {0}, {1}, "email_ids", "Contact Email", {2}, "0", {3}, {4}, {5}) - """.format(name_counter, contact_detail.mobile_no, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) + VALUES (2, "{0}", "{1}", "phone_nos", "Contact", "{2}", 0, "{3}", "{4}", "{5}") + """.format(str(name_counter), contact_detail.mobile_no, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) name_counter += 1 \ No newline at end of file From d50c35f3cf4e815974568a70e402a6d4ff5147e2 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 16:50:02 +0530 Subject: [PATCH 13/26] chore: codacy fixes --- .../report/addresses_and_contacts/addresses_and_contacts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js index 2169f58365..16f5979eff 100644 --- a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js +++ b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js @@ -12,7 +12,7 @@ frappe.query_reports["Addresses And Contacts"] = { "get_query": function() { return { "filters": { - "name": ["in","Contact,Address"], + "name": ["in","Contact, Address"], } } } From 15cc48bba5345e6cde159a93c9289ed683117ff8 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 17:50:24 +0530 Subject: [PATCH 14/26] fix: reduce address json to new json structure --- frappe/contacts/doctype/address/address.json | 645 ++----------------- 1 file changed, 45 insertions(+), 600 deletions(-) diff --git a/frappe/contacts/doctype/address/address.json b/frappe/contacts/doctype/address/address.json index 2947af03ec..333bbe916a 100644 --- a/frappe/contacts/doctype/address/address.json +++ b/frappe/contacts/doctype/address/address.json @@ -1,666 +1,159 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, - "beta": 0, "creation": "2013-01-10 16:34:32", - "custom": 0, - "docstatus": 0, "doctype": "DocType", "document_type": "Setup", - "editable_grid": 0, + "field_order": [ + "address_details", + "address_title", + "address_type", + "address_line1", + "address_line2", + "city", + "county", + "state", + "country", + "pincode", + "column_break0", + "email_id", + "phone", + "fax", + "is_primary_address", + "is_shipping_address", + "disabled", + "linked_with", + "is_your_company_address", + "links" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "address_details", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "options": "fa fa-map-marker", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "fa fa-map-marker" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", "fieldname": "address_title", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Address Title", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "address_type", "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 1, "label": "Address Type", - "length": 0, - "no_copy": 0, "options": "Billing\nShipping\nOffice\nPersonal\nPlant\nPostal\nShop\nSubsidiary\nWarehouse\nCurrent\nPermanent\nOther", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "address_line1", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Address Line 1", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "address_line2", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address Line 2", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Address Line 2" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "city", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, "in_global_search": 1, "in_list_view": 1, - "in_standard_filter": 0, "label": "City/Town", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "search_index": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "county", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "County", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "County" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "state", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "State", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "State" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "country", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, "in_global_search": 1, - "in_list_view": 0, "in_standard_filter": 1, "label": "Country", - "length": 0, - "no_copy": 0, "options": "Country", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "search_index": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "pincode", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Postal Code", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "search_index": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break0", "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "email_id", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Email Address", - "length": 0, - "no_copy": 0, - "options": "Email", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Email" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "phone", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Phone", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Phone" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "fax", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Fax", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Fax" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "0", - "description": "", "fieldname": "is_primary_address", "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Preferred Billing Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Preferred Billing Address" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "0", - "description": "", "fieldname": "is_shipping_address", "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Preferred Shipping Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Preferred Shipping Address" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, + "default": "0", "fieldname": "disabled", "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Disabled", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Disabled" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "linked_with", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Reference", - "length": 0, - "no_copy": 0, - "options": "fa fa-pushpin", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "fa fa-pushpin" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "0", "fieldname": "is_your_company_address", "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Is Your Company Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Is Your Company Address" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "links", "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Links", - "length": 0, - "no_copy": 0, - "options": "Dynamic Link", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Dynamic Link" } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, "icon": "fa fa-map-marker", "idx": 5, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-11-27 17:57:22.913973", + "modified": "2019-08-09 14:16:53.343251", "modified_by": "Administrator", "module": "Contacts", "name": "Address", @@ -668,109 +161,61 @@ "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, "create": 1, - "delete": 0, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Sales User", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 }, { - "amend": 0, - "cancel": 0, "create": 1, - "delete": 0, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Purchase User", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 }, { - "amend": 0, - "cancel": 0, "create": 1, - "delete": 0, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Maintenance User", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 }, { - "amend": 0, - "cancel": 0, "create": 1, - "delete": 0, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Accounts User", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 }, { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, "export": 1, - "if_owner": 0, "import": 1, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "System Manager", "set_user_permissions": 1, "share": 1, - "submit": 0, "write": 1 } ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, "search_fields": "country, state", - "show_name_in_global_search": 0, "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 -} + "sort_order": "DESC" +} \ No newline at end of file From cbaf7f08f5d020f451d7cdb437b1130cae2b7043 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 09:12:38 +0530 Subject: [PATCH 15/26] fix: codacy --- .../report/addresses_and_contacts/addresses_and_contacts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js index 16f5979eff..10137e80d5 100644 --- a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js +++ b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.js @@ -12,7 +12,7 @@ frappe.query_reports["Addresses And Contacts"] = { "get_query": function() { return { "filters": { - "name": ["in","Contact, Address"], + "name": ["in", "Contact, Address"], } } } From 403a1a3d76879ed994740f2e1793c18eafa1c160 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 20 Aug 2019 22:14:42 +0530 Subject: [PATCH 16/26] chore: code cleanup --- frappe/contacts/doctype/contact/contact.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index 73cf6d2f11..400fefe64d 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -204,13 +204,11 @@ def contact_query(doctype, txt, searchfield, start, page_len, filters): def get_contact_with_phone_number(number): if not number: return - contacts = frappe.get_all('Contact', or_filters=[ + contacts = frappe.get_all('Contact', filters=[ ['Contact Phone', 'phone', 'like' '%{}'.format(number)] ], limit=1) - contact = contacts[0].name if contacts else None - - return contact + return contacts[0].name if contacts else None def get_contact_name(email_id): contact = frappe.get_list("Contact Email", filters={"email_id": email_id}, fields=["parent"], limit=1) From 7a79e4cbd1e8b39af62c5c0b4e49919591dd4e2d Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 16:09:54 +0530 Subject: [PATCH 17/26] fix: return parent from contact phone --- frappe/contacts/doctype/contact/contact.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index 400fefe64d..ab8b114192 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -204,11 +204,11 @@ def contact_query(doctype, txt, searchfield, start, page_len, filters): def get_contact_with_phone_number(number): if not number: return - contacts = frappe.get_all('Contact', filters=[ - ['Contact Phone', 'phone', 'like' '%{}'.format(number)] - ], limit=1) + contacts = frappe.get_all('Contact Phone', filters=[ + ['phone', 'like', '{0}'.format(number)] + ], fields=["parent"], limit=1) - return contacts[0].name if contacts else None + return contacts[0].parent if contacts else None def get_contact_name(email_id): contact = frappe.get_list("Contact Email", filters={"email_id": email_id}, fields=["parent"], limit=1) From 3b06c185ecb17131ea2b63c2ee80a6b33438427c Mon Sep 17 00:00:00 2001 From: Himanshu Date: Thu, 22 Aug 2019 22:14:12 +0530 Subject: [PATCH 18/26] Update frappe/contacts/doctype/contact/contact.py Co-Authored-By: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- frappe/contacts/doctype/contact/contact.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index ab8b114192..3e52be186f 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -205,11 +205,11 @@ def get_contact_with_phone_number(number): if not number: return contacts = frappe.get_all('Contact Phone', filters=[ - ['phone', 'like', '{0}'.format(number)] + ['phone', 'like', '%{0}'.format(number)] ], fields=["parent"], limit=1) return contacts[0].parent if contacts else None def get_contact_name(email_id): contact = frappe.get_list("Contact Email", filters={"email_id": email_id}, fields=["parent"], limit=1) - return contact[0].parent if contact else None \ No newline at end of file + return contact[0].parent if contact else None From 378bbc5ed0a6cdc1d340af815aa01d045b93a179 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 22 Aug 2019 23:15:36 +0530 Subject: [PATCH 19/26] fix: review changes --- frappe/contacts/doctype/contact/contact.py | 29 ++++++++----------- .../doctype/contact_email/contact_email.js | 8 ----- .../contact_email/test_contact_email.py | 10 ------- .../doctype/contact_phone/contact_phone.js | 8 ----- .../contact_phone/test_contact_phone.py | 10 ------- frappe/core/doctype/user/user.py | 10 +++---- .../google_contacts/google_contacts.py | 18 +++++------- .../move_email_and_phone_to_child_table.py | 6 ++-- 8 files changed, 28 insertions(+), 71 deletions(-) delete mode 100644 frappe/contacts/doctype/contact_email/contact_email.js delete mode 100644 frappe/contacts/doctype/contact_email/test_contact_email.py delete mode 100644 frappe/contacts/doctype/contact_phone/contact_phone.js delete mode 100644 frappe/contacts/doctype/contact_phone/test_contact_phone.py diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index ab8b114192..70bd167960 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -29,23 +29,8 @@ class Contact(Document): break def validate(self): - if len(self.email_ids) == 1: - self.email_ids[0].is_primary = 1 - self.email_id = self.email_ids[0].email_id - else: - for email_id in self.email_ids: - if email_id.is_primary == 1: - self.email_id = email_id.email_id - break - - if len(self.phone_nos) == 1: - self.phone_nos[0].is_primary = 1 - self.phone = self.phone_nos[0].phone - else: - for contact_number in self.phone_nos: - if contact_number.is_primary == 1: - self.phone = contact_number.phone - break + self.set_primary("email_id", "email_ids") + self.set_primary("phone", "phone_nos") if self.email_id: self.email_id = self.email_id.strip() @@ -100,6 +85,16 @@ class Contact(Document): if autosave: self.save(ignore_permissions=True) + def set_primary(self, fieldname, child_table): + if len(self.get(child_table)) == 1: + self.get(child_table)[0].is_primary = 1 + setattr(self, fieldname, self.get(child_table)[0].get(fieldname)) + else: + for d in self.get(child_table): + if d.is_primary == 1: + setattr(self, fieldname, d.get(fieldname)) + break + def get_default_contact(doctype, name): '''Returns default contact for the given doctype, name''' out = frappe.db.sql('''select parent, diff --git a/frappe/contacts/doctype/contact_email/contact_email.js b/frappe/contacts/doctype/contact_email/contact_email.js deleted file mode 100644 index ebd41f6f45..0000000000 --- a/frappe/contacts/doctype/contact_email/contact_email.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2019, Frappe Technologies and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Contact Email', { - // refresh: function(frm) { - - // } -}); diff --git a/frappe/contacts/doctype/contact_email/test_contact_email.py b/frappe/contacts/doctype/contact_email/test_contact_email.py deleted file mode 100644 index eef27ba3fe..0000000000 --- a/frappe/contacts/doctype/contact_email/test_contact_email.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt -from __future__ import unicode_literals - -# import frappe -import unittest - -class TestContactEmail(unittest.TestCase): - pass diff --git a/frappe/contacts/doctype/contact_phone/contact_phone.js b/frappe/contacts/doctype/contact_phone/contact_phone.js deleted file mode 100644 index 32e3be38b8..0000000000 --- a/frappe/contacts/doctype/contact_phone/contact_phone.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2019, Frappe Technologies and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Contact Phone', { - // refresh: function(frm) { - - // } -}); diff --git a/frappe/contacts/doctype/contact_phone/test_contact_phone.py b/frappe/contacts/doctype/contact_phone/test_contact_phone.py deleted file mode 100644 index 1d595127c5..0000000000 --- a/frappe/contacts/doctype/contact_phone/test_contact_phone.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt -from __future__ import unicode_literals - -# import frappe -import unittest - -class TestContactPhone(unittest.TestCase): - pass diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 24bc98e142..2173ca1864 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -1038,7 +1038,7 @@ def create_contact(user, ignore_links=False, ignore_mandatory=False): if user.name in ["Administrator", "Guest"]: return if not frappe.db.get_value("Contact", {"email_id": user.email}): - d = frappe.get_doc({ + contact = frappe.get_doc({ "doctype": "Contact", "first_name": user.first_name, "last_name": user.last_name, @@ -1047,14 +1047,14 @@ def create_contact(user, ignore_links=False, ignore_mandatory=False): }) if user.email: - d.add_email(user.email) + contact.add_email(user.email) if user.phone: - d.add_phone(user.phone) + contact.add_phone(user.phone) if user.mobile_no: - d.add_phone(user.mobile_no) - d.insert(ignore_permissions=True, ignore_links=ignore_links, ignore_mandatory=ignore_mandatory) + contact.add_phone(user.mobile_no) + contact.insert(ignore_permissions=True, ignore_links=ignore_links, ignore_mandatory=ignore_mandatory) @frappe.whitelist() diff --git a/frappe/integrations/doctype/google_contacts/google_contacts.py b/frappe/integrations/doctype/google_contacts/google_contacts.py index d6be8a9c3b..4955fc9d7f 100644 --- a/frappe/integrations/doctype/google_contacts/google_contacts.py +++ b/frappe/integrations/doctype/google_contacts/google_contacts.py @@ -138,22 +138,20 @@ def sync(g_contact=None): if name.get("metadata").get("primary"): contact = frappe.get_doc({ "doctype": "Contact", - "salutation": name.get("honorificPrefix") if name.get("honorificPrefix") else "", - "first_name": name.get("givenName") if name.get("givenName") else "", - "middle_name": name.get("middleName") if name.get("middleName") else "", - "last_name": name.get("familyName") if name.get("familyName") else "", + "salutation": name.get("honorificPrefix") or "", + "first_name": name.get("givenName") or "", + "middle_name": name.get("middleName") or "", + "last_name": name.get("familyName") or "", "designation": get_indexed_value(connection.get("organizations"), 0, "title"), "source": "Google Contacts", "google_contacts_description": get_indexed_value(connection.get("organizations"), 0, "name") }) - if connection.get("emailAddresses"): - for email in connection.get("emailAddresses"): - contact.add_email(email_id=email.get("value"), is_primary=1 if email.get("primary") else 0) + for email in connection.get("emailAddresses", []): + contact.add_email(email_id=email.get("value"), is_primary=1 if email.get("primary") else 0) - if connection.get("phoneNumbers"): - for phone in connection.get("phoneNumbers"): - contact.add_phone(phone=phone.get("value"), is_primary=1 if phone.get("primary") else 0) + for phone in connection.get("phoneNumbers", []): + contact.add_phone(phone=phone.get("value"), is_primary=1 if phone.get("primary") else 0) contact.insert(ignore_permissions=True) diff --git a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py index e29be18afc..a3eacd657a 100644 --- a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py +++ b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py @@ -14,7 +14,7 @@ def execute(): frappe.db.sql(""" INSERT INTO `tabContact Email` (`idx`, `name`, `email_id`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) - VALUES (1, "{0}", "{1}", "email_ids", "Contact", "{2}", 1, "{3}", "{4}", "{5}") + VALUES (1, '{0}', '{1}', 'email_ids', 'Contact', '{2}', 1, '{3}', '{4}', '{5}') """.format(str(name_counter), contact_detail.email_id, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) name_counter += 1 @@ -22,7 +22,7 @@ def execute(): frappe.db.sql(""" INSERT INTO `tabContact Phone` (`idx`, `name`, `phone`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) - VALUES (1, "{0}", "{1}", "phone_nos", "Contact", "{2}", 1, "{3}", "{4}", "{5}") + VALUES (1, '{0}', '{1}', 'phone_nos', 'Contact', '{2}', 1, '{3}', '{4}', '{5}') """.format(str(name_counter), contact_detail.phone, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) name_counter += 1 @@ -30,6 +30,6 @@ def execute(): frappe.db.sql(""" INSERT INTO `tabContact Phone` (`idx`, `name`, `phone`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) - VALUES (2, "{0}", "{1}", "phone_nos", "Contact", "{2}", 0, "{3}", "{4}", "{5}") + VALUES (2, '{0}', '{1}', 'phone_nos', 'Contact', '{2}', 0, '{3}', '{4}', '{5}') """.format(str(name_counter), contact_detail.mobile_no, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) name_counter += 1 \ No newline at end of file From 02a6e7a138691a5f7d58e9fd1c59e5f46b9a0bb4 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 23 Aug 2019 15:16:17 +0530 Subject: [PATCH 20/26] fix: use frappe generate_hash --- frappe/patches/v12_0/move_email_and_phone_to_child_table.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py index a3eacd657a..feb97e1ab5 100644 --- a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py +++ b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py @@ -15,7 +15,7 @@ def execute(): INSERT INTO `tabContact Email` (`idx`, `name`, `email_id`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) VALUES (1, '{0}', '{1}', 'email_ids', 'Contact', '{2}', 1, '{3}', '{4}', '{5}') - """.format(str(name_counter), contact_detail.email_id, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) + """.format(frappe.generate_hash(contact_detail.email_id, 10), contact_detail.email_id, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) name_counter += 1 if contact_detail.phone: @@ -23,7 +23,7 @@ def execute(): INSERT INTO `tabContact Phone` (`idx`, `name`, `phone`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) VALUES (1, '{0}', '{1}', 'phone_nos', 'Contact', '{2}', 1, '{3}', '{4}', '{5}') - """.format(str(name_counter), contact_detail.phone, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) + """.format(frappe.generate_hash(contact_detail.phone, 10), contact_detail.phone, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) name_counter += 1 if contact_detail.mobile_no: @@ -31,5 +31,5 @@ def execute(): INSERT INTO `tabContact Phone` (`idx`, `name`, `phone`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) VALUES (2, '{0}', '{1}', 'phone_nos', 'Contact', '{2}', 0, '{3}', '{4}', '{5}') - """.format(str(name_counter), contact_detail.mobile_no, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) + """.format(frappe.generate_hash(contact_detail.mobile_no, 10), contact_detail.mobile_no, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) name_counter += 1 \ No newline at end of file From b96626e7de7616684a7143d73cc871e302253146 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 26 Aug 2019 12:50:56 +0530 Subject: [PATCH 21/26] fix: add city state and country --- frappe/contacts/address_and_contact.py | 5 +++++ frappe/hooks.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/frappe/contacts/address_and_contact.py b/frappe/contacts/address_and_contact.py index 73e5d6b176..657788423d 100644 --- a/frappe/contacts/address_and_contact.py +++ b/frappe/contacts/address_and_contact.py @@ -50,6 +50,11 @@ def load_address_and_contact(doc, key=None): "is_primary": 0 }, fields=["phone"]) + if contact.address: + contact["city"] = frappe.db.get_value("Address", contact.address, "city") + contact["state"] = frappe.db.get_value("Address", contact.address, "state") + contact["country"] = frappe.db.get_value("Address", contact.address, "country") + contact_list = sorted(contact_list, key = functools.cmp_to_key(lambda a, b: (int(a.is_primary_contact - b.is_primary_contact)) or diff --git a/frappe/hooks.py b/frappe/hooks.py index 2382aa0695..3bdaaffef8 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -263,6 +263,11 @@ user_privacy_documents = [ 'match_field': 'email_id', 'personal_fields': ['first_name', 'last_name', 'phone'], }, + { + 'doctype': 'Contact Email', + 'match_field': 'email_id', + 'personal_fields': ['email_id'], + }, { 'doctype': 'Address', 'match_field': 'email_id', From 3b6de21b117be4c125e249251792b8ff8dd22ec7 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 26 Aug 2019 22:41:18 +0530 Subject: [PATCH 22/26] fix: use address display --- frappe/contacts/address_and_contact.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frappe/contacts/address_and_contact.py b/frappe/contacts/address_and_contact.py index 657788423d..90e57c362d 100644 --- a/frappe/contacts/address_and_contact.py +++ b/frappe/contacts/address_and_contact.py @@ -51,9 +51,8 @@ def load_address_and_contact(doc, key=None): }, fields=["phone"]) if contact.address: - contact["city"] = frappe.db.get_value("Address", contact.address, "city") - contact["state"] = frappe.db.get_value("Address", contact.address, "state") - contact["country"] = frappe.db.get_value("Address", contact.address, "country") + address = frappe.get_doc("Address", contact.address) + contact["address"] = get_address_display(address.as_dict()) contact_list = sorted(contact_list, key = functools.cmp_to_key(lambda a, b: From e6ebbde9c7b9ee2641f2b934d7eb3a1d64076092 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 28 Aug 2019 00:03:58 +0530 Subject: [PATCH 23/26] fix: get address in single line --- frappe/contacts/address_and_contact.py | 4 ++-- frappe/contacts/doctype/address/address.py | 28 ++++++++++++---------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/frappe/contacts/address_and_contact.py b/frappe/contacts/address_and_contact.py index 90e57c362d..64d94dab4e 100644 --- a/frappe/contacts/address_and_contact.py +++ b/frappe/contacts/address_and_contact.py @@ -10,7 +10,7 @@ import re def load_address_and_contact(doc, key=None): """Loads address list and contact list in `__onload`""" - from frappe.contacts.doctype.address.address import get_address_display + from frappe.contacts.doctype.address.address import get_address_display, get_condensed_address filters = [ ["Dynamic Link", "link_doctype", "=", doc.doctype], @@ -52,7 +52,7 @@ def load_address_and_contact(doc, key=None): if contact.address: address = frappe.get_doc("Address", contact.address) - contact["address"] = get_address_display(address.as_dict()) + contact["address"] = get_condensed_address(address) contact_list = sorted(contact_list, key = functools.cmp_to_key(lambda a, b: diff --git a/frappe/contacts/doctype/address/address.py b/frappe/contacts/doctype/address/address.py index 57ed4e937f..c404c3028e 100644 --- a/frappe/contacts/doctype/address/address.py +++ b/frappe/contacts/doctype/address/address.py @@ -143,13 +143,13 @@ def get_list_context(context=None): } def get_address_list(doctype, txt, filters, limit_start, limit_page_length = 20, order_by = None): - from frappe.www.list import get_list - user = frappe.session.user - ignore_permissions = False - if is_website_user(): - if not filters: filters = [] - add_name = [] - contact = frappe.db.sql(""" + from frappe.www.list import get_list + user = frappe.session.user + ignore_permissions = False + if is_website_user(): + if not filters: filters = [] + add_name = [] + contact = frappe.db.sql(""" select address.name from @@ -165,12 +165,12 @@ def get_address_list(doctype, txt, filters, limit_start, limit_page_length = 20, `tabDynamic Link` as link on contact.name = link.parent where contact.user = %s)""",(user)) - for c in contact: - add_name.append(c[0]) - filters.append(("Address", "name", "in", add_name)) - ignore_permissions = True + for c in contact: + add_name.append(c[0]) + filters.append(("Address", "name", "in", add_name)) + ignore_permissions = True - return get_list(doctype, txt, filters, limit_start, limit_page_length, ignore_permissions=ignore_permissions) + return get_list(doctype, txt, filters, limit_start, limit_page_length, ignore_permissions=ignore_permissions) def has_website_permission(doc, ptype, user, verbose=False): """Returns true if there is a related lead or contact related to this document""" @@ -263,3 +263,7 @@ def address_query(doctype, txt, searchfield, start, page_len, filters): 'link_name': link_name, 'link_doctype': link_doctype }) + +def get_condensed_address(doc): + fields = ["address_title", "address_line1", "address_line2", "city", "county", "state", "country"] + return ", ".join([doc.get(d) for d in fields]) \ No newline at end of file From 3d73ef3c130d002ebb415dac0e0b3c0f6591af5d Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 28 Aug 2019 00:07:00 +0530 Subject: [PATCH 24/26] fix: use escape --- frappe/patches/v12_0/move_email_and_phone_to_child_table.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py index feb97e1ab5..7ad16e5378 100644 --- a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py +++ b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py @@ -8,7 +8,7 @@ def execute(): name_counter = 100000000 for contact_detail in contact_details: - contact_name = contact_detail.name.replace('"', '\\"').replace("'", "\\'") + contact_name = frappe.db.escape(contact_detail.name) if contact_detail.email_id: frappe.db.sql(""" From 9e181d0bb1cfe81f551b0c0fb9f246b513413f8f Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 28 Aug 2019 09:38:03 +0530 Subject: [PATCH 25/26] fix: show field only if present --- frappe/contacts/doctype/address/address.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/contacts/doctype/address/address.py b/frappe/contacts/doctype/address/address.py index c404c3028e..39a6a3abbc 100644 --- a/frappe/contacts/doctype/address/address.py +++ b/frappe/contacts/doctype/address/address.py @@ -266,4 +266,4 @@ def address_query(doctype, txt, searchfield, start, page_len, filters): def get_condensed_address(doc): fields = ["address_title", "address_line1", "address_line2", "city", "county", "state", "country"] - return ", ".join([doc.get(d) for d in fields]) \ No newline at end of file + return ", ".join([doc.get(d) for d in fields if doc.get(d)]) \ No newline at end of file From 9e5f68d0254737d772f8c5d3aaef06eab4033459 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 29 Aug 2019 09:28:09 +0530 Subject: [PATCH 26/26] fix: patch --- frappe/hooks.py | 1 - .../v12_0/move_email_and_phone_to_child_table.py | 12 ++++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/frappe/hooks.py b/frappe/hooks.py index 3bdaaffef8..eb0d5bbe77 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -266,7 +266,6 @@ user_privacy_documents = [ { 'doctype': 'Contact Email', 'match_field': 'email_id', - 'personal_fields': ['email_id'], }, { 'doctype': 'Address', diff --git a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py index 7ad16e5378..bb23fedfd5 100644 --- a/frappe/patches/v12_0/move_email_and_phone_to_child_table.py +++ b/frappe/patches/v12_0/move_email_and_phone_to_child_table.py @@ -6,7 +6,6 @@ def execute(): frappe.reload_doc("contacts", "doctype", "contact_phone") frappe.reload_doc("contacts", "doctype", "contact") - name_counter = 100000000 for contact_detail in contact_details: contact_name = frappe.db.escape(contact_detail.name) @@ -14,22 +13,19 @@ def execute(): frappe.db.sql(""" INSERT INTO `tabContact Email` (`idx`, `name`, `email_id`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) - VALUES (1, '{0}', '{1}', 'email_ids', 'Contact', '{2}', 1, '{3}', '{4}', '{5}') + VALUES (1, '{0}', '{1}', 'email_ids', 'Contact', {2}, 1, '{3}', '{4}', '{5}') """.format(frappe.generate_hash(contact_detail.email_id, 10), contact_detail.email_id, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) - name_counter += 1 if contact_detail.phone: frappe.db.sql(""" INSERT INTO `tabContact Phone` (`idx`, `name`, `phone`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) - VALUES (1, '{0}', '{1}', 'phone_nos', 'Contact', '{2}', 1, '{3}', '{4}', '{5}') + VALUES (1, '{0}', '{1}', 'phone_nos', 'Contact', {2}, 1, '{3}', '{4}', '{5}') """.format(frappe.generate_hash(contact_detail.phone, 10), contact_detail.phone, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) - name_counter += 1 if contact_detail.mobile_no: frappe.db.sql(""" INSERT INTO `tabContact Phone` (`idx`, `name`, `phone`, `parentfield`, `parenttype`, `parent`, `is_primary`, `creation`, `modified`, `modified_by`) - VALUES (2, '{0}', '{1}', 'phone_nos', 'Contact', '{2}', 0, '{3}', '{4}', '{5}') - """.format(frappe.generate_hash(contact_detail.mobile_no, 10), contact_detail.mobile_no, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) - name_counter += 1 \ No newline at end of file + VALUES (2, '{0}', '{1}', 'phone_nos', 'Contact', {2}, 0, '{3}', '{4}', '{5}') + """.format(frappe.generate_hash(contact_detail.mobile_no, 10), contact_detail.mobile_no, contact_name, contact_detail.creation, contact_detail.modified, contact_detail.modified_by)) \ No newline at end of file