fix: merge conflicts and sider issues
diff --git a/erpnext/crm/doctype/crm_note/__init__.py b/erpnext/crm/doctype/crm_note/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/crm/doctype/crm_note/__init__.py
diff --git a/erpnext/crm/doctype/crm_note/crm_note.json b/erpnext/crm/doctype/crm_note/crm_note.json
new file mode 100644
index 0000000..fc2a4d1
--- /dev/null
+++ b/erpnext/crm/doctype/crm_note/crm_note.json
@@ -0,0 +1,48 @@
+{
+ "actions": [],
+ "autoname": "autoincrement",
+ "creation": "2022-06-04 15:49:23.416644",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "note",
+  "added_by",
+  "added_on"
+ ],
+ "fields": [
+  {
+   "columns": 5,
+   "fieldname": "note",
+   "fieldtype": "Text Editor",
+   "in_list_view": 1,
+   "label": "Note"
+  },
+  {
+   "fieldname": "added_by",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Added By",
+   "options": "User"
+  },
+  {
+   "fieldname": "added_on",
+   "fieldtype": "Datetime",
+   "in_list_view": 1,
+   "label": "Added On"
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2022-06-04 16:29:07.807252",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "CRM Note",
+ "naming_rule": "Autoincrement",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": []
+}
\ No newline at end of file
diff --git a/erpnext/crm/doctype/crm_note/crm_note.py b/erpnext/crm/doctype/crm_note/crm_note.py
new file mode 100644
index 0000000..6c7eeb4
--- /dev/null
+++ b/erpnext/crm/doctype/crm_note/crm_note.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+
+class CRMNote(Document):
+	pass
diff --git a/erpnext/crm/doctype/crm_settings/crm_settings.json b/erpnext/crm/doctype/crm_settings/crm_settings.json
index a2a19b9..26a07d2 100644
--- a/erpnext/crm/doctype/crm_settings/crm_settings.json
+++ b/erpnext/crm/doctype/crm_settings/crm_settings.json
@@ -10,12 +10,10 @@
   "campaign_naming_by",
   "allow_lead_duplication_based_on_emails",
   "column_break_4",
-  "create_event_on_next_contact_date",
   "auto_creation_of_contact",
   "opportunity_section",
   "close_opportunity_after_days",
   "column_break_9",
-  "create_event_on_next_contact_date_opportunity",
   "quotation_section",
   "default_valid_till",
   "section_break_13",
@@ -56,12 +54,6 @@
    "label": "Auto Creation of Contact"
   },
   {
-   "default": "1",
-   "fieldname": "create_event_on_next_contact_date",
-   "fieldtype": "Check",
-   "label": "Create Event on Next Contact Date"
-  },
-  {
    "fieldname": "opportunity_section",
    "fieldtype": "Section Break",
    "label": "Opportunity"
@@ -74,12 +66,6 @@
    "label": "Close Replied Opportunity After Days"
   },
   {
-   "default": "1",
-   "fieldname": "create_event_on_next_contact_date_opportunity",
-   "fieldtype": "Check",
-   "label": "Create Event on Next Contact Date"
-  },
-  {
    "fieldname": "column_break_4",
    "fieldtype": "Column Break"
   },
@@ -105,7 +91,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2021-12-20 12:51:38.894252",
+ "modified": "2022-06-06 11:22:08.464253",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "CRM Settings",
@@ -143,5 +129,6 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js
index 999599c..4814311 100644
--- a/erpnext/crm/doctype/lead/lead.js
+++ b/erpnext/crm/doctype/lead/lead.js
@@ -24,31 +24,39 @@
 		this.frm.set_query("lead_owner", function (doc, cdt, cdn) {
 			return { query: "frappe.core.doctype.user.user.user_query" }
 		});
-
-		this.frm.set_query("contact_by", function (doc, cdt, cdn) {
-			return { query: "frappe.core.doctype.user.user.user_query" }
-		});
 	}
 
 	refresh () {
+		var me = this;
 		let doc = this.frm.doc;
 		erpnext.toggle_naming_series();
-		frappe.dynamic_link = { doc: doc, fieldname: 'name', doctype: 'Lead' }
+		frappe.dynamic_link = {
+			doc: doc,
+			fieldname: 'name',
+			doctype: 'Lead'
+		};
 
 		if (!this.frm.is_new() && doc.__onload && !doc.__onload.is_customer) {
 			this.frm.add_custom_button(__("Customer"), this.make_customer, __("Create"));
-			this.frm.add_custom_button(__("Opportunity"), this.make_opportunity, __("Create"));
+			this.frm.add_custom_button(__("Opportunity"), function() {
+				me.frm.trigger("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'), this.add_lead_to_prospect, __('Action'));
+			if (!doc.__onload.linked_prospects.length) {
+				this.frm.add_custom_button(__("Prospect"), this.make_prospect, __("Create"));
+				this.frm.add_custom_button(__('Add to Prospect'), this.add_lead_to_prospect, __('Action'));
+			}
 		}
 
 		if (!this.frm.is_new()) {
 			frappe.contacts.render_address_and_contact(this.frm);
-			cur_frm.trigger('render_contact_day_html');
 		} else {
 			frappe.contacts.clear_address_and_contact(this.frm);
 		}
+
+		this.frm.dashboard.links_area.hide();
+		this.show_notes();
+		this.show_activities();
 	}
 
 	add_lead_to_prospect () {
@@ -74,7 +82,7 @@
 					}
 				},
 				freeze: true,
-				freeze_message: __('...Adding Lead to Prospect')
+				freeze_message: __('Adding Lead to Prospect...')
 			});
 		}, __('Add Lead to Prospect'), __('Add'));
 	}
@@ -86,13 +94,6 @@
 		})
 	}
 
-	make_opportunity () {
-		frappe.model.open_mapped_doc({
-			method: "erpnext.crm.doctype.lead.lead.make_opportunity",
-			frm: cur_frm
-		})
-	}
-
 	make_quotation () {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.crm.doctype.lead.lead.make_quotation",
@@ -111,9 +112,10 @@
 			prospect.fax = cur_frm.doc.fax;
 			prospect.website = cur_frm.doc.website;
 			prospect.prospect_owner = cur_frm.doc.lead_owner;
+			prospect.notes = cur_frm.doc.notes;
 
-			let lead_prospect_row = frappe.model.add_child(prospect, 'prospect_lead');
-			lead_prospect_row.lead = cur_frm.doc.name;
+			let leads_row = frappe.model.add_child(prospect, 'leads');
+			leads_row.lead = cur_frm.doc.name;
 
 			frappe.set_route("Form", "Prospect", prospect.name);
 		});
@@ -125,26 +127,109 @@
 		}
 	}
 
