[CLAUDE] Workflow: W1 gỡ 2 bom per-type type-3 — deactivate per-Code (R-6 tập tường minh) + overview family; test-before RED→GREEN +4 test (672/672)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@ -82,7 +82,22 @@ public record AwDefinitionDto(
|
||||
public record AwTypeSummaryDto(
|
||||
int ApplicableType,
|
||||
string ApplicableTypeLabel,
|
||||
// `Active` = bản đang áp dụng ĐẦU TIÊN của loại (giữ nguyên nghĩa từ Mig 22 — FE đọc
|
||||
// thẳng ô này: ApprovalWorkflowsV2Page.tsx thẻ landing + panel "đang áp dụng").
|
||||
// ⚠️ Với loại per-Code-family, đây chỉ là MỘT trong N bản đang áp dụng (bản Version cao
|
||||
// nhất gặp trước), KHÔNG đại diện cho `Code` nào cả ⇒ panel per-Code phải tự cắt theo
|
||||
// `Code` (KHKK đang làm vậy: ApprovalWorkflowsV2Page.tsx:321-339), đừng đọc ô này.
|
||||
AwDefinitionDto? Active,
|
||||
// [S187 W1b] Các bản ĐANG ÁP DỤNG CÒN LẠI của loại — KHÔNG lặp lại bản trong `Active`.
|
||||
// Tập đầy đủ những bản đang áp dụng = [Active] ∪ ActiveOthers.
|
||||
//
|
||||
// Vì sao cần: loại per-Code-family có NHIỀU quy trình cùng IsActive trong CÙNG một
|
||||
// ApplicableType (type-10 KHKK 8 nhóm N1..N8 · type-3 HĐ 7 loại). Trước bản này overview
|
||||
// chỉ trả 1 và N-1 bản còn lại chỉ còn đường ra qua `History` — mà `History` là KHO PHIÊN
|
||||
// BẢN, FE dựng mục "phiên bản cũ" bằng `history.filter(d => !d.isActive)` ⇒ chúng KHÔNG
|
||||
// xuất hiện ở đâu trên màn hình. Loại 1-active-per-type thì danh sách này RỖNG (không đổi gì).
|
||||
List<AwDefinitionDto> ActiveOthers,
|
||||
// KHO PHIÊN BẢN — MỌI version của loại, kể cả bản đang áp dụng (không lọc `!IsActive`).
|
||||
List<AwDefinitionDto> History);
|
||||
|
||||
public record AwAdminOverviewDto(List<AwTypeSummaryDto> Types);
|
||||
@ -206,10 +221,26 @@ public class GetAwAdminOverviewQueryHandler(
|
||||
.Select(type =>
|
||||
{
|
||||
var versions = definitions.Where(d => d.ApplicableType == type).Select(ToDto).ToList();
|
||||
|
||||
// 🔴 [S187 W1b] Trả ĐỦ mọi bản đang áp dụng của loại, không chỉ bản đầu.
|
||||
//
|
||||
// Loại per-Code-family (type-10 KHKK 8 nhóm · type-3 HĐ 7 loại) có N bản cùng
|
||||
// IsActive; bản trước lấy `versions.FirstOrDefault(v => v.IsActive)` ⇒ N-1 bản kia
|
||||
// rơi hết vào `History`, nơi FE lọc `!isActive` để dựng danh sách phiên bản cũ ⇒
|
||||
// chúng biến mất khỏi UI, im lặng.
|
||||
//
|
||||
// Chia 2 ô thay vì gộp 1: `Active` PHẢI giữ nguyên giá trị cũ (FE đang đọc thẳng),
|
||||
// nên `ActiveOthers` gánh phần còn lại — hợp của 2 ô = trọn tập, KHÔNG phần tử nào
|
||||
// xuất hiện hai lần. Không hỏi ApplicableType ở đây là CỐ Ý: luật là "có mấy bản
|
||||
// đang áp dụng thì trả bấy nhiêu", tự đúng cho loại family thêm sau này; loại
|
||||
// 1-active-per-type giữ y hệt hành vi cũ (`ActiveOthers` rỗng).
|
||||
var actives = versions.Where(v => v.IsActive).ToList();
|
||||
|
||||
return new AwTypeSummaryDto(
|
||||
(int)type,
|
||||
AwLabels.Type.GetValueOrDefault(type, type.ToString()),
|
||||
versions.FirstOrDefault(v => v.IsActive),
|
||||
actives.FirstOrDefault(),
|
||||
actives.Skip(1).ToList(),
|
||||
versions);
|
||||
})
|
||||
.ToList();
|
||||
@ -328,6 +359,22 @@ public class CreateAwDefinitionCommandValidator : AbstractValidator<CreateAwDefi
|
||||
public class CreateAwDefinitionCommandHandler(IApplicationDbContext db)
|
||||
: IRequestHandler<CreateAwDefinitionCommand, Guid>
|
||||
{
|
||||
// 🔴 [S187 W1a] Những loại tắt bản active theo phạm vi **per-CODE** — TẬP TYPE TƯỜNG MINH.
|
||||
//
|
||||
// Tiêu chí vào danh sách: loại đó có NHIỀU quy trình sống song song trong CÙNG một
|
||||
// ApplicableType, mỗi cái một `Code` riêng, và mỗi cái phải tự giữ bản active của mình:
|
||||
// • type-10 `ContractSigningPlan` (KHKK) — 8 nhóm duyệt `KHKK-N1..N8`
|
||||
// (`DbInitializer.SeedKhkkGroupWorkflowsAsync`, seed cả 8 với IsActive=1);
|
||||
// • type-3 `Contract` (HĐ) — 7 loại hợp đồng, mỗi loại một quy trình riêng.
|
||||
//
|
||||
// Thêm loại vào đây = quyết định về NGỮ NGHĨA của loại đó, không phải về hình dạng mã:
|
||||
// mọi `Code` của loại đều đi nhánh per-Code, kể cả mã ngoài họ (R-6).
|
||||
private static readonly ApprovalWorkflowApplicableType[] PerCodeDeactivationTypes =
|
||||
[
|
||||
ApprovalWorkflowApplicableType.ContractSigningPlan,
|
||||
ApprovalWorkflowApplicableType.Contract,
|
||||
];
|
||||
|
||||
public async Task<Guid> Handle(CreateAwDefinitionCommand request, CancellationToken ct)
|
||||
{
|
||||
var typeEnum = (ApprovalWorkflowApplicableType)request.ApplicableType;
|
||||
@ -353,21 +400,26 @@ public class CreateAwDefinitionCommandHandler(IApplicationDbContext db)
|
||||
.MaxAsync(w => (int?)w.Version, ct) ?? 0;
|
||||
nextVersion++;
|
||||
|
||||
// Tắt bản đang active — PHẠM VI phụ thuộc loại (bản trước: LUÔN per-type).
|
||||
// Tắt bản đang active — PHẠM VI phụ thuộc loại (bản gốc Mig 22: LUÔN per-type).
|
||||
//
|
||||
// • type-10 `ContractSigningPlan` (KHKK): **per-CODE**. Loại này có 8 quy trình
|
||||
// SỐNG SONG SONG cùng type — mỗi nhóm duyệt N1..N8 một `Code` riêng
|
||||
// (`DbInitializer.SeedKhkkGroupWorkflowsAsync:609`, seed cả 8 với IsActive=1).
|
||||
// Tắt theo type ⇒ tạo version mới cho MỘT nhóm sẽ hạ IsActive của CẢ 7 nhóm còn
|
||||
// lại (mỗi nhóm mất quy trình active ⇒ FE hết auto-pin ⇒ không tạo được phiếu).
|
||||
// • các loại khác: **per-TYPE** như cũ — 1 active/type là bất biến của chúng.
|
||||
// • Loại nằm trong `PerCodeDeactivationTypes` (khai báo + tiêu chí ở ĐẦU class này):
|
||||
// **per-CODE**. Chúng có NHIỀU quy trình SỐNG SONG SONG trong cùng một type, mỗi
|
||||
// cái một `Code`. Tắt theo type ⇒ tạo version mới cho MỘT cái sẽ hạ IsActive của
|
||||
// TẤT CẢ những cái còn lại (mỗi cái mất quy trình active ⇒ FE hết auto-pin ⇒
|
||||
// không lập được phiếu), im lặng và KHÔNG có endpoint bật lại.
|
||||
// • các loại còn lại: **per-TYPE** như cũ — với CHÚNG, 1 active/type vẫn là bất biến.
|
||||
// 🔴 Đây là câu tự-khai từng SAI: bản trước viết "các loại khác: per-TYPE như cũ —
|
||||
// 1 active/type là bất biến của chúng" khi tập per-Code chỉ có type-10, rồi type-3
|
||||
// mọc thêm 7 quy trình `HD-*` sống song song ⇒ câu đó bao luôn type-3 và thành lời
|
||||
// khai sai. Nay câu này neo vào TẬP TYPE tường minh, không neo vào con số.
|
||||
//
|
||||
// 🔴 [S182 R-6] Vị ngữ type-10 KHOÁ đúng 3 vế `Code == request.Code &&
|
||||
// ApplicableType == typeEnum && IsActive`. CẤM thay bằng biến-thể regex
|
||||
// `^KHKK-N[1-8]$`: `Code` type-10 nằm ngoài họ đó (vd `QT-KHKK-V2-001`) sẽ rơi
|
||||
// lại nhánh per-type và nuke đúng 8 nhóm mà rào này sinh ra để cứu.
|
||||
// (`nextVersion` `:334-337` vốn đã tính per-Code ⇒ nhánh này làm 2 vế khớp nhau.)
|
||||
var actives = typeEnum == ApprovalWorkflowApplicableType.ContractSigningPlan
|
||||
// 🔴 [S182 R-6 · giữ nguyên hiệu lực @S187] Vị ngữ per-Code KHOÁ đúng 3 vế `Code == code
|
||||
// && ApplicableType == typeEnum && IsActive`. CẤM thay bằng biến-thể regex trên `Code`
|
||||
// (`^KHKK-N[1-8]$`, `^HD-...$`): mã nằm ngoài họ (vd `QT-KHKK-V2-001`, `QT-HD-V2-001`)
|
||||
// sẽ rơi lại nhánh per-type và nuke đúng tập mà rào này sinh ra để cứu. Phân loại theo
|
||||
// ApplicableType, KHÔNG theo hình dạng mã. (`nextVersion` phía trên vốn đã tính
|
||||
// per-Code toàn cục ⇒ nhánh này làm 2 vế khớp nhau.)
|
||||
var actives = PerCodeDeactivationTypes.Contains(typeEnum)
|
||||
? await db.ApprovalWorkflows
|
||||
.Where(w => w.Code == code && w.ApplicableType == typeEnum && w.IsActive)
|
||||
.ToListAsync(ct)
|
||||
|
||||
Reference in New Issue
Block a user