# API Đơn hàng vận chuyển

Base URL: `/orders` | `Content-Type: application/json`

> Tất cả API yêu cầu `JwtTenantAuthGuard` + Permission tương ứng.

---

## 1. Đơn hàng (Orders)

### POST `/orders` — Tạo đơn hàng
**Permission:** `order-create`

```json
{
  "customer_id": 1,
  "sender_name": "Nguyen Van A",
  "sender_phone": "0909000001",
  "sender_province_id": 1,
  "sender_district_id": 1,
  "sender_ward_id": 1,
  "sender_address": "123 Duong Le Loi",
  "receiver_name": "Tran Thi B",
  "receiver_phone": "0909000002",
  "receiver_province_id": 2,
  "receiver_district_id": 2,
  "receiver_ward_id": 2,
  "receiver_address": "456 Duong Nguyen Hue",
  "service_type_id": 1,
  "cod_amount": 0,
  "insurance_opted": 0,
  "payer": "sender",
  "payment_method": "cash",
  "items": [
    {
      "name": "Ao khoac",
      "quantity": 1,
      "weight_gram": 500,
      "length_cm": 30,
      "width_cm": 20,
      "height_cm": 10,
      "declared_value": 200000
    }
  ],
  "note": ""
}
```

Trả về `order_code` + thông tin đơn hàng.

---

### GET `/orders` — Danh sách đơn hàng
**Permission:** `order-index`

**Query params:**
| Param | Type | Description |
|---|---|---|
| `page` | int | Mặc định 1 |
| `limit` | int | Mặc định 10 |
| `search` | string | Tìm kiếm order_code |
| `current_status` | string | Lọc theo trạng thái |

---

### GET `/orders/:id` — Chi tiết đơn hàng
**Permission:** `order-index`

Trả về order + items + fees + statusHistory + serviceType + currentWarehouse + assignedCourier.

---

### GET `/orders/code/:orderCode` — Tra cứu theo mã vận đơn
**Permission:** `order-index`

---

### GET `/orders/:id/timeline` — Lịch sử trạng thái
**Permission:** `order-index`

---

### POST `/orders/:id/cancel` — Hủy đơn hàng
**Permission:** `order-cancel`

Chỉ hủy được khi trạng thái `pending` hoặc `picked_up`.

```json
{ "reason": "Khach hang yeu cau huy" }
```

---

## 2. Vận chuyển (Tracking)

### POST `/orders/:id/pickup` — Xác nhận đã lấy hàng
**Permission:** `order-update-status`

| Field | Type | Description |
|---|---|---|
| `courier_id` | int | Nhân viên lấy hàng |
| `warehouse_id` | int | Kho nhập |

---

### POST `/orders/:id/location` — Cập nhật vị trí
**Permission:** `order-update-status`

```json
{
  "warehouse_id": 1,
  "status": "at_hub",
  "description": "Hang da ve kho"
}
```

Expected status values (state machine):
- `pending` → `picked_up` / `cancelled`
- `picked_up` → `in_transit` / `cancelled`
- `in_transit` → `at_hub`
- `at_hub` → `in_transit` / `out_for_delivery`
- `out_for_delivery` → `delivered` / `failed_delivery`
- `failed_delivery` → `out_for_delivery` / `returned`
- `delivered` / `returned` / `cancelled` — terminal

---

### POST `/orders/:id/assign-courier` — Phân công giao hàng
**Permission:** `order-update-status`

| Field | Type | Description |
|---|---|---|
| `courier_id` | int | Nhân viên giao |

---

## 3. Giao hàng (Delivery)

### POST `/orders/:id/delivery-attempt` — Ghi nhận kết quả giao
**Permission:** `order-update-status`

```json
{
  "courier_id": 1,
  "result": "success",
  "failure_reason": "",
  "note": ""
}
```

`result`: `"success"` | `"failed"`. Tối đa 3 lần thất bại → tự động chuyển `returned`.

---

## 4. COD

### GET `/orders/:id/cod` — Xem COD của đơn hàng
**Permission:** `order-index`

---

### PUT `/orders/cod/:codId/remit` — Nộp tiền COD
**Permission:** `cod-remit`

```json
{ "remit_reference": "" }
```

---

### PUT `/orders/cod/:codId/reconcile` — Đối soát COD
**Permission:** `cod-reconcile`

```json
{ "remit_reference": "REF123" }
```

---

## 5. Hành chính (Administrative Units)

Base URL: `/administrative-units`

### GET `/administrative-units/provinces`
**Permission:** `administrative-unit-index`

Danh sách tỉnh/thành phố (`level = province`, `status = active`).

---

### GET `/administrative-units/:provinceId/districts`
**Permission:** `administrative-unit-index`

Danh sách quận/huyện theo tỉnh (`parent_id`).

---

### GET `/administrative-units/:districtId/wards`
**Permission:** `administrative-unit-index`

Danh sách xã/phường theo huyện (`parent_id`).

---

## Seed data

Chạy seed cho tenant:
```
npm run seed:tenant <tenant_code>
```

Seeder sẽ upsert 63 tỉnh, 710 huyện, ~10835 xã từ `flow/data/province.json`.
