# Project Service Links API Contract

## Overview
This document outlines the API contract for attaching, detaching, listing, and updating the status of Services under a Project.

**Task:** PMS-API-2.2
**Depends on:** PMS-API-2.1, PMS-API-1.2

## General Headers
All requests must include the following headers:
- `Authorization`: `Bearer <token>`
- `X-Company-Id`: `<company_id>`
- `Accept`: `application/json`
- `Content-Type`: `application/json` (For POST/PUT/PATCH requests)

## Base URL
`/api/v1/project/projects/{projectId}/services`

---

## 1. Attach Service to Project

**Endpoint:** `POST /api/v1/project/projects/{projectId}/services`

### Request Body
```json
{
  "service_id": 10,
  "status": "active"
}
```

### Success Response (201 Created)
```json
{
  "success": true,
  "message": "Service attached to project successfully.",
  "data": {
    "id": 501,
    "project_id": 100,
    "service_id": 10,
    "service": { 
      "id": 10, 
      "name": "Digital Marketing", 
      "code": "DM" 
    },
    "status": "active",
    "created_at": "2026-09-14T10:00:00+00:00",
    "updated_at": "2026-09-14T10:00:00+00:00"
  }
}
```

### Validation Error (422 Unprocessable Entity) - Duplicate Attach
```json
{
  "success": false,
  "message": "Validation failed.",
  "errors": {
    "service_id": ["This service is already attached to the project."]
  }
}
```

---

## 2. List Attached Services

**Endpoint:** `GET /api/v1/project/projects/{projectId}/services`

### Query Parameters (Optional)
- `status`: Filter by status (`active` or `inactive`)
- `per_page`: Pagination limit (default 15)
- `page`: Page number

### Success Response (200 OK)
```json
{
  "success": true,
  "message": "Project services retrieved successfully.",
  "data": [
    {
      "id": 501,
      "project_id": 100,
      "service_id": 10,
      "service": { 
        "id": 10, 
        "name": "Digital Marketing", 
        "code": "DM" 
      },
      "status": "active",
      "created_at": "2026-09-14T10:00:00+00:00",
      "updated_at": "2026-09-14T10:00:00+00:00"
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 15,
    "total": 1
  }
}
```

---

## 3. Update Service Link Status

**Endpoint:** `PATCH /api/v1/project/projects/{projectId}/services/{serviceId}`

### Request Body
```json
{
  "status": "inactive"
}
```

### Success Response (200 OK)
```json
{
  "success": true,
  "message": "Project service status updated successfully.",
  "data": {
    "id": 501,
    "project_id": 100,
    "service_id": 10,
    "status": "inactive",
    "updated_at": "2026-09-14T10:05:00+00:00"
  }
}
```

---

## 4. Detach (Remove) Service from Project

**Endpoint:** `DELETE /api/v1/project/projects/{projectId}/services/{serviceId}`

### Success Response (200 OK)
```json
{
  "success": true,
  "message": "Service detached from project successfully.",
  "data": null
}
```

### Error Response (400 Bad Request) - Contract Active
```json
{
  "success": false,
  "message": "Cannot detach service because an active contract references this link.",
  "errors": null
}
```

## Business Rules & Logic
- **BR-02:** Multiple services can be attached per project.
- **Tenant Scope:** Project and service must share the same `company_id`.
- **Uniqueness:** A project and service combination must be unique. Duplicate requests will return a `422` error.
- **Deletion Constraint:** A service link cannot be detached (deleted) if an active or non-cancelled contract references it. (Return 400 Bad Request).
- **Service Status:** It is preferred to attach only active services.
