diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js index 0bf2ab96153..7f5f1a4cb4e 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -40,6 +40,9 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller this.frm.add_custom_button(__("Opportunity"), this.make_opportunity, __("Create")); this.frm.add_custom_button(__("Quotation"), this.make_quotation, __("Create")); this.frm.add_custom_button(__("Prospect"), this.make_prospect, __("Create")); + this.frm.add_custom_button(__('Add to Prospect'), function() { + cur_frm.trigger('add_lead_to_prospect') + }, __('Action')); } if (!this.frm.is_new()) { @@ -50,6 +53,34 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller } } + add_lead_to_prospect () { + frappe.prompt([ + { + fieldname: 'prospect', + label: __('Prospect'), + fieldtype: 'Link', + options: 'Prospect', + reqd: 1 + } + ], + function(data) { + frappe.call({ + method: 'erpnext.crm.doctype.lead.lead.add_lead_to_prospect', + args: { + 'lead': cur_frm.doc.name, + 'prospect': data.prospect + }, + callback: function(r) { + if (!r.exc) { + cur_frm.reload_doc(); + } + }, + freeze: true, + freeze_message: __('...Adding Lead to Prospect') + }) + }, __('Add Lead to Prospect'), __('Add')); + } + make_customer () { frappe.model.open_mapped_doc({ method: "erpnext.crm.doctype.lead.lead.make_customer", @@ -72,10 +103,22 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller } make_prospect () { - frappe.model.open_mapped_doc({ - method: "erpnext.crm.doctype.lead.lead.make_prospect", - frm: cur_frm - }) + frappe.model.with_doctype("Prospect", function() { + let prospect = frappe.model.get_new_doc("Prospect"); + prospect.company_name = cur_frm.doc.company_name; + prospect.no_of_employees = cur_frm.doc.no_of_employees; + prospect.industry = cur_frm.doc.industry; + prospect.market_segment = cur_frm.doc.market_segment; + prospect.territory = cur_frm.doc.territory; + prospect.fax = cur_frm.doc.fax; + prospect.website = cur_frm.doc.website; + prospect.prospect_owner = cur_frm.doc.lead_owner; + + let lead_prospect_row = frappe.model.add_child(prospect, 'prospect_lead'); + lead_prospect_row.lead = cur_frm.doc.name; + + frappe.set_route("Form", "Prospect", prospect.name); + }); } company_name () { diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index 693fc6a1600..c6115ee4389 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -62,6 +62,7 @@ class Lead(SellingController): def on_update(self): self.add_calendar_event() + self.update_prospects() def before_insert(self): self.contact_doc = self.create_contact() @@ -88,6 +89,12 @@ class Lead(SellingController): "description": ('Contact ' + cstr(self.lead_name)) + (self.contact_by and ('. By : ' + cstr(self.contact_by)) or '') }, force) + def update_prospects(self): + prospects = frappe.get_all('Prospect Lead', filters={'lead': self.name}, fields=['parent']) + for row in prospects: + prospect = frappe.get_doc('Prospect', row.parent) + prospect.save(ignore_permissions=True) + def check_email_id_is_unique(self): if self.email_id: # validate email is unique @@ -262,15 +269,6 @@ def make_quotation(source_name, target_doc=None): return target_doc -@frappe.whitelist() -def make_prospect(source_name, target_doc=None): - target_doc = get_mapped_doc("Lead", source_name, - {"Lead": { - "doctype": "Prospect", - }}, target_doc) - - return target_doc - def _set_missing_values(source, target): address = frappe.get_all('Dynamic Link', { 'link_doctype': source.doctype, @@ -363,12 +361,13 @@ def daily_open_lead(): for lead in leads: frappe.db.set_value("Lead", lead.name, "status", "Open") -def add_prospect_link_in_communication(communication, method): - if communication.get('reference_doctype') == "Lead": - links = frappe.get_all('Prospect Lead', filters={'lead': communication.get('reference_name')}, fields=['parent', 'parenttype']) - - for link in links: - communication.append('timeline_links', { - 'link_doctype': link['parenttype'], - 'link_name': link['parent'] - }) +@frappe.whitelist() +def add_lead_to_prospect(lead, prospect): + prospect = frappe.get_doc('Prospect', prospect) + prospect.append('prospect_lead', { + 'lead': lead + }) + prospect.save(ignore_permissions=True) + frappe.msgprint(_('Lead {0} has been added to prospect {1}.').format(frappe.bold(lead), frappe.bold(prospect.name)), + title=_('Lead Added'), indicator='green') + \ No newline at end of file diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js index bcfae11a05f..80588ee0029 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.js +++ b/erpnext/crm/doctype/opportunity/opportunity.js @@ -12,6 +12,14 @@ frappe.ui.form.on("Opportunity", { 'Supplier Quotation': 'Supplier Quotation' }; + frm.set_query("opportunity_from", function() { + return{ + "filters": { + "name": ["in", ["Customer", "Lead", "Prospect"]], + } + } + }); + if (frm.doc.opportunity_from && frm.doc.party_name){ frm.trigger('set_contact_link'); } @@ -87,10 +95,18 @@ frappe.ui.form.on("Opportunity", { }, __('Create')); } - frm.add_custom_button(__('Quotation'), - cur_frm.cscript.create_quotation, __('Create')); + if (frm.doc.opportunity_from != "Customer") { + frm.add_custom_button(__('Customer'), + function() { + frm.trigger("make_customer") + }, __('Create')); + } - } + frm.add_custom_button(__('Quotation'), + function() { + frm.trigger("create_quotation") + }, __('Create')); + } if(!frm.doc.__islocal && frm.perm[0].write && frm.doc.docstatus==0) { if(frm.doc.status==="Open") { @@ -187,6 +203,13 @@ erpnext.crm.Opportunity = class Opportunity extends frappe.ui.form.Controller { frm: cur_frm }) } + + make_customer() { + frappe.model.open_mapped_doc({ + method: "erpnext.crm.doctype.opportunity.opportunity.make_customer", + frm: cur_frm + }) + } }; extend_cscript(cur_frm.cscript, new erpnext.crm.Opportunity({frm: cur_frm})); diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json index e4b0e473096..12a564a9cb3 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.json +++ b/erpnext/crm/doctype/opportunity/opportunity.json @@ -78,13 +78,13 @@ }, { "fieldname": "opportunity_from", - "fieldtype": "Select", + "fieldtype": "Link", "in_list_view": 1, "in_standard_filter": 1, "label": "Opportunity From", "oldfieldname": "enquiry_from", "oldfieldtype": "Select", - "options": "\nLead\nProspect\nCustomer", + "options": "DocType", "print_hide": 1, "reqd": 1 }, @@ -430,7 +430,7 @@ "icon": "fa fa-info-sign", "idx": 195, "links": [], - "modified": "2021-08-23 14:43:09.484227", + "modified": "2021-08-25 10:28:24.923543", "modified_by": "Administrator", "module": "CRM", "name": "Opportunity", diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 23ad98a2828..9e620312b9f 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -265,6 +265,26 @@ def make_quotation(source_name, target_doc=None): return doclist +@frappe.whitelist() +def make_customer(source_name, target_doc=None): + def set_missing_values(source, target): + if source.opportunity_from == "Lead": + target.lead_name = source.party_name + if source.opportunity_from == "Prospect": + target.prospect = source.party_name + + doclist = get_mapped_doc("Opportunity", source_name, { + "Opportunity": { + "doctype": "Customer", + "field_map": { + "currency": "default_currency", + "customer_name": "customer_name" + } + } + }, target_doc, set_missing_values) + + return doclist + @frappe.whitelist() def make_request_for_quotation(source_name, target_doc=None): def update_item(obj, target, source_parent): diff --git a/erpnext/crm/doctype/prospect/prospect.js b/erpnext/crm/doctype/prospect/prospect.js index 793afccf3dc..64256cf31f3 100644 --- a/erpnext/crm/doctype/prospect/prospect.js +++ b/erpnext/crm/doctype/prospect/prospect.js @@ -19,21 +19,12 @@ frappe.ui.form.on('Prospect', { }) }, __("Create")); } - }, - make_customer () { - console.log("Make Customer"); - frappe.model.open_mapped_doc({ - method: "erpnext.crm.doctype.prospect.prospect.make_customer", - frm: cur_frm - }) - }, - - make_opportunity () { - console.log("Make Opportunity"); - // frappe.model.open_mapped_doc({ - // method: "erpnext.crm.doctype.lead.lead.make_opportunity", - // frm: cur_frm - // }) + if (!cur_frm.is_new()) { + frappe.contacts.render_address_and_contact(cur_frm); + cur_frm.trigger('render_contact_day_html'); + } else { + frappe.contacts.clear_address_and_contact(cur_frm); + } } }); diff --git a/erpnext/crm/doctype/prospect/prospect.py b/erpnext/crm/doctype/prospect/prospect.py index bd278dca35c..dc165af8253 100644 --- a/erpnext/crm/doctype/prospect/prospect.py +++ b/erpnext/crm/doctype/prospect/prospect.py @@ -6,12 +6,23 @@ from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc class Prospect(Document): - def after_save(self): + def validate(self): + self.update_lead_details() + + def on_update(self): self.link_with_lead_contact_and_address() def on_trash(self): self.unlink_dynamic_links() + def update_lead_details(self): + for row in self.get('prospect_lead'): + lead = frappe.get_value('Lead', row.lead, ['lead_name', 'status', 'email_id', 'mobile_no'], as_dict=True) + row.lead_name = lead.lead_name + row.status = lead.status + row.email = lead.email_id + row.mobile_no = lead.mobile_no + def link_with_lead_contact_and_address(self): for row in self.prospect_lead: links = frappe.get_all('Dynamic Link', filters={'link_doctype': 'Lead', 'link_name': row.lead}, fields=['parent', 'parenttype']) diff --git a/erpnext/crm/doctype/prospect_lead/prospect_lead.json b/erpnext/crm/doctype/prospect_lead/prospect_lead.json index 1797712a55a..3c160d9e802 100644 --- a/erpnext/crm/doctype/prospect_lead/prospect_lead.json +++ b/erpnext/crm/doctype/prospect_lead/prospect_lead.json @@ -21,45 +21,41 @@ "reqd": 1 }, { - "fetch_from": "lead.lead_name", - "fetch_if_empty": 1, "fieldname": "lead_name", "fieldtype": "Data", "in_list_view": 1, - "label": "Lead Name" + "label": "Lead Name", + "read_only": 1 }, { - "fetch_from": "lead.status", - "fetch_if_empty": 1, "fieldname": "status", "fieldtype": "Select", "in_list_view": 1, "label": "Status", - "options": "Lead\nOpen\nReplied\nOpportunity\nQuotation\nLost Quotation\nInterested\nConverted\nDo Not Contact" + "options": "Lead\nOpen\nReplied\nOpportunity\nQuotation\nLost Quotation\nInterested\nConverted\nDo Not Contact", + "read_only": 1 }, { - "fetch_from": "lead.email_id", - "fetch_if_empty": 1, "fieldname": "email", "fieldtype": "Data", "in_list_view": 1, "label": "Email", - "options": "Email" + "options": "Email", + "read_only": 1 }, { - "fetch_from": "lead.mobile_no", - "fetch_if_empty": 1, "fieldname": "mobile_no", "fieldtype": "Data", "in_list_view": 1, "label": "Mobile No", - "options": "Phone" + "options": "Phone", + "read_only": 1 } ], "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-08-20 01:58:39.387874", + "modified": "2021-08-25 12:58:24.638054", "modified_by": "Administrator", "module": "CRM", "name": "Prospect Lead", diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 8069a1566f5..8f7c7db208e 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -249,9 +249,6 @@ doc_events = { "on_update": [ "erpnext.support.doctype.service_level_agreement.service_level_agreement.update_hold_time", "erpnext.support.doctype.issue.issue.set_first_response_time" - ], - "after_insert": [ - "erpnext.crm.doctype.lead.lead.add_prospect_link_in_communication" ] }, ("Sales Taxes and Charges Template", 'Price List'): {