﻿{
  "info": {
    "_postman_id": "maintenance-missing-features-v2-aya",
    "name": "Maintenance Domain - Missing Features API AYA",
    "description": "# Maintenance Domain Missing Features API\n\n## Base URL\n`{{base_url}}` = `http://localhost:8000/api/v1`\n\nExample: `{{base_url}}/maintenance/price-offers`\n\n## Authentication\n1. Run **Login** request first\n2. Token is auto-saved to `auth_token` variable\n\n## Features\n1. Price Offer Versioning\n2. Price Offer PDF Export\n3. Handover Visits\n4. Customer Approval Reminders (Scheduler)\n5. Contract Expiry Alerts (Scheduler)",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{auth_token}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "http://localhost:8000/api/v1",
      "type": "string",
      "description": "Base URL including API version prefix"
    },
    {
      "key": "auth_token",
      "value": "",
      "type": "string"
    },
    {
      "key": "offer_id",
      "value": "1",
      "type": "string"
    },
    {
      "key": "visit_id",
      "value": "2",
      "type": "string"
    },
    {
      "key": "technical_offer_id",
      "value": "1",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Authentication",
      "description": "Run Login first to get token",
      "item": [
        {
          "name": "Login",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "var response = pm.response.json();",
                  "if (response.result && response.result.token) {",
                  "    pm.collectionVariables.set('auth_token', response.result.token);",
                  "    pm.test('Login successful - token saved', function() { pm.response.to.have.status(200); });",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n    \"phone_or_email\": \"admin@admin.com\",\n    \"password\": \"admin\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/auth/login",
              "host": ["{{base_url}}"],
              "path": ["auth", "login"]
            },
            "description": "Login to get Bearer token. Token is auto-saved to auth_token variable."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Maintenance Requests (US-001)",
      "description": "Create / Update / Delete / List maintenance price requests — includes preventive-maintenance fields (shown when request_type = preventive)",
      "item": [
        {
          "name": "List All Requests",
          "request": {
            "method": "GET",
            "header": [ { "key": "Accept", "value": "application/json" }, { "key": "Authorization", "value": "Bearer {{auth_token}}" } ],
            "url": {
              "raw": "{{base_url}}/maintenance/requests?per_page=9999",
              "host": ["{{base_url}}"],
              "path": ["maintenance","requests"],
              "query": [ { "key": "per_page", "value": "9999" } ]
            },
            "description": "Retrieve all maintenance requests (set per_page large to fetch all). Use filters (status,priority,customer_id) as needed."
          },
          "response": []
        },
        {
          "name": "Create Price Request (Preventive)",
          "request": {
            "method": "POST",
            "header": [ { "key": "Authorization", "value": "Bearer {{auth_token}}" , "type": "text" }, { "key": "Content-Type", "value": "application/json", "type": "text" } ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"customer_id\": 2,\n  \"customer_name\": \"ABC Facilities\",\n  \"location_id\": null,\n  \"contact_id\": null,\n  \"source\": \"manual\", // allowed values: manual, portal, api, system\n  \"technical_supervisor_id\": null,\n  \"is_percentage\": false,\n  \"reported_issue\": \"طلب تسعير لعقد صيانة وقائية - فحص شامل للمعدات.\",\n  \"request_type\": \"preventive\",\n  \"priority\": \"normal\",\n  \"assigned_to\": null,\n  \"requested_at\": \"2026-02-19 10:00:00\",\n  \"preferred_visit_date\": \"2026-03-01\",\n  \"notes\": \"طلب عقد صيانة وقائية - مبنى فرعي\",\n  \"save_as_draft\": false,\n\n  // --- Preventive-specific fields (shown when request_type = preventive) ---\n  \"system_types\": [\"HVAC\", \"generators\"],\n  \"has_chiller\": true,\n  \"approximate_unit_count\": 12,\n  \"visit_frequency\": \"quarterly\",\n  \"consumables_required\": true,\n  \"consumable_types\": [\"filters\", \"oils\"],\n  \"scope_of_work\": \"تنظيف مرشحات، فحص تشغيل، استبدال قطع بسيطة عند الحاجة\"\n}"
            },
            "url": { "raw": "{{base_url}}/maintenance/requests", "host": ["{{base_url}}"], "path": ["maintenance","requests"] }
          },
          "response": []
        },
        {
          "name": "Get Request",
          "request": {
            "method": "GET",
            "header": [ { "key": "Authorization", "value": "Bearer {{auth_token}}" } ],
            "url": { "raw": "{{base_url}}/maintenance/requests/1", "host": ["{{base_url}}"], "path": ["maintenance","requests","1"] }
          },
          "response": []
        },
        {
          "name": "Update Request",
          "request": {
            "method": "PUT",
            "header": [ { "key": "Authorization", "value": "Bearer {{auth_token}}" , "type": "text" }, { "key": "Content-Type", "value": "application/json", "type": "text" } ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"location_id\": 10,\n  \"contact_id\": 5,\n  \"request_type\": \"preventive\",\n  \"priority\": \"high\",\n  \"notes\": \"تحديث نطاق الأعمال ورفع أولوية\",\n\n  // Preventive fields (can be updated)\n  \"system_types\": [\"HVAC\"],\n  \"has_chiller\": false,\n  \"approximate_unit_count\": 8,\n  \"visit_frequency\": \"monthly\",\n  \"consumables_required\": false,\n  \"consumable_types\": []\n}"
            },
            "url": { "raw": "{{base_url}}/maintenance/requests/1", "host": ["{{base_url}}"], "path": ["maintenance","requests","1"] }
          },
          "response": []
        },
        {
          "name": "Delete Request (Soft)",
          "request": {
            "method": "DELETE",
            "header": [ { "key": "Authorization", "value": "Bearer {{auth_token}}" } ],
            "url": { "raw": "{{base_url}}/maintenance/requests/1", "host": ["{{base_url}}"], "path": ["maintenance","requests","1"] }
          },
          "response": []
        },
        {
          "name": "Update Request Status",
          "request": {
            "method": "PUT",
            "header": [ { "key": "Authorization", "value": "Bearer {{auth_token}}" , "type": "text" }, { "key": "Content-Type", "value": "application/json", "type": "text" } ],
            "body": { "mode": "raw", "raw": "{\n  \"status\": \"assigned\",\n  \"notes\": \"Assigned to technician\"\n}" },
            "url": { "raw": "{{base_url}}/maintenance/requests/1/status", "host": ["{{base_url}}"], "path": ["maintenance","requests","1","status"] }
          },
          "response": []
        },
        {
          "name": "Convert Request → Technical Offer (Convert-to-Quote)",
          "request": {
            "method": "POST",
            "header": [ { "key": "Authorization", "value": "Bearer {{auth_token}}" , "type": "text" }, { "key": "Content-Type", "value": "application/json", "type": "text" } ],
            "body": { "mode": "raw", "raw": "{\n  \"description\": \"Convert request to technical offer for pricing\",\n  \"contract_type\": \"preventive\",\n  \"visit_count\": 4,\n  \"visit_frequency\": \"quarterly\"\n}" },
            "url": { "raw": "{{base_url}}/maintenance/requests/1/convert-to-quote", "host": ["{{base_url}}"], "path": ["maintenance","requests","1","convert-to-quote"] },
            "description": "Convert a maintenance request (order_id) to a Technical Offer — frontend should send the request/order id when initiating price creation. After conversion use /maintenance/price-offers/from-technical-offer/{technical_offer_id} to create the price offer."
          },
          "response": []
        },
        {
          "name": "Assign Technician",
          "request": {
            "method": "POST",
            "header": [ { "key": "Authorization", "value": "Bearer {{auth_token}}" , "type": "text" }, { "key": "Content-Type", "value": "application/json", "type": "text" } ],
            "body": { "mode": "raw", "raw": "{\n  \"technician_id\": 5\n}" },
            "url": { "raw": "{{base_url}}/maintenance/requests/1/technician", "host": ["{{base_url}}"], "path": ["maintenance","requests","1","technician"] }
          },
          "response": []
        },
        {
          "name": "Assign Staff",
          "request": {
            "method": "POST",
            "header": [ { "key": "Authorization", "value": "Bearer {{auth_token}}" , "type": "text" }, { "key": "Content-Type", "value": "application/json", "type": "text" } ],
            "body": { "mode": "raw", "raw": "{\n  \"staff_id\": 6\n}" },
            "url": { "raw": "{{base_url}}/maintenance/requests/1/staff", "host": ["{{base_url}}"], "path": ["maintenance","requests","1","staff"] }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Price Offer Versioning",
      "description": "Endpoints for managing price offer versions",
      "item": [
        {
          "name": "Create Price Offer from Request (recommended flow)",
          "request": {
            "method": "POST",
            "header": [ { "key": "Authorization", "value": "Bearer {{auth_token}}", "type": "text" }, { "key": "Content-Type", "value": "application/json", "type": "text" } ],
            "body": { "mode": "raw", "raw": "{\n  \"description\": \"Create technical offer from request/order\",\n  \"contract_type\": \"preventive\",\n  \"visit_count\": 4,\n  \"visit_frequency\": \"quarterly\"\n}" },
            "url": { "raw": "{{base_url}}/maintenance/requests/1/convert-to-quote", "host": ["{{base_url}}"], "path": ["maintenance","requests","1","convert-to-quote"] },
            "description": "Recommended flow for frontend: send `order_id` (maintenance request id) to `/maintenance/requests/{id}/convert-to-quote` to create a Technical Offer, then call `/maintenance/price-offers/from-technical-offer/{technical_offer_id}`. Do NOT send `technical_offer_id` from the UI — send the request/order id and let the server create the technical offer."
          },
          "response": []
        },
        {
          "name": "1. List All Price Offers",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers?per_page=15",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers"],
              "query": [
                { "key": "per_page", "value": "15" },
                { "key": "status", "value": "pending_customer_approval", "disabled": true }
              ]
            }
          },
          "response": []
        },
        {
          "name": "2. List Latest Versions Only",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/latest-versions?per_page=15",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "latest-versions"],
              "query": [
                { "key": "per_page", "value": "15" },
                { "key": "status", "value": "pending_customer_approval", "disabled": true }
              ]
            },
            "description": "Returns only the latest version of each offer chain."
          },
          "response": []
        },
        {
          "name": "3. Get Pending Pricing Offers",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/pending-pricing",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "pending-pricing"]
            }
          },
          "response": []
        },
        {
          "name": "4. Get Price Offer Details",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}"]
            }
          },
          "response": []
        },
        {
          "name": "5. Get Version History",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}/versions",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}", "versions"]
            },
            "description": "Get all versions in the offer chain."
          },
          "response": []
        },
        {
          "name": "6. Compare Two Versions",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"compare_with_version\": 1\n}"
            },
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}/compare-versions",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}", "compare-versions"]
            },
            "description": "Compare current offer with another version number."
          },
          "response": []
        },
        {
          "name": "7. Create New Version",
          "request": {
            "method": "POST",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}/create-version",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}", "create-version"]
            },
            "description": "Creates new version when offer is rejected. Original becomes superseded."
          },
          "response": []
        },
        {
          "name": "8. Update Pricing",
          "request": {
            "method": "PUT",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"visit_cost\": 500.00,\n  \"discount_percentage\": 10,\n  \"spare_parts_policy\": \"على حساب العميل\",\n  \"offer_validity_date\": \"2026-03-18\",\n  \"payment_method\": \"تحويل بنكي\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}"]
            }
          },
          "response": []
        },
        {
          "name": "9. Add Additional Cost",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"cost_type\": \"transportation\",\n  \"cost_name\": \"تكاليف النقل\",\n  \"cost_value\": 200.00,\n  \"show_in_offer\": true,\n  \"order\": 1\n}"
            },
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}/costs",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}", "costs"]
            }
          },
          "response": []
        },
        {
          "name": "10. Finalize (Send for Internal Approval)",
          "request": {
            "method": "POST",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}/finalize",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}", "finalize"]
            }
          },
          "response": []
        },
        {
          "name": "11. Internal Approve",
          "request": {
            "method": "POST",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}/approve",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}", "approve"]
            }
          },
          "response": []
        },
        {
          "name": "12. Customer Approve",
          "request": {
            "method": "POST",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}/customer-approve",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}", "customer-approve"]
            }
          },
          "response": []
        },
        {
          "name": "13. Customer Reject",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"reason\": \"السعر مرتفع، نرجو مراجعة العرض\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}/customer-reject",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}", "customer-reject"]
            }
          },
          "response": []
        },
        {
          "name": "14. Create from Technical Offer",
          "request": {
            "method": "POST",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/from-technical-offer/{{technical_offer_id}}",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "from-technical-offer", "{{technical_offer_id}}"]
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Price Offer PDF",
      "description": "Generate and download PDF for price offers",
      "item": [
        {
          "name": "Preview PDF (Stream)",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/pdf" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}/pdf",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}", "pdf"]
            }
          },
          "response": []
        },
        {
          "name": "Download PDF (Attachment)",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/pdf" }],
            "url": {
              "raw": "{{base_url}}/maintenance/price-offers/{{offer_id}}/pdf/download",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "price-offers", "{{offer_id}}", "pdf", "download"]
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Handover Visits",
      "description": "Asset handover/receipt visits - requires receipt approval before scheduling",
      "item": [
        {
          "name": "1. Create Handover Visit",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"project_id\": 1,\n  \"location_id\": null,\n  \"cost_center_id\": null,\n  \"planned_date\": \"2026-03-01\",\n  \"notes\": \"زيارة استلام معدات من العميل\",\n  \"asset_ids\": [1, 2],\n  \"asset_notes\": {\n    \"1\": \"مكيف صالون رئيسي\",\n    \"2\": \"مكيف غرفة الاجتماعات\"\n  }\n}"
            },
            "url": {
              "raw": "{{base_url}}/maintenance/handover-visits",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "handover-visits"]
            }
          },
          "response": []
        },
        {
          "name": "2. Get Pending Handover Visits",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/handover-visits/pending",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "handover-visits", "pending"],
              "query": [
                { "key": "project_id", "value": "", "disabled": true }
              ]
            }
          },
          "response": []
        },
        {
          "name": "3. Get Ready-to-Schedule Visits",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/handover-visits/ready-to-schedule",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "handover-visits", "ready-to-schedule"]
            }
          },
          "response": []
        },
        {
          "name": "4. Check If Can Schedule",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/maintenance/handover-visits/{{visit_id}}/can-schedule",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "handover-visits", "{{visit_id}}", "can-schedule"]
            }
          },
          "response": []
        },
        {
          "name": "5. Schedule Handover Visit",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"scheduled_at\": \"2026-03-05 09:00:00\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/maintenance/handover-visits/{{visit_id}}/schedule",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "handover-visits", "{{visit_id}}", "schedule"]
            },
            "description": "Fails if receipt not approved."
          },
          "response": []
        },
        {
          "name": "6. Complete Handover Visit",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"received_assets\": [\n    { \"asset_id\": 1, \"condition\": \"good\", \"notes\": \"في حالة جيدة\" },\n    { \"asset_id\": 2, \"condition\": \"excellent\", \"notes\": \"جديد تماماً\" }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/maintenance/handover-visits/{{visit_id}}/complete",
              "host": ["{{base_url}}"],
              "path": ["maintenance", "handover-visits", "{{visit_id}}", "complete"]
            },
            "description": "Condition values: excellent | good | fair | poor"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Scheduler Jobs (Info Only)",
      "description": "These are NOT API endpoints. Run via artisan commands.",
      "item": [
        {
          "name": "[CMD] Send Price Offer Reminders",
          "request": {
            "method": "GET",
            "header": [],
            "url": { "raw": "https://placeholder-not-an-endpoint.test", "host": ["placeholder-not-an-endpoint.test"] },
            "description": "NOT an API endpoint.\n\ndocker exec building-app php artisan maintenance:send-price-offer-reminders\n\nSchedule: Daily 9:00 AM\nFinds offers pending_customer_approval for 7+ days, sends max 3 reminders."
          },
          "response": []
        },
        {
          "name": "[CMD] Send Contract Expiry Alerts",
          "request": {
            "method": "GET",
            "header": [],
            "url": { "raw": "https://placeholder-not-an-endpoint.test", "host": ["placeholder-not-an-endpoint.test"] },
            "description": "NOT an API endpoint.\n\ndocker exec building-app php artisan maintenance:send-contract-expiry-alerts\n\nSchedule: Daily 8:00 AM\nAlert intervals: 60, 30, 14, 7, 3, 1 days before expiry."
          },
          "response": []
        }
      ]
    }
  ]
}
