diff --git a/components/process-flow/VariableManager.vue b/components/process-flow/VariableManager.vue index b3b8c2e..5b8a1c4 100644 --- a/components/process-flow/VariableManager.vue +++ b/components/process-flow/VariableManager.vue @@ -518,8 +518,7 @@ const variableForm = ref({ // Variable type options with descriptions const variableTypes = [ { label: 'String - Text values', value: 'string' }, - { label: 'Int - Whole numbers', value: 'int' }, - { label: 'Decimal - Decimal numbers', value: 'decimal' }, + { label: 'Number - Decimal numbers', value: 'number' }, { label: 'Object - Complex data structure', value: 'object' }, { label: 'DateTime - Date and time values', value: 'datetime' }, { label: 'Date - Date values only', value: 'date' }, diff --git a/docs/json/form/manager-approval-customScript.js b/docs/json/form/manager-approval-customScript.js index dd42bb1..66483a4 100644 --- a/docs/json/form/manager-approval-customScript.js +++ b/docs/json/form/manager-approval-customScript.js @@ -14,7 +14,7 @@ const setApprovalDate = () => { 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_display")) || 0; + const overBudget = parseFloat(getField("over_budget_amount")) || 0; if (totalClaimed > 0 && policyLimit > 0) { const percentageOver = ((overBudget / policyLimit) * 100).toFixed(1); @@ -222,7 +222,7 @@ onFieldChange("manager_name", (newValue) => { function waitForFields(fields, callback, maxAttempts = 20) { let attempts = 0; function check() { - const allPresent = fields.every(f => getField(f) !== undefined); + const allPresent = fields.every((f) => getField(f) !== undefined); if (allPresent) { callback(); } else if (attempts < maxAttempts) { @@ -239,13 +239,15 @@ waitForFields( [ "total_cost_display", "policy_limit_display", - "over_budget_amount_display", + "over_budget_amount", // add any other required fields here ], () => { setApprovalDate(); calculateRecommendedAmounts(); - showInfo("Review the claim details above and make your approval decision below."); + showInfo( + "Review the claim details above and make your approval decision below." + ); } ); @@ -271,3 +273,23 @@ onFieldChange("manager_decision", function () { 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"); + } +})(); diff --git a/docs/json/form/manager-approval-form.json b/docs/json/form/manager-approval-form.json index 018d51e..c9500af 100644 --- a/docs/json/form/manager-approval-form.json +++ b/docs/json/form/manager-approval-form.json @@ -54,6 +54,7 @@ "type": "text", "label": "Claim Summary", "width": "100%", + "readonly": true, "gridColumn": "span 12", "validation": "", "placeholder": "Claim summary will be populated from process", @@ -73,6 +74,7 @@ "type": "text", "label": "Employee Name", "width": "50%", + "readonly": true, "gridColumn": "span 6", "validation": "", "placeholder": "Employee name", @@ -92,6 +94,7 @@ "type": "text", "label": "Department", "width": "50%", + "readonly": true, "gridColumn": "span 6", "validation": "", "placeholder": "Department", @@ -111,6 +114,7 @@ "type": "text", "label": "Trip Purpose", "width": "50%", + "readonly": true, "gridColumn": "span 6", "validation": "", "placeholder": "Trip purpose", @@ -130,6 +134,7 @@ "type": "text", "label": "Destination", "width": "50%", + "readonly": true, "gridColumn": "span 6", "validation": "", "placeholder": "Destination", @@ -165,9 +170,16 @@ "type": "number", "label": "Total Claimed Amount (RM)", "width": "33.33%", + "readonly": true, "gridColumn": "span 4", "validation": "", - "placeholder": "0.00" + "placeholder": "0.00", + "conditionalLogic": { + "action": "show", + "enabled": false, + "operator": "and", + "conditions": [] + } } }, { @@ -178,22 +190,36 @@ "type": "number", "label": "Policy Limit (RM)", "width": "33.33%", + "readonly": true, "gridColumn": "span 4", "validation": "", - "placeholder": "0.00" + "placeholder": "0.00", + "conditionalLogic": { + "action": "show", + "enabled": false, + "operator": "and", + "conditions": [] + } } }, { "type": "number", "props": { "help": "Amount exceeding policy limits", - "name": "over_budget_amount_display", + "name": "over_budget_amount", "type": "number", "label": "Over Budget Amount (RM)", "width": "33.33%", + "readonly": true, "gridColumn": "span 4", "validation": "", - "placeholder": "0.00" + "placeholder": "0.00", + "conditionalLogic": { + "action": "show", + "enabled": false, + "operator": "and", + "conditions": [] + } } }, { diff --git a/docs/json/process-builder/travel-workflow-process.json b/docs/json/process-builder/travel-workflow-process.json index 8659062..55819ad 100644 --- a/docs/json/process-builder/travel-workflow-process.json +++ b/docs/json/process-builder/travel-workflow-process.json @@ -55,50 +55,6 @@ "sourceHandle": "script-1753000005-right", "targetHandle": "gateway-1753000006-left" }, - { - "id": "gateway-1753000006-form-1753000007-edge", - "data": { "condition": "isOverBudget === true" }, - "type": "custom", - "label": "Requires Approval", - "source": "gateway-1753000006", - "target": "form-1753000007", - "animated": true, - "sourceHandle": "gateway-1753000006-top", - "targetHandle": "form-1753000007-left" - }, - { - "id": "gateway-1753000006-script-1753000008-edge", - "data": { "condition": "isOverBudget === false" }, - "type": "custom", - "label": "Auto Approve", - "source": "gateway-1753000006", - "target": "script-1753000008", - "animated": true, - "sourceHandle": "gateway-1753000006-bottom", - "targetHandle": "script-1753000008-left" - }, - { - "id": "form-1753000007-script-1753000009-edge", - "data": {}, - "type": "custom", - "label": "", - "source": "form-1753000007", - "target": "script-1753000009", - "animated": true, - "sourceHandle": "form-1753000007-right", - "targetHandle": "script-1753000009-left" - }, - { - "id": "script-1753000008-notification-1753000010-edge", - "data": {}, - "type": "custom", - "label": "", - "source": "script-1753000008", - "target": "notification-1753000010", - "animated": true, - "sourceHandle": "script-1753000008-right", - "targetHandle": "notification-1753000010-left" - }, { "id": "script-1753000009-notification-1753000011-edge", "data": {}, @@ -131,21 +87,65 @@ "animated": true, "sourceHandle": "notification-1753000011-bottom", "targetHandle": "end-1753000012-top" + }, + { + "id": "form-1753000007-script-set-approved-amount-1753423747167", + "data": {}, + "type": "custom", + "label": "", + "source": "form-1753000007", + "target": "script-set-approved-amount", + "animated": true, + "sourceHandle": "form-1753000007-right", + "targetHandle": "script-set-approved-amount-left" + }, + { + "id": "script-set-approved-amount-script-1753000009-1753423748408", + "data": {}, + "type": "custom", + "label": "", + "source": "script-set-approved-amount", + "target": "script-1753000009", + "animated": true, + "sourceHandle": "script-set-approved-amount-right", + "targetHandle": "script-1753000009-left" + }, + { + "id": "gateway-1753000006-form-1753000007-1753423756117", + "data": {}, + "type": "custom", + "label": "Requires Approval", + "source": "gateway-1753000006", + "target": "form-1753000007", + "animated": true, + "sourceHandle": "gateway-1753000006-right", + "targetHandle": "form-1753000007-left" + }, + { + "id": "gateway-1753000006-notification-1753000010-1753423759335", + "data": {}, + "type": "custom", + "label": "Auto Approve", + "source": "gateway-1753000006", + "target": "notification-1753000010", + "animated": true, + "sourceHandle": "gateway-1753000006-right", + "targetHandle": "notification-1753000010-left" } ], "nodes": [ { "id": "start-1753000001", - "data": { - "label": "Start Travel Claim", - "description": "Employee initiates travel reimbursement claim", + "data": { + "label": "Start Travel Claim", "shape": "circle", - "backgroundColor": "#dcfce7", - "borderColor": "#10b981" + "borderColor": "#10b981", + "description": "Employee initiates travel reimbursement claim", + "backgroundColor": "#dcfce7" }, "type": "start", "label": "Start Travel Claim", - "position": { "x": 100, "y": 300 } + "position": { "x": 105, "y": 300 } }, { "id": "form-1753000002", @@ -159,7 +159,11 @@ "borderColor": "#9333ea", "description": "Employee fills travel reimbursement claim form", "assignedRoles": [ - { "label": "Employee", "value": "3", "description": "Regular employee role" } + { + "label": "Employee", + "value": "3", + "description": "Regular employee role" + } ], "assignedUsers": [], "inputMappings": [], @@ -174,7 +178,10 @@ { "formField": "return_date", "processVariable": "returnDate" }, { "formField": "travel_type", "processVariable": "travelType" }, { "formField": "transport_cost", "processVariable": "transportCost" }, - { "formField": "accommodation_cost", "processVariable": "accommodationCost" }, + { + "formField": "accommodation_cost", + "processVariable": "accommodationCost" + }, { "formField": "meals_cost", "processVariable": "mealsCost" }, { "formField": "other_cost", "processVariable": "otherCost" }, { "formField": "has_receipts", "processVariable": "hasReceipts" } @@ -186,7 +193,7 @@ }, "type": "form", "label": "Travel Claim Form", - "position": { "x": 400, "y": 270 } + "position": { "x": 405, "y": 270 } }, { "id": "script-1753000003", @@ -198,8 +205,15 @@ "borderColor": "#6b7280", "description": "Validate form data and calculate totals", "inputVariables": [ - "employeeName", "tripPurpose", "destination", "transportCost", - "accommodationCost", "mealsCost", "otherCost", "departureDate", "returnDate" + "employeeName", + "tripPurpose", + "destination", + "transportCost", + "accommodationCost", + "mealsCost", + "otherCost", + "departureDate", + "returnDate" ], "scriptLanguage": "javascript", "backgroundColor": "#f9fafb", @@ -260,7 +274,7 @@ }, "type": "api", "label": "Get Policy Rates", - "position": { "x": 1100, "y": 270 } + "position": { "x": 1095, "y": 270 } }, { "id": "script-1753000005", @@ -271,7 +285,12 @@ "scriptCode": "// Process policy API response\nconst policyResponse = processVariables.policyApiResponse || {};\n\n// Mock policy rates based on travel type (in real system, would come from API)\nlet maxTransport = 0, maxAccommodation = 0, maxMeals = 0, maxOther = 0;\n\nswitch(processVariables.travelType) {\n case 'flight':\n maxTransport = 2000;\n maxAccommodation = 300 * processVariables.tripDuration;\n maxMeals = 150 * processVariables.tripDuration;\n maxOther = 100 * processVariables.tripDuration;\n break;\n case 'train':\n maxTransport = 500;\n maxAccommodation = 250 * processVariables.tripDuration;\n maxMeals = 120 * processVariables.tripDuration;\n maxOther = 80 * processVariables.tripDuration;\n break;\n case 'car':\n maxTransport = 800;\n maxAccommodation = 200 * processVariables.tripDuration;\n maxMeals = 100 * processVariables.tripDuration;\n maxOther = 60 * processVariables.tripDuration;\n break;\n default:\n maxTransport = 300;\n maxAccommodation = 150 * processVariables.tripDuration;\n maxMeals = 80 * processVariables.tripDuration;\n maxOther = 50 * processVariables.tripDuration;\n}\n\n// Calculate allowed amounts\nprocessVariables.allowedTransport = Math.min(processVariables.transportCost, maxTransport);\nprocessVariables.allowedAccommodation = Math.min(processVariables.accommodationCost, maxAccommodation);\nprocessVariables.allowedMeals = Math.min(processVariables.mealsCost, maxMeals);\nprocessVariables.allowedOther = Math.min(processVariables.otherCost, maxOther);\n\n// Calculate total allowed and reimbursement\nprocessVariables.totalAllowed = processVariables.allowedTransport + processVariables.allowedAccommodation + processVariables.allowedMeals + processVariables.allowedOther;\nprocessVariables.reimbursementAmount = processVariables.totalAllowed;\n\n// Check if over budget\nprocessVariables.isOverBudget = processVariables.totalCost > processVariables.totalAllowed;\nprocessVariables.overBudgetAmount = Math.max(0, processVariables.totalCost - processVariables.totalAllowed);\n\n// Create claim summary\nprocessVariables.claimSummary = `Travel Claim - ${processVariables.employeeName} - ${processVariables.tripPurpose} - ${processVariables.destination} - RM${processVariables.reimbursementAmount.toFixed(2)} reimbursement`;\n\n// Set initial approval status\nprocessVariables.approvalStatus = processVariables.isOverBudget ? 'pending_approval' : 'auto_approved';", "borderColor": "#6b7280", "description": "Calculate reimbursement based on policy rates", - "inputVariables": ["policyApiResponse", "totalCost", "travelType", "tripDuration"], + "inputVariables": [ + "policyApiResponse", + "totalCost", + "travelType", + "tripDuration" + ], "scriptLanguage": "javascript", "backgroundColor": "#f9fafb", "outputVariables": [ @@ -309,7 +328,7 @@ }, "type": "script", "label": "Calculate Reimbursement", - "position": { "x": 1450, "y": 270 } + "position": { "x": 1455, "y": 270 } }, { "id": "gateway-1753000006", @@ -358,7 +377,7 @@ }, "type": "gateway", "label": "Budget Check", - "position": { "x": 1800, "y": 270 } + "position": { "x": 1755, "y": 330 } }, { "id": "form-1753000007", @@ -368,71 +387,68 @@ "formId": 3, "formName": "Travel Claim Approval Form", "formUuid": "travel-approval-form-uuid", - "textColor": "#dc2626", - "borderColor": "#ef4444", + "textColor": "#6b21a8", + "borderColor": "#9333ea", "description": "Manager reviews and approves/rejects over-budget travel claim", "assignedRoles": [ - { "label": "Manager", "value": "4", "description": "Department manager role" } + { + "label": "Manager", + "value": "4", + "description": "Department manager role" + } ], "assignedUsers": [], "inputMappings": [ - { "processVariable": "claimSummary", "formField": "claim_summary" }, - { "processVariable": "totalCost", "formField": "total_cost_display" }, - { "processVariable": "overBudgetAmount", "formField": "over_budget_amount_display" }, - { "processVariable": "totalAllowed", "formField": "policy_limit_display" } + { "formField": "claim_summary", "processVariable": "claimSummary" }, + { + "formField": "employee_name_display", + "processVariable": "employeeName" + }, + { + "formField": "department_display", + "processVariable": "department" + }, + { + "formField": "trip_purpose_display", + "processVariable": "tripPurpose" + }, + { + "formField": "destination_display", + "processVariable": "destination" + }, + { "formField": "total_cost_display", "processVariable": "totalCost" }, + { + "formField": "policy_limit_display", + "processVariable": "totalAllowed" + }, + { + "formField": "over_budget_amount", + "processVariable": "overBudgetAmount" + } ], "assignmentType": "roles", "outputMappings": [ - { "formField": "manager_decision", "processVariable": "managerDecision" }, - { "formField": "manager_comments", "processVariable": "managerComments" } + { + "formField": "manager_decision", + "processVariable": "managerDecision" + }, + { + "formField": "manager_comments", + "processVariable": "managerComments" + }, + { + "formField": "custom_approved_amount", + "processVariable": "customApprovedAmount" + } ], - "backgroundColor": "#fef2f2", + "backgroundColor": "#faf5ff", "fieldConditions": [], "assignmentVariable": "", "assignmentVariableType": "user_id" }, "type": "form", "label": "Manager Approval", - "position": { "x": 2150, "y": 100 } - }, - { - "id": "script-1753000008", - "data": { - "label": "Auto Approve & Store", - "shape": "rectangle", - "textColor": "#374151", - "scriptCode": "// Auto-approve claim within budget\nprocessVariables.finalApprovalStatus = 'approved';\nprocessVariables.approvedAmount = processVariables.reimbursementAmount;\nprocessVariables.approvalTimestamp = new Date().toISOString();\nprocessVariables.approvedBy = 'System (Auto-approved)';\nprocessVariables.approvalComments = 'Claim is within policy limits and auto-approved.';\n\n// Create final claim record for storage\nprocessVariables.finalClaimRecord = {\n employeeName: processVariables.employeeName,\n employeeEmail: processVariables.employeeEmail,\n department: processVariables.department,\n tripPurpose: processVariables.tripPurpose,\n destination: processVariables.destination,\n totalClaimed: processVariables.totalCost,\n approvedAmount: processVariables.approvedAmount,\n status: processVariables.finalApprovalStatus,\n submissionDate: processVariables.submissionTimestamp,\n approvalDate: processVariables.approvalTimestamp,\n approvedBy: processVariables.approvedBy\n};\n\n// Mock API call to store claim (in real system, would call actual storage API)\nprocessVariables.claimId = 'CLAIM-' + Date.now();\nprocessVariables.storageResult = 'success';", - "borderColor": "#10b981", - "description": "Auto-approve claim and store in system", - "inputVariables": ["reimbursementAmount", "claimSummary"], - "scriptLanguage": "javascript", - "backgroundColor": "#f0fdf4", - "outputVariables": [ - { - "name": "finalApprovalStatus", - "type": "string", - "description": "Final approval status" - }, - { - "name": "approvedAmount", - "type": "number", - "description": "Final approved amount" - }, - { - "name": "claimId", - "type": "string", - "description": "Generated claim ID" - }, - { - "name": "approvalTimestamp", - "type": "string", - "description": "When claim was approved" - } - ] - }, - "type": "script", - "label": "Auto Approve & Store", - "position": { "x": 2150, "y": 440 } + "position": { "x": 1980, "y": 105 } }, { "id": "script-1753000009", @@ -440,7 +456,7 @@ "label": "Process Manager Decision", "shape": "rectangle", "textColor": "#374151", - "scriptCode": "// Process manager's decision\nprocessVariables.finalApprovalStatus = processVariables.managerDecision === 'approve' ? 'approved' : 'rejected';\nprocessVariables.approvalTimestamp = new Date().toISOString();\nprocessVariables.approvedBy = 'Manager';\nprocessVariables.approvalComments = processVariables.managerComments || '';\n\n// Set approved amount based on decision\nif (processVariables.finalApprovalStatus === 'approved') {\n processVariables.approvedAmount = processVariables.totalCost; // Manager can approve full amount\n} else {\n processVariables.approvedAmount = 0;\n}\n\n// Create final claim record for storage\nprocessVariables.finalClaimRecord = {\n employeeName: processVariables.employeeName,\n employeeEmail: processVariables.employeeEmail,\n department: processVariables.department,\n tripPurpose: processVariables.tripPurpose,\n destination: processVariables.destination,\n totalClaimed: processVariables.totalCost,\n approvedAmount: processVariables.approvedAmount,\n status: processVariables.finalApprovalStatus,\n submissionDate: processVariables.submissionTimestamp,\n approvalDate: processVariables.approvalTimestamp,\n approvedBy: processVariables.approvedBy,\n managerComments: processVariables.approvalComments\n};\n\n// Mock API call to store claim\nprocessVariables.claimId = 'CLAIM-' + Date.now();\nprocessVariables.storageResult = 'success';", + "scriptCode": "// Process manager's decision\nconst decision = processVariables.managerDecision;\nconst customAmount = parseFloat(processVariables.customApprovedAmount) || 0;\nconst policyLimit = parseFloat(processVariables.totalAllowed) || 0;\nif (decision === 'approve_full' && customAmount > 0) {\n processVariables.approvedAmount = customAmount;\n} else if (decision === 'approve_policy') {\n processVariables.approvedAmount = policyLimit;\n} else if (decision === 'reject') {\n processVariables.approvedAmount = 0;\n}\nprocessVariables.finalApprovalStatus = processVariables.managerDecision === 'approve' ? 'approved' : 'rejected';\nprocessVariables.approvalTimestamp = new Date().toISOString();\nprocessVariables.approvedBy = 'Manager';\nprocessVariables.approvalComments = processVariables.managerComments || '';\n\n// Set approved amount based on decision\nif (processVariables.finalApprovalStatus === 'approved') {\n processVariables.approvedAmount = processVariables.totalCost; // Manager can approve full amount\n} else {\n processVariables.approvedAmount = 0;\n}\n\n// Create final claim record for storage\nprocessVariables.finalClaimRecord = {\n employeeName: processVariables.employeeName,\n employeeEmail: processVariables.employeeEmail,\n department: processVariables.department,\n tripPurpose: processVariables.tripPurpose,\n destination: processVariables.destination,\n totalClaimed: processVariables.totalCost,\n approvedAmount: processVariables.approvedAmount,\n status: processVariables.finalApprovalStatus,\n submissionDate: processVariables.submissionTimestamp,\n approvalDate: processVariables.approvalTimestamp,\n approvedBy: processVariables.approvedBy,\n managerComments: processVariables.approvalComments\n};\n\n// Mock API call to store claim\nprocessVariables.claimId = 'CLAIM-' + Date.now();\nprocessVariables.storageResult = 'success';", "borderColor": "#6b7280", "description": "Process manager decision and store final result", "inputVariables": ["managerDecision", "managerComments", "totalCost"], @@ -471,7 +487,7 @@ }, "type": "script", "label": "Process Manager Decision", - "position": { "x": 2500, "y": 100 } + "position": { "x": 2520, "y": 105 } }, { "id": "notification-1753000010", @@ -487,7 +503,7 @@ "recipientRole": "", "recipientType": "email", "recipientUser": "", - "recipientEmail": "{employeeEmail}", + "recipientEmail": "mdafiqiskandar@gmail.com", "recipientGroup": "", "deliveryOptions": { "sms": false, "email": true, "inApp": true }, "richTextMessage": "", @@ -496,7 +512,7 @@ }, "type": "notification", "label": "Auto Approval Notification", - "position": { "x": 2500, "y": 440 } + "position": { "x": 2265, "y": 375 } }, { "id": "notification-1753000011", @@ -507,12 +523,12 @@ "priority": "high", "expiration": { "unit": "hours", "value": 48, "enabled": false }, "description": "Notify employee of manager's decision", - "htmlMessage": "
Dear {employeeName},
\nYour manager has reviewed your travel reimbursement claim.
\n \n{approvalComments}
\nIf approved, your reimbursement will be processed within 3-5 business days.
\n \nBest regards,
\n Travel Management System
Dear {employeeName},
\nYour manager has reviewed your travel reimbursement claim.
\n \n{approvalComments}
\nIf approved, your reimbursement will be processed within 3-5 business days.
\n \nBest regards,
\n Travel Management System