Dự án

Tổng quan

Hồ sơ

Hành động

Task #2380

mở
HN TP

Task #2377: Các vấn đề demo 6/10

[KHN] Khi xoá/ thay đổi 1 lớp trong khn

Task #2380: [KHN] Khi xoá/ thay đổi 1 lớp trong khn

Thêm bởi Hải Yến Ngô cách đây khoảng 1 tháng. Cập nhật cách đây 20 ngày.

Trạng thái:
New
Mức ưu tiên:
Cao
Phân công cho:
Phiên bản:
-
Bắt đầu:
07-10-2026
Hết hạn:
Tiến độ:

0%

Thời gian ước lượng:
Build tại bản:
Người Test:
Thời gian test xong:

Mô tả

  • Khi 1 khn đã đc duyệt và xếp lịch => bị sai/chỉnh sửa lớp huấn luyện
  • đưa ra giải pháp khi xoá/điều chỉnh lớp huấn luyện trong KHN
  • YÊU CẦU: thay đổi 1 lớp trong khn thì sẽ phải xử lý như thế nào để ít thao tác và nhanh chóng nhất

Giải pháp của Dev Lực:

Thay đổi Kế hoạch năm
Đây là một bài toán nghiệp vụ rất thực tế và điển hình trong các hệ thống điều hành huấn luyện quân sự/đào tạo đại học.

Trong hệ thống, chuỗi liên kết dữ liệu đi theo trục:
{Kế hoạch năm (KHN)} -> {TBNVHL (Notification)} -> {Kế hoạch huấn luyện (KHHL)} -> {Thời khóa biểu (TKB Sessions)}


I. ĐÁNH GIÁ NGHẼN NGHIỆP VỤ NẾU LÀM THEO CÁCH THỦ CÔNG HIỆN TẠI

Nếu một Kế hoạch năm (KHN) đã duyệt và đã xếp TKB, mà hệ thống áp dụng cơ chế khóa cứng (hiện tại đang chặn sửa khi đã có TBNVHL), người dùng sẽ rơi vào "Cơn ác mộng thao tác":

  1. Phải hủy duyệt TKB -> Xóa/dỡ lịch các tuần/tháng.
  2. Hủy duyệt/Xóa Kế hoạch huấn luyện.
  3. Xóa các Thông báo nhiệm vụ huấn luyện (TBNVHL).
  4. Hủy duyệt KHN -> Chuyển về Lưu nháp -> Sửa/xóa lớp.
  5. Gửi duyệt lại từ đầu toàn bộ các tầng và phải xếp lại TKB từ đầu (mất toàn bộ công sức xếp giảng viên, giảng đường, thao trường của cả các lớp không liên quan).

👉 Yêu cầu đặt ra: Cần giải pháp "Khu trú ảnh hưởng (Blast Radius Isolation)" kết hợp "Đồng bộ tự động 1 chạm (1-Click Smart Cascade)" — tức là sửa tại KHN, hệ thống tự động xử lý các module bên dưới với số lần click chuột ít nhất và không ảnh hưởng đến các lớp khác.


II. GIẢI PHÁP TỔNG THỂ CHO TỪNG TÌNH HUỐNG

Khi quản lý và điều chỉnh lớp trong Kế hoạch năm, thực tế sẽ rơi vào 3 tình huống nghiệp vụ:

                      [ QUẢN LÝ & ĐIỀU CHỈNH KẾ HOẠCH NĂM ]
                                        │
           ┌────────────────────────────┼────────────────────────────┐
           ▼                            ▼                            ▼
    【Tình huống 1】              【Tình huống 2】              【Tình huống 3】
     XÓA HẲN 1 LỚP               ĐIỀU CHỈNH TIẾN ĐỘ            NHÂN BẢN KHN CHO LỚP
 (Lớp hoãn học, gán nhầm)      (Lớp học khung riêng)        CÙNG CHƯƠNG TRÌNH ĐÀO TẠO
           │                            │                            │
           ▼                            ▼                            ▼
  Thu hồi lịch cục bộ         Tách nhánh (Fork Plan)          Sao chép phân bổ bài học
(Chỉ xóa session lớp đó)     thành KHN riêng cho lớp         (Tạo KHN Lưu nháp mới)

1. TÌNH HUỐNG 1: XÓA HOÀN TOÀN 1 LỚP KHỎI KHN

