# Sales Bookings API Documentation

APIs for sales users to see their assigned bookings and track read/unread status. All endpoints require **authentication** (`Authorization: Bearer <token>`).

**Base path:** `/api/sales-bookings` (under `auth:sanctum`)

---

## 1. Summary (Dashboard)

**GET** `/api/sales-bookings/summary`

Returns dashboard data: total/unread/read counts, breakdown by payment status and booking status, and recent unread bookings.

**Response**

```json
{
  "success": true,
  "data": {
    "summary": {
      "total": 42,
      "unread": 5,
      "read": 37,
      "by_payment_status": { "pending": 10, "paid": 30, "partial": 2 },
      "by_status": { "pending": 40, "void": 2 }
    },
    "recent_unread": [
      {
        "id": 1,
        "booking_number": "BK2026020001",
        "planned_trip": { "id": 1, "itinerary_code": "...", "departure_date": "...", "package": { "package_name": "..." } },
        "main_contact_traveler": { "chinese_first_name": "...", "chinese_last_name": "...", "contact": { ... } }
      }
    ]
  }
}
```

- `recent_unread`: up to 5 most recent unread bookings with `planned_trip`, `planned_trip.package`, `main_contact_traveler`, `main_contact_traveler.contact`.

---

## 2. Unread Count (Badge)

**GET** `/api/sales-bookings/unread-count`

Lightweight endpoint for notification badge.

**Response**

```json
{
  "success": true,
  "data": {
    "unread_count": 5
  }
}
```

---

## 3. List My Bookings (Paginated)

**GET** `/api/sales-bookings`

List all bookings where the current user is the sales contact (`sales_contact_id`). Each item includes read/unread via `sales_booking_read` (when present).

**Query parameters**

| Parameter       | Type   | Description |
|----------------|--------|-------------|
| `view_mode`    | string | **View mode:** `by_booking` (default) = order by booking created_at (or `sort_by`); `by_trip` = order by planned trip **departure_date** then booking `created_at` (bookings grouped by trip). |
| `is_read`      | 0 \| 1 | Filter: `1` = read only, `0` = unread only |
| `payment_status` | string | Filter by `payment_status` |
| `status`       | string | Filter by booking `status` (comma-separated for multiple) |
| `search`       | string | Search in `booking_number` or main contact name (Chinese/English) |
| `sort_by`      | string | Used when `view_mode=by_booking`. One of: `created_at`, `booking_date`, `booking_number`, `total_amount`, `payment_status`, `planned_trip_id`. Default: `created_at` |
| `sort_dir`     | string | `asc` \| `desc`. Default: `desc`. In `by_trip` mode applies to planned trip departure date. |
| `per_page`     | int    | Items per page. Default: `15` |

**Response**

```json
{
  "success": true,
  "data": {
    "current_page": 1,
    "data": [
      {
        "id": 1,
        "booking_number": "BK2026020001",
        "booking_date": "2026-02-26T00:00:00.000000Z",
        "status": "pending",
        "payment_status": "pending",
        "total_amount": "10000.00",
        "travelers_count": 2,
        "planned_trip": { "id": 1, "itinerary_code": "...", "departure_date": "...", "package": { "package_name": "..." } },
        "sales_booking_read": { "is_read": false, "read_at": null },
        "main_contact_traveler": { "chinese_first_name": "...", "chinese_last_name": "...", "contact": { ... } }
      }
    ],
    "per_page": 15,
    "total": 42
  }
}
```

- If the booking is read, `sales_booking_read` has `is_read: true` and `read_at` (timestamp). If unread, `is_read: false`, `read_at: null`.

---

## 4. Get Booking Detail (Auto-Marks as Read)

**GET** `/api/sales-bookings/{bookingId}`

Returns full booking detail for a booking assigned to the current sales user. **Calling this endpoint marks the booking as read.**

**Response**

```json
{
  "success": true,
  "data": {
    "id": 1,
    "booking_number": "BK2026020001",
    "planned_trip": { ... },
    "sales_contact": { "id": 1, "name": "...", "display_name": "...", "email": "..." },
    "travelers": [ ... ],
    "sales_booking_read": { "is_read": true, "read_at": "2026-02-26T12:00:00.000000Z" }
  }
}
```

- Same booking structure as the main booking detail API (planned_trip, travelers, contact, passport, etc.).  
- **404** if booking not found or not assigned to current user.

---

## 5. Mark One Booking as Read

**PATCH** `/api/sales-bookings/{bookingId}/read`

Marks the given booking as read for the current user.

**Response**

```json
{
  "success": true,
  "message": "已標記為已讀",
  "data": {
    "id": 1,
    "user_id": 1,
    "booking_id": 1,
    "is_read": true,
    "read_at": "2026-02-26T12:00:00.000000Z"
  }
}
```

- **404** if booking not found or not assigned to current user.

---

## 6. Mark One Booking as Unread

**PATCH** `/api/sales-bookings/{bookingId}/unread`

Marks the given booking as unread for the current user.

**Response**

```json
{
  "success": true,
  "message": "已標記為未讀",
  "data": {
    "id": 1,
    "user_id": 1,
    "booking_id": 1,
    "is_read": false,
    "read_at": null
  }
}
```

- **404** if booking not found or not assigned to current user.

---

## 7. Mark All as Read

**PATCH** `/api/sales-bookings/all/read`

Marks all unread bookings (for the current sales user) as read.

**Response**

```json
{
  "success": true,
  "message": "已將 5 筆訂單標記為已讀",
  "data": {
    "updated_count": 5
  }
}
```

---

## 8. Batch Mark as Read

**PATCH** `/api/sales-bookings/batch/read`

Marks multiple bookings as read. Only bookings assigned to the current user are updated.

**Request body (JSON)**

```json
{
  "booking_ids": [1, 2, 3]
}
```

| Field         | Type    | Required | Description |
|---------------|---------|----------|-------------|
| `booking_ids`| array of int | Yes | Booking IDs; must exist in `bookings` table. |

**Response**

```json
{
  "success": true,
  "message": "已將 3 筆訂單標記為已讀",
  "data": {
    "updated_count": 3
  }
}
```

- Validation error (422) if `booking_ids` is missing, not an array, or contains non-existent IDs.

---

## Quick Reference

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/sales-bookings/summary` | Dashboard summary + recent unread |
| GET | `/api/sales-bookings/unread-count` | Unread count for badge |
| GET | `/api/sales-bookings` | List my bookings (paginated, filterable) |
| GET | `/api/sales-bookings/{bookingId}` | Booking detail (marks as read) |
| PATCH | `/api/sales-bookings/{bookingId}/read` | Mark one as read |
| PATCH | `/api/sales-bookings/{bookingId}/unread` | Mark one as unread |
| PATCH | `/api/sales-bookings/all/read` | Mark all as read |
| PATCH | `/api/sales-bookings/batch/read` | Batch mark as read (body: `{ "booking_ids": [1,2,3] }`) |

All routes require **Bearer token** (Sanctum). User must be the sales contact for the booking to access it.
