Skip to content

Quản lý học viên (Students) ​

Student là căn cước "học viên trường" — entity riêng tách khỏi User (tài khoản). Một User có thể là học viên nhiều trường (đa tenant), nhưng trong mỗi tenant, mỗi User có tối đa một Student record với mã học viên + lifecycle riêng.

Một dòng tóm tắt

User = tài khoản đăng nhập; Student = "đã được trường nhận học". Khi attach User vào Batch lần đầu, listener EnsureStudentForBatchMember tự tạo Student record với student_code + status active. Sau đó bạn quản lý lifecycle (admit / graduate / withdraw) qua Học viên trong sidebar.

Khác biệt User vs Student ​

Khía cạnhUser (tài khoản)Student (học viên trường)
Định danhEmailstudent_code (mã do trường cấp)
Phạm viĐăng nhập + truy cập toàn tenantHọc viên thuộc trường
LifecycleActive / suspended / deletedActive / Graduated / Withdrawn
Số bản ghi1 user = 1 row1 user = 0 hoặc 1 student record
Quản lýTenant AdminTraining Manager

Student là rich data, không phải vai trò

Student record là dữ liệu hồ sơ với lifecycle, code, dates — không phải vai trò đăng nhập. Một học viên có cả: tài khoản User (để đăng nhập) + Student record (mã học viên + lifecycle trường).

Vào quản lý Students ​

Sidebar → Đào tạo → Học viên (URL: /admin/students).

Bảng list hiển thị:

CộtMô tả
Mã học viên (student_code)Searchable, sortable, copyable
Họ tênusers.first_name + last_name
Emailusers.email
Trạng tháiActive / Graduated / Withdrawn — badge màu
Lớp đang họcactive_batches_count — số batch_user ở trạng thái active
Ngày nhập họcadmitted_at

Filter: status, soft-deleted records (TrashedFilter).

Mặc định sort theo admitted_at desc — học viên mới nhất lên đầu.

Auto-admit khi attach Batch ​

Listener EnsureStudentForBatchMember chạy mỗi khi event UserJoinedBatch dispatch:

  1. User được attach vào một Batch (qua BatchResource Users tab, import CSV, hoặc tạo trực tiếp).
  2. Hệ thống kiểm tra: User đã có Student record chưa?
  3. Chưa → tạo mới với:
    • user_id = User
    • student_code = auto-generate theo pattern (xem Student code)
    • status = active
    • admitted_at = now()
  4. Đã có → giữ nguyên (idempotent).

→ Bạn không cần tạo Student thủ công cho cohort B2B import — chỉ cần attach vào Batch là đủ.

Tạo Student thủ công ​

Trường hợp cần tạo Student không qua Batch (vd: học viên đã đăng ký nhưng chưa vào lớp):

  1. Click Tạo mới trong Học viên.
  2. Form:
    • Tài khoản (user_id) — chọn User đã có (autocomplete email/tên). User chưa có → đề nghị Tenant Admin tạo trước qua User Management.
    • Mã học viên (student_code) — để trống để auto-generate, hoặc nhập tay (unique).
    • Trạng thái (status) — mặc định Active.
    • Ngày nhập học (admitted_at) — mặc định hôm nay.
    • Ngày tốt nghiệp / Ngày thôi học (tuỳ chọn — set khi cần).
    • Ghi chú (text — note nội bộ ngắn gọn).
    • Section Thông tin cá nhân (tuỳ chọn) — xem Thông tin cá nhân bên dưới.
  3. Click Lưu.

Thông tin cá nhân ​

Form học viên có section Thông tin cá nhân:

TrườngRàng buộc
Ngày sinhKhông quá hôm nay
Số CCCD12 chữ số (hoặc CMND cũ 9 chữ số)
Ngày cấp CCCDKhông trước ngày sinh, không quá hôm nay
Địa chỉTự do

Ai thấy số CCCD?

Số CCCD và Ngày cấp CCCD chỉ hiện cho người có quyền sửa hồ sơ học viên (Quản lý đào tạo, Tenant Admin). Giảng viên xem hồ sơ trong Trainer Panel hay trong cửa sổ xem nhanh ở trang lớp không thấy hai trường này; ngày sinh và địa chỉ thì vẫn thấy. Quy tắc này áp cả cho file xuất danh sách.

