diff --git a/crm/api/assignment_rule.py b/crm/api/assignment_rule.py new file mode 100644 index 00000000..824474f6 --- /dev/null +++ b/crm/api/assignment_rule.py @@ -0,0 +1,32 @@ +import frappe + + +@frappe.whitelist() +def get_assignment_rules_list(): + assignment_rules = [] + for docname in frappe.get_all( + "Assignment Rule", filters={"document_type": ["in", ["CRM Lead", "CRM Deal"]]} + ): + doc = frappe.get_value( + "Assignment Rule", + docname, + fieldname=[ + "name", + "description", + "disabled", + "priority", + ], + as_dict=True, + ) + users_exists = bool(frappe.db.exists("Assignment Rule User", {"parent": docname.name})) + assignment_rules.append({**doc, "users_exists": users_exists}) + return assignment_rules + + +@frappe.whitelist() +def duplicate_assignment_rule(docname, new_name): + doc = frappe.get_doc("Assignment Rule", docname) + doc.name = new_name + doc.assignment_rule_name = new_name + doc.insert() + return doc diff --git a/crm/install.py b/crm/install.py index cced779d..8d72a464 100644 --- a/crm/install.py +++ b/crm/install.py @@ -25,6 +25,8 @@ def after_install(force=False): add_standard_dropdown_items() add_default_scripts() create_default_manager_dashboard(force) + create_assignment_rule_custom_fields() + add_assignment_rule_property_setters() frappe.db.commit() @@ -421,3 +423,80 @@ def add_default_scripts(): for doctype in ["CRM Lead", "CRM Deal"]: create_product_details_script(doctype) create_forecasting_script() + + +def add_assignment_rule_property_setters(): + """Add a property setter to the Assignment Rule DocType for assign_condition and unassign_condition.""" + + default_fields = { + "doctype": "Property Setter", + "doctype_or_field": "DocField", + "doc_type": "Assignment Rule", + "property_type": "Data", + "is_system_generated": 1, + } + + if not frappe.db.exists("Property Setter", {"name": "Assignment Rule-assign_condition-depends_on"}): + frappe.get_doc( + { + **default_fields, + "name": "Assignment Rule-assign_condition-depends_on", + "field_name": "assign_condition", + "property": "depends_on", + "value": "eval: !doc.assign_condition_json", + } + ).insert() + else: + frappe.db.set_value( + "Property Setter", + {"name": "Assignment Rule-assign_condition-depends_on"}, + "value", + "eval: !doc.assign_condition_json", + ) + if not frappe.db.exists("Property Setter", {"name": "Assignment Rule-unassign_condition-depends_on"}): + frappe.get_doc( + { + **default_fields, + "name": "Assignment Rule-unassign_condition-depends_on", + "field_name": "unassign_condition", + "property": "depends_on", + "value": "eval: !doc.unassign_condition_json", + } + ).insert() + else: + frappe.db.set_value( + "Property Setter", + {"name": "Assignment Rule-unassign_condition-depends_on"}, + "value", + "eval: !doc.unassign_condition_json", + ) + + +def create_assignment_rule_custom_fields(): + if not frappe.get_meta("Assignment Rule").has_field("assign_condition_json"): + click.secho("* Installing Custom Fields in Assignment Rule") + + create_custom_fields( + { + "Assignment Rule": [ + { + "description": "Autogenerated field by CRM App", + "fieldname": "assign_condition_json", + "fieldtype": "Code", + "label": "Assign Condition JSON", + "insert_after": "assign_condition", + "depends_on": "eval: doc.assign_condition_json", + }, + { + "description": "Autogenerated field by CRM App", + "fieldname": "unassign_condition_json", + "fieldtype": "Code", + "label": "Unassign Condition JSON", + "insert_after": "unassign_condition", + "depends_on": "eval: doc.unassign_condition_json", + }, + ], + } + ) + + frappe.clear_cache(doctype="Assignment Rule") diff --git a/crm/locale/pt.po b/crm/locale/pt.po index 9fae951a..421be756 100644 --- a/crm/locale/pt.po +++ b/crm/locale/pt.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: shariq@frappe.io\n" "POT-Creation-Date: 2025-09-14 09:35+0000\n" -"PO-Revision-Date: 2025-09-16 20:02\n" +"PO-Revision-Date: 2025-09-17 20:27\n" "Last-Translator: shariq@frappe.io\n" "Language-Team: Portuguese\n" "MIME-Version: 1.0\n" @@ -588,7 +588,7 @@ msgstr "Atribuído a" #: frontend/src/components/Settings/AssignmentRules/AssigneeRules.vue:5 msgid "Assignee Rules" -msgstr "" +msgstr "Regras de Atribuição" #: frontend/src/components/Settings/AssignmentRules/AssigneeRules.vue:75 msgid "Assignees" diff --git a/crm/patches.txt b/crm/patches.txt index c038f250..78a09165 100644 --- a/crm/patches.txt +++ b/crm/patches.txt @@ -15,4 +15,5 @@ crm.patches.v1_0.move_twilio_agent_to_telephony_agent crm.patches.v1_0.create_default_scripts # 13-06-2025 crm.patches.v1_0.update_deal_status_probabilities crm.patches.v1_0.update_deal_status_type -crm.patches.v1_0.create_default_lost_reasons \ No newline at end of file +crm.patches.v1_0.create_default_lost_reasons +crm.patches.v1_0.add_fields_in_assignment_rule diff --git a/crm/patches/v1_0/add_fields_in_assignment_rule.py b/crm/patches/v1_0/add_fields_in_assignment_rule.py new file mode 100644 index 00000000..72e21a6b --- /dev/null +++ b/crm/patches/v1_0/add_fields_in_assignment_rule.py @@ -0,0 +1,9 @@ +from crm.install import ( + add_assignment_rule_property_setters, + create_assignment_rule_custom_fields, +) + + +def execute(): + create_assignment_rule_custom_fields() + add_assignment_rule_property_setters() diff --git a/frontend/.gitignore b/frontend/.gitignore index 53f7466a..ec3e7197 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -2,4 +2,5 @@ node_modules .DS_Store dist dist-ssr -*.local \ No newline at end of file +*.local +components.d.ts \ No newline at end of file diff --git a/frontend/src/components/ConditionsFilter/CFCondition.vue b/frontend/src/components/ConditionsFilter/CFCondition.vue new file mode 100644 index 00000000..943ad231 --- /dev/null +++ b/frontend/src/components/ConditionsFilter/CFCondition.vue @@ -0,0 +1,469 @@ + + + diff --git a/frontend/src/components/ConditionsFilter/CFConditions.vue b/frontend/src/components/ConditionsFilter/CFConditions.vue new file mode 100644 index 00000000..03b50269 --- /dev/null +++ b/frontend/src/components/ConditionsFilter/CFConditions.vue @@ -0,0 +1,142 @@ + + + diff --git a/frontend/src/components/ConditionsFilter/filterableFields.ts b/frontend/src/components/ConditionsFilter/filterableFields.ts new file mode 100644 index 00000000..16bead91 --- /dev/null +++ b/frontend/src/components/ConditionsFilter/filterableFields.ts @@ -0,0 +1,17 @@ +import { createResource } from 'frappe-ui' + +export const filterableFields = createResource({ + url: 'crm.api.doc.get_filterable_fields', + transform: (data) => { + data = data + .filter((field) => !field.fieldname.startsWith('_')) + .map((field) => { + return { + label: field.label, + value: field.fieldname, + ...field, + } + }) + return data + }, +}) diff --git a/frontend/src/components/Icons/SettingsIcon2.vue b/frontend/src/components/Icons/SettingsIcon2.vue new file mode 100644 index 00000000..cd7d77da --- /dev/null +++ b/frontend/src/components/Icons/SettingsIcon2.vue @@ -0,0 +1,19 @@ + diff --git a/frontend/src/components/Settings/AssignmentRules/AssigneeSearch.vue b/frontend/src/components/Settings/AssignmentRules/AssigneeSearch.vue new file mode 100644 index 00000000..6d5a6bfc --- /dev/null +++ b/frontend/src/components/Settings/AssignmentRules/AssigneeSearch.vue @@ -0,0 +1,166 @@ + + + diff --git a/frontend/src/components/Settings/AssignmentRules/AssignmentRuleListItem.vue b/frontend/src/components/Settings/AssignmentRules/AssignmentRuleListItem.vue new file mode 100644 index 00000000..01336adc --- /dev/null +++ b/frontend/src/components/Settings/AssignmentRules/AssignmentRuleListItem.vue @@ -0,0 +1,204 @@ + + + diff --git a/frontend/src/components/Settings/AssignmentRules/AssignmentRulePage.vue b/frontend/src/components/Settings/AssignmentRules/AssignmentRulePage.vue new file mode 100644 index 00000000..4b77e921 --- /dev/null +++ b/frontend/src/components/Settings/AssignmentRules/AssignmentRulePage.vue @@ -0,0 +1,19 @@ + + + diff --git a/frontend/src/components/Settings/AssignmentRules/AssignmentRulesList.vue b/frontend/src/components/Settings/AssignmentRules/AssignmentRulesList.vue new file mode 100644 index 00000000..d911c335 --- /dev/null +++ b/frontend/src/components/Settings/AssignmentRules/AssignmentRulesList.vue @@ -0,0 +1,41 @@ + + + diff --git a/frontend/src/components/Settings/AssignmentRules/AssignmentRulesSection.vue b/frontend/src/components/Settings/AssignmentRules/AssignmentRulesSection.vue new file mode 100644 index 00000000..7d37c95a --- /dev/null +++ b/frontend/src/components/Settings/AssignmentRules/AssignmentRulesSection.vue @@ -0,0 +1,96 @@ + + + diff --git a/frontend/src/components/Settings/AssignmentRules/AssignmentSchedule.vue b/frontend/src/components/Settings/AssignmentRules/AssignmentSchedule.vue new file mode 100644 index 00000000..e54b7535 --- /dev/null +++ b/frontend/src/components/Settings/AssignmentRules/AssignmentSchedule.vue @@ -0,0 +1,85 @@ + + + diff --git a/frontend/src/components/Settings/AssignmentRules/AssignmentScheduleItem.vue b/frontend/src/components/Settings/AssignmentRules/AssignmentScheduleItem.vue new file mode 100644 index 00000000..6f443f06 --- /dev/null +++ b/frontend/src/components/Settings/AssignmentRules/AssignmentScheduleItem.vue @@ -0,0 +1,42 @@ + + + diff --git a/frontend/src/components/Settings/Settings.vue b/frontend/src/components/Settings/Settings.vue index ed5d4a15..fdbdc549 100644 --- a/frontend/src/components/Settings/Settings.vue +++ b/frontend/src/components/Settings/Settings.vue @@ -3,6 +3,7 @@ v-model="showSettings" :options="{ size: '5xl' }" @close="activeSettingsPage = ''" + :disableOutsideClickToClose="disableSettingModalOutsideClick" >