feat: Competitor Tagging in Opportunity and Quotation (#28050)

* feat: Competitor Tagging in Opportunity and Quotation

* fix: review changes

* fix: linter issue

* fix: section label

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
diff --git a/erpnext/crm/doctype/competitor/__init__.py b/erpnext/crm/doctype/competitor/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/crm/doctype/competitor/__init__.py
diff --git a/erpnext/crm/doctype/competitor/competitor.js b/erpnext/crm/doctype/competitor/competitor.js
new file mode 100644
index 0000000..a5b617d
--- /dev/null
+++ b/erpnext/crm/doctype/competitor/competitor.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Competitor', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/crm/doctype/competitor/competitor.json b/erpnext/crm/doctype/competitor/competitor.json
new file mode 100644
index 0000000..280441f
--- /dev/null
+++ b/erpnext/crm/doctype/competitor/competitor.json
@@ -0,0 +1,68 @@
+{
+ "actions": [],
+ "allow_rename": 1,
+ "autoname": "field:competitor_name",
+ "creation": "2021-10-21 10:28:52.071316",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "competitor_name",
+  "website"
+ ],
+ "fields": [
+  {
+   "fieldname": "competitor_name",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Competitor Name",
+   "reqd": 1,
+   "unique": 1
+  },
+  {
+   "allow_in_quick_entry": 1,
+   "fieldname": "website",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Website",
+   "options": "URL"
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2021-10-21 12:43:59.106807",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Competitor",
+ "naming_rule": "By fieldname",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Sales User",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/crm/doctype/competitor/competitor.py b/erpnext/crm/doctype/competitor/competitor.py
new file mode 100644
index 0000000..a292e461
--- /dev/null
+++ b/erpnext/crm/doctype/competitor/competitor.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+
+class Competitor(Document):
+	pass
diff --git a/erpnext/crm/doctype/competitor/test_competitor.py b/erpnext/crm/doctype/competitor/test_competitor.py
new file mode 100644
index 0000000..f77d7e6
--- /dev/null
+++ b/erpnext/crm/doctype/competitor/test_competitor.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+
+# import frappe
+import unittest
+
+
+class TestCompetitor(unittest.TestCase):
+	pass
diff --git a/erpnext/crm/doctype/competitor_detail/__init__.py b/erpnext/crm/doctype/competitor_detail/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/crm/doctype/competitor_detail/__init__.py
diff --git a/erpnext/crm/doctype/competitor_detail/competitor_detail.json b/erpnext/crm/doctype/competitor_detail/competitor_detail.json
new file mode 100644
index 0000000..9512b22
--- /dev/null
+++ b/erpnext/crm/doctype/competitor_detail/competitor_detail.json
@@ -0,0 +1,33 @@
+{
+ "actions": [],
+ "allow_rename": 1,
+ "creation": "2021-10-21 10:34:58.841689",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "competitor"
+ ],
+ "fields": [
+  {
+   "fieldname": "competitor",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Competitor",
+   "options": "Competitor",
+   "reqd": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-10-21 10:34:58.841689",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Competitor Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/crm/doctype/competitor_detail/competitor_detail.py b/erpnext/crm/doctype/competitor_detail/competitor_detail.py
new file mode 100644
index 0000000..0ef7560
--- /dev/null
+++ b/erpnext/crm/doctype/competitor_detail/competitor_detail.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+
+class CompetitorDetail(Document):
+	pass
diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json
index dc886b5..feb6044 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -23,7 +23,6 @@
   "status",
   "converted_by",
   "sales_stage",
-  "order_lost_reason",
   "first_response_time",
   "expected_closing",
   "next_contact",
@@ -64,7 +63,11 @@
   "transaction_date",
   "language",
   "amended_from",
-  "lost_reasons"
+  "lost_detail_section",
+  "lost_reasons",
+  "order_lost_reason",
+  "column_break_56",
+  "competitors"
  ],
  "fields": [
   {
@@ -154,10 +157,9 @@
    "reqd": 1
   },
   {
-   "depends_on": "eval:doc.status===\"Lost\"",
    "fieldname": "order_lost_reason",
    "fieldtype": "Small Text",
-   "label": "Lost Reason",
+   "label": "Detailed Reason",
    "no_copy": 1,
    "read_only": 1
   },
@@ -409,6 +411,7 @@
    "width": "150px"
   },
   {
+   "depends_on": "eval:doc.status===\"Lost\"",
    "fieldname": "lost_reasons",
    "fieldtype": "Table MultiSelect",
    "label": "Lost Reasons",
@@ -486,15 +489,33 @@
    "label": "Grand Total",
    "options": "currency",
    "read_only": 1
+  },
+  {
+   "fieldname": "lost_detail_section",
+   "fieldtype": "Section Break",
+   "label": "Lost Reasons"
+  },
+  {
+   "fieldname": "column_break_56",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "competitors",
+   "fieldtype": "Table MultiSelect",
+   "label": "Competitors",
+   "options": "Competitor Detail",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-info-sign",
  "idx": 195,
  "links": [],
- "modified": "2021-09-06 10:02:18.609136",
+ "migration_hash": "d87c646ea2579b6900197fd41e6c5c5a",
+ "modified": "2021-10-21 11:04:30.151379",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Opportunity",
+ "naming_rule": "By \"Naming Series\" field",
  "owner": "Administrator",
  "permissions": [
   {
diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py
index 90eae8d..0bef80a 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.py
+++ b/erpnext/crm/doctype/opportunity/opportunity.py
@@ -116,16 +116,20 @@
 			self.party_name = lead_name
 
 	@frappe.whitelist()
-	def declare_enquiry_lost(self, lost_reasons_list, detailed_reason=None):
+	def declare_enquiry_lost(self, lost_reasons_list, competitors, detailed_reason=None):
 		if not self.has_active_quotation():
-			frappe.db.set(self, 'status', 'Lost')
+			self.status = 'Lost'
+			self.lost_reasons = self.competitors = []
 
 			if detailed_reason:
-				frappe.db.set(self, 'order_lost_reason', detailed_reason)
+				self.order_lost_reason = detailed_reason
 
 			for reason in lost_reasons_list:
 				self.append('lost_reasons', reason)
 
+			for competitor in competitors:
+				self.append('competitors', competitor)
+
 			self.save()
 
 		else:
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index 43a4490..ad788e5 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -110,7 +110,8 @@
   "enq_det",
   "supplier_quotation",
   "opportunity",
-  "lost_reasons"
+  "lost_reasons",
+  "competitors"
  ],
  "fields": [
   {
@@ -946,6 +947,14 @@
    "label": "Bundle Items",
    "options": "fa fa-suitcase",
    "print_hide": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "competitors",
+   "fieldtype": "Table MultiSelect",
+   "label": "Competitors",
+   "options": "Competitor Detail",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-shopping-cart",
@@ -953,10 +962,12 @@
  "is_submittable": 1,
  "links": [],
  "max_attachments": 1,
- "modified": "2021-08-27 20:10:07.864951",
+ "migration_hash": "75a86a19f062c2257bcbc8e6e31c7f1e",
+ "modified": "2021-10-21 12:58:55.514512",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Quotation",
+ "naming_rule": "By \"Naming Series\" field",
  "owner": "Administrator",
  "permissions": [
   {
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index 31b62d6..c4752ae 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -68,7 +68,7 @@
 		opp.set_status(status=status, update=True)
 
 	@frappe.whitelist()
-	def declare_enquiry_lost(self, lost_reasons_list, detailed_reason=None):
+	def declare_enquiry_lost(self, lost_reasons_list, competitors, detailed_reason=None):
 		if not self.has_sales_order():
 			get_lost_reasons = frappe.get_list('Quotation Lost Reason',
 			fields = ["name"])
@@ -84,6 +84,9 @@
 				else:
 					frappe.throw(_("Invalid lost reason {0}, please create a new lost reason").format(frappe.bold(reason.get('lost_reason'))))
 
+			for competitor in competitors:
+				self.append('competitors', competitor)
+
 			self.update_opportunity('Lost')
 			self.update_lead()
 			self.save()
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index a86e604..2050478 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -474,33 +474,37 @@
 					"reqd": 1
 				},
 				{
+					"fieldtype": "Table MultiSelect",
+					"label": __("Competitors"),
+					"fieldname": "competitors",
+					"options": "Competitor Detail"
+				},
+				{
 					"fieldtype": "Text",
 					"label": __("Detailed Reason"),
 					"fieldname": "detailed_reason"
 				},
 			],
 			primary_action: function() {
-				var values = dialog.get_values();
-				var reasons = values["lost_reason"];
-				var detailed_reason = values["detailed_reason"];
+				let values = dialog.get_values();
 
 				frm.call({
 					doc: frm.doc,
 					method: 'declare_enquiry_lost',
 					args: {
-						'lost_reasons_list': reasons,
-						'detailed_reason': detailed_reason
+						'lost_reasons_list': values.lost_reason,
+						'competitors': values.competitors,
+						'detailed_reason': values.detailed_reason
 					},
 					callback: function(r) {
 						dialog.hide();
 						frm.reload_doc();
 					},
 				});
-				refresh_field("lost_reason");
 			},
 			primary_action_label: __('Declare Lost')
 		});
 
 		dialog.show();
 	}
-})
+})
\ No newline at end of file