-	contact_date () {
-		if (this.frm.doc.contact_date) {
-			let d = moment(this.frm.doc.contact_date);
-			d.add(1, "day");
-			this.frm.set_value("ends_on", d.format(frappe.defaultDatetimeFormat));
-		}
+	show_notes() {
+		if (this.frm.doc.docstatus == 1) return;
+
+		const crm_notes = new erpnext.utils.CRMNotes({
+			frm: this.frm,
+			notes_wrapper: $(this.frm.fields_dict.notes_html.wrapper),
+		});
+		crm_notes.refresh();
 	}
 
-	render_contact_day_html() {
-		if (cur_frm.doc.contact_date) {
-			let contact_date = frappe.datetime.obj_to_str(cur_frm.doc.contact_date);
-			let diff_days = frappe.datetime.get_day_diff(contact_date, frappe.datetime.get_today());
-			let color = diff_days > 0 ? "orange" : "green";
-			let message = diff_days > 0 ? __("Next Contact Date") : __("Last Contact Date");
-			let html = `<div class="col-xs-12">
-						<span class="indicator whitespace-nowrap ${color}"><span> ${message} : ${frappe.datetime.global_date_format(contact_date)}</span></span>
-					</div>` ;
-			cur_frm.dashboard.set_headline_alert(html);
-		}
+	show_activities() {
+		if (this.frm.doc.docstatus == 1) return;
+
+		const crm_activities = new erpnext.utils.CRMActivities({
+			frm: this.frm,
+			open_activities_wrapper: $(this.frm.fields_dict.open_activities_html.wrapper),
+			all_activities_wrapper: $(this.frm.fields_dict.all_activities_html.wrapper),
+			form_wrapper: $(this.frm.wrapper),
+		});
+		crm_activities.refresh();
 	}
 };
 
+
 extend_cscript(cur_frm.cscript, new erpnext.LeadController({ frm: cur_frm }));
+
+frappe.ui.form.on("Lead", {
+	make_opportunity: async function(frm) {
+		let existing_prospect = (await frappe.db.get_value("Prospect Lead",
+			{
+				"lead": frm.doc.name
+			},
+			"name", null, "Prospect"
+		)).message.name;
+
+		if (!existing_prospect) {
+			var fields = [
+				{
+					"label": "Create Prospect",
+					"fieldname": "create_prospect",
+					"fieldtype": "Check",
+					"default": 1
+				},
+				{
+					"label": "Prospect Name",
+					"fieldname": "prospect_name",
+					"fieldtype": "Data",
+					"default": frm.doc.company_name,
+					"depends_on": "create_prospect"
+				}
+			];
+		}
+		let existing_contact = (await frappe.db.get_value("Contact",
+			{
+				"first_name": frm.doc.first_name || frm.doc.lead_name,
+				"last_name": frm.doc.last_name
+			},
+			"name"
+		)).message.name;
+
+		if (!existing_contact) {
+			fields.push(
+				{
+					"label": "Create Contact",
+					"fieldname": "create_contact",
+					"fieldtype": "Check",
+					"default": "1"
+				}
+			);
+		}
+
+		if (fields) {
+			var d = new frappe.ui.Dialog({
+				title: __('Create Opportunity'),
+				fields: fields,
+				primary_action: function() {
+					var data = d.get_values();
+					frappe.call({
+						method: 'create_prospect_and_contact',
+						doc: frm.doc,
+						args: {
+							data: data,
+						},
+						freeze: true,
+						callback: function(r) {
+							if (!r.exc) {
+								frappe.model.open_mapped_doc({
+									method: "erpnext.crm.doctype.lead.lead.make_opportunity",
+									frm: frm
+								});
+							}
+							d.hide();
+						}
+					});
+				},
+				primary_action_label: __('Create')
+			});
+			d.show();
+		} else {
+			frappe.model.open_mapped_doc({
+				method: "erpnext.crm.doctype.lead.lead.make_opportunity",
+				frm: frm
+			});
+		}
+	}
+})
\ No newline at end of file
diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json
index 542977e..df6ff56 100644
--- a/erpnext/crm/doctype/lead/lead.json
+++ b/erpnext/crm/doctype/lead/lead.json
@@ -3,79 +3,77 @@
  "allow_events_in_timeline": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
- "creation": "2013-04-10 11:45:37",
+ "creation": "2022-02-08 13:14:41.083327",
  "doctype": "DocType",
  "document_type": "Document",
  "email_append_to": 1,
  "engine": "InnoDB",
  "field_order": [
-  "lead_details",
   "naming_series",
   "salutation",
   "first_name",
   "middle_name",
   "last_name",
+  "column_break_1",
   "lead_name",
-  "col_break123",
-  "status",
-  "company_name",
-  "designation",
+  "job_title",
   "gender",
-  "contact_details_section",
+  "source",
+  "col_break123",
+  "lead_owner",
+  "status",
+  "customer",
+  "type",
+  "request_type",
+  "contact_info_tab",
   "email_id",
+  "website",
+  "column_break_20",
   "mobile_no",
   "whatsapp_no",
   "column_break_16",
   "phone",
   "phone_ext",
-  "additional_information_section",
+  "organization_section",
+  "company_name",
   "no_of_employees",
+  "column_break_28",
+  "annual_revenue",
   "industry",
   "market_segment",
-  "column_break_22",
+  "column_break_31",
+  "territory",
   "fax",
-  "website",
-  "type",
-  "request_type",
   "address_section",
   "address_html",
-  "city",
-  "pincode",
-  "county",
   "column_break2",
   "contact_html",
-  "state",
-  "country",
-  "section_break_12",
-  "lead_owner",
-  "ends_on",
-  "column_break_14",
-  "contact_by",
-  "contact_date",
-  "lead_source_details_section",
-  "company",
-  "territory",
-  "language",
-  "column_break_50",
-  "source",
+  "qualification_tab",
+  "qualification_status",
+  "column_break_64",
+  "qualified_by",
+  "qualified_on",
+  "other_info_tab",
   "campaign_name",
+  "company",
+  "column_break_22",
+  "language",
+  "image",
+  "title",
+  "column_break_50",
+  "disabled",
   "unsubscribed",
   "blog_subscriber",
-  "notes_section",
-  "notes",
-  "other_information_section",
-  "customer",
-  "image",
-  "title"
+  "activities_tab",
+  "open_activities_html",
+  "all_activities_section",
+  "all_activities_html",
+  "notes_tab",
+  "notes_html",
+  "notes"
  ],
  "fields": [
   {
-   "fieldname": "lead_details",
-   "fieldtype": "Section Break",
-   "label": "Lead Details",
-   "options": "fa fa-user"
-  },
-  {
    "fieldname": "naming_series",
    "fieldtype": "Select",
    "label": "Series",
@@ -86,6 +84,7 @@
    "set_only_once": 1
   },
   {
+   "depends_on": "eval:!doc.__islocal",
    "fieldname": "lead_name",
    "fieldtype": "Data",
    "in_global_search": 1,
@@ -108,7 +107,7 @@
   {
    "fieldname": "email_id",
    "fieldtype": "Data",
-   "label": "Email Address",
+   "label": "Email",
    "oldfieldname": "email_id",
    "oldfieldtype": "Data",
    "options": "Email",
@@ -189,50 +188,9 @@
    "print_hide": 1
   },
   {
-   "fieldname": "section_break_12",
+   "fieldname": "contact_info_tab",
    "fieldtype": "Section Break",
-   "label": "Follow Up"
-  },
-  {
-   "fieldname": "contact_by",
-   "fieldtype": "Link",
-   "label": "Next Contact By",
-   "oldfieldname": "contact_by",
-   "oldfieldtype": "Link",
-   "options": "User",
-   "width": "100px"
-  },
-  {
-   "fieldname": "column_break_14",
-   "fieldtype": "Column Break"
-  },
-  {
-   "bold": 1,
-   "fieldname": "contact_date",
-   "fieldtype": "Datetime",
-   "label": "Next Contact Date",
-   "no_copy": 1,
-   "oldfieldname": "contact_date",
-   "oldfieldtype": "Date",
-   "width": "100px"
-  },
-  {
-   "bold": 1,
-   "fieldname": "ends_on",
-   "fieldtype": "Datetime",
-   "label": "Ends On",
-   "no_copy": 1
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "notes_section",
-   "fieldtype": "Section Break",
-   "label": "Notes"
-  },
-  {
-   "fieldname": "notes",
-   "fieldtype": "Text Editor",
-   "label": "Notes"
+   "label": "Contact Info"
   },
   {
    "fieldname": "address_html",
@@ -241,34 +199,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "city",
-   "fieldtype": "Data",
-   "label": "City/Town",
-   "mandatory_depends_on": "eval: doc.address_title && doc.address_type"
-  },
-  {
-   "fieldname": "county",
-   "fieldtype": "Data",
-   "label": "County"
-  },
-  {
-   "fieldname": "state",
-   "fieldtype": "Data",
-   "label": "State"
-  },
-  {
-   "fieldname": "country",
-   "fieldtype": "Link",
-   "label": "Country",
-   "mandatory_depends_on": "eval: doc.address_title && doc.address_type",
-   "options": "Country"
-  },
-  {
-   "fieldname": "pincode",
-   "fieldtype": "Data",
-   "label": "Postal Code"
-  },
-  {
    "fieldname": "column_break2",
    "fieldtype": "Column Break"
   },
@@ -289,7 +219,7 @@
   {
    "fieldname": "mobile_no",
    "fieldtype": "Data",
-   "label": "Mobile No.",
+   "label": "Mobile No",
    "oldfieldname": "mobile_no",
    "oldfieldtype": "Data",
    "options": "Phone"
@@ -381,14 +311,6 @@
    "print_hide": 1
   },
   {
-   "fieldname": "designation",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "in_standard_filter": 1,
-   "label": "Designation",
-   "options": "Designation"
-  },
-  {
    "fieldname": "language",
    "fieldtype": "Link",
    "label": "Print Language",
@@ -411,12 +333,6 @@
    "label": "Last Name"
   },
   {
-   "collapsible": 1,
-   "fieldname": "additional_information_section",
-   "fieldtype": "Section Break",
-   "label": "Additional Information"
-  },
-  {
    "fieldname": "no_of_employees",
    "fieldtype": "Int",
    "label": "No. of Employees"
@@ -428,36 +344,14 @@
   {
    "fieldname": "whatsapp_no",
    "fieldtype": "Data",
-   "label": "WhatsApp No.",
+   "label": "WhatsApp",
    "options": "Phone"
   },
   {
-   "collapsible": 1,
-   "depends_on": "eval: !doc.__islocal",
-   "fieldname": "address_section",
-   "fieldtype": "Section Break",
-   "label": "Address"
-  },
-  {
-   "fieldname": "lead_source_details_section",
-   "fieldtype": "Section Break",
-   "label": "Lead Source Details"
-  },
-  {
    "fieldname": "column_break_50",
    "fieldtype": "Column Break"
   },
   {
-   "fieldname": "other_information_section",
-   "fieldtype": "Section Break",
-   "label": "Other Information"
-  },
-  {
-   "fieldname": "contact_details_section",
-   "fieldtype": "Section Break",
-   "label": "Contact Details"
-  },
-  {
    "fieldname": "column_break_16",
    "fieldtype": "Column Break"
   },
@@ -465,17 +359,136 @@
    "fieldname": "phone_ext",
    "fieldtype": "Data",
    "label": "Phone Ext."
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "qualification_tab",
+   "fieldtype": "Section Break",
+   "label": "Qualification"
+  },
+  {
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "notes_tab",
+   "fieldtype": "Tab Break",
+   "label": "Notes"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "other_info_tab",
+   "fieldtype": "Section Break",
+   "label": "Additional Information"
+  },
+  {
+   "fieldname": "column_break_1",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "qualified_by",
+   "fieldtype": "Link",
+   "label": "Qualified By",
+   "options": "User"
+  },
+  {
+   "fieldname": "qualified_on",
+   "fieldtype": "Date",
+   "label": "Qualified on"
+  },
+  {
+   "fieldname": "qualification_status",
+   "fieldtype": "Select",
+   "label": "Qualification Status",
+   "options": "Unqualified\nIn Process\nQualified"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "address_section",
+   "fieldtype": "Section Break",
+   "label": "Address & Contacts"
+  },
+  {
+   "fieldname": "column_break_64",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_20",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "job_title",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Job Title"
+  },
+  {
+   "fieldname": "annual_revenue",
+   "fieldtype": "Currency",
+   "label": "Annual Revenue"
+  },
+  {
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "activities_tab",
+   "fieldtype": "Tab Break",
+   "label": "Activities"
+  },
+  {
+   "fieldname": "organization_section",
+   "fieldtype": "Section Break",
+   "label": "Organization"
+  },
+  {
+   "fieldname": "column_break_28",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_31",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "notes_html",
+   "fieldtype": "HTML",
+   "label": "Notes HTML"
+  },
+  {
+   "fieldname": "open_activities_html",
+   "fieldtype": "HTML",
+   "label": "Open Activities HTML"
+  },
+  {
+   "fieldname": "all_activities_section",
+   "fieldtype": "Section Break",
+   "label": "All Activities"
+  },
+  {
+   "fieldname": "all_activities_html",
+   "fieldtype": "HTML",
+   "label": "All Activities HTML"
+  },
+  {
+   "fieldname": "notes",
+   "fieldtype": "Table",
+   "hidden": 1,
+   "label": "Notes",
+   "no_copy": 1,
+   "options": "CRM Note"
+  },
+  {
+   "default": "0",
+   "fieldname": "disabled",
+   "fieldtype": "Check",
+   "label": "Disabled"
   }
  ],
  "icon": "fa fa-user",
  "idx": 5,
  "image_field": "image",
  "links": [],
- "modified": "2021-08-04 00:24:57.208590",
+ "modified": "2022-06-06 18:10:14.494424",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Lead",
  "name_case": "Title Case",
+ "naming_rule": "By \"Naming Series\" field",
  "owner": "Administrator",
  "permissions": [
   {
@@ -535,6 +548,7 @@
  "show_name_in_global_search": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "subject_field": "title",
  "title_field": "title"
 }
\ No newline at end of file
diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py
index c9a64ff..0d12499 100644
--- a/erpnext/crm/doctype/lead/lead.py
+++ b/erpnext/crm/doctype/lead/lead.py
@@ -1,27 +1,19 @@
 # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 # License: GNU General Public License v3. See license.txt
 
-
 import frappe
 from frappe import _
 from frappe.contacts.address_and_contact import load_address_and_contact
 from frappe.email.inbox import link_communication_to_document
 from frappe.model.mapper import get_mapped_doc
-from frappe.utils import (
-	comma_and,
-	cstr,
-	get_link_to_form,
-	getdate,
-	has_gravatar,
-	nowdate,
-	validate_email_address,
-)
+from frappe.utils import comma_and, get_link_to_form, has_gravatar, validate_email_address
 
 from erpnext.accounts.party import set_taxes
 from erpnext.controllers.selling_controller import SellingController
+from erpnext.crm.utils import CRMNote, copy_comments, link_communications, link_open_events
 
 
-class Lead(SellingController):
+class Lead(SellingController, CRMNote):
 	def get_feed(self):
 		return "{0}: {1}".format(_(self.status), self.lead_name)
 
@@ -29,6 +21,7 @@
 		customer = frappe.db.get_value("Customer", {"lead_name": self.name})
 		self.get("__onload").is_customer = customer
 		load_address_and_contact(self)
+		self.set_onload("linked_prospects", self.get_linked_prospects())
 
 	def validate(self):
 		self.set_full_name()
@@ -37,79 +30,42 @@
 		self.set_status()
 		self.check_email_id_is_unique()
 		self.validate_email_id()
-		self.validate_contact_date()
-		self.set_prev()
+
+	def before_insert(self):
+		self.contact_doc = None
+		if frappe.db.get_single_value("CRM Settings", "auto_creation_of_contact"):
+			self.contact_doc = self.create_contact()
+
+	def after_insert(self):
+		self.link_to_contact()
+
+	def on_update(self):
+		self.update_prospect()
+
+	def on_trash(self):
+		frappe.db.sql("""update `tabIssue` set lead='' where lead=%s""", self.name)
+
+		self.unlink_dynamic_links()
+		self.remove_link_from_prospect()
 
 	def set_full_name(self):
 		if self.first_name:
-			self.lead_name = " ".join(filter(None, [self.first_name, self.middle_name, self.last_name]))
-
-	def validate_email_id(self):
-		if self.email_id:
-			if not self.flags.ignore_email_validation:
-				validate_email_address(self.email_id, throw=True)
-
-			if self.email_id == self.lead_owner:
-				frappe.throw(_("Lead Owner cannot be same as the Lead"))
-
-			if self.email_id == self.contact_by:
-				frappe.throw(_("Next Contact By cannot be same as the Lead Email Address"))
-
-			if self.is_new() or not self.image:
-				self.image = has_gravatar(self.email_id)
-
-	def validate_contact_date(self):
-		if self.contact_date and getdate(self.contact_date) < getdate(nowdate()):
-			frappe.throw(_("Next Contact Date cannot be in the past"))
-
-		if self.ends_on and self.contact_date and (getdate(self.ends_on) < getdate(self.contact_date)):
-			frappe.throw(_("Ends On date cannot be before Next Contact Date."))
-
-	def on_update(self):
-		self.add_calendar_event()
-		self.update_prospects()
-
-	def set_prev(self):
-		if self.is_new():
-			self._prev = frappe._dict({"contact_date": None, "ends_on": None, "contact_by": None})
-		else:
-			self._prev = frappe.db.get_value(
-				"Lead", self.name, ["contact_date", "ends_on", "contact_by"], as_dict=1
+			self.lead_name = " ".join(
+				filter(None, [self.salutation, self.first_name, self.middle_name, self.last_name])
 			)
 
-	def before_insert(self):
-		self.contact_doc = self.create_contact()
+	def set_lead_name(self):
+		if not self.lead_name:
+			# Check for leads being created through data import
+			if not self.company_name and not self.email_id and not self.flags.ignore_mandatory:
+				frappe.throw(_("A Lead requires either a person's name or an organization's name"))
+			elif self.company_name:
+				self.lead_name = self.company_name
+			else:
+				self.lead_name = self.email_id.split("@")[0]
 
-	def after_insert(self):
-		self.update_links()
-
-	def update_links(self):
-		# update contact links
-		if self.contact_doc:
-			self.contact_doc.append(
-				"links", {"link_doctype": "Lead", "link_name": self.name, "link_title": self.lead_name}
-			)
-			self.contact_doc.save()
-
-	def add_calendar_event(self, opts=None, force=False):
-		if frappe.db.get_single_value("CRM Settings", "create_event_on_next_contact_date"):
-			super(Lead, self).add_calendar_event(
-				{
-					"owner": self.lead_owner,
-					"starts_on": self.contact_date,
-					"ends_on": self.ends_on or "",
-					"subject": ("Contact " + cstr(self.lead_name)),
-					"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 set_title(self):
+		self.title = self.company_name or self.lead_name
 
 	def check_email_id_is_unique(self):
 		if self.email_id:
@@ -124,15 +80,47 @@
 
 				if duplicate_leads:
 					frappe.throw(
-						_("Email Address must be unique, already exists for {0}").format(comma_and(duplicate_leads)),
+						_("Email Address must be unique, it is already used in {0}").format(
+							comma_and(duplicate_leads)
+						),
 						frappe.DuplicateEntryError,
 					)
 
-	def on_trash(self):
-		frappe.db.sql("""update `tabIssue` set lead='' where lead=%s""", self.name)
+	def validate_email_id(self):
+		if self.email_id:
+			if not self.flags.ignore_email_validation:
+				validate_email_address(self.email_id, throw=True)
 
-		self.unlink_dynamic_links()
-		self.delete_events()
+			if self.email_id == self.lead_owner:
+				frappe.throw(_("Lead Owner cannot be same as the Lead Email Address"))
+
+			if self.is_new() or not self.image:
+				self.image = has_gravatar(self.email_id)
+
+	def link_to_contact(self):
+		# update contact links
+		if self.contact_doc:
+			self.contact_doc.append(
+				"links", {"link_doctype": "Lead", "link_name": self.name, "link_title": self.lead_name}
+			)
+			self.contact_doc.save()
+
+	def update_prospect(self):
+		lead_row_name = frappe.db.get_value(
+			"Prospect Lead", filters={"lead": self.name}, fieldname="name"
+		)
+		if lead_row_name:
+			lead_row = frappe.get_doc("Prospect Lead", lead_row_name)
+			lead_row.update(
+				{
+					"lead_name": self.lead_name,
+					"email": self.email_id,
+					"mobile_no": self.mobile_no,
+					"lead_owner": self.lead_owner,
+					"status": self.status,
+				}
+			)
+			lead_row.db_update()
 
 	def unlink_dynamic_links(self):
 		links = frappe.get_all(
@@ -155,6 +143,30 @@
 					linked_doc.remove(to_remove)
 					linked_doc.save(ignore_permissions=True)
 
+	def remove_link_from_prospect(self):
+		prospects = self.get_linked_prospects()
+
+		for d in prospects:
+			prospect = frappe.get_doc("Prospect", d.parent)
+			if len(prospect.get("leads")) == 1:
+				prospect.delete(ignore_permissions=True)
+			else:
+				to_remove = None
+				for d in prospect.get("leads"):
+					if d.lead == self.name:
+						to_remove = d
+
+				if to_remove:
+					prospect.remove(to_remove)
+					prospect.save(ignore_permissions=True)
+
+	def get_linked_prospects(self):
+		return frappe.get_all(
+			"Prospect Lead",
+			filters={"lead": self.name},
+			fields=["parent"],
+		)
+
 	def has_customer(self):
 		return frappe.db.get_value("Customer", {"lead_name": self.name})
 
@@ -171,50 +183,78 @@
 			"Quotation", {"party_name": self.name, "docstatus": 1, "status": "Lost"}
 		)
 
-	def set_lead_name(self):
-		if not self.lead_name:
-			# Check for leads being created through data import
-			if not self.company_name and not self.email_id and not self.flags.ignore_mandatory:
-				frappe.throw(_("A Lead requires either a person's name or an organization's name"))
-			elif self.company_name:
-				self.lead_name = self.company_name
-			else:
-				self.lead_name = self.email_id.split("@")[0]
+	@frappe.whitelist()
+	def create_prospect_and_contact(self, data):
+		data = frappe._dict(data)
+		if data.create_contact:
+			self.create_contact()
 
-	def set_title(self):
-		self.title = self.company_name or self.lead_name
+		if data.create_prospect:
+			self.create_prospect(data.prospect_name)
 
 	def create_contact(self):
-		if frappe.db.get_single_value("CRM Settings", "auto_creation_of_contact"):
-			if not self.lead_name:
-				self.set_full_name()
-				self.set_lead_name()
+		if not self.lead_name:
+			self.set_full_name()
+			self.set_lead_name()
 
-			contact = frappe.new_doc("Contact")
-			contact.update(
+		contact = frappe.new_doc("Contact")
+		contact.update(
+			{
+				"first_name": self.first_name or self.lead_name,
+				"last_name": self.last_name,
+				"salutation": self.salutation,
+				"gender": self.gender,
+				"job_title": self.job_title,
+				"company_name": self.company_name,
+			}
+		)
+
+		if self.email_id:
+			contact.append("email_ids", {"email_id": self.email_id, "is_primary": 1})
+
+		if self.phone:
+			contact.append("phone_nos", {"phone": self.phone, "is_primary_phone": 1})
+
+		if self.mobile_no:
+			contact.append("phone_nos", {"phone": self.mobile_no, "is_primary_mobile_no": 1})
+
+		contact.insert(ignore_permissions=True)
+		contact.reload()  # load changes by hooks on contact
+
+		return contact
+
+	def create_prospect(self, company_name):
+		try:
+			prospect = frappe.new_doc("Prospect")
+
+			prospect.company_name = company_name or self.company_name
+			prospect.no_of_employees = self.no_of_employees
+			prospect.industry = self.industry
+			prospect.market_segment = self.market_segment
+			prospect.annual_revenue = self.annual_revenue
+			prospect.territory = self.territory
+			prospect.fax = self.fax
+			prospect.website = self.website
+			prospect.prospect_owner = self.lead_owner
+			prospect.company = self.company
+			prospect.notes = self.notes
+
+			prospect.append(
+				"leads",
 				{
-					"first_name": self.first_name or self.lead_name,
-					"last_name": self.last_name,
-					"salutation": self.salutation,
-					"gender": self.gender,
-					"designation": self.designation,
-					"company_name": self.company_name,
-				}
+					"lead": self.name,
+					"lead_name": self.lead_name,
+					"email": self.email_id,
+					"mobile_no": self.mobile_no,
+					"lead_owner": self.lead_owner,
+					"status": self.status,
+				},
 			)
-
-			if self.email_id:
-				contact.append("email_ids", {"email_id": self.email_id, "is_primary": 1})
-
-			if self.phone:
-				contact.append("phone_nos", {"phone": self.phone, "is_primary_phone": 1})
-
-			if self.mobile_no:
-				contact.append("phone_nos", {"phone": self.mobile_no, "is_primary_mobile_no": 1})
-
-			contact.insert(ignore_permissions=True)
-			contact.reload()  # load changes by hooks on contact
-
-			return contact
+			prospect.flags.ignore_permissions = True
+			prospect.flags.ignore_mandatory = True
+			prospect.save()
+		except frappe.DuplicateEntryError:
+			frappe.throw(_("Prospect {0} already exists").format(company_name or self.company_name))
 
 
 @frappe.whitelist()
@@ -274,6 +314,8 @@
 					"company_name": "customer_name",
 					"email_id": "contact_email",
 					"mobile_no": "contact_mobile",
+					"lead_owner": "opportunity_owner",
+					"notes": "notes",
 				},
 			}
 		},
@@ -422,21 +464,25 @@
 	return lead
 
 
-def daily_open_lead():
-	leads = frappe.get_all("Lead", filters=[["contact_date", "Between", [nowdate(), nowdate()]]])
-	for lead in leads:
-		frappe.db.set_value("Lead", lead.name, "status", "Open")
-
-
 @frappe.whitelist()
 def add_lead_to_prospect(lead, prospect):
 	prospect = frappe.get_doc("Prospect", prospect)
-	prospect.append("prospect_lead", {"lead": lead})
+	prospect.append("leads", {"lead": lead})
 	prospect.save(ignore_permissions=True)
+
+	carry_forward_communication_and_comments = frappe.db.get_single_value(
+		"CRM Settings", "carry_forward_communication_and_comments"
+	)
+
+	if carry_forward_communication_and_comments:
+		copy_comments("Lead", lead, prospect)
+		link_communications("Lead", lead, prospect)
+	link_open_events("Lead", lead, prospect)
+
 	frappe.msgprint(
 		_("Lead {0} has been added to prospect {1}.").format(
 			frappe.bold(lead), frappe.bold(prospect.name)
 		),
-		title=_("Lead Added"),
+		title=_("Lead -> Prospect"),
 		indicator="green",
 	)
diff --git a/erpnext/crm/doctype/lead/lead_list.js b/erpnext/crm/doctype/lead/lead_list.js
index 75208fa..dbeaf60 100644
--- a/erpnext/crm/doctype/lead/lead_list.js
+++ b/erpnext/crm/doctype/lead/lead_list.js
@@ -16,7 +16,7 @@
 						prospect.prospect_owner = r.lead_owner;
 
 						leads.forEach(function(lead) {
-							let lead_prospect_row = frappe.model.add_child(prospect, 'prospect_lead');
+							let lead_prospect_row = frappe.model.add_child(prospect, 'leads');
 							lead_prospect_row.lead = lead.name;
 						});
 						frappe.set_route("Form", "Prospect", prospect.name);
diff --git a/erpnext/crm/doctype/lead/test_lead.py b/erpnext/crm/doctype/lead/test_lead.py
index 166ae2c..8fe688d 100644
--- a/erpnext/crm/doctype/lead/test_lead.py
+++ b/erpnext/crm/doctype/lead/test_lead.py
@@ -5,7 +5,10 @@
 import unittest
 
 import frappe
-from frappe.utils import random_string
+from frappe.utils import random_string, today
+
+from erpnext.crm.doctype.lead.lead import make_opportunity
+from erpnext.crm.utils import get_linked_prospect
 
 test_records = frappe.get_test_records("Lead")
 
@@ -83,6 +86,105 @@
 		self.assertEqual(frappe.db.exists("Lead", lead_doc.name), None)
 		self.assertEqual(len(address_1.get("links")), 1)
 
+	def test_prospect_creation_from_lead(self):
+		frappe.db.sql("delete from `tabLead` where lead_name='Rahul Tripathi'")
+		frappe.db.sql("delete from `tabProspect` where name='Prospect Company'")
+
+		lead = make_lead(
+			first_name="Rahul",
+			last_name="Tripathi",
+			email_id="rahul@gmail.com",
+			company_name="Prospect Company",
+		)
+
+		event = create_event("Meeting 1", today(), "Lead", lead.name)
+
+		lead.create_prospect(lead.company_name)
+
+		prospect = get_linked_prospect("Lead", lead.name)
+		self.assertEqual(prospect, "Prospect Company")
+
+		event.reload()
+		self.assertEqual(event.event_participants[1].reference_doctype, "Prospect")
+		self.assertEqual(event.event_participants[1].reference_docname, prospect)
+
+	def test_opportunity_from_lead(self):
+		frappe.db.sql("delete from `tabLead` where lead_name='Rahul Tripathi'")
+		frappe.db.sql("delete from `tabOpportunity` where party_name='Rahul Tripathi'")
+
+		lead = make_lead(
+			first_name="Rahul",
+			last_name="Tripathi",
+			email_id="rahul@gmail.com",
+			company_name="Prospect Company",
+		)
+
+		lead.add_note("test note")
+		event = create_event("Meeting 1", today(), "Lead", lead.name)
+		create_todo("followup", "Lead", lead.name)
+
+		opportunity = make_opportunity(lead.name)
+		opportunity.save()
+
+		self.assertEqual(opportunity.get("party_name"), lead.name)
+		self.assertEqual(opportunity.notes[0].note, "test note")
+
+		event.reload()
+		self.assertEqual(event.event_participants[1].reference_doctype, "Opportunity")
+		self.assertEqual(event.event_participants[1].reference_docname, opportunity.name)
+
+		self.assertTrue(
+			frappe.db.get_value(
+				"ToDo", {"reference_type": "Opportunity", "reference_name": opportunity.name}
+			)
+		)
+
+	def test_copy_events_from_lead_to_prospect(self):
+		frappe.db.sql("delete from `tabLead` where lead_name='Rahul Tripathi'")
+		frappe.db.sql("delete from `tabProspect` where name='Prospect Company'")
+
+		lead = make_lead(
+			first_name="Rahul",
+			last_name="Tripathi",
+			email_id="rahul@gmail.com",
+			company_name="Prospect Company",
+		)
+
+		lead.create_prospect(lead.company_name)
+		prospect = get_linked_prospect("Lead", lead.name)
+
+		event = create_event("Meeting", today(), "Lead", lead.name)
+
+		self.assertEqual(len(event.event_participants), 2)
+		self.assertEqual(event.event_participants[1].reference_doctype, "Prospect")
+		self.assertEqual(event.event_participants[1].reference_docname, prospect)
+
+
+def create_event(subject, starts_on, reference_type, reference_name):
+	event = frappe.new_doc("Event")
+	event.subject = subject
+	event.starts_on = starts_on
+	event.event_type = "Private"
+	event.all_day = 1
+	event.owner = "Administrator"
+	event.append(
+		"event_participants", {"reference_doctype": reference_type, "reference_docname": reference_name}
+	)
+	event.reference_type = reference_type
+	event.reference_name = reference_name
+	event.insert()
+	return event
+
+
+def create_todo(description, reference_type, reference_name):
+	todo = frappe.new_doc("ToDo")
+	todo.description = description
+	todo.owner = "Administrator"
+	todo.reference_type = reference_type
+	todo.reference_name = reference_name
+	todo.insert()
+	return todo
+
 
 def make_lead(**args):
 	args = frappe._dict(args)
@@ -93,6 +195,7 @@
 			"first_name": args.first_name or "_Test",
 			"last_name": args.last_name or "Lead",
 			"email_id": args.email_id or "new_lead_{}@example.com".format(random_string(5)),
+			"company_name": args.company_name or "_Test Company",
 		}
 	).insert()
 
diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js
index 8e7d67e..c53ea9d 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.js
+++ b/erpnext/crm/doctype/opportunity/opportunity.js
@@ -32,13 +32,6 @@
 		}
 	},
 
