Merge pull request #867 from frappe/main-hotfix
This commit is contained in:
commit
fc50f669fd
@ -14,7 +14,7 @@ export function useDocument(doctype, docname) {
|
|||||||
documentsCache[doctype][docname] = createDocumentResource({
|
documentsCache[doctype][docname] = createDocumentResource({
|
||||||
doctype: doctype,
|
doctype: doctype,
|
||||||
name: docname,
|
name: docname,
|
||||||
onSuccess: () => setupFormScript(),
|
onSuccess: async () => await setupFormScript(),
|
||||||
setValue: {
|
setValue: {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
toast.success(__('Document updated successfully'))
|
toast.success(__('Document updated successfully'))
|
||||||
@ -27,23 +27,49 @@ export function useDocument(doctype, docname) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupFormScript() {
|
async function setupFormScript() {
|
||||||
if (controllersCache[doctype]?.[docname]) return
|
if (
|
||||||
|
controllersCache[doctype] &&
|
||||||
|
typeof controllersCache[doctype][docname] === 'object'
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (!controllersCache[doctype]) {
|
if (!controllersCache[doctype]) {
|
||||||
controllersCache[doctype] = {}
|
controllersCache[doctype] = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
controllersCache[doctype][docname] = setupScript(
|
controllersCache[doctype][docname] = {}
|
||||||
documentsCache[doctype][docname],
|
|
||||||
)
|
const controllersArray = await setupScript(documentsCache[doctype][docname])
|
||||||
|
|
||||||
|
if (!controllersArray || controllersArray.length === 0) return
|
||||||
|
|
||||||
|
const organizedControllers = {}
|
||||||
|
for (const controller of controllersArray) {
|
||||||
|
const controllerKey = controller.constructor.name // e.g., "CRMLead", "CRMProducts"
|
||||||
|
if (!organizedControllers[controllerKey]) {
|
||||||
|
organizedControllers[controllerKey] = []
|
||||||
|
}
|
||||||
|
organizedControllers[controllerKey].push(controller)
|
||||||
|
}
|
||||||
|
controllersCache[doctype][docname] = organizedControllers
|
||||||
}
|
}
|
||||||
|
|
||||||
function getControllers(row = null) {
|
function getControllers(row = null) {
|
||||||
const _doctype = row?.doctype || doctype
|
const _doctype = row?.doctype || doctype
|
||||||
return (controllersCache[doctype]?.[docname] || []).filter(
|
const controllerKey = _doctype.replace(/\s+/g, '')
|
||||||
(c) => c.constructor.name === _doctype.replace(/\s+/g, ''),
|
|
||||||
)
|
const docControllers = controllersCache[doctype]?.[docname]
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof docControllers === 'object' &&
|
||||||
|
docControllers !== null &&
|
||||||
|
!Array.isArray(docControllers)
|
||||||
|
) {
|
||||||
|
return docControllers[controllerKey] || []
|
||||||
|
}
|
||||||
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
async function triggerOnRefresh() {
|
async function triggerOnRefresh() {
|
||||||
@ -100,7 +126,15 @@ export function useDocument(doctype, docname) {
|
|||||||
async function triggerOnCreateLead() {
|
async function triggerOnCreateLead() {
|
||||||
const args = Array.from(arguments)
|
const args = Array.from(arguments)
|
||||||
const handler = async function () {
|
const handler = async function () {
|
||||||
await this.on_create_lead(...args)
|
await this.on_create_lead?.(...args)
|
||||||
|
}
|
||||||
|
await trigger(handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function triggerConvertToDeal() {
|
||||||
|
const args = Array.from(arguments)
|
||||||
|
const handler = async function () {
|
||||||
|
await this.convert_to_deal?.(...args)
|
||||||
}
|
}
|
||||||
await trigger(handler)
|
await trigger(handler)
|
||||||
}
|
}
|
||||||
@ -139,5 +173,6 @@ export function useDocument(doctype, docname) {
|
|||||||
triggerOnRefresh,
|
triggerOnRefresh,
|
||||||
setupFormScript,
|
setupFormScript,
|
||||||
triggerOnCreateLead,
|
triggerOnCreateLead,
|
||||||
|
triggerConvertToDeal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,15 +20,23 @@ export function getScript(doctype, view = 'Form') {
|
|||||||
doctypeScripts[doctype][script.name] = script || {}
|
doctypeScripts[doctype][script.name] = script || {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onError: (err) => {
|
||||||
|
console.error(
|
||||||
|
`Error loading CRM Form Scripts for ${doctype} (view: ${view}):`,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!doctypeScripts[doctype] && !scripts.loading) {
|
if (!doctypeScripts[doctype] && !scripts.loading) {
|
||||||
scripts.fetch()
|
scripts.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupScript(document, helpers = {}) {
|
async function setupScript(document, helpers = {}) {
|
||||||
let scripts = doctypeScripts[doctype]
|
await scripts.promise
|
||||||
if (!scripts) return null
|
|
||||||
|
let scriptDefs = doctypeScripts[doctype]
|
||||||
|
if (!scriptDefs || Object.keys(scriptDefs).length === 0) return null
|
||||||
|
|
||||||
const { $dialog, $socket, makeCall } = globalStore()
|
const { $dialog, $socket, makeCall } = globalStore()
|
||||||
|
|
||||||
@ -42,7 +50,7 @@ export function getScript(doctype, view = 'Form') {
|
|||||||
makePhoneCall: makeCall,
|
makePhoneCall: makeCall,
|
||||||
}
|
}
|
||||||
|
|
||||||
return setupMultipleFormControllers(scripts, document, helpers)
|
return setupMultipleFormControllers(scriptDefs, document, helpers)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupMultipleFormControllers(scriptStrings, document, helpers) {
|
function setupMultipleFormControllers(scriptStrings, document, helpers) {
|
||||||
@ -126,10 +134,10 @@ export function getScript(doctype, view = 'Form') {
|
|||||||
return meta[doctype]
|
return meta[doctype]
|
||||||
}
|
}
|
||||||
|
|
||||||
setupHelperMethods(FormClass, document)
|
const getDoc = () => document.doc
|
||||||
|
|
||||||
if (isChildDoctype) {
|
if (isChildDoctype) {
|
||||||
instance.doc = createDocProxy(document.doc, parentInstance, instance)
|
instance.doc = createDocProxy(getDoc, parentInstance, instance)
|
||||||
|
|
||||||
if (!parentInstance._childInstances) {
|
if (!parentInstance._childInstances) {
|
||||||
parentInstance._childInstances = []
|
parentInstance._childInstances = []
|
||||||
@ -137,22 +145,21 @@ export function getScript(doctype, view = 'Form') {
|
|||||||
|
|
||||||
parentInstance._childInstances.push(instance)
|
parentInstance._childInstances.push(instance)
|
||||||
} else {
|
} else {
|
||||||
instance.doc = createDocProxy(document.doc, instance)
|
instance.doc = createDocProxy(getDoc, instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupHelperMethods(FormClass, document) {
|
function setupHelperMethods(FormClass) {
|
||||||
if (typeof FormClass.prototype.getRow !== 'function') {
|
if (typeof FormClass.prototype.getRow !== 'function') {
|
||||||
FormClass.prototype.getRow = function (parentField, idx) {
|
FormClass.prototype.getRow = function (parentField, idx) {
|
||||||
let data = document.doc
|
|
||||||
idx = idx || this.currentRowIdx
|
idx = idx || this.currentRowIdx
|
||||||
|
|
||||||
let dt = null
|
let dt = null
|
||||||
|
|
||||||
if (this instanceof Array) {
|
if (this instanceof Array) {
|
||||||
const { getFields } = getMeta(data.doctype)
|
const { getFields } = getMeta(this.doc.doctype)
|
||||||
let fields = getFields()
|
let fields = getFields()
|
||||||
let field = fields.find((f) => f.fieldname === parentField)
|
let field = fields.find((f) => f.fieldname === parentField)
|
||||||
dt = field?.options?.replace(/\s+/g, '')
|
dt = field?.options?.replace(/\s+/g, '')
|
||||||
@ -162,13 +169,13 @@ export function getScript(doctype, view = 'Form') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data[parentField]) {
|
if (!this.doc[parentField]) {
|
||||||
console.warn(
|
console.warn(
|
||||||
__('⚠️ No data found for parent field: {0}', [parentField]),
|
__('⚠️ No data found for parent field: {0}', [parentField]),
|
||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const row = data[parentField].find((r) => r.idx === idx)
|
const row = this.doc[parentField].find((r) => r.idx === idx)
|
||||||
|
|
||||||
if (!row) {
|
if (!row) {
|
||||||
console.warn(
|
console.warn(
|
||||||
@ -180,7 +187,7 @@ export function getScript(doctype, view = 'Form') {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
row.parent = row.parent || data.name
|
row.parent = row.parent || this.doc.name
|
||||||
|
|
||||||
if (this instanceof Array && dt) {
|
if (this instanceof Array && dt) {
|
||||||
return createDocProxy(
|
return createDocProxy(
|
||||||
@ -220,46 +227,76 @@ export function getScript(doctype, view = 'Form') {
|
|||||||
const FormClass = new Function(...helperKeys, wrappedScript)(
|
const FormClass = new Function(...helperKeys, wrappedScript)(
|
||||||
...helperValues,
|
...helperValues,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
setupHelperMethods(FormClass)
|
||||||
|
|
||||||
return FormClass
|
return FormClass
|
||||||
}
|
}
|
||||||
|
|
||||||
function createDocProxy(data, instance, childInstance = null) {
|
function createDocProxy(source, instance, childInstance = null) {
|
||||||
return new Proxy(data, {
|
const isFunction = typeof source === 'function'
|
||||||
get(target, prop) {
|
const getCurrentData = () => (isFunction ? source() : source)
|
||||||
if (prop === 'trigger') {
|
|
||||||
if ('trigger' in data) {
|
return new Proxy(
|
||||||
console.warn(
|
{},
|
||||||
__(
|
{
|
||||||
'⚠️ Avoid using "trigger" as a field name — it conflicts with the built-in trigger() method.',
|
get(target, prop) {
|
||||||
),
|
const currentDocData = getCurrentData()
|
||||||
|
if (!currentDocData) return undefined
|
||||||
|
|
||||||
|
if (prop === 'trigger') {
|
||||||
|
if (currentDocData && 'trigger' in currentDocData) {
|
||||||
|
console.warn(
|
||||||
|
__(
|
||||||
|
'⚠️ Avoid using "trigger" as a field name — it conflicts with the built-in trigger() method.',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (methodName, ...args) => {
|
||||||
|
const method = instance[methodName]
|
||||||
|
if (typeof method === 'function') {
|
||||||
|
return method.apply(instance, args)
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
__('⚠️ Method "{0}" not found in class.', [methodName]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop === 'getRow') {
|
||||||
|
return instance.getRow.bind(
|
||||||
|
childInstance || instance._childInstances || instance,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (methodName, ...args) => {
|
return currentDocData[prop]
|
||||||
const method = instance[methodName]
|
},
|
||||||
if (typeof method === 'function') {
|
set(target, prop, value) {
|
||||||
return method.apply(instance, args)
|
const currentDocData = getCurrentData()
|
||||||
} else {
|
if (!currentDocData) return false
|
||||||
console.warn(
|
|
||||||
__('⚠️ Method "{0}" not found in class.', [methodName]),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prop === 'getRow') {
|
currentDocData[prop] = value
|
||||||
return instance.getRow.bind(
|
return true
|
||||||
childInstance || instance._childInstances || instance,
|
},
|
||||||
)
|
has(target, prop) {
|
||||||
}
|
const currentDocData = getCurrentData()
|
||||||
|
if (!currentDocData) return false
|
||||||
return target[prop]
|
return prop in currentDocData
|
||||||
|
},
|
||||||
|
ownKeys(target) {
|
||||||
|
const currentDocData = getCurrentData()
|
||||||
|
if (!currentDocData) return []
|
||||||
|
return Reflect.ownKeys(currentDocData)
|
||||||
|
},
|
||||||
|
getOwnPropertyDescriptor(target, prop) {
|
||||||
|
const currentDocData = getCurrentData()
|
||||||
|
if (!currentDocData) return undefined
|
||||||
|
return Reflect.getOwnPropertyDescriptor(currentDocData, prop)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
set(target, prop, value) {
|
)
|
||||||
target[prop] = value
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -355,6 +355,7 @@ import { usersStore } from '@/stores/users'
|
|||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { statusesStore } from '@/stores/statuses'
|
import { statusesStore } from '@/stores/statuses'
|
||||||
import { getMeta } from '@/stores/meta'
|
import { getMeta } from '@/stores/meta'
|
||||||
|
import { useDocument } from '@/data/document'
|
||||||
import {
|
import {
|
||||||
whatsappEnabled,
|
whatsappEnabled,
|
||||||
callEnabled,
|
callEnabled,
|
||||||
@ -614,6 +615,8 @@ const existingOrganizationChecked = ref(false)
|
|||||||
const existingContact = ref('')
|
const existingContact = ref('')
|
||||||
const existingOrganization = ref('')
|
const existingOrganization = ref('')
|
||||||
|
|
||||||
|
const { triggerConvertToDeal } = useDocument('CRM Lead', props.leadId)
|
||||||
|
|
||||||
async function convertToDeal() {
|
async function convertToDeal() {
|
||||||
if (existingContactChecked.value && !existingContact.value) {
|
if (existingContactChecked.value && !existingContact.value) {
|
||||||
toast.error(__('Please select an existing contact'))
|
toast.error(__('Please select an existing contact'))
|
||||||
@ -633,6 +636,12 @@ async function convertToDeal() {
|
|||||||
existingOrganization.value = ''
|
existingOrganization.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await triggerConvertToDeal?.(
|
||||||
|
lead.data,
|
||||||
|
deal,
|
||||||
|
() => (showConvertToDealModal.value = false),
|
||||||
|
)
|
||||||
|
|
||||||
let _deal = await call('crm.fcrm.doctype.crm_lead.crm_lead.convert_to_deal', {
|
let _deal = await call('crm.fcrm.doctype.crm_lead.crm_lead.convert_to_deal', {
|
||||||
lead: lead.data.name,
|
lead: lead.data.name,
|
||||||
deal,
|
deal,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user