fix: add validation for mandatory fields in useDocument

(cherry picked from commit dbcda4c548270f4b030d819857b1f393fdaadecb)
This commit is contained in:
Shariq Ansari 2025-09-25 21:41:02 +05:30 committed by Mergify
parent 4989dc0921
commit ff4ca9fe66
2 changed files with 71 additions and 1 deletions

View File

@ -1,7 +1,8 @@
import { getScript } from '@/data/script' import { getScript } from '@/data/script'
import { globalStore } from '@/stores/global' import { globalStore } from '@/stores/global'
import { getMeta } from '@/stores/meta'
import { showSettings, activeSettingsPage } from '@/composables/settings' 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 { createDocumentResource, createResource, toast } from 'frappe-ui'
import { ref, reactive } from 'vue' import { ref, reactive } from 'vue'
@ -11,6 +12,7 @@ const assigneesCache = {}
export function useDocument(doctype, docname) { export function useDocument(doctype, docname) {
const { setupScript, scripts } = getScript(doctype) const { setupScript, scripts } = getScript(doctype)
const meta = getMeta(doctype)
documentsCache[doctype] = documentsCache[doctype] || {} documentsCache[doctype] = documentsCache[doctype] || {}
@ -37,6 +39,7 @@ export function useDocument(doctype, docname) {
} }
}, },
setValue: { setValue: {
validate,
onSuccess: () => { onSuccess: () => {
triggerOnSave() triggerOnSave()
toast.success(__('Document updated successfully')) toast.success(__('Document updated successfully'))
@ -152,6 +155,42 @@ export function useDocument(doctype, docname) {
return [] 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() { async function triggerOnLoad() {
const handler = async function () { const handler = async function () {
await (this.onLoad?.() || this.on_load?.() || this.onload?.()) await (this.onLoad?.() || this.on_load?.() || this.onload?.())
@ -280,6 +319,7 @@ export function useDocument(doctype, docname) {
assignees: assigneesCache[doctype][docname || ''], assignees: assigneesCache[doctype][docname || ''],
scripts, scripts,
error, error,
validate,
getControllers, getControllers,
triggerOnLoad, triggerOnLoad,
triggerOnBeforeCreate, triggerOnBeforeCreate,

View File

@ -421,6 +421,36 @@ export function evaluateDependsOnValue(expression, doc) {
return out 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) { export function convertSize(size) {
const units = ['B', 'KB', 'MB', 'GB', 'TB'] const units = ['B', 'KB', 'MB', 'GB', 'TB']
let unitIndex = 0 let unitIndex = 0