# Module `tuition` — Học phí & công nợ

> 07/7/2026 · Giai đoạn: **MVP** · Bản HTML: [tuition.html](tuition.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: **chưa có — scaffold mới** (đã chốt tách module riêng, [review §3](../giai-doan-1-mvp/review-module-split-2026-07-06.md)).
> Schema chi tiết: [§2.4](../giai-doan-1-mvp/schema-du-lieu-2026-07-06.md)

## 1. Vai trò
Quản lý **học phí theo đợt** (thực tế học viên đóng nhiều lần): bảng giá, công nợ, phiếu thu, miễn giảm. v1.5 mở rộng thành kế toán đầy đủ + HĐĐT (module `finance`) — tuition giữ phần gắn với hồ sơ học viên.

## 2. Feature / BO / Action

| Feature | BO chính | Action |
|---|---|---|
| `pricelist` | Bảng học phí theo hạng/khóa | view·create·edit·**approve** |
| `installment` | Công nợ theo đợt | view·create·edit·export |
| `receipt` | Phiếu thu | view·create·**collect**·**refund**·**reprint** |
| `discount` | Miễn giảm | view·create·**approve** |

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

### Bảng học phí (`pricelist`)
| Trường | Kiểu | Ghi chú |
|---|---|---|
| Hạng / khóa áp dụng | ref | giá theo hạng, override theo khóa |
| Mức phí chuẩn | money | |
| Cơ cấu đợt mặc định | jsonb | vd 50% – 30% – 20%, mốc theo trạng thái hồ sơ |
| Hiệu lực từ | date | version giá |

### Công nợ đợt (`installment`) — *bảng `tuition_hoc_phi_dot`*
| Trường | Kiểu | Ghi chú |
|---|---|---|
| Học viên | khóa nghiệp vụ | `(ma_dk, ma_kh, ma_csdt)` — không FK cứng |
| Đợt (1,2,3…) | number | UNIQUE theo học viên+đợt |
| Số tiền phải đóng / đã đóng | money | |
| Hạn đóng / ngày đóng | date | |
| Trạng thái | enum | chưa đóng / đóng một phần / đã đóng |
| Số hóa đơn | text | liên kết HĐĐT (finance v1.5) |

### Phiếu thu (`receipt`)
Số phiếu (quy tắc mã catalog), học viên, đợt, số tiền, hình thức (tiền mặt/CK), người thu, ngày, trạng thái (thu/hoàn).

### Miễn giảm (`discount`)
Học viên, lý do, số tiền/%, người duyệt — điều chỉnh vào công nợ đợt.

## 4. Quy tắc nghiệp vụ
1. Tạo hồ sơ → sinh **kế hoạch đợt** từ cơ cấu mặc định của bảng giá (sửa được theo thỏa thuận).
2. Thu đủ đợt 1 → **callback sang student** đổi trạng thái hồ sơ `da_thu_dot1`.
3. Phiếu thu đã in **không sửa** — sai thì lập phiếu hoàn + phiếu mới (audit).
4. Miễn giảm bắt buộc có người duyệt (`approve`) — không trừ tay vào công nợ.
5. Data scope: kế toán thấy hồ sơ từ `hop_le` trở đi; học viên thấy công nợ của mình (app).

## 5. Liên kết chéo module
| Module | Khóa | Ghi chú |
|---|---|---|
| student | `(ma_dk, ma_kh, ma_csdt)` | công nợ theo hồ sơ; callback trạng thái |
| catalog | quy tắc mã phiếu, hạng | |
| finance (v1.5) | số hóa đơn | xuất HĐĐT, sổ thu chi |
| payment (v2) | phiếu thu | thanh toán online đổ về |
| portal (v1.5) | công nợ | học viên tra cứu trên app |

## 6. Câu hỏi mở
- Vĩnh An thu mấy đợt, mốc gắn trạng thái nào (việc khảo sát)?
- Có thu hộ lệ phí sát hạch/khám SK không → thêm loại khoản thu?

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

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

```json
[
  {
    "group": "main",
    "feature": "pricelist",
    "label": "Bảng học phí",
    "actions": [
      "view",
      "create",
      "edit",
      "approve"
    ]
  },
  {
    "group": "main",
    "feature": "installment",
    "label": "Công nợ đợt",
    "actions": [
      "view",
      "create",
      "edit",
      "export"
    ]
  },
  {
    "group": "main",
    "feature": "receipt",
    "label": "Phiếu thu",
    "actions": [
      "view",
      "create",
      "collect",
      "refund",
      "reprint"
    ]
  },
  {
    "group": "main",
    "feature": "discount",
    "label": "Miễn giảm",
    "actions": [
      "view",
      "create",
      "approve"
    ]
  }
]
```

> ⚠️ Action đặc thù (`collect`, `refund`, `reprint`) cần bổ sung vào validator manifest — xem [plan data-scope P1](../giai-doan-1-mvp/plan-data-scope-2026-07-06.md).

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

| Feature | `QTHT` | `GIAM_DOC` | `KE_TOAN` | `QL_DAO_TAO` | `TUYEN_SINH` | `HOC_VIEN` |
|---|:--:|:--:|:--:|:--:|:--:|:--:|
| `pricelist` | R | R·A | W | R | R | — |
| `installment` | R | R | W | R | R | R² |
| `receipt` | R | R | W | — | — | — |
| `discount` | R | R·A | W | — | — | — |

> **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 đủ: `tuition.main.<feature>.<action>`.
> Đặc thù: receipt +collect,refund,reprint (KE_TOAN — in lại phiếu có log)

### 7.3 Quyền mức record (row-level)

**(a) Manifest — bổ sung `fields` + `scopeVars` vào các feature bị scope** *(mở rộng schema theo [plan data-scope P1](../giai-doan-1-mvp/plan-data-scope-2026-07-06.md) — manifest chỉ khai "cái gì scope được", KHÔNG chứa rule)*:

```json
[
  {
    "group": "main",
    "feature": "installment",
    "fields": [
      "ma_dk",
      "ma_kh",
      "ma_csdt"
    ],
    "scopeVars": [
      "current_ma_dk_list"
    ]
  }
]
```

**(b) Điều kiện record theo vai trò:**

| Vai trò | Feature (action) | Điều kiện record |
|---|---|---|
| `HOC_VIEN` | installment (view) | ma_dk ∈ ctx.current_ma_dk_list |

**(c) Seed `rt_role.grants` (kind `rule` — nhiều rule cùng resource+action = OR):**

```json
[
  {
    "kind": "rule",
    "module": "tuition",
    "feature": "installment",
    "actions": [
      "view"
    ],
    "predicate": {
      "op": "in",
      "field": "ma_dk",
      "values": [
        {
          "ctx": "current_ma_dk_list"
        }
      ]
    }
  }
]
```

> Biến ngữ cảnh: `current_user_id` — engine có sẵn · `current_giao_vien_id`/`current_ma_gv` — module teacher tra từ user đăng nhập (ctxVars, plan P3) · `current_nguoi_lxid`/`current_ma_dk_list` — module student tra (1 người nhiều lượt đăng ký) · `current_assigned_*` — danh sách phụ trách/được phân công.
> Scope ³ của KE_TOAN (từ trạng thái hợp lệ) enforce ở `student.hoso` — tuition đọc công nợ theo hồ sơ đã lọc.
