diff --git a/frontend/src/components/Modals/AddressModal.vue b/frontend/src/components/Modals/AddressModal.vue
index e7c4543f..444490c4 100644
--- a/frontend/src/components/Modals/AddressModal.vue
+++ b/frontend/src/components/Modals/AddressModal.vue
@@ -84,7 +84,10 @@ const error = ref(null)
const title = ref(null)
const editMode = ref(false)
-const { document: _address } = useDocument('Address', props.address || '')
+const { document: _address, triggerOnBeforeCreate } = useDocument(
+ 'Address',
+ props.address || '',
+)
const dialogOptions = computed(() => {
let title = !editMode.value
@@ -95,8 +98,7 @@ const dialogOptions = computed(() => {
{
label: editMode.value ? __('Save') : __('Create'),
variant: 'solid',
- onClick: () =>
- editMode.value ? updateAddress() : createAddress.submit(),
+ onClick: () => (editMode.value ? updateAddress() : createAddress()),
},
]
@@ -133,16 +135,22 @@ async function updateAddress() {
await _address.save.submit(null, callBacks)
}
-const createAddress = createResource({
+async function createAddress() {
+ loading.value = true
+ error.value = null
+
+ await triggerOnBeforeCreate?.()
+
+ await _createAddress.submit({
+ doc: {
+ doctype: 'Address',
+ ..._address.doc,
+ },
+ })
+}
+
+const _createAddress = createResource({
url: 'frappe.client.insert',
- makeParams() {
- return {
- doc: {
- doctype: 'Address',
- ..._address.doc,
- },
- }
- },
onSuccess(doc) {
loading.value = false
if (doc.name) {
diff --git a/frontend/src/components/Modals/ContactModal.vue b/frontend/src/components/Modals/ContactModal.vue
index 25a0c022..4578ca35 100644
--- a/frontend/src/components/Modals/ContactModal.vue
+++ b/frontend/src/components/Modals/ContactModal.vue
@@ -86,7 +86,7 @@ const show = defineModel()
const loading = ref(false)
-const { document: _contact } = useDocument('Contact')
+const { document: _contact, triggerOnBeforeCreate } = useDocument('Contact')
async function createContact() {
if (_contact.doc.email_id) {
@@ -99,6 +99,8 @@ async function createContact() {
delete _contact.doc.mobile_no
}
+ await triggerOnBeforeCreate?.()
+
const doc = await call('frappe.client.insert', {
doc: {
doctype: 'Contact',
diff --git a/frontend/src/components/Modals/CreateDocumentModal.vue b/frontend/src/components/Modals/CreateDocumentModal.vue
index be5bbf01..0a2933a7 100644
--- a/frontend/src/components/Modals/CreateDocumentModal.vue
+++ b/frontend/src/components/Modals/CreateDocumentModal.vue
@@ -27,7 +27,7 @@
-
+
@@ -51,6 +51,7 @@
import FieldLayout from '@/components/FieldLayout/FieldLayout.vue'
import EditIcon from '@/components/Icons/EditIcon.vue'
import { usersStore } from '@/stores/users'
+import { useDocument } from '@/data/document'
import { isMobileView } from '@/composables/settings'
import { showQuickEntryModal, quickEntryProps } from '@/composables/modals'
import { FeatherIcon, createResource, ErrorMessage, call } from 'frappe-ui'
@@ -76,7 +77,7 @@ const show = defineModel()
const loading = ref(false)
const error = ref(null)
-let _data = ref({})
+const { document: _data, triggerOnBeforeCreate } = useDocument(props.doctype)
const dialogOptions = computed(() => {
let doctype = props.doctype
@@ -109,12 +110,14 @@ async function create() {
loading.value = true
error.value = null
+ await triggerOnBeforeCreate?.()
+
let doc = await call(
'frappe.client.insert',
{
doc: {
doctype: props.doctype,
- ..._data.value,
+ ..._data.doc,
},
},
{
@@ -138,7 +141,7 @@ watch(
if (!value) return
nextTick(() => {
- _data.value = { ...props.data }
+ _data.doc = { ...props.data }
})
},
)
diff --git a/frontend/src/components/Modals/DealModal.vue b/frontend/src/components/Modals/DealModal.vue
index 8bf9498b..7ccb128f 100644
--- a/frontend/src/components/Modals/DealModal.vue
+++ b/frontend/src/components/Modals/DealModal.vue
@@ -98,7 +98,11 @@ const show = defineModel()
const router = useRouter()
const error = ref(null)
-const { document: deal, triggerOnChange } = useDocument('CRM Deal')
+const {
+ document: deal,
+ triggerOnChange,
+ triggerOnBeforeCreate,
+} = useDocument('CRM Deal')
const hasOrganizationSections = ref(true)
const hasContactSections = ref(true)
@@ -175,7 +179,7 @@ const dealStatuses = computed(() => {
return statuses
})
-function createDeal() {
+async function createDeal() {
if (deal.doc.website && !deal.doc.website.startsWith('http')) {
deal.doc.website = 'https://' + deal.doc.website
}
@@ -186,6 +190,8 @@ function createDeal() {
deal.doc['mobile_no'] = null
} else deal.doc['contact'] = null
+ await triggerOnBeforeCreate?.()
+
createResource({
url: 'crm.fcrm.doctype.crm_deal.crm_deal.create_deal',
params: { args: deal.doc },
diff --git a/frontend/src/components/Modals/LeadModal.vue b/frontend/src/components/Modals/LeadModal.vue
index d82dbe52..7c2dc728 100644
--- a/frontend/src/components/Modals/LeadModal.vue
+++ b/frontend/src/components/Modals/LeadModal.vue
@@ -74,7 +74,11 @@ const router = useRouter()
const error = ref(null)
const isLeadCreating = ref(false)
-const { document: lead, triggerOnChange } = useDocument('CRM Lead')
+const {
+ document: lead,
+ triggerOnChange,
+ triggerOnBeforeCreate,
+} = useDocument('CRM Lead')
const leadStatuses = computed(() => {
let statuses = statusOptions('lead', null, [], triggerOnChange)
@@ -112,71 +116,73 @@ const tabs = createResource({
const createLead = createResource({
url: 'frappe.client.insert',
- makeParams(values) {
- return {
- doc: {
- doctype: 'CRM Lead',
- ...values,
- },
- }
- },
})
-function createNewLead() {
+async function createNewLead() {
if (lead.doc.website && !lead.doc.website.startsWith('http')) {
lead.doc.website = 'https://' + lead.doc.website
}
- createLead.submit(lead.doc, {
- validate() {
- error.value = null
- if (!lead.doc.first_name) {
- error.value = __('First Name is mandatory')
- return error.value
- }
- if (lead.doc.annual_revenue) {
- if (typeof lead.doc.annual_revenue === 'string') {
- lead.doc.annual_revenue = lead.doc.annual_revenue.replace(/,/g, '')
- } else if (isNaN(lead.doc.annual_revenue)) {
- error.value = __('Annual Revenue should be a number')
+ await triggerOnBeforeCreate?.()
+
+ createLead.submit(
+ {
+ doc: {
+ doctype: 'CRM Lead',
+ ...lead.doc,
+ },
+ },
+ {
+ validate() {
+ error.value = null
+ if (!lead.doc.first_name) {
+ error.value = __('First Name is mandatory')
return error.value
}
- }
- if (
- lead.doc.mobile_no &&
- isNaN(lead.doc.mobile_no.replace(/[-+() ]/g, ''))
- ) {
- error.value = __('Mobile No should be a number')
- return error.value
- }
- if (lead.doc.email && !lead.doc.email.includes('@')) {
- error.value = __('Invalid Email')
- return error.value
- }
- if (!lead.doc.status) {
- error.value = __('Status is required')
- return error.value
- }
- isLeadCreating.value = true
+ if (lead.doc.annual_revenue) {
+ if (typeof lead.doc.annual_revenue === 'string') {
+ lead.doc.annual_revenue = lead.doc.annual_revenue.replace(/,/g, '')
+ } else if (isNaN(lead.doc.annual_revenue)) {
+ error.value = __('Annual Revenue should be a number')
+ return error.value
+ }
+ }
+ if (
+ lead.doc.mobile_no &&
+ isNaN(lead.doc.mobile_no.replace(/[-+() ]/g, ''))
+ ) {
+ error.value = __('Mobile No should be a number')
+ return error.value
+ }
+ if (lead.doc.email && !lead.doc.email.includes('@')) {
+ error.value = __('Invalid Email')
+ return error.value
+ }
+ if (!lead.doc.status) {
+ error.value = __('Status is required')
+ return error.value
+ }
+ isLeadCreating.value = true
+ },
+ onSuccess(data) {
+ capture('lead_created')
+ isLeadCreating.value = false
+ show.value = false
+ router.push({ name: 'Lead', params: { leadId: data.name } })
+ updateOnboardingStep('create_first_lead', true, false, () => {
+ localStorage.setItem('firstLead' + user, data.name)
+ })
+ },
+ onError(err) {
+ isLeadCreating.value = false
+ if (!err.messages) {
+ error.value = err.message
+ return
+ }
+ error.value = err.messages.join('\n')
+ },
},
- onSuccess(data) {
- capture('lead_created')
- isLeadCreating.value = false
- show.value = false
- router.push({ name: 'Lead', params: { leadId: data.name } })
- updateOnboardingStep('create_first_lead', true, false, () => {
- localStorage.setItem('firstLead' + user, data.name)
- })
- },
- onError(err) {
- isLeadCreating.value = false
- if (!err.messages) {
- error.value = err.message
- return
- }
- error.value = err.messages.join('\n')
- },
- })
+ )
}
function openQuickEntryModal() {
diff --git a/frontend/src/components/Modals/OrganizationModal.vue b/frontend/src/components/Modals/OrganizationModal.vue
index a0d12887..c5ac5f5f 100644
--- a/frontend/src/components/Modals/OrganizationModal.vue
+++ b/frontend/src/components/Modals/OrganizationModal.vue
@@ -88,9 +88,15 @@ const show = defineModel()
const loading = ref(false)
const error = ref(null)
-const { document: organization } = useDocument('CRM Organization')
+const { document: organization, triggerOnBeforeCreate } =
+ useDocument('CRM Organization')
async function createOrganization() {
+ loading.value = true
+ error.value = null
+
+ await triggerOnBeforeCreate?.()
+
const doc = await call(
'frappe.client.insert',
{