-	contact_date: function(frm) {
-		if(frm.doc.contact_date < frappe.datetime.now_datetime()){
-			frm.set_value("contact_date", "");
-			frappe.throw(__("Next follow up date should be greater than now."))
-		}
-	},
-
 	onload_post_render: function(frm) {
 		frm.get_field("items").grid.set_multiple_add("item_code", "qty");
 	},
@@ -130,6 +123,13 @@
 				});
 			}
 		}
+
+		if (!frm.is_new()) {
+			frappe.contacts.render_address_and_contact(frm);
+			// frm.trigger('render_contact_day_html');
+		} else {
+			frappe.contacts.clear_address_and_contact(frm);
+		}
 	},
 
 	set_contact_link: function(frm) {
@@ -227,8 +227,7 @@
 			'total': flt(total),
 			'base_total': flt(base_total)
 		});
-	}
-
+	},
 });
 frappe.ui.form.on("Opportunity Item", {
 	calculate: function(frm, cdt, cdn) {
@@ -264,13 +263,14 @@
 		this.frm.trigger('currency');
 	}
 
+	refresh() {
+		this.show_notes();
+		this.show_activities();
+	}
+
 	setup_queries() {
 		var me = this;
 
-		if(this.frm.fields_dict.contact_by.df.options.match(/^User/)) {
-			this.frm.set_query("contact_by", erpnext.queries.user);
-		}
-
 		me.frm.set_query('customer_address', erpnext.queries.address_query);
 
 		this.frm.set_query("item_code", "items", function() {
@@ -287,6 +287,14 @@
 		}
 		else if (me.frm.doc.opportunity_from == "Customer") {
 			me.frm.set_query('party_name', erpnext.queries['customer']);
+		} else if (me.frm.doc.opportunity_from == "Prospect") {
+			me.frm.set_query('party_name', function() {
+				return {
+					filters: {
+						"company": me.frm.doc.company
+					}
+				};
+			});
 		}
 	}
 
@@ -303,6 +311,24 @@
 			frm: cur_frm
 		})
 	}
