Allowing the creation of an Oganization as Lead (#11724)

* Allow the creation of an organization lead

* Changes following test fails

* Test case correction
This commit is contained in:
Charles-Henri Decultot
2017-11-27 07:28:22 +01:00
committed by Rushabh Mehta
parent dcbc4284d3
commit 22641e44ad
8 changed files with 197 additions and 27 deletions

View File

@@ -11,6 +11,7 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
}, },
onload: function() { onload: function() {
if(cur_frm.fields_dict.lead_owner.df.options.match(/^User/)) { if(cur_frm.fields_dict.lead_owner.df.options.match(/^User/)) {
cur_frm.fields_dict.lead_owner.get_query = function(doc, cdt, cdn) { cur_frm.fields_dict.lead_owner.get_query = function(doc, cdt, cdn) {
return { query: "frappe.core.doctype.user.user.user_query" } return { query: "frappe.core.doctype.user.user.user_query" }
@@ -61,10 +62,21 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
method: "erpnext.crm.doctype.lead.lead.make_quotation", method: "erpnext.crm.doctype.lead.lead.make_quotation",
frm: cur_frm frm: cur_frm
}) })
},
organization_lead: function() {
if (this.frm.doc.organization_lead == 1) {
this.frm.set_df_property('company_name', 'reqd', 1);
} else {
this.frm.set_df_property('company_name', 'reqd', 0);
}
},
company_name: function() {
if (this.frm.doc.organization_lead == 1) {
this.frm.set_value("lead_name", this.frm.doc.company_name);
}
} }
}); });
$.extend(cur_frm.cscript, new erpnext.LeadController({frm: cur_frm})); $.extend(cur_frm.cscript, new erpnext.LeadController({frm: cur_frm}));

View File

@@ -12,6 +12,37 @@
"document_type": "Document", "document_type": "Document",
"editable_grid": 0, "editable_grid": 0,
"fields": [ "fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "organization_lead",
"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": "Lead is an Organization",
"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": 1,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@@ -80,6 +111,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:!doc.organization_lead",
"fieldname": "lead_name", "fieldname": "lead_name",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0, "hidden": 0,
@@ -673,6 +705,38 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:doc.organization_lead",
"fieldname": "contact_html",
"fieldtype": "HTML",
"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": "Contact HTML",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"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,
"depends_on": "eval:!doc.organization_lead",
"fieldname": "phone", "fieldname": "phone",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0, "hidden": 0,
@@ -704,6 +768,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:!doc.organization_lead",
"fieldname": "salutation", "fieldname": "salutation",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@@ -735,6 +800,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:!doc.organization_lead",
"fieldname": "mobile_no", "fieldname": "mobile_no",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0, "hidden": 0,
@@ -766,6 +832,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval:!doc.organization_lead",
"fieldname": "fax", "fieldname": "fax",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0, "hidden": 0,
@@ -1147,7 +1214,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-08-21 02:28:21.581948", "modified": "2017-11-24 11:10:56.485917",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "CRM", "module": "CRM",
"name": "Lead", "name": "Lead",

View File

@@ -23,6 +23,7 @@ class Lead(SellingController):
load_address_and_contact(self) load_address_and_contact(self)
def validate(self): def validate(self):
self.set_lead_name()
self._prev = frappe._dict({ self._prev = frappe._dict({
"contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if \ "contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if \
(not cint(self.get("__islocal"))) else None, (not cint(self.get("__islocal"))) else None,
@@ -98,6 +99,10 @@ class Lead(SellingController):
"status": "Lost" "status": "Lost"
}) })
def set_lead_name(self):
if not self.lead_name:
frappe.db.set_value("Lead", self.name, "lead_name", self.organization_name)
@frappe.whitelist() @frappe.whitelist()
def make_customer(source_name, target_doc=None): def make_customer(source_name, target_doc=None):
return _make_customer(source_name, target_doc) return _make_customer(source_name, target_doc)
@@ -124,6 +129,7 @@ def _make_customer(source_name, target_doc=None, ignore_permissions=False):
} }
}}, target_doc, set_missing_values, ignore_permissions=ignore_permissions) }}, target_doc, set_missing_values, ignore_permissions=ignore_permissions)
print(doclist)
return doclist return doclist
@frappe.whitelist() @frappe.whitelist()

View File