UNIQUE constraint

  • user_id UNIQUE trong students — một User chỉ có một Student record. Lỗi khi cố tạo duplicate.
  • student_code UNIQUE — mã học viên không trùng. Lỗi nếu nhập trùng.
  • Trường user_id không sửa được sau khi tạo (tránh phá liên kết).

Student code ​

student_code là định danh trường cấp cho học viên — hiển thị trên hồ sơ, certificate (nếu cấu hình), báo cáo gửi B2B.

Auto-generate pattern ​

Khi để trống ở form, hệ thống generate theo pattern cấu hình với atomic counter:

  • Mặc định: CGA{seq:4} → CGA0001, CGA0002, ...
  • Cấu hình ở Cài đặt → Chung → tab Mã học viên (Tenant Admin, quyền configure_student_code).
  • Counter atomic per-tenant — không trùng dù nhiều admin tạo cùng lúc.

Token dùng được trong mẫu:

TokenNghĩaVí dụ (tháng 5/2026, số thứ tự 1)
{YYYY}Năm 4 chữ số2026
{YY}Năm 2 chữ số26
{MM}Tháng 2 chữ số05
{seq:N}Số thứ tự, đệm 0 cho đủ N chữ số{seq:4} → 0001

Token không nhận ra được giữ nguyên nguyên văn. Ví dụ: SA{MM}{YY}{seq:3} → SA0526001.

Ghi đè thủ công ​

Nhập student_code tuỳ ý khi tạo / edit — vd: tổ chức có sẵn mã 2026-MARKETING-001. Validation:

  • UNIQUE check trong tenant.
  • Max 64 ký tự.
  • Cho phép số, chữ, dấu gạch.

Khi nào nên ghi đè?

  • Migration từ hệ thống cũ — giữ mã cũ để học viên không bị lạ.
  • Cohort doanh nghiệp với mã của khách hàng — vd: ACME-2026-CTO.
  • Pattern khác mặc định — vd: theo lớp K12-CN-001.

Lifecycle: Admit → Graduate / Withdraw ​

Status enum StudentStatus:

StatusKhi nàoKèm field
ActiveMặc định khi tạoadmitted_at
GraduatedĐánh dấu tốt nghiệpgraduated_at
WithdrawnĐánh dấu thôi họcwithdrawn_at

Học viên ở status Graduated / Withdrawn không xuất hiện ở danh sách lớp đang học (filter UI).

Action: Tốt nghiệp (Graduate) ​

Action chỉ hiện khi student Active.

  1. Trong bảng list → row → Tốt nghiệp.
  2. Modal:
    • Ngày tốt nghiệp (mặc định hôm nay).
  3. Confirm.
  4. Hệ thống:
    • status = Graduated
    • graduated_at = ngày bạn chọn.
    • Không tự động đóng các BatchEnrollment đang active. Bạn có thể tách bằng cách Complete enrollment trước hoặc để hệ thống tự auto-complete khi Batch chuyển sang Completed.

Action: Cho thôi học (Withdraw) ​

  1. Action Cho thôi học → modal xác nhận:
    • Ngày thôi học (mặc định hôm nay).
  2. Confirm.
  3. status = Withdrawn, withdrawn_at = ngày chọn.
  4. Không tự huỷ BatchEnrollment. Cần Drop từng BatchEnrollment thủ công nếu muốn (qua tab Lớp học của student hoặc qua Batch).

Withdraw ≠ Drop khỏi lớp

Withdraw là school-level (rời trường). Drop là batch-level (rời một lớp). Học viên có thể:

  • Drop khỏi lớp A nhưng vẫn Active ở trường (vì còn lớp B).
  • Withdraw khỏi trường nhưng không tự động Drop lớp đang học.

Quy ước thực tế: thường khi Withdraw, bạn cũng Drop tất cả lớp active của họ. Workflow đề xuất: Withdraw → mở tab Ghi danh → Drop từng BatchEnrollment.

Action: Khôi phục (Reactivate) ​