+
+	show_notes() {
+		const crm_notes = new erpnext.utils.CRMNotes({
+			frm: this.frm,
+			notes_wrapper: $(this.frm.fields_dict.notes_html.wrapper),
+		});
+		crm_notes.refresh();
+	}
+
+	show_activities() {
+		const crm_activities = new erpnext.utils.CRMActivities({
+			frm: this.frm,
+			open_activities_wrapper: $(this.frm.fields_dict.open_activities_html.wrapper),
+			all_activities_wrapper: $(this.frm.fields_dict.all_activities_html.wrapper),
+			form_wrapper: $(this.frm.wrapper),
+		});
+		crm_activities.refresh();
+	}
 };
 
 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 089f2d2..7854007 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_events_in_timeline": 1,
  "allow_import": 1,
  "allow_rename": 1,
  "autoname": "naming_series:",
@@ -11,69 +12,85 @@
  "email_append_to": 1,
  "engine": "InnoDB",
  "field_order": [
-  "from_section",
   "naming_series",
   "opportunity_from",
   "party_name",
   "customer_name",
-  "source",
   "column_break0",
-  "title",
   "opportunity_type",
+  "source",
+  "opportunity_owner",
+  "column_break_10",
   "status",
-  "converted_by",
   "sales_stage",
-  "first_response_time",
   "expected_closing",
-  "next_contact",
-  "contact_by",
-  "contact_date",
-  "column_break2",
-  "to_discuss",
+  "probability",
+  "organization_details_section",
+  "no_of_employees",
+  "annual_revenue",
+  "column_break_23",
+  "customer_group",
+  "industry",
+  "column_break_31",
+  "market_segment",
+  "territory",
+  "website",
   "section_break_14",
   "currency",
+  "column_break_36",
   "conversion_rate",
-  "base_opportunity_amount",
-  "with_items",
   "column_break_17",
-  "probability",
   "opportunity_amount",
+  "base_opportunity_amount",
+  "more_info",
+  "company",
+  "campaign",
+  "transaction_date",
+  "column_break1",
+  "language",
+  "amended_from",
+  "title",
+  "first_response_time",
+  "lost_detail_section",
+  "lost_reasons",
+  "order_lost_reason",
+  "column_break_56",
+  "competitors",
+  "contact_info",
+  "primary_contact_section",
+  "contact_person",
+  "job_title",
+  "column_break_54",
+  "contact_email",
+  "contact_mobile",
+  "column_break_22",
+  "whatsapp",
+  "phone",
+  "phone_ext",
+  "address_contact_section",
+  "address_html",
+  "customer_address",
+  "address_display",
+  "column_break3",
+  "contact_html",
+  "contact_display",
   "items_section",
   "items",
   "section_break_32",
   "base_total",
   "column_break_33",
   "total",
-  "contact_info",
-  "customer_address",
-  "address_display",
-  "territory",
-  "customer_group",
-  "column_break3",
-  "contact_person",
-  "contact_display",
-  "contact_email",
-  "contact_mobile",
-  "more_info",
-  "company",
-  "campaign",
-  "column_break1",
-  "transaction_date",
-  "language",
-  "amended_from",
-  "lost_detail_section",
-  "lost_reasons",
-  "order_lost_reason",
-  "column_break_56",
-  "competitors"
+  "activities_tab",
+  "open_activities_html",
+  "all_activities_section",
+  "all_activities_html",
+  "notes_tab",
+  "notes_html",
+  "notes",
+  "dashboard_tab"
  ],
  "fields": [
   {
-   "fieldname": "from_section",
-   "fieldtype": "Section Break",
-   "options": "fa fa-user"
-  },
-  {
    "fieldname": "naming_series",
    "fieldtype": "Select",
    "in_list_view": 1,
@@ -113,8 +130,9 @@
    "bold": 1,
    "fieldname": "customer_name",
    "fieldtype": "Data",
+   "hidden": 1,
    "in_global_search": 1,
-   "label": "Customer / Lead Name",
+   "label": "Customer Name",
    "read_only": 1
   },
   {
@@ -167,47 +185,9 @@
    "label": "Expected Closing Date"
   },
   {
-   "collapsible": 1,
-   "collapsible_depends_on": "contact_by",
-   "fieldname": "next_contact",
-   "fieldtype": "Section Break",
-   "label": "Follow Up"
-  },
-  {
-   "fieldname": "contact_by",
-   "fieldtype": "Link",
-   "in_standard_filter": 1,
-   "label": "Next Contact By",
-   "oldfieldname": "contact_by",
-   "oldfieldtype": "Link",
-   "options": "User",
-   "width": "75px"
-  },
-  {
-   "fieldname": "contact_date",
-   "fieldtype": "Datetime",
-   "label": "Next Contact Date",
-   "oldfieldname": "contact_date",
-   "oldfieldtype": "Date"
-  },
-  {
-   "fieldname": "column_break2",
-   "fieldtype": "Column Break",
-   "oldfieldtype": "Column Break",
-   "width": "50%"
-  },
-  {
-   "fieldname": "to_discuss",
-   "fieldtype": "Small Text",
-   "label": "To Discuss",
-   "no_copy": 1,
-   "oldfieldname": "to_discuss",
-   "oldfieldtype": "Small Text"
-  },
-  {
    "fieldname": "section_break_14",
    "fieldtype": "Section Break",
-   "label": "Sales"
+   "label": "Opportunity Value"
   },
   {
    "fieldname": "currency",
@@ -222,12 +202,6 @@
    "options": "currency"
   },
   {
-   "default": "0",
-   "fieldname": "with_items",
-   "fieldtype": "Check",
-   "label": "With Items"
-  },
-  {
    "fieldname": "column_break_17",
    "fieldtype": "Column Break"
   },
@@ -245,9 +219,8 @@
    "label": "Probability (%)"
   },
   {
-   "depends_on": "with_items",
    "fieldname": "items_section",
-   "fieldtype": "Section Break",
+   "fieldtype": "Tab Break",
    "label": "Items",
    "oldfieldtype": "Section Break",
    "options": "fa fa-shopping-cart"
@@ -262,18 +235,16 @@
    "options": "Opportunity Item"
   },
   {
-   "collapsible": 1,
-   "collapsible_depends_on": "next_contact_by",
-   "depends_on": "eval:doc.party_name",
    "fieldname": "contact_info",
-   "fieldtype": "Section Break",
-   "label": "Contact Info",
+   "fieldtype": "Tab Break",
+   "label": "Contacts",
    "options": "fa fa-bullhorn"
   },
   {
    "depends_on": "eval:doc.party_name",
    "fieldname": "customer_address",
    "fieldtype": "Link",
+   "hidden": 1,
    "label": "Customer / Lead Address",
    "options": "Address",
    "print_hide": 1
@@ -327,19 +298,16 @@
    "read_only": 1
   },
   {
-   "depends_on": "eval:doc.party_name",
    "fieldname": "contact_email",
    "fieldtype": "Data",
    "label": "Contact Email",
-   "options": "Email",
-   "read_only": 1
+   "options": "Email"
   },
   {
-   "depends_on": "eval:doc.party_name",
    "fieldname": "contact_mobile",
-   "fieldtype": "Small Text",
-   "label": "Contact Mobile No",
-   "read_only": 1
+   "fieldtype": "Data",
+   "label": "Contact Mobile",
+   "options": "Phone"
   },
   {
    "collapsible": 1,
@@ -417,12 +385,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "converted_by",
-   "fieldtype": "Link",
-   "label": "Converted By",
-   "options": "User"
-  },
-  {
    "bold": 1,
    "fieldname": "first_response_time",
    "fieldtype": "Duration",
@@ -474,6 +436,7 @@
    "fieldtype": "Column Break"
   },
   {
+   "depends_on": "eval:doc.status===\"Lost\"",
    "fieldname": "lost_detail_section",
    "fieldtype": "Section Break",
    "label": "Lost Reasons"
@@ -488,12 +451,163 @@
    "label": "Competitors",
    "options": "Competitor Detail",
    "read_only": 1
+  },
+  {
+   "fieldname": "column_break_10",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "organization_details_section",
+   "fieldtype": "Section Break",
+   "label": "Organization"
+  },
+  {
+   "fieldname": "no_of_employees",
+   "fieldtype": "Int",
+   "label": "No of Employees"
+  },
+  {
+   "fieldname": "annual_revenue",
+   "fieldtype": "Currency",
+   "label": "Annual Revenue"
+  },
+  {
+   "fieldname": "industry",
+   "fieldtype": "Link",
+   "label": "Industry",
+   "options": "Industry Type"
+  },
+  {
+   "fieldname": "market_segment",
+   "fieldtype": "Link",
+   "label": "Market Segment",
+   "options": "Market Segment"
+  },
+  {
+   "fieldname": "column_break_23",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "address_contact_section",
+   "fieldtype": "Section Break",
+   "label": "Address & Contact"
+  },
+  {
+   "fieldname": "column_break_36",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "opportunity_owner",
+   "fieldtype": "Link",
+   "label": "Opportunity Owner",
+   "options": "User"
+  },
+  {
+   "fieldname": "website",
+   "fieldtype": "Data",
+   "label": "Website"
+  },
+  {
+   "fieldname": "column_break_22",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "whatsapp",
+   "fieldtype": "Data",
+   "label": "WhatsApp",
+   "options": "Phone"
+  },
+  {
+   "fieldname": "phone",
+   "fieldtype": "Data",
+   "label": "Phone",
+   "options": "Phone"
+  },
+  {
+   "fieldname": "phone_ext",
+   "fieldtype": "Data",
+   "label": "Phone Ext."
+  },
+  {
+   "fieldname": "column_break_31",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "primary_contact_section",
+   "fieldtype": "Section Break",
+   "label": "Primary Contact"
+  },
+  {
+   "fieldname": "column_break_54",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "dashboard_tab",
+   "fieldtype": "Tab Break",
+   "label": "Dashboard",
+   "show_dashboard": 1
+  },
+  {
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "notes_tab",
+   "fieldtype": "Tab Break",
+   "label": "Notes"
+  },
+  {
+   "fieldname": "notes_html",
+   "fieldtype": "HTML",
+   "label": "Notes HTML"
+  },
+  {
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "activities_tab",
+   "fieldtype": "Tab Break",
+   "label": "Activities"
+  },
+  {
+   "fieldname": "job_title",
+   "fieldtype": "Data",
+   "label": "Job Title"
+  },
+  {
+   "fieldname": "address_html",
+   "fieldtype": "HTML",
+   "label": "Address HTML"
+  },
+  {
+   "fieldname": "contact_html",
+   "fieldtype": "HTML",
+   "label": "Contact HTML"
+  },
+  {
+   "fieldname": "open_activities_html",
+   "fieldtype": "HTML",
+   "label": "Open Activities HTML"
+  },
+  {
+   "fieldname": "all_activities_section",
+   "fieldtype": "Section Break",
+   "label": "All Activities"
+  },
+  {
+   "fieldname": "all_activities_html",
+   "fieldtype": "HTML",
+   "label": "All Activities HTML"
+  },
+  {
+   "fieldname": "notes",
+   "fieldtype": "Table",
+   "hidden": 1,
+   "label": "Notes",
+   "no_copy": 1,
+   "options": "CRM Note"
   }
  ],
  "icon": "fa fa-info-sign",
  "idx": 195,
  "links": [],
- "modified": "2022-01-29 19:32:26.382896",
+ "modified": "2022-06-10 10:37:25.537444",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Opportunity",
diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py
index c70a4f6..0dc0cd3 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.py
+++ b/erpnext/crm/doctype/opportunity/opportunity.py
@@ -6,39 +6,42 @@
 
 import frappe
 from frappe import _
+from frappe.contacts.address_and_contact import load_address_and_contact
 from frappe.email.inbox import link_communication_to_document
 from frappe.model.mapper import get_mapped_doc
 from frappe.query_builder import DocType, Interval
 from frappe.query_builder.functions import Now
-from frappe.utils import cint, flt, get_fullname
+from frappe.utils import flt, get_fullname
 
-from erpnext.crm.utils import add_link_in_communication, copy_comments
+from erpnext.crm.utils import (
+	CRMNote,
+	copy_comments,
+	link_communications,
+	link_open_events,
+	link_open_tasks,
+)
 from erpnext.setup.utils import get_exchange_rate
 from erpnext.utilities.transaction_base import TransactionBase
 
 
-class Opportunity(TransactionBase):
+class Opportunity(TransactionBase, CRMNote):
+	def onload(self):
+		ref_doc = frappe.get_doc(self.opportunity_from, self.party_name)
+		load_address_and_contact(ref_doc)
+		self.set("__onload", ref_doc.get("__onload"))
+
 	def after_insert(self):
 		if self.opportunity_from == "Lead":
 			frappe.get_doc("Lead", self.party_name).set_status(update=True)
+			self.disable_lead()
 
