diff --git a/crm/fcrm/doctype/crm_deal/api.py b/crm/fcrm/doctype/crm_deal/api.py
index 75a89de1..e37ca74d 100644
--- a/crm/fcrm/doctype/crm_deal/api.py
+++ b/crm/fcrm/doctype/crm_deal/api.py
@@ -2,6 +2,7 @@ import frappe
from frappe import _
from crm.api.doc import get_doctype_fields
+from crm.fcrm.doctype.crm_form_script.crm_form_script import get_form_script
@frappe.whitelist()
def get_deal(name):
@@ -27,5 +28,6 @@ def get_deal(name):
)
deal["doctype_fields"] = get_doctype_fields("CRM Deal")
- deal["doctype"] = "CRM Deal"
+ deal["doctype"] = "CRM Deal"
+ deal["_form_script"] = get_form_script('CRM Deal')
return deal
diff --git a/crm/fcrm/doctype/crm_form_script/__init__.py b/crm/fcrm/doctype/crm_form_script/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/crm/fcrm/doctype/crm_form_script/crm_form_script.js b/crm/fcrm/doctype/crm_form_script/crm_form_script.js
new file mode 100644
index 00000000..7f6f150e
--- /dev/null
+++ b/crm/fcrm/doctype/crm_form_script/crm_form_script.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+// frappe.ui.form.on("CRM Form Script", {
+// refresh(frm) {
+
+// },
+// });
diff --git a/crm/fcrm/doctype/crm_form_script/crm_form_script.json b/crm/fcrm/doctype/crm_form_script/crm_form_script.json
new file mode 100644
index 00000000..3fe64b37
--- /dev/null
+++ b/crm/fcrm/doctype/crm_form_script/crm_form_script.json
@@ -0,0 +1,70 @@
+{
+ "actions": [],
+ "allow_rename": 1,
+ "autoname": "prompt",
+ "creation": "2023-12-28 14:18:09.329868",
+ "doctype": "DocType",
+ "engine": "InnoDB",
+ "field_order": [
+ "dt",
+ "column_break_gboh",
+ "enabled",
+ "section_break_xeox",
+ "script"
+ ],
+ "fields": [
+ {
+ "fieldname": "column_break_gboh",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_xeox",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "dt",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "DocType",
+ "options": "DocType",
+ "reqd": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "enabled",
+ "fieldtype": "Check",
+ "label": "Enabled"
+ },
+ {
+ "fieldname": "script",
+ "fieldtype": "Code",
+ "label": "Script",
+ "options": "JS"
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2023-12-28 16:26:39.967069",
+ "modified_by": "Administrator",
+ "module": "FCRM",
+ "name": "CRM Form Script",
+ "naming_rule": "Set by user",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": []
+}
\ No newline at end of file
diff --git a/crm/fcrm/doctype/crm_form_script/crm_form_script.py b/crm/fcrm/doctype/crm_form_script/crm_form_script.py
new file mode 100644
index 00000000..32649d62
--- /dev/null
+++ b/crm/fcrm/doctype/crm_form_script/crm_form_script.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe.model.document import Document
+
+
+class CRMFormScript(Document):
+ def validate(self):
+ self.check_if_duplicate()
+
+ def check_if_duplicate(self):
+ """Check if there is already a script for this doctype"""
+ if self.dt and self.enabled:
+ filters = {
+ "dt": self.dt,
+ "enabled": 1,
+ }
+ if self.name:
+ filters["name"] = ["!=", self.name]
+
+ if frappe.db.exists("CRM Form Script", filters):
+ frappe.throw(
+ frappe._(
+ "Script already exists for this doctype and is enabled"
+ ),
+ frappe.DuplicateEntryError,
+ )
+
+def get_form_script(dt):
+ """Returns the script for the given doctype"""
+ FormScript = frappe.qb.DocType("CRM Form Script")
+ query = (
+ frappe.qb.from_(FormScript)
+ .select("script")
+ .where(FormScript.dt == dt)
+ .where(FormScript.enabled == 1)
+ .limit(1)
+ )
+
+ doc = query.run(as_dict=True)
+ if doc:
+ return doc[0].script
+ else:
+ return None
diff --git a/crm/fcrm/doctype/crm_form_script/test_crm_form_script.py b/crm/fcrm/doctype/crm_form_script/test_crm_form_script.py
new file mode 100644
index 00000000..ae222e72
--- /dev/null
+++ b/crm/fcrm/doctype/crm_form_script/test_crm_form_script.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+
+# import frappe
+from frappe.tests.utils import FrappeTestCase
+
+
+class TestCRMFormScript(FrappeTestCase):
+ pass
diff --git a/crm/fcrm/doctype/crm_lead/api.py b/crm/fcrm/doctype/crm_lead/api.py
index 0cb80556..9758d045 100644
--- a/crm/fcrm/doctype/crm_lead/api.py
+++ b/crm/fcrm/doctype/crm_lead/api.py
@@ -2,6 +2,7 @@ import frappe
from frappe import _
from crm.api.doc import get_doctype_fields
+from crm.fcrm.doctype.crm_form_script.crm_form_script import get_form_script
@frappe.whitelist()
def get_lead(name):
@@ -16,4 +17,5 @@ def get_lead(name):
lead["doctype_fields"] = get_doctype_fields("CRM Lead")
lead["doctype"] = "CRM Lead"
- return lead
\ No newline at end of file
+ lead["_form_script"] = get_form_script('CRM Lead')
+ return lead
diff --git a/frontend/src/components/CustomActions.vue b/frontend/src/components/CustomActions.vue
new file mode 100644
index 00000000..7a674053
--- /dev/null
+++ b/frontend/src/components/CustomActions.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
diff --git a/frontend/src/pages/Deal.vue b/frontend/src/pages/Deal.vue
index f5267a52..3a1602ff 100644
--- a/frontend/src/pages/Deal.vue
+++ b/frontend/src/pages/Deal.vue
@@ -4,33 +4,10 @@
-
-
-
+
{
- let assignees = JSON.parse(data._assign) || []
- data._assignedTo = assignees.map((user) => ({
- name: user,
- image: getUser(user).user_image,
- label: getUser(user).full_name,
- }))
+ setupAssignees(data)
+ setupCustomActions(data, {
+ doc: data,
+ $dialog,
+ router,
+ updateField,
+ deleteDoc: deleteDeal,
+ call,
+ })
},
})
diff --git a/frontend/src/pages/Lead.vue b/frontend/src/pages/Lead.vue
index 78488952..819048cb 100644
--- a/frontend/src/pages/Lead.vue
+++ b/frontend/src/pages/Lead.vue
@@ -4,33 +4,10 @@
-
-
-
+
{
- let assignees = JSON.parse(data._assign) || []
- data._assignedTo = assignees.map((user) => ({
- name: user,
- image: getUser(user).user_image,
- label: getUser(user).full_name,
- }))
+ setupAssignees(data)
+ setupCustomActions(data, {
+ doc: data,
+ $dialog,
+ router,
+ updateField,
+ deleteDoc: deleteLead,
+ call,
+ })
},
})
diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js
index cd284afb..6164cc22 100644
--- a/frontend/src/utils/index.js
+++ b/frontend/src/utils/index.js
@@ -1,8 +1,9 @@
import TaskStatusIcon from '@/components/Icons/TaskStatusIcon.vue'
import TaskPriorityIcon from '@/components/Icons/TaskPriorityIcon.vue'
import { useDateFormat, useTimeAgo } from '@vueuse/core'
+import { usersStore } from '@/stores/users'
import { toast } from 'frappe-ui'
-import { h, computed } from 'vue'
+import { h } from 'vue'
export function createToast(options) {
toast({
@@ -112,3 +113,19 @@ export function validateEmail(email) {
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return regExp.test(email)
}
+
+export function setupAssignees(data) {
+ let { getUser } = usersStore()
+ let assignees = JSON.parse(data._assign) || []
+ data._assignedTo = assignees.map((user) => ({
+ name: user,
+ image: getUser(user).user_image,
+ label: getUser(user).full_name,
+ }))
+}
+
+export function setupCustomActions(data, obj) {
+ let script = new Function(data._form_script + '\nreturn setupForm')()
+ let formScript = script(obj)
+ data._customActions = formScript?.actions || []
+}
\ No newline at end of file