[CLAUDE] Domain+App+Infra+Admin: W1 KHKK — Mig 69 ContractSigningPlans 7 bang + policy KeHoachKyKet + seeder UPGRADE-if-exists + CodeGen KHKK + Designer type-10
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m40s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m40s
- Domain/ContractSigningPlans: 7 entity + 3 enum (Phase 1/2/3/98/99; DossierItem Kind/Status start=1); ApplicableType += ContractSigningPlan=10 (slot 10, append-only) - Mig 69 AddContractSigningPlans: 7 CreateTable / 20 CreateIndex / 0 ALTER; UNIQUE filtered (PlanId,SupplierId) WHERE IsDeleted=0 (#57); FK 6 con Cascade 1-hop + 2 Restrict, 0 multiple-cascade-path; database-agent review PASS 8/8 + DB11 - MenuKeys.All += KeHoachKyKet (policy KeHoachKyKet.* x4 sinh runtime; menu-row prod KHONG doi — 142 giu); STATUS canonical 54->55 / 216->220 - DbInitializer.SeedKeHoachKyKetAccessAsync: UPGRADE-if-exists (F-S1 — khong insert-NO-OP) + vế CanDelete (Drafter/Admin), 13/13 role CanCreate+CanUpdate, chay SAU revoke; revoker khong phu Khkk_* (reviewer Truc-1 PASS) - ContractSigningPlanCodeGenerator: KHKK/{YYYY}/{Seq:D3} (owner OK @S161) qua WorkflowAppCodeSequences dung chung, SERIALIZABLE - AWV2AdminFeatures: 3 site count/retained/orphan + nhanh ContractSigningPlanLevelOpinions (chong no FK 500 khi xoa Level); +label VN type-10 (F-7); +ep false 2 co early-finalize server-side cho type-10 (F-8 — containment tang BE, FE da ep o levelFlagsPayload) - fe-admin Designer: deep-link type-10 + an 2 checkbox early-finalize (anh phan "PHA VO" S155) — containment 2 lop render+payload - tests: +4 (566 total, 0 fail) — schema-invariant 7 bang + codegen format (fault-inject 2 chieu chung co rang) Reviewer: PASS_WITH_FLAGS 10 issue -> 8 fixed cung commit, 2 giu trang thai (F-1 acceptance đo-CO cho prod; F-4 ke thua y PE prod) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@ -92,6 +92,9 @@ internal static class AwLabels
|
||||
[ApprovalWorkflowApplicableType.DuyetNcc] = "Duyệt NCC",
|
||||
[ApprovalWorkflowApplicableType.DuyetNccPhuongAn] = "Duyệt NCC + Giải pháp",
|
||||
[ApprovalWorkflowApplicableType.Contract] = "Hợp đồng",
|
||||
// [W1 S161 — reviewer F-7] Thiếu entry = fallback ToString() tiếng Anh lên tiêu đề
|
||||
// Designer VÀ ghi vào cột Name DB (useState `Quy trình ${label}` phía FE).
|
||||
[ApprovalWorkflowApplicableType.ContractSigningPlan] = "Kế hoạch ký kết HĐ",
|
||||
};
|
||||
}
|
||||
|
||||
@ -370,8 +373,12 @@ public class CreateAwDefinitionCommandHandler(IApplicationDbContext db)
|
||||
AllowReturnToDrafter = l.AllowReturnToDrafter,
|
||||
AllowApproverEditDetails = l.AllowApproverEditDetails,
|
||||
AllowApproverEditBudget = l.AllowApproverEditBudget,
|
||||
AllowApproverSkipToFinal = l.AllowApproverSkipToFinal,
|
||||
AllowApproverFinalize = l.AllowApproverFinalize,
|
||||
// [W1 S161 — reviewer F-8, F-B3 containment TẦNG BE] type=10 KHKK: 2 đường
|
||||
// early-finalize anh phán "PHÁ VỠ" (S155), W3 không port code path ⇒ ép false
|
||||
// server-side (FE đã ép ở levelFlagsPayload — đây chặn curl bypass). PUT
|
||||
// sửa-tại-chỗ đã có echo-so-BẰNG chặn đổi cờ ⇒ chỉ cần guard ở CREATE.
|
||||
AllowApproverSkipToFinal = typeEnum != ApprovalWorkflowApplicableType.ContractSigningPlan && l.AllowApproverSkipToFinal,
|
||||
AllowApproverFinalize = typeEnum != ApprovalWorkflowApplicableType.ContractSigningPlan && l.AllowApproverFinalize,
|
||||
AllowApproverDelete = l.AllowApproverDelete, // [Mig 68 S155] F6
|
||||
}).ToList(),
|
||||
})
|
||||
@ -842,7 +849,9 @@ public class UpdateAwDefinitionCommandHandler(
|
||||
// được "quy trình vừa bị sửa lúc nào, ai sửa, vì sao".
|
||||
// ⚠️ KHAI GIỚI HẠN: repo CHƯA có bảng changelog cho quy trình duyệt, mà
|
||||
// đợt 1 bị chốt "no new table" ⇒ vết cho workflow thuộc 5 module Văn
|
||||
// phòng số (Proposal/Leave/Ot/Travel/Vehicle) hiện CHỈ có UpdatedAt/
|
||||
// phòng số (Proposal/Leave/Ot/Travel/Vehicle) + KHKK (W1 S161 — reviewer F-6b:
|
||||
// `ContractSigningPlanChangelogs` là changelog PHIẾU, không phải changelog QUY-TRÌNH;
|
||||
// wire nếu cần ở W2/W3) hiện CHỈ có UpdatedAt/
|
||||
// UpdatedBy ở (a). Bảng `ApprovalWorkflowChangelogs` = việc tách riêng.
|
||||
if (changes.Count > 0 &&
|
||||
def.ApplicableType is ApprovalWorkflowApplicableType.DuyetNcc
|
||||
@ -883,8 +892,8 @@ public class UpdateAwDefinitionCommandHandler(
|
||||
await tx.CommitAsync(ct);
|
||||
}
|
||||
|
||||
// Đếm chữ ký CÒN HIỆU LỰC trên các dòng Cấp — quét CẢ 7 bảng LevelOpinion đang
|
||||
// FK vào ApprovalWorkflowLevels (PE + HĐ + 5 module Văn phòng số). Chỉ soi PE là
|
||||
// Đếm chữ ký CÒN HIỆU LỰC trên các dòng Cấp — quét CẢ 8 bảng LevelOpinion đang
|
||||
// FK vào ApprovalWorkflowLevels (PE + HĐ + 5 module Văn phòng số + KHKK W1). Chỉ soi PE là
|
||||
// vẫn nổ FK 547 khi quy trình thuộc module khác (§F.3 blast radius ≥6 module).
|
||||
// 🔴 `!p.IsDeleted` viết TƯỜNG MINH: chỉ PE + Contract có global query filter,
|
||||
// 5 bảng Office KHÔNG có ⇒ dựa filter là đúng PE mà sai 5 module kia.
|
||||
@ -938,6 +947,16 @@ public class UpdateAwDefinitionCommandHandler(
|
||||
.GroupBy(o => o.ApprovalWorkflowLevelId)
|
||||
.Select(g => new LevelOpinionCount(g.Key, g.Count())).ToListAsync(ct));
|
||||
|
||||
// [W1 Mig 69 — S161] GĐ2 Kế hoạch ký kết HĐ (type=10). Site liệt-kê-thủ-công:
|
||||
// module mới có LevelOpinions PHẢI vào CẢ 3 danh sách trong file này
|
||||
// (count-sống · retained-ref · orphan-delete) — thiếu 1 = admin xoá Level nổ FK 500.
|
||||
// Tự kiểm: grep -n "LevelOpinions.AsNoTracking\|LevelOpinions$" file này.
|
||||
Merge(await db.ContractSigningPlanLevelOpinions.AsNoTracking()
|
||||
.Where(o => levelIds.Contains(o.ApprovalWorkflowLevelId) && !o.IsDeleted
|
||||
&& db.ContractSigningPlans.Any(p => p.Id == o.ContractSigningPlanId && !p.IsDeleted))
|
||||
.GroupBy(o => o.ApprovalWorkflowLevelId)
|
||||
.Select(g => new LevelOpinionCount(g.Key, g.Count())).ToListAsync(ct));
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
@ -948,7 +967,7 @@ public class UpdateAwDefinitionCommandHandler(
|
||||
// 🔴 `IgnoreQueryFilters()` LÀ BẮT BUỘC, không phải trang trí: PE và Contract có global
|
||||
// filter `!IsDeleted` (`PurchaseEvaluationConfiguration.cs:84`). Không tắt filter thì hồ
|
||||
// sơ xoá mềm biến mất khỏi phép JOIN ⇒ ta lại kết luận "mồ côi" ⇒ đúng cái sai đang chữa.
|
||||
// (5 bảng Văn phòng số KHÔNG có filter — gọi vẫn vô hại, giữ 7 khối cùng một hình dạng.)
|
||||
// (5 bảng Văn phòng số + KHKK-LevelOpinions KHÔNG có filter — gọi vẫn vô hại, giữ 8 khối cùng một hình dạng.)
|
||||
private async Task<Dictionary<Guid, List<RetainedOpinionRef>>> ListRetainedOpinionsAsync(
|
||||
List<Guid> levelIds, CancellationToken ct)
|
||||
{
|
||||
@ -1003,6 +1022,14 @@ public class UpdateAwDefinitionCommandHandler(
|
||||
.Select(x => new RetainedOpinionRef(x.o.ApprovalWorkflowLevelId, "Đơn xe", x.p.MaDonTu, x.p.IsDeleted))
|
||||
.ToListAsync(ct));
|
||||
|
||||
// [W1 Mig 69 — S161] GĐ2 Kế hoạch ký kết HĐ — mirror nhánh trên (site 2/3).
|
||||
rows.AddRange(await db.ContractSigningPlanLevelOpinions.AsNoTracking().IgnoreQueryFilters()
|
||||
.Where(o => levelIds.Contains(o.ApprovalWorkflowLevelId))
|
||||
.Join(db.ContractSigningPlans, o => o.ContractSigningPlanId, p => p.Id, (o, p) => new { o, p })
|
||||
.Where(x => x.o.IsDeleted || x.p.IsDeleted)
|
||||
.Select(x => new RetainedOpinionRef(x.o.ApprovalWorkflowLevelId, "Kế hoạch ký kết HĐ", x.p.MaKeHoach, x.p.IsDeleted))
|
||||
.ToListAsync(ct));
|
||||
|
||||
return rows.GroupBy(r => r.LevelId).ToDictionary(g => g.Key, g => g.ToList());
|
||||
}
|
||||
|
||||
@ -1061,6 +1088,11 @@ public class UpdateAwDefinitionCommandHandler(
|
||||
.Where(o => levelIds.Contains(o.ApprovalWorkflowLevelId)
|
||||
&& !db.VehicleBookings.IgnoreQueryFilters().Any(p => p.Id == o.VehicleBookingId))
|
||||
.ExecuteDeleteAsync(ct);
|
||||
// [W1 Mig 69 — S161] GĐ2 Kế hoạch ký kết HĐ — mirror nhánh trên (site 3/3).
|
||||
n += await db.ContractSigningPlanLevelOpinions
|
||||
.Where(o => levelIds.Contains(o.ApprovalWorkflowLevelId)
|
||||
&& !db.ContractSigningPlans.IgnoreQueryFilters().Any(p => p.Id == o.ContractSigningPlanId))
|
||||
.ExecuteDeleteAsync(ct);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SolutionErp.Domain.ApprovalWorkflowsV2;
|
||||
using SolutionErp.Domain.ContractSigningPlans;
|
||||
using SolutionErp.Domain.Contracts;
|
||||
using SolutionErp.Domain.Contracts.Details;
|
||||
using SolutionErp.Domain.Forms;
|
||||
@ -141,5 +142,17 @@ public interface IApplicationDbContext
|
||||
// Phase 11 P11-B Wave 1 (Mig 42) — Số dư phép theo năm (NV × LoạiPhép × Năm).
|
||||
DbSet<LeaveBalance> LeaveBalances { get; }
|
||||
|
||||
// [W1 Mig 69 — S161] GĐ2 "Kế hoạch ký kết HĐ" (ContractSigningPlan) — 7 bảng.
|
||||
// Workflow V2 ApplicableType = ContractSigningPlan = 10 (`ApprovalWorkflow.cs:66`).
|
||||
// Mã phiếu "KHKK/{YYYY}/{Seq:D3}" atomic qua `WorkflowAppCodeSequences` DÙNG CHUNG (:136),
|
||||
// KHÔNG bảng sequence riêng.
|
||||
DbSet<ContractSigningPlan> ContractSigningPlans { get; }
|
||||
DbSet<ContractSigningPlanLine> ContractSigningPlanLines { get; }
|
||||
DbSet<ContractSigningPlanDossierItem> ContractSigningPlanDossierItems { get; }
|
||||
DbSet<ContractSigningPlanLevelOpinion> ContractSigningPlanLevelOpinions { get; }
|
||||
DbSet<ContractSigningPlanAttachment> ContractSigningPlanAttachments { get; }
|
||||
DbSet<ContractSigningPlanChangelog> ContractSigningPlanChangelogs { get; }
|
||||
DbSet<ContractSigningPlanApproval> ContractSigningPlanApprovals { get; }
|
||||
|
||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
namespace SolutionErp.Application.ContractSigningPlans.Services;
|
||||
|
||||
// [W1 Mig 69 — S161 2026-07-29] Atomic codegen mã phiếu "Kế hoạch ký kết HĐ" (GĐ2)
|
||||
// — mirror IPurchaseEvaluationCodeGenerator.
|
||||
// Format anh chốt @S161: KHKK/{YYYY}/{Seq:D3} (VD: KHKK/2026/001, KHKK/2026/002).
|
||||
// - Sequence per-năm qua bảng WorkflowAppCodeSequences DÙNG CHUNG (per-prefix row,
|
||||
// IApplicationDbContext) — KHÔNG bảng sequence riêng (spec W1 §②-9, #8-CẮT spec cũ).
|
||||
// - Seq reset đầu năm tự nhiên (key Prefix "KHKK/{YYYY}" mới).
|
||||
// Caller: W2 Submit (gen lúc trình duyệt, KHÔNG lúc tạo nháp — mirror quyết spec cũ).
|
||||
public interface IContractSigningPlanCodeGenerator
|
||||
{
|
||||
// Gen mã atomic — transaction SERIALIZABLE chống race (mirror PE/Contract codegen).
|
||||
Task<string> GenerateAsync(CancellationToken ct = default);
|
||||
}
|
||||
Reference in New Issue
Block a user