# RobotInstaller database

Thiết kế này bám theo `database.md` và sơ đồ database hiện có, sau đó bổ sung vài cột cần cho web server:

- `PackageType`: phân biệt package `.deb` và `docker`.
- `AppVersion`: version hiện tại của app đóng gói.
- metadata artifact: `DockerImage`, `FileChecksumSha256`, `FileSizeBytes`, `UploadedAt`.
- `Role`, `IsActive` cho tài khoản đăng nhập web.

## Database

Tên database được chọn: `RobotInstaller`

Server:

```powershell
172.20.235.176
```

Không lưu mật khẩu thật vào file cấu hình. Khi chạy local, tạo file `.env` từ `web-server/.env.example` rồi điền mật khẩu thật.

## Cấu trúc chính

| Bảng | Vai trò |
| --- | --- |
| `dbo.Users` | Người dùng web server |
| `dbo.Packages` | Danh mục package |
| `dbo.PackageVersions` | Các version của từng package |
| `dbo.Applications` | App được đóng gói từ nhiều package |
| `dbo.ApplicationPackages` | Liên kết app-package, có thể chọn version cụ thể |
| `dbo.Documents` | Nội dung tài liệu và metadata file đính kèm |
| `dbo.Notifications` | Thông báo riêng cho từng user và thông báo hệ thống do Admin đăng |

## Ràng buộc quan trọng

- `Users.Username`, `Users.Email` là duy nhất.
- `Packages.PackageCode` là duy nhất.
- `Applications.AppCode` là duy nhất.
- Mỗi package không được trùng `Version`.
- Mỗi app chỉ chứa một dòng cho mỗi package.
- Mỗi package chỉ có tối đa một `IsLatest = 1`.
- `ApplicationPackages.SelectedVersionId` bắt buộc thuộc đúng `PackageId` trên cùng dòng.

## View cho API

| View | Dùng cho màn hình |
| --- | --- |
| `dbo.vw_PackageList` | Danh sách package kèm latest version |
| `dbo.vw_PackageVersionList` | Chi tiết version của package |
| `dbo.vw_ApplicationList` | Danh sách app kèm số package |
| `dbo.vw_ApplicationPackageDetails` | Chi tiết package/version trong app |

## Stored procedure

| Procedure | Mục đích |
| --- | --- |
| `dbo.SetLatestPackageVersion` | Đặt một version là latest và tự clear latest cũ |
| `dbo.DeletePackageVersion` | Xóa version và các liên kết app đang dùng version đó |

## Triển khai bằng sqlcmd

```powershell
$env:SQLCMDPASSWORD = '<mat-khau-sa>'

sqlcmd -S 172.20.235.176 -U sa -b -i .\database\01_create_database.sql
sqlcmd -S 172.20.235.176 -U sa -d RobotInstaller -b -i .\database\02_schema.sql
sqlcmd -S 172.20.235.176 -U sa -d RobotInstaller -b -i .\database\03_views.sql
sqlcmd -S 172.20.235.176 -U sa -d RobotInstaller -b -i .\database\04_notifications.sql
sqlcmd -S 172.20.235.176 -U sa -d RobotInstaller -b -i .\database\05_documents.sql
```

Chạy các lệnh trên từ thư mục `web-server`.

Khi dùng `sqlcmd` để seed/test dữ liệu, thêm `-I` hoặc bật `SET QUOTED_IDENTIFIER ON` vì schema có filtered index cho ràng buộc một latest version trên mỗi package.

`04_notifications.sql` và `05_documents.sql` là các migration chỉ bổ sung bảng/index và có thể chạy lặp lại. Với database đang hoạt động, chỉ chạy các migration còn thiếu; không chạy lại `02_schema.sql` vì script schema gốc chủ động dừng khi phát hiện bảng đã tồn tại. Web server cũng tự bảo đảm bảng `Documents` tồn tại khi chức năng tài liệu được truy cập.

## Luồng dữ liệu đề xuất

1. Upload package mới:
   - nếu package chưa tồn tại, insert vào `Packages`;
   - insert version vào `PackageVersions`;
   - gọi `dbo.SetLatestPackageVersion @PackageVersionId`.

2. Update package:
   - insert thêm một dòng mới vào `PackageVersions`;
   - gọi `dbo.SetLatestPackageVersion @PackageVersionId`.

3. Tạo app:
   - insert vào `Applications`;
   - insert các package được chọn vào `ApplicationPackages`;
   - nếu user chọn version cụ thể, điền `SelectedVersionId`.

4. Xóa package:
   - xóa dòng trong `Packages`;
   - database tự cascade sang `PackageVersions` và `ApplicationPackages`.

5. Xóa version:
   - gọi `dbo.DeletePackageVersion @PackageVersionId` để xóa cả liên kết app đang dùng version đó.