-		if self.opportunity_from in ["Lead", "Prospect"]:
+			link_open_tasks(self.opportunity_from, self.party_name, self)
+			link_open_events(self.opportunity_from, self.party_name, self)
 			if frappe.db.get_single_value("CRM Settings", "carry_forward_communication_and_comments"):
 				copy_comments(self.opportunity_from, self.party_name, self)
-				add_link_in_communication(self.opportunity_from, self.party_name, self)
+				link_communications(self.opportunity_from, self.party_name, self)
 
 	def validate(self):
-		self._prev = frappe._dict(
-			{
-				"contact_date": frappe.db.get_value("Opportunity", self.name, "contact_date")
-				if (not cint(self.get("__islocal")))
-				else None,
-				"contact_by": frappe.db.get_value("Opportunity", self.name, "contact_by")
-				if (not cint(self.get("__islocal")))
-				else None,
-			}
-		)
-
 		self.make_new_lead_if_required()
 		self.validate_item_details()
 		self.validate_uom_is_integer("uom", "qty")
@@ -48,11 +51,8 @@
 		if not self.title:
 			self.title = self.customer_name
 
-		if not self.with_items:
-			self.items = []
-
-		else:
-			self.calculate_totals()
+		self.calculate_totals()
+		self.update_prospect()
 
 	def map_fields(self):
 		for field in self.meta.get_valid_columns():
@@ -75,6 +75,44 @@
 		self.total = flt(total)
 		self.base_total = flt(base_total)
 
+	def update_prospect(self):
+		prospect_name = None
+		if self.opportunity_from == "Prospect" and self.party_name:
+			prospect_name = self.party_name
+		elif self.opportunity_from == "Lead":
+			prospect_name = frappe.db.get_value("Prospect Lead", {"lead": self.party_name}, "parent")
+
+		if prospect_name:
+			prospect = frappe.get_doc("Prospect", prospect_name)
+
+			opportunity_values = {
+				"opportunity": self.name,
+				"amount": self.opportunity_amount,
+				"stage": self.sales_stage,
+				"deal_owner": self.opportunity_owner,
+				"probability": self.probability,
+				"expected_closing": self.expected_closing,
+				"currency": self.currency,
+				"contact_person": self.contact_person,
+			}
+
+			opportunity_already_added = False
+			for d in prospect.get("opportunities", []):
+				if d.opportunity == self.name:
+					opportunity_already_added = True
+					d.update(opportunity_values)
+					d.db_update()
+
+			if not opportunity_already_added:
+				prospect.append("opportunities", opportunity_values)
+				prospect.flags.ignore_permissions = True
+				prospect.flags.ignore_mandatory = True
+				prospect.save()
+
+	def disable_lead(self):
+		if self.opportunity_from == "Lead":
+			frappe.db.set_value("Lead", self.party_name, {"disabled": 1, "docstatus": 1})
+
 	def make_new_lead_if_required(self):
 		"""Set lead against new opportunity"""
 		if (not self.get("party_name")) and self.contact_email:
@@ -144,11 +182,8 @@
 		else:
 			frappe.throw(_("Cannot declare as lost, because Quotation has been made."))
 
-	def on_trash(self):
-		self.delete_events()
-
 	def has_active_quotation(self):
-		if not self.with_items:
+		if not self.get("items", []):
 			return frappe.get_all(
 				"Quotation",
 				{"opportunity": self.name, "status": ("not in", ["Lost", "Closed"]), "docstatus": 1},
@@ -165,7 +200,7 @@
 			)
 
 	def has_ordered_quotation(self):
-		if not self.with_items:
+		if not self.get("items", []):
 			return frappe.get_all(
 				"Quotation", {"opportunity": self.name, "status": "Ordered", "docstatus": 1}, "name"
 			)
@@ -195,43 +230,20 @@
 			return True
 
 	def validate_cust_name(self):
-		if self.party_name and self.opportunity_from == "Customer":
-			self.customer_name = frappe.db.get_value("Customer", self.party_name, "customer_name")
-		elif self.party_name and self.opportunity_from == "Lead":
-			lead_name, company_name = frappe.db.get_value(
-				"Lead", self.party_name, ["lead_name", "company_name"]
-			)
-			self.customer_name = company_name or lead_name
+		if self.party_name:
+			if self.opportunity_from == "Customer":
+				self.customer_name = frappe.db.get_value("Customer", self.party_name, "customer_name")
+			elif self.opportunity_from == "Lead":
+				customer_name = frappe.db.get_value("Prospect Lead", {"lead": self.party_name}, "parent")
+				if not customer_name:
+					lead_name, company_name = frappe.db.get_value(
+						"Lead", self.party_name, ["lead_name", "company_name"]
+					)
+					customer_name = company_name or lead_name
 
-	def on_update(self):
-		self.add_calendar_event()
-
-	def add_calendar_event(self, opts=None, force=False):
-		if frappe.db.get_single_value("CRM Settings", "create_event_on_next_contact_date_opportunity"):
-			if not opts:
-				opts = frappe._dict()
-
-			opts.description = ""
-			opts.contact_date = self.contact_date
-
-			if self.party_name and self.opportunity_from == "Customer":
-				if self.contact_person:
-					opts.description = f"Contact {self.contact_person}"
-				else:
-					opts.description = f"Contact customer {self.party_name}"
-			elif self.party_name and self.opportunity_from == "Lead":
-				if self.contact_display:
-					opts.description = f"Contact {self.contact_display}"
-				else:
-					opts.description = f"Contact lead {self.party_name}"
-
-			opts.subject = opts.description
-			opts.description += f". By : {self.contact_by}"
-
-			if self.to_discuss:
-				opts.description += f" To Discuss : {frappe.render_template(self.to_discuss, {'doc': self})}"
-
-			super(Opportunity, self).add_calendar_event(opts, force)
+				self.customer_name = customer_name
+			elif self.opportunity_from == "Prospect":
+				self.customer_name = self.party_name
 
 	def validate_item_details(self):
 		if not self.get("items"):
@@ -295,7 +307,7 @@
 
 		quotation.run_method("set_missing_values")
 		quotation.run_method("calculate_taxes_and_totals")
-		if not source.with_items:
+		if not source.get("items", []):
 			quotation.opportunity = source.name
 
 	doclist = get_mapped_doc(
@@ -440,34 +452,3 @@
 	link_communication_to_document(doc, "Opportunity", opportunity.name, ignore_communication_links)
 
 	return opportunity.name
-
-
-@frappe.whitelist()
-def get_events(start, end, filters=None):
-	"""Returns events for Gantt / Calendar view rendering.
-	:param start: Start date-time.
-	:param end: End date-time.
-	:param filters: Filters (JSON).
-	"""
-	from frappe.desk.calendar import get_event_conditions
-
-	conditions = get_event_conditions("Opportunity", filters)
-
-	data = frappe.db.sql(
-		"""
-		select
-			distinct `tabOpportunity`.name, `tabOpportunity`.customer_name, `tabOpportunity`.opportunity_amount,
-			`tabOpportunity`.title, `tabOpportunity`.contact_date
-		from
-			`tabOpportunity`
-		where
-			(`tabOpportunity`.contact_date between %(start)s and %(end)s)
-			{conditions}
-		""".format(
-			conditions=conditions
-		),
-		{"start": start, "end": end},
-		as_dict=True,
-		update={"allDay": 0},
-	)
-	return data
diff --git a/erpnext/crm/doctype/opportunity/opportunity_calendar.js b/erpnext/crm/doctype/opportunity/opportunity_calendar.js
deleted file mode 100644
index 58fa2b8..0000000
--- a/erpnext/crm/doctype/opportunity/opportunity_calendar.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-// License: GNU General Public License v3. See license.txt
-frappe.views.calendar["Opportunity"] = {
-	field_map: {
-		"start": "contact_date",
-		"end": "contact_date",
-		"id": "name",
-		"title": "customer_name",
-		"allDay": "allDay"
-    },
-	options: {
-		header: {
-			left: 'prev,next today',
-			center: 'title',
-			right: 'month'
-		}
-    },
-    get_events_method: 'erpnext.crm.doctype.opportunity.opportunity.get_events'
-}
diff --git a/erpnext/crm/doctype/prospect/prospect.js b/erpnext/crm/doctype/prospect/prospect.js
index 8721a5b..495ed29 100644
--- a/erpnext/crm/doctype/prospect/prospect.js
+++ b/erpnext/crm/doctype/prospect/prospect.js
@@ -27,5 +27,26 @@
 		} else {
 			frappe.contacts.clear_address_and_contact(frm);
 		}
+		frm.trigger("show_notes");
+		frm.trigger("show_activities");
+	},
+
+	show_notes (frm) {
+		const crm_notes = new erpnext.utils.CRMNotes({
+			frm: frm,
+			notes_wrapper: $(frm.fields_dict.notes_html.wrapper),
+		});
+		crm_notes.refresh();
+	},
+
+	show_activities (frm) {
+		const crm_activities = new erpnext.utils.CRMActivities({
+			frm: frm,
+			open_activities_wrapper: $(frm.fields_dict.open_activities_html.wrapper),
+			all_activities_wrapper: $(frm.fields_dict.all_activities_html.wrapper),
+			form_wrapper: $(frm.wrapper),
+		});
+		crm_activities.refresh();
 	}
+
 });
diff --git a/erpnext/crm/doctype/prospect/prospect.json b/erpnext/crm/doctype/prospect/prospect.json
index c9554ba..2750e5b 100644
--- a/erpnext/crm/doctype/prospect/prospect.json
+++ b/erpnext/crm/doctype/prospect/prospect.json
@@ -1,33 +1,42 @@
 {
  "actions": [],
+ "allow_events_in_timeline": 1,
  "autoname": "field:company_name",
  "creation": "2021-08-19 00:21:06.995448",
  "doctype": "DocType",
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
+  "overview_tab",
   "company_name",
-  "industry",
-  "market_segment",
   "customer_group",
+  "no_of_employees",
+  "annual_revenue",
+  "column_break_4",
+  "market_segment",
+  "industry",
   "territory",
   "column_break_6",
-  "no_of_employees",
-  "currency",
-  "annual_revenue",
-  "more_details_section",
-  "fax",
-  "website",
-  "column_break_13",
   "prospect_owner",
+  "website",
+  "fax",
   "company",
-  "leads_section",
-  "prospect_lead",
   "address_and_contact_section",
+  "column_break_16",
+  "contacts_tab",
   "address_html",
-  "column_break_17",
+  "column_break_18",
   "contact_html",
+  "leads_section",
+  "leads",
+  "opportunities_tab",
+  "opportunities",
+  "activities_tab",
+  "open_activities_html",
+  "all_activities_section",
+  "all_activities_html",
   "notes_section",
+  "notes_html",
   "notes"
  ],
  "fields": [
@@ -75,13 +84,6 @@
    "label": "No. of Employees"
   },
   {
-   "fieldname": "currency",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Currency",
-   "options": "Currency"
-  },
-  {
    "fieldname": "annual_revenue",
    "fieldtype": "Currency",
    "in_list_view": 1,
@@ -108,52 +110,31 @@
   },
   {
    "fieldname": "leads_section",
-   "fieldtype": "Section Break",
+   "fieldtype": "Tab Break",
    "label": "Leads"
   },
   {
-   "fieldname": "prospect_lead",
-   "fieldtype": "Table",
-   "options": "Prospect Lead"
-  },
-  {
    "fieldname": "address_html",
    "fieldtype": "HTML",
    "label": "Address HTML"
   },
   {
-   "fieldname": "column_break_17",
-   "fieldtype": "Column Break"
-  },
-  {
    "fieldname": "contact_html",
    "fieldtype": "HTML",
    "label": "Contact HTML"
   },
   {
    "collapsible": 1,
+   "depends_on": "eval:!doc.__islocal",
    "fieldname": "notes_section",
-   "fieldtype": "Section Break",
+   "fieldtype": "Tab Break",
    "label": "Notes"
   },
   {
-   "fieldname": "notes",
-   "fieldtype": "Text Editor"
-  },
-  {
-   "fieldname": "more_details_section",
-   "fieldtype": "Section Break",
-   "label": "More Details"
-  },
-  {
-   "fieldname": "column_break_13",
-   "fieldtype": "Column Break"
-  },
-  {
    "depends_on": "eval: !doc.__islocal",
    "fieldname": "address_and_contact_section",
    "fieldtype": "Section Break",
-   "label": "Address and Contact"
+   "label": "Address"
   },
   {
    "fieldname": "company",
@@ -161,11 +142,83 @@
    "label": "Company",
    "options": "Company",
    "reqd": 1
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "opportunities_tab",
+   "fieldtype": "Tab Break",
+   "label": "Opportunities"
+  },
+  {
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "activities_tab",
+   "fieldtype": "Tab Break",
+   "label": "Activities"
+  },
+  {
+   "fieldname": "notes_html",
+   "fieldtype": "HTML",
+   "label": "Notes HTML"
+  },
+  {
+   "fieldname": "opportunities",
+   "fieldtype": "Table",
+   "label": "Opportunities",
+   "options": "Prospect Opportunity"
+  },
+  {
+   "fieldname": "contacts_tab",
+   "fieldtype": "Tab Break",
+   "label": "Address & Contact"
+  },
+  {
+   "fieldname": "column_break_18",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "leads",
+   "fieldtype": "Table",
+   "options": "Prospect Lead"
+  },
+  {
+   "fieldname": "column_break_16",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "overview_tab",
+   "fieldtype": "Tab Break",
+   "label": "Overview"
+  },
+  {
+   "fieldname": "open_activities_html",
+   "fieldtype": "HTML",
+   "label": "Open Activities HTML"
+  },
+  {
+   "fieldname": "all_activities_section",
+   "fieldtype": "Section Break",
+   "label": "All Activities"
+  },
+  {
+   "fieldname": "all_activities_html",
+   "fieldtype": "HTML",
+   "label": "All Activities HTML"
+  },
+  {
+   "fieldname": "notes",
+   "fieldtype": "Table",
+   "hidden": 1,
+   "label": "Notes",
+   "no_copy": 1,
+   "options": "CRM Note"
   }
  ],
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2021-11-01 13:10:36.759249",
+ "modified": "2022-06-09 16:58:45.100244",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Prospect",
@@ -207,6 +260,7 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "title_field": "company_name",
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/crm/doctype/prospect/prospect.py b/erpnext/crm/doctype/prospect/prospect.py
index 39436f5..fbb1158 100644
--- a/erpnext/crm/doctype/prospect/prospect.py
+++ b/erpnext/crm/doctype/prospect/prospect.py
@@ -3,19 +3,15 @@
 
 import frappe
 from frappe.contacts.address_and_contact import load_address_and_contact