Action chỉ hiện khi status là Graduated hoặc Withdrawn:

  1. Click Khôi phục → modal confirm.
  2. status = Active, clear graduated_at / withdrawn_at.

Hữu ích khi:

  • Quay lại học sau thời gian gián đoạn.
  • Nhầm tốt nghiệp / thôi học (bấm sai).

Bulk actions ​

Bảng list hỗ trợ:

  • Tốt nghiệp đã chọn (bulk) — tick nhiều rows → bulk graduate với cùng graduated_at.
  • Cho thôi học đã chọn — tương tự cho withdraw.

Cuối cohort

Khi cohort kết thúc + tất cả học viên pass:

  1. Bulk graduate học viên cohort đó.
  2. Optionally — Complete BatchEnrollment riêng từng người.
  3. Chuyển Batch → status Completed (auto-complete remaining enrollments).

Hồ sơ chi tiết Student ​

Click vào dòng → trang Xem (/admin/students/{id}).

Hồ sơ Student vs Hồ sơ học tập 360°

Trang này là hồ sơ học viên của trung tâm — mã, lifecycle, điểm danh, đơn từ. Muốn nhìn TOÀN BỘ việc học của người đó (kể cả khoá tự học, chứng chỉ, gói thuê bao, luyện tập, lộ trình) thì mở Hồ sơ học tập 360° từ danh sách Người dùng. Tỉ lệ điểm danh ở hai nơi dùng chung một công thức nên luôn khớp.

Trang hồ sơ có 3 section + 3 relation managers:

Section 1 — Hồ sơ (Profile) ​

Read-only metadata:

  • Mã học viên (copyable)
  • Họ tên + email
  • Trạng thái (badge)
  • Ngày nhập học / tốt nghiệp / thôi học
  • Ghi chú (free text)
  • Số điện thoại (lấy từ tài khoản) và section Thông tin cá nhân (số CCCD chỉ hiện cho người có quyền sửa hồ sơ)

Section 2 — Tóm tắt điểm danh (Cross-batch attendance) ​

Tự động tính qua StudentAttendanceSummaryService:

  • Tỉ lệ điểm danh tổng thể — session-weighted (không phải avg đơn giản).
  • Phân tích theo từng lớp — % per batch.
  • 5 buổi vắng gần nhất — với ngày + tên buổi + lý do.

Color-coded:

  • ≥ 85% — xanh (success)
  • 70–84% — vàng (warning)
  • < 70% — đỏ (danger)

Session-weighted khác avg đơn giản

Học viên qua 2 lớp:

  • Lớp A: 8/10 buổi (80%) — held 10 sessions.
  • Lớp B: 5/5 buổi (100%) — held 5 sessions.

Avg đơn giản: (80 + 100) / 2 = 90%. Session-weighted: (8+5) / (10+5) = 86.7%.

Service dùng session-weighted — phản ánh đúng tải học thật.

Empty state: nếu chưa có buổi nào held trong các lớp của học viên, hiển thị "Chưa có buổi học nào trong các lớp của học viên này."

Section 3 — Bảng điểm tổng hợp (Transcript) ​

Per-batch transcript qua StudentTranscriptService. Mặc định collapsed — click để mở.

Mỗi batch hiển thị:

  • Tên + mã lớp
  • joined_at / exited_at (nếu có)
  • BatchEnrollment status (Active / Suspended / Transferred Out / Dropped / Completed)
  • Cho mỗi khoá thuộc Program:
    • Tên khoá
    • % tiến độ + completion flag
    • Hoạt động gần nhất (timestamp)

Bao gồm cả enrollment đã đóng

Transcript bao gồm cả transferred_out, dropped, completed — đây là bản ghi authoritative "học viên đã đi qua đâu", không phải snapshot hiện tại. Nếu chỉ muốn xem nơi đang học, dùng widget active_batches_count trong list.

Relation manager 1 — Ghi danh (BatchEnrollments) ​

Tab/section quản lý ghi danh từng lớp của học viên:

  • Bảng tất cả batch_user records (active + closed).
  • Header action Ghi danh vào lớp — mở modal chọn Batch active → tạo enrollment mới.
  • Per-row actions: Chuyển lớp, Tạm dừng, Khôi phục, Cho thôi học (Drop), Hoàn tất.

