From 24e526528134a95f838928398ced25340653ef66 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 14 Dec 2017 13:06:21 +0530 Subject: [PATCH] [enhance] Search customer using primary contact mobile number (#11998) * [enhance] Search customer using primary contact mobile number * Update build.json --- erpnext/patches.txt | 3 +- .../v10_0/set_primary_contact_for_customer.py | 21 +++ erpnext/public/build.json | 5 +- .../public/js/utils/customer_quick_entry.js | 80 +++++++++ erpnext/selling/doctype/customer/customer.js | 9 + .../selling/doctype/customer/customer.json | 156 +++++++++++++++++- erpnext/selling/doctype/customer/customer.py | 59 +++++++ 7 files changed, 328 insertions(+), 5 deletions(-) create mode 100644 erpnext/patches/v10_0/set_primary_contact_for_customer.py create mode 100644 erpnext/public/js/utils/customer_quick_entry.js diff --git a/erpnext/patches.txt b/erpnext/patches.txt index d2e6adf983..530cc5c3c0 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -480,4 +480,5 @@ erpnext.patches.v9_2.delete_process_payroll erpnext.patches.v10_0.add_agriculture_domain erpnext.patches.v10_0.add_non_profit_domain erpnext.patches.v10_0.setup_vat_for_uae_and_saudi_arabia -erpnext.patches.v10_0.copy_projects_renamed_fields \ No newline at end of file +erpnext.patches.v10_0.set_primary_contact_for_customer +erpnext.patches.v10_0.copy_projects_renamed_fields diff --git a/erpnext/patches/v10_0/set_primary_contact_for_customer.py b/erpnext/patches/v10_0/set_primary_contact_for_customer.py new file mode 100644 index 0000000000..ae0b31c21f --- /dev/null +++ b/erpnext/patches/v10_0/set_primary_contact_for_customer.py @@ -0,0 +1,21 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doctype('Customer') + + frappe.db.sql(""" + update + `tabCustomer`, ( + select `tabContact`.name, `tabContact`.mobile_no, `tabContact`.email_id, + `tabDynamic Link`.link_name from `tabContact`, `tabDynamic Link` + where `tabContact`.name = `tabDynamic Link`.parent and + `tabDynamic Link`.link_doctype = 'Customer' and `tabContact`.is_primary_contact = 1 + ) as contact + set + `tabCustomer`.customer_primary_contact = contact.name, + `tabCustomer`.mobile_no = contact.mobile_no, `tabCustomer`.email_id = contact.email_id + where `tabCustomer`.name = contact.link_name""") \ No newline at end of file diff --git a/erpnext/public/build.json b/erpnext/public/build.json index 612bc60010..0dd3ed7c27 100644 --- a/erpnext/public/build.json +++ b/erpnext/public/build.json @@ -21,7 +21,7 @@ "public/js/pos/pos.html", "public/js/pos/pos_bill_item.html", "public/js/pos/pos_bill_item_new.html", - "public/js/pos/pos_selected_item.html", + "public/js/pos/pos_selected_item.html", "public/js/pos/pos_item.html", "public/js/pos/pos_tax_row.html", "public/js/pos/customer_toolbar.html", @@ -34,6 +34,7 @@ "public/js/agriculture/ternary_plot.js", "public/js/templates/item_quick_entry.html", "public/js/utils/item_quick_entry.js", + "public/js/utils/customer_quick_entry.js", "public/js/education/student_button.html", "public/js/education/assessment_result_tool.html" ], @@ -42,4 +43,4 @@ "stock/dashboard/item_dashboard_list.html", "stock/dashboard/item_dashboard.js" ] -} \ No newline at end of file +} diff --git a/erpnext/public/js/utils/customer_quick_entry.js b/erpnext/public/js/utils/customer_quick_entry.js new file mode 100644 index 0000000000..f454ba057b --- /dev/null +++ b/erpnext/public/js/utils/customer_quick_entry.js @@ -0,0 +1,80 @@ +frappe.provide('frappe.ui.form'); + +frappe.ui.form.CustomerQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({ + init: function(doctype, after_insert) { + this._super(doctype, after_insert); + }, + + render_dialog: function() { + this.mandatory = this.mandatory.concat(this.get_variant_fields()); + this._super(); + }, + + get_variant_fields: function() { + var variant_fields = [{ + fieldtype: "Section Break", + label: __("Primary Contact Details"), + collapsible: 1 + }, + { + label: __("Email Id"), + fieldname: "email_id", + fieldtype: "Data" + }, + { + fieldtype: "Column Break" + }, + { + label: __("Mobile Number"), + fieldname: "mobile_no", + fieldtype: "Data" + }, + { + fieldtype: "Section Break", + label: __("Primary Address Details"), + collapsible: 1 + }, + { + label: __("Address Line 1"), + fieldname: "address_line1", + fieldtype: "Data" + }, + { + label: __("Address Line 2"), + fieldname: "address_line2", + fieldtype: "Data" + }, + { + label: __("ZIP Code"), + fieldname: "pincode", + fieldtype: "Data" + }, + { + fieldtype: "Column Break" + }, + { + label: __("City"), + fieldname: "city", + fieldtype: "Data" + }, + { + label: __("State"), + fieldname: "state", + fieldtype: "Data" + }, + { + label: __("Country"), + fieldname: "country", + fieldtype: "Link", + options: "Country" + }, + { + label: __("Customer POS Id"), + fieldname: "customer_pos_id", + fieldtype: "Data", + hidden: 1 + }]; + + return variant_fields; + }, +}) \ No newline at end of file diff --git a/erpnext/selling/doctype/customer/customer.js b/erpnext/selling/doctype/customer/customer.js index d85f5c1e86..9603290998 100644 --- a/erpnext/selling/doctype/customer/customer.js +++ b/erpnext/selling/doctype/customer/customer.js @@ -24,6 +24,15 @@ frappe.ui.form.on("Customer", { filters: filters } }); + + frm.set_query('customer_primary_contact', function(doc) { + return { + query: "erpnext.selling.doctype.customer.customer.get_customer_primary_contact", + filters: { + 'customer': doc.name + } + } + }) }, refresh: function(frm) { if(frappe.defaults.get_default("cust_master_name")!="Naming Series") { diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index fd9d0a173f..b618bf3fbc 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -719,6 +719,158 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "primary_contact_detail", + "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": "Primary Contact Detail", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "customer_primary_contact", + "fieldtype": "Link", + "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": "Customer Primary Contact", + "length": 0, + "no_copy": 0, + "options": "Contact", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_26", + "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, + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "mobile_no", + "fieldtype": "Read Only", + "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": "Mobile Number", + "length": 0, + "no_copy": 0, + "options": "customer_primary_contact.mobile_no", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "email_id", + "fieldtype": "Read Only", + "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 Id", + "length": 0, + "no_copy": 0, + "options": "customer_primary_contact.email_id", + "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, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1202,7 +1354,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-11-23 17:41:23.243421", + "modified": "2017-12-13 18:17:19.894331", "modified_by": "Administrator", "module": "Selling", "name": "Customer", @@ -1393,7 +1545,7 @@ "quick_entry": 1, "read_only": 0, "read_only_onload": 0, - "search_fields": "customer_name,customer_group,territory", + "search_fields": "customer_name,customer_group,territory, mobile_no", "show_name_in_global_search": 1, "sort_order": "ASC", "title_field": "customer_name", diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 8e45921278..24d63e6fd8 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -56,6 +56,8 @@ class Customer(TransactionBase): def on_update(self): self.validate_name_with_customer_group() + self.create_primary_contact() + self.create_primary_address() if self.flags.old_lead != self.lead_name: self.update_lead_status() @@ -63,6 +65,18 @@ class Customer(TransactionBase): if self.flags.is_new_doc: self.create_lead_address_contact() + def create_primary_contact(self): + if not self.customer_primary_contact: + if self.mobile_no or self.email_id: + contact = make_contact(self) + self.db_set('customer_primary_contact', contact.name) + self.db_set('mobile_no', self.mobile_no) + self.db_set('email_id', self.email_id) + + def create_primary_address(self): + if self.flags.is_new_doc and self.get('address_line_1'): + make_address(self) + def update_lead_status(self): '''If Customer created from Lead, update lead status to "Converted" update Customer link in Quotation, Opportunity''' @@ -246,3 +260,48 @@ def get_credit_limit(customer, company): credit_limit = frappe.db.get_value("Company", company, "credit_limit") return flt(credit_limit) + +def make_contact(args, is_primary_contact=1): + contact = frappe.get_doc({ + 'doctype': 'Contact', + 'first_name': args.get('name'), + 'mobile_no': args.get('mobile_no'), + 'email_id': args.get('email_id'), + 'is_primary_contact': is_primary_contact, + 'links': [{ + 'link_doctype': args.get('doctype'), + 'link_name': args.get('name') + }] + }).insert() + + return contact + +def make_address(args, is_primary_address=1): + address = frappe.get_doc({ + 'doctype': 'Address', + 'address_title': args.get('name'), + 'address_line1': args.get('address_line1'), + 'address_line2': args.get('address_line2'), + 'city': args.get('city'), + 'state': args.get('state'), + 'pincode': args.get('pincode'), + 'country': args.get('country'), + 'links': [{ + 'link_doctype': args.get('doctype'), + 'link_name': args.get('name') + }] + }).insert() + + return address + +def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, filters): + customer = frappe.db.escape(filters.get('customer')) + return frappe.db.sql(""" + select `tabContact`.name from `tabContact`, `tabDynamic Link` + where `tabContact`.name = `tabDynamic Link`.parent and `tabDynamic Link`.link_name = %(customer)s + and `tabDynamic Link`.link_doctype = 'Customer' and `tabContact`.is_primary_contact = 1 + and `tabContact`.name like %(txt)s + """, { + 'customer': customer, + 'txt': '%%%s%%' % txt + })