- Updated VariableManager.vue to change variable type labels for clarity, replacing 'Int' and 'Decimal' with 'Number'. - Modified manager-approval-customScript.js to correct field references and enhance conditional logic for displaying the custom approved amount. - Enhanced manager-approval-form.json by adding 'readonly' attributes to several fields, ensuring they are non-editable during the approval process. - Revised travel-workflow-process.json to improve node connections and labels for better workflow clarity. - Updated travel-workflow-variables.json to refine variable descriptions and ensure consistency across the workflow. - Adjusted [id].vue to improve form data handling and loading states, enhancing user experience during workflow execution.
562 lines
25 KiB
JSON
562 lines
25 KiB
JSON
{
|
|
"edges": [
|
|
{
|
|
"id": "start-1753000001-form-1753000002-edge",
|
|
"data": {},
|
|
"type": "custom",
|
|
"label": "",
|
|
"source": "start-1753000001",
|
|
"target": "form-1753000002",
|
|
"animated": true,
|
|
"sourceHandle": "start-1753000001-right",
|
|
"targetHandle": "form-1753000002-left"
|
|
},
|
|
{
|
|
"id": "form-1753000002-script-1753000003-edge",
|
|
"data": {},
|
|
"type": "custom",
|
|
"label": "",
|
|
"source": "form-1753000002",
|
|
"target": "script-1753000003",
|
|
"animated": true,
|
|
"sourceHandle": "form-1753000002-right",
|
|
"targetHandle": "script-1753000003-left"
|
|
},
|
|
{
|
|
"id": "script-1753000003-api-1753000004-edge",
|
|
"data": {},
|
|
"type": "custom",
|
|
"label": "",
|
|
"source": "script-1753000003",
|
|
"target": "api-1753000004",
|
|
"animated": true,
|
|
"sourceHandle": "script-1753000003-right",
|
|
"targetHandle": "api-1753000004-left"
|
|
},
|
|
{
|
|
"id": "api-1753000004-script-1753000005-edge",
|
|
"data": {},
|
|
"type": "custom",
|
|
"label": "",
|
|
"source": "api-1753000004",
|
|
"target": "script-1753000005",
|
|
"animated": true,
|
|
"sourceHandle": "api-1753000004-right",
|
|
"targetHandle": "script-1753000005-left"
|
|
},
|
|
{
|
|
"id": "script-1753000005-gateway-1753000006-edge",
|
|
"data": {},
|
|
"type": "custom",
|
|
"label": "",
|
|
"source": "script-1753000005",
|
|
"target": "gateway-1753000006",
|
|
"animated": true,
|
|
"sourceHandle": "script-1753000005-right",
|
|
"targetHandle": "gateway-1753000006-left"
|
|
},
|
|
{
|
|
"id": "script-1753000009-notification-1753000011-edge",
|
|
"data": {},
|
|
"type": "custom",
|
|
"label": "",
|
|
"source": "script-1753000009",
|
|
"target": "notification-1753000011",
|
|
"animated": true,
|
|
"sourceHandle": "script-1753000009-right",
|
|
"targetHandle": "notification-1753000011-left"
|
|
},
|
|
{
|
|
"id": "notification-1753000010-end-1753000012-edge",
|
|
"data": {},
|
|
"type": "custom",
|
|
"label": "",
|
|
"source": "notification-1753000010",
|
|
"target": "end-1753000012",
|
|
"animated": true,
|
|
"sourceHandle": "notification-1753000010-right",
|
|
"targetHandle": "end-1753000012-left"
|
|
},
|
|
{
|
|
"id": "notification-1753000011-end-1753000012-edge",
|
|
"data": {},
|
|
"type": "custom",
|
|
"label": "",
|
|
"source": "notification-1753000011",
|
|
"target": "end-1753000012",
|
|
"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",
|
|
"shape": "circle",
|
|
"borderColor": "#10b981",
|
|
"description": "Employee initiates travel reimbursement claim",
|
|
"backgroundColor": "#dcfce7"
|
|
},
|
|
"type": "start",
|
|
"label": "Start Travel Claim",
|
|
"position": { "x": 105, "y": 300 }
|
|
},
|
|
{
|
|
"id": "form-1753000002",
|
|
"data": {
|
|
"label": "Travel Claim Form",
|
|
"shape": "rectangle",
|
|
"formId": 2,
|
|
"formName": "Employee Travel Reimbursement Claim",
|
|
"formUuid": "travel-reimbursement-form-uuid",
|
|
"textColor": "#6b21a8",
|
|
"borderColor": "#9333ea",
|
|
"description": "Employee fills travel reimbursement claim form",
|
|
"assignedRoles": [
|
|
{
|
|
"label": "Employee",
|
|
"value": "3",
|
|
"description": "Regular employee role"
|
|
}
|
|
],
|
|
"assignedUsers": [],
|
|
"inputMappings": [],
|
|
"assignmentType": "roles",
|
|
"outputMappings": [
|
|
{ "formField": "employee_name", "processVariable": "employeeName" },
|
|
{ "formField": "employee_email", "processVariable": "employeeEmail" },
|
|
{ "formField": "department", "processVariable": "department" },
|
|
{ "formField": "trip_purpose", "processVariable": "tripPurpose" },
|
|
{ "formField": "destination", "processVariable": "destination" },
|
|
{ "formField": "departure_date", "processVariable": "departureDate" },
|
|
{ "formField": "return_date", "processVariable": "returnDate" },
|
|
{ "formField": "travel_type", "processVariable": "travelType" },
|
|
{ "formField": "transport_cost", "processVariable": "transportCost" },
|
|
{
|
|
"formField": "accommodation_cost",
|
|
"processVariable": "accommodationCost"
|
|
},
|
|
{ "formField": "meals_cost", "processVariable": "mealsCost" },
|
|
{ "formField": "other_cost", "processVariable": "otherCost" },
|
|
{ "formField": "has_receipts", "processVariable": "hasReceipts" }
|
|
],
|
|
"backgroundColor": "#faf5ff",
|
|
"fieldConditions": [],
|
|
"assignmentVariable": "",
|
|
"assignmentVariableType": "user_id"
|
|
},
|
|
"type": "form",
|
|
"label": "Travel Claim Form",
|
|
"position": { "x": 405, "y": 270 }
|
|
},
|
|
{
|
|
"id": "script-1753000003",
|
|
"data": {
|
|
"label": "Validate & Calculate Total",
|
|
"shape": "rectangle",
|
|
"textColor": "#374151",
|
|
"scriptCode": "// Validate form inputs\nconst transport = parseFloat(processVariables.transportCost) || 0;\nconst accommodation = parseFloat(processVariables.accommodationCost) || 0;\nconst meals = parseFloat(processVariables.mealsCost) || 0;\nconst other = parseFloat(processVariables.otherCost) || 0;\n\n// Calculate total cost\nprocessVariables.totalCost = transport + accommodation + meals + other;\n\n// Validate required fields\nif (!processVariables.employeeName || !processVariables.tripPurpose || !processVariables.destination) {\n processVariables.validationError = 'Required fields are missing';\n processVariables.isValidSubmission = false;\n} else if (processVariables.totalCost <= 0) {\n processVariables.validationError = 'Total cost must be greater than 0';\n processVariables.isValidSubmission = false;\n} else {\n processVariables.validationError = '';\n processVariables.isValidSubmission = true;\n}\n\n// Calculate trip duration\nconst departure = new Date(processVariables.departureDate);\nconst returnDate = new Date(processVariables.returnDate);\nprocessVariables.tripDuration = Math.ceil((returnDate - departure) / (1000 * 60 * 60 * 24)) + 1;\n\n// Create submission timestamp\nprocessVariables.submissionTimestamp = new Date().toISOString();",
|
|
"borderColor": "#6b7280",
|
|
"description": "Validate form data and calculate totals",
|
|
"inputVariables": [
|
|
"employeeName",
|
|
"tripPurpose",
|
|
"destination",
|
|
"transportCost",
|
|
"accommodationCost",
|
|
"mealsCost",
|
|
"otherCost",
|
|
"departureDate",
|
|
"returnDate"
|
|
],
|
|
"scriptLanguage": "javascript",
|
|
"backgroundColor": "#f9fafb",
|
|
"outputVariables": [
|
|
{
|
|
"name": "totalCost",
|
|
"type": "number",
|
|
"description": "Total claim amount"
|
|
},
|
|
{
|
|
"name": "isValidSubmission",
|
|
"type": "boolean",
|
|
"description": "Whether submission is valid"
|
|
},
|
|
{
|
|
"name": "validationError",
|
|
"type": "string",
|
|
"description": "Validation error message if any"
|
|
},
|
|
{
|
|
"name": "tripDuration",
|
|
"type": "number",
|
|
"description": "Trip duration in days"
|
|
},
|
|
{
|
|
"name": "submissionTimestamp",
|
|
"type": "string",
|
|
"description": "When claim was submitted"
|
|
}
|
|
]
|
|
},
|
|
"type": "script",
|
|
"label": "Validate & Calculate Total",
|
|
"position": { "x": 750, "y": 270 }
|
|
},
|
|
{
|
|
"id": "api-1753000004",
|
|
"data": {
|
|
"body": {
|
|
"data": "{ \"travel_type\": \"{travelType}\", \"destination\": \"{destination}\", \"trip_duration\": {tripDuration} }",
|
|
"type": "raw"
|
|
},
|
|
"label": "Get Policy Rates",
|
|
"shape": "rectangle",
|
|
"apiUrl": "https://jsonplaceholder.typicode.com/posts",
|
|
"params": [],
|
|
"headers": [{ "key": "Content-Type", "value": "application/json" }],
|
|
"apiMethod": "POST",
|
|
"textColor": "#1e40af",
|
|
"borderColor": "#3b82f6",
|
|
"description": "Get company policy rates for travel type and destination",
|
|
"requestBody": "",
|
|
"authorization": { "type": "none" },
|
|
"errorVariable": "policyApiError",
|
|
"outputVariable": "policyApiResponse",
|
|
"backgroundColor": "#eff6ff",
|
|
"continueOnError": false
|
|
},
|
|
"type": "api",
|
|
"label": "Get Policy Rates",
|
|
"position": { "x": 1095, "y": 270 }
|
|
},
|
|
{
|
|
"id": "script-1753000005",
|
|
"data": {
|
|
"label": "Calculate Reimbursement",
|
|
"shape": "rectangle",
|
|
"textColor": "#374151",
|
|
"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"
|
|
],
|
|
"scriptLanguage": "javascript",
|
|
"backgroundColor": "#f9fafb",
|
|
"outputVariables": [
|
|
{
|
|
"name": "totalAllowed",
|
|
"type": "number",
|
|
"description": "Total allowed reimbursement per policy"
|
|
},
|
|
{
|
|
"name": "reimbursementAmount",
|
|
"type": "number",
|
|
"description": "Final reimbursement amount"
|
|
},
|
|
{
|
|
"name": "isOverBudget",
|
|
"type": "boolean",
|
|
"description": "Whether claim exceeds policy limits"
|
|
},
|
|
{
|
|
"name": "overBudgetAmount",
|
|
"type": "number",
|
|
"description": "Amount over budget"
|
|
},
|
|
{
|
|
"name": "claimSummary",
|
|
"type": "string",
|
|
"description": "Summary of the claim"
|
|
},
|
|
{
|
|
"name": "approvalStatus",
|
|
"type": "string",
|
|
"description": "Current approval status"
|
|
}
|
|
]
|
|
},
|
|
"type": "script",
|
|
"label": "Calculate Reimbursement",
|
|
"position": { "x": 1455, "y": 270 }
|
|
},
|
|
{
|
|
"id": "gateway-1753000006",
|
|
"data": {
|
|
"label": "Budget Check",
|
|
"shape": "diamond",
|
|
"textColor": "#c2410c",
|
|
"conditions": [
|
|
{
|
|
"id": "condition-group-1",
|
|
"output": "Requires Approval",
|
|
"conditions": [
|
|
{
|
|
"id": "condition-over-budget",
|
|
"value": "true",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"operator": "is_true",
|
|
"variable": "isOverBudget",
|
|
"valueType": "boolean",
|
|
"logicalOperator": "and"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "condition-group-2",
|
|
"output": "Auto Approve",
|
|
"conditions": [
|
|
{
|
|
"id": "condition-within-budget",
|
|
"value": "false",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"operator": "is_false",
|
|
"variable": "isOverBudget",
|
|
"valueType": "boolean",
|
|
"logicalOperator": "and"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"borderColor": "#f97316",
|
|
"defaultPath": "Auto Approve",
|
|
"description": "Check if claim exceeds policy limits",
|
|
"backgroundColor": "#fff7ed"
|
|
},
|
|
"type": "gateway",
|
|
"label": "Budget Check",
|
|
"position": { "x": 1755, "y": 330 }
|
|
},
|
|
{
|
|
"id": "form-1753000007",
|
|
"data": {
|
|
"label": "Manager Approval",
|
|
"shape": "rectangle",
|
|
"formId": 3,
|
|
"formName": "Travel Claim Approval Form",
|
|
"formUuid": "travel-approval-form-uuid",
|
|
"textColor": "#6b21a8",
|
|
"borderColor": "#9333ea",
|
|
"description": "Manager reviews and approves/rejects over-budget travel claim",
|
|
"assignedRoles": [
|
|
{
|
|
"label": "Manager",
|
|
"value": "4",
|
|
"description": "Department manager role"
|
|
}
|
|
],
|
|
"assignedUsers": [],
|
|
"inputMappings": [
|
|
{ "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": "custom_approved_amount",
|
|
"processVariable": "customApprovedAmount"
|
|
}
|
|
],
|
|
"backgroundColor": "#faf5ff",
|
|
"fieldConditions": [],
|
|
"assignmentVariable": "",
|
|
"assignmentVariableType": "user_id"
|
|
},
|
|
"type": "form",
|
|
"label": "Manager Approval",
|
|
"position": { "x": 1980, "y": 105 }
|
|
},
|
|
{
|
|
"id": "script-1753000009",
|
|
"data": {
|
|
"label": "Process Manager Decision",
|
|
"shape": "rectangle",
|
|
"textColor": "#374151",
|
|
"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"],
|
|
"scriptLanguage": "javascript",
|
|
"backgroundColor": "#f9fafb",
|
|
"outputVariables": [
|
|
{
|
|
"name": "finalApprovalStatus",
|
|
"type": "string",
|
|
"description": "Final approval status after manager review"
|
|
},
|
|
{
|
|
"name": "approvedAmount",
|
|
"type": "number",
|
|
"description": "Final approved amount"
|
|
},
|
|
{
|
|
"name": "claimId",
|
|
"type": "string",
|
|
"description": "Generated claim ID"
|
|
},
|
|
{
|
|
"name": "approvalTimestamp",
|
|
"type": "string",
|
|
"description": "When claim was processed"
|
|
}
|
|
]
|
|
},
|
|
"type": "script",
|
|
"label": "Process Manager Decision",
|
|
"position": { "x": 2520, "y": 105 }
|
|
},
|
|
{
|
|
"id": "notification-1753000010",
|
|
"data": {
|
|
"label": "Auto Approval Notification",
|
|
"message": "Your travel claim has been auto-approved",
|
|
"subject": "Travel Claim Auto-Approved - {claimId}",
|
|
"priority": "medium",
|
|
"expiration": { "unit": "hours", "value": 24, "enabled": false },
|
|
"description": "Notify employee of auto-approved claim",
|
|
"htmlMessage": "<div style=\"font-family: Arial, sans-serif; padding: 20px; border-left: 4px solid #10b981;\">\n <h2 style=\"color: #10b981; margin-top: 0;\">✅ Travel Claim Auto-Approved</h2>\n <p>Dear {employeeName},</p>\n <p>Your travel reimbursement claim has been <strong>automatically approved</strong>!</p>\n \n <div style=\"background: #f0fdf4; padding: 15px; border-radius: 8px; margin: 20px 0;\">\n <h3 style=\"margin-top: 0; color: #059669;\">Claim Details:</h3>\n <ul style=\"list-style: none; padding: 0;\">\n <li><strong>Claim ID:</strong> {claimId}</li>\n <li><strong>Trip Purpose:</strong> {tripPurpose}</li>\n <li><strong>Destination:</strong> {destination}</li>\n <li><strong>Total Claimed:</strong> RM{totalCost}</li>\n <li><strong>Approved Amount:</strong> RM{approvedAmount}</li>\n <li><strong>Status:</strong> {finalApprovalStatus}</li>\n </ul>\n </div>\n \n <p>Your reimbursement will be processed within 3-5 business days.</p>\n \n <p style=\"margin-bottom: 0;\">Best regards,<br>\n <strong>Travel Management System</strong></p>\n</div>",
|
|
"messageFormat": "html",
|
|
"recipientRole": "",
|
|
"recipientType": "email",
|
|
"recipientUser": "",
|
|
"recipientEmail": "mdafiqiskandar@gmail.com",
|
|
"recipientGroup": "",
|
|
"deliveryOptions": { "sms": false, "email": true, "inApp": true },
|
|
"richTextMessage": "",
|
|
"notificationType": "success",
|
|
"recipientVariable": "employeeEmail"
|
|
},
|
|
"type": "notification",
|
|
"label": "Auto Approval Notification",
|
|
"position": { "x": 2265, "y": 375 }
|
|
},
|
|
{
|
|
"id": "notification-1753000011",
|
|
"data": {
|
|
"label": "Manager Decision Notification",
|
|
"message": "Your travel claim has been reviewed by your manager",
|
|
"subject": "Travel Claim Decision - {claimId}",
|
|
"priority": "high",
|
|
"expiration": { "unit": "hours", "value": 48, "enabled": false },
|
|
"description": "Notify employee of manager's decision",
|
|
"htmlMessage": "<div style=\"font-family: Arial, sans-serif; padding: 20px; border-left: 4px solid #3b82f6;\">\n <h2 style=\"color: #1e40af; margin-top: 0;\">📋 Travel Claim Decision</h2>\n <p>Dear {employeeName},</p>\n <p>Your manager has reviewed your travel reimbursement claim.</p>\n \n <div style=\"background: #eff6ff; padding: 15px; border-radius: 8px; margin: 20px 0;\">\n <h3 style=\"margin-top: 0; color: #1e40af;\">Claim Details:</h3>\n <ul style=\"list-style: none; padding: 0;\">\n <li><strong>Claim ID:</strong> {claimId}</li>\n <li><strong>Trip Purpose:</strong> {tripPurpose}</li>\n <li><strong>Destination:</strong> {destination}</li>\n <li><strong>Total Claimed:</strong> RM{totalCost}</li>\n <li><strong>Approved Amount:</strong> RM{approvedAmount}</li>\n <li><strong>Status:</strong> <span style=\"font-weight: bold;\">{finalApprovalStatus}</span></li>\n </ul>\n </div>\n \n <div style=\"background: #f8fafc; padding: 15px; border-radius: 8px; margin: 20px 0;\">\n <h4 style=\"margin-top: 0;\">Manager Comments:</h4>\n <p style=\"font-style: italic;\">{approvalComments}</p>\n </div>\n \n <p>If approved, your reimbursement will be processed within 3-5 business days.</p>\n \n <p style=\"margin-bottom: 0;\">Best regards,<br>\n <strong>Travel Management System</strong></p>\n</div>",
|
|
"messageFormat": "html",
|
|
"recipientRole": "",
|
|
"recipientType": "email",
|
|
"recipientUser": "",
|
|
"recipientEmail": "mdafiqiskandar@gmail.com",
|
|
"recipientGroup": "",
|
|
"deliveryOptions": { "sms": false, "email": true, "inApp": true },
|
|
"richTextMessage": "",
|
|
"notificationType": "info",
|
|
"recipientVariable": "employeeEmail"
|
|
},
|
|
"type": "notification",
|
|
"label": "Manager Decision Notification",
|
|
"position": { "x": 2850, "y": 105 }
|
|
},
|
|
{
|
|
"id": "end-1753000012",
|
|
"data": {
|
|
"label": "End",
|
|
"shape": "circle",
|
|
"borderColor": "#f59e0b",
|
|
"description": "Travel claim process completed",
|
|
"backgroundColor": "#fef3c7"
|
|
},
|
|
"type": "end",
|
|
"label": "End",
|
|
"position": { "x": 3195, "y": 300 }
|
|
}
|
|
],
|
|
"viewport": {
|
|
"x": -1535.387843430428,
|
|
"y": 250.2076943977823,
|
|
"zoom": 0.8368461998102432
|
|
}
|
|
}
|