Chi tiết quy trình: xem Ghi danh & Chuyển lớp và Chuyển lớp (Batch Transfer).

Relation manager 2 — Ghi chú (StudentNotes) ​

Notes timeline cho học viên này. Xem Ghi chú học viên cho chi tiết.

Relation manager 3 — Lịch sử chuyển lớp (Transfers) ​

Read-only audit log của tất cả lần chuyển lớp:

  • Lớp đi → lớp đến
  • Người thực hiện (transferred_by)
  • Thời điểm
  • Lý do

Không sửa được record này (chỉ tạo qua Transfer action).

Import học viên CSV (cho roster) ​

Khác với Import học viên vào Batch (tạo User + attach Batch), import vào StudentResource chỉ tạo Student record cho User đã tồn tại.

Khi nào dùng? ​

  • Migration từ hệ thống cũ — bạn có CSV với danh sách học viên + mã cũ + ngày nhập học.
  • Backfill data sau khi tạo nhiều User qua kênh khác mà chưa có Student record.

Format CSV ​

csv
email,student_code,admitted_at,notes,date_of_birth,citizen_id,citizen_id_issued_on,address
hung@example.com,STD-2024-001,2024-09-01,Chuyển từ chi nhánh HCM,15/03/2001,001201012345,20/05/2021,Hà Nội
lan@example.com,,2026-04-15,,,,,
CộtBắt buộcMô tả
email✅Phải khớp với User đã tồn tại
student_code⬜Trống → auto-generate
admitted_at⬜Trống → now()
notes⬜Free text
date_of_birth⬜Ngày sinh
citizen_id⬜Số CCCD 12 số (hoặc CMND 9 số)
citizen_id_issued_on⬜Ngày cấp CCCD — không trước ngày sinh
address⬜Địa chỉ

Ngày ghi dạng 2001-03-15 hoặc 15/03/2001; không nhận ngày trong tương lai. Tệp tối đa 10MB, mã hoá UTF-8.

Bổ sung thông tin cho học viên đã có

Với người đã là học viên, dòng có ít nhất một ô thông tin cá nhân sẽ được xếp loại Cập nhật hồ sơ: chỉ các ô có giá trị được ghi vào hồ sơ, ô trống giữ nguyên dữ liệu cũ, mã học viên không đổi. Việc cập nhật này chỉ dành cho người có quyền sửa hồ sơ học viên; người không có quyền đó sẽ thấy những dòng này ở loại Đã là học viên (bỏ qua).

Quy trình ​

  1. Header Nhập học viên → upload CSV.
  2. Preview hiển thị tóm tắt:
    • Sẵn sàng (ready) — sẽ được tạo
    • Cập nhật hồ sơ (update) — học viên đã có, bổ sung thông tin cá nhân
    • Đã là học viên (already_student) — User đã có Student record (skip)
    • Không có user (no_user) — email không khớp User nào (skip)
    • Không hợp lệ (invalid) — email malformed (skip)
    • Trùng lặp (duplicate) — email xuất hiện 2 lần trong file (skip dòng sau)
  3. Confirm → Import.
  4. Kết quả: "Đã nhập mới X, cập nhật Y trên tổng Z dòng."

Backfill từ legacy

Có lệnh artisan riêng php artisan training:backfill-students quét tất cả User đã thuộc Batch nhưng chưa có Student record → tạo bulk. Hữu ích khi update từ phiên bản cũ. Liên hệ Tenant Admin / Central Admin để chạy.

Export roster (xuất danh sách) ​

Header Xuất danh sách → modal:

  • Định dạng: CSV / XLSX.
  • Phạm vi: theo filter hiện tại (vd: filter Active rồi export → chỉ xuất Active students).
  • Download → file kèm tất cả cột visible.

Dashboard widgets (Tenant Admin / Training Manager) ​

StudentStatsOverview ​

Stats overview widget hiển thị 4 ô:

ÔÝ nghĩa
Học viên đang họccount(status = active) — đang nhập học
Đã tốt nghiệpcount(status = graduated) — tích luỹ
Đã thôi họccount(status = withdrawn) — tích luỹ
Tỷ lệ thôi họcwithdrawn / (active + graduated + withdrawn) — color-coded

