# API dự án

Liệt kê, tạo, cập nhật, xóa và tìm kiếm dự án kỹ thuật cùng các nguyên công và bước gia công lồng bên trong.

Source: https://support.toolingmetrics.com/vi/api/reference/projects/
Updated: 2026-10-29

Đường dẫn gốc: `/v1/organizations/:organization_id/projects`

## Endpoint

| Phương thức | Đường dẫn | Mô tả |
|---|---|---|
| `GET` | `/projects` | Liệt kê mọi dự án (dạng tóm tắt) |
| `GET` | `/projects/:id` | Lấy một dự án kèm nguyên công và bước gia công |
| `POST` | `/projects` | Tạo dự án |
| `PATCH` | `/projects/:id` | Cập nhật dự án |
| `DELETE` | `/projects/:id` | Xóa dự án |
| `GET` | `/projects/search` | Tìm dự án theo tên |

## Đối tượng dự án (dạng chi tiết)

```json
{
  "id": 8,
  "name": "Cylinder Block Rev2",
  "description": "...",
  "status": "released",
  "multiple_setup": false,
  "created_at": "2025-04-01T08:00:00Z",
  "updated_at": "2025-06-01T10:00:00Z",
  "created_by": { "id": 7, "email": "user@example.com" },
  "jobs": [
    {
      "id": 12,
      "name": "Op 10 — Facing",
      "order": 1,
      "status": "draft",
      "locked": false,
      "machine": { "id": 1, "designation": "DMG-001", "name": "DMG 5-axis" },
      "part": { "id": 5, "number": "P-0042", "description": "Cylinder Block" },
      "operations": [
        { "id": 20, "name": "Face milling" }
      ]
    }
  ]
}
```

## Phản hồi danh sách

Endpoint danh sách `GET /projects` trả về bản tóm tắt gọn — không phải cấu trúc lồng nhau đầy đủ:

```json
[
  { "id": 8, "name": "Cylinder Block Rev2", "status": "released", "locked": false },
  { "id": 9, "name": "Shaft Housing", "status": "draft", "locked": false }
]
```

## Tham số

### Tạo / cập nhật

| Tham số | Kiểu | Mô tả |
|---|---|---|
| `name` | string | Tên dự án |
| `description` | string | Mô tả dự án |
| `status` | string | Một trong các giá trị `draft`, `released`, `approved`, `active`, `archived`. Phê duyệt một dự án đã phát hành sẽ sao chép các sản phẩm của mô hình dụng cụ thành hàng hóa do người tạo dự án tạo, nên người dùng của khóa cũng phải được phép tạo các hàng hóa đó và cập nhật các hàng hóa đã có; nếu không sẽ nhận `401` |
| `multiple_setup` | boolean | Dự án có ghép nhiều lần gá trên máy hay không |
| `picture` | string | Ảnh dự án dạng PNG mã hóa Base64 |
| `jobs_attributes` | array | Các nguyên công lồng bên trong (xem bên dưới) |

Khác với [chi tiết](https://support.toolingmetrics.com/vi/api/reference/parts/) và [máy gia công](https://support.toolingmetrics.com/vi/api/reference/machines/), dự án tự lấy tổ chức từ đoạn đường dẫn `:organization_id` — bạn không cần (và không thể, vì `organization_id` không phải tham số được chấp nhận) truyền lại trong thân yêu cầu. Điều này cũng áp dụng cho từng nguyên công trong `jobs_attributes`.

### Thuộc tính nguyên công (`jobs_attributes`)

| Tham số | Kiểu | Mô tả |
|---|---|---|
| `id` | integer | Bắt buộc khi cập nhật một nguyên công đã có |
| `name` | string | Tên nguyên công |
| `order` | integer | Thứ tự hiển thị |
| `machine_id` | integer | Máy gia công được gán |
| `part_id` | integer | Chi tiết gia công |
| `status` | string | Trạng thái nguyên công |
| `_destroy` | boolean | Truyền `true` để xóa nguyên công |
| `operations_attributes` | array | Các bước gia công lồng bên trong (xem bên dưới) |

### Thuộc tính bước gia công (`operations_attributes`)

| Tham số | Kiểu | Mô tả |
|---|---|---|
| `id` | integer | Bắt buộc khi cập nhật một bước gia công đã có |
| `name` | string | Tên bước gia công |
| `order` | integer | Thứ tự hiển thị trong nguyên công |
| `cycle_time` | integer | Thời gian chu kỳ ước tính. **Phải là số nguyên** — `numericality: only_integer: true` từ chối số thập phân với mã `422` |
| `tool_number` | integer | Số T trong chương trình NC |
| `tool_assembly_id` | integer | Mô hình dụng cụ được gán |
| `_destroy` | boolean | Truyền `true` để xóa bước gia công |

### Bộ lọc danh sách / tìm kiếm

| Tham số | Kiểu | Mô tả |
|---|---|---|
| `status` | string | Lọc theo trạng thái (endpoint danh sách). **Đồng thời ngầm lọc `locked: false`** — truyền `status` sẽ loại các dự án đã khóa dù bạn không yêu cầu bộ lọc đó. Bỏ `status` nếu bạn cần lấy cả dự án đã khóa. |
| `q` | string | Khớp chuỗi con trong tên dự án, không phân biệt chữ hoa chữ thường (endpoint tìm kiếm) |

## Ví dụ

```bash
# Search projects by name
curl "https://api.toolingmetrics.com/v1/organizations/12/projects/search?q=Cylinder" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Get a project with full job and operation detail
curl "https://api.toolingmetrics.com/v1/organizations/12/projects/8" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

```python
import requests

BASE = "https://api.toolingmetrics.com/v1"
HEADERS = {"Authorization": "Bearer YOUR_TOKEN"}

# Create a project with one job and one operation (CAM post-processor integration)
payload = {
    "name": "Cylinder Block Rev2",
    "status": "draft",
    "jobs_attributes": [
        {
            "name": "Op 10 — Facing",
            "order": 1,
            "machine_id": 1,
            "part_id": 5,
            "operations_attributes": [
                {
                    "name": "Face milling",
                    "order": 1,
                    "cycle_time": 750,
                    "tool_number": 1,
                    "tool_assembly_id": 42,
                }
            ],
        }
    ],
}

response = requests.post(
    f"{BASE}/organizations/12/projects",
    headers={**HEADERS, "Content-Type": "application/json"},
    json=payload,
)
response.raise_for_status()
project = response.json()
print(f"Created project #{project['id']}: {project['name']}")
```

## Lỗi thường gặp

| Mã trạng thái | Nguyên nhân |
|---|---|
| `401` | Người dùng của khóa không được phép thực hiện thay đổi đó: ví dụ phê duyệt một dự án đã phát hành khi không có quyền thay đổi các hàng hóa mà việc phê duyệt tạo hoặc cập nhật |
| `404` | Không tìm thấy ID dự án, máy gia công hoặc chi tiết |
| `422` | Thiếu trường bắt buộc hoặc giá trị trạng thái không hợp lệ |
