6.1 KiB
sub-implementer-backend-0 — W1 KHKK lane BE (RELAUNCH-CẮT-GỌT, tiếp lane chết #53)
Ghi TỪNG MỤC ngay sau khi xong mục đó (lane trước chết trước khi kịp ghi). Run:
2026-07-29-S161-khkk-w1-schema· specspec-wave-w1-schema-designer-29-07-2026.md§② 2→9.
§0 — AUDIT mục "✅ ĐÃ XONG" (trước khi làm tiếp)
| Vật | Đo | Verdict |
|---|---|---|
Domain/ContractSigningPlans/ |
8 file (7 entity + ContractSigningPlanPhase.cs) |
PASS |
ContractSigningPlanPhase |
:10-14 = DangSoanThao=1 / ChoDuyet=2 / DaDuyet=3 / TraLai=98 / TuChoi=99 |
PASS khớp spec :16 |
DossierItemKind |
ContractSigningPlanDossierItem.cs:7-12 = MauVatLieu=1/Shopdrawing=2/Khac=99 |
PASS |
DossierItemStatus |
ContractSigningPlanDossierItem.cs:17-23 = ChuaNop=1..TvgsBac=4 (KHÔNG 0) |
PASS — vá C2 |
ApprovalWorkflowApplicableType.ContractSigningPlan = 10 |
ApprovalWorkflow.cs:66 (append-only, sau TravelRequest = 9) |
PASS |
Header +DepartmentId Guid? (C5) |
ContractSigningPlan.cs:21 |
PASS |
Lines +ContractId Guid? (C6) |
ContractSigningPlanLine.cs:25 |
PASS |
| Changelog ĐỦ 4 cột (C1) | ContractSigningPlanChangelog.cs:29,30,34,36 EntityType/EntityId/UserName/FieldChangesJson |
PASS |
| Configuration đã có | ContractSigningPlanConfiguration + ...Line + ...DossierItem + ...LevelOpinion = 4/7 |
đúng như brief |
| UNIQUE filtered Lines | ContractSigningPlanLineConfiguration.cs:22-24 (PlanId,SupplierId) + HasFilter("[IsDeleted] = 0") |
PASS gotcha #57 |
| UNIQUE LevelOpinions | ContractSigningPlanLevelOpinionConfiguration.cs:36 (PlanId,LevelId) IsUnique KHÔNG filter |
PASS (parity 7 twin, UPSERT) |
→ 0 lệch spec ⇒ KHÔNG sửa gì phần đã xong.
MỤC 1 — 3 Configuration còn lại ✅
3 file MỚI (khuôn = 4 config đã có + twin PE PurchaseEvaluationConfiguration.cs:156-210):
Configurations/ContractSigningPlanAttachmentConfiguration.cs- FileName 500 IsRequired · StoragePath 1000 IsRequired · ContentType 200 IsRequired (spec
:134-137; RỘNG hơn PE 255/500/100 — khuônProposalAttachmentConfiguration.cs:15-17) · Note 1000 · PurposeHasConversion<int>() - FK Cascade Plan;
ContractSigningPlanDossierItemIdchỉHasIndex(KHÔNG FK — tránh MULTIPLE CASCADE PATHS) HasQueryFilter(!IsDeleted)— AuditableEntity
- FileName 500 IsRequired · StoragePath 1000 IsRequired · ContentType 200 IsRequired (spec
Configurations/ContractSigningPlanChangelogConfiguration.cs- Summary 1000 (spec, PE để 500) · ContextNote 2000 · UserName 200 · FieldChangesJson
nvarchar(max) - IX
(PlanId, CreatedAt)+(PlanId, EntityType)(index twin C1) - BaseEntity ⇒ KHÔNG HasQueryFilter (parity PE Changelog)
- Summary 1000 (spec, PE để 500) · ContextNote 2000 · UserName 200 · FieldChangesJson
Configurations/ContractSigningPlanApprovalConfiguration.cs- Comment 1000 · From/ToPhase/Decision
HasConversion<int>() - IX
(PlanId, ApprovedAt)(twin PE:168) + IXApprovalWorkflowLevelId ApprovalWorkflowLevelIdloose-Guid KHÔNG FK (nếu Restrict → admin xoá Level nổ 500, vì 3 site dọn dẹp chỉ biết họ*LevelOpinions)- BaseEntity ⇒ KHÔNG HasQueryFilter
- Comment 1000 · From/ToPhase/Decision
⚠️ Cả 7 bảng con đều FK Cascade 1-hop từ Plan ⇒ 0 multiple-cascade-path.
MỤC 2 — DbSets ×7 ✅
Application/Common/Interfaces/IApplicationDbContext.cs:3+using SolutionErp.Domain.ContractSigningPlans;·:144-153block 7 DbSet + chú thích "mã KHKK quaWorkflowAppCodeSequences(:136) DÙNG CHUNG, KHÔNG bảng sequence riêng".Infrastructure/Persistence/ApplicationDbContext.cs:5+using ·:129-1367public DbSet<...> => Set<...>().- Config tự nạp qua
ApplyConfigurationsFromAssembly(ApplicationDbContext.cscuốiOnModelCreating) — 0 dòng đăng ký tay.
MỤC 4 (làm sớm, trước build) — MenuKeys ✅
Domain/Identity/MenuKeys.cs:179 — thêm ĐÚNG 1 dòng KeHoachKyKet, vào All (const sẵn :41, KHÔNG key mới).
⇒ Program.cs foreach All × Actions tự sinh 4 policy KeHoachKyKet.{Read,Create,Update,Delete}.
Build sau mục 1+2+4
dotnet build SolutionErp.slnx → Build succeeded. 0 Warning(s) / 0 Error(s) (56.77s, 6 project).
MỤC 3 — Mig 69 AddContractSigningPlans ✅
Lệnh: dotnet ef migrations add AddContractSigningPlans --project src/Backend/SolutionErp.Infrastructure --startup-project src/Backend/SolutionErp.Api --output-dir Persistence/Migrations
3-file rule (gotcha #17) — git status chứng:
?? 20260729122015_AddContractSigningPlans.cs(22.059 B)?? 20260729122015_AddContractSigningPlans.Designer.cs(264.515 B)M ApplicationDbContextModelSnapshot.cs
Nội dung đo (grep, KHÔNG đọc-mắt):
grep -c CreateTable= 7 · Down = 7 DropTable (:350-368) · 0AddColumn/DropColumn/AlterColumn/Sql/RenameColumn⇒ 0 ALTER bảng cũ.- UNIQUE filtered Lines
:301-306:(ContractSigningPlanId, SupplierId)unique: true, filter: "[IsDeleted] = 0"✅ gotcha #57 - UNIQUE LevelOpinions
:287-291:(ContractSigningPlanId, ApprovalWorkflowLevelId)unique: true(KHÔNG filter — đúng parity twin) - UNIQUE MaKeHoach
:325-330: filter[MaKeHoach] IS NOT NULL - FK: Plan→ApprovalWorkflows Restrict
:47· LevelOpinions→ApprovalWorkflowLevels Restrict:201· 6 con→Plan Cascade (:76,108,139,171,207,238) - maxLength khớp spec
:134-137100%: MaKeHoach 50 · GhiChu/ContextNote 2000 · Name 500 · Note 1000 · TvgsName 200 · Summary 1000 · SignedByFullName 200 NOT NULL · FileName 500 / StoragePath 1000 / ContentType 200 · Comment(LevelOpinion) 2000 / Comment(Approval) 1000 · HoSoLink 1000. ChỉFieldChangesJson=nvarchar(max):124(cố ý, JSON tự do).
Apply 2 DB:
migrations list --connection …SolutionErp_DevTRƯỚC apply: chỉ 1 Pending = Mig 69 ⇒ 0 drift (khác S133 phải catch-up).- Dev:
Applying migration '20260729122015_AddContractSigningPlans'. Done. - Design (default factory):
Applying migration '20260729122015_AddContractSigningPlans'. Done. sqlcmdDev:sys.tables WHERE is_ms_shipped=0= 96 (89→96, +7) ·LIKE 'ContractSigningPlan%'= 7.