// Manager Approval Form Custom Script Engine // This script provides dynamic behavior for the manager approval form console.log("Manager Approval Form Script Loaded"); // Auto-set approval date to today const setApprovalDate = () => { const today = new Date(); const formattedDate = today.toISOString().split("T")[0]; // YYYY-MM-DD format setField("approval_date", formattedDate); }; // Calculate and display recommended approval amounts const calculateRecommendedAmounts = () => { const totalClaimed = parseFloat(getField("total_cost_display")) || 0; const policyLimit = parseFloat(getField("policy_limit_display")) || 0; const overBudget = parseFloat(getField("over_budget_amount")) || 0; if (totalClaimed > 0 && policyLimit > 0) { const percentageOver = ((overBudget / policyLimit) * 100).toFixed(1); showInfo( `This claim is ${percentageOver}% over the policy limit. Policy limit: RM${policyLimit.toFixed(2)}, Claimed: RM${totalClaimed.toFixed(2)}` ); } }; // Validate manager decision and provide guidance const handleDecisionChange = (decision) => { const totalClaimed = parseFloat(getField("total_cost_display")) || 0; const policyLimit = parseFloat(getField("policy_limit_display")) || 0; console.log("Manager decision changed to:", decision); switch (decision) { case "approve_full": showField("custom_approved_amount"); showInfo( `💰 Approving full amount: RM${totalClaimed.toFixed(2)}. You can enter a custom amount if needed.` ); setField("custom_approved_amount", totalClaimed.toString()); break; case "approve_policy": hideField("custom_approved_amount"); showInfo( `⚖️ Approving policy limit only: RM${policyLimit.toFixed(2)}. Employee will be notified of the reduced amount.` ); break; case "reject": hideField("custom_approved_amount"); showError( "❌ Claim will be rejected. Please provide detailed comments explaining the rejection reason." ); break; default: hideField("custom_approved_amount"); } }; // Validate custom approved amount const validateCustomAmount = (amount) => { const numAmount = parseFloat(amount) || 0; const totalClaimed = parseFloat(getField("total_cost_display")) || 0; const policyLimit = parseFloat(getField("policy_limit_display")) || 0; if (numAmount < 0) { showError("Approved amount cannot be negative"); return false; } if (numAmount > totalClaimed) { showError( `Approved amount (RM${numAmount}) cannot exceed claimed amount (RM${totalClaimed})` ); return false; } if (numAmount > 0 && numAmount < policyLimit) { showInfo( `Custom amount (RM${numAmount}) is less than policy limit (RM${policyLimit}). Consider approving policy limit instead.` ); } return true; }; // Validate manager comments based on decision const validateComments = (comments, decision) => { if (!comments || comments.trim().length < 10) { showError("Please provide detailed comments (minimum 10 characters)"); return false; } if (decision === "reject" && comments.length < 50) { showError( "Rejection requires detailed explanation (minimum 50 characters)" ); return false; } if (decision === "approve_full") { const totalClaimed = parseFloat(getField("total_cost_display")) || 0; const policyLimit = parseFloat(getField("policy_limit_display")) || 0; const overBudget = totalClaimed - policyLimit; if (overBudget > 500 && !comments.toLowerCase().includes("business")) { showInfo( "Consider mentioning business justification for approving over-budget amounts > RM500" ); } } return true; }; // Format manager name (title case) const formatManagerName = (name) => { if (!name || typeof name !== "string") return name; return name .toLowerCase() .split(" ") .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(" "); }; // Form validation before submission const validateApprovalForm = () => { let isValid = true; const errors = []; // Check required fields const requiredFields = { manager_decision: "Approval Decision", manager_comments: "Manager Comments", manager_name: "Manager Name", approval_date: "Approval Date", }; Object.entries(requiredFields).forEach(([fieldName, displayName]) => { const value = getField(fieldName); if (!value || value.toString().trim() === "") { errors.push(`${displayName} is required`); isValid = false; } }); // Validate decision-specific requirements const decision = getField("manager_decision"); const comments = getField("manager_comments"); const customAmount = getField("custom_approved_amount"); if (decision && comments) { if (!validateComments(comments, decision)) { isValid = false; } } if (decision === "approve_full" && customAmount) { if (!validateCustomAmount(customAmount)) { isValid = false; } } // Validate approval date is not in the future const approvalDate = getField("approval_date"); if (approvalDate) { const selectedDate = new Date(approvalDate); const today = new Date(); today.setHours(23, 59, 59, 999); // End of today if (selectedDate > today) { errors.push("Approval date cannot be in the future"); isValid = false; } } // Show validation results if (errors.length > 0) { showError(`Please fix the following errors:\n• ${errors.join("\n• ")}`); } else { showSuccess("Form validation passed! Ready to submit approval decision."); } return isValid; }; // Set up field change handlers onFieldChange("manager_decision", (newValue) => { if (newValue) { handleDecisionChange(newValue); } }); onFieldChange("custom_approved_amount", (newValue) => { if (newValue) { validateCustomAmount(newValue); } }); onFieldChange("manager_comments", (newValue) => { const decision = getField("manager_decision"); if (newValue && decision) { validateComments(newValue, decision); } }); onFieldChange("manager_name", (newValue) => { if (newValue && typeof newValue === "string") { const formatted = formatManagerName(newValue); if (formatted !== newValue) { setTimeout(() => { setField("manager_name", formatted); }, 100); } } }); // Wait until all required fields are present before running initialization function waitForFields(fields, callback, maxAttempts = 20) { let attempts = 0; function check() { const allPresent = fields.every((f) => getField(f) !== undefined); if (allPresent) { callback(); } else if (attempts < maxAttempts) { attempts++; setTimeout(check, 100); } else { showError("Some required fields are missing. Please reload the page."); } } check(); } waitForFields( [ "total_cost_display", "policy_limit_display", "over_budget_amount", // add any other required fields here ], () => { setApprovalDate(); calculateRecommendedAmounts(); showInfo( "Review the claim details above and make your approval decision below." ); } ); // Expose validation function for form submission window.validateManagerApprovalForm = validateApprovalForm; console.log("Manager Approval Form Script initialized successfully"); // Conditional logic for field: custom_approved_amount onFieldChange("manager_decision", function () { if (getField("manager_decision") === "approve_full") { showField("custom_approved_amount"); } else { hideField("custom_approved_amount"); } }); // Initial evaluation for field: custom_approved_amount (function () { if (getField("manager_decision") === "approve_full") { showField("custom_approved_amount"); } else { hideField("custom_approved_amount"); } })(); // Conditional Logic Script // Conditional logic for field: custom_approved_amount onFieldChange("manager_decision", function () { if (getField("manager_decision") === "approve_full") { showField("custom_approved_amount"); } else { hideField("custom_approved_amount"); } }); // Initial evaluation for field: custom_approved_amount (function () { if (getField("manager_decision") === "approve_full") { showField("custom_approved_amount"); } else { hideField("custom_approved_amount"); } })();