85 lines
6.1 KiB
Markdown
85 lines
6.1 KiB
Markdown
# 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**.
|