Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ERPNext Integration fixes & async form/list custom actions #352

Merged
merged 10 commits into from
Sep 16, 2024
4 changes: 3 additions & 1 deletion crm/fcrm/doctype/crm_deal/crm_deal.json
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2024-06-20 12:55:41.602364",
"modified": "2024-09-16 19:44:19.553715",
"modified_by": "Administrator",
"module": "FCRM",
"name": "CRM Deal",
Expand Down Expand Up @@ -371,8 +371,10 @@
"write": 1
}
],
"show_title_field_in_link": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"title_field": "organization",
"track_changes": 1
}
3 changes: 2 additions & 1 deletion crm/fcrm/doctype/crm_form_script/crm_form_script.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"default": "0",
"fieldname": "enabled",
"fieldtype": "Check",
"hidden": 1,
"label": "Enabled"
},
{
Expand Down Expand Up @@ -64,7 +65,7 @@
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2024-09-11 12:56:09.288849",
"modified": "2024-09-16 19:40:19.340948",
"modified_by": "Administrator",
"module": "FCRM",
"name": "CRM Form Script",
Expand Down
3 changes: 2 additions & 1 deletion crm/fcrm/doctype/crm_lead/crm_lead.json
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@
"image_field": "image",
"index_web_pages_for_search": 1,
"links": [],
"modified": "2024-02-05 00:58:07.321058",
"modified": "2024-09-16 19:46:01.307171",
"modified_by": "Administrator",
"module": "FCRM",
"name": "CRM Lead",
Expand Down Expand Up @@ -325,6 +325,7 @@
],
"sender_field": "email",
"sender_name_field": "first_name",
"show_title_field_in_link": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
Expand Down
53 changes: 40 additions & 13 deletions crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,33 @@
"engine": "InnoDB",
"field_order": [
"enabled",
"is_erpnext_in_the_current_site",
"is_erpnext_in_different_site",
"column_break_vfru",
"erpnext_company",
"section_break_oubd",
"erpnext_site_url",
"column_break_fllx",
"api_key",
"api_secret"
"api_secret",
"section_break_jnbn",
"create_customer_on_status_change",
"column_break_kbhw",
"deal_status"
],
"fields": [
{
"depends_on": "eval:doc.enabled && !doc.is_erpnext_in_the_current_site",
"depends_on": "eval:doc.enabled && doc.is_erpnext_in_different_site",
"fieldname": "api_key",
"fieldtype": "Data",
"label": "API Key",
"mandatory_depends_on": "eval:!doc.is_erpnext_in_the_current_site"
"mandatory_depends_on": "is_erpnext_in_different_site"
},
{
"depends_on": "eval:doc.enabled && !doc.is_erpnext_in_the_current_site",
"depends_on": "eval:doc.enabled && doc.is_erpnext_in_different_site",
"fieldname": "api_secret",
"fieldtype": "Data",
"label": "API Secret",
"mandatory_depends_on": "eval:!doc.is_erpnext_in_the_current_site"
"mandatory_depends_on": "is_erpnext_in_different_site"
},
{
"depends_on": "enabled",
Expand All @@ -40,11 +44,11 @@
"fieldtype": "Column Break"
},
{
"depends_on": "eval:doc.enabled && !doc.is_erpnext_in_the_current_site",
"depends_on": "eval:doc.enabled && doc.is_erpnext_in_different_site",
"fieldname": "erpnext_site_url",
"fieldtype": "Data",
"label": "ERPNext Site URL",
"mandatory_depends_on": "eval:!doc.is_erpnext_in_the_current_site"
"mandatory_depends_on": "is_erpnext_in_different_site"
},
{
"depends_on": "enabled",
Expand All @@ -57,24 +61,47 @@
"fieldname": "column_break_vfru",
"fieldtype": "Column Break"
},
{
"default": "0",
"fieldname": "enabled",
"fieldtype": "Check",
"label": "Enabled"
},
{
"default": "0",
"depends_on": "enabled",
"fieldname": "is_erpnext_in_the_current_site",
"fieldname": "is_erpnext_in_different_site",
"fieldtype": "Check",
"label": "Is ERPNext in the current site?"
"label": "Is ERPNext installed on a different site?"
},
{
"fieldname": "section_break_jnbn",
"fieldtype": "Section Break"
},
{
"default": "0",
"fieldname": "enabled",
"depends_on": "enabled",
"fieldname": "create_customer_on_status_change",
"fieldtype": "Check",
"label": "Enabled"
"label": "Create customer on status change"
},
{
"fieldname": "column_break_kbhw",
"fieldtype": "Column Break"
},
{
"depends_on": "eval:doc.enabled && doc.create_customer_on_status_change",
"fieldname": "deal_status",
"fieldtype": "Link",
"label": "Deal Status",
"mandatory_depends_on": "create_customer_on_status_change",
"options": "CRM Deal Status"
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2024-09-13 15:06:23.317262",
"modified": "2024-09-16 21:30:40.097360",
"modified_by": "Administrator",
"module": "FCRM",
"name": "ERPNext CRM Settings",
Expand Down
36 changes: 26 additions & 10 deletions crm/fcrm/doctype/erpnext_crm_settings/erpnext_crm_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ def validate(self):
self.create_crm_form_script()

def validate_if_erpnext_installed(self):
if self.is_erpnext_in_the_current_site:
if not self.is_erpnext_in_different_site:
if "erpnext" not in frappe.get_installed_apps():
frappe.throw(_("ERPNext is not installed in the current site"))

def add_quotation_to_option(self):
if self.is_erpnext_in_the_current_site:
if not self.is_erpnext_in_different_site:
if not frappe.db.exists("Property Setter", {"name": "Quotation-quotation_to-link_filters"}):
make_property_setter(
doctype="Quotation",
Expand All @@ -35,7 +35,7 @@ def add_quotation_to_option(self):
)

def create_custom_fields(self):
if self.is_erpnext_in_the_current_site:
if not self.is_erpnext_in_different_site:
from erpnext.crm.frappe_crm_api import create_custom_fields_for_frappe_crm
create_custom_fields_for_frappe_crm()
else:
Expand Down Expand Up @@ -80,7 +80,7 @@ def get_quotation_url(crm_deal, organization):
if not erpnext_crm_settings.enabled:
frappe.throw(_("ERPNext is not integrated with the CRM"))

if erpnext_crm_settings.is_erpnext_in_the_current_site:
if not erpnext_crm_settings.is_erpnext_in_different_site:
quotation_url = get_url_to_form("Quotation")
return f"{quotation_url}/new?quotation_to=CRM Deal&crm_deal={crm_deal}&party_name={crm_deal}"
else:
Expand All @@ -95,6 +95,7 @@ def create_prospect_in_remote_site(crm_deal, erpnext_crm_settings):
client = get_erpnext_site_client(erpnext_crm_settings)
doc = frappe.get_doc("CRM Deal", crm_deal)
contacts = get_contacts(doc)
address = get_organization_address(doc.organization)
return client.post_api("erpnext.crm.frappe_crm_api.create_prospect_against_crm_deal",
{
"organization": doc.organization,
Expand All @@ -107,7 +108,8 @@ def create_prospect_in_remote_site(crm_deal, erpnext_crm_settings):
"website": doc.website,
"annual_revenue": doc.annual_revenue,
"contacts": json.dumps(contacts),
"erpnext_company": erpnext_crm_settings.erpnext_company
"erpnext_company": erpnext_crm_settings.erpnext_company,
"address": address.as_dict() if address else None
},
)
except Exception:
Expand All @@ -130,12 +132,22 @@ def get_contacts(doc):
})
return contacts

