# Module `catalog` — Danh mục dùng chung

> 07/7/2026 · Giai đoạn: **MVP** · Bản HTML: [catalog.html](catalog.html) · Sơ đồ tổng thể: [../so-do-ws-module-feature-2026-07-06.md](../so-do-ws-module-feature-2026-07-06.md)
> Trạng thái code: **đã scaffold** (4 danh mục) — cần bổ sung loại giấy tờ + checklist + quy tắc mã.

## 1. Vai trò
Kho **danh mục quy định** (regulation-as-config) cho mọi module khác — km/giờ theo hạng, checklist giấy tờ, bộ mã. Mục tiêu: **thông tư đổi → sửa dữ liệu danh mục trong vài ngày, không sửa code**. Mọi module đều `depends` catalog.

## 2. Feature / BO / Action

| Feature | BO chính | Action |
|---|---|---|
| `license` | Hạng GPLX | view·create·edit·delete·import |
| `training-category` | Hạng đào tạo | view·create·edit·delete |
| `doc-type` | Loại giấy tờ + Checklist theo hạng | view·create·edit·delete·configure |
| `edu-level` | Trình độ học vấn | view·create·edit·delete |
| `subject` | Môn học | view·create·edit·delete |
| `code-rule` | Quy tắc sinh mã (học viên/khóa/phiếu) | view·configure |

## 3. Dữ liệu chính

### Hạng GPLX (`license`) — *đã có, cần thêm cột quy định đào tạo*
| Trường | Kiểu | Bắt buộc | Ghi chú |
|---|---|---|---|
| Mã hạng | text | ✔ | B, C1, C, D1, D2, A1, A2… (đã seed theo quy định mới) |
| Tên hạng / mô tả | text | ✔ | |
| Hạn sử dụng (năm) | number | | |
| Tuổi tối thiểu | number | ✔* | *bổ sung — phục vụ validate hồ sơ |
| Km thực hành tối thiểu | number | ✔* | *bổ sung — phục vụ đối soát DAT |
| Giờ thực hành tối thiểu | number | ✔* | *bổ sung |
| Hiệu lực từ | date | ✔* | *bổ sung — version theo thông tư |
| Trạng thái | bool | ✔ | |

### Loại giấy tờ + Checklist (`doc-type`) — *mới*
| Trường | Kiểu | Bắt buộc | Ghi chú |
|---|---|---|---|
| Mã / tên loại giấy tờ | text | ✔ | đơn ĐK, CCCD, khám SK, ảnh thẻ, GPLX cũ… |
| Có hạn sử dụng | bool | ✔ | giấy khám SK có hạn |
| Checklist: hạng × giấy tờ | ref×ref | ✔ | kèm `áp dụng` (mới/nâng hạng/cả hai) + `bắt buộc` |

### Quy tắc sinh mã (`code-rule`) — *mới*
| Trường | Kiểu | Ghi chú |
|---|---|---|
| Đối tượng | enum | học viên / khóa / phiếu thu / báo cáo |
| Mẫu mã | text | vd `HV-{ma_csdt}-{YYYY}-{seq5}` — giữ tương thích mã cũ khi migrate |

## 4. Quy tắc nghiệp vụ
1. Danh mục có **hiệu lực theo thời gian** — bản ghi mới không ghi đè bản cũ (hồ sơ cũ vẫn tham chiếu đúng quy định tại thời điểm của nó).
2. Không cho xóa cứng danh mục đã được tham chiếu — chỉ ngừng hiệu lực.
3. Checklist giấy tờ là nguồn duy nhất cho màn hình tiếp nhận hồ sơ (student) — thiếu mục nào cảnh báo đúng mục đó.

## 5. Liên kết chéo module
Mọi module tham chiếu bằng **mã danh mục** (`ma_hang`, mã loại giấy tờ…) — không FK cứng. Người dùng chính: giáo vụ trưởng cấu hình; các module khác chỉ đọc.

## 6. Câu hỏi mở
- Bộ mã học viên/khóa Vĩnh An đang dùng quy tắc gì (việc #2)?
- Bộ giấy tờ chính xác theo NĐ 94/2026 + TT 17/2026-BXD → seed checklist.

## 7. Ma trận phân quyền (→ manifest & seed role)

### 7.1 Khai báo `permissions[]` trong `manifest.json`

```json
[
  {
    "group": "main",
    "feature": "license",
    "label": "Hạng GPLX",
    "actions": [
      "view",
      "create",
      "edit",
      "delete",
      "import"
    ]
  },
  {
    "group": "main",
    "feature": "training-category",
    "label": "Hạng đào tạo",
    "actions": [
      "view",
      "create",
      "edit",
      "delete"
    ]
  },
  {
    "group": "main",
    "feature": "doc-type",
    "label": "Loại giấy tờ & checklist",
    "actions": [
      "view",
      "create",
      "edit",
      "delete",
      "configure"
    ]
  },
  {
    "group": "main",
    "feature": "edu-level",
    "label": "Trình độ học vấn",
    "actions": [
      "view",
      "create",
      "edit",
      "delete"
    ]
  },
  {
    "group": "main",
    "feature": "subject",
    "label": "Môn học",
    "actions": [
      "view",
      "create",
      "edit",
      "delete"
    ]
  },
  {
    "group": "main",
    "feature": "code-rule",
    "label": "Quy tắc sinh mã",
    "actions": [
      "view",
      "configure"
    ]
  }
]
```


### 7.2 Ma trận vai trò × feature (seed `rt_role`)

| Feature | `QTHT` | `GIAM_DOC` | `QL_DAO_TAO` | `GIAO_VU` | `TUYEN_SINH` |
|---|:--:|:--:|:--:|:--:|:--:|
| `license` | W | R | W | R | R |
| `training-category` | W | R | W | R | R |
| `doc-type` | W | R | W | R | R |
| `edu-level` | W | R | R | R | R |
| `subject` | W | R | R | R | R |
| `code-rule` | W | R | R | — | — |

> **R** xem · **W** tạo/sửa · **A** duyệt · **—** không có quyền · ¹ dữ liệu **phân công** · ² **của chính mình** · ³ **theo trạng thái** hồ sơ. Vai trò không liệt kê = không có quyền. Permission key đầy đủ: `catalog.main.<feature>.<action>`.
> W của QTHT gồm cả delete·import·configure
