From 9f0a4a6cb0a3ee4a4b0cd7099b56ed9ee84d0690 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 11 Sep 2019 20:12:57 +0530 Subject: [PATCH 01/42] fix: reintroduced mobile_no --- frappe/contacts/doctype/contact/contact.json | 11 ++++++-- .../doctype/contact_phone/contact_phone.json | 28 ++++++++++++------- .../addresses_and_contacts.py | 2 +- .../test_addresses_and_contacts.py | 2 +- frappe/hooks.py | 2 +- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/frappe/contacts/doctype/contact/contact.json b/frappe/contacts/doctype/contact/contact.json index f700411e80..d4eb552e6e 100644 --- a/frappe/contacts/doctype/contact/contact.json +++ b/frappe/contacts/doctype/contact/contact.json @@ -20,6 +20,7 @@ "designation", "gender", "phone", + "mobile_no", "image", "sb_00", "email_ids", @@ -203,13 +204,19 @@ "fieldtype": "Table", "label": "Phone Nos", "options": "Contact Phone" + }, + { + "fieldname": "mobile_no", + "fieldtype": "Data", + "label": "Mobile No", + "read_only": 1 } ], "icon": "fa fa-user", "idx": 1, "image_field": "image", - "modified": "2019-08-09 10:23:00.486673", - "modified_by": "Administrator", + "modified": "2019-09-11 20:02:08.961211", + "modified_by": "himanshu@erpnext.com", "module": "Contacts", "name": "Contact", "name_case": "Title Case", diff --git a/frappe/contacts/doctype/contact_phone/contact_phone.json b/frappe/contacts/doctype/contact_phone/contact_phone.json index 971dedf3d2..4627f4e69d 100644 --- a/frappe/contacts/doctype/contact_phone/contact_phone.json +++ b/frappe/contacts/doctype/contact_phone/contact_phone.json @@ -5,26 +5,34 @@ "engine": "InnoDB", "field_order": [ "phone", - "is_primary" + "is_primary_phone", + "is_primary_mobile" ], "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" + }, + { + "default": "0", + "fieldname": "is_primary_phone", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Is Primary Phone" + }, + { + "default": "0", + "fieldname": "is_primary_mobile", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Is Primary Mobile" } ], "istable": 1, - "modified": "2019-08-05 11:40:59.104224", - "modified_by": "Administrator", + "modified": "2019-09-11 19:52:31.732427", + "modified_by": "himanshu@erpnext.com", "module": "Contacts", "name": "Contact Phone", "owner": "Administrator", 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 fb345a4384..ba0ecd41d1 100644 --- a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py +++ b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py @@ -7,7 +7,7 @@ import frappe from frappe import _ field_map = { - "Contact": ["first_name", "last_name", "address", "phone", "email_id", "is_primary_contact"], + "Contact": ["first_name", "last_name", "address", "phone", "mobile_no", "email_id", "is_primary_contact"], "Address": ["address_line1", "address_line2", "city", "state", "pincode", "country", "is_primary_address"] } 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 d87676e272..434d138a6c 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 @@ -103,7 +103,7 @@ class TestAddressesAndContacts(unittest.TestCase): 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] + 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', None, 'test_contact@example.com', 1] self.assertListEqual(test_item, report_data[idx]) def tearDown(self): diff --git a/frappe/hooks.py b/frappe/hooks.py index eb0d5bbe77..6b37e54d11 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -261,7 +261,7 @@ user_privacy_documents = [ { 'doctype': 'Contact', 'match_field': 'email_id', - 'personal_fields': ['first_name', 'last_name', 'phone'], + 'personal_fields': ['first_name', 'last_name', 'phone', 'mobile_no'], }, { 'doctype': 'Contact Email', From a4967bfd740c563be5745175ba76533cf844b0e5 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 12 Sep 2019 00:17:15 +0530 Subject: [PATCH 02/42] fix: add validation for primary nos --- frappe/contacts/doctype/contact/contact.py | 44 +++++++++++++++---- .../doctype/contact_phone/contact_phone.json | 8 ++-- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index 085452988a..ceecb1f428 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -29,8 +29,9 @@ class Contact(Document): break def validate(self): - self.set_primary("email_id", "email_ids") - self.set_primary("phone", "phone_nos") + self.set_primary_email() + self.set_primary_phone_and_mobile_no("phone") + self.set_primary_phone_and_mobile_no("mobile_no") if self.email_id: self.email_id = self.email_id.strip() @@ -85,14 +86,41 @@ 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)) + def set_primary_email(self): + primary_email = [email.email_id for email in self.email_ids if email.is_primary] + + if len(primary_email) > 1: + frappe.throw(_("Only one Email ID can be set as primary.")) + + if len(self.email_ids) == 1: + self.email_ids[0].is_primary = 1 + self.email_id = self.email_ids[0].email_id else: - for d in self.get(child_table): + for d in self.email_ids: if d.is_primary == 1: - setattr(self, fieldname, d.get(fieldname)) + self.email_id = d.email_id + break + + def set_primary_phone_and_mobile_no(self, fieldname): + field_name = "is_primary_" + fieldname + is_primary = [phone.phone for phone in self.phone_nos if phone.get(field_name)] + + if len(is_primary) > 1: + frappe.throw(_("Only one {0} can be set as primary.").format(frappe.bold(frappe.unscrub(fieldname)))) + + if len(self.phone_nos) == 1: + if self.phone_nos[0].phone == self.phone or self.phone_nos[0].phone == self.mobile_no: + return + + setattr(self.phone_nos[0], fieldname, 1) + setattr(self, fieldname, self.phone_nos[0].get("phone")) + else: + for d in self.phone_nos: + if d.get(field_name) == 1: + if d.phone == self.phone or d.phone == self.mobile_no: + frappe.throw(_("Same number {0} cannot be set for Phone and Mobile No.").format(frappe.bold(d.phone))) + + setattr(self, fieldname, d.phone) break def get_default_contact(doctype, name): diff --git a/frappe/contacts/doctype/contact_phone/contact_phone.json b/frappe/contacts/doctype/contact_phone/contact_phone.json index 4627f4e69d..248abfa9fe 100644 --- a/frappe/contacts/doctype/contact_phone/contact_phone.json +++ b/frappe/contacts/doctype/contact_phone/contact_phone.json @@ -6,7 +6,7 @@ "field_order": [ "phone", "is_primary_phone", - "is_primary_mobile" + "is_primary_mobile_no" ], "fields": [ { @@ -24,14 +24,14 @@ }, { "default": "0", - "fieldname": "is_primary_mobile", + "fieldname": "is_primary_mobile_no", "fieldtype": "Check", "in_list_view": 1, - "label": "Is Primary Mobile" + "label": "Is Primary Mobile No" } ], "istable": 1, - "modified": "2019-09-11 19:52:31.732427", + "modified": "2019-09-11 20:57:22.108260", "modified_by": "himanshu@erpnext.com", "module": "Contacts", "name": "Contact Phone", From a20f3fc4acfe060094c40301e90ea58a8c76e275 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 12 Sep 2019 00:29:09 +0530 Subject: [PATCH 03/42] fix: make user select one email and phone --- frappe/contacts/doctype/contact/contact.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index ceecb1f428..b02c8c9076 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -87,10 +87,15 @@ class Contact(Document): self.save(ignore_permissions=True) def set_primary_email(self): + if not self.email_ids: + return + primary_email = [email.email_id for email in self.email_ids if email.is_primary] if len(primary_email) > 1: frappe.throw(_("Only one Email ID can be set as primary.")) + elif len(primary_email) == 0: + frappe.throw(_("Select primary {0}.").format(frappe.bold("Email"))) if len(self.email_ids) == 1: self.email_ids[0].is_primary = 1 @@ -102,11 +107,16 @@ class Contact(Document): break def set_primary_phone_and_mobile_no(self, fieldname): + if not self.phone_nos: + return + field_name = "is_primary_" + fieldname is_primary = [phone.phone for phone in self.phone_nos if phone.get(field_name)] if len(is_primary) > 1: frappe.throw(_("Only one {0} can be set as primary.").format(frappe.bold(frappe.unscrub(fieldname)))) + elif len(is_primary) == 0: + frappe.throw(_("Select primary {0}.").format(frappe.bold(frappe.scrub(fieldname)))) if len(self.phone_nos) == 1: if self.phone_nos[0].phone == self.phone or self.phone_nos[0].phone == self.mobile_no: From d1bdb554ff2deda6fcfc0b4115f57a2b13c92e45 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 12 Sep 2019 00:39:40 +0530 Subject: [PATCH 04/42] patch: set is_primary_mobile_no --- frappe/patches/v12_0/set_mobile_no.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 frappe/patches/v12_0/set_mobile_no.py diff --git a/frappe/patches/v12_0/set_mobile_no.py b/frappe/patches/v12_0/set_mobile_no.py new file mode 100644 index 0000000000..4f1f816cc8 --- /dev/null +++ b/frappe/patches/v12_0/set_mobile_no.py @@ -0,0 +1,7 @@ +import frappe + +def execute(): + frappe.reload_doc("contacts", "doctype", "contact_phone") + frappe.reload_doc("contacts", "doctype", "contact") + + frappe.db.sql("""UPDATE `tabContact Phone` SET is_primary_mobile_no='1' WHERE idx='2'""") \ No newline at end of file From 52b75fecd4061b8166aa6ef4c5ce182473373702 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 13 Sep 2019 11:50:03 +0530 Subject: [PATCH 05/42] fix: throw error when phone and mobile are same --- frappe/contacts/doctype/contact/contact.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index b02c8c9076..c555d4abe5 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -90,12 +90,8 @@ class Contact(Document): if not self.email_ids: return - primary_email = [email.email_id for email in self.email_ids if email.is_primary] - - if len(primary_email) > 1: + if len([email.email_id for email in self.email_ids if email.is_primary]) > 1: frappe.throw(_("Only one Email ID can be set as primary.")) - elif len(primary_email) == 0: - frappe.throw(_("Select primary {0}.").format(frappe.bold("Email"))) if len(self.email_ids) == 1: self.email_ids[0].is_primary = 1 @@ -111,18 +107,15 @@ class Contact(Document): return field_name = "is_primary_" + fieldname - is_primary = [phone.phone for phone in self.phone_nos if phone.get(field_name)] - if len(is_primary) > 1: + if len([phone.phone for phone in self.phone_nos if phone.get(field_name)]) > 1: frappe.throw(_("Only one {0} can be set as primary.").format(frappe.bold(frappe.unscrub(fieldname)))) - elif len(is_primary) == 0: - frappe.throw(_("Select primary {0}.").format(frappe.bold(frappe.scrub(fieldname)))) if len(self.phone_nos) == 1: if self.phone_nos[0].phone == self.phone or self.phone_nos[0].phone == self.mobile_no: - return + frappe.throw(_("Same number {0} cannot be set for Phone and Mobile No.").format(frappe.bold(self.phone_nos[0].phone))) - setattr(self.phone_nos[0], fieldname, 1) + setattr(self.phone_nos[0], field_name, 1) setattr(self, fieldname, self.phone_nos[0].get("phone")) else: for d in self.phone_nos: From d0176106773d205788a6c939d934f39f10bba7d5 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 15 Sep 2019 20:08:28 +0530 Subject: [PATCH 06/42] test: test cases for contacts --- frappe/contacts/doctype/contact/contact.py | 18 ++-- .../contacts/doctype/contact/test_contact.py | 84 ++++++++++++++++++- .../doctype/contact/test_records.json | 19 ----- .../google_contacts/google_contacts.py | 2 +- 4 files changed, 95 insertions(+), 28 deletions(-) delete mode 100644 frappe/contacts/doctype/contact/test_records.json diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index 9137025dd8..952d198004 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -80,10 +80,11 @@ class Contact(Document): if autosave: self.save(ignore_permissions=True) - def add_phone(self, phone, is_primary=0, autosave=False): + def add_phone(self, phone, is_primary_phone=0, is_primary_mobile_no=0, autosave=False): self.append("phone_nos", { "phone": phone, - "is_primary": is_primary + "is_primary_phone": is_primary_phone, + "is_primary_mobile_no": is_primary_mobile_no }) if autosave: @@ -93,8 +94,12 @@ class Contact(Document): if not self.email_ids: return - if len([email.email_id for email in self.email_ids if email.is_primary]) > 1: + primary_email = [email.email_id for email in self.email_ids if email.is_primary] + + if len(self.email_ids) > 1 and len(primary_email) > 1: frappe.throw(_("Only one Email ID can be set as primary.")) + elif len(self.email_ids) > 1 and len(primary_email) == 0: + frappe.throw(_("Set primary Email ID.")) if len(self.email_ids) == 1: self.email_ids[0].is_primary = 1 @@ -106,13 +111,16 @@ class Contact(Document): break def set_primary_phone_and_mobile_no(self, fieldname): - if not self.phone_nos: + if len(self.phone_nos) == 0: return field_name = "is_primary_" + fieldname + primary = [phone.phone for phone in self.phone_nos if phone.get(field_name)] - if len([phone.phone for phone in self.phone_nos if phone.get(field_name)]) > 1: + if len(self.phone_nos) > 1 and len(primary) > 1: frappe.throw(_("Only one {0} can be set as primary.").format(frappe.bold(frappe.unscrub(fieldname)))) + elif len(self.phone_nos) > 1 and len(primary) == 0: + frappe.throw(_("Set primary {0}").format(frappe.unscrub(fieldname))) if len(self.phone_nos) == 1: if self.phone_nos[0].phone == self.phone or self.phone_nos[0].phone == self.mobile_no: diff --git a/frappe/contacts/doctype/contact/test_contact.py b/frappe/contacts/doctype/contact/test_contact.py index 496ff68299..bac2503aef 100644 --- a/frappe/contacts/doctype/contact/test_contact.py +++ b/frappe/contacts/doctype/contact/test_contact.py @@ -5,8 +5,86 @@ from __future__ import unicode_literals import frappe import unittest - -test_records = frappe.get_test_records('Contact') +from frappe.exceptions import ValidationError class TestContact(unittest.TestCase): - pass + + def create_contact(self, name, salutation, emails=None, phones=None, save=True): + doc = frappe.get_doc({ + "doctype": "Contact", + "first_name": name, + "status": "Open", + "salutation": salutation + }) + if emails: + for d in emails: + doc.add_email(d.get("email"), d.get("is_primary")) + + if phones: + for d in phones: + doc.add_phone(d.get("phone"), d.get("is_primary_phone"), d.get("is_primary_mobile_no")) + + if save: + doc.insert() + + return doc + + def tearDown(self): + frappe.db.sql("delete from `tabContact`") + frappe.db.sql("delete from `tabContact Phone`") + frappe.db.sql("delete from `tabContact Email`") + + def test_check_default_email(self): + emails = [ + {"email": "test1@example.com", "is_primary": 0}, + {"email": "test2@example.com", "is_primary": 0}, + {"email": "test3@example.com", "is_primary": 0}, + {"email": "test4@example.com", "is_primary": 1}, + {"email": "test5@example.com", "is_primary": 0}, + ] + contact = self.create_contact("Email", "Mr", emails=emails) + + self.assertEqual(contact.email_id, "test4@example.com") + + def test_check_default_phone_and_mobile(self): + phones = [ + {"phone": "+91 0000000000", "is_primary_phone": 0, "is_primary_mobile_no": 0}, + {"phone": "+91 0000000001", "is_primary_phone": 0, "is_primary_mobile_no": 0}, + {"phone": "+91 0000000002", "is_primary_phone": 1, "is_primary_mobile_no": 0}, + {"phone": "+91 0000000003", "is_primary_phone": 0, "is_primary_mobile_no": 1}, + ] + contact = self.create_contact("Phone", "Mr", phones=phones) + + self.assertEqual(contact.phone, "+91 0000000002") + self.assertEqual(contact.mobile_no, "+91 0000000003") + + def test_same_phone_and_mobile(self): + phones = [ + {"phone": "+91 0000000000", "is_primary_phone": 1, "is_primary_mobile_no": 1}, + ] + contact = self.create_contact("Phone", "Mr", phones=phones, save=False) + self.assertRaises(ValidationError, contact.save) + + def test_no_primary_set(self): + emails = [ + {"email": "test1@example.com", "is_primary": 0}, + {"email": "test2@example.com", "is_primary": 0}, + {"email": "test3@example.com", "is_primary": 0}, + {"email": "test4@example.com", "is_primary": 0}, + {"email": "test5@example.com", "is_primary": 0}, + ] + phones = [ + {"phone": "+91 0000000000", "is_primary_phone": 0, "is_primary_mobile_no": 0}, + {"phone": "+91 0000000001", "is_primary_phone": 0, "is_primary_mobile_no": 0}, + {"phone": "+91 0000000002", "is_primary_phone": 0, "is_primary_mobile_no": 0}, + {"phone": "+91 0000000003", "is_primary_phone": 0, "is_primary_mobile_no": 0}, + ] + + contact_email = self.create_contact("Default", "Mr", emails=emails, phones=phones, save=False) + contact_phone = self.create_contact("Default", "Mr", emails=emails, phones=phones, save=False) + + # No default set for emails if many emails are passed as params + self.assertRaises(ValidationError, contact_email.save) + + # No default set for phones if many phones are passed as params + self.assertRaises(ValidationError, contact_phone.save) \ No newline at end of file diff --git a/frappe/contacts/doctype/contact/test_records.json b/frappe/contacts/doctype/contact/test_records.json deleted file mode 100644 index 8f4be113b4..0000000000 --- a/frappe/contacts/doctype/contact/test_records.json +++ /dev/null @@ -1,19 +0,0 @@ -[ - { - "doctype": "Contact", - "salutation": "Mr", - "email_id": "test_contact@example.com", - "first_name": "_Test Contact For _Test Customer", - "is_primary_contact": 1, - "phone": "+91 0000000000", - "status": "Open" - }, - { - "doctype": "Contact", - "email_id": "test_contact@example.com", - "first_name": "_Test Contact For _Test Supplier", - "is_primary_contact": 1, - "phone": "+91 0000000000", - "status": "Open" - } -] \ No newline at end of file diff --git a/frappe/integrations/doctype/google_contacts/google_contacts.py b/frappe/integrations/doctype/google_contacts/google_contacts.py index 738c097f63..8c6ab97017 100644 --- a/frappe/integrations/doctype/google_contacts/google_contacts.py +++ b/frappe/integrations/doctype/google_contacts/google_contacts.py @@ -187,7 +187,7 @@ def sync_contacts_from_google_contacts(g_contact): contact.add_email(email_id=email.get("value"), is_primary=1 if email.get("metadata").get("primary") else 0) for phone in connection.get("phoneNumbers", []): - contact.add_phone(phone=phone.get("value"), is_primary=1 if phone.get("metadata").get("primary") else 0) + contact.add_phone(phone=phone.get("value"), is_primary_phone=1 if phone.get("metadata").get("primary") else 0) contact.insert(ignore_permissions=True) From cc74ab39a04fa0d95dffe31080ea96abf690b0ee Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 15 Sep 2019 20:38:17 +0530 Subject: [PATCH 07/42] test: fix test cases --- .../contacts/doctype/contact/test_contact.py | 48 +++++++++---------- .../test_addresses_and_contacts.py | 2 +- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/frappe/contacts/doctype/contact/test_contact.py b/frappe/contacts/doctype/contact/test_contact.py index bac2503aef..82abec3b1e 100644 --- a/frappe/contacts/doctype/contact/test_contact.py +++ b/frappe/contacts/doctype/contact/test_contact.py @@ -9,31 +9,6 @@ from frappe.exceptions import ValidationError class TestContact(unittest.TestCase): - def create_contact(self, name, salutation, emails=None, phones=None, save=True): - doc = frappe.get_doc({ - "doctype": "Contact", - "first_name": name, - "status": "Open", - "salutation": salutation - }) - if emails: - for d in emails: - doc.add_email(d.get("email"), d.get("is_primary")) - - if phones: - for d in phones: - doc.add_phone(d.get("phone"), d.get("is_primary_phone"), d.get("is_primary_mobile_no")) - - if save: - doc.insert() - - return doc - - def tearDown(self): - frappe.db.sql("delete from `tabContact`") - frappe.db.sql("delete from `tabContact Phone`") - frappe.db.sql("delete from `tabContact Email`") - def test_check_default_email(self): emails = [ {"email": "test1@example.com", "is_primary": 0}, @@ -87,4 +62,25 @@ class TestContact(unittest.TestCase): self.assertRaises(ValidationError, contact_email.save) # No default set for phones if many phones are passed as params - self.assertRaises(ValidationError, contact_phone.save) \ No newline at end of file + self.assertRaises(ValidationError, contact_phone.save) + +def create_contact(name, salutation, emails=None, phones=None, save=True): + doc = frappe.get_doc({ + "doctype": "Contact", + "first_name": name, + "status": "Open", + "salutation": salutation + }) + + if emails: + for d in emails: + doc.add_email(d.get("email"), d.get("is_primary")) + + if phones: + for d in phones: + doc.add_phone(d.get("phone"), d.get("is_primary_phone"), d.get("is_primary_mobile_no")) + + if save: + doc.insert() + + return doc \ No newline at end of file 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 434d138a6c..47e1c28e8b 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 @@ -83,7 +83,7 @@ def create_linked_contact(link_list, address): "status": "Open" }) contact.add_email("test_contact@example.com") - contact.add_phone("+91 0000000000") + contact.add_phone("+91 0000000000", is_primary_phone=True) for name in link_list: contact.append("links",{ From 7dba556b8c5b029ebe264d724a13a86dd18f6449 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 16 Sep 2019 10:19:40 +0530 Subject: [PATCH 08/42] test: fix test cases --- frappe/contacts/doctype/contact/test_contact.py | 10 +++++----- .../test_addresses_and_contacts.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frappe/contacts/doctype/contact/test_contact.py b/frappe/contacts/doctype/contact/test_contact.py index 82abec3b1e..d406f824a3 100644 --- a/frappe/contacts/doctype/contact/test_contact.py +++ b/frappe/contacts/doctype/contact/test_contact.py @@ -17,7 +17,7 @@ class TestContact(unittest.TestCase): {"email": "test4@example.com", "is_primary": 1}, {"email": "test5@example.com", "is_primary": 0}, ] - contact = self.create_contact("Email", "Mr", emails=emails) + contact = create_contact("Email", "Mr", emails=emails) self.assertEqual(contact.email_id, "test4@example.com") @@ -28,7 +28,7 @@ class TestContact(unittest.TestCase): {"phone": "+91 0000000002", "is_primary_phone": 1, "is_primary_mobile_no": 0}, {"phone": "+91 0000000003", "is_primary_phone": 0, "is_primary_mobile_no": 1}, ] - contact = self.create_contact("Phone", "Mr", phones=phones) + contact = create_contact("Phone", "Mr", phones=phones) self.assertEqual(contact.phone, "+91 0000000002") self.assertEqual(contact.mobile_no, "+91 0000000003") @@ -37,7 +37,7 @@ class TestContact(unittest.TestCase): phones = [ {"phone": "+91 0000000000", "is_primary_phone": 1, "is_primary_mobile_no": 1}, ] - contact = self.create_contact("Phone", "Mr", phones=phones, save=False) + contact = create_contact("Phone", "Mr", phones=phones, save=False) self.assertRaises(ValidationError, contact.save) def test_no_primary_set(self): @@ -55,8 +55,8 @@ class TestContact(unittest.TestCase): {"phone": "+91 0000000003", "is_primary_phone": 0, "is_primary_mobile_no": 0}, ] - contact_email = self.create_contact("Default", "Mr", emails=emails, phones=phones, save=False) - contact_phone = self.create_contact("Default", "Mr", emails=emails, phones=phones, save=False) + contact_email = create_contact("Default", "Mr", emails=emails, phones=phones, save=False) + contact_phone = create_contact("Default", "Mr", emails=emails, phones=phones, save=False) # No default set for emails if many emails are passed as params self.assertRaises(ValidationError, contact_email.save) 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 47e1c28e8b..2db395102a 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 @@ -82,7 +82,7 @@ def create_linked_contact(link_list, address): "address": address, "status": "Open" }) - contact.add_email("test_contact@example.com") + contact.add_email("test_contact@example.com", is_primary=True) contact.add_phone("+91 0000000000", is_primary_phone=True) for name in link_list: From ac1c242a142f9cd7a31de6447beef5a931732cde Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 19 Sep 2019 17:55:34 +0530 Subject: [PATCH 09/42] feat: Energy Points for assigned users on a document --- frappe/model/document.py | 12 +++++++++++ .../energy_point_rule/energy_point_rule.json | 11 +++++++++- .../energy_point_rule/energy_point_rule.py | 21 +++++++++++-------- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/frappe/model/document.py b/frappe/model/document.py index fd1ffec483..45e63c7160 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -1232,6 +1232,18 @@ class Document(BaseDocument): frappe.bold(self.meta.get_label(from_date_field)), ), frappe.exceptions.InvalidDates) + def get_assigned_users(self): + assignments = frappe.get_all('ToDo', + fields=['owner'], + filters={ + 'reference_type': self.doctype, + 'reference_name': self.name, + 'status': ('!=', 'Cancelled'), + }) + + users = set([assignment.owner for assignment in assignments]) + return users + def execute_action(doctype, name, action, **kwargs): '''Execute an action on a document (called by background worker)''' doc = frappe.get_doc(doctype, name) diff --git a/frappe/social/doctype/energy_point_rule/energy_point_rule.json b/frappe/social/doctype/energy_point_rule/energy_point_rule.json index 7a599701dc..fc7cdd280c 100644 --- a/frappe/social/doctype/energy_point_rule/energy_point_rule.json +++ b/frappe/social/doctype/energy_point_rule/energy_point_rule.json @@ -12,6 +12,7 @@ "for_doc_event", "condition", "points", + "for_assigned_users", "user_field", "multiplier_field", "max_points" @@ -56,6 +57,7 @@ "reqd": 1 }, { + "depends_on": "eval:!doc.for_assigned_users || doc.for_doc_event==='New'", "description": "The user from this field will be rewarded points", "fieldname": "user_field", "fieldtype": "Select", @@ -84,9 +86,16 @@ "fieldtype": "Select", "label": "For Document Event", "options": "New\nSubmit\nCancel\nCustom" + }, + { + "default": "0", + "depends_on": "eval:doc.for_doc_event !=='New'", + "fieldname": "for_assigned_users", + "fieldtype": "Check", + "label": "Allot Points To Assigned Users" } ], - "modified": "2019-09-05 14:22:27.664645", + "modified": "2019-09-19 17:45:58.137148", "modified_by": "Administrator", "module": "Social", "name": "Energy Point Rule", diff --git a/frappe/social/doctype/energy_point_rule/energy_point_rule.py b/frappe/social/doctype/energy_point_rule/energy_point_rule.py index 1641e05f5e..9bd97dd281 100644 --- a/frappe/social/doctype/energy_point_rule/energy_point_rule.py +++ b/frappe/social/doctype/energy_point_rule/energy_point_rule.py @@ -31,21 +31,24 @@ class EnergyPointRule(Document): reference_doctype = doc.doctype reference_name = doc.name - user = doc.get(self.user_field) + users = [] + if self.for_assigned_users: + users = doc.get_assigned_users() + else: + users = [doc.get(self.user_field)] rule = self.name # incase of zero as result after roundoff if not points: return - # if user_field has no value - if not user or user == 'Administrator': return - try: - create_energy_points_log(reference_doctype, reference_name, { - 'points': points, - 'user': user, - 'rule': rule - }) + for user in users: + if not user or user == 'Administrator': continue + create_energy_points_log(reference_doctype, reference_name, { + 'points': points, + 'user': user, + 'rule': rule + }) except Exception as e: frappe.log_error(frappe.get_traceback(), 'apply_energy_point') From f3b7461498c9d9413616dfbf043b28603a242491 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 19 Sep 2019 18:19:33 +0530 Subject: [PATCH 10/42] fix: test fixes for same phone and mobile --- frappe/contacts/doctype/contact/contact.py | 57 +++++++------------ .../contacts/doctype/contact/test_contact.py | 2 +- 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index c7f2de738e..75f2d56916 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -30,11 +30,9 @@ class Contact(Document): def validate(self): self.set_primary_email() - self.set_primary_phone_and_mobile_no("phone") - self.set_primary_phone_and_mobile_no("mobile_no") - - if self.email_id: - self.email_id = self.email_id.strip() + self.set_primary("phone") + self.set_primary("mobile_no") + self.check_if_primary_phone_and_mobile_no_same() self.set_user() @@ -94,48 +92,35 @@ class Contact(Document): if not self.email_ids: return - primary_email = [email.email_id for email in self.email_ids if email.is_primary] - - if len(self.email_ids) > 1 and len(primary_email) > 1: + if len([email.email_id for email in self.email_ids if email.is_primary]) > 1: frappe.throw(_("Only one Email ID can be set as primary.")) - elif len(self.email_ids) > 1 and len(primary_email) == 0: - frappe.throw(_("Set primary Email ID.")) - if len(self.email_ids) == 1: - self.email_ids[0].is_primary = 1 - self.email_id = self.email_ids[0].email_id - else: - for d in self.email_ids: - if d.is_primary == 1: - self.email_id = d.email_id - break + for d in self.email_ids: + if d.is_primary == 1: + self.email_id = d.email_id.strip() + break - def set_primary_phone_and_mobile_no(self, fieldname): + def set_primary(self, fieldname): + # Used to set primary mobile and phone no. if len(self.phone_nos) == 0: return field_name = "is_primary_" + fieldname - primary = [phone.phone for phone in self.phone_nos if phone.get(field_name)] - if len(self.phone_nos) > 1 and len(primary) > 1: - frappe.throw(_("Only one {0} can be set as primary.").format(frappe.bold(frappe.unscrub(fieldname)))) - elif len(self.phone_nos) > 1 and len(primary) == 0: - frappe.throw(_("Set primary {0}").format(frappe.unscrub(fieldname))) + is_primary = [phone.phone for phone in self.phone_nos if phone.get(field_name)] - if len(self.phone_nos) == 1: - if self.phone_nos[0].phone == self.phone or self.phone_nos[0].phone == self.mobile_no: - frappe.throw(_("Same number {0} cannot be set for Phone and Mobile No.").format(frappe.bold(self.phone_nos[0].phone))) + if len(is_primary) > 1: + frappe.throw(_("Only one {0} can be set as primary.").format(frappe.scrub(fieldname))) - setattr(self.phone_nos[0], field_name, 1) - setattr(self, fieldname, self.phone_nos[0].get("phone")) - else: - for d in self.phone_nos: - if d.get(field_name) == 1: - if d.phone == self.phone or d.phone == self.mobile_no: - frappe.throw(_("Same number {0} cannot be set for Phone and Mobile No.").format(frappe.bold(d.phone))) + for d in self.phone_nos: + if d.get(field_name) == 1: + setattr(self, fieldname, d.phone) + break - setattr(self, fieldname, d.phone) - break + def check_if_primary_phone_and_mobile_no_same(self): + if self.phone and self.mobile_no and self.phone == self.mobile_no: + number = frappe.bold(self.phone) + frappe.throw(_("Number {0} cannot be set as primary for Phone as well as Mobile No.").format(number)) def get_default_contact(doctype, name): '''Returns default contact for the given doctype, name''' diff --git a/frappe/contacts/doctype/contact/test_contact.py b/frappe/contacts/doctype/contact/test_contact.py index d406f824a3..2e6f9ad422 100644 --- a/frappe/contacts/doctype/contact/test_contact.py +++ b/frappe/contacts/doctype/contact/test_contact.py @@ -51,7 +51,7 @@ class TestContact(unittest.TestCase): phones = [ {"phone": "+91 0000000000", "is_primary_phone": 0, "is_primary_mobile_no": 0}, {"phone": "+91 0000000001", "is_primary_phone": 0, "is_primary_mobile_no": 0}, - {"phone": "+91 0000000002", "is_primary_phone": 0, "is_primary_mobile_no": 0}, + {"phone": "+91 0000000002", "is_primary_phone": 1, "is_primary_mobile_no": 1}, {"phone": "+91 0000000003", "is_primary_phone": 0, "is_primary_mobile_no": 0}, ] From cc8953ad663979f620551e9bf7d00d4a2d2d6985 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 20 Sep 2019 14:00:40 +0530 Subject: [PATCH 11/42] tests: fix test cases --- .../doctype/contact/test_records.json | 39 +++++++++++++++++++ frappe/core/doctype/user/user.py | 4 +- .../test_personal_data_download_request.py | 3 ++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 frappe/contacts/doctype/contact/test_records.json diff --git a/frappe/contacts/doctype/contact/test_records.json b/frappe/contacts/doctype/contact/test_records.json new file mode 100644 index 0000000000..eb540ce4db --- /dev/null +++ b/frappe/contacts/doctype/contact/test_records.json @@ -0,0 +1,39 @@ +[ + { + "doctype": "Contact", + "salutation": "Mr", + "first_name": "_Test Contact For _Test Customer", + "is_primary_contact": 1, + "status": "Open", + "email_ids": [ + { + "email_id": "test_contact@example.com", + "is_primary": 1 + } + ], + "phone_nos": [ + { + "phone": "+91 0000000000", + "is_primary_phone": 1 + } + ] + }, + { + "doctype": "Contact", + "first_name": "_Test Contact For _Test Supplier", + "is_primary_contact": 1, + "status": "Open", + "email_ids": [ + { + "email_id": "test_contact@example.com", + "is_primary": 1 + } + ], + "phone_nos": [ + { + "phone": "+91 0000000000", + "is_primary_phone": 1 + } + ] + } +] \ No newline at end of file diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index cd754aef3a..157b7fe26d 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -1035,9 +1035,10 @@ def update_roles(role_profile): user.add_roles(*roles) def create_contact(user, ignore_links=False, ignore_mandatory=False): + from frappe.contacts.doctype.contact.contact import get_contact_name if user.name in ["Administrator", "Guest"]: return - if not frappe.db.get_value("Contact", {"email_id": user.email}): + if not get_contact_name(user.email): contact = frappe.get_doc({ "doctype": "Contact", "first_name": user.first_name, @@ -1056,7 +1057,6 @@ def create_contact(user, ignore_links=False, ignore_mandatory=False): contact.add_phone(user.mobile_no) contact.insert(ignore_permissions=True, ignore_links=ignore_links, ignore_mandatory=ignore_mandatory) - @frappe.whitelist() def generate_keys(user): """ diff --git a/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py b/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py index 64d4e45660..1965999042 100644 --- a/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py +++ b/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py @@ -13,6 +13,9 @@ class TestRequestPersonalData(unittest.TestCase): def setUp(self): create_user_if_not_exists(email='test_privacy@example.com') + def tearDown(self): + frappe.db.sql("""DELETE FROM `tabPersonal Data Download Request`""") + def test_user_data_creation(self): user_data = json.loads(get_user_data('test_privacy@example.com')) expected_data = {'Contact': frappe.get_all('Contact', {'email_id':'test_privacy@example.com'}, ["*"])} From a0a57f4a5d4712e348b5cc97daaa44bfa4e45435 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 20 Sep 2019 14:22:40 +0530 Subject: [PATCH 12/42] tests: fix tests --- .../test_personal_data_download_request.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py b/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py index 1965999042..50a144b4e0 100644 --- a/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py +++ b/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py @@ -7,7 +7,7 @@ import frappe import unittest import json from frappe.website.doctype.personal_data_download_request.personal_data_download_request import get_user_data - +from frappe.contacts.doctype.contact.contact import get_contact_name class TestRequestPersonalData(unittest.TestCase): def setUp(self): @@ -18,7 +18,8 @@ class TestRequestPersonalData(unittest.TestCase): def test_user_data_creation(self): user_data = json.loads(get_user_data('test_privacy@example.com')) - expected_data = {'Contact': frappe.get_all('Contact', {'email_id':'test_privacy@example.com'}, ["*"])} + contact_name = get_contact_name('test_privacy@example.com') + expected_data = {'Contact': frappe.get_all('Contact', contact_name, ["*"])} expected_data = json.loads(json.dumps(expected_data, default=str)) self.assertEqual({'Contact': user_data['Contact']}, expected_data) @@ -48,8 +49,7 @@ class TestRequestPersonalData(unittest.TestCase): frappe.db.sql("delete from `tabEmail Queue`") def create_user_if_not_exists(email, first_name = None): - if frappe.db.exists("User", email): - return + frappe.delete_doc_if_exists("User", email) frappe.get_doc({ "doctype": "User", From 1fdb70ddbad10b7c56c6c8424e54e63cb1406c06 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 20 Sep 2019 14:36:28 +0530 Subject: [PATCH 13/42] fix: orm query --- .../test_personal_data_download_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py b/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py index 50a144b4e0..9a62b845e1 100644 --- a/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py +++ b/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py @@ -19,7 +19,7 @@ class TestRequestPersonalData(unittest.TestCase): def test_user_data_creation(self): user_data = json.loads(get_user_data('test_privacy@example.com')) contact_name = get_contact_name('test_privacy@example.com') - expected_data = {'Contact': frappe.get_all('Contact', contact_name, ["*"])} + expected_data = {'Contact': frappe.get_all('Contact', {"name": contact_name}, ["*"])} expected_data = json.loads(json.dumps(expected_data, default=str)) self.assertEqual({'Contact': user_data['Contact']}, expected_data) From 7c075703a18bfb1cb45643d561ffa30385f8113b Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 20 Sep 2019 15:51:21 +0530 Subject: [PATCH 14/42] fix: codacy --- .../doctype/contact/test_records.json | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/frappe/contacts/doctype/contact/test_records.json b/frappe/contacts/doctype/contact/test_records.json index eb540ce4db..11c5329e93 100644 --- a/frappe/contacts/doctype/contact/test_records.json +++ b/frappe/contacts/doctype/contact/test_records.json @@ -1,39 +1,39 @@ [ - { - "doctype": "Contact", - "salutation": "Mr", - "first_name": "_Test Contact For _Test Customer", - "is_primary_contact": 1, - "status": "Open", - "email_ids": [ - { - "email_id": "test_contact@example.com", - "is_primary": 1 - } - ], - "phone_nos": [ - { - "phone": "+91 0000000000", - "is_primary_phone": 1 - } - ] - }, - { - "doctype": "Contact", - "first_name": "_Test Contact For _Test Supplier", - "is_primary_contact": 1, - "status": "Open", - "email_ids": [ - { - "email_id": "test_contact@example.com", - "is_primary": 1 - } - ], - "phone_nos": [ - { - "phone": "+91 0000000000", - "is_primary_phone": 1 - } - ] - } + { + "doctype": "Contact", + "salutation": "Mr", + "first_name": "_Test Contact For _Test Customer", + "is_primary_contact": 1, + "status": "Open", + "email_ids": [ + { + "email_id": "test_contact@example.com", + "is_primary": 1 + } + ], + "phone_nos": [ + { + "phone": "+91 0000000000", + "is_primary_phone": 1 + } + ] + }, + { + "doctype": "Contact", + "first_name": "_Test Contact For _Test Supplier", + "is_primary_contact": 1, + "status": "Open", + "email_ids": [ + { + "email_id": "test_contact@example.com", + "is_primary": 1 + } + ], + "phone_nos": [ + { + "phone": "+91 0000000000", + "is_primary_phone": 1 + } + ] + } ] \ No newline at end of file From cefd87b81abe6edab895ce07b7c6dd05d66a3fa7 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 20 Sep 2019 16:29:31 +0530 Subject: [PATCH 15/42] fix: add primary email --- frappe/core/doctype/user/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 157b7fe26d..00620638bf 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -1048,7 +1048,7 @@ def create_contact(user, ignore_links=False, ignore_mandatory=False): }) if user.email: - contact.add_email(user.email) + contact.add_email(user.email, is_primary=True) if user.phone: contact.add_phone(user.phone) From a8b53deb7553cf84c91908bec235c42c52d06cc0 Mon Sep 17 00:00:00 2001 From: ci2014 Date: Sat, 21 Sep 2019 15:41:54 +0200 Subject: [PATCH 16/42] Fix loop error in utils.py Property Setters got deleted on bench migrate and haven't been readded, because data was passed instead of d. Now it works. --- frappe/modules/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/modules/utils.py b/frappe/modules/utils.py index b06297023e..528ca6e88b 100644 --- a/frappe/modules/utils.py +++ b/frappe/modules/utils.py @@ -119,7 +119,7 @@ def sync_customizations_for_doctype(data, folder): custom_doctype, doctype_fieldname), doc_type) for d in data[key]: - _insert(data) + _insert(d) else: for d in data[key]: From 770f56f4ce53c0d4d65be16950758bb9e5eb56c0 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sat, 21 Sep 2019 20:53:20 +0530 Subject: [PATCH 17/42] fix: set column width --- frappe/contacts/doctype/contact_email/contact_email.json | 3 ++- frappe/contacts/doctype/contact_phone/contact_phone.json | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/frappe/contacts/doctype/contact_email/contact_email.json b/frappe/contacts/doctype/contact_email/contact_email.json index cfcc39ca8b..00b680e416 100644 --- a/frappe/contacts/doctype/contact_email/contact_email.json +++ b/frappe/contacts/doctype/contact_email/contact_email.json @@ -16,6 +16,7 @@ "options": "Email" }, { + "columns": 2, "default": "0", "fieldname": "is_primary", "fieldtype": "Check", @@ -24,7 +25,7 @@ } ], "istable": 1, - "modified": "2019-08-02 13:14:22.193463", + "modified": "2019-09-21 20:51:02.031722", "modified_by": "Administrator", "module": "Contacts", "name": "Contact Email", diff --git a/frappe/contacts/doctype/contact_phone/contact_phone.json b/frappe/contacts/doctype/contact_phone/contact_phone.json index 248abfa9fe..c0f171d62a 100644 --- a/frappe/contacts/doctype/contact_phone/contact_phone.json +++ b/frappe/contacts/doctype/contact_phone/contact_phone.json @@ -16,6 +16,7 @@ "label": "Phone" }, { + "columns": 2, "default": "0", "fieldname": "is_primary_phone", "fieldtype": "Check", @@ -23,6 +24,7 @@ "label": "Is Primary Phone" }, { + "columns": 2, "default": "0", "fieldname": "is_primary_mobile_no", "fieldtype": "Check", @@ -31,8 +33,8 @@ } ], "istable": 1, - "modified": "2019-09-11 20:57:22.108260", - "modified_by": "himanshu@erpnext.com", + "modified": "2019-09-21 20:46:06.177615", + "modified_by": "Administrator", "module": "Contacts", "name": "Contact Phone", "owner": "Administrator", From 7fe35a2d3cd2b698374842503781fdaa354187d4 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Mon, 23 Sep 2019 15:54:46 +0530 Subject: [PATCH 18/42] fix: set default value in set_value as None to avoid error. ``` frappe.db.set_value('Call Log', log.name, { fieldname: doc.name, display_name_field: doc.get_title() }, update_modified=False) ``` this code should not fail if value is not pass because value is passed in the dict. --- frappe/database/database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/database/database.py b/frappe/database/database.py index 412051c76f..a1b8d390a9 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -607,7 +607,7 @@ class Database(object): """Update multiple values. Alias for `set_value`.""" return self.set_value(*args, **kwargs) - def set_value(self, dt, dn, field, val, modified=None, modified_by=None, + def set_value(self, dt, dn, field, val=None, modified=None, modified_by=None, update_modified=True, debug=False): """Set a single value in the database, do not call the ORM triggers but update the modified timestamp (unless specified not to). From eee41cac3137ee4defa4b02c692c082d3bc4a3e4 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 23 Sep 2019 16:17:08 +0530 Subject: [PATCH 19/42] test: Add test for point allocation based on assignment --- .../energy_point_log/test_energy_point_log.py | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/frappe/social/doctype/energy_point_log/test_energy_point_log.py b/frappe/social/doctype/energy_point_log/test_energy_point_log.py index c44b3b14df..8aef5a3801 100644 --- a/frappe/social/doctype/energy_point_log/test_energy_point_log.py +++ b/frappe/social/doctype/energy_point_log/test_energy_point_log.py @@ -7,6 +7,7 @@ import frappe import unittest from .energy_point_log import get_energy_points as _get_energy_points, create_review_points_log, review from frappe.utils.testutils import add_custom_field, clear_custom_fields +from frappe.desk.form.assign_to import add as assign_to class TestEnergyPointLog(unittest.TestCase): def tearDown(self): @@ -185,7 +186,31 @@ class TestEnergyPointLog(unittest.TestCase): self.assertEquals(points_after_todo_creation, points_before_todo_creation + todo_point_rule.points) -def create_energy_point_rule_for_todo(multiplier_field=None, for_doc_event='Custom', max_points=None): + def test_point_allocation_for_assigned_users(self): + todo = create_a_todo() + + assign_users_to_todo(todo.name, ['test@example.com', 'test2@example.com']) + + test_user_before_points = get_points('test@example.com') + test2_user_before_points = get_points('test2@example.com') + + rule = create_energy_point_rule_for_todo(for_assigned_users=1) + + todo.status = 'Closed' + todo.save() + + test_user_after_points = get_points('test@example.com') + test2_user_after_points = get_points('test2@example.com') + + self.assertEquals(test_user_after_points, + test_user_before_points + rule.points) + + self.assertEquals(test2_user_after_points, + test2_user_before_points + rule.points) + + +def create_energy_point_rule_for_todo(multiplier_field=None, for_doc_event='Custom', + max_points=None, for_assigned_users=0): name = 'ToDo Closed' point_rule = frappe.db.get_all( 'Energy Point Rule', @@ -204,6 +229,7 @@ def create_energy_point_rule_for_todo(multiplier_field=None, for_doc_event='Cust 'condition': 'doc.status == "Closed"', 'for_doc_event': for_doc_event, 'user_field': 'owner', + 'for_assigned_users': for_assigned_users, 'multiplier_field': multiplier_field, 'max_points': max_points }).insert(ignore_permissions=1) @@ -216,4 +242,12 @@ def create_a_todo(): def get_points(user, point_type='energy_points'): - return _get_energy_points(user).get(point_type) or 0 \ No newline at end of file + return _get_energy_points(user).get(point_type) or 0 + +def assign_users_to_todo(todo_name, users): + for user in users: + assign_to({ + 'assign_to': user, + 'doctype': 'ToDo', + 'name': todo_name + }) \ No newline at end of file From b07b87392d7b82347245a70fb2ef2fb3860a19f5 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 23 Sep 2019 16:18:22 +0530 Subject: [PATCH 20/42] fix: Add field description and remove mandatory constraint --- .../doctype/energy_point_rule/energy_point_rule.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/social/doctype/energy_point_rule/energy_point_rule.json b/frappe/social/doctype/energy_point_rule/energy_point_rule.json index fc7cdd280c..43714cd5be 100644 --- a/frappe/social/doctype/energy_point_rule/energy_point_rule.json +++ b/frappe/social/doctype/energy_point_rule/energy_point_rule.json @@ -61,8 +61,7 @@ "description": "The user from this field will be rewarded points", "fieldname": "user_field", "fieldtype": "Select", - "label": "User Field", - "reqd": 1 + "label": "User Field" }, { "fieldname": "multiplier_field", @@ -71,7 +70,7 @@ }, { "depends_on": "eval:doc.multiplier_field", - "description": "Maximum points allowed after multiplying points with the multiplier value\n(Note: For no limit set value as 0)", + "description": "Maximum points allowed after multiplying points with the multiplier value\n(Note: For no limit leave this field empty or set 0)", "fieldname": "max_points", "fieldtype": "Int", "label": "Maximum Points" @@ -90,12 +89,13 @@ { "default": "0", "depends_on": "eval:doc.for_doc_event !=='New'", + "description": "Users assigned to the reference document will get points.", "fieldname": "for_assigned_users", "fieldtype": "Check", "label": "Allot Points To Assigned Users" } ], - "modified": "2019-09-19 17:45:58.137148", + "modified": "2019-09-20 11:26:26.101557", "modified_by": "Administrator", "module": "Social", "name": "Energy Point Rule", From 0d6b8072dfdeb59e2557afff4b6d6a3ff3ebcf73 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 23 Sep 2019 16:36:35 +0530 Subject: [PATCH 21/42] fix: boilerplate creation --- frappe/modules/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/modules/utils.py b/frappe/modules/utils.py index b06297023e..44c986e80c 100644 --- a/frappe/modules/utils.py +++ b/frappe/modules/utils.py @@ -242,7 +242,7 @@ def make_boilerplate(template, doc, opts=None): base_class = 'Document' base_class_import = 'from frappe.model.document import Document' - if doc.is_tree: + if hasattr(doc, "is_tree"): base_class = 'NestedSet' base_class_import = 'from frappe.utils.nestedset import NestedSet' From 6682d5c07cc4a3a9c6d9ed65ea4b73fd1db0f9e3 Mon Sep 17 00:00:00 2001 From: Leandro Iannece Date: Mon, 23 Sep 2019 15:29:25 -0300 Subject: [PATCH 22/42] Fixed jinja templates and translation in login page --- frappe/www/login.html | 4 ++-- frappe/www/login.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/www/login.html b/frappe/www/login.html index 8c470ac6dd..48b30800b5 100644 --- a/frappe/www/login.html +++ b/frappe/www/login.html @@ -13,12 +13,12 @@