> ## Documentation Index
> Fetch the complete documentation index at: https://tomotek.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Thiết kế Database

## Cấu trúc bảng cốt lõi cho module Quản lý Chip

***

### 1. Bảng `chips` - Chip định danh

> Bảng quan trọng nhất, mỗi dòng tương ứng với 1 chip vật lý duy nhất

| Trường | Kiểu dữ liệu | Mô tả |
| - | - | - |
| `id` | BIGINT | Primary Key |
| `sn` | VARCHAR(50) | Serial Number duy nhất của chip, unique index, không thể sửa đổi |
| `model` | VARCHAR(100) | Model chip (VD: ISO11784 FDX-B) |
| `factory_id` | VARCHAR(100) | Mã định danh theo nhà máy (nếu có) |
| `expiry_date` | DATE | Ngày hết hạn |
| `status` | ENUM | `Available`, `Sending-to-Clinic`, `In-Clinic`, `Activated`, `Returning`, `Returned`, `Problem by TMT`, `Problem by Clinic`, `Problem by Factory` |
| `clinic_id` | BIGINT | NULL nếu chip đang ở kho TMT, Clinic ID nếu chip đang ở Clinic |
| `export_order_id` | BIGINT | ID đơn xuất đang liên kết (nếu có) |
| `pet_id` | BIGINT | ID thú cưng nếu chip đã được kích hoạt |
| `activated_at` | TIMESTAMP | Thời gian kích hoạt |
| `problem_reason` | TEXT | Lý do khi chip vào trạng thái Problem |
| `created_at`, `updated_at` | TIMESTAMP | |
| `created_by` | BIGINT | Người nhập chip vào hệ thống |

**Index:** `(sn) UNIQUE`, `(status)`, `(clinic_id, status)`, `(expiry_date)`

**Quy tắc bất biến:**

* `sn` không bao giờ được thay đổi sau khi tạo
* Không bao giờ xóa dòng trong bảng này, chỉ chuyển trạng thái
* Khi status = `Activated` thì `pet_id` và `activated_at` không bao giờ được thay đổi

***

### 2. Bảng `export_rounds` - Đợt xuất kho

| Trường | Kiểu dữ liệu | Mô tả |
| - | - | - |
| `id` | BIGINT | Primary Key |
| `round_code` | VARCHAR(50) | Mã đợt xuất `EXP-{YYYYMMDD}-{XXXX}` tự động tạo |
| `name` | VARCHAR(255) | Tên đợt xuất (người dùng nhập) |
| `source_type` | ENUM | `manual`, `from_request` |
| `status` | ENUM | `draft`, `scanning`, `completed`, `cancelled` |
| `created_at`, `updated_at` | TIMESTAMP | |
| `created_by` | BIGINT | |

***

### 3. Bảng `export_orders` - Đơn xuất ký gửi theo Clinic

| Trường | Kiểu dữ liệu | Mô tả |
| - | - | - |
| `id` | BIGINT | Primary Key |
| `export_round_id` | BIGINT | Foreign Key tới export\_rounds |
| `clinic_id` | BIGINT | Clinic nhận chip |
| `requested_quantity` | INTEGER | Số lượng yêu cầu |
| `scanned_quantity` | INTEGER | Số lượng đã quét |
| `status` | ENUM | `Pending Scan`, `Scanning`, `Completed`, `Partially Received`, `Fully Received`, `Cancelled` |
| `created_at`, `updated_at` | TIMESTAMP | |

***

### 4. Bảng `chip_requests` - Yêu cầu nhận chip từ Clinic

| Trường | Kiểu dữ liệu | Mô tả |
| - | - | - |
| `id` | BIGINT | Primary Key |
| `clinic_id` | BIGINT | |
| `requested_quantity` | INTEGER | Số lượng yêu cầu |
| `approved_quantity` | INTEGER | Số lượng Admin duyệt |
| `reason` | TEXT | Lý do yêu cầu |
| `expected_date` | DATE | Ngày mong nhận |
| `status` | ENUM | `pending`, `approved`, `rejected`, `in_export_round`, `fulfilled` |
| `export_round_id` | BIGINT | ID đợt xuất đã đưa vào |
| `created_at`, `updated_at` | TIMESTAMP | |

***

### 5. Bảng `chip_status_logs` - Lịch sử trạng thái chip

> Bảng bất biến, chỉ INSERT, không UPDATE, không DELETE

| Trường | Kiểu dữ liệu | Mô tả |
| - | - | - |
| `id` | BIGINT | Primary Key |
| `chip_id` | BIGINT | |
| `from_status` | ENUM | Trạng thái cũ |
| `to_status` | ENUM | Trạng thái mới |
| `reason` | TEXT | Lý do thay đổi trạng thái |
| `reference_type` | VARCHAR(50) | Loại tham chiếu: ExportOrder, Request, Activation |
| `reference_id` | BIGINT | ID tham chiếu |
| `created_by` | BIGINT | Người thực hiện thay đổi |
| `created_at` | TIMESTAMP | |

**Quy tắc bất biến:**

> KHÔNG UPDATE, KHÔNG DELETE, KHÔNG SOFT DELETE. CHỈ CHO PHÉP INSERT.
> Mọi thay đổi trạng thái chip đều phải có 1 dòng tương ứng trong bảng này.

***

## Quy tắc nghiệp vụ Database

* Số lượng chip tồn kho TMT = `COUNT(*) FROM chips WHERE status = 'Available' OR status = 'Returned'`
* Số lượng chip đang gửi = `COUNT(*) FROM chips WHERE status = 'Sending-to-Clinic'`
* Số lượng chip tại Clinic X = `COUNT(*) FROM chips WHERE clinic_id = X AND status = 'In-Clinic'`
* Số lượng chip đã kích hoạt = `COUNT(*) FROM chips WHERE status = 'Activated'`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.