{
  "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
  }
}