@@ -1,7 +1,7 @@
QUnit.module("sales"); QUnit.module("sales");
QUnit.test("test: lead", function (assert) { QUnit.test("test: lead", function (assert) {
assert.expect(4); assert.expect(10);
let done = assert.async(); let done = assert.async();
let lead_name = frappe.utils.get_random(10); let lead_name = frappe.utils.get_random(10);
frappe.run_serially([ frappe.run_serially([
@@ -40,4 +40,53 @@ QUnit.test("test: lead", function (assert) {
() => done() () => done()
]); ]);
frappe.run_serially([
// test lead creation
() => frappe.set_route("List", "Lead"),
() => frappe.new_doc("Lead"),
() => frappe.timeout(1),
() => cur_frm.set_value("organization_lead", "1"),
() => cur_frm.set_value("organization_name", lead_name),
() => cur_frm.save(),
() => frappe.timeout(1),
() => {
assert.ok(cur_frm.doc.lead_name.includes(lead_name),
'name correctly set');
frappe.lead_name = cur_frm.doc.name;
},
// create address and contact
() => frappe.click_link('Address & Contact'),
() => frappe.click_button('New Address'),
() => frappe.timeout(1),
() => frappe.set_control('address_line1', 'Gateway'),
() => frappe.set_control('city', 'Mumbai'),
() => cur_frm.save(),
() => frappe.timeout(3),
() => assert.equal(frappe.get_route()[1], 'Lead',
'back to lead form'),
() => frappe.click_link('Address & Contact'),
() => assert.ok($('.address-box').text().includes('Mumbai'),
'city is seen in address box'),
() => frappe.click_button('New Contact'),
() => frappe.timeout(1),
() => frappe.set_control('first_name', 'John'),
() => frappe.set_control('last_name', 'Doe'),
() => cur_frm.save(),
() => frappe.timeout(3),
() => assert.equal(frappe.get_route()[1], 'Lead',
'back to lead form'),
() => frappe.click_link('Address & Contact'),
() => assert.ok($('.address-box').text().includes('John'),
'contact is seen in contact box'),
// make customer
() => frappe.click_button('Make'),
() => frappe.click_link('customer'),
() => frappe.timeout(2),
() => assert.equal(cur_frm.doc.lead_name, frappe.lead_name,
'lead name correctly mapped'),
() => done()
]);
}); });

View File

@@ -21,3 +21,14 @@ class TestLead(unittest.TestCase):
customer.company = "_Test Company" customer.company = "_Test Company"
customer.customer_group = "_Test Customer Group" customer.customer_group = "_Test Customer Group"
customer.insert() customer.insert()
def test_make_customer_from_organization(self):
from erpnext.crm.doctype.lead.lead import make_customer
customer = make_customer("_T-Lead-00002")
self.assertEquals(customer.doctype, "Customer")
self.assertEquals(customer.lead_name, "_T-Lead-00002")
customer.company = "_Test Company"
customer.customer_group = "_Test Customer Group"
customer.insert()

View File

@@ -23,5 +23,13 @@
"email_id": "test_lead3@example.com", "email_id": "test_lead3@example.com",
"lead_name": "_Test Lead 3", "lead_name": "_Test Lead 3",
"status": "Converted" "status": "Converted"
},
{
"doctype": "Lead",
"email_id": "test_lead4@example.com",
"organization_lead": 1,
"lead_name": "_Test Lead 4",
"organization_name": "_Test Lead 4",
"status": "Open"
} }
] ]

View File

@@ -43,6 +43,9 @@ A Lead is a potential Customer, someone who can give you business. A Customer is
organization or individual who has given you business before (and has an Account organization or individual who has given you business before (and has an Account
in your system). A Contact is a person who belongs to the Customer. in your system). A Contact is a person who belongs to the Customer.
A Lead can sometimes be an organization you are trying to make a deal with. In this case you can select "Lead is an Organization" and add as many contacts within this organization as you want.
It is useful if you are establishing a relationship with several people within the same organization.
A Lead can be converted to a Customer by selecting “Customer” from the **Make** A Lead can be converted to a Customer by selecting “Customer” from the **Make**
dropdown. Once the Customer is created, the Lead becomes “Converted” and any dropdown. Once the Customer is created, the Lead becomes “Converted” and any
further Opportunities from the same source can be created against this further Opportunities from the same source can be created against this

View File

@@ -88,11 +88,25 @@ class Customer(TransactionBase):
address.append('links', dict(link_doctype='Customer', link_name=self.name)) address.append('links', dict(link_doctype='Customer', link_name=self.name))
address.save() address.save()
lead = frappe.db.get_value("Lead", self.lead_name, ["lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True) lead = frappe.db.get_value("Lead", self.lead_name, ["organization_lead", "lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True)
if not lead.lead_name: if not lead.lead_name:
frappe.throw(_("Please mention the Lead Name in Lead {0}").format(self.lead_name)) frappe.throw(_("Please mention the Lead Name in Lead {0}").format(self.lead_name))
if lead.organization_lead:
contact_names = frappe.get_all('Dynamic Link', filters={
"parenttype":"Contact",
"link_doctype":"Lead",
"link_name":self.lead_name
}, fields=["parent as name"])
for contact_name in contact_names:
contact = frappe.get_doc('Contact', contact_name.get('name'))
if not contact.has_link('Customer', self.name):
contact.append('links', dict(link_doctype='Customer', link_name=self.name))
contact.save()
else:
lead.lead_name = lead.lead_name.split(" ") lead.lead_name = lead.lead_name.split(" ")
lead.first_name = lead.lead_name[0] lead.first_name = lead.lead_name[0]
lead.last_name = " ".join(lead.lead_name[1:]) lead.last_name = " ".join(lead.lead_name[1:])