(Ví dụ: Lớp bị hoãn khóa học, chuyển sang năm sau hoặc chọn nhầm lớp vào KHN này)

  • Mục tiêu: Xóa lớp khỏi KHN nhưng không xóa TKB của các lớp khác, giải phóng tài nguyên giảng viên/phòng học.
  • Cách xử lý tối ưu (Ít thao tác nhất):
    • Tại KHN: Người dùng bấm nút "Xóa lớp khỏi KHN" -> Hệ thống bật Popup xác nhận kèm Ma trận ảnh hưởng (Hiển thị rõ: Lớp đang có 3 TBNVHL, 1 KHHL, 45 tiết TKB đã xếp).
    • Hệ thống tự động chạy ngầm trong 1 Transaction:
      1. Với TKB (TrainingTimetable_Session):
        • Tự động xóa các tiết của riêng lớp đó (fixed_class_id = @classId) từ thời điểm hiện tại trở đi (date >= TODAY).
        • Giải phóng tài nguyên: Giảng viên (lecturer_id), Phòng học (room_id) của các tiết bị xóa lập tức được giải phóng để lớp khác sử dụng.
        • Lưu ý lớp ghép: Nếu là tiết học ghép nhiều lớp, hệ thống chỉ tách lớp bị xóa ra khỏi nhóm ghép, giữ nguyên tiết học cho các lớp còn lại.
        • Các tiết đã diễn ra trong quá khứ (date < TODAY) được giữ nguyên trạng thái đóng băng để lưu vết hồ sơ đào tạo.
      2. Với KHHL & TBNVHL:
        • Tự động xóa liên kết của lớp trong TrainingNotification_FixedClass và CH_TrainingClass.
        • Chạy hàm cập nhật lại tổng số tiết/tổng hợp (Recalculate Summary).
      3. Với KHN: Xóa bản ghi trong YearPlan_FixedClass.
  • Thao tác người dùng: Đúng 1 click (Chọn lớp -> Bấm Xóa -> Nhập lý do -> Xác nhận).

2. TÌNH HUỐNG 2: ĐIỀU CHỈNH TIẾN ĐỘ / NỘI DUNG HỌC CỦA RIÊNG LỚP ĐÓ

(Ví dụ: Lớp A cần học thêm một số môn đặc thù hoặc giảm tiết, lệch khung với các lớp còn lại trong KHN)

  • Vấn đề: Trong hệ thống hiện tại, 1 KHN gồm nhiều lớp dùng chung bảng phân bổ bài học YearPlan_Lesson. Nếu sửa trực tiếp bài học trên KHN này sẽ làm lệch luôn tiến độ của các lớp còn lại.
  • Cách xử lý tối ưu (Cơ chế "Tách nhánh KHN" - Forking Plan):
    • Tại KHN: Người dùng chọn Lớp A -> Bấm "Tách thành Kế hoạch riêng".
    • Hệ thống tự động:
      1. Rút Lớp A ra khỏi KHN hiện tại (KHN cũ giữ nguyên cho các lớp còn lại).
      2. Clone sang một bản ghi KHN mới dành riêng cho Lớp A (kế thừa lại toàn bộ bài học và lịch TKB đã xếp đến thời điểm hiện tại).
      3. Mở giao diện lập kế hoạch của KHN mới để người dùng chỉnh sửa bài học/tiết cho Lớp A.
      4. Khi duyệt KHN mới, hệ thống chỉ đẩy chênh lệch (Delta) vào TKB để xếp bổ sung các bài mới.

3. TÌNH HUỐNG 3: NHÂN BẢN KẾ HOẠCH NĂM CHO CÁC LỚP CÙNG CHƯƠNG TRÌNH ĐÀO TẠO (CLONE PLAN)