def get_organization_address(organization):
address = frappe.get_value("CRM Organization", organization, "address")
address = frappe.get_doc("Address", address) if address else None
return address

def create_customer_in_erpnext(doc, method):
erpnext_crm_settings = frappe.get_single("ERPNext CRM Settings")
if not erpnext_crm_settings.enabled or doc.status != "Won":
if (
not erpnext_crm_settings.enabled
or not erpnext_crm_settings.create_customer_on_status_change
or doc.status != erpnext_crm_settings.deal_status
):
return

contacts = get_contacts(doc)
address = get_organization_address(doc.organization)
customer = {
"customer_name": doc.organization,
"customer_group": "All Customer Groups",
Expand All @@ -146,12 +158,15 @@ def create_customer_in_erpnext(doc, method):
"website": doc.website,
"crm_deal": doc.name,
"contacts": json.dumps(contacts),
"address": address.as_dict() if address else None,
}
if erpnext_crm_settings.is_erpnext_in_the_current_site:
if not erpnext_crm_settings.is_erpnext_in_different_site:
from erpnext.crm.frappe_crm_api import create_customer
create_customer(customer)
else:
create_customer_in_remote_site(customer, erpnext_crm_settings)
create_customer_in_remote_site(customer, erpnext_crm_settings)

frappe.publish_realtime("crm_customer_created")

