1
0
forked from test/crm

Merge pull request #1283 from frappe/mergify/bp/main-hotfix/pr-1282

fix: add validation for mandatory fields in useDocument (backport #1282)
This commit is contained in:
Shariq Ansari 2025-09-25 21:53:09 +05:30 committed by GitHub
commit 105c78e264
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 71 additions and 1 deletions

View File

@ -1,7 +1,8 @@
import { getScript } from '@/data/script'
import { globalStore } from '@/stores/global'
import { getMeta } from '@/stores/meta'
import { showSettings, activeSettingsPage } from '@/composables/settings'
import { runSequentially, parseAssignees } from '@/utils'
import { runSequentially, parseAssignees, evaluateExpression } from '@/utils'
import { createDocumentResource, createResource, toast } from 'frappe-ui'
import { ref, reactive } from 'vue'
@ -11,6 +12,7 @@ const assigneesCache = {}
export function useDocument(doctype, docname) {
const { setupScript, scripts } = getScript(doctype)
const meta = getMeta(doctype)
documentsCache[doctype] = documentsCache[doctype] || {}
@ -37,6 +39,7 @@ export function useDocument(doctype, docname) {
}
},
setValue: {
validate,
onSuccess: () => {
triggerOnSave()
toast.success(__('Document updated successfully'))
@ -152,6 +155,42 @@ export function useDocument(doctype, docname) {
return []
}
function validate(d) {
checkMandatory(d.doc || d.fieldname)
}
function checkMandatory(doc) {
let fields = meta?.getFields() || []
if (!fields || fields.length === 0) return
let missingFields = []
fields.forEach((df) => {
let parent = meta?.doctypeMeta?.[df.parent] || null
if (evaluateExpression(df.mandatory_depends_on, doc, parent)) {
const value = doc[df.fieldname]
if (
value === undefined ||
value === null ||
(typeof value === 'string' && value.trim() === '') ||
(Array.isArray(value) && value.length === 0)
) {
missingFields.push(df.label || df.fieldname)
}
}
})
if (missingFields.length > 0) {
toast.error(
__('Mandatory fields required: {0}', [missingFields.join(', ')]),
)
throw new Error(
__('Mandatory fields required: {0}', [missingFields.join(', ')]),
)
}
}
async function triggerOnLoad() {
const handler = async function () {
await (this.onLoad?.() || this.on_load?.() || this.onload?.())
@ -280,6 +319,7 @@ export function useDocument(doctype, docname) {
assignees: assigneesCache[doctype][docname || ''],
scripts,
error,
validate,
getControllers,
triggerOnLoad,
triggerOnBeforeCreate,

View File

@ -421,6 +421,36 @@ export function evaluateDependsOnValue(expression, doc) {
return out
}
export function evaluateExpression(expression, doc, parent) {
if (!expression) return false
if (!doc) return false
let out = null
if (typeof expression === 'boolean') {
out = expression
} else if (typeof expression === 'function') {
out = expression(doc)
} else if (expression.substr(0, 5) == 'eval:') {
try {
out = _eval(expression.substr(5), { doc, parent })
if (parent && parent.istable && expression.includes('is_submittable')) {
out = true
}
} catch (e) {
out = true
}
} else {
let value = doc[expression]
if (Array.isArray(value)) {
out = !!value.length
} else {
out = !!value
}
}
return out
}
export function convertSize(size) {
const units = ['B', 'KB', 'MB', 'GB', 'TB']
let unitIndex = 0