Files
sys-analysis-design/.claude/skills/ba-3-specification/templates/api-contract.md
Leonard-ThindPad-P50 c81f249920 init git
2026-09-08 10:26:21 +07:00

164 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# API — Contract đề xuất — <US-id>
| | |
|---|---|
| **Version** | 1.0 |
| **Date** | YYYY-MM-DD |
| **Author** | <BA> (skill ba-3-specification) |
| **Status** | 🟡 Draft |
| **Nguồn contract** | ⚠️ **BA đề xuất — chờ BE xác nhận** / ✅ BE cung cấp |
| **Approved by** | BE Lead: — |
| **Source** | SRS_… v1.0 |
| **Scope** | US-0nn |
> 🔴 **Đọc dòng `Nguồn contract` trước.** Contract do BA đề xuất là **giả định**, không phải
> sự thật — dev phải đối chiếu với tài liệu BE trước khi code. Contract do BE cung cấp mới
> là ràng buộc.
---
## 1. Ba điểm phải chốt trước tiên
*Ba chỗ này gây bug nhiều nhất và thường không ai hỏi.*
| # | Vấn đề | Quyết định | Lý do |
|---|---|---|---|
| 1 | **Số lớn** (id, số tiền) truyền dạng gì | `string` / `number` | Vượt `2^53` thì JavaScript làm tròn sai ⇒ id 19 chữ số bị hỏng |
| 2 | **Thời gian** định dạng gì, múi giờ nào | ISO-8601 UTC / … | |
| 3 | **Phân trang** kiểu gì | offset (`page`,`size`) / cursor | Có trả `total` không? Có `hasNext` không? |
🔴 Điểm 3: nếu API kiểu offset mà **không trả `hasNext`**, giao diện không biết còn trang sau
hay không — nút "Trang sau" sẽ hỏng. Chốt ngay ở đây.
## 2. Quy ước chung
| | |
|---|---|
| **Base URL** | |
| **Xác thực** | |
| **Định dạng phản hồi** | `{ code, message, data }` / … |
| **Mã HTTP dùng** | 200 · 400 · 401 · 403 · 404 · 409 · 500 |
| **Ngôn ngữ thông điệp** | Trả mã lỗi (FE tự dịch) / Trả text đã dịch theo header |
🔴 **Lỗi nghiệp vụ phải trả mã HTTP 4xx, không phải 200 kèm cờ lỗi trong body.** Trả 200
khiến tầng gọi API coi là thành công và giao diện không hiện lỗi — bug im lặng, rất khó phát hiện.
---
## 3. Endpoint
### 3.1 `GET /api/v1/<resource>` — Lấy danh sách
| | |
|---|---|
| **Mục đích** | |
| **Màn hình** | SCR-01 |
| **Quyền** | ROLE-01 (🔶 chỉ cửa hàng phụ trách), ROLE-02, ROLE-04 |
**Query parameters**
| Tên | Kiểu | Bắt buộc | Mặc định | Ràng buộc | Ghi chú |
|---|---|---|---|---|---|
| `keyword` | string | ❌ | — | ≤ 100 ký tự | Tìm theo mã hoặc tên |
| `status` | enum | ❌ | tất cả | `DRAFT`\|`ACTIVE` | |
| `page` | int | ❌ | 0 | ≥ 0 | **0-based hay 1-based?** ← chốt rõ |
| `size` | int | ❌ | 20 | 1–100 | |
| `sort` | string | ❌ | `code,asc` | | |
**Response 200**
```json
{
"code": "SUCCESS",
"message": null,
"data": {
"items": [
{
"id": "1234567890123456789",
"code": "STR-001",
"name": "…",
"status": "ACTIVE",
"createdAt": "2026-08-30T07:05:00Z"
}
],
"page": { "page": 0, "size": 20, "total": 137, "hasNext": true }
}
}
```
**Từng trường**
| Trường | Kiểu | Có thể null | Nguồn | Ghi chú |
|---|---|---|---|---|
| `id` | string | ❌ | | **String vì là số 19 chữ số** |
| `createdAt` | string | ❌ | | ISO-8601, UTC |
**Response lỗi**
| HTTP | `code` | Khi nào | Mã lỗi SRS |
|---|---|---|---|
| 400 | `INVALID_PARAM` | Tham số sai định dạng | `E-STL-0010` |
| 403 | `FORBIDDEN` | Không đủ quyền | `E-STL-0403` |
---
### 3.2 `POST /api/v1/<resource>` — Tạo mới
**Request body**
```json
{ "code": "STR-001", "name": "…", "typeId": "12345" }
```
| Trường | Kiểu | Bắt buộc | Ràng buộc | Field SRS |
|---|---|---|---|---|
| `code` | string | ✅ | 3–20 ký tự, `^[A-Z0-9-]+$` | F01 |
🔴 **Ràng buộc ở API phải khớp với bảng field trong SRS.** Lệch nhau ⇒ giao diện chặn một
kiểu, backend chặn kiểu khác, người dùng gặp lỗi khó hiểu.
**Response 200 / lỗi**
| HTTP | `code` | Khi nào | Mã lỗi SRS |
|---|---|---|---|
| 409 | `DUPLICATE_CODE` | Mã đã tồn tại | `E-STL-0001` |
---
## 4. Bảng đối chiếu mã lỗi
*Mọi mã lỗi trong SRS §4.1 phải có một dòng ở đây, và ngược lại.*
| Mã lỗi SRS | Endpoint | HTTP | `code` của API | ☐ Khớp |
|---|---|---|---|---|
| `E-STL-0001` | POST /stores | 409 | `DUPLICATE_CODE` | ☐ |
Mã lỗi SRS không có endpoint nào sinh ra ⇒ hoặc lỗi chỉ ở giao diện (ghi rõ), hoặc bị bỏ sót.
## 5. Điểm cần BE xác nhận
*Chỉ dùng khi contract do BA đề xuất.*
| # | Điểm cần chốt | Đề xuất của BA | BE trả lời | Ngày |
|---|---|---|---|---|
| 1 | `id` trả string hay number | string | | |
| 2 | `page` 0-based hay 1-based | 0-based | | |
| 3 | Có trả `hasNext` không | Có | | |
| 4 | Lỗi nghiệp vụ trả 4xx hay 200 | 4xx | | |
## 6. Hành vi khi API lỗi *(giao diện phải làm gì)*
| Tình huống | Giao diện làm gì | AC |
|---|---|---|
| 401 hết phiên | Chuyển về đăng nhập, giữ đường dẫn để quay lại | |
| 403 | Hiện thông báo không đủ quyền, không xoá dữ liệu đã nhập | AC-12 |
| 5xx / timeout | Hiện lỗi, cho thử lại, **giữ nguyên dữ liệu đã nhập** | AC-09 |
| Mạng chậm | Hiện trạng thái đang tải, khoá nút gửi để tránh gửi hai lần | |
🔴 **Khoá nút gửi khi đang xử lý** — không có nó thì người dùng bấm hai lần tạo ra hai bản ghi.
## 7. Open Questions
| ID | Câu hỏi | Hỏi ai | Từ ngày | Chặn gì |
|---|---|---|---|---|