-from frappe.model.document import Document
 from frappe.model.mapper import get_mapped_doc
 
-from erpnext.crm.utils import add_link_in_communication, copy_comments
+from erpnext.crm.utils import CRMNote, copy_comments, link_communications, link_open_events
 
 
-class Prospect(Document):
+class Prospect(CRMNote):
 	def onload(self):
 		load_address_and_contact(self)
 
-	def validate(self):
-		self.update_lead_details()
-
 	def on_update(self):
 		self.link_with_lead_contact_and_address()
 
@@ -23,23 +19,24 @@
 		self.unlink_dynamic_links()
 
 	def after_insert(self):
-		if frappe.db.get_single_value("CRM Settings", "carry_forward_communication_and_comments"):
-			for row in self.get("prospect_lead"):
-				copy_comments("Lead", row.lead, self)
-				add_link_in_communication("Lead", row.lead, self)
+		carry_forward_communication_and_comments = frappe.db.get_single_value(
+			"CRM Settings", "carry_forward_communication_and_comments"
+		)
 
-	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
+		for row in self.get("leads"):
+			if carry_forward_communication_and_comments:
+				copy_comments("Lead", row.lead, self)
+				link_communications("Lead", row.lead, self)
+			link_open_events("Lead", row.lead, self)
+
+		for row in self.get("opportunities"):
+			if carry_forward_communication_and_comments:
+				copy_comments("Opportunity", row.opportunity, self)
+				link_communications("Opportunity", row.opportunity, self)
+			link_open_events("Opportunity", row.opportunity, self)
 
 	def link_with_lead_contact_and_address(self):
-		for row in self.prospect_lead:
+		for row in self.leads:
 			links = frappe.get_all(
 				"Dynamic Link",
 				filters={"link_doctype": "Lead", "link_name": row.lead},
@@ -116,9 +113,7 @@
 		{
 			"Prospect": {
 				"doctype": "Opportunity",
-				"field_map": {
-					"name": "party_name",
-				},
+				"field_map": {"name": "party_name", "prospect_owner": "opportunity_owner"},
 			}
 		},
 		target_doc,
@@ -127,3 +122,25 @@
 	)
 
 	return doclist
+
+
+@frappe.whitelist()
+def get_opportunities(prospect):
+	return frappe.get_all(
+		"Opportunity",
+		filters={"opportunity_from": "Prospect", "party_name": prospect},
+		fields=[
+			"opportunity_owner",
+			"sales_stage",
+			"status",
+			"expected_closing",
+			"probability",
+			"opportunity_amount",
+			"currency",
+			"contact_person",
+			"contact_email",
+			"contact_mobile",
+			"creation",
+			"name",
+		],
+	)
diff --git a/erpnext/crm/doctype/prospect/test_prospect.py b/erpnext/crm/doctype/prospect/test_prospect.py
index ddd7b93..874f84c 100644
--- a/erpnext/crm/doctype/prospect/test_prospect.py
+++ b/erpnext/crm/doctype/prospect/test_prospect.py
@@ -20,7 +20,7 @@
 		add_lead_to_prospect(lead_doc.name, prospect_doc.name)
 		prospect_doc.reload()
 		lead_exists_in_prosoect = False
-		for rec in prospect_doc.get("prospect_lead"):
+		for rec in prospect_doc.get("leads"):
 			if rec.lead == lead_doc.name:
 				lead_exists_in_prosoect = True
 		self.assertEqual(lead_exists_in_prosoect, True)
diff --git a/erpnext/crm/doctype/prospect_lead/prospect_lead.json b/erpnext/crm/doctype/prospect_lead/prospect_lead.json
index 3c160d9..075c0f9 100644
--- a/erpnext/crm/doctype/prospect_lead/prospect_lead.json
+++ b/erpnext/crm/doctype/prospect_lead/prospect_lead.json
@@ -7,12 +7,15 @@
  "field_order": [
   "lead",
   "lead_name",
-  "status",
   "email",
-  "mobile_no"
+  "column_break_4",
+  "mobile_no",
+  "lead_owner",
+  "status"
  ],
  "fields": [
   {
+   "columns": 2,
    "fieldname": "lead",
    "fieldtype": "Link",
    "in_list_view": 1,
@@ -21,6 +24,8 @@
    "reqd": 1
   },
   {
+   "columns": 2,
+   "fetch_from": "lead.lead_name",
    "fieldname": "lead_name",
    "fieldtype": "Data",
    "in_list_view": 1,
@@ -28,14 +33,17 @@
    "read_only": 1
   },
   {
+   "columns": 1,
+   "fetch_from": "lead.status",
    "fieldname": "status",
-   "fieldtype": "Select",
+   "fieldtype": "Data",
    "in_list_view": 1,
    "label": "Status",
-   "options": "Lead\nOpen\nReplied\nOpportunity\nQuotation\nLost Quotation\nInterested\nConverted\nDo Not Contact",
    "read_only": 1
   },
   {
+   "columns": 2,
+   "fetch_from": "lead.email_id",
    "fieldname": "email",
    "fieldtype": "Data",
    "in_list_view": 1,
@@ -44,18 +52,32 @@
    "read_only": 1
   },
   {
+   "columns": 2,
+   "fetch_from": "lead.mobile_no",
    "fieldname": "mobile_no",
    "fieldtype": "Data",
    "in_list_view": 1,
    "label": "Mobile No",
    "options": "Phone",
    "read_only": 1
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "columns": 1,
+   "fetch_from": "lead.lead_owner",
+   "fieldname": "lead_owner",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Lead Owner"
   }
  ],
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-08-25 12:58:24.638054",
+ "modified": "2022-04-28 20:27:58.805970",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Prospect Lead",
@@ -63,5 +85,6 @@
  "permissions": [],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/crm/doctype/prospect_opportunity/__init__.py b/erpnext/crm/doctype/prospect_opportunity/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/crm/doctype/prospect_opportunity/__init__.py
diff --git a/erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.json b/erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.json
new file mode 100644
index 0000000..d8c2520
--- /dev/null
+++ b/erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.json
@@ -0,0 +1,101 @@
+{
+ "actions": [],
+ "autoname": "autoincrement",
+ "creation": "2022-04-27 17:40:37.965161",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "opportunity",
+  "amount",
+  "stage",
+  "deal_owner",
+  "column_break_4",
+  "probability",
+  "expected_closing",
+  "currency",
+  "contact_person"
+ ],
+ "fields": [
+  {
+   "columns": 2,
+   "fieldname": "opportunity",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Opportunity",
+   "options": "Opportunity"
+  },
+  {
+   "columns": 2,
+   "fetch_from": "opportunity.opportunity_amount",
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Amount",
+   "options": "currency"
+  },
+  {
+   "columns": 2,
+   "fetch_from": "opportunity.sales_stage",
+   "fieldname": "stage",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Stage"
+  },
+  {
+   "columns": 1,
+   "fetch_from": "opportunity.probability",
+   "fieldname": "probability",
+   "fieldtype": "Percent",
+   "in_list_view": 1,
+   "label": "Probability"
+  },
+  {
+   "columns": 1,
+   "fetch_from": "opportunity.expected_closing",
+   "fieldname": "expected_closing",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Closing"
+  },
+  {
+   "fetch_from": "opportunity.currency",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency"
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "columns": 2,
+   "fetch_from": "opportunity.opportunity_owner",
+   "fieldname": "deal_owner",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Deal Owner"
+  },
+  {
+   "fetch_from": "opportunity.contact_person",
+   "fieldname": "contact_person",
+   "fieldtype": "Link",
+   "label": "Contact Person",
+   "options": "Contact"
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2022-04-28 10:05:38.730368",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Prospect Opportunity",
+ "naming_rule": "Autoincrement",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": []
+}
\ No newline at end of file
diff --git a/erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.py b/erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.py
new file mode 100644
index 0000000..8f5d19a
--- /dev/null
+++ b/erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+
+class ProspectOpportunity(Document):
+	pass
diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.js b/erpnext/crm/report/lost_opportunity/lost_opportunity.js
index 97c56f8..927c54d 100644
--- a/erpnext/crm/report/lost_opportunity/lost_opportunity.js
+++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.js
@@ -57,11 +57,5 @@
 			"fieldtype": "Dynamic Link",
 			"options": "opportunity_from"
 		},
-		{
-			"fieldname":"contact_by",
-			"label": __("Next Contact By"),
-			"fieldtype": "Link",
-			"options": "User"
-		},
 	]
 };
diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.json b/erpnext/crm/report/lost_opportunity/lost_opportunity.json
index e7a8e12..f6f36bd 100644
--- a/erpnext/crm/report/lost_opportunity/lost_opportunity.json
+++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.json
@@ -7,8 +7,8 @@
  "doctype": "Report",
  "idx": 0,
  "is_standard": "Yes",
- "json": "{\"order_by\": \"`tabOpportunity`.`modified` desc\", \"filters\": [[\"Opportunity\", \"status\", \"=\", \"Lost\"]], \"fields\": [[\"name\", \"Opportunity\"], [\"opportunity_from\", \"Opportunity\"], [\"party_name\", \"Opportunity\"], [\"customer_name\", \"Opportunity\"], [\"opportunity_type\", \"Opportunity\"], [\"status\", \"Opportunity\"], [\"contact_by\", \"Opportunity\"], [\"docstatus\", \"Opportunity\"], [\"lost_reason\", \"Lost Reason Detail\"]], \"add_totals_row\": 0, \"add_total_row\": 0, \"page_length\": 20}",
- "modified": "2020-07-29 15:49:02.848845",
+ "json": "{\"order_by\": \"`tabOpportunity`.`modified` desc\", \"filters\": [[\"Opportunity\", \"status\", \"=\", \"Lost\"]], \"fields\": [[\"name\", \"Opportunity\"], [\"opportunity_from\", \"Opportunity\"], [\"party_name\", \"Opportunity\"], [\"customer_name\", \"Opportunity\"], [\"opportunity_type\", \"Opportunity\"], [\"status\", \"Opportunity\"], [\"docstatus\", \"Opportunity\"], [\"lost_reason\", \"Lost Reason Detail\"]], \"add_totals_row\": 0, \"add_total_row\": 0, \"page_length\": 20}",
+ "modified": "2022-06-04 15:49:02.848845",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Lost Opportunity",
diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.py b/erpnext/crm/report/lost_opportunity/lost_opportunity.py
index a57b44b..254511c 100644
--- a/erpnext/crm/report/lost_opportunity/lost_opportunity.py
+++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.py
@@ -61,13 +61,6 @@
 			"options": "Territory",
 			"width": 150,
 		},
-		{
-			"label": _("Next Contact By"),
-			"fieldname": "contact_by",
-			"fieldtype": "Link",
-			"options": "User",
-			"width": 150,
-		},
 	]
 	return columns
 
@@ -81,7 +74,6 @@
 			`tabOpportunity`.party_name,
 			`tabOpportunity`.customer_name,
 			`tabOpportunity`.opportunity_type,
-			`tabOpportunity`.contact_by,
 			GROUP_CONCAT(`tabOpportunity Lost Reason Detail`.lost_reason separator ', ') lost_reason,
 			`tabOpportunity`.sales_stage,
 			`tabOpportunity`.territory
@@ -115,9 +107,6 @@
 	if filters.get("party_name"):
 		conditions.append(" and `tabOpportunity`.party_name=%(party_name)s")
 
-	if filters.get("contact_by"):
-		conditions.append(" and `tabOpportunity`.contact_by=%(contact_by)s")
-
 	return " ".join(conditions) if conditions else ""
 
 
diff --git a/erpnext/crm/utils.py b/erpnext/crm/utils.py
index 5783b2c..33441b1 100644
--- a/erpnext/crm/utils.py
+++ b/erpnext/crm/utils.py
@@ -1,4 +1,6 @@
 import frappe
+from frappe.model.document import Document
+from frappe.utils import cstr, now
 
 
 def update_lead_phone_numbers(contact, method):
@@ -41,7 +43,7 @@
 		comment.insert()
 
 
-def add_link_in_communication(doctype, docname, doc):
+def link_communications(doctype, docname, doc):
 	communication_list = get_linked_communication_list(doctype, docname)
 
 	for communication in communication_list:
@@ -60,3 +62,138 @@
 	)
 
 	return communications + communication_links
