Files
solution-erp/.claude/workflows/runs/2026-07-29-S161-khkk-w1-schema/sub-implementer-backend-0.md
2026-07-29 19:32:44 +07:00

85 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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` · spec `spec-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`):
1. `Configurations/ContractSigningPlanAttachmentConfiguration.cs`
- FileName 500 IsRequired · StoragePath 1000 IsRequired · ContentType 200 IsRequired (spec `:134-137`;
RỘNG hơn PE 255/500/100 — khuôn `ProposalAttachmentConfiguration.cs:15-17`) · Note 1000 · Purpose `HasConversion<int>()`
- FK **Cascade** Plan; `ContractSigningPlanDossierItemId` chỉ `HasIndex` (KHÔNG FK — tránh MULTIPLE CASCADE PATHS)
- `HasQueryFilter(!IsDeleted)` — AuditableEntity
2. `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)
3. `Configurations/ContractSigningPlanApprovalConfiguration.cs`
- Comment 1000 · From/ToPhase/Decision `HasConversion<int>()`
- IX `(PlanId, ApprovedAt)` (twin PE `:168`) + IX `ApprovalWorkflowLevelId`
- `ApprovalWorkflowLevelId` loose-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
⚠️ 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-153` block 7 DbSet + chú thích "mã KHKK qua `WorkflowAppCodeSequences` (:136) DÙNG CHUNG, KHÔNG bảng sequence riêng".
- `Infrastructure/Persistence/ApplicationDbContext.cs:5` +using · `:129-136` 7 `public DbSet<...> => Set<...>()`.
- Config tự nạp qua `ApplyConfigurationsFromAssembly` (`ApplicationDbContext.cs` cuối `OnModelCreating`) — 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`) · **0** `AddColumn/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-137` 100%: 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_Dev` TRƯỚ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.`
- `sqlcmd` Dev: `sys.tables WHERE is_ms_shipped=0` = **96** (89→96, +7) · `LIKE 'ContractSigningPlan%'` = **7**.