Hệ thống học vụ song ngữ Việt–Anh: đăng ký học phần, quản lý điểm, điểm danh, đồ án–khóa luận, truyền thông học vụ và trợ lý AI có nguồn tham chiếu.
Tiếng Việt · English · Tài liệu kỹ thuật đầy đủ · Bộ ảnh/GIF hiện tại
CampusCore là tên dự án/codebase; giao diện hiện dùng nhận diện CampusUTE. Backend là Spring Boot modular monolith, được tổ chức theo miền nghiệp vụ, cùng Next.js Web Portal và PostgreSQL/Flyway. RAG chạy trong một sidecar nội bộ. Expo mobile là client đang phát triển, dùng chung API Java.
- Tổng quan và vai trò
- Ảnh giao diện và GIF
- Kỹ thuật toàn dự án
- Kiến trúc
- Công nghệ
- Chạy local
- Tài khoản demo
- Kiểm thử và ranh giới bằng chứng
- Tài liệu liên quan
| Vai trò | Công việc chính | Ranh giới |
|---|---|---|
| Sinh viên | Đăng ký/rút môn, CTĐT, lịch, điểm, phúc khảo, điểm danh, rèn luyện, nhóm khóa luận | Hồ sơ của mình và tài nguyên được cấp quyền |
| Giảng viên | Lịch dạy, roster, điểm, điểm danh, thông báo/email, đề xuất–hướng dẫn–chấm khóa luận | Lớp/đề tài/phân công thực tế |
| Trưởng bộ môn / Trưởng khoa | Thẩm định và điều hành học thuật, xem tiến độ/khối lượng | Bộ môn/khoa và phân công chuyên môn hợp lệ |
| Admin / Super Admin | Tài khoản, danh mục, lớp, đợt, phúc khảo, audit, tri thức RAG | Authority quản trị và chốt nghiệp vụ tương ứng |
Tài khoản do Phòng Đào tạo cấp phát; không có tự đăng ký công khai. Giao diện login hiện có tab Sinh viên, Giảng viên, Trưởng khoa; đường vào quản trị được xử lý theo role/deep link. Quyền trên menu không thay thế kiểm tra ở service và database.
Bộ ảnh chụp từ build local theo source hiện tại, với PostgreSQL/demo riêng, không dùng dữ liệu production. Mỗi vai trò đăng nhập thật và kiểm danh tính qua API. Nguồn chụp, toàn bộ ảnh và giới hạn · Manifest runtime.
| Trang chủ Việt | Trang chủ Anh |
|---|---|
![]() |
![]() |
| Cổng đăng nhập hiện tại | Hướng dẫn khôi phục tài khoản |
|---|---|
![]() |
![]() |
| Tổng quan | Đăng ký và kế hoạch CTĐT |
|---|---|
![]() |
![]() |
| Thời khóa biểu | Bảng điểm tích lũy |
|---|---|
![]() |
![]() |
| Điểm danh | Đồ án – khóa luận |
|---|---|
![]() |
![]() |
| Điểm rèn luyện | Trợ lý chuyên sâu, trả lời từ corpus kỹ thuật |
|---|---|
![]() |
![]() |
| Điểm học phần | Email học vụ |
|---|---|
![]() |
![]() |
| Khóa luận giảng viên | Tổng quan trưởng khoa |
|---|---|
![]() |
![]() |
| Tài khoản và vai trò | Đợt đồ án – khóa luận |
|---|---|
![]() |
![]() |
| Đăng ký mặc định theo CTĐT | Tri thức có kiểm duyệt |
|---|---|
![]() |
![]() |
GIF là chuỗi màn hình thật, mỗi màn hình giữ khoảng 4 giây; không phải video thao tác liên tục và không chứng minh các mutation đã được thực hiện.
Sinh viên: tổng quan → đăng ký → lịch → bảng điểm → khóa luận → trợ lý.
Giảng viên và quản trị: điểm → điểm danh → email → tổng quan quản trị → tri thức.
Quản trị khóa luận: sinh viên → giảng viên → trưởng khoa → quản lý đợt → audit.
Song ngữ: đối chiếu trang chủ, dashboard sinh viên và trưởng khoa Việt/Anh.
Bộ tài liệu kỹ thuật Việt / English technical guide giải thích 42 chủ đề với bài toán, luồng, invariant, lỗi, đánh đổi và nguồn mã/kiểm thử.
| Nhóm kỹ thuật | Điểm chính | Chi tiết |
|---|---|---|
| Kiến trúc và frontend | Modular monolith, service–repository, JDBC/JPA có giới hạn; Next BFF bảo toàn cookie/SSE, chống traversal; React Query theo danh tính; locale/ngày dân sự | T01–T05 |
| Bảo mật và phiên | JWT access/refresh riêng; kiểm authority hiện tại/credential revision; CSRF; 2FA; single-flight, Web Locks, rotation overlap; RBAC + scope; rate limit | T06–T10 |
| Đăng ký và CTĐT | Khóa Student/Section, tăng sĩ số có điều kiện, unique index, idempotency/hash; tiên quyết/lịch/tín chỉ; batch dry-run/apply và cursor; rút môn W | T11–T14 |
| Điểm và hoạt động học tập | Nháp/công bố, điểm 50/50, GPA best attempt; phúc khảo có deadline/audit; điểm danh theo ngày và cảnh báo chính xác; rèn luyện; CSV/PDF/iCalendar | T15–T18 |
| Đồ án – khóa luận | Facade giữ transaction khi tách service; state machine theo loại đợt; khoa/bộ môn; điều kiện học thuật; nhóm/ngoại lệ; file rollback; GVPB; hội đồng; preview/công bố | T19–T26 |
| AI và tri thức | Weighted lexical RAG, difficulty routing, corpus scope, context cá nhân; SSE/heartbeat/cancel; quota/lease/CAS; RLS; kiểm duyệt hai người và guards | T27–T32 |
| Truyền thông | TinyMCE self-host + sanitizer hai tầng; audience/version/lịch thông báo; deep link an toàn; audit; email scoped recipients và DTO/client validation | T33–T34 |
| Mobile và vận hành | Expo Bearer/refresh; Flyway; storage local/database/Supabase; Docker nhiều stage; readiness/timeout; backup/restore; CI/image identity; kiểm thử và tái tạo media | T35–T42 |
Các chốt quan trọng: khóa dòng tuần tự hóa truy cập vào bản ghi cạnh tranh, không tự bảo đảm toàn bộ transaction serializable; RAG lexical có trọng số, không phải BM25/vector search; cảnh báo điểm danh mang tính tư vấn; quota tính theo nhánh dispatch, không phải mọi lần bấm gửi; metadata báo cáo không chứng minh file còn tồn tại.
flowchart TD
subgraph CLIENT["Máy khách"]
WEB["Web Next.js 15<br/>Cookie HttpOnly · CSRF · Việt/Anh"]
MOB["Mobile Expo / React Native<br/>Bearer JWT · đang phát triển"]
end
subgraph APP["Ứng dụng"]
API["Java REST API · Spring Boot 4.1<br/>modular monolith · RBAC + scope<br/>transaction ở tầng service"]
RAG["RAG sidecar nội bộ :4011<br/>cùng artifact Java · không publish ra host"]
end
subgraph DATA["Dữ liệu và tích hợp"]
PG[("PostgreSQL 15<br/>Flyway · constraint · RLS")]
STO["Lưu trữ báo cáo<br/>local · database · Supabase"]
SMTP["SMTP<br/>tùy chọn"]
DS["DeepSeek<br/>tùy chọn · timeout và fallback"]
end
WEB -->|"cùng origin /api/v1"| API
MOB -->|"/api/v1 · Bearer"| API
API --> PG
API --> STO
API -->|"token dịch vụ"| RAG
RAG --> PG
API -.->|"MAIL_ENABLED"| SMTP
RAG -.->|"DEEPSEEK_ENABLED"| DS
Cổng host, cờ tích hợp và thứ tự khởi động thuộc Compose; sơ đồ chỉ thể hiện ranh giới runtime.
sequenceDiagram
participant SV as Sinh viên
participant Web as Next.js
participant API as RegistrationService
participant DB as PostgreSQL
SV->>Web: Chọn lớp học phần
Web->>API: POST /api/v1/me/enrollments (Idempotency-Key)
API->>DB: BEGIN, giữ khóa theo chủ + hash payload
alt Yêu cầu trùng đã hoàn tất
DB-->>API: Bản đăng ký hiện có
API-->>Web: Trả lại kết quả cũ
else Yêu cầu mới
API->>DB: Khóa Student, rồi Section
API->>DB: Kiểm tra đợt, khóa học, tiên quyết, tín chỉ, lịch học
API->>DB: Tăng sĩ số có điều kiện khi lớp còn mở và chưa đầy
alt Lớp đầy hoặc vi phạm ràng buộc
API->>DB: ROLLBACK
API-->>Web: 409 / lỗi nghiệp vụ có cấu trúc
else Hợp lệ
API->>DB: Ghi enrollment, sự kiện, hoàn tất bản ghi yêu cầu
API->>DB: COMMIT
API-->>Web: 201 Enrollment
end
end
Web-->>SV: Cập nhật lịch và thông báo kết quả
Thứ tự khóa và câu lệnh thuộc RegistrationService; khóa dòng không tự nâng mọi truy vấn lên serializable.
flowchart TD
U["Câu hỏi + ngôn ngữ + phạm vi"] --> G["Guard đầu vào · quyền · phạm vi"]
G --> P{"Cần ngữ cảnh cá nhân<br/>của người hỏi?"}
P -->|Có| C["Dịch vụ học vụ có kiểm quyền"]
P -->|Không| R["Corpus đã công bố<br/>xếp hạng lexical có trọng số"]
R --> D{"Cần tổng hợp và<br/>đã cấu hình nhà cung cấp?"}
D -->|Không| L["Trả lời cục bộ có trích dẫn"]
D -->|Có| Q["Ledger · lease · quota nguyên tử"]
Q --> M["DeepSeek tùy chọn, có timeout"]
M -->|Lỗi| L
M --> O["Guard đầu ra · trích dẫn · chốt trạng thái lượt"]
C --> O
L --> O
O --> S["SSE cho web · JSON cho mobile"]
Bản đồ định hướng, chưa gồm các nhánh hội thoại, ngoài chủ đề và phục hồi. Xếp hạng lexical có trọng số, không phải BM25 hay vector search; guard mẫu không bảo đảm chặn hoàn toàn prompt injection.
stateDiagram-v2
[*] --> DRAFT: Admin A tạo hoặc sửa bản nháp
DRAFT --> PENDING_REVIEW: Admin A gửi duyệt
PENDING_REVIEW --> PUBLISHED: Admin B khác người tạo xuất bản
PENDING_REVIEW --> PENDING_REVIEW: Chính Admin A xuất bản bị chặn 409 KNOWLEDGE_SECOND_REVIEW_REQUIRED
PUBLISHED --> ARCHIVED: Bản mới được xuất bản hoặc tài liệu bị lưu trữ
ARCHIVED --> [*]
Người xuất bản phải khác người tạo; xuất bản kiểm lại nội dung công khai và ghi audit trước khi trợ lý đọc snapshot mới.
flowchart LR
SV["Sinh viên"] --> A1["Hồ sơ của mình<br/>đăng ký · lịch · điểm · điểm danh<br/>khóa luận · trợ lý"]
GV["Giảng viên"] --> A2["Lớp, đề tài, phân công thực tế<br/>điểm · điểm danh · email · hướng dẫn"]
TK["Trưởng bộ môn / Trưởng khoa"] --> A3["Bộ môn / khoa<br/>thẩm định · tiến độ · khối lượng"]
AD["Admin / Super Admin"] --> A4["Tài khoản · danh mục · đợt<br/>phúc khảo · audit · tri thức RAG"]
A1 & A2 & A3 & A4 --> Z["Kiểm tra lại ở service và database"]
Quyền trên menu không thay thế kiểm tra ở service và database; xem mô hình phân quyền.
Chi tiết và ranh giới từng sơ đồ: kiến trúc.
| Tầng | Công nghệ và chủ sở hữu phiên bản |
|---|---|
| Java API | Java 21, Spring Boot 4.1, Spring Security/Validation, JDBC, JPA có giới hạn — Maven |
| Web | Next.js 15, React 18, TypeScript, React Query, Tailwind, Radix, TinyMCE — package.json |
| Dữ liệu | PostgreSQL 15, Flyway, constraint/trigger/index/RLS — database image, migrations |
| Mobile | Expo, React Native, TypeScript — mobile manifest |
| Tích hợp | RAG lexical nội bộ; DeepSeek, SMTP, Supabase storage theo cấu hình — Compose |
| Kiểm thử/vận hành | JUnit/Mockito, PostgreSQL IT, node:test, Playwright, Docker/Compose, GitHub Actions — CI |
Cần Docker/Compose đang hoạt động. Đọc .env.example và runbook demo trước khi chọn cổng, demo account hoặc SMTP.
git clone https://github.com/JasonTM17/Student_Management_UTE.git
cd Student_Management_UTE
Copy-Item .env.example .env
# Chỉnh cấu hình local và secret theo .env.example.
docker compose up -d --build
docker compose ps
curl.exe http://127.0.0.1:4010/api/v1/health/liveness| Dịch vụ | Host mặc định | Biến ghi đè |
|---|---|---|
| Web | 3000 | FRONTEND_HOST_PORT |
| API | 4010 | RESTFUL_API_HOST_PORT |
| PostgreSQL | 5432 | POSTGRES_HOST_PORT |
| Mailpit UI / SMTP | 8025 / 1025 | MAILPIT_UI_HOST_PORT / MAILPIT_SMTP_HOST_PORT |
| RAG | Chỉ nội bộ 4011 | Không publish ra host |
Danh mục migration do node scripts/check-migrations.mjs kiểm tra; phiên bản Node/Java chạy trong CI, phiên bản client được khóa trong các lockfile.
OpenAPI ở /v3/api-docs, Swagger ở /swagger-ui.html trên origin API. Readiness cần X-Health-Key đúng cấu hình. Compose chạy role provisioner trước migration; RAG chạy Flyway, API tắt Flyway. Mailpit có mặt không đồng nghĩa MAIL_ENABLED đã bật. Xem hướng dẫn vận hành cho build, storage và restore.
Chỉ dùng trong môi trường local/đánh giá đã chủ động bật DEMO_ACCOUNTS_ENABLED=true; Compose local opt-in; render.yaml cũng chủ động bật tài khoản demo, gồm admin, theo quyết định chủ sở hữu đã ghi nhận. Kiểm tra phạm vi demo cho từng deployment công khai. DemoAccountGate áp lại chính sách mỗi lần boot; không mở khóa bằng SQL để lách gate.
| Vai trò | Tài khoản seed |
|---|---|
| Sinh viên | student@campuscore.edu, student2@campuscore.edu, student3@campuscore.edu, student4@campuscore.edu |
| Giảng viên | lecturer@campuscore.edu |
| Trưởng khoa | truongkhoa@campuscore.demo |
| Trưởng bộ môn | truongbomon@campuscore.demo |
| Admin / người duyệt tri thức thứ hai | admin@campuscore.edu, admin002@campuscore.demo |
Mật khẩu seed công khai cho demo là password123. Quick-fill còn cần opt-in build và các biến password theo runbook; admin không có password prefill trong client. Các profile chỉ để minh họa có thể bị khóa theo chủ ý; không suy từ danh bạ rằng mọi tài khoản đều đăng nhập được. Email OTP/2FA và khôi phục phụ thuộc SMTP thật được cấu hình.
npm test --prefix frontend
npm run typecheck --prefix frontend
npm test --prefix mobile
mvn -f java-services/pom.xml verify
node scripts/check-doc-hygiene.mjs
git diff --checkPostgreSQL race/RLS suites cần database tạm và cấu hình theo CI. Ma trận bằng chứng phân biệt unit, H2, PostgreSQL, browser và provider thật. Bộ ảnh mới chứng minh render local và các request đã ghi trong manifest; không chứng minh tất cả mutation, độ chịu tải, email giao thành công hoặc production.