+
+
+def link_communications_with_prospect(communication, method):
+	prospect = get_linked_prospect(communication.reference_doctype, communication.reference_name)
+
+	if prospect:
+		already_linked = any(
+			[
+				d.name
+				for d in communication.get("timeline_links")
+				if d.link_doctype == "Prospect" and d.link_name == prospect
+			]
+		)
+		if not already_linked:
+			row = communication.append("timeline_links")
+			row.link_doctype = "Prospect"
+			row.link_name = prospect
+			row.db_update()
+
+
+def get_linked_prospect(reference_doctype, reference_name):
+	prospect = None
+	if reference_doctype == "Lead":
+		prospect = frappe.db.get_value("Prospect Lead", {"lead": reference_name}, "parent")
+
+	elif reference_doctype == "Opportunity":
+		opportunity_from, party_name = frappe.db.get_value(
+			"Opportunity", reference_name, ["opportunity_from", "party_name"]
+		)
+		if opportunity_from == "Lead":
+			prospect = frappe.db.get_value(
+				"Prospect Opportunity", {"opportunity": reference_name}, "parent"
+			)
+		if opportunity_from == "Prospect":
+			prospect = party_name
+
+	return prospect
+
+
+def link_events_with_prospect(event, method):
+	if event.event_participants:
+		ref_doctype = event.event_participants[0].reference_doctype
+		ref_docname = event.event_participants[0].reference_docname
+		prospect = get_linked_prospect(ref_doctype, ref_docname)
+		if prospect:
+			event.add_participant("Prospect", prospect)
+			event.save()
+
+
+def link_open_tasks(ref_doctype, ref_docname, doc):
+	todos = get_open_todos(ref_doctype, ref_docname)
+
+	for todo in todos:
+		todo_doc = frappe.get_doc("ToDo", todo.name)
+		todo_doc.reference_type = doc.doctype
+		todo_doc.reference_name = doc.name
+		todo_doc.db_update()
+
+
+def link_open_events(ref_doctype, ref_docname, doc):
+	events = get_open_events(ref_doctype, ref_docname)
+	for event in events:
+		event_doc = frappe.get_doc("Event", event.name)
+		event_doc.add_participant(doc.doctype, doc.name)
+		event_doc.save()
+
+
+@frappe.whitelist()
+def get_open_activities(ref_doctype, ref_docname):
+	tasks = get_open_todos(ref_doctype, ref_docname)
+	events = get_open_events(ref_doctype, ref_docname)
+
+	return {"tasks": tasks, "events": events}
+
+
+def get_open_todos(ref_doctype, ref_docname):
+	return frappe.get_all(
+		"ToDo",
+		filters={"reference_type": ref_doctype, "reference_name": ref_docname, "status": "Open"},
+		fields=[
+			"name",
+			"description",
+			"allocated_to",
+			"date",
+		],
+	)
+
+
+def get_open_events(ref_doctype, ref_docname):
+	event = frappe.qb.DocType("Event")
+	event_link = frappe.qb.DocType("Event Participants")
+
+	query = (
+		frappe.qb.from_(event)
+		.join(event_link)
+		.on(event_link.parent == event.name)
+		.select(
+			event.name,
+			event.subject,
+			event.event_category,
+			event.starts_on,
+			event.ends_on,
+			event.description,
+		)
+		.where(
+			(event_link.reference_doctype == ref_doctype)
+			& (event_link.reference_docname == ref_docname)
+			& (event.status == "Open")
+		)
+	)
+	data = query.run(as_dict=True)
+
+	return data
+
+
+class CRMNote(Document):
+	@frappe.whitelist()
+	def add_note(self, note):
+		self.append("notes", {"note": note, "added_by": frappe.session.user, "added_on": now()})
+		self.save()
+
+	@frappe.whitelist()
+	def edit_note(self, note, row_id):
+		for d in self.notes:
+			if cstr(d.name) == row_id:
+				d.note = note
+				d.db_update()
+
+	@frappe.whitelist()
+	def delete_note(self, row_id):
+		for d in self.notes:
+			if cstr(d.name) == row_id:
+				self.remove(d)
+				break
+		self.save()
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 7d7f65d..b3c35cf 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -299,7 +299,11 @@
 		"on_update": [
 			"erpnext.support.doctype.service_level_agreement.service_level_agreement.on_communication_update",
 			"erpnext.support.doctype.issue.issue.set_first_response_time",
-		]
+		],
+		"after_insert": "erpnext.crm.utils.link_communications_with_prospect",
+	},
+	"Event": {
+		"after_insert": "erpnext.crm.utils.link_events_with_prospect",
 	},
 	"Sales Taxes and Charges Template": {
 		"on_update": "erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings.validate_cart_settings"
@@ -453,7 +457,6 @@
 		"erpnext.hr.utils.allocate_earned_leaves",
 		"erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall.create_process_loan_security_shortfall",
 		"erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
-		"erpnext.crm.doctype.lead.lead.daily_open_lead",
 	],
 	"weekly": ["erpnext.hr.doctype.employee.employee_reminders.send_reminders_in_advance_weekly"],
 	"monthly": ["erpnext.hr.doctype.employee.employee_reminders.send_reminders_in_advance_monthly"],
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 318875d..2addf91 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -375,3 +375,4 @@
 erpnext.patches.v13_0.set_payroll_entry_status
 erpnext.patches.v13_0.job_card_status_on_hold
 erpnext.patches.v14_0.migrate_gl_to_payment_ledger
+erpnext.patches.v14_0.crm_ux_cleanup
diff --git a/erpnext/patches/v14_0/crm_ux_cleanup.py b/erpnext/patches/v14_0/crm_ux_cleanup.py
new file mode 100644
index 0000000..923daee
--- /dev/null
+++ b/erpnext/patches/v14_0/crm_ux_cleanup.py
@@ -0,0 +1,84 @@
+import frappe
+from frappe.model.utils.rename_field import rename_field
+from frappe.utils import add_months, cstr, today
+
+
+def execute():
+	for doctype in ("Lead", "Opportunity", "Prospect", "Prospect Lead"):
+		frappe.reload_doc("crm", "doctype", doctype)
+
+	try:
+		rename_field("Lead", "designation", "job_title")
+		rename_field("Opportunity", "converted_by", "opportunity_owner")
+		rename_field("Prospect", "prospect_lead", "leads")
+	except Exception as e:
+		if e.args[0] != 1054:
+			raise
+
+	add_calendar_event_for_leads()
+	add_calendar_event_for_opportunities()
+
+
+def add_calendar_event_for_leads():
+	# create events based on next contact date
+	leads = frappe.get_all(
+		"Lead",
+		{"contact_date": [">=", add_months(today(), -1)]},
+		["name", "contact_date", "contact_by", "ends_on", "lead_name", "lead_owner"],
+	)
+	for d in leads:
+		event = frappe.get_doc(
+			{
+				"doctype": "Event",
+				"owner": d.lead_owner,
+				"subject": ("Contact " + cstr(d.lead_name)),
+				"description": (
+					("Contact " + cstr(d.lead_name)) + (("<br>By: " + cstr(d.contact_by)) if d.contact_by else "")
+				),
+				"starts_on": d.contact_date,
+				"ends_on": d.ends_on,
+				"event_type": "Private",
+			}
+		)
+
+		event.append("event_participants", {"reference_doctype": "Lead", "reference_docname": d.name})
+
+		event.insert(ignore_permissions=True)
+
+
+def add_calendar_event_for_opportunities():
+	# create events based on next contact date
+	opportunities = frappe.get_all(
+		"Opportunity",
+		{"contact_date": [">=", add_months(today(), -1)]},
+		[
+			"name",
+			"contact_date",
+			"contact_by",
+			"to_discuss",
+			"party_name",
+			"opportunity_owner",
+			"contact_person",
+		],
+	)
+	for d in opportunities:
+		event = frappe.get_doc(
+			{
+				"doctype": "Event",
+				"owner": d.opportunity_owner,
+				"subject": ("Contact " + cstr(d.contact_person or d.party_name)),
+				"description": (
+					("Contact " + cstr(d.contact_person or d.party_name))
+					+ (("<br>By: " + cstr(d.contact_by)) if d.contact_by else "")
+					+ (("<br>Agenda: " + cstr(d.to_discuss)) if d.to_discuss else "")
+				),
+				"starts_on": d.contact_date,
+				"event_type": "Private",
+			}
+		)
+
+		event.append(
+			"event_participants", {"reference_doctype": "Opportunity", "reference_docname": d.name}
+		)
+
+		event.insert(ignore_permissions=True)
diff --git a/erpnext/public/js/erpnext.bundle.js b/erpnext/public/js/erpnext.bundle.js
index 3dae6d4..d545929 100644
--- a/erpnext/public/js/erpnext.bundle.js
+++ b/erpnext/public/js/erpnext.bundle.js
@@ -22,5 +22,8 @@
 import "./telephony";
 import "./templates/call_link.html";
 import "./bulk_transaction_processing";
+import "./utils/crm_activities";
+import "./templates/crm_activities.html";
+import "./templates/crm_notes.html";
 
 // import { sum } from 'frappe/public/utils/util.js'