def create_customer_in_remote_site(customer, erpnext_crm_settings):
client = get_erpnext_site_client(erpnext_crm_settings)
Expand All @@ -166,9 +181,10 @@ def create_customer_in_remote_site(customer, erpnext_crm_settings):

def get_crm_form_script():
return """
function setupForm({ doc, call, $dialog, updateField, createToast }) {
async function setupForm({ doc, call, $dialog, updateField, createToast }) {
let actions = [];
if (!["Lost", "Won"].includes(doc?.status)) {
let is_erpnext_integration_enabled = await call("frappe.client.get_single_value", {doctype: "ERPNext CRM Settings", field: "enabled"});
if (!["Lost", "Won"].includes(doc?.status) && is_erpnext_integration_enabled) {
actions.push({
label: __("Create Quotation"),
onClick: async () => {
Expand Down
11 changes: 9 additions & 2 deletions frontend/src/components/Fields.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,22 @@
(field.read_only && data[field.name]) ||
!field.read_only ||
!field.hidden) &&
(!field.depends_on || field.display_depends_on)
(!field.depends_on || field.display_via_depends_on)
"
>
<div
v-if="field.type != 'Check'"
class="mb-2 text-sm text-gray-600"
>
{{ __(field.label) }}
<span class="text-red-500" v-if="field.mandatory">*</span>
<span
class="text-red-500"
v-if="
field.mandatory ||
(field.mandatory_depends_on && field.mandatory_via_depends_on)
"
>*</span
>
</div>
<FormControl
v-if="field.read_only && field.type !== 'Check'"
Expand Down
15 changes: 9 additions & 6 deletions frontend/src/components/ListBulkActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<script setup>
import EditValueModal from '@/components/Modals/EditValueModal.vue'
import AssignmentModal from '@/components/Modals/AssignmentModal.vue'
import { setupListActions, createToast } from '@/utils'
import { setupListCustomizations, createToast } from '@/utils'
import { globalStore } from '@/stores/global'
import { capture } from '@/telemetry'
import { call } from 'frappe-ui'
Expand All @@ -45,7 +45,7 @@ const list = defineModel()

const router = useRouter()

const { $dialog } = globalStore()
const { $dialog, $socket } = globalStore()

const showEditModal = ref(false)
const selectedValues = ref([])
Expand Down Expand Up @@ -230,17 +230,20 @@ function reload(unselectAll) {
list.value?.reload()
}

onMounted(() => {
onMounted(async () => {
if (!list.value?.data) return
setupListActions(list.value.data, {
let customization = await setupListCustomizations(list.value.data, {
list: list.value,
call,
createToast,
$dialog,
$socket,
router,
})
customBulkActions.value = list.value?.data?.bulkActions || []
customListActions.value = list.value?.data?.listActions || []
customBulkActions.value =
customization?.bulkActions || list.value?.data?.bulkActions || []
customListActions.value =
customization?.actions || list.value?.data?.listActions || []
})

defineExpose({
Expand Down
9 changes: 7 additions & 2 deletions frontend/src/components/Settings/ERPNextSettings.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
<template>
<SettingsPage doctype="ERPNext CRM Settings" :title="__('ERPNext Settings')" class="p-8" />
<SettingsPage
doctype="ERPNext CRM Settings"
:title="__('ERPNext Settings')"
:successMessage="__('ERPNext Settings updated')"
class="p-8"
/>
</template>
<script setup>
import SettingsPage from '@/components/Settings/SettingsPage.vue'
import SettingsPage from '@/components/Settings/SettingsPage.vue'
</script>
Loading
Loading