From 252fe05edc0768e2d59f9e400d0dcfa773918282 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Mon, 30 Jun 2025 17:43:42 +0530 Subject: [PATCH 01/11] feat: created lost reason doctype (cherry picked from commit 5d01b88a1e949f8388d8ca9f3e6ef62fe30a977a) --- crm/fcrm/doctype/crm_deal/crm_deal.json | 9 ++- .../crm_lead_source/crm_lead_source.json | 17 +++- crm/fcrm/doctype/crm_lost_reason/__init__.py | 0 .../crm_lost_reason/crm_lost_reason.js | 8 ++ .../crm_lost_reason/crm_lost_reason.json | 79 +++++++++++++++++++ .../crm_lost_reason/crm_lost_reason.py | 9 +++ .../crm_lost_reason/test_crm_lost_reason.py | 30 +++++++ 7 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 crm/fcrm/doctype/crm_lost_reason/__init__.py create mode 100644 crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.js create mode 100644 crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.json create mode 100644 crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.py create mode 100644 crm/fcrm/doctype/crm_lost_reason/test_crm_lost_reason.py diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.json b/crm/fcrm/doctype/crm_deal/crm_deal.json index bbef186d..6344d6d9 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.json +++ b/crm/fcrm/doctype/crm_deal/crm_deal.json @@ -14,6 +14,7 @@ "column_break_ijan", "status", "deal_owner", + "lost_reason", "section_break_jgpm", "probability", "deal_value", @@ -391,12 +392,18 @@ { "fieldname": "column_break_kpxa", "fieldtype": "Column Break" + }, + { + "fieldname": "lost_reason", + "fieldtype": "Link", + "label": "Lost Reason", + "options": "CRM Lost Reason" } ], "grid_page_length": 50, "index_web_pages_for_search": 1, "links": [], - "modified": "2025-06-16 11:42:49.413483", + "modified": "2025-06-30 17:40:28.673539", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Deal", diff --git a/crm/fcrm/doctype/crm_lead_source/crm_lead_source.json b/crm/fcrm/doctype/crm_lead_source/crm_lead_source.json index 416ccd7e..87fb72f3 100644 --- a/crm/fcrm/doctype/crm_lead_source/crm_lead_source.json +++ b/crm/fcrm/doctype/crm_lead_source/crm_lead_source.json @@ -27,9 +27,10 @@ "label": "Details" } ], + "grid_page_length": 50, "index_web_pages_for_search": 1, "links": [], - "modified": "2025-01-02 22:13:30.498404", + "modified": "2025-06-30 16:53:51.721752", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Lead Source", @@ -44,7 +45,7 @@ "print": 1, "read": 1, "report": 1, - "role": "Sales User", + "role": "System Manager", "share": 1, "write": 1 }, @@ -60,6 +61,15 @@ "share": 1, "write": 1 }, + { + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales User", + "share": 1 + }, { "email": 1, "export": 1, @@ -71,7 +81,8 @@ } ], "quick_entry": 1, + "row_format": "Dynamic", "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/crm/fcrm/doctype/crm_lost_reason/__init__.py b/crm/fcrm/doctype/crm_lost_reason/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.js b/crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.js new file mode 100644 index 00000000..effd824a --- /dev/null +++ b/crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.js @@ -0,0 +1,8 @@ +// Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("CRM Lost Reason", { +// refresh(frm) { + +// }, +// }); diff --git a/crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.json b/crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.json new file mode 100644 index 00000000..ce774060 --- /dev/null +++ b/crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.json @@ -0,0 +1,79 @@ +{ + "actions": [], + "allow_rename": 1, + "autoname": "field:lost_reason", + "creation": "2025-06-30 16:51:31.082360", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "lost_reason", + "description" + ], + "fields": [ + { + "fieldname": "lost_reason", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Lost Reason", + "reqd": 1, + "unique": 1 + }, + { + "fieldname": "description", + "fieldtype": "Text Editor", + "label": "Description" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "links": [], + "modified": "2025-06-30 16:59:15.094049", + "modified_by": "Administrator", + "module": "FCRM", + "name": "CRM Lost Reason", + "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, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales User", + "share": 1, + "write": 1 + } + ], + "quick_entry": 1, + "row_format": "Dynamic", + "sort_field": "creation", + "sort_order": "DESC", + "states": [] +} diff --git a/crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.py b/crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.py new file mode 100644 index 00000000..b43a399c --- /dev/null +++ b/crm/fcrm/doctype/crm_lost_reason/crm_lost_reason.py @@ -0,0 +1,9 @@ +# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class CRMLostReason(Document): + pass diff --git a/crm/fcrm/doctype/crm_lost_reason/test_crm_lost_reason.py b/crm/fcrm/doctype/crm_lost_reason/test_crm_lost_reason.py new file mode 100644 index 00000000..2f353477 --- /dev/null +++ b/crm/fcrm/doctype/crm_lost_reason/test_crm_lost_reason.py @@ -0,0 +1,30 @@ +# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +from frappe.tests import IntegrationTestCase, UnitTestCase + + +# On IntegrationTestCase, the doctype test records and all +# link-field test record dependencies are recursively loaded +# Use these module variables to add/remove to/from that list +EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"] +IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"] + + +class UnitTestCRMLostReason(UnitTestCase): + """ + Unit tests for CRMLostReason. + Use this class for testing individual functions and methods. + """ + + pass + + +class IntegrationTestCRMLostReason(IntegrationTestCase): + """ + Integration tests for CRMLostReason. + Use this class for testing interactions between multiple components. + """ + + pass From 6aa4a03b0f3e8073b51ded14a88bfa059be0d960 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Tue, 1 Jul 2025 16:53:40 +0530 Subject: [PATCH 02/11] chore: resolved conflict (cherry picked from commit 92d728072843b1449cb2e2e626cde7a218e68530) --- crm/fcrm/doctype/crm_deal/crm_deal.json | 11 ++++++++++- crm/fcrm/doctype/crm_deal/crm_deal.py | 11 +++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.json b/crm/fcrm/doctype/crm_deal/crm_deal.json index 6344d6d9..121c5e95 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.json +++ b/crm/fcrm/doctype/crm_deal/crm_deal.json @@ -15,6 +15,7 @@ "status", "deal_owner", "lost_reason", + "other_lost_reason", "section_break_jgpm", "probability", "deal_value", @@ -397,13 +398,21 @@ "fieldname": "lost_reason", "fieldtype": "Link", "label": "Lost Reason", + "mandatory_depends_on": "eval: doc.status == \"Lost\"", "options": "CRM Lost Reason" + }, + { + "depends_on": "eval: doc.lost_reason == \"Other\"", + "fieldname": "other_lost_reason", + "fieldtype": "Data", + "label": "Specify Other Reason", + "mandatory_depends_on": "eval: doc.lost_reason == \"Other\"" } ], "grid_page_length": 50, "index_web_pages_for_search": 1, "links": [], - "modified": "2025-06-30 17:40:28.673539", + "modified": "2025-06-30 17:53:23.408301", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Deal", diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.py b/crm/fcrm/doctype/crm_deal/crm_deal.py index 9afab159..97b09523 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.py +++ b/crm/fcrm/doctype/crm_deal/crm_deal.py @@ -25,6 +25,7 @@ class CRMDeal(Document): if self.has_value_changed("status"): add_status_change_log(self) self.validate_forcasting_fields() + self.validate_lost_reason() def after_insert(self): if self.deal_owner: @@ -149,6 +150,16 @@ class CRMDeal(Document): if not self.close_date: frappe.throw(_("Close Date is required."), frappe.MandatoryError) + def validate_lost_reason(self): + """ + Validate the lost reason if the status is set to "Lost". + """ + if self.status == "Lost": + if not self.lost_reason: + frappe.throw(_("Please specify a reason for losing the deal."), frappe.ValidationError) + elif self.lost_reason == "Other" and not self.other_lost_reason: + frappe.throw(_("Please specify the reason for losing the deal."), frappe.ValidationError) + @staticmethod def default_list_data(): columns = [ From e0cdeea2f9c6b223ad65ac98c2640faf102068ba Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 2 Jul 2025 11:10:53 +0530 Subject: [PATCH 03/11] fix: made lost notes as text and non mandatory if lost reason is not Other (cherry picked from commit 97b2253e9d464e5a25dd1de8ffadd9d513cb3fda) --- crm/fcrm/doctype/crm_deal/crm_deal.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.json b/crm/fcrm/doctype/crm_deal/crm_deal.json index 121c5e95..6b7ce0fe 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.json +++ b/crm/fcrm/doctype/crm_deal/crm_deal.json @@ -15,7 +15,7 @@ "status", "deal_owner", "lost_reason", - "other_lost_reason", + "lost_notes", "section_break_jgpm", "probability", "deal_value", @@ -402,17 +402,16 @@ "options": "CRM Lost Reason" }, { - "depends_on": "eval: doc.lost_reason == \"Other\"", - "fieldname": "other_lost_reason", - "fieldtype": "Data", - "label": "Specify Other Reason", + "fieldname": "lost_notes", + "fieldtype": "Text", + "label": "Lost Notes", "mandatory_depends_on": "eval: doc.lost_reason == \"Other\"" } ], "grid_page_length": 50, "index_web_pages_for_search": 1, "links": [], - "modified": "2025-06-30 17:53:23.408301", + "modified": "2025-07-02 11:07:50.192089", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Deal", From 040692c13cc4aea846062b4ca8e55d1359543988 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 2 Jul 2025 13:58:51 +0530 Subject: [PATCH 04/11] fix: removed unused triggerOnChange (cherry picked from commit 7730e46cfc2c0886c9bb1237d1558c31a05be712) --- frontend/src/components/Modals/DealModal.vue | 8 ++------ frontend/src/components/Modals/LeadModal.vue | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/Modals/DealModal.vue b/frontend/src/components/Modals/DealModal.vue index 7ccb128f..c9436e76 100644 --- a/frontend/src/components/Modals/DealModal.vue +++ b/frontend/src/components/Modals/DealModal.vue @@ -98,11 +98,7 @@ const show = defineModel() const router = useRouter() const error = ref(null) -const { - document: deal, - triggerOnChange, - triggerOnBeforeCreate, -} = useDocument('CRM Deal') +const { document: deal, triggerOnBeforeCreate } = useDocument('CRM Deal') const hasOrganizationSections = ref(true) const hasContactSections = ref(true) @@ -172,7 +168,7 @@ const tabs = createResource({ }) const dealStatuses = computed(() => { - let statuses = statusOptions('deal', null, [], triggerOnChange) + let statuses = statusOptions('deal') if (!deal.doc.status) { deal.doc.status = statuses[0].value } diff --git a/frontend/src/components/Modals/LeadModal.vue b/frontend/src/components/Modals/LeadModal.vue index 7c2dc728..9eb6ce50 100644 --- a/frontend/src/components/Modals/LeadModal.vue +++ b/frontend/src/components/Modals/LeadModal.vue @@ -74,14 +74,10 @@ const router = useRouter() const error = ref(null) const isLeadCreating = ref(false) -const { - document: lead, - triggerOnChange, - triggerOnBeforeCreate, -} = useDocument('CRM Lead') +const { document: lead, triggerOnBeforeCreate } = useDocument('CRM Lead') const leadStatuses = computed(() => { - let statuses = statusOptions('lead', null, [], triggerOnChange) + let statuses = statusOptions('lead') if (!lead.doc.status) { lead.doc.status = statuses?.[0]?.value } From 6647a834859db155af8c974d26505e7eee2c35e3 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 2 Jul 2025 13:59:34 +0530 Subject: [PATCH 05/11] fix: renamed other_lost_reason to lost_notes (cherry picked from commit 5bbec00803e299c3d997bd5d3335ef2a4ab78028) --- crm/fcrm/doctype/crm_deal/crm_deal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.py b/crm/fcrm/doctype/crm_deal/crm_deal.py index 97b09523..3022e6a7 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.py +++ b/crm/fcrm/doctype/crm_deal/crm_deal.py @@ -157,7 +157,7 @@ class CRMDeal(Document): if self.status == "Lost": if not self.lost_reason: frappe.throw(_("Please specify a reason for losing the deal."), frappe.ValidationError) - elif self.lost_reason == "Other" and not self.other_lost_reason: + elif self.lost_reason == "Other" and not self.lost_notes: frappe.throw(_("Please specify the reason for losing the deal."), frappe.ValidationError) @staticmethod From 9b315c2e0ccb431e44e5d48963214e058711eb15 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 2 Jul 2025 14:10:14 +0530 Subject: [PATCH 06/11] refactor: statusOptions code (cherry picked from commit 881126c7f1145fb2db1143b63c1e0f2f81ebb2ea) --- frontend/src/pages/Deal.vue | 12 +++++++++--- frontend/src/pages/Lead.vue | 12 +++++++++--- frontend/src/pages/MobileDeal.vue | 12 +++++++++--- frontend/src/pages/MobileLead.vue | 12 +++++++++--- frontend/src/stores/statuses.js | 16 ++-------------- 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/frontend/src/pages/Deal.vue b/frontend/src/pages/Deal.vue index c21400f6..baaf0a53 100644 --- a/frontend/src/pages/Deal.vue +++ b/frontend/src/pages/Deal.vue @@ -26,9 +26,10 @@ :options=" statusOptions( 'deal', - document, - deal.data._customStatuses, - triggerOnChange, + document.statuses?.length + ? document.statuses + : deal.data._customStatuses, + triggerStatusChange, ) " > @@ -755,6 +756,11 @@ const { assignees, document, triggerOnChange } = useDocument( props.dealId, ) +async function triggerStatusChange(value) { + await triggerOnChange('status', value) + document.save.submit() +} + function reloadAssignees(data) { if (data?.hasOwnProperty('deal_owner')) { assignees.reload() diff --git a/frontend/src/pages/Lead.vue b/frontend/src/pages/Lead.vue index 1b830319..16b74414 100644 --- a/frontend/src/pages/Lead.vue +++ b/frontend/src/pages/Lead.vue @@ -26,9 +26,10 @@ :options=" statusOptions( 'lead', - document, - lead.data._customStatuses, - triggerOnChange, + document.statuses?.length + ? document.statuses + : lead.data._customStatuses, + triggerStatusChange, ) " > @@ -320,6 +321,11 @@ const { triggerOnChange, assignees, document } = useDocument( props.leadId, ) +async function triggerStatusChange(value) { + await triggerOnChange('status', value) + document.save.submit() +} + const lead = createResource({ url: 'crm.fcrm.doctype.crm_lead.api.get_lead', params: { name: props.leadId }, diff --git a/frontend/src/pages/MobileDeal.vue b/frontend/src/pages/MobileDeal.vue index 1920266f..1039b387 100644 --- a/frontend/src/pages/MobileDeal.vue +++ b/frontend/src/pages/MobileDeal.vue @@ -14,9 +14,10 @@ :options=" statusOptions( 'deal', - document, - deal.data._customStatuses, - triggerOnChange, + document.statuses?.length + ? document.statuses + : deal.data._customStatuses, + triggerStatusChange, ) " > @@ -624,6 +625,11 @@ const { assignees, document, triggerOnChange } = useDocument( props.dealId, ) +async function triggerStatusChange(value) { + await triggerOnChange('status', value) + document.save.submit() +} + function reloadAssignees(data) { if (data?.hasOwnProperty('deal_owner')) { assignees.reload() diff --git a/frontend/src/pages/MobileLead.vue b/frontend/src/pages/MobileLead.vue index 21743037..0a83e0ec 100644 --- a/frontend/src/pages/MobileLead.vue +++ b/frontend/src/pages/MobileLead.vue @@ -14,9 +14,10 @@ :options=" statusOptions( 'lead', - document, - lead.data._customStatuses, - triggerOnChange, + document.statuses?.length + ? document.statuses + : lead.data._customStatuses, + triggerStatusChange, ) " > @@ -473,6 +474,11 @@ const { assignees, document, triggerOnChange } = useDocument( props.leadId, ) +async function triggerStatusChange(value) { + await triggerOnChange('status', value) + document.save.submit() +} + function reloadAssignees(data) { if (data?.hasOwnProperty('lead_owner')) { assignees.reload() diff --git a/frontend/src/stores/statuses.js b/frontend/src/stores/statuses.js index 0bcdbf3d..637c8d2f 100644 --- a/frontend/src/stores/statuses.js +++ b/frontend/src/stores/statuses.js @@ -77,19 +77,10 @@ export const statusesStore = defineStore('crm-statuses', () => { return communicationStatuses[name] } - function statusOptions( - doctype, - document, - statuses = [], - triggerOnChange = null, - ) { + function statusOptions(doctype, statuses = [], triggerStatusChange = null) { let statusesByName = doctype == 'deal' ? dealStatusesByName : leadStatusesByName - if (document?.statuses?.length) { - statuses = document.statuses - } - if (statuses?.length) { statusesByName = statuses.reduce((acc, status) => { acc[status] = statusesByName[status] @@ -104,11 +95,8 @@ export const statusesStore = defineStore('crm-statuses', () => { value: statusesByName[status]?.name, icon: () => h(IndicatorIcon, { class: statusesByName[status]?.color }), onClick: async () => { + await triggerStatusChange?.(statusesByName[status]?.name) capture('status_changed', { doctype, status }) - if (document) { - await triggerOnChange?.('status', statusesByName[status]?.name) - document.save.submit() - } }, }) } From a7bc3abcdd4dd3034b5855ebe8e9beff0f73014a Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 2 Jul 2025 14:11:11 +0530 Subject: [PATCH 07/11] fix: show lost reason modal if status changed to lost (cherry picked from commit d89c304b134a7ec1f7a16bc667f2ee13858daac9) # Conflicts: # frontend/components.d.ts --- frontend/components.d.ts | 4 + .../src/components/Modals/LostReasonModal.vue | 99 +++++++++++++++++++ frontend/src/pages/Deal.vue | 23 ++++- frontend/src/pages/MobileDeal.vue | 23 ++++- 4 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 frontend/src/components/Modals/LostReasonModal.vue diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 984d8e3a..84f74933 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -162,7 +162,11 @@ declare module 'vue' { ListIcon: typeof import('./src/components/Icons/ListIcon.vue')['default'] ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default'] LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default'] +<<<<<<< HEAD LucideCalendar: typeof import('~icons/lucide/calendar')['default'] +======= + LostReasonModal: typeof import('./src/components/Modals/LostReasonModal.vue')['default'] +>>>>>>> d89c304b (fix: show lost reason modal if status changed to lost) LucideInfo: typeof import('~icons/lucide/info')['default'] LucideMoreHorizontal: typeof import('~icons/lucide/more-horizontal')['default'] LucidePlus: typeof import('~icons/lucide/plus')['default'] diff --git a/frontend/src/components/Modals/LostReasonModal.vue b/frontend/src/components/Modals/LostReasonModal.vue new file mode 100644 index 00000000..7553641d --- /dev/null +++ b/frontend/src/components/Modals/LostReasonModal.vue @@ -0,0 +1,99 @@ + + diff --git a/frontend/src/pages/Deal.vue b/frontend/src/pages/Deal.vue index baaf0a53..3efb5b0e 100644 --- a/frontend/src/pages/Deal.vue +++ b/frontend/src/pages/Deal.vue @@ -327,6 +327,11 @@ :docname="props.dealId" name="Deals" /> + From d0d67bf2ad72458454e9cc93891ec292381761ec Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 2 Jul 2025 15:58:12 +0530 Subject: [PATCH 10/11] fix: update default probability from deal status (cherry picked from commit c96e5ff6c58ca991aca8f705114317e96beb5d42) --- crm/fcrm/doctype/crm_deal/crm_deal.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.py b/crm/fcrm/doctype/crm_deal/crm_deal.py index 3022e6a7..6e056ffe 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.py +++ b/crm/fcrm/doctype/crm_deal/crm_deal.py @@ -142,8 +142,16 @@ class CRMDeal(Document): if self.status == "Won" and not self.close_date: self.close_date = frappe.utils.nowdate() + def update_default_probability(self): + """ + Update the default probability based on the status. + """ + if not self.probability or self.probability == 0: + self.probability = frappe.db.get_value("CRM Deal Status", self.status, "probability") or 0 + def validate_forcasting_fields(self): self.update_close_date() + self.update_default_probability() if frappe.db.get_single_value("FCRM Settings", "enable_forecasting"): if not self.deal_value or self.deal_value == 0: frappe.throw(_("Deal Value is required."), frappe.MandatoryError) From b50c2e6d00dce2fc198ec7bc67a48ff806af307b Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Wed, 2 Jul 2025 16:35:51 +0530 Subject: [PATCH 11/11] chore: resolved conflict --- frontend/components.d.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 84f74933..63df320c 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -162,11 +162,7 @@ declare module 'vue' { ListIcon: typeof import('./src/components/Icons/ListIcon.vue')['default'] ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default'] LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default'] -<<<<<<< HEAD - LucideCalendar: typeof import('~icons/lucide/calendar')['default'] -======= LostReasonModal: typeof import('./src/components/Modals/LostReasonModal.vue')['default'] ->>>>>>> d89c304b (fix: show lost reason modal if status changed to lost) LucideInfo: typeof import('~icons/lucide/info')['default'] LucideMoreHorizontal: typeof import('~icons/lucide/more-horizontal')['default'] LucidePlus: typeof import('~icons/lucide/plus')['default']