From 7ded0a074236992b166950fee7e979a11b7b5fe7 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Mon, 28 Apr 2025 16:10:44 +0530 Subject: [PATCH 01/27] fix: show formatted percent, currency if read only --- frontend/src/components/FieldLayout/Field.vue | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/FieldLayout/Field.vue b/frontend/src/components/FieldLayout/Field.vue index 7c4e7b34..e87da020 100644 --- a/frontend/src/components/FieldLayout/Field.vue +++ b/frontend/src/components/FieldLayout/Field.vue @@ -14,12 +14,13 @@ diff --git a/frontend/src/components/Modals/CreateDocumentModal.vue b/frontend/src/components/Modals/CreateDocumentModal.vue new file mode 100644 index 00000000..6c1ccaf8 --- /dev/null +++ b/frontend/src/components/Modals/CreateDocumentModal.vue @@ -0,0 +1,146 @@ + + + diff --git a/frontend/src/components/Modals/GlobalModals.vue b/frontend/src/components/Modals/GlobalModals.vue new file mode 100644 index 00000000..c01dfd23 --- /dev/null +++ b/frontend/src/components/Modals/GlobalModals.vue @@ -0,0 +1,32 @@ + + diff --git a/frontend/src/composables/document.js b/frontend/src/composables/document.js new file mode 100644 index 00000000..cd9b1a5c --- /dev/null +++ b/frontend/src/composables/document.js @@ -0,0 +1,14 @@ +import { ref } from 'vue' + +export const showCreateDocumentModal = ref(false) +export const createDocumentDoctype = ref('') +export const createDocumentData = ref({}) + +export function createDocument(doctype, obj, close) { + if (doctype) { + close() + createDocumentDoctype.value = doctype + createDocumentData.value = obj || {} + showCreateDocumentModal.value = true + } +} From 32f3aaf38f131f2636c69d72a7b077f25595add7 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 14 May 2025 13:19:54 +0530 Subject: [PATCH 14/27] fix: show formatted percent, currency & float only when not focused --- frontend/components.d.ts | 1 + .../components/Controls/FormattedInput.vue | 29 +++++++++++++++++++ frontend/src/components/Controls/Grid.vue | 24 ++++++++------- frontend/src/stores/meta.js | 14 +++++++++ frontend/src/utils/numberFormat.js | 11 +++---- 5 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 frontend/src/components/Controls/FormattedInput.vue diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 30f16244..99bd28e3 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -114,6 +114,7 @@ declare module 'vue' { FileVideoIcon: typeof import('./src/components/Icons/FileVideoIcon.vue')['default'] Filter: typeof import('./src/components/Filter.vue')['default'] FilterIcon: typeof import('./src/components/Icons/FilterIcon.vue')['default'] + FormattedInput: typeof import('./src/components/Controls/FormattedInput.vue')['default'] FrappeCloudIcon: typeof import('./src/components/Icons/FrappeCloudIcon.vue')['default'] GenderIcon: typeof import('./src/components/Icons/GenderIcon.vue')['default'] GeneralSettings: typeof import('./src/components/Settings/GeneralSettings.vue')['default'] diff --git a/frontend/src/components/Controls/FormattedInput.vue b/frontend/src/components/Controls/FormattedInput.vue new file mode 100644 index 00000000..0c943da8 --- /dev/null +++ b/frontend/src/components/Controls/FormattedInput.vue @@ -0,0 +1,29 @@ + + diff --git a/frontend/src/components/Controls/Grid.vue b/frontend/src/components/Controls/Grid.vue index 668072fd..620ee471 100644 --- a/frontend/src/components/Controls/Grid.vue +++ b/frontend/src/components/Controls/Grid.vue @@ -207,38 +207,41 @@ @change="(e) => fieldChange(e.target.value, field, row)" /> - - - diff --git a/frontend/src/components/Controls/Grid.vue b/frontend/src/components/Controls/Grid.vue index 620ee471..6b0f2f08 100644 --- a/frontend/src/components/Controls/Grid.vue +++ b/frontend/src/components/Controls/Grid.vue @@ -206,7 +206,7 @@ :options="field.options" @change="(e) => fieldChange(e.target.value, field, row)" /> - Date: Wed, 14 May 2025 14:04:25 +0530 Subject: [PATCH 16/27] feat: added callback to update link field value after creating new --- frontend/src/components/Controls/Grid.vue | 11 +++++++++-- frontend/src/components/FieldLayout/Field.vue | 7 ++++++- .../src/components/Modals/CreateDocumentModal.vue | 7 ++++--- frontend/src/components/Modals/GlobalModals.vue | 2 ++ frontend/src/composables/document.js | 6 ++++-- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/Controls/Grid.vue b/frontend/src/components/Controls/Grid.vue index 6b0f2f08..15fe4900 100644 --- a/frontend/src/components/Controls/Grid.vue +++ b/frontend/src/components/Controls/Grid.vue @@ -126,7 +126,9 @@ " :filters="field.filters" @change="(v) => fieldChange(v, field, row)" - :onCreate="field.create" + :onCreate=" + (value, close) => field.create(v, field, row, close) + " /> { function getFieldObj(field) { if (field.fieldtype === 'Link' && field.options !== 'User') { if (!field.create) { - field.create = (obj, close) => createDocument(field.options, obj, close) + field.create = (value, field, row, close) => { + const callback = (d) => { + if (d) fieldChange(d.name, field, row) + } + createDocument(field.options, value, close, callback) + } } } diff --git a/frontend/src/components/FieldLayout/Field.vue b/frontend/src/components/FieldLayout/Field.vue index 534a151e..a598bb39 100644 --- a/frontend/src/components/FieldLayout/Field.vue +++ b/frontend/src/components/FieldLayout/Field.vue @@ -275,7 +275,12 @@ const field = computed(() => { if (field.fieldtype === 'Link' && field.options !== 'User') { if (!field.create) { - field.create = (obj, close) => createDocument(field.options, obj, close) + field.create = (value, close) => { + const callback = (d) => { + if (d) fieldChange(d.name, field) + } + createDocument(field.options, value, close, callback) + } } } diff --git a/frontend/src/components/Modals/CreateDocumentModal.vue b/frontend/src/components/Modals/CreateDocumentModal.vue index 6c1ccaf8..0c3e5eb1 100644 --- a/frontend/src/components/Modals/CreateDocumentModal.vue +++ b/frontend/src/components/Modals/CreateDocumentModal.vue @@ -62,7 +62,7 @@ const props = defineProps({ }, }) -const emit = defineEmits(['showQuickEntryModal']) +const emit = defineEmits(['showQuickEntryModal', 'callback']) const { isManager } = usersStore() @@ -100,11 +100,11 @@ const tabs = createResource({ auto: true, }) -async function create(close) { +async function create() { loading.value = true error.value = null - await call( + let doc = await call( 'frappe.client.insert', { doc: { @@ -124,6 +124,7 @@ async function create(close) { loading.value = false show.value = false + emit('callback', doc) } watch( diff --git a/frontend/src/components/Modals/GlobalModals.vue b/frontend/src/components/Modals/GlobalModals.vue index c01dfd23..0c62c1b4 100644 --- a/frontend/src/components/Modals/GlobalModals.vue +++ b/frontend/src/components/Modals/GlobalModals.vue @@ -5,6 +5,7 @@ :doctype="createDocumentDoctype" :data="createDocumentData" @showQuickEntryModal="(dt) => openQuickEntryModal(dt)" + @callback="(data) => createDocumentCallback(data)" /> Date: Wed, 14 May 2025 15:21:07 +0530 Subject: [PATCH 17/27] fix: added default percent & int to 0 --- frontend/src/components/Controls/Grid.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Controls/Grid.vue b/frontend/src/components/Controls/Grid.vue index 15fe4900..7255c309 100644 --- a/frontend/src/components/Controls/Grid.vue +++ b/frontend/src/components/Controls/Grid.vue @@ -213,7 +213,7 @@ class="[&_input]:text-right" type="text" variant="outline" - :value="row[field.fieldname]" + :value="row[field.fieldname] || '0'" :disabled="Boolean(field.read_only)" @change="fieldChange($event.target.value, field, row)" /> @@ -223,7 +223,7 @@ type="text" variant="outline" :value="getFloatWithPrecision(field.fieldname, row)" - :formattedValue="row[field.fieldname] + '%'" + :formattedValue="(row[field.fieldname] || '0') + '%'" :disabled="Boolean(field.read_only)" @change="fieldChange(flt($event.target.value), field, row)" /> From 60ed0a2043624e2327c576372b2f8516107a2ac0 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 14 May 2025 15:21:47 +0530 Subject: [PATCH 18/27] fix: cache controller on document level not on doctype level --- frontend/src/data/document.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frontend/src/data/document.js b/frontend/src/data/document.js index 7de0bced..ce10c36e 100644 --- a/frontend/src/data/document.js +++ b/frontend/src/data/document.js @@ -36,14 +36,20 @@ export function useDocument(doctype, docname) { } function setupFormScript() { - if (controllersCache[doctype]) return + if (controllersCache[doctype]?.[docname]) return - controllersCache[doctype] = setupScript(documentsCache[doctype][docname]) + if (!controllersCache[doctype]) { + controllersCache[doctype] = {} + } + + controllersCache[doctype][docname] = setupScript( + documentsCache[doctype][docname], + ) } function getControllers(row = null) { const _doctype = row?.doctype || doctype - return (controllersCache[doctype] || []).filter( + return (controllersCache[doctype]?.[docname] || []).filter( (c) => c.constructor.name === _doctype.replace(/\s+/g, ''), ) } From afe828f01206c22c1f3679f9ab7663b5b9887653 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 14 May 2025 16:55:19 +0530 Subject: [PATCH 19/27] fix: update mandatory field indicator color and replace FormControl with FormattedInput for various field types --- frontend/src/components/Controls/Grid.vue | 8 ++++++++ frontend/src/components/FieldLayout/Field.vue | 11 ++++++----- frontend/src/components/SidePanelLayout.vue | 13 +++++++------ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/Controls/Grid.vue b/frontend/src/components/Controls/Grid.vue index 7255c309..e08cdd7d 100644 --- a/frontend/src/components/Controls/Grid.vue +++ b/frontend/src/components/Controls/Grid.vue @@ -42,6 +42,14 @@ :title="field.label" > {{ __(field.label) }} + *
diff --git a/frontend/src/components/FieldLayout/Field.vue b/frontend/src/components/FieldLayout/Field.vue index a598bb39..92ce15f8 100644 --- a/frontend/src/components/FieldLayout/Field.vue +++ b/frontend/src/components/FieldLayout/Field.vue @@ -7,7 +7,7 @@ field.reqd || (field.mandatory_depends_on && field.mandatory_via_depends_on) " - class="text-ink-red-3" + class="text-ink-red-2" >*
@@ -161,7 +161,7 @@ :description="field.description" @change="fieldChange($event.target.value, field)" /> - - - - From 3516e1ff44503e6cabf029b202d0f9874691cebf Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 14 May 2025 19:08:29 +0530 Subject: [PATCH 22/27] fix: update field visibility logic and disable inputs based on read-only status --- frontend/src/components/SidePanelLayout.vue | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/SidePanelLayout.vue b/frontend/src/components/SidePanelLayout.vue index 6727af40..c01607bf 100644 --- a/frontend/src/components/SidePanelLayout.vue +++ b/frontend/src/components/SidePanelLayout.vue @@ -65,7 +65,14 @@
@@ -266,6 +273,7 @@ @change.stop=" fieldChange(flt($event.target.value), field) " + :disabled="Boolean(field.read_only)" /> Date: Wed, 14 May 2025 19:57:09 +0530 Subject: [PATCH 23/27] fix: added products table in crm lead --- crm/fcrm/doctype/crm_deal/crm_deal.js | 18 ++----- crm/fcrm/doctype/crm_lead/crm_lead.js | 64 +++++++++++++++++++++++++ crm/fcrm/doctype/crm_lead/crm_lead.json | 46 +++++++++++++++++- 3 files changed, 111 insertions(+), 17 deletions(-) diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.js b/crm/fcrm/doctype/crm_deal/crm_deal.js index a7f26fb5..3526767a 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.js +++ b/crm/fcrm/doctype/crm_deal/crm_deal.js @@ -12,20 +12,10 @@ frappe.ui.form.on("CRM Deal", { frm.doc.products.forEach((d) => { total += d.amount; total_qty += d.qty; - net_total += d.net_amount || d.amount; + net_total += d.net_amount; }); - if (total) { - frappe.model.set_value(frm.doctype, frm.docname, "total", total); - } - if (total_qty) { - frappe.model.set_value( - frm.doctype, - frm.docname, - "total_qty", - total_qty - ); - } + frappe.model.set_value(frm.doctype, frm.docname, "total", total); frappe.model.set_value( frm.doctype, frm.docname, @@ -44,9 +34,7 @@ frappe.ui.form.on("CRM Products", { }, product_code: function (frm, cdt, cdn) { let d = frappe.get_doc(cdt, cdn); - if (!d.product_name) { - frappe.model.set_value(cdt, cdn, "product_name", d.product_code); - } + frappe.model.set_value(cdt, cdn, "product_name", d.product_code); }, rate: function (frm, cdt, cdn) { let d = frappe.get_doc(cdt, cdn); diff --git a/crm/fcrm/doctype/crm_lead/crm_lead.js b/crm/fcrm/doctype/crm_lead/crm_lead.js index 0a9d57e1..af944f40 100644 --- a/crm/fcrm/doctype/crm_lead/crm_lead.js +++ b/crm/fcrm/doctype/crm_lead/crm_lead.js @@ -5,4 +5,68 @@ frappe.ui.form.on("CRM Lead", { refresh(frm) { frm.add_web_link(`/crm/leads/${frm.doc.name}`, __("Open in Portal")); }, + update_total: function (frm) { + let total = 0; + let total_qty = 0; + let net_total = 0; + frm.doc.products.forEach((d) => { + total += d.amount; + total_qty += d.qty; + net_total += d.net_amount; + }); + + frappe.model.set_value(frm.doctype, frm.docname, "total", total); + frappe.model.set_value( + frm.doctype, + frm.docname, + "net_total", + net_total || total + ); + } }); + +frappe.ui.form.on("CRM Products", { + products_add: function (frm, cdt, cdn) { + frm.trigger("update_total"); + }, + products_remove: function (frm, cdt, cdn) { + frm.trigger("update_total"); + }, + product_code: function (frm, cdt, cdn) { + let d = frappe.get_doc(cdt, cdn); + frappe.model.set_value(cdt, cdn, "product_name", d.product_code); + }, + rate: function (frm, cdt, cdn) { + let d = frappe.get_doc(cdt, cdn); + if (d.rate && d.qty) { + frappe.model.set_value(cdt, cdn, "amount", d.rate * d.qty); + } + frm.trigger("update_total"); + }, + qty: function (frm, cdt, cdn) { + let d = frappe.get_doc(cdt, cdn); + if (d.rate && d.qty) { + frappe.model.set_value(cdt, cdn, "amount", d.rate * d.qty); + } + frm.trigger("update_total"); + }, + discount_percentage: function (frm, cdt, cdn) { + let d = frappe.get_doc(cdt, cdn); + if (d.discount_percentage && d.amount) { + discount_amount = (d.discount_percentage / 100) * d.amount; + frappe.model.set_value( + cdt, + cdn, + "discount_amount", + discount_amount + ); + frappe.model.set_value( + cdt, + cdn, + "net_amount", + d.amount - discount_amount + ); + } + frm.trigger("update_total"); + } +}); \ No newline at end of file diff --git a/crm/fcrm/doctype/crm_lead/crm_lead.json b/crm/fcrm/doctype/crm_lead/crm_lead.json index e39af407..a9c25416 100644 --- a/crm/fcrm/doctype/crm_lead/crm_lead.json +++ b/crm/fcrm/doctype/crm_lead/crm_lead.json @@ -37,6 +37,12 @@ "annual_revenue", "image", "converted", + "products_tab", + "products", + "section_break_ggwh", + "total", + "column_break_uisv", + "net_total", "sla_tab", "sla", "sla_creation", @@ -285,12 +291,47 @@ "fieldtype": "Table", "label": "Status Change Log", "options": "CRM Status Change Log" + }, + { + "fieldname": "products_tab", + "fieldtype": "Tab Break", + "label": "Products" + }, + { + "fieldname": "products", + "fieldtype": "Table", + "label": "Products", + "options": "CRM Products" + }, + { + "fieldname": "section_break_ggwh", + "fieldtype": "Section Break" + }, + { + "fieldname": "total", + "fieldtype": "Currency", + "label": "Total", + "options": "currency", + "read_only": 1 + }, + { + "fieldname": "column_break_uisv", + "fieldtype": "Column Break" + }, + { + "description": "Total after discount", + "fieldname": "net_total", + "fieldtype": "Currency", + "label": "Net Total", + "options": "currency", + "read_only": 1 } ], + "grid_page_length": 50, "image_field": "image", "index_web_pages_for_search": 1, "links": [], - "modified": "2025-01-02 22:14:01.991054", + "modified": "2025-05-14 19:51:06.184569", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Lead", @@ -331,6 +372,7 @@ "share": 1 } ], + "row_format": "Dynamic", "sender_field": "email", "sender_name_field": "first_name", "show_title_field_in_link": 1, @@ -339,4 +381,4 @@ "states": [], "title_field": "lead_name", "track_changes": 1 -} \ No newline at end of file +} From fdd6c46b5f718800dd062dbde1c718a2c93ddfbe Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 14 May 2025 19:57:51 +0530 Subject: [PATCH 24/27] fix: create product detail script on install --- crm/fcrm/doctype/crm_products/crm_products.py | 104 +++++++++++++++++- crm/install.py | 8 ++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/crm/fcrm/doctype/crm_products/crm_products.py b/crm/fcrm/doctype/crm_products/crm_products.py index e8a34bb8..e77b5ab5 100644 --- a/crm/fcrm/doctype/crm_products/crm_products.py +++ b/crm/fcrm/doctype/crm_products/crm_products.py @@ -1,9 +1,111 @@ # Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -# import frappe +import frappe from frappe.model.document import Document class CRMProducts(Document): pass + + +def create_product_details_script(doctype): + if not frappe.db.exists("CRM Form Script", "Product Details Script for " + doctype): + script = get_product_details_script() + frappe.get_doc( + { + "doctype": "CRM Form Script", + "name": "Product Details Script for " + doctype, + "dt": doctype, + "view": "Form", + "script": script, + "enabled": 1, + "is_standard": 1, + } + ).insert() + + +def get_product_details_script(doctype): + doctype_class = "class " + doctype.replace(" ", "") + + return ( + doctype_class + + """ + { + update_total() { + let total = 0 + let total_qty = 0 + let net_total = 0 + let discount_applied = false + + this.doc.products.forEach((d) => { + total += d.amount + total_qty += d.qty + net_total += d.net_amount + if (d.discount_percentage > 0) { + discount_applied = true + } + }) + + this.doc.total = total + this.doc.net_total = net_total || total + + if (!net_total && discount_applied) { + this.doc.net_total = net_total + } + } +} + +class CRMProducts { + products_add() { + let row = this.doc.getRow('products') + row.trigger('qty') + this.doc.trigger('update_total') + } + + products_remove() { + this.doc.trigger('update_total') + } + + async product_code(idx) { + let row = this.doc.getRow('products', idx) + + let a = await call("frappe.client.get_value", { + doctype: "CRM Product", + filters: { name: row.product_code }, + fieldname: ["product_name", "standard_rate"], + }) + + row.product_name = a.product_name + if (a.standard_rate && !row.rate) { + row.rate = a.standard_rate + row.trigger("rate") + } + } + + qty(idx) { + let row = this.doc.getRow('products', idx) + row.amount = row.qty * row.rate + row.trigger('discount_percentage', idx) + } + + rate() { + let row = this.doc.getRow('products') + row.amount = row.qty * row.rate + row.trigger('discount_percentage') + } + + discount_percentage(idx) { + let row = this.doc.getRow('products', idx) + if (!row.discount_percentage) { + row.net_amount = row.amount + row.discount_amount = 0 + } + if (row.discount_percentage && row.amount) { + row.discount_amount = (row.discount_percentage / 100) * row.amount + row.net_amount = row.amount - row.discount_amount + } + this.doc.trigger('update_total') + } +}""" + ) diff --git a/crm/install.py b/crm/install.py index 1e0d816f..5f25e7d0 100644 --- a/crm/install.py +++ b/crm/install.py @@ -4,6 +4,8 @@ import click import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields +from crm.fcrm.doctype.crm_products.crm_products import create_product_details_script + def before_install(): pass @@ -19,6 +21,7 @@ def after_install(force=False): add_default_industries() add_default_lead_sources() add_standard_dropdown_items() + add_default_scripts() frappe.db.commit() @@ -353,3 +356,8 @@ def add_standard_dropdown_items(): crm_settings.append("dropdown_items", item) crm_settings.save() + + +def add_default_scripts(): + for doctype in ["CRM Lead", "CRM Deal"]: + create_product_details_script(doctype) From d6ff40cc6aceae1dbf1f50dc033604a476914c7d Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 14 May 2025 19:58:39 +0530 Subject: [PATCH 25/27] chore: formatting fix --- crm/uninstall.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crm/uninstall.py b/crm/uninstall.py index 34622d0b..a186c79f 100644 --- a/crm/uninstall.py +++ b/crm/uninstall.py @@ -1,12 +1,13 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import click import frappe + def before_uninstall(): delete_email_template_custom_fields() + def delete_email_template_custom_fields(): if frappe.get_meta("Email Template").has_field("enabled"): click.secho("* Uninstalling Custom Fields from Email Template") @@ -19,4 +20,4 @@ def delete_email_template_custom_fields(): for fieldname in fieldnames: frappe.db.delete("Custom Field", {"name": "Email Template-" + fieldname}) - frappe.clear_cache(doctype="Email Template") \ No newline at end of file + frappe.clear_cache(doctype="Email Template") From d3a6cc968fe3101d6ed060796c7c9b24eaea8f5e Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 14 May 2025 20:00:48 +0530 Subject: [PATCH 26/27] fix: add patch to create default scripts --- crm/patches.txt | 3 ++- crm/patches/v1_0/create_default_scripts.py | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 crm/patches/v1_0/create_default_scripts.py diff --git a/crm/patches.txt b/crm/patches.txt index f602b2bc..59f37bfb 100644 --- a/crm/patches.txt +++ b/crm/patches.txt @@ -11,4 +11,5 @@ crm.patches.v1_0.create_default_fields_layout #22/01/2025 crm.patches.v1_0.create_default_sidebar_fields_layout crm.patches.v1_0.update_deal_quick_entry_layout crm.patches.v1_0.update_layouts_to_new_format -crm.patches.v1_0.move_twilio_agent_to_telephony_agent \ No newline at end of file +crm.patches.v1_0.move_twilio_agent_to_telephony_agent +crm.patches.v1_0.create_default_scripts \ No newline at end of file diff --git a/crm/patches/v1_0/create_default_scripts.py b/crm/patches/v1_0/create_default_scripts.py new file mode 100644 index 00000000..37e3b0d1 --- /dev/null +++ b/crm/patches/v1_0/create_default_scripts.py @@ -0,0 +1,5 @@ +from crm.install import add_default_scripts + + +def execute(): + add_default_scripts() From adbb9f57650f6a863d25eff3688b06c24a250ef4 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 14 May 2025 20:02:45 +0530 Subject: [PATCH 27/27] fix: pass doctype argument to get_product_details_script in create_product_details_script --- crm/fcrm/doctype/crm_products/crm_products.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crm/fcrm/doctype/crm_products/crm_products.py b/crm/fcrm/doctype/crm_products/crm_products.py index e77b5ab5..59f28e5c 100644 --- a/crm/fcrm/doctype/crm_products/crm_products.py +++ b/crm/fcrm/doctype/crm_products/crm_products.py @@ -11,7 +11,7 @@ class CRMProducts(Document): def create_product_details_script(doctype): if not frappe.db.exists("CRM Form Script", "Product Details Script for " + doctype): - script = get_product_details_script() + script = get_product_details_script(doctype) frappe.get_doc( { "doctype": "CRM Form Script", @@ -30,8 +30,8 @@ def get_product_details_script(doctype): return ( doctype_class + + " {" + """ - { update_total() { let total = 0 let total_qty = 0 @@ -40,7 +40,6 @@ def get_product_details_script(doctype): this.doc.products.forEach((d) => { total += d.amount - total_qty += d.qty net_total += d.net_amount if (d.discount_percentage > 0) { discount_applied = true