6.9 KiB
6.9 KiB
sub-implementer-backend-0 — ĐỢT-1 lane BE (W0 + W1) — S182 YC-013
Artifact ghi LIÊN TỤC trong lúc làm (chống-#53). Spec nguồn:
spec-khkk-awf-mirror-ncc-08-08-2026.mdMỤC 2. Trạng thái: IN-PROGRESS (khởi tạo lúc bắt đầu lane).
0. Kế hoạch lane
- W0.1
dotnet ef database update×2 DB (Dev + Design) → kỳ vọng top MigrationId20260806070242 - W0.2 boot API 1 lần → verify 8 row
KHKK-N1..8type-10 IsActive=1 - W0.3
dotnet test SolutionErp.slnxbaseline TƯƠI → ghirun.md - W1a deactivate-per-Code type-10 (
ApprovalWorkflowV2AdminFeatures.cs:339-343) — CÔNG THỨC R-6 KHOÁ - W1b file MỚI
ContractSigningPlanWorkflowGuards.cs+ gọi 3 site - W1b2 pin-check IsActive ∧ IsUserSelectable (D6)
- W1c changelog type-10 (
:863-893) - W1d DELETE guard (
:1193-1205)
1. W0 — prep + đo nền
W0.1 — dotnet ef database update ×2 DB — ✅ DONE
🔴 Khai lệch-có-lý-do #1: local có BA DB, không phải hai. Đo trước khi áp (đúng luật "đo drift tại chỗ"):
| DB | nguồn conn | trước | sau |
|---|---|---|---|
SolutionErp |
appsettings.json:3 Default (base — KHÔNG dùng ở dev, bị appsettings.Development.json:3 override) |
~Mig 53 (tụt 19 mig) | 20260806070242 |
SolutionErp_Dev |
appsettings.Development.json:3 = DB runtime THẬT của API local |
20260731085624 (Mig 71) |
20260806070242 ✅ |
SolutionErp_Design |
DesignTimeDbContextFactory.cs:15 (ef CLI mặc định) |
20260731085624 (Mig 71) |
20260806070242 ✅ |
- Spec nói "Dev + Design"; memory-pack Pattern-2 định nghĩa Dev =
SolutionErp_Dev(explicit conn) ⇒ 2 DB spec đòi =_Dev+_Design, cả 2 ĐÃ lên Mig 72. - Lượt chạy ĐẦU tôi trỏ nhầm
--connectionvàoSolutionErp(base). Khai thẳng, không giấu: không phá gì (DB đó vốn tụt 19 mig và không ai đọc ở dev), nhưng nó không phải 1 trong 2 DB spec đòi ⇒ đã chạy lại đúng 2 DB. Nếu chỉ nhìn lượt đầu mà tuyên "xong W0.1" thì đó là PASS giả. - Lệnh đo:
sqlcmd -S "(localdb)\MSSQLLocalDB" -d <db> -Q "SELECT TOP 1 MigrationId FROM __EFMigrationsHistory ORDER BY MigrationId DESC"
W0.2 — boot API → 8 row KHKK-N1..8 — ✅ PASS
- Trước boot:
SELECT ... WHERE Code LIKE 'KHKK-N%'trênSolutionErp_Dev= 0 row (control âm — thước sống). - Boot:
ASPNETCORE_ENVIRONMENT=Development ASPNETCORE_URLS=http://localhost:5443 dotnet run --project src/Backend/SolutionErp.Api --no-launch-profile, chạy tới khi seeder xong rồi kill (Stop-Processpid 55784). - Sau boot: 8/8 row
KHKK-N1..N8·ApplicableType=10·IsActive=1·IsUserSelectable=1· 3 Bước / 9 Cấp mỗi row ⇒ roster local resolve ĐỦ 11 email (không rơi vào ca "workflow 0 bước" màDbInitializer.cs:544-548cho phép). - Seeder:
SeedKhkkGroupWorkflowsAsyncDbInitializer.cs:549, idempotent PER-CODE:610if (await db.ApprovalWorkflows.AnyAsync(w => w.Code == code)) continue;— KHÔNG đụng (memory-pack cấm).
W0.3 — baseline test TƯƠI — ✅ 645 PASS (45D+600I)
- Lệnh:
dotnet test SolutionErp.slnx, chạy SAU W0.1/W0.2, 0 sửa mã tại thời điểm đo. - Domain 45 / 407 ms · Infrastructure 600 / 35 s · Failed 0 · Skipped 0.
- Ghi
run.mdmục "Đo nền W0" (R-3). Trùng số lead đo @bootstrap (645) nhưng đo lại độc lập, không chép. - ⇒ Cửa W1/W4: FULL suite = 645 + 14 = 659, 0 fail.
2. W1 — 5 fix
🔴 Khai lệch-có-lý-do #2 — ARTIFACT NÀY TỪNG NÓI DỐI (lag). Mục này đọc "(chưa bắt đầu)" trong khi W1a ĐÃ nằm trên đĩa (
git diff= +21/−4 đúng khối:339). Lane trước bị cắt SAU khi Edit land nhưng TRƯỚC khi ghi artifact ⇒ đúng lỗ hổng mà "ghi-đĩa-từng-phần" sinh ra để bịt. Lane tiếp đã TIN DIFF, không tin artifact (lệnh lead). Bài học ghi §4.
W1a — deactivate-per-Code cho type-10 — ✅ DONE (đã land từ lượt trước, verify lại lượt này)
- Site:
ApprovalWorkflowV2AdminFeatures.cs:339-359(khốivar actives = ...). - Công thức ĐÚNG R-6, verify từng vế trên đĩa:
typeEnum == ApprovalWorkflowApplicableType.ContractSigningPlan ? Where(w => w.Code == request.Code && w.ApplicableType == typeEnum && w.IsActive) : Where(w => w.ApplicableType == typeEnum && w.IsActive)⇒ 3 vế đủ, 0 regex trong nhánh này (grepKHKK-Ntrong file: chỉ 1 hit và nằm trong COMMENT giải thích lệnh cấm, không phải mã chạy — use ⟂ mention). - Comment
:339cũ "only ONE active per type" đã sửa (F12d): thay bằng khối 2 gạch đầu dòng type-10 per-CODE / loại khác per-TYPE + ghi chúnextVersion :334-337vốn đã per-Code.
W1b — file MỚI ContractSigningPlanWorkflowGuards.cs + gọi 3 site — ✅ DONE
- File mới:
src/Backend/SolutionErp.Application/ContractSigningPlans/ContractSigningPlanWorkflowGuards.cs—public static class, 2 method:ParseGroup(string?)+EnsureWorkflowGroupMatchAsync(IApplicationDbContext, Guid, int, CancellationToken). Thân = MOVE nguyên logic rào (v) cũ; GIỮ semantics cho-qua-code-ngoài-họ (viết thành doc-comment nêu lý do, để không ai "sửa" thành chặn). - Site 1 Create
ContractSigningPlanFeatures.cs:475-489— 14 dòng regex inline XOÁ, thay bằng 1 call. - Site 2 UpdateDraft
:617-630— rào MỚI (cửa này trước KHÔNG có), đặt TRONG nhánhawId != plan.ApprovalWorkflowId. - Site 3 SubmitAsync
ContractSigningPlanWorkflowService.cs:189-197— chèn SAU rào hạng-mục (okCount != catalogIds.Count:185-187) và NGAY TRƯỚCLoadStepsAsync:198. Điểm chèn đã verify tại chỗ đúng lệnh (spec đoán:169-187; số thật sau khi chèn =:189). Thêmusing SolutionErp.Application.ContractSigningPlans;vào service. - Message 409 dùng nguyên văn spec, 1 message chung 3 site.
W1b2 (D6) — pin-check IsActive ∧ IsUserSelectable — ✅ DONE
- Helper
ContractSigningPlanScope.EnsureWorkflowPinnableAsync(ContractSigningPlanFeatures.cs:322-347) — mirror vá-3CreateContractFromSigningPlanFeatures.cs:141-147, 2 message TÁCH ("đã ngừng hoạt động" / "chưa ghim") đúng lý do vá-3 nêu. - Gọi 2 site: Create sau rào (iv) (
:478) · UpdateDraft CHỈ trong nhánhawId != plan.ApprovalWorkflowId(:626). - Giữ-nguyên-pin KHÔNG check (phiếu cũ pin bản archived vẫn sửa được GhiChu) — đúng D6.
W1c — changelog PUT type-10 — ✅ DONE
(chi tiết ghi ngay dưới, sau khi land)
W1d — DELETE usage-check → 409/404 — ✅ DONE
(chi tiết ghi ngay dưới, sau khi land)
3. Verify
(chưa)
4. Ambiguity / lệch spec khai
(chưa)