{
  "info": {
    "name": "PMTTS API",
    "description": "Project Management & Task Tracking System — Laravel API for the PMTTS Flutter app. Run the 'Login as Admin' request first (or any 'Login as ...' request) to auto-populate the {{token}} variable used by every other request.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [{ "key": "token", "value": "{{token}}", "type": "string" }]
  },
  "variable": [
    { "key": "base_url", "value": "http://192.168.0.230:8000/api", "type": "string" },
    { "key": "token", "value": "", "type": "string" },
    { "key": "project_id", "value": "1", "type": "string" },
    { "key": "task_id", "value": "1", "type": "string" },
    { "key": "lead_id", "value": "1", "type": "string" },
    { "key": "client_id", "value": "1", "type": "string" },
    { "key": "requirement_id", "value": "1", "type": "string" },
    { "key": "document_id", "value": "1", "type": "string" },
    { "key": "work_log_id", "value": "1", "type": "string" },
    { "key": "extension_request_id", "value": "1", "type": "string" },
    { "key": "change_request_id", "value": "1", "type": "string" },
    { "key": "notification_id", "value": "", "type": "string" },
    { "key": "plan_id", "value": "1", "type": "string" },
    { "key": "plan_assignment_id", "value": "1", "type": "string" },
    { "key": "target_date", "value": "2026-07-13", "type": "string" },
    { "key": "user_id", "value": "1", "type": "string" },
    { "key": "otp", "value": "", "type": "string" },
    { "key": "holiday_id", "value": "1", "type": "string" },
    { "key": "tester_a_id", "value": "7", "type": "string" },
    { "key": "tester_b_id", "value": "10", "type": "string" },
    { "key": "developer_a_id", "value": "5", "type": "string" },
    { "key": "developer_b_id", "value": "6", "type": "string" }
  ],
  "item": [
    {
      "name": "Auth",
      "item": [
        {
          "name": "Login as Admin",
          "event": [{
            "listen": "test",
            "script": { "type": "text/javascript", "exec": [
              "const body = pm.response.json();",
              "if (body.token) { pm.collectionVariables.set('token', body.token); }",
              "if (body.user) { pm.collectionVariables.set('user_id', body.user.id); }"
            ] }
          }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"admin@pmtts.com\",\n  \"password\": \"Password@123\"\n}" },
            "url": { "raw": "{{base_url}}/auth/login", "host": ["{{base_url}}"], "path": ["auth", "login"] }
          }
        },
        {
          "name": "Login as Planner",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.token) { pm.collectionVariables.set('token', body.token); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"planner@pmtts.com\",\n  \"password\": \"Password@123\"\n}" },
            "url": { "raw": "{{base_url}}/auth/login", "host": ["{{base_url}}"], "path": ["auth", "login"] }
          }
        },
        {
          "name": "Login as Sales",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.token) { pm.collectionVariables.set('token', body.token); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"sales@pmtts.com\",\n  \"password\": \"Password@123\"\n}" },
            "url": { "raw": "{{base_url}}/auth/login", "host": ["{{base_url}}"], "path": ["auth", "login"] }
          }
        },
        {
          "name": "Login as Analyst",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.token) { pm.collectionVariables.set('token', body.token); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"analyst@pmtts.com\",\n  \"password\": \"Password@123\"\n}" },
            "url": { "raw": "{{base_url}}/auth/login", "host": ["{{base_url}}"], "path": ["auth", "login"] }
          }
        },
        {
          "name": "Login as Developer",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.token) { pm.collectionVariables.set('token', body.token); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"developer@pmtts.com\",\n  \"password\": \"Password@123\"\n}" },
            "url": { "raw": "{{base_url}}/auth/login", "host": ["{{base_url}}"], "path": ["auth", "login"] }
          }
        },
        {
          "name": "Login as Tester",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.token) { pm.collectionVariables.set('token', body.token); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"tester@pmtts.com\",\n  \"password\": \"Password@123\"\n}" },
            "url": { "raw": "{{base_url}}/auth/login", "host": ["{{base_url}}"], "path": ["auth", "login"] }
          }
        },
        {
          "name": "Login as Implementer",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.token) { pm.collectionVariables.set('token', body.token); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"implementer@pmtts.com\",\n  \"password\": \"Password@123\"\n}" },
            "url": { "raw": "{{base_url}}/auth/login", "host": ["{{base_url}}"], "path": ["auth", "login"] }
          }
        },
        {
          "name": "Logout",
          "request": {
            "method": "POST",
            "url": { "raw": "{{base_url}}/auth/logout", "host": ["{{base_url}}"], "path": ["auth", "logout"] }
          }
        },
        {
          "name": "Me",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/auth/me", "host": ["{{base_url}}"], "path": ["auth", "me"] }
          }
        },
        {
          "name": "Switch Active Role",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"role\": \"developer\"\n}" },
            "url": { "raw": "{{base_url}}/auth/switch-role", "host": ["{{base_url}}"], "path": ["auth", "switch-role"] }
          }
        },
        {
          "name": "Forgot Password (send OTP)",
          "auth": { "type": "noauth" },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.debug_otp) { pm.collectionVariables.set('otp', body.debug_otp); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"developer@pmtts.com\"\n}" },
            "url": { "raw": "{{base_url}}/auth/forgot-password", "host": ["{{base_url}}"], "path": ["auth", "forgot-password"] }
          }
        },
        {
          "name": "Resend OTP",
          "auth": { "type": "noauth" },
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"developer@pmtts.com\"\n}" },
            "url": { "raw": "{{base_url}}/auth/resend-otp", "host": ["{{base_url}}"], "path": ["auth", "resend-otp"] }
          }
        },
        {
          "name": "Verify OTP",
          "auth": { "type": "noauth" },
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"developer@pmtts.com\",\n  \"otp\": \"{{otp}}\"\n}" },
            "url": { "raw": "{{base_url}}/auth/verify-otp", "host": ["{{base_url}}"], "path": ["auth", "verify-otp"] }
          }
        },
        {
          "name": "Reset Password",
          "auth": { "type": "noauth" },
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"email\": \"developer@pmtts.com\",\n  \"otp\": \"{{otp}}\",\n  \"password\": \"NewPass@123\",\n  \"password_confirmation\": \"NewPass@123\"\n}" },
            "url": { "raw": "{{base_url}}/auth/reset-password", "host": ["{{base_url}}"], "path": ["auth", "reset-password"] }
          }
        },
        {
          "name": "Change Password",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"current_password\": \"Password@123\",\n  \"password\": \"Password@1234\",\n  \"password_confirmation\": \"Password@1234\"\n}" },
            "url": { "raw": "{{base_url}}/auth/change-password", "host": ["{{base_url}}"], "path": ["auth", "change-password"] }
          }
        },
        {
          "name": "Update Profile",
          "request": {
            "method": "POST",
            "description": "Sent as POST with a _method=PUT spoof field. PHP does not parse multipart/form-data bodies on real PUT/PATCH requests, so file uploads (profile_image) must be transported over POST; Laravel's method-spoofing then routes it as PUT.",
            "body": {
              "mode": "formdata",
              "formdata": [
                { "key": "_method", "value": "PUT", "type": "text" },
                { "key": "first_name", "value": "Ahmed", "type": "text" },
                { "key": "last_name", "value": "Al-Rashid", "type": "text" },
                { "key": "phone", "value": "+962-79-000-0000", "type": "text" },
                { "key": "department", "value": "IT Operations", "type": "text" },
                { "key": "profile_image", "type": "file", "src": [] }
              ]
            },
            "url": { "raw": "{{base_url}}/profile", "host": ["{{base_url}}"], "path": ["profile"] }
          }
        }
      ]
    },
    {
      "name": "Dashboard",
      "item": [
        {
          "name": "Get Dashboard",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/dashboard", "host": ["{{base_url}}"], "path": ["dashboard"] }
          }
        }
      ]
    },
    {
      "name": "Projects",
      "description": "Tester assignment: \"tester_ids\" (array of user IDs) is the canonical input for Create/Update Project and supports multiple testers via the project_user pivot. \"tester_assignee_id\" (single user ID) is still accepted on both endpoints as a backward-compatible legacy input. All project responses expose the merged tester set as \"testers\"; \"tester_assignee\" is not part of the response. Client assignment: \"client_ids\" (array of Client IDs from /clients) is the input for Create/Update Project and supports multiple Clients via the client_project pivot; project responses expose attached Clients as \"clients\" whenever loaded. The legacy \"client_name\"/\"client_email\"/\"client_phone\" free-text fields remain unchanged and independent of \"client_ids\"/\"clients\".",
      "item": [
        {
          "name": "List Projects",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/projects?search=&status=&technology=", "host": ["{{base_url}}"], "path": ["projects"], "query": [
              { "key": "search", "value": "" }, { "key": "status", "value": "" }, { "key": "technology", "value": "" }
            ] }
          }
        },
        {
          "name": "Create Project",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('project_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "description": "tester_ids (array of tester user IDs) is the canonical way to assign testers here — it supports multiple testers and syncs to the project_user pivot. tester_assignee_id (single ID) is still accepted for backward compatibility but is legacy; prefer tester_ids for new integrations. client_ids (array of existing Client IDs, see the Clients folder / GET /clients) is optional and attaches one or more Clients to the project via the client_project pivot; the legacy client_name/client_email/client_phone free-text fields remain independently supported and are not affected by client_ids. Each client_ids value must be an existing Client ID — an unknown ID returns HTTP 422. Duplicate IDs in the array do not create duplicate Project↔Client relationships. Omitting client_ids simply creates the Project without adding any Client relationships.",
            "body": { "mode": "raw", "raw": "{\n  \"name\": \"Warehouse Inventory System\",\n  \"description\": \"Barcode-based inventory tracking for warehouses.\",\n  \"status\": \"planning\",\n  \"technology\": \"Laravel\",\n  \"start_date\": \"2026-08-01\",\n  \"end_date\": \"2027-01-01\",\n  \"expected_working_hours\": 200,\n  \"client_name\": \"Acme Logistics\",\n  \"client_email\": \"ops@acme.com\",\n  \"client_phone\": \"+962-79-000-1111\",\n  \"sales_assignee_id\": 3,\n  \"planner_assignee_id\": 2,\n  \"analyst_assignee_id\": 4,\n  \"tester_ids\": [7],\n  \"client_ids\": [1, 2]\n}" },
            "url": { "raw": "{{base_url}}/projects", "host": ["{{base_url}}"], "path": ["projects"] }
          }
        },
        {
          "name": "Get Project",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/projects/{{project_id}}", "host": ["{{base_url}}"], "path": ["projects", "{{project_id}}"] }
          },
          "response": [
            {
              "name": "Example response (with clients and testers)",
              "originalRequest": {
                "method": "GET",
                "url": { "raw": "{{base_url}}/projects/{{project_id}}", "host": ["{{base_url}}"], "path": ["projects", "{{project_id}}"] }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "cookie": [],
              "body": "{\n  \"data\": {\n    \"id\": 12,\n    \"name\": \"Warehouse Inventory System\",\n    \"description\": \"Barcode-based inventory tracking for warehouses.\",\n    \"status\": \"planning\",\n    \"technology\": \"Laravel\",\n    \"start_date\": \"2026-08-01\",\n    \"end_date\": \"2027-01-01\",\n    \"expected_working_hours\": 200,\n    \"client_name\": \"Acme Logistics\",\n    \"client_email\": \"ops@acme.com\",\n    \"client_phone\": \"+962-79-000-1111\",\n    \"sales_assignee\": { \"id\": 3, \"full_name\": \"Omar Nasser\", \"initials\": \"ON\", \"email\": \"sales@pmtts.com\" },\n    \"planner_assignee\": { \"id\": 2, \"full_name\": \"Sara Hassan\", \"initials\": \"SH\", \"email\": \"planner@pmtts.com\" },\n    \"analyst_assignee\": { \"id\": 4, \"full_name\": \"Lina Khalil\", \"initials\": \"LK\", \"email\": \"analyst@pmtts.com\" },\n    \"testers\": [\n      { \"id\": 7, \"full_name\": \"Hana Aziz\", \"initials\": \"HA\", \"email\": \"tester@pmtts.com\" }\n    ],\n    \"clients\": [\n      { \"id\": 1, \"name\": \"Acme Logistics\", \"email\": \"ops@acme.com\", \"phone\": \"+962-79-000-1111\" }\n    ],\n    \"tasks_count\": 3,\n    \"tasks_completed_count\": 1,\n    \"created_at\": \"2026-08-01T09:00:00.000000Z\",\n    \"updated_at\": \"2026-08-19T10:00:00.000000Z\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Update Project",
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "description": "tester_ids (canonical) synchronizes the project's tester set when supplied — it replaces the full set with exactly the IDs given, and supports multiple testers. Omitting tester_ids leaves existing tester assignments unchanged. Sending tester_ids: [] clears all tester assignments. tester_assignee_id remains accepted as a legacy input for backward compatibility. client_ids follows the identical pattern for Clients: when supplied it REPLACES the project's full Client set with exactly the IDs given — this is replace behavior, not append; client_ids: [2, 5] results in exactly Clients 2 and 5 being attached, regardless of whatever Clients were attached before. Omitting client_ids leaves existing Client relationships unchanged. Sending client_ids: [] removes all Client relationships. Multiple Client IDs are supported. Each ID must be an existing Client — an unknown ID returns HTTP 422. Duplicate IDs in the array do not create duplicate pivot rows. The legacy client_name/client_email/client_phone fields are independent and unaffected by client_ids. Notification testing: sales_assignee_id, planner_assignee_id, analyst_assignee_id and tester_ids each drive the 'Project Assigned' / 'Project Removed' notifications — whoever held a field before this request receives 'Project Removed' if that field's value changes, and whoever the field points to afterward receives 'Project Assigned'; a field left unchanged (or omitted) notifies nobody. The example body assumes Create Project was run first (sales_assignee_id=3, planner_assignee_id=2, analyst_assignee_id=4, tester_ids=[7]) — resent as-is it changes nothing and triggers no notifications (no-change scenario). tester_ids defaults to [{{tester_b_id}}] here to directly replace the tester_ids:[7] set at creation (Tester A -> Tester B), since two Tester-role users are seeded by default (ids {{tester_a_id}} and {{tester_b_id}}). Only one Sales/Planner/Analyst user is seeded by default, so to test a replacement for those roles (Analyst A -> Analyst B, Sales A -> Sales B, Planner A -> Planner B) first create a second user with that role via Users > Create User, then set the relevant *_assignee_id to the new user's id.",
            "body": { "mode": "raw", "raw": "{\n  \"status\": \"development\",\n  \"sales_assignee_id\": 3,\n  \"planner_assignee_id\": 2,\n  \"analyst_assignee_id\": 4,\n  \"tester_ids\": [{{tester_b_id}}],\n  \"client_ids\": [1, 2]\n}" },
            "url": { "raw": "{{base_url}}/projects/{{project_id}}", "host": ["{{base_url}}"], "path": ["projects", "{{project_id}}"] }
          }
        },
        {
          "name": "Delete Project",
          "request": {
            "method": "DELETE",
            "url": { "raw": "{{base_url}}/projects/{{project_id}}", "host": ["{{base_url}}"], "path": ["projects", "{{project_id}}"] }
          }
        }
      ]
    },
    {
      "name": "Clients",
      "description": "Used by the mobile/frontend app to retrieve the available Clients, let the user select one or more, and then send the selected IDs as client_ids when creating or updating a Project (see the Projects folder's Create Project / Update Project requests). Create/Update/Delete are restricted to Admin and Sales (role:admin|sales); List/Get also allow Planner (role:admin|sales|planner).",
      "item": [
        {
          "name": "List Clients",
          "request": {
            "method": "GET",
            "description": "Returns the available Clients so the mobile app can display them and let the user select one or more before creating/updating a Project via client_ids. Paginated (default per_page=20); pass per_page to request a different page size, e.g. per_page=50. Each Client object contains: id, name, email, phone, created_at, updated_at.",
            "url": { "raw": "{{base_url}}/clients?per_page=20", "host": ["{{base_url}}"], "path": ["clients"], "query": [
              { "key": "per_page", "value": "20" }
            ] }
          }
        },
        {
          "name": "Create Client (Admin/Sales)",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('client_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"name\": \"Nova Retail Group\",\n  \"email\": \"contact@novaretail.com\",\n  \"phone\": \"+962-79-222-3333\"\n}" },
            "url": { "raw": "{{base_url}}/clients", "host": ["{{base_url}}"], "path": ["clients"] }
          }
        },
        {
          "name": "Get Client",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/clients/{{client_id}}", "host": ["{{base_url}}"], "path": ["clients", "{{client_id}}"] }
          }
        },
        {
          "name": "Update Client (Admin/Sales)",
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"name\": \"Nova Retail Group LLC\",\n  \"phone\": \"+962-79-222-4444\"\n}" },
            "url": { "raw": "{{base_url}}/clients/{{client_id}}", "host": ["{{base_url}}"], "path": ["clients", "{{client_id}}"] }
          }
        },
        {
          "name": "Delete Client (Admin/Sales)",
          "request": {
            "method": "DELETE",
            "url": { "raw": "{{base_url}}/clients/{{client_id}}", "host": ["{{base_url}}"], "path": ["clients", "{{client_id}}"] }
          }
        }
      ]
    },
    {
      "name": "Tasks",
      "item": [
        {
          "name": "List Tasks",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/tasks?project_id=&status=&priority=", "host": ["{{base_url}}"], "path": ["tasks"], "query": [
              { "key": "project_id", "value": "" }, { "key": "status", "value": "" }, { "key": "priority", "value": "" }
            ] }
          }
        },
        {
          "name": "Task Board (Admin/Planner)",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/tasks/board?project_id=", "host": ["{{base_url}}"], "path": ["tasks", "board"], "query": [{ "key": "project_id", "value": "" }] }
          }
        },
        {
          "name": "My Tasks (Developer/Tester)",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/tasks/my-tasks", "host": ["{{base_url}}"], "path": ["tasks", "my-tasks"] }
          }
        },
        {
          "name": "Create Task",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('task_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"project_id\": {{project_id}},\n  \"title\": \"Set up staging environment\",\n  \"description\": \"Provision and configure the staging server.\",\n  \"priority\": \"high\",\n  \"due_date\": \"2026-08-01\",\n  \"estimated_hours\": 16,\n  \"developer_ids\": [5, 6]\n}" },
            "url": { "raw": "{{base_url}}/tasks", "host": ["{{base_url}}"], "path": ["tasks"] }
          }
        },
        {
          "name": "Get Task",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/tasks/{{task_id}}", "host": ["{{base_url}}"], "path": ["tasks", "{{task_id}}"] }
          }
        },
        {
          "name": "Update Task",
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "description": "status drives the 'Task Status Updated' notification (Admin/Planner) whenever it actually changes; a change into 'completed' sends 'Task Completed' instead of 'Task Status Updated'; a change from 'completed' to 'reopened' additionally notifies the task's current developer(s) with 'Task Reopened' (completed -> any other status does not send 'Task Reopened'). Sending the same status as before, or omitting status, triggers no status notification. developer_ids (optional) replaces the task's full developer set with exactly the IDs given, same replace semantics as Project tester_ids — whoever is removed receives 'Task Removed' and whoever is newly added receives 'New Task Assigned'; omitting developer_ids leaves the current developers unchanged and sends no assignment notification. The example body assumes Create Task was run first with developer_ids:[5, 6]; to test Developer A -> Developer B cleanly, first PUT with developer_ids: [{{developer_a_id}}] alone, then PUT again with developer_ids: [{{developer_b_id}}] as shown below.",
            "body": { "mode": "raw", "raw": "{\n  \"status\": \"inProgress\",\n  \"actual_hours\": 4,\n  \"developer_ids\": [{{developer_b_id}}]\n}" },
            "url": { "raw": "{{base_url}}/tasks/{{task_id}}", "host": ["{{base_url}}"], "path": ["tasks", "{{task_id}}"] }
          }
        },
        {
          "name": "Add Comment to Task",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"body\": \"This task is blocking the release. Please prioritize it.\"\n}" },
            "url": { "raw": "{{base_url}}/tasks/{{task_id}}/comments", "host": ["{{base_url}}"], "path": ["tasks", "{{task_id}}", "comments"] }
          }
        },
        {
          "name": "Start Task Timer",
          "request": {
            "method": "POST",
            "url": { "raw": "{{base_url}}/tasks/{{task_id}}/timer/start", "host": ["{{base_url}}"], "path": ["tasks", "{{task_id}}", "timer", "start"] }
          }
        },
        {
          "name": "Stop Task Timer",
          "request": {
            "method": "POST",
            "url": { "raw": "{{base_url}}/tasks/{{task_id}}/timer/stop", "host": ["{{base_url}}"], "path": ["tasks", "{{task_id}}", "timer", "stop"] }
          }
        },
        {
          "name": "Get Current Task Timer",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/tasks/{{task_id}}/timer", "host": ["{{base_url}}"], "path": ["tasks", "{{task_id}}", "timer"] }
          }
        },
        {
          "name": "Delete Task",
          "request": {
            "method": "DELETE",
            "url": { "raw": "{{base_url}}/tasks/{{task_id}}", "host": ["{{base_url}}"], "path": ["tasks", "{{task_id}}"] }
          }
        }
      ]
    },
    {
      "name": "Leads (Sales)",
      "item": [
        {
          "name": "List Leads",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/leads?status=&search=", "host": ["{{base_url}}"], "path": ["leads"], "query": [{ "key": "status", "value": "" }, { "key": "search", "value": "" }] }
          }
        },
        {
          "name": "Create Lead",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('lead_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"company_name\": \"Nova Retail Group\",\n  \"contact_name\": \"Yousef Amer\",\n  \"email\": \"yousef@novaretail.com\",\n  \"phone\": \"+962-79-222-3333\",\n  \"estimated_days\": 60,\n  \"description\": \"Point-of-sale integration with existing inventory system.\"\n}" },
            "url": { "raw": "{{base_url}}/leads", "host": ["{{base_url}}"], "path": ["leads"] }
          }
        },
        {
          "name": "Get Lead",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/leads/{{lead_id}}", "host": ["{{base_url}}"], "path": ["leads", "{{lead_id}}"] }
          }
        },
        {
          "name": "Update Lead",
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"status\": \"qualified\"\n}" },
            "url": { "raw": "{{base_url}}/leads/{{lead_id}}", "host": ["{{base_url}}"], "path": ["leads", "{{lead_id}}"] }
          }
        },
        {
          "name": "Convert Lead to Project",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "description": "tester_assignee_id here is a legacy/backward-compatible input (single tester). Lead conversion does not currently support tester_ids or multiple testers.",
            "body": { "mode": "raw", "raw": "{\n  \"planner_assignee_id\": 2,\n  \"analyst_assignee_id\": 4,\n  \"tester_assignee_id\": 7\n}" },
            "url": { "raw": "{{base_url}}/leads/{{lead_id}}/convert", "host": ["{{base_url}}"], "path": ["leads", "{{lead_id}}", "convert"] }
          }
        },
        {
          "name": "Delete Lead",
          "request": {
            "method": "DELETE",
            "url": { "raw": "{{base_url}}/leads/{{lead_id}}", "host": ["{{base_url}}"], "path": ["leads", "{{lead_id}}"] }
          }
        }
      ]
    },
    {
      "name": "Requirements (Analyst)",
      "item": [
        {
          "name": "List Requirements",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/requirements?project_id=", "host": ["{{base_url}}"], "path": ["requirements"], "query": [{ "key": "project_id", "value": "" }] }
          }
        },
        {
          "name": "Upload Requirement (BRD/SRS)",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('requirement_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "body": {
              "mode": "formdata",
              "formdata": [
                { "key": "project_id", "value": "{{project_id}}", "type": "text" },
                { "key": "title", "value": "Business Requirements Document", "type": "text" },
                { "key": "type", "value": "BRD", "type": "text" },
                { "key": "version", "value": "v1.0", "type": "text" },
                { "key": "file", "type": "file", "src": [] }
              ]
            },
            "url": { "raw": "{{base_url}}/requirements", "host": ["{{base_url}}"], "path": ["requirements"] }
          }
        },
        {
          "name": "Get Requirement",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/requirements/{{requirement_id}}", "host": ["{{base_url}}"], "path": ["requirements", "{{requirement_id}}"] }
          },
          "response": [
            {
              "name": "Example response (file_path is a full URL)",
              "originalRequest": {
                "method": "GET",
                "url": { "raw": "{{base_url}}/requirements/{{requirement_id}}", "host": ["{{base_url}}"], "path": ["requirements", "{{requirement_id}}"] }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "cookie": [],
              "body": "{\n  \"data\": {\n    \"id\": 8,\n    \"project_id\": 5,\n    \"project_name\": \"sandy Inventory System\",\n    \"title\": \"Business Requirements Document\",\n    \"type\": \"BRD\",\n    \"file_path\": \"http://192.168.0.230:8000/storage/requirements/Z8rmZYZBV7IX2LiwSZvFLh8VkjZF3G1tpZzYMWi8.pdf\",\n    \"version\": \"v1.0\",\n    \"status\": \"pending\",\n    \"uploader\": { \"id\": 1, \"full_name\": \"Ahmed Al-Rashid M\", \"initials\": \"AA\", \"email\": \"admin@pmtts.com\" },\n    \"created_at\": \"2026-08-10T14:37:36.000000Z\"\n  }\n}"
            },
            {
              "name": "Example response (no file uploaded, file_path is null)",
              "originalRequest": {
                "method": "GET",
                "url": { "raw": "{{base_url}}/requirements/{{requirement_id}}", "host": ["{{base_url}}"], "path": ["requirements", "{{requirement_id}}"] }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "cookie": [],
              "body": "{\n  \"data\": {\n    \"id\": 1,\n    \"project_id\": 1,\n    \"project_name\": \"E-Commerce Platform Redesign\",\n    \"title\": \"Business Requirements Document\",\n    \"type\": \"BRD\",\n    \"file_path\": null,\n    \"version\": \"v1.0\",\n    \"status\": \"approved\",\n    \"uploader\": { \"id\": 4, \"full_name\": \"Lina Khalil\", \"initials\": \"LK\", \"email\": \"analyst@pmtts.com\" },\n    \"created_at\": \"2026-07-13T09:39:22.000000Z\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Update/Approve Requirement",
          "request": {
            "method": "PATCH",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"status\": \"approved\"\n}" },
            "url": { "raw": "{{base_url}}/requirements/{{requirement_id}}", "host": ["{{base_url}}"], "path": ["requirements", "{{requirement_id}}"] }
          }
        },
        {
          "name": "Delete Requirement",
          "request": {
            "method": "DELETE",
            "url": { "raw": "{{base_url}}/requirements/{{requirement_id}}", "host": ["{{base_url}}"], "path": ["requirements", "{{requirement_id}}"] }
          }
        }
      ]
    },
    {
      "name": "Documents (Implementer)",
      "item": [
        {
          "name": "List Documents",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/documents?project_id=&type=", "host": ["{{base_url}}"], "path": ["documents"], "query": [{ "key": "project_id", "value": "" }, { "key": "type", "value": "" }] }
          }
        },
        {
          "name": "Upload Document",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('document_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "body": {
              "mode": "formdata",
              "formdata": [
                { "key": "project_id", "value": "{{project_id}}", "type": "text" },
                { "key": "name", "value": "System Deployment Guide v2.3", "type": "text" },
                { "key": "type", "value": "project_document", "type": "text" },
                { "key": "file", "type": "file", "src": [] }
              ]
            },
            "url": { "raw": "{{base_url}}/documents", "host": ["{{base_url}}"], "path": ["documents"] }
          }
        },
        {
          "name": "Get Document",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/documents/{{document_id}}", "host": ["{{base_url}}"], "path": ["documents", "{{document_id}}"] }
          },
          "response": [
            {
              "name": "Example response (file_path is a full URL)",
              "originalRequest": {
                "method": "GET",
                "url": { "raw": "{{base_url}}/documents/{{document_id}}", "host": ["{{base_url}}"], "path": ["documents", "{{document_id}}"] }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "cookie": [],
              "body": "{\n  \"data\": {\n    \"id\": 3,\n    \"project_id\": 2,\n    \"project_name\": \"HR Management System\",\n    \"name\": \"System Deployment Guide v2.3\",\n    \"type\": \"training_material\",\n    \"file_path\": \"http://192.168.0.230:8000/storage/documents/system-deployment-guide-v23.pdf\",\n    \"uploader\": { \"id\": 8, \"full_name\": \"Tarek Saad\", \"initials\": \"TS\", \"email\": \"implementer@pmtts.com\" },\n    \"created_at\": \"2026-07-13T09:39:22.000000Z\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Delete Document",
          "request": {
            "method": "DELETE",
            "url": { "raw": "{{base_url}}/documents/{{document_id}}", "host": ["{{base_url}}"], "path": ["documents", "{{document_id}}"] }
          }
        }
      ]
    },
    {
      "name": "Work Logs",
      "item": [
        {
          "name": "List Work Logs (mine, or all as Admin)",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/work-logs?user_id=", "host": ["{{base_url}}"], "path": ["work-logs"], "query": [{ "key": "user_id", "value": "" }] }
          }
        },
        {
          "name": "Create Work Log",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('work_log_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"task_id\": {{task_id}},\n  \"project_id\": {{project_id}},\n  \"log_date\": \"2026-07-09\",\n  \"status\": \"inProgress\",\n  \"hours_worked\": 6,\n  \"task_progress\": 55,\n  \"accomplishment_notes\": \"Completed the product listing API endpoints and started integration tests.\",\n  \"check_in_at\": \"2026-07-09 09:00:00\"\n}" },
            "url": { "raw": "{{base_url}}/work-logs", "host": ["{{base_url}}"], "path": ["work-logs"] }
          }
        },
        {
          "name": "Get Work Log",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/work-logs/{{work_log_id}}", "host": ["{{base_url}}"], "path": ["work-logs", "{{work_log_id}}"] }
          }
        },
        {
          "name": "Update Work Log (check out)",
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"check_out_at\": \"2026-07-09 17:00:00\",\n  \"task_progress\": 80\n}" },
            "url": { "raw": "{{base_url}}/work-logs/{{work_log_id}}", "host": ["{{base_url}}"], "path": ["work-logs", "{{work_log_id}}"] }
          }
        }
      ]
    },
    {
      "name": "Extension Requests",
      "item": [
        {
          "name": "List Extension Requests",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/extension-requests?status=", "host": ["{{base_url}}"], "path": ["extension-requests"], "query": [{ "key": "status", "value": "" }] }
          }
        },
        {
          "name": "Submit Extension Request (Developer)",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('extension_request_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"task_id\": {{task_id}},\n  \"reason\": \"Additional integration testing is required before this can be marked complete.\",\n  \"requested_deadline\": \"2026-08-15\",\n  \"supporting_notes\": \"Blocked on third-party API access.\"\n}" },
            "url": { "raw": "{{base_url}}/extension-requests", "host": ["{{base_url}}"], "path": ["extension-requests"] }
          }
        },
        {
          "name": "Get Extension Request",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/extension-requests/{{extension_request_id}}", "host": ["{{base_url}}"], "path": ["extension-requests", "{{extension_request_id}}"] }
          }
        },
        {
          "name": "Review Extension Request (Planner/Admin)",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"status\": \"approved\",\n  \"review_notes\": \"Approved, please proceed.\"\n}" },
            "url": { "raw": "{{base_url}}/extension-requests/{{extension_request_id}}/review", "host": ["{{base_url}}"], "path": ["extension-requests", "{{extension_request_id}}", "review"] }
          }
        }
      ]
    },
    {
      "name": "Change Requests",
      "item": [
        {
          "name": "List Change Requests",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/change-requests?status=", "host": ["{{base_url}}"], "path": ["change-requests"], "query": [{ "key": "status", "value": "" }] }
          }
        },
        {
          "name": "Submit Change Request (Analyst/Developer)",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('change_request_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"project_id\": {{project_id}},\n  \"task_id\": {{task_id}},\n  \"description\": \"Client requested an additional multi-currency checkout option.\",\n  \"impact_assessment\": \"Adds an estimated 2 weeks to the timeline.\"\n}" },
            "url": { "raw": "{{base_url}}/change-requests", "host": ["{{base_url}}"], "path": ["change-requests"] }
          }
        },
        {
          "name": "Get Change Request",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/change-requests/{{change_request_id}}", "host": ["{{base_url}}"], "path": ["change-requests", "{{change_request_id}}"] }
          }
        },
        {
          "name": "Review Change Request (Planner/Admin)",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"status\": \"approved\",\n  \"review_notes\": \"Approved, scope updated.\"\n}" },
            "url": { "raw": "{{base_url}}/change-requests/{{change_request_id}}/review", "host": ["{{base_url}}"], "path": ["change-requests", "{{change_request_id}}", "review"] }
          }
        }
      ]
    },
    {
      "name": "Notifications",
      "item": [
        {
          "name": "List Notifications",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.length) { pm.collectionVariables.set('notification_id', body.data[0].id); }",
            "",
            "pm.test('response is a paginated notifications list', function () {",
            "    pm.response.to.have.status(200);",
            "    pm.expect(body).to.have.property('data');",
            "});",
            "",
            "if (body.data && body.data.length) {",
            "    pm.test('most recent notification has a title and body (list is latest-first)', function () {",
            "        pm.expect(body.data[0].data).to.have.property('title');",
            "        pm.expect(body.data[0].data).to.have.property('body');",
            "    });",
            "}"
          ] } }],
          "request": {
            "method": "GET",
            "description": "Returns the authenticated user's notifications, newest first (Laravel's notifications() relation orders by created_at desc), so body.data[0] is always the most recently received notification for whoever {{token}} currently belongs to. To verify a specific notification feature: log in as the expected recipient (e.g. Login as Tester after a Tester replacement), then call this immediately after the triggering action — body.data[0].data.title / .body / .task_id / .project_id will describe the notification just generated. The response is not filtered by type or read status, so if other notifications may have landed for the same user in between, check further down body.data rather than assuming index 0.",
            "url": { "raw": "{{base_url}}/notifications", "host": ["{{base_url}}"], "path": ["notifications"] }
          }
        },
        {
          "name": "Unread Count",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/notifications/unread-count", "host": ["{{base_url}}"], "path": ["notifications", "unread-count"] }
          }
        },
        {
          "name": "Mark Notification as Read",
          "request": {
            "method": "POST",
            "url": { "raw": "{{base_url}}/notifications/{{notification_id}}/read", "host": ["{{base_url}}"], "path": ["notifications", "{{notification_id}}", "read"] }
          }
        },
        {
          "name": "Mark All as Read",
          "request": {
            "method": "POST",
            "url": { "raw": "{{base_url}}/notifications/read-all", "host": ["{{base_url}}"], "path": ["notifications", "read-all"] }
          }
        }
      ]
    },
    {
      "name": "Audit Logs",
      "item": [
        {
          "name": "List Audit Logs",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/audit-logs?action_type=&search=", "host": ["{{base_url}}"], "path": ["audit-logs"], "query": [{ "key": "action_type", "value": "" }, { "key": "search", "value": "" }] }
          }
        }
      ]
    },
    {
      "name": "Reports (Admin/Analyst)",
      "item": [
        {
          "name": "Task/Project Reports",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/reports", "host": ["{{base_url}}"], "path": ["reports"] }
          }
        },
        {
          "name": "Team Utilization Report",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/reports/team-utilization?from=&to=", "host": ["{{base_url}}"], "path": ["reports", "team-utilization"], "query": [{ "key": "from", "value": "" }, { "key": "to", "value": "" }] }
          }
        }
      ]
    },
    {
      "name": "Users (Admin)",
      "item": [
        {
          "name": "List Users",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/users?search=&role=&is_active=", "host": ["{{base_url}}"], "path": ["users"], "query": [{ "key": "search", "value": "" }, { "key": "role", "value": "" }, { "key": "is_active", "value": "" }] }
          }
        },
        {
          "name": "Create User",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('user_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"first_name\": \"Reem\",\n  \"last_name\": \"Odeh\",\n  \"email\": \"reem.odeh@pmtts.com\",\n  \"username\": \"reem.odeh\",\n  \"department\": \"Engineering\",\n  \"roles\": [\"developer\"]\n}" },
            "url": { "raw": "{{base_url}}/users", "host": ["{{base_url}}"], "path": ["users"] }
          }
        },
        {
          "name": "Get User",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/users/{{user_id}}", "host": ["{{base_url}}"], "path": ["users", "{{user_id}}"] }
          }
        },
        {
          "name": "Update User",
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"department\": \"Quality Assurance\",\n  \"roles\": [\"developer\", \"tester\"]\n}" },
            "url": { "raw": "{{base_url}}/users/{{user_id}}", "host": ["{{base_url}}"], "path": ["users", "{{user_id}}"] }
          }
        },
        {
          "name": "Toggle Active/Inactive",
          "request": {
            "method": "POST",
            "url": { "raw": "{{base_url}}/users/{{user_id}}/toggle-active", "host": ["{{base_url}}"], "path": ["users", "{{user_id}}", "toggle-active"] }
          }
        },
        {
          "name": "Delete User",
          "request": {
            "method": "DELETE",
            "url": { "raw": "{{base_url}}/users/{{user_id}}", "host": ["{{base_url}}"], "path": ["users", "{{user_id}}"] }
          }
        }
      ]
    },
    {
      "name": "Team Assignment / Plans (Admin/Planner)",
      "item": [
        {
          "name": "List Plans",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/plans", "host": ["{{base_url}}"], "path": ["plans"] }
          }
        },
        {
          "name": "Get My Assignments",
          "request": {
            "method": "GET",
            "description": "Returns the authenticated user's own assignments for the current active Plan only (not other users'). Each assignment includes `target` (session slot: session_1/session_2/together) and a separate `is_target` boolean (whether Admin/Planner flagged that assignment as a Target) alongside project, date, and note.",
            "url": { "raw": "{{base_url}}/plans/my-assignments", "host": ["{{base_url}}"], "path": ["plans", "my-assignments"] }
          }
        },
        {
          "name": "Get Active Plan",
          "request": {
            "method": "GET",
            "description": "Admin/Planner only. Returns the COMPLETE current active Plan (start_date <= today <= end_date; newest created wins on overlap), including every assignment for every user — not just the caller's own. Returns `{ \"data\": null }` if no Plan is currently active. Each assignment includes `target` (session slot) and the separate `is_target` boolean.",
            "url": { "raw": "{{base_url}}/plans/active", "host": ["{{base_url}}"], "path": ["plans", "active"] }
          }
        },
        {
          "name": "Get Target Assignments By Date",
          "request": {
            "method": "GET",
            "description": "Admin/Planner only. Returns ONLY the assignments belonging to the CURRENT ACTIVE Plan (same active-Plan resolution as /plans/active) that are on the given `date` AND explicitly marked `is_target = true`, across all users. The `target` field (session_1/session_2/together) is NOT used to decide inclusion — an assignment with `target=session_1` and `is_target=false` is excluded, while `is_target=true` is included regardless of its session value. Returns `{ \"data\": [] }` if there is no active Plan, or if the active Plan has no matching target assignments on that date. `date` is required.",
            "url": {
              "raw": "{{base_url}}/plans/targets?date={{target_date}}",
              "host": ["{{base_url}}"],
              "path": ["plans", "targets"],
              "query": [{ "key": "date", "value": "{{target_date}}" }]
            }
          }
        },
        {
          "name": "Create Plan (with day-by-day assignments)",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('plan_id', body.data.id); }",
            "if (body.data && body.data.assignments && body.data.assignments.length) { pm.collectionVariables.set('plan_assignment_id', body.data.assignments[0].id); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"session_label\": \"Sprint Plan\",\n  \"start_date\": \"2026-07-13\",\n  \"end_date\": \"2026-07-17\",\n  \"frequency\": \"weekly\",\n  \"assignments\": [\n    { \"project_id\": {{project_id}}, \"user_id\": 5, \"assignment_date\": \"2026-07-13\", \"target\": \"session_1\", \"is_target\": true, \"note\": \"Focus on API endpoints\" },\n    { \"project_id\": {{project_id}}, \"user_id\": 6, \"assignment_date\": \"2026-07-13\", \"target\": \"session_2\", \"is_target\": false, \"note\": \"QA support\" }\n  ]\n}" },
            "url": { "raw": "{{base_url}}/plans", "host": ["{{base_url}}"], "path": ["plans"] }
          }
        },
        {
          "name": "Get Plan",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/plans/{{plan_id}}", "host": ["{{base_url}}"], "path": ["plans", "{{plan_id}}"] }
          }
        },
        {
          "name": "Update Plan",
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "description": "Admin/Planner only. Updates the existing Plan in place (same `plan_id`) — also available via PATCH on the same URL. The `assignments` array, when included, represents the COMPLETE desired state of the Plan's assignments: an item with an existing `id` is updated in place (its id and plan_id are preserved); an item with no `id` is created as a new assignment on this Plan; any existing assignment whose `id` is NOT present in the array is deleted. `target` (session slot) and `is_target` (boolean) are independent and both persisted as sent. `note` is nullable and can be cleared by sending `null`. Sending an assignment `id` that belongs to a different Plan is rejected with 422 and makes no changes. Omit `assignments` entirely to update only the Plan's own fields (session_label/start_date/end_date/frequency) without touching assignments.",
            "body": { "mode": "raw", "raw": "{\n  \"session_label\": \"Sprint Plan (Revised)\",\n  \"start_date\": \"2026-07-13\",\n  \"end_date\": \"2026-07-18\",\n  \"frequency\": \"weekly\",\n  \"assignments\": [\n    { \"id\": {{plan_assignment_id}}, \"project_id\": {{project_id}}, \"user_id\": 5, \"assignment_date\": \"2026-07-13\", \"target\": \"session_1\", \"is_target\": true, \"note\": \"Focus on API endpoints\" },\n    { \"project_id\": {{project_id}}, \"user_id\": 6, \"assignment_date\": \"2026-07-14\", \"target\": \"session_2\", \"is_target\": false, \"note\": \"QA support\" }\n  ]\n}" },
            "url": { "raw": "{{base_url}}/plans/{{plan_id}}", "host": ["{{base_url}}"], "path": ["plans", "{{plan_id}}"] }
          }
        },
        {
          "name": "Plan Summary",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/plans/{{plan_id}}/summary", "host": ["{{base_url}}"], "path": ["plans", "{{plan_id}}", "summary"] }
          }
        },
        {
          "name": "Latest Plan Summary",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/plans/latest-summary", "host": ["{{base_url}}"], "path": ["plans", "latest-summary"] }
          }
        }
      ]
    },
    {
      "name": "System Settings (Admin)",
      "item": [
        {
          "name": "Get Settings",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/system-settings", "host": ["{{base_url}}"], "path": ["system-settings"] }
          }
        },
        {
          "name": "Update Settings",
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"settings\": {\n    \"language\": \"en\",\n    \"date_format\": \"DD/MM/YYYY\",\n    \"notify_overdue_tasks\": \"1\",\n    \"plan_suggestion_frequency\": \"weekly\"\n  }\n}" },
            "url": { "raw": "{{base_url}}/system-settings", "host": ["{{base_url}}"], "path": ["system-settings"] }
          }
        },
        {
          "name": "List Holidays",
          "request": {
            "method": "GET",
            "url": { "raw": "{{base_url}}/holidays", "host": ["{{base_url}}"], "path": ["holidays"] }
          }
        },
        {
          "name": "Add Holiday",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "const body = pm.response.json();",
            "if (body.data && body.data.id) { pm.collectionVariables.set('holiday_id', body.data.id); }"
          ] } }],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"date\": \"2026-08-20\",\n  \"name\": \"National Day\"\n}" },
            "url": { "raw": "{{base_url}}/holidays", "host": ["{{base_url}}"], "path": ["holidays"] }
          }
        },
        {
          "name": "Delete Holiday",
          "request": {
            "method": "DELETE",
            "url": { "raw": "{{base_url}}/holidays/{{holiday_id}}", "host": ["{{base_url}}"], "path": ["holidays", "{{holiday_id}}"] }
          }
        }
      ]
    }
  ]
}
