Files
solution-erp/.claude/workflows/runs/2026-08-08-S182-khkk-awf-mirror-ncc/sub-implementer-backend-0.md
2026-08-08 01:54:54 +07:00

6.9 KiB
Raw Blame History

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.md MỤ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 MigrationId 20260806070242
  • W0.2 boot API 1 lần → verify 8 row KHKK-N1..8 type-10 IsActive=1
  • W0.3 dotnet test SolutionErp.slnx baseline TƯƠI → ghi run.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 --connection vào SolutionErp (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ên SolutionErp_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-Process pid 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-548 cho phép).
  • Seeder: SeedKhkkGroupWorkflowsAsync DbInitializer.cs:549, idempotent PER-CODE :610 if (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.md mụ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ối var 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 (grep KHKK-N trong 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 :339 cũ "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-337 vốn đã per-Code.

W1b — file MỚI ContractSigningPlanWorkflowGuards.cs + gọi 3 site — DONE

  • File mới: src/Backend/SolutionErp.Application/ContractSigningPlans/ContractSigningPlanWorkflowGuards.cspublic 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ánh awId != 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ƯỚC LoadStepsAsync :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êm using 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á-3 CreateContractFromSigningPlanFeatures.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ánh awId != 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)