(Ví dụ: Tiểu đoàn 1 và Tiểu đoàn 2 cùng học CTĐT Sĩ quan Chỉ huy Tham mưu Lục quân Khóa 89; Tiểu đoàn 1 đã lập xong KHN chuẩn, cần nhân bản sang cho các lớp thuộc Tiểu đoàn 2)

  • Mục tiêu: Tái sử dụng 100% công sức phân bổ bài học theo tháng (YearPlan_Lesson), giảm 95% thời gian nhập liệu, đảm bảo tính chuẩn hóa khung chương trình và cách ly độc lập hoàn toàn giữa các lớp.
  • Các ràng buộc nghiệp vụ bắt buộc (Validation Rules):
    1. Cùng Chương trình đào tạo (curriculum_version_id): Lớp đích bắt buộc phải thuộc cùng CTĐT với KHN nguồn (FixedClass -> Cohort -> curriculum_version_id), đảm bảo cây bài học (lesson_id) và môn học (subject_version_id) tồn tại và hợp lệ.
    2. Cùng Năm đào tạo (year_no): Lớp đích phải cùng năm thứ đào tạo (ví dụ: cùng học năm thứ 2), tránh vi phạm định mức môn theo năm học (ValidateSubjectYearPeriodsAsync).
    3. Lớp đích chưa có KHN trong năm học: Mỗi lớp trong một năm học chỉ thuộc tối đa 1 KHN (tuân thủ logic GetAllFixedClassNotInYearPlan).
    4. Kiểm tra định mức tiết tối đa tháng (ValidateMonthlyPeriodsAsync): Tự động đối soát số tiết sao chép với định mức ConfigSlot của lớp đích để cảnh báo nếu tháng nào vượt khung.
    5. Trạng thái Kế hoạch mới: KHN mới bắt buộc ở trạng thái "Lưu nháp" (iYearPlanStatus.LuuNhap), kể cả khi KHN nguồn đã duyệt.
    6. Tuyệt đối KHÔNG tự động nhân bản TBNVHL, KHHL hay TKB: TKB gắn liền với giảng viên, thao trường, phòng học cụ thể; nhân bản TKB sẽ gây xung đột tài nguyên. KHN mới sau khi được duyệt sẽ sinh TBNVHL và xếp TKB độc lập theo quy trình chuẩn.
  • Cách xử lý tối ưu:
    • Tại danh sách KHN hoặc màn lập KHN: Người dùng chọn KHN gốc -> Bấm nút "Nhân bản kế hoạch".
    • Bật Modal chọn lớp đích (hệ thống tự động lọc danh sách lớp thỏa mãn 3 điều kiện trên).
    • Người dùng xác nhận -> Hệ thống sao chép Header YearPlan, gán YearPlan_FixedClass mới và Bulk Copy toàn bộ YearPlan_Lesson trong 1 Transaction -> Điều hướng ngay sang màn hình Lập kế hoạch của bản ghi mới để rà soát/tinh chỉnh.

III. THIẾT KẾ GIAO DIỆN & TRẢI NGHIỆM NGƯỜI DÙNG (UX/UI)

Để đảm bảo tính pháp lý quân sự (không sửa ngầm) nhưng vẫn nhanh chóng:

  1. Vị trí đặt tính năng:

    • Tại màn hình danh sách Kế hoạch năm (LapKeHoachNamListComponent): Bổ sung các nút hành động:
      • "Nhân bản kế hoạch" (Clone Plan).
      • "Điều chỉnh lớp" (Adjust Class) trên từng dòng hoặc trong xem chi tiết.
    • Tại màn xem chi tiết (KeHoachNamViewDetailComponent): Menu thao tác nhanh.
  2. Modal Hướng dẫn Thông minh (Impact Wizard - Dùng cho Điều chỉnh/Xóa/Tách lớp):

    • Bước 1 (Chọn hành động):
      • Chọn lớp cần thao tác.
      • Chọn loại điều chỉnh: [Xóa bỏ] hoặc [Tách lớp ra kế hoạch riêng].
      • Nhập Lý do điều chỉnh (Bắt buộc theo nghiệp vụ quân sự: ví dụ "Theo Quyết định số... của Hiệu trưởng").
    • Bước 2 (Xem trước ảnh hưởng & Xác nhận):
      • Hệ thống hiển thị bảng tóm tắt:
        • Số đợt TBNVHL bị ảnh hưởng: X đợt.
        • Số tiết TKB sẽ tự động hủy/chuyển đổi: Y tiết (từ ngày DD/MM/YYYY).
        • Cảnh báo tiết học ghép (nếu có).
      • Bấm nút: [Xác nhận & Tự động đồng bộ].
  3. Modal Nhân bản Kế hoạch năm (Clone Plan Modal):

    • Thông tin KHN gốc: Hiển thị rõ Mã, Tên, Năm học, CTĐT, Năm thứ.
    • Thông tin KHN mới:
      • Mã KHN mới (Hệ thống tự sinh gợi ý theo mã lớp đích).
      • Tên KHN mới.
    • Chọn Lớp đích: Danh sách checkbox chỉ hiển thị các lớp thỏa mãn (Cùng CTĐT, Cùng năm thứ, Chưa có KHN trong năm học).
    • Tóm tắt dữ liệu sẽ nhân bản:
      • Số môn học sao chép: A môn.
      • Số bài học sao chép: B bài học (Tổng C tiết phân bổ trên 10-12 tháng).
    • Bấm nút: [Nhân bản sang kế hoạch mới] -> Mở ngay màn Lập kế hoạch để người dùng kiểm tra.

IV. KIẾN TRÚC KỸ THUẬT BACKEND (ĐỂ ĐẢM BẢO CHẠY NHANH & TOÀN VẸN)