diff --git a/erpnext/public/js/templates/crm_activities.html b/erpnext/public/js/templates/crm_activities.html
new file mode 100644
index 0000000..e0c237c
--- /dev/null
+++ b/erpnext/public/js/templates/crm_activities.html
@@ -0,0 +1,172 @@
+<div class="open-activities">
+	<div class="new-btn pb-3">
+		<span>
+			<button class="btn btn-sm small new-task-btn mr-1">
+				<svg class="icon icon-sm">
+					<use href="#icon-small-message"></use>
+				</svg>
+				{{ __("New Task") }}
+			</button>
+			<button class="btn btn-sm small new-event-btn">
+				<svg class="icon icon-sm">
+					<use href="#icon-calendar"></use>
+				</svg>
+				{{ __("New Event") }}
+			</button>
+		</span>
+	</div>
+	<div class="section-body">
+		<div class="open-tasks pr-1">
+			<div class="open-section-head">
+				<span class="ml-2">{{ __("Open Tasks") }}</span>
+			</div>
+			{% if (tasks.length) { %}
+				{% for(var i=0, l=tasks.length; i<l; i++) { %}
+					<div class="single-activity">
+						<div class="flex justify-between mb-2">
+							<div class="row label-area font-md ml-1">
+								<span class="mr-2">
+									<svg class="icon icon-sm">
+										<use href="#icon-small-message"></use>
+									</svg>
+								</span>
+								<a href="/app/todo/{{ tasks[i].name }}" title="{{ __('Open Task') }}">
+									{%= tasks[i].description %}
+								</a>
+							</div>
+							<div class="checkbox">
+								<input type="checkbox" class="completion-checkbox"
+									name="{{tasks[i].name}}" title="{{ __('Mark As Closed') }}">
+							</div>
+						</div>
+						<div class="text-muted ml-1">{%= frappe.datetime.global_date_format(tasks[i].date) %}</div>
+						{% if(tasks[i].allocated_to) { %}
+							<div class="text-muted  ml-1">
+								{{ __("Allocated To:") }}
+								{%= tasks[i].allocated_to %}
+							</div>
+						{% } %}
+						</div>
+			    {% } %}
+            {% } else { %}
+                <div class="single-activity no-activity text-muted">
+                    {{ __("No open task") }}
+                </div>
+		    {% } %}
+		</div>
+		<div class="open-events pl-1">
+			<div class="open-section-head">
+				<span class="ml-2">{{ __("Open Events") }}</span>
+			</div>
+			{% if (events.length) { %}
+                {% let icon_set = {"Sent/Received Email": "mail", "Call": "call", "Meeting": "share-people"}; %}
+                {% for(var i=0, l=events.length; i<l; i++) { %}
+                    <div class="single-activity">
+                        <div class="flex justify-between mb-2">
+                            <div class="row label-area font-md ml-1 title">
+                                <span class="mr-2">
+                                    <svg class="icon icon-sm">
+                                        <use href="#icon-{{ icon_set[events[i].event_category] || 'calendar' }}"></use>
+                                    </svg>
+                                </span>
+                                <a href="/app/event/{{ events[i].name }}" title="{{ __('Open Event') }}">
+                                    {%= events[i].subject %}
+                                </a>
+                            </div>
+                            <div class="checkbox">
+                                <input type="checkbox" class="completion-checkbox"
+                                    name="{{ events[i].name }}" title="{{ __('Mark As Closed') }}">
+                            </div>
+                        </div>
+                        <div class="text-muted ml-1">
+                            {%= frappe.datetime.global_date_format(events[i].starts_on) %}
+
+                            {% if (events[i].ends_on) { %}
+                                {% if (frappe.datetime.obj_to_user(events[i].starts_on) != frappe.datetime.obj_to_user(events[i].ends_on)) %}
+                                    -
+                                    {%= frappe.datetime.global_date_format(frappe.datetime.obj_to_user(events[i].ends_on)) %}
+                                    {%= frappe.datetime.get_time(events[i].ends_on) %}
+                                {% } else if (events[i].ends_on) { %}
+                                    -
+                                    {%= frappe.datetime.get_time(events[i].ends_on) %}
+                                {% } %}
+                            {% } %}
+
+                        </div>
+                    </div>
+                {% } %}
+            {% } else { %}
+            <div class="single-activity no-activity text-muted">
+                {{ __("No open event") }}
+            </div>
+		    {% } %}
+		</div>
+	</div>
+</div>
+
+
+<style>
+.open-activities {
+	min-height: 50px;
+	padding-left: 0px;
+	padding-bottom: 15px !important;
+}
+
+.open-activities .new-btn {
+	text-align: right;
+}
+
+.single-activity {
+	min-height: 90px;
+	border: 1px solid var(--border-color);
+	padding: 10px;
+	border-bottom: 0;
+	padding-right: 0;
+}
+
+.single-activity:last-child {
+	border-bottom: 1px solid var(--border-color);
+}
+
+.single-activity:hover .completion-checkbox{
+	display: block;
+}
+
+.completion-checkbox {
+	vertical-align: middle;
+	display: none;
+}
+
+.checkbox {
+	min-width: 22px;
+}
+
+.open-tasks {
+	width: 50%;
+}
+
+.open-tasks:first-child {
+	border-right: 0;
+}
+
+.open-events {
+	width: 50%;
+}
+
+.open-section-head {
+	background-color: var(--bg-color);
+	min-height: 30px;
+	border-bottom: 1px solid var(--border-color);
+	padding: 10px;
+	font-weight: bold;
+}
+
+.no-activity {
+    text-align: center;
+    padding-top: 30px;
+}
+
+.form-footer {
+	background-color: var(--bg-color);
+}
+</style>
\ No newline at end of file
diff --git a/erpnext/public/js/templates/crm_notes.html b/erpnext/public/js/templates/crm_notes.html
new file mode 100644
index 0000000..fddeb1c
--- /dev/null
+++ b/erpnext/public/js/templates/crm_notes.html
@@ -0,0 +1,74 @@
+<div class="notes-section col-xs-12">
+	<div class="new-btn pb-3">
+		<button class="btn btn-sm small new-note-btn mr-1">
+			<svg class="icon icon-sm">
+				<use href="#icon-add"></use>
+			</svg>
+			{{ __("New Note") }}
+		</button>
+	</div>
+	<div class="all-notes">
+		{% if (notes.length) { %}
+			{% for(var i=0, l=notes.length; i<l; i++) { %}
+				<div class="comment-content p-3 row" name="{{ notes[i].name }}">
+					<div class="mb-2 head col-xs-3">
+						<div class="row">
+							<div class="col-xs-2">
+								{{ frappe.avatar(notes[i].added_by) }}
+							</div>
+							<div class="col-xs-10">
+								<div class="mr-2 title font-weight-bold">
+									{{ strip_html(notes[i].added_by) }}
+								</div>
+								<div class="time small text-muted">
+									{{ frappe.datetime.global_date_format(notes[i].added_on) }}
+								</div>
+							</div>
+						</div>
+					</div>
+					<div class="content col-xs-8">
+						{{ notes[i].note }}
+					</div>
+					<div class="col-xs-1 text-right">
+						<span class="edit-note-btn btn btn-link">
+							<svg class="icon icon-sm"><use xlink:href="#icon-edit"></use></svg>
+						</span>
+						<span class="delete-note-btn  btn btn-link pl-2">
+							<svg class="icon icon-xs"><use xlink:href="#icon-delete"></use></svg>
+						</span>
+					</div>
+				</div>
+			{% } %}
+		{% } else { %}
+            <div class="no-activity text-muted pt-6">
+                {{ __("No Notes") }}
+            </div>
+		    {% } %}
+	</div>
+</div>
+
+<style>
+
+.comment-content {
+    border: 1px solid var(--border-color);
+	border-bottom: none;
+}
+
+.comment-content:last-child {
+    border-bottom: 1px solid var(--border-color);
+}
+
+.new-btn {
+	text-align: right;
+}
+
+.notes-section .no-activity {
+	min-height: 100px;
+	text-align: center;
+}
+
+.notes-section .btn {
+	padding: 0.2rem 0.2rem;
+}
+
+</style>
\ No newline at end of file
diff --git a/erpnext/public/js/utils/crm_activities.js b/erpnext/public/js/utils/crm_activities.js
new file mode 100644
index 0000000..bbd9ded
--- /dev/null
+++ b/erpnext/public/js/utils/crm_activities.js
@@ -0,0 +1,234 @@
+erpnext.utils.CRMActivities = class CRMActivities {
+	constructor(opts) {
+		$.extend(this, opts);
+	}
+
+	refresh() {
+		var me = this;
+		$(this.open_activities_wrapper).empty();
+		let cur_form_footer = this.form_wrapper.find('.form-footer');
+
+		// all activities
+		if (!$(this.all_activities_wrapper).find('.form-footer').length) {
+			this.all_activities_wrapper.empty();
+			$(cur_form_footer).appendTo(this.all_activities_wrapper);
+
+			// remove frappe-control class to avoid absolute position for action-btn
+			$(this.all_activities_wrapper).removeClass('frappe-control');
+			// hide new event button
+			$('.timeline-actions').find('.btn-default').hide();
+			// hide new comment box
+			$(".comment-box").hide();
+			// show only communications by default
+			$($('.timeline-content').find('.nav-link')[0]).tab('show');
+		}
+
+		// open activities
+		frappe.call({
+			method: "erpnext.crm.utils.get_open_activities",
+			args: {
+				ref_doctype: this.frm.doc.doctype,
+				ref_docname: this.frm.doc.name
+			},
+			callback: (r) => {
+				if (!r.exc) {
+					var activities_html = frappe.render_template('crm_activities', {
+						tasks: r.message.tasks,
+						events: r.message.events
+					});
+
+					$(activities_html).appendTo(me.open_activities_wrapper);
+
+					$(".open-tasks").find(".completion-checkbox").on("click", function() {
+						me.update_status(this, "ToDo");
+					});
+
+					$(".open-events").find(".completion-checkbox").on("click", function() {
+						me.update_status(this, "Event");
+					});
+
+					me.create_task();
+					me.create_event();
+				}
+			}
+		});
+	}
+
+	create_task () {
+		let me = this;
+		let _create_task = () => {
+			const args = {
+				doc: me.frm.doc,
+				frm: me.frm,
+				title: __("New Task")
+			};
+			let composer = new frappe.views.InteractionComposer(args);
+			composer.dialog.get_field('interaction_type').set_value("ToDo");
+			// hide column having interaction type field
+			$(composer.dialog.get_field('interaction_type').wrapper).closest('.form-column').hide();
+			// hide summary field
+			$(composer.dialog.get_field('summary').wrapper).closest('.form-section').hide();
+		};
+		$(".new-task-btn").click(_create_task);
+	}
+
+	create_event () {
+		let me = this;
+		let _create_event = () => {
+			const args = {
+				doc: me.frm.doc,
+				frm: me.frm,
+				title: __("New Event")
+			};
+			let composer = new frappe.views.InteractionComposer(args);
+			composer.dialog.get_field('interaction_type').set_value("Event");
+			$(composer.dialog.get_field('interaction_type').wrapper).hide();
+		};
+		$(".new-event-btn").click(_create_event);
+	}
+
+	async update_status (input_field, doctype) {
+		let completed = $(input_field).prop("checked") ? 1 : 0;
+		let docname = $(input_field).attr("name");
+		if (completed) {
+			await frappe.db.set_value(doctype, docname, "status", "Closed");
+			this.refresh();
+		}
+	}
+};
+
+erpnext.utils.CRMNotes = class CRMNotes {
+	constructor(opts) {
+		$.extend(this, opts);
+	}
+
+	refresh() {
+		var me = this;
+		this.notes_wrapper.find('.notes-section').remove();
+
+		let notes = this.frm.doc.notes || [];
+		notes.sort(
+			function(a, b) {
+				return new Date(b.added_on) - new Date(a.added_on);
+			}
+		);
+
+		let notes_html = frappe.render_template(
+			'crm_notes',
+			{
+				notes: notes
+			}
+		);
+		$(notes_html).appendTo(this.notes_wrapper);
+
+		this.add_note();
+
+		$(".notes-section").find(".edit-note-btn").on("click", function() {
+			me.edit_note(this);
+		});
+
+		$(".notes-section").find(".delete-note-btn").on("click", function() {
+			me.delete_note(this);
+		});
+	}
+
+
+	add_note () {
+		let me = this;
+		let _add_note = () => {
+			var d = new frappe.ui.Dialog({
+				title: __('Add a Note'),
+				fields: [
+					{
+						"label": "Note",
+						"fieldname": "note",
+						"fieldtype": "Text Editor",
+						"reqd": 1
+					}
+				],
+				primary_action: function() {
+					var data = d.get_values();
+					frappe.call({
+						method: "add_note",
+						doc: me.frm.doc,
+						args: {
+							note: data.note
+						},
+						freeze: true,
+						callback: function(r) {
+							if (!r.exc) {
+								me.frm.refresh_field("notes");
+								me.refresh();
+							}
+							d.hide();
+						}
+					});
+				},
+				primary_action_label: __('Add')
+			});
+			d.show();
+		};
+		$(".new-note-btn").click(_add_note);
+	}
+
+	edit_note (edit_btn) {
+		var me = this;
+		let row = $(edit_btn).closest('.comment-content');
+		let row_id = row.attr("name");
+		let row_content = $(row).find(".content").html();
+		if (row_content) {
+			var d = new frappe.ui.Dialog({
+				title: __('Edit Note'),
+				fields: [
+					{
+						"label": "Note",
+						"fieldname": "note",
+						"fieldtype": "Text Editor",
+						"default": row_content
+					}
+				],
+				primary_action: function() {
+					var data = d.get_values();
+					frappe.call({
+						method: "edit_note",
+						doc: me.frm.doc,
+						args: {
+							note: data.note,
+							row_id: row_id
+						},
+						freeze: true,
+						callback: function(r) {
+							if (!r.exc) {
+								me.frm.refresh_field("notes");
+								me.refresh();
+								d.hide();
+							}
+
+						}
+					});
+				},
+				primary_action_label: __('Done')
+			});
+			d.show();
+		}
+	}
+
+	delete_note (delete_btn) {
+		var me = this;
+		let row_id = $(delete_btn).closest('.comment-content').attr("name");
+		frappe.call({
+			method: "delete_note",
+			doc: me.frm.doc,
+			args: {
+				row_id: row_id
+			},
+			freeze: true,
+			callback: function(r) {
+				if (!r.exc) {
+					me.frm.refresh_field("notes");
+					me.refresh();
+				}
+			}
+		});
+	}
+};
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index 4fa4515..a513b8f 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -8,7 +8,6 @@
 from frappe.utils import flt, getdate, nowdate
 
 from erpnext.controllers.selling_controller import SellingController
-from erpnext.crm.utils import add_link_in_communication, copy_comments
 
 form_grid_templates = {"items": "templates/form_grid/item_grid.html"}
 
@@ -36,16 +35,6 @@
 
 		make_packing_list(self)
 
-	def after_insert(self):
-		if frappe.db.get_single_value("CRM Settings", "carry_forward_communication_and_comments"):
-			if self.opportunity:
-				copy_comments("Opportunity", self.opportunity, self)
-				add_link_in_communication("Opportunity", self.opportunity, self)
-
-			elif self.quotation_to == "Lead" and self.party_name:
-				copy_comments("Lead", self.party_name, self)
-				add_link_in_communication("Lead", self.party_name, self)
-
 	def validate_valid_till(self):
 		if self.valid_till and getdate(self.valid_till) < getdate(self.transaction_date):
 			frappe.throw(_("Valid till date cannot be before transaction date"))
diff --git a/erpnext/templates/utils.py b/erpnext/templates/utils.py
index 4295188..48b4480 100644
--- a/erpnext/templates/utils.py
+++ b/erpnext/templates/utils.py
@@ -34,7 +34,6 @@
 			status="Open",
 			title=subject,
 			contact_email=sender,
-			to_discuss=message,
 		)
 	)
 
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index 73cbcd4..cd1bf9f 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -5,7 +5,7 @@
 import frappe
 import frappe.share
 from frappe import _
-from frappe.utils import cint, cstr, flt, get_time, now_datetime
+from frappe.utils import cint, flt, get_time, now_datetime
 
 from erpnext.controllers.status_updater import StatusUpdater
 
@@ -30,64 +30,6 @@
 			except ValueError:
 				frappe.throw(_("Invalid Posting Time"))
 
-	def add_calendar_event(self, opts, force=False):
-		if (
-			cstr(self.contact_by) != cstr(self._prev.contact_by)
-			or cstr(self.contact_date) != cstr(self._prev.contact_date)
-			or force
-			or (hasattr(self, "ends_on") and cstr(self.ends_on) != cstr(self._prev.ends_on))
-		):
-
-			self.delete_events()
-			self._add_calendar_event(opts)
-
-	def delete_events(self):
-		participations = frappe.get_all(
-			"Event Participants",
-			filters={
-				"reference_doctype": self.doctype,
-				"reference_docname": self.name,
-				"parenttype": "Event",
-			},
-			fields=["name", "parent"],
-		)
-
-		if participations:
-			for participation in participations:
-				total_participants = frappe.get_all(
-					"Event Participants", filters={"parenttype": "Event", "parent": participation.parent}
-				)
-
-				if len(total_participants) <= 1:
-					frappe.db.sql("delete from `tabEvent` where name='%s'" % participation.parent)
-
-				frappe.db.sql("delete from `tabEvent Participants` where name='%s'" % participation.name)
-
-	def _add_calendar_event(self, opts):
-		opts = frappe._dict(opts)
-
-		if self.contact_date:
-			event = frappe.get_doc(
-				{
-					"doctype": "Event",
-					"owner": opts.owner or self.owner,
-					"subject": opts.subject,
-					"description": opts.description,
-					"starts_on": self.contact_date,
-					"ends_on": opts.ends_on,
-					"event_type": "Private",
-				}
-			)
-
-			event.append(
-				"event_participants", {"reference_doctype": self.doctype, "reference_docname": self.name}
-			)
-
-			event.insert(ignore_permissions=True)
-
-			if frappe.db.exists("User", self.contact_by):
-				frappe.share.add("Event", event.name, self.contact_by, flags={"ignore_share_permission": True})
-
 	def validate_uom_is_integer(self, uom_field, qty_fields):
 		validate_uom_is_integer(self, uom_field, qty_fields)