Tỉ lệ thôi học:

  • < 5% — xanh (success)
  • 5–15% — vàng (warning)
  • 15% — đỏ (danger)

AdmissionsTrendChart ​

Bar chart số học viên nhập học mỗi tháng trong 12 tháng gần nhất.

Sort theo admitted_at. Buckets gom trong PHP để portable giữa MariaDB / SQLite test.

Đọc trend

  • Đỉnh tháng 4 + tháng 9 — đầu kỳ học (đa số tổ chức trường).
  • Sụt bất thường → có thể marketing yếu / sự kiện ảnh hưởng.
  • Tăng đều → growth healthy.

Quan hệ với các module khác ​

Với UserManagement ​

  • Student belongsTo User.
  • Soft delete User → cascade soft delete Student (tuỳ migration config).
  • Hard delete User → cascade FK rules.

Với TrainingManagement (Batch) ​

  • Student có nhiều BatchEnrollment qua relation batchEnrollments (FK qua user_id, không phải student_id — vì BatchUser pivot dùng user_id).
  • Auto-create student listener: EnsureStudentForBatchMember.

Với Gamification ​

  • Student không có rule riêng — gamification dựa trên User.
  • Có thể tạo rule custom "đạt huy hiệu khi tốt nghiệp" — đề nghị Tenant Admin cấu hình qua module Gamification.

Với Certificate ​

  • Certificate gắn với User + Course, không gắn Student.
  • Tuy nhiên template chứng chỉ có thể nhúng student_code qua biến — yêu cầu Course Manager template.

Với Notifications ​

  • Auto-events: StudentAdmitted, StudentTransferred, BatchEnrollmentStatusChanged — Tenant Admin có thể cấu hình email template tương ứng.

Câu hỏi thường gặp ​

Học viên cũ chưa có Student record — phải làm gì? Chạy php artisan training:backfill-students (Tenant Admin/Central Admin). Hoặc tạo thủ công từng người.

Một User có thể là 2 học viên với 2 mã khác nhau? Không. UNIQUE(user_id) trong students. Nếu cần đa-cohort với mã khác, đây là design choice — đề xuất Tenant Admin nếu thực sự cần.

Đổi student_code sau khi đã in chứng chỉ? Đổi được nhưng chứng chỉ đã cấp giữ mã cũ (hardcoded vào PDF khi sinh). Nếu cần cấp lại với mã mới, regenerate chứng chỉ — work qua Tenant Admin.

Tôi tạo Student rồi nhưng chưa attach Batch nào — họ có vào Learnspace được không? Có. User vào Learnspace bằng tài khoản — Student record không gate truy cập. Học viên thấy Learnspace trống cho đến khi có Batch / Course enrollment.

Soft-deleted student có hiện ở widget StudentStats không? Không. Widget query withoutTrashed. Tuy nhiên TrashedFilter trong list cho admin xem.

Pattern student_code custom? Cấu hình ở config/trainingmanagement.php hoặc settings — Central Admin set. Hỗ trợ placeholder {YYYY}, {MM}, {counter:N} (zero-padded N digits).

Tôi withdraw nhầm — sao revert nhanh? Action Khôi phục → status về Active, clear withdrawn_at. Đơn giản. BatchEnrollment đã đóng (nếu có) thì không tự mở lại.

Cross-batch attendance summary load chậm? Service query held_session_ids cho mỗi batch + count attended. Học viên qua 10+ batch lớn có thể chậm — nếu thường xuyên, đề xuất Tenant Admin cache/optimize.

Tôi muốn export student với điểm + attendance trong 1 file? Hiện chưa có "consolidated export" trong UI — phải export từng phần. Đề xuất tính năng nếu thường xuyên.

StudentNote có thấy được trong Trainer Panel? Trainer có thể đọc + tạo + sửa note (cùng giới hạn 24h). Tuy nhiên Trainer Panel hiện chưa expose hồ sơ Student riêng; trainer xem note qua Tenant Admin Panel (nếu được Tenant Admin gán quyền vào panel đó).

LMS Documentation