Để hiện thực hóa luồng này mà không bị lỗi timeout hoặc deadlock:

  1. Tạo API Endpoints chuyên biệt:

    • API Điều chỉnh/Tách lớp:
      • POST api/tenant/YearPlans/adjust-fixed-class
      • DTO:
        {
          year_plan_id: string;
          action_type: 'DELETE' | 'REPLACE' | 'FORK';
          source_fixed_class_id: string;
          target_fixed_class_id?: string; // Dùng khi REPLACE
          reason: string;
          effective_from_date: Date;     // Mặc định là ngày hôm nay
        }
        
    • API Nhân bản Kế hoạch năm:
      • POST api/tenant/YearPlans/clone
      • DTO:
        {
          source_year_plan_id: string;
          target_code: string;
          target_name: string;
          target_fixed_class_ids: string[];
        }
        
  2. Cơ chế xử lý trong Backend:

    • Bọc toàn bộ trong 1 DbTransaction: Đảm bảo hoặc thành công toàn bộ từ KHN đến TKB, hoặc rollback sạch sẽ nếu có lỗi.
    • Cơ chế xử lý khi Clone KHN:
      1. Validate các lớp đích: đảm bảo cùng curriculum_version_id, cùng year_no và chưa tồn tại trong KHN nào của năm học đó.
      2. Insert bản ghi cha YearPlan mới với status = iYearPlanStatus.LuuNhap.
      3. Insert danh sách YearPlan_FixedClass cho các lớp đích.
      4. Query toàn bộ YearPlan_Lesson của KHN nguồn và Bulk Insert sang KHN mới (giữ nguyên subject_version_id, lesson_id, calendar_month, calendar_year, total_periods, details_json, all_periods_selected).
      5. Tái sử dụng hàm validation: ValidateMonthlyPeriodsAsync và ValidateSubjectYearPeriodsAsync để đảm bảo dữ liệu mới không vi phạm quota của lớp đích.
    • Tái sử dụng Engine TKB đã tối ưu (khi xóa/tách lớp):
      • Khi xóa/sửa session hàng loạt của lớp đó, tái sử dụng service TrainingTimetable_SessionService với cơ chế Warm Cache + Defer Side-Effects + Flush gom nhóm key (theo tài liệu Toi_uu_luong_luu_xoa_lich.md). Điều này giúp việc xóa 50-100 tiết của lớp diễn ra trong dưới 1 giây.
    • Ghi vết lịch sử tự động (TrainingTimetable_ChangeLog):
      • Ghi nhận lịch sử điều chỉnh với lý do của người dùng để phục vụ công tác thanh tra/kiểm tra sau này.
    • Bypass Validation chặn thông thường: Trong luồng này, thêm cờ Context.IsAdminAdjustment = true để bỏ qua việc throw exception tại ValidateTrainingNotificationLockedMonthsAsync.

BẢNG SO SÁNH HIỆU QUẢ

Tiêu chí Quy trình thủ công hiện tại Giải pháp đề xuất
Xóa / Điều chỉnh lớp trong KHN đã duyệt 8 – 10 bước qua 4 màn hình (30 phút – vài tiếng nếu phải xếp lại TKB) 1 click tại KHN, xử lý ngầm 3 – 5 giây, cách ly 100% các lớp khác
Lập KHN cho lớp mới cùng CTĐT Nhập thủ công lại từ đầu hàng trăm bài học (1 – 2 ngày) Nhân bản 1 chạm kế thừa toàn bộ khung bài học (1 – 2 giây), chuyển về Lưu nháp để rà soát
Tác động đến lớp khác Nguy cơ làm hỏng hoặc phải xếp lại lịch cả khóa 0% (Cách ly hoàn toàn giữa các lớp)
Tính toàn vẹn dữ liệu Dễ sót dữ liệu giữa các module 100% đồng bộ qua Database Transaction
Tính pháp lý quân đội Mất dấu vết cũ do xóa đi làm lại Lưu vết đầy đủ qua ChangeLog và RevisionRequest

Giải pháp này giải quyết triệt để cả hai bài toán cốt lõi:

  1. Tiền kỳ (Lập kế hoạch): Nhân bản nhanh chóng, chuẩn hóa theo Chương trình đào tạo.
  2. Hậu kỳ (Điều hành thực tế): Người dùng chỉ thao tác tại điểm phát sinh nhu cầu (Kế hoạch năm), toàn bộ các mắt xích phía sau (TBNVHL, KHHL, TKB) tự động thích ứng chính xác theo quan hệ dữ liệu đã được thiết lập sẵn.

TP Cập nhật bởi Tiến Lực Phạm cách đây 23 ngày Hành động #1

  • Mô tả cập nhật (Sự khác nhau)
  • Phân công cho gán cho Tiến Lực Phạm

TP Cập nhật bởi Tiến Lực Phạm cách đây 23 ngày Hành động #2

TP Cập nhật bởi Tiến Lực Phạm cách đây 20 ngày Hành động #3

Hành động

Định dạng khác của trang này: PDF Atom