{
  "info": {
    "name": "FWG Malaysia – Leave Management API",
    "_postman_id": "fwg-leave-api-v1",
    "description": "Complete Leave Management API for FWG Malaysia.\n\nSETUP:\n1. Set collection variable `base_url` → e.g. http://localhost\n2. Run the Login request — token is auto-saved to `token` variable\n3. All subsequent requests use `token` automatically\n\nEmployee Mobile API base: {{base_url}}/api/v1/employee\nAdmin Web Panel base:      {{base_url}}/leave",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    { "key": "base_url",         "value": "http://localhost",  "type": "string", "description": "Your server base URL" },
    { "key": "token",            "value": "",                  "type": "string", "description": "Sanctum token — auto-set by Login request" },
    { "key": "leave_request_id", "value": "1",                 "type": "string", "description": "Leave request ID — auto-set by Submit Leave request" }
  ],
  "item": [
    {
      "name": "🔐 Auth",
      "item": [
        {
          "name": "Login",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "var json = pm.response.json();",
                  "if (json.data && json.data.token) {",
                  "    pm.collectionVariables.set('token', json.data.token);",
                  "    console.log('✅ Token saved:', json.data.token);",
                  "} else {",
                  "    console.log('❌ Token not found in response');",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Accept",       "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n    \"email\": \"employee@fwgmalayasia.com\",\n    \"password\": \"password123\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v1/employee/auth/login",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "employee", "auth", "login"]
            },
            "description": "Authenticate and retrieve Sanctum token.\nThe test script auto-saves the token to the `token` collection variable."
          },
          "response": [
            {
              "name": "200 OK – Login Success",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Login successful\",\n    \"data\": {\n        \"token\": \"1|abc123xyz...\",\n        \"user\": {\n            \"id\": 5,\n            \"name\": \"Ahmad Razif\",\n            \"email\": \"employee@fwgmalayasia.com\"\n        }\n    }\n}"
            },
            {
              "name": "401 – Invalid Credentials",
              "status": "Unauthorized",
              "code": 401,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": false,\n    \"message\": \"Invalid credentials\"\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "📋 Leave – Employee API",
      "description": "Mobile employee endpoints.\nBase: {{base_url}}/api/v1/employee\nAll require Bearer token.",
      "item": [
        {
          "name": "1. Get Leave Types",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{token}}" },
              { "key": "Accept",        "value": "application/json" }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/employee/leave/types",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "employee", "leave", "types"]
            },
            "description": "Returns all active leave types with the authenticated employee's current year balance.\n\nAlso returns:\n• dotnet_work_type_id  — .NET payroll ID for each leave type (for sync)\n• dotnet_work_types    — full dropdown from .NET API (static fallback if unreachable)\n• min_leave_date       — today + 6 days (use as minDate in date picker)\n• advance_days         — advance notice required (currently 6 days)\n\nNo request body or query parameters."
          },
          "response": [
            {
              "name": "200 OK",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave types retrieved successfully\",\n    \"data\": {\n        \"leave_types\": [\n            {\n                \"id\": 1,\n                \"name\": \"Annual Leave\",\n                \"description\": \"Yearly entitlement for personal use\",\n                \"max_days_per_year\": 14,\n                \"requires_approval\": true,\n                \"is_paid\": true,\n                \"dotnet_work_type_id\": 8,\n                \"balance\": {\n                    \"total_days\": 14,\n                    \"used_days\": 3,\n                    \"remaining_days\": 11\n                }\n            },\n            {\n                \"id\": 2,\n                \"name\": \"Medical Leave\",\n                \"description\": \"Sick or medical leave\",\n                \"max_days_per_year\": 14,\n                \"requires_approval\": true,\n                \"is_paid\": true,\n                \"dotnet_work_type_id\": 9,\n                \"balance\": {\n                    \"total_days\": 14,\n                    \"used_days\": 0,\n                    \"remaining_days\": 14\n                }\n            },\n            {\n                \"id\": 3,\n                \"name\": \"Unpaid Leave\",\n                \"description\": \"Leave without pay\",\n                \"max_days_per_year\": 0,\n                \"requires_approval\": true,\n                \"is_paid\": false,\n                \"dotnet_work_type_id\": 6,\n                \"balance\": {\n                    \"total_days\": 0,\n                    \"used_days\": 0,\n                    \"remaining_days\": 0\n                }\n            }\n        ],\n        \"dotnet_work_types\": [\n            { \"id\": 1,  \"name\": \"General Working\" },\n            { \"id\": 2,  \"name\": \"Off Day\" },\n            { \"id\": 6,  \"name\": \"Unpaid Leave\" },\n            { \"id\": 7,  \"name\": \"Absent\" },\n            { \"id\": 8,  \"name\": \"Annual Leave\" },\n            { \"id\": 9,  \"name\": \"Medical Leave\" },\n            { \"id\": 10, \"name\": \"Maternity Leave\" },\n            { \"id\": 11, \"name\": \"Paternity Leave\" },\n            { \"id\": 12, \"name\": \"Hospitalization Leave\" },\n            { \"id\": 15, \"name\": \"Replacement Leave\" },\n            { \"id\": 16, \"name\": \"Compensate Leave\" },\n            { \"id\": 17, \"name\": \"Marriage Leave\" }\n        ],\n        \"year\": \"2026\",\n        \"min_leave_date\": \"2026-10-13\",\n        \"advance_days\": 6\n    }\n}"
            }
          ]
        },
        {
          "name": "2. Submit Leave Request – Full Day",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "var json = pm.response.json();",
                  "if (json.data && json.data.leave_request_id) {",
                  "    pm.collectionVariables.set('leave_request_id', json.data.leave_request_id);",
                  "    console.log('✅ Leave Request ID saved:', json.data.leave_request_id);",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{token}}" },
              { "key": "Content-Type",  "value": "application/json" },
              { "key": "Accept",        "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n    \"leave_type_id\": 1,\n    \"from_date\": \"2026-10-20\",\n    \"to_date\": \"2026-10-22\",\n    \"is_half_day\": false,\n    \"reason\": \"Family holiday trip\",\n    \"remarks\": \"Pre-planned family event\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v1/employee/leave/request",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "employee", "leave", "request"]
            },
            "description": "Submit a full-day leave request.\n\nBUSINESS RULES (enforced in order):\n1. from_date must be >= today + 6 days\n2. Leave type must be active\n3. No existing pending request (one-at-a-time policy)\n4. No overlapping dates with pending/approved leaves\n5. Sufficient balance if max_days_per_year > 0\n6. All requests are always created with status=pending — admin must approve\n\nDAY COUNT:\n• Full day: diffInDays(from_date, to_date) + 1\n• Half day: 0.5\n\nFIELDS:\n• leave_type_id  required  integer, must exist\n• from_date      required  YYYY-MM-DD, >= today+6\n• to_date        required  YYYY-MM-DD, >= from_date\n• is_half_day    optional  boolean, default false\n• half_day_type  if half   first_half | second_half\n• reason         required  string max:500\n• remarks        optional  string"
          },
          "response": [
            {
              "name": "200 OK – Pending Approval",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave request submitted successfully. Pending approval.\",\n    \"data\": {\n        \"leave_request_id\": 42,\n        \"leave_type\": \"Annual Leave\",\n        \"from_date\": \"2026-10-20\",\n        \"to_date\": \"2026-10-22\",\n        \"days\": 3,\n        \"is_half_day\": false,\n        \"half_day_type\": null,\n        \"half_day_display\": \"Full Day\",\n        \"status\": \"pending\",\n        \"requires_approval\": true\n    }\n}"
            },
            {
              "name": "200 OK – Pending Approval (requires_approval: false)",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave request submitted successfully. Pending approval.\",\n    \"data\": {\n        \"leave_request_id\": 43,\n        \"leave_type\": \"Replacement Leave\",\n        \"from_date\": \"2026-10-20\",\n        \"to_date\": \"2026-10-20\",\n        \"days\": 1,\n        \"is_half_day\": false,\n        \"half_day_type\": null,\n        \"half_day_display\": \"Full Day\",\n        \"status\": \"pending\",\n        \"requires_approval\": false\n    }\n}"
            },
            {
              "name": "422 – Validation Failed",
              "status": "Unprocessable Entity",
              "code": 422,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": false,\n    \"message\": \"Validation failed\",\n    \"errors\": {\n        \"from_date\": [\n            \"Leave must be applied at least 6 days in advance. The earliest date you can apply for is 13 Oct 2026.\"\n        ],\n        \"reason\": [\"The reason field is required.\"]\n    }\n}"
            },
            {
              "name": "400 – Pending Request Exists",
              "status": "Bad Request",
              "code": 400,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": false,\n    \"message\": \"You have a pending leave request (Annual Leave, 20 Oct 2026 – 22 Oct 2026). Please wait for it to be approved or rejected before applying for new leave.\",\n    \"pending_request\": {\n        \"id\": 41,\n        \"leave_type\": \"Annual Leave\",\n        \"from_date\": \"20 Oct 2026\",\n        \"to_date\": \"22 Oct 2026\",\n        \"days\": 3,\n        \"applied_on\": \"07 Oct 2026\"\n    }\n}"
            },
            {
              "name": "400 – Overlapping Dates",
              "status": "Bad Request",
              "code": 400,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": false,\n    \"message\": \"You already have a leave request for this period\"\n}"
            },
            {
              "name": "400 – Insufficient Balance",
              "status": "Bad Request",
              "code": 400,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": false,\n    \"message\": \"Insufficient leave balance. Available: 2 days\"\n}"
            },
            {
              "name": "400 – Inactive Leave Type",
              "status": "Bad Request",
              "code": 400,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": false,\n    \"message\": \"This leave type is not active\"\n}"
            }
          ]
        },
        {
          "name": "3. Submit Leave Request – Half Day",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{token}}" },
              { "key": "Content-Type",  "value": "application/json" },
              { "key": "Accept",        "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n    \"leave_type_id\": 2,\n    \"from_date\": \"2026-10-20\",\n    \"to_date\": \"2026-10-20\",\n    \"is_half_day\": true,\n    \"half_day_type\": \"first_half\",\n    \"reason\": \"Medical appointment in the morning\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v1/employee/leave/request",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "employee", "leave", "request"]
            },
            "description": "Submit a half-day leave request.\n\nFor half-day, from_date and to_date MUST be the same date.\nDays counted = 0.5\n\nhalf_day_type values:\n• first_half  → First Half (Morning)\n• second_half → Second Half (Afternoon)"
          },
          "response": [
            {
              "name": "200 OK – Half Day Pending",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave request submitted successfully. Pending approval.\",\n    \"data\": {\n        \"leave_request_id\": 44,\n        \"leave_type\": \"Medical Leave\",\n        \"from_date\": \"2026-10-20\",\n        \"to_date\": \"2026-10-20\",\n        \"days\": 0.5,\n        \"is_half_day\": true,\n        \"half_day_type\": \"first_half\",\n        \"half_day_display\": \"First Half (Morning)\",\n        \"status\": \"pending\",\n        \"requires_approval\": true\n    }\n}"
            }
          ]
        },
        {
          "name": "4. Get Leave Allocation & History",
          "request": {
            "method": "GET",
            "header": [
              { "key": "Authorization", "value": "Bearer {{token}}" },
              { "key": "Accept",        "value": "application/json" }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/employee/leave-allocation?year=2026",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "employee", "leave-allocation"],
              "query": [
                {
                  "key": "year",
                  "value": "2026",
                  "description": "Optional. Calendar year. Defaults to current year."
                }
              ]
            },
            "description": "Returns the employee's risk-based leave allocation, current balances, restrictions, summary totals, and last 10 leave requests.\n\nRISK LEVELS:\n• High   — Security Guard, Patrol Staff, Control Room Operator, Night Shift Operator, Security/Patrol Supervisor\n           Annual: 18-24 | Sick: 10-12 | Casual: 6-8 | All restrictions ON\n• Medium — Supervisor, Team Lead, Field Officer, Operations Manager, Shift Supervisor\n           Annual: 15-18 | Sick: 8-12 | Casual: 6 | advance_approval_required only\n• Low    — All others\n           Annual: 12-15 | Sick: 8-10 | Casual: 6 | No restrictions\n\nQUERY PARAMS:\n• year (optional) — integer, defaults to current year"
          },
          "response": [
            {
              "name": "200 OK – High Risk Employee",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave allocation retrieved successfully\",\n    \"data\": {\n        \"employee\": {\n            \"id\": 5,\n            \"name\": \"Ahmad Razif\",\n            \"designations\": [\"Security Guard\"],\n            \"risk_level\": \"high\"\n        },\n        \"leave_balances\": {\n            \"annual_leave\": {\n                \"allocated\": 24,\n                \"range\": { \"min\": 18, \"max\": 24 },\n                \"used\": 3,\n                \"remaining\": 21\n            },\n            \"sick_leave\": {\n                \"allocated\": 12,\n                \"range\": { \"min\": 10, \"max\": 12 },\n                \"used\": 0,\n                \"remaining\": 12\n            },\n            \"casual_leave\": {\n                \"allocated\": 8,\n                \"range\": { \"min\": 6, \"max\": 8 },\n                \"used\": 0,\n                \"remaining\": 8\n            }\n        },\n        \"restrictions\": {\n            \"critical_duty_windows\": true,\n            \"advance_approval_required\": true,\n            \"replacement_mandatory\": true,\n            \"blackout_periods\": true\n        },\n        \"summary\": {\n            \"total_allocated\": 44,\n            \"total_used\": 3,\n            \"total_remaining\": 41\n        },\n        \"history\": [\n            {\n                \"id\": 42,\n                \"leave_type\": \"Annual Leave\",\n                \"from_date\": \"2026-09-10\",\n                \"to_date\": \"2026-09-12\",\n                \"days\": 3,\n                \"is_half_day\": false,\n                \"half_day_type\": null,\n                \"half_day_display\": \"Full Day\",\n                \"reason\": \"Personal\",\n                \"status\": \"approved\",\n                \"approved_by\": \"Admin Manager\",\n                \"approved_at\": \"2026-09-08 10:00:00\",\n                \"created_at\": \"2026-09-07 09:00:00\"\n            }\n        ],\n        \"year\": 2026\n    }\n}"
            },
            {
              "name": "200 OK – Low Risk Employee",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave allocation retrieved successfully\",\n    \"data\": {\n        \"employee\": {\n            \"id\": 12,\n            \"name\": \"Lim Wei Jian\",\n            \"designations\": [\"Office Admin\"],\n            \"risk_level\": \"low\"\n        },\n        \"leave_balances\": {\n            \"annual_leave\": {\n                \"allocated\": 15,\n                \"range\": { \"min\": 12, \"max\": 15 },\n                \"used\": 0,\n                \"remaining\": 15\n            },\n            \"sick_leave\": {\n                \"allocated\": 10,\n                \"range\": { \"min\": 8, \"max\": 10 },\n                \"used\": 0,\n                \"remaining\": 10\n            },\n            \"casual_leave\": {\n                \"allocated\": 6,\n                \"range\": { \"min\": 6, \"max\": 6 },\n                \"used\": 0,\n                \"remaining\": 6\n            }\n        },\n        \"restrictions\": {\n            \"critical_duty_windows\": false,\n            \"advance_approval_required\": false,\n            \"replacement_mandatory\": false,\n            \"blackout_periods\": false\n        },\n        \"summary\": {\n            \"total_allocated\": 31,\n            \"total_used\": 0,\n            \"total_remaining\": 31\n        },\n        \"history\": [],\n        \"year\": 2026\n    }\n}"
            }
          ]
        },
        {
          "name": "5. Check Leave Eligibility",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{token}}" },
              { "key": "Content-Type",  "value": "application/json" },
              { "key": "Accept",        "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n    \"from_date\": \"2026-10-17\",\n    \"to_date\": \"2026-10-18\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v1/employee/check-leave-eligibility",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "employee", "check-leave-eligibility"]
            },
            "description": "Checks whether the employee is eligible to take leave for the specified date range based on risk level restrictions.\n\n⚠️ This checks ONLY risk-based restrictions.\nIt does NOT check leave balance or existing requests.\nUse this to show eligibility warnings in the UI BEFORE the employee submits.\n\nCRITICAL DUTY WINDOW:\n• High-risk employees are blocked if any date in range falls on a weekend.\n\nVALIDATION:\n• from_date  required  date, >= today\n• to_date    required  date, >= from_date"
          },
          "response": [
            {
              "name": "200 OK – Not Eligible (High Risk + Weekend)",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave eligibility checked successfully\",\n    \"data\": {\n        \"employee\": {\n            \"id\": 5,\n            \"name\": \"Ahmad Razif\",\n            \"risk_level\": \"high\"\n        },\n        \"period\": {\n            \"from_date\": \"2026-10-17\",\n            \"to_date\": \"2026-10-18\",\n            \"days\": 2\n        },\n        \"eligibility\": {\n            \"allowed\": false,\n            \"restrictions\": [\n                \"Leave cannot be taken during critical duty windows\"\n            ],\n            \"requirements\": [\n                \"Replacement must be assigned before leave approval\"\n            ]\n        }\n    }\n}"
            },
            {
              "name": "200 OK – Eligible with Requirements (Medium Risk)",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave eligibility checked successfully\",\n    \"data\": {\n        \"employee\": {\n            \"id\": 8,\n            \"name\": \"Siti Aminah\",\n            \"risk_level\": \"medium\"\n        },\n        \"period\": {\n            \"from_date\": \"2026-10-20\",\n            \"to_date\": \"2026-10-21\",\n            \"days\": 2\n        },\n        \"eligibility\": {\n            \"allowed\": true,\n            \"restrictions\": [],\n            \"requirements\": [\n                \"Advance approval required (minimum 3 days notice)\"\n            ]\n        }\n    }\n}"
            },
            {
              "name": "200 OK – Fully Eligible (Low Risk)",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave eligibility checked successfully\",\n    \"data\": {\n        \"employee\": {\n            \"id\": 12,\n            \"name\": \"Lim Wei Jian\",\n            \"risk_level\": \"low\"\n        },\n        \"period\": {\n            \"from_date\": \"2026-10-20\",\n            \"to_date\": \"2026-10-21\",\n            \"days\": 2\n        },\n        \"eligibility\": {\n            \"allowed\": true,\n            \"restrictions\": [],\n            \"requirements\": []\n        }\n    }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "⚙️ Leave – Admin Panel",
      "description": "Admin web panel endpoints — called via AJAX.\nBase: {{base_url}}/leave\nRequire web session or Sanctum token + X-CSRF-TOKEN header.",
      "item": [
        {
          "name": "6. Approve Leave Request",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{token}}" },
              { "key": "Content-Type",  "value": "application/json" },
              { "key": "Accept",        "value": "application/json" },
              { "key": "X-CSRF-TOKEN",  "value": "{{csrf_token}}", "description": "Required for web session auth" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n    \"approval_notes\": \"Approved. Ensure handover is completed before leave.\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/leave/{{leave_request_id}}/approve",
              "host": ["{{base_url}}"],
              "path": ["leave", "{{leave_request_id}}", "approve"]
            },
            "description": "Approve a pending leave request.\n\n⚠️ Only works if current status is 'pending'.\n\nSIDE EFFECT:\nIncrements LeaveBalance.used_days by days_count.\nCreates a balance record if one doesn't exist.\n\nFIELD:\n• approval_notes  optional  max:500"
          },
          "response": [
            {
              "name": "200 OK – Approved",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave request approved successfully\",\n    \"data\": {\n        \"status\": \"approved\",\n        \"approved_at\": \"2026-10-07T10:30:00.000000Z\",\n        \"approved_by\": \"Admin Manager\"\n    }\n}"
            },
            {
              "name": "400 – Already Processed",
              "status": "Bad Request",
              "code": 400,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": false,\n    \"message\": \"Leave request has already been approved\"\n}"
            }
          ]
        },
        {
          "name": "7. Reject Leave Request",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{token}}" },
              { "key": "Content-Type",  "value": "application/json" },
              { "key": "Accept",        "value": "application/json" },
              { "key": "X-CSRF-TOKEN",  "value": "{{csrf_token}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n    \"rejection_reason\": \"Insufficient coverage during this period. Please reschedule.\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/leave/{{leave_request_id}}/reject",
              "host": ["{{base_url}}"],
              "path": ["leave", "{{leave_request_id}}", "reject"]
            },
            "description": "Reject a pending leave request.\n\n⚠️ Only works if current status is 'pending'.\nNo balance deduction on rejection.\nThe rejection_reason is stored in approval_notes.\n\nFIELD:\n• rejection_reason  required  max:500"
          },
          "response": [
            {
              "name": "200 OK – Rejected",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave request rejected successfully\",\n    \"data\": {\n        \"status\": \"rejected\",\n        \"rejected_at\": \"2026-10-07T11:00:00.000000Z\",\n        \"rejected_by\": \"Admin Manager\"\n    }\n}"
            },
            {
              "name": "400 – Already Processed",
              "status": "Bad Request",
              "code": 400,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": false,\n    \"message\": \"Leave request has already been rejected\"\n}"
            }
          ]
        },
        {
          "name": "8. Update Leave Status – Flexible",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Authorization", "value": "Bearer {{token}}" },
              { "key": "Content-Type",  "value": "application/json" },
              { "key": "Accept",        "value": "application/json" },
              { "key": "X-CSRF-TOKEN",  "value": "{{csrf_token}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n    \"status\": \"approved\",\n    \"comment\": \"Approved after replacement confirmed.\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/leave/{{leave_request_id}}/update-status",
              "host": ["{{base_url}}"],
              "path": ["leave", "{{leave_request_id}}", "update-status"]
            },
            "description": "Flexible status update. Moves a leave request to any status from any state.\nUsed by the admin 'Update Status' modal.\n\nFIELDS:\n• status   required  pending | approved | rejected\n• comment  optional  max:500\n\nBALANCE ADJUSTMENT:\n• Any → approved           → deducts days_count from used_days\n• approved → pending/rejected → reverses deduction (restores days)\n• Same → same              → no-op, returns success"
          },
          "response": [
            {
              "name": "200 OK – Status Updated to Approved",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave status updated to approved successfully\",\n    \"data\": {\n        \"status\": \"approved\",\n        \"updated_at\": \"2026-10-07T11:30:00.000000Z\",\n        \"updated_by\": \"Admin Manager\"\n    }\n}"
            },
            {
              "name": "200 OK – No-op (Already on Requested Status)",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave request is already approved\",\n    \"data\": { \"status\": \"approved\" }\n}"
            },
            {
              "name": "422 – Unknown Status",
              "status": "Unprocessable Entity",
              "code": 422,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": false,\n    \"message\": \"Status 'cancelled' is not configured. Please contact the administrator.\"\n}"
            }
          ]
        },
        {
          "name": "9. Delete Leave Request",
          "request": {
            "method": "DELETE",
            "header": [
              { "key": "Authorization", "value": "Bearer {{token}}" },
              { "key": "Accept",        "value": "application/json" },
              { "key": "X-CSRF-TOKEN",  "value": "{{csrf_token}}" }
            ],
            "url": {
              "raw": "{{base_url}}/leave/{{leave_request_id}}",
              "host": ["{{base_url}}"],
              "path": ["leave", "{{leave_request_id}}"]
            },
            "description": "Delete a leave request.\n\n⚠️ Only pending or rejected requests can be deleted.\nApproved requests return 400 and cannot be deleted.\n\nNo request body required."
          },
          "response": [
            {
              "name": "200 OK – Deleted",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": true,\n    \"message\": \"Leave request deleted successfully\"\n}"
            },
            {
              "name": "400 – Cannot Delete Approved",
              "status": "Bad Request",
              "code": 400,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n    \"success\": false,\n    \"message\": \"Cannot delete approved leave requests\"\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "📚 Quick Reference",
      "item": [
        {
          "name": "Leave Status Values",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/employee/leave/types",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "employee", "leave", "types"]
            },
            "description": "LEAVE STATUSES (type = 'leave' in statuses table)\n• pending  — Default on submission when requires_approval = true\n• approved — Set by admin or auto when requires_approval = false\n• rejected — Set by admin rejection\n\nHALF DAY TYPES\n• first_half  → First Half (Morning)\n• second_half → Second Half (Afternoon)\n\n.NET PAYROLL WORK TYPE IDs (FALLBACK)\n1  General Working\n2  Off Day\n3  Off Day Working\n4  Holiday\n5  Holiday Working\n6  Unpaid Leave\n7  Absent\n8  Annual Leave\n9  Medical Leave\n10 Maternity Leave\n11 Paternity Leave\n12 Hospitalization Leave\n13 Paid By SOCSO\n14 Non Schedule Day\n15 Replacement Leave\n16 Compensate Leave\n17 Marriage Leave\n\nHTTP STATUS CODES\n200  Success\n400  Business rule violation\n401  Unauthenticated\n422  Validation failed — see errors object\n500  Server / DB error"
          }
        }
      ]
    }
  ]
}
