6b1e2d9220
[CLAUDE] Tests: Chunk F — K7 Mig 31 Approver F2 service regression + delete deprecated Drafter F2 tests
...
Sub-task 1: Fix broken references
- Tests reading removed User.AllowDrafterSkipToFinal prop -> delete entire test methods (semantic deprecated, no value)
- 3 deleted: SkipToFinal_DrafterAllowed_SetsPointerToFinalLevel + SkipToFinal_DrafterDenied_NonAdmin_Throws + SkipToFinal_AdminBypass_Succeeds
Sub-task 2: Add 3 Approver F2 service tests (PurchaseEvaluationWorkflowServiceReturnModeTests)
- ApproveV2_SkipToFinal_AdminTickFlag_SetsPhaseDaDuyet (happy path)
- ApproveV2_SkipToFinal_FlagOff_NonAdmin_ThrowsConflictException (denied)
- ApproveV2_SkipToFinal_FlagOff_Admin_BypassesFlagCheck (admin bypass)
Pattern reusable: SeedApproverF2WorkflowAsync 2 Step x 2 Level cookie-cutter
(Implementer memory Pattern 11 S22 SeedWorkflowAsync). PE init Phase=ChoDuyet
+ pointer Step 0 Cap 1. TestApplicationDbContext SQLite. Add EntityFrameworkCore
using for ToListAsync queries on PEL/PEA/Changelog audit assertions.
Verify:
- dotnet build SolutionErp.slnx 0 err 2 pre-existing DocxRenderer warn
- dotnet test SolutionErp.slnx 104 PASS (58 Domain + 46 Infra, 3 deleted + 3 added cancel out, baseline preserved)
- 3 Approver F2 tests verified individually PASS
Plan K Chunk F test-after carry per Phase 9 UAT mode bro confirm.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-14 23:41:26 +07:00
40f64c6b32
[CLAUDE] PE-Workflow: UAT S22+1 — disable cả 3 button khi không quyền + BE guard
...
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m29s
User UAT feedback: "Nếu đã không được quyền thao tác thì ko được quyền thao tác
hết tất cả các hành động" — trước đây chỉ "Duyệt" disabled, "Trả lại" + "Từ chối"
vẫn enabled (design intent S17 cũ).
FE 2 app mirror (PeWorkflowPanel.tsx):
- `isDisabled = blockedByV2Level` (drop `isForwardApprove &&` qualifier)
- Tooltip update "mới thao tác được (Duyệt / Trả lại / Từ chối)"
- Comment refresh ghi UAT S22+1 spec + cross-ref BE EnsureCanRejectV2Async
BE defense-in-depth (PurchaseEvaluationWorkflowService.cs):
- Helper mới `EnsureCanRejectV2Async` mirror FE actorInV2Level logic:
Skip silent khi admin/V1/non-ChoDuyet/no actor/no pointer. Throw
ForbiddenException khi V2 + ChoDuyet + actor != currentLevel.ApproverUserId.
- Invoke ở top Reject branch (cover cả TuChoi + Trả lại sub-branches).
- Chặn request forge: non-approver gọi PATCH /transitions direct sẽ 403.
Test (test-before §7 — security guard critical algorithm):
- ReturnMode tests existing 7/7 vẫn PASS (a2.Id = currentLevel approver, guard accept)
- +1 NEW test `Reject_NonApprover_V2_Throws_ForbiddenException` — outsider
Drafter role gọi Reject phiếu V2 → throw + Phase không mutate
Verify:
- dotnet test SolutionErp.slnx — 104/104 PASS (+1 guard regression)
Δ: 103 → 104
- npm run build × 2 app — pass (482ms + 583ms)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-13 21:46:51 +07:00
215b1e036a
[CLAUDE] Tests: Plan C task 1-3 — Service per-NV Allow* test catch-up (S21 t4-t5 Mig 28-29)
...
14 test cover 3 helper sửa lớn S21 t4-t5 (test-after UAT backlog):
Task 1+2 — PurchaseEvaluationWorkflowServiceReturnModeTests.cs (7 test):
- ApplyReturnModeAsync Drafter allowed/denied/admin bypass (3 test mode flag)
- OneLevel happy path (peer review chain in same Step)
- OneLevel admin bypass (override disabled flag)
- skipToFinal Drafter allowed/denied/admin bypass (3 test per-user F2)
Task 3 — PurchaseEvaluationDraftGuardTests.cs (7 test):
- Drafter scope: DangSoanThao + TraLai → return (2 test)
- F3 Approver scope: ChoDuyet + flag on + actor match → return
- F3 Approver scope: ChoDuyet + flag off → ConflictException
- F3 Approver scope: ChoDuyet + flag on + actor mismatch → ForbiddenException
- Admin bypass ChoDuyet + flag off → return
- DaDuyet any caller → ConflictException (terminal phase)
InternalsVisibleTo: expose PurchaseEvaluationDraftGuard internal helper cho test.
Finding: skipToFinal Service mutate Phase=ChoDuyet TRƯỚC validate user flag.
Throw chặn SaveChanges nên DB không persist nhưng in-memory dirty. Note trong
test — không refactor scope catch-up (defer S22+).
Verify:
- dotnet test SolutionErp.slnx — 103/103 PASS (58 Domain + 45 Infra)
Δ: 89 → 103 (+14: ReturnMode 7 + Guard 7)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-13 21:14:03 +07:00
dbda37eb30
[CLAUDE] Tests: Plan C task 4 — regression test #44 silent 403 (Authorize policy ApprovalWorkflowsV2)
...
5 reflection-based tests verify ApprovalWorkflowsV2Controller Authorize policy
split (gotcha #44 fix `f77ea38` S18):
- class-level [Authorize] (any authenticated), NO Policy
- GET Overview inherits class-level (no action policy)
- POST Create + DELETE + PATCH user-selectable require Policy="Workflows.Create"
Pattern reusable: catch future regression nếu ai add Policy lên class-level
hoặc GET action → test fail ngay, không cần UAT reproduce silent 403.
Add ProjectReference Api → Infrastructure.Tests cho reflection access.
Verify:
- dotnet test SolutionErp.slnx — 89/89 PASS (58 Domain + 31 Infra = 26+5 #44 )
Δ: 84 → 89 (+5)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-13 21:05:25 +07:00
de0088742f
[CLAUDE] PurchaseEvaluation: Chunk A — BE guard target TraLai/TuChoi BẮT BUỘC decision=Reject + 3 regression test
...
Defense-in-depth chặn FE inconsistency (gotcha #45 — Session 21 turn 3).
Bug pattern: button "← Trả lại" trong PeWorkflowPanel.tsx gửi decision=Approve
khi target=TraLai do `isReject` local var thiếu nhánh TraLai → BE skip Reject
branch → enter APPROVE STEP → ApproveV2Async UPSERT opinion = "đã duyệt" +
advance Cấp. User UAT thấy: "Trả về nhưng hệ thống vẫn duyệt".
BE guard:
- Service `TransitionAsync` thêm early check sau set isAdmin/isSystem
- targetPhase ∈ {TraLai, TuChoi} && decision != Reject → throw ConflictException
- Boundary protection cho mọi caller tương lai (API client / mobile / cron)
Tests (Infra suite +3):
- TransitionAsync_TargetTraLai_WithApproveDecision_Throws_AndDoesNotMutateState
- TransitionAsync_TargetTuChoi_WithApproveDecision_Throws_AndDoesNotMutateState
- TransitionAsync_TargetTraLai_WithRejectDecision_SetsPhaseTraLai (happy path)
+ NoOpNotificationService stub reusable cho future PE service tests
Verify:
- dotnet test SolutionErp.slnx → 84 PASS (58 Domain + 26 Infra = +3 from 81 baseline)
- Build pass (0 err, 2 warn CS8602 pre-existing DocxRenderer)
Pending Chunk B: FE fix PeWorkflowPanel.tsx isReject + dialog isSendBack
mirror 2 app (fe-admin + fe-user) — sync với BE guard rule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-13 09:41:14 +07:00
dbb0089e28
[CLAUDE] Drastic refactor: flat workflow Phòng × Cấp + Migration 21 (Chunk A)
...
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m18s
User chốt drastic refactor — bỏ phase enum hoàn toàn, dùng ChoDuyet=10
đơn nhất + currentStepIndex tracking. Workflow flat list (Phòng × Cấp ×
Approvers). Mỗi PE/HĐ pin WorkflowDefinitionId chạy hết quy trình đó.
Schema (Migration 21 `RefactorWorkflowToFlatModel`):
- Phase enum +ChoDuyet=10 (PE + Contract). Legacy 2-9 + 98 deprecated.
- WorkflowStep + DepartmentId Guid? (FK Restrict) + PositionLevel int?
(PE + Contract — mirror).
- PE/Contract + CurrentWorkflowStepIndex int? + RejectedAtStepIndex int?
- DROP table PurchaseEvaluationWorkflowStepInnerSteps (Mig 18)
- DROP table WorkflowStepInnerSteps (Mig 20)
- DROP column ContractDeptApproval.InnerStepId (Mig 20)
- DROP column PEDeptApproval.InnerStepId (Mig 18)
- DROP filtered indexes (Mig 19/20) + restore simple unique
(TargetId, Phase, Dept, Stage) non-filtered
Service rewrite (PE + Contract WorkflowService.TransitionAsync):
- Phase transitions: DangSoanThao → ChoDuyet (Drafter trình, init idx=0)
- ChoDuyet → ChoDuyet (advance idx per approve)
- ChoDuyet → DaDuyet/DaPhatHanh (idx >= steps.Count → terminal)
- ChoDuyet → DangSoanThao (Trả lại — save RejectedAtStepIndex)
- ChoDuyet → TuChoi (Từ chối — khoá vĩnh viễn)
- DangSoanThao + RejectedAtStepIndex → ChoDuyet jump-back to saved idx
- Approver match: actor.Dept == step.Dept AND actor.PositionLevel >=
step.PositionLevel (OR-of-many cùng cấp/dept = pass) OR
Approvers.Any(Kind=User AND id match) OR
Approvers.Any(Kind=Role AND actorRoles contains)
- Admin role bypass policy. Last step done → gen mã HĐ (Contract only)
App CQRS:
- WorkflowStepDto + WorkflowStepInput drop InnerStep, add DepartmentId
+ PositionLevel fields. PE + Contract mirror.
Tests rewrite:
- DROP PeNStageApprovalTests.cs (6 test) + ContractNStageApprovalTests.cs
(6 test) + PeTwoStageApprovalTests.cs (7 test) — legacy N-stage/2-stage
no longer applicable
- UPDATE PeWorkflowAdminTests signature to new flat input
- 96 → 77 test pass (drop 19 legacy)
Reference Domain entities removed:
- WorkflowStepInnerStep (Contract)
- PurchaseEvaluationWorkflowStepInnerStep (PE)
- DTOs WorkflowStepInnerStepDto / CreateWorkflowStepInnerStepInput per module
Memory `feedback_drastic_refactor_scope.md` validated: drastic refactor
done in dedicated session với context fresh, scope ~5h actual (planned ~8-10h
with 2x buffer).
Verify:
- dotnet build SolutionErp.slnx 0 error
- dotnet ef database update Mig 21 LocalDB applied OK
- dotnet test 77 pass (54 Domain + 23 Infra)
- 3-file rule: Migration .cs + Designer.cs + Snapshot updated
Pending Chunk B: FE Designer flat UI (PeWorkflowsPage + WorkflowsPage).
Pending Chunk C: FE PeWorkflowPanel + workflow timeline display.
Pending Chunk D: Docs + Skill + Memory + session log.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-08 12:04:51 +07:00
0d776987e4
[CLAUDE] PE workflow 3-button Duyệt/Trả lại/Từ chối (Task 4)
...
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m6s
User chỉ thị thay 2-button hiện tại bằng 3 hành động rõ ràng:
- Duyệt = forward phase tiếp theo
- Trả lại = về DangSoanThao + Drafter sửa → workflow tự jump tới phase
đã reject (smart reject Mig 16 pattern + clear N-stage rows)
- Từ chối = phiếu khoá hoàn toàn (Phase=TuChoi → 17 handler Mig 16 lock
edit). Drafter phải tạo phiếu mới.
Domain (PurchaseEvaluationPolicy.cs):
- NccOnly + NccWithPlan: thêm (X → TuChoi) transition cho mọi phase
trung gian (ChoPurchasing/ChoCCM/ChoCEODuyetNCC/ChoDuAn/ChoCEODuyetPA)
với roles của phase đó. Trước đây chỉ DangSoanThao → TuChoi (Drafter).
- FromDefinition expand: mỗi step (trừ DangSoanThao) thêm
(step.Phase → TuChoi) với roles của step.
Service (PurchaseEvaluationWorkflowService.cs):
- Reject branch tách 2 case:
* target=TuChoi → giữ nguyên (KHÔNG override + KHÔNG set
RejectedFromPhase + KHÔNG clear N-stage rows). Phiếu khoá vĩnh viễn.
* target khác (thường DangSoanThao) → smart reject (set
RejectedFromPhase + force DangSoanThao + clear N-stage rows).
FE (PeWorkflowPanel.tsx, fe-admin + fe-user mirror):
- next.phases render 3 button rõ ràng:
* "✓ Duyệt → <label>" brand (forward)
* "← Trả lại (về Drafter sửa)" red (target=DangSoanThao + isSendBack)
* "✗ Hủy / Từ chối" red (target=TuChoi)
- Decision logic: target=TuChoi || isSendBack → Reject (2), else Approve (1)
- Dialog confirm:
* Title rõ theo loại hành động
* Cancel case: warning red "Phiếu sẽ bị khoá hoàn toàn"
* SendBack case: hint amber "Phiếu sẽ về Đang soạn thảo, Drafter sửa
rồi trình lại — workflow tự jump tới phase này"
Tests update + add 1 test mới:
- Reject_Sets_RejectedFromPhase_And_Forces_DangSoanThao →
Reject_To_DangSoanThao_Sets_RejectedFromPhase_TraLai (rename + change
target từ TuChoi → DangSoanThao để test Trả lại pattern)
- + Reject_To_TuChoi_Locks_Permanently_No_RejectedFromPhase (NEW test
Từ chối — phase=TuChoi + RejectedFromPhase null)
- NStage_Reject_Clears_InnerStep_Rows_At_Phase: target TuChoi →
DangSoanThao (test Trả lại + clear N-stage rows pattern)
Verify:
- dotnet build 0 error
- dotnet test 95 → **96 pass** (+1 test mới Từ chối)
- npm build fe-admin + fe-user pass
Pending Task 2: Sample data seed N-stage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-07 19:25:44 +07:00
7c0772acca
[CLAUDE] Tests: Contract N-stage approval 6 test mirror PE (Chunk D)
...
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m1s
ContractNStageApprovalTests.cs (NEW, 6 test) cover N-stage logic Mig 20
mirror PeNStageApprovalTests pattern:
1. NStage_FirstInner_NV_Approve_Blocks_Phase_Transition
NV cấp 1 → 1 row InnerStepId set, phase chưa đổi.
2. NStage_All_3_Levels_Sequential_Pass_Allow_Phase_Transition
NV → PP → TP duyệt lần lượt → 3 rows + phase chuyển.
3. NStage_TP_Bypass_Skips_Lower_Levels_Same_Dept
TP có CanBypassReview → 1 transition tạo 3 rows (NV+PP IsBypassed,
TP exact match).
4. NStage_Wrong_Department_Throws_Forbidden
Actor dept khác inner step's dept → ForbiddenException.
5. NStage_Reject_Clears_InnerStep_Rows_At_Phase
NV approve → 1 row. Admin reject → DangSoanThao + RejectedFromPhase
set + N-stage rows cleared.
6. LegacyFallback_NoInnerSteps_Uses_2Stage_Logic
Contract không pin WorkflowDefinitionId → fallback hardcoded Standard
policy → no inner steps → legacy 2-stage Stage=Review row.
Phase pair DangKiemTraCCM → DangTrinhKy + role CostControl khớp
Standard.Transitions (DangGopY → DangDamPhan trong test ban đầu fail
vì policy chỉ cho [Drafter, DeptManager]; switched to phase pair work).
Helper SeedWorkflowDefinitionAsync 2 step adjacent (DangGopY + DangDamPhan)
+ SeedContractAsync với Project + Supplier seed cho FK.
FakeChangelogService + FakeContractCodeGenerator stubs (no-op cho tests
không cần verify changelog/codegen path).
Verify: 89 → **95 test pass** (54 Domain + 41 Infra: 17 codegen + 6 PE WF
versioning + 6 PE 2-stage + 6 PE N-stage + 6 Contract N-stage).
Pending Chunk E: API check (Workflows controller likely auto-bind via DTO,
skip nếu OK).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-07 19:07:32 +07:00
3d76c6bc0c
[CLAUDE] Tests: PE N-stage workflow approval (6 test) + IdentityFixture extend (Chunk D)
...
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
PeNStageApprovalTests.cs (NEW, 6 test) cover N-stage logic Mig 18:
1. NStage_FirstInner_NV_Approve_Blocks_Phase_Transition
NV.PRO duyệt cấp 1 → 1 row InnerStepId set, phase chưa đổi (còn 2 cấp).
2. NStage_All_3_Levels_Sequential_Pass_Allow_Phase_Transition
NV → PP → TP duyệt lần lượt → 3 rows + phase chuyển. Order asc enforce.
3. NStage_TP_Bypass_Skips_Lower_Levels_Same_Dept
TP có CanBypassReview → 1 transition tạo 3 rows (NV+PP IsBypassed=true,
TP exact match). Audit chuẩn.
4. NStage_Wrong_Department_Throws_Forbidden
Actor dept khác inner step's dept → ForbiddenException.
5. NStage_Reject_Clears_InnerStep_Rows_At_Phase
NV approve → 1 row. Reject → DangSoanThao + RejectedFromPhase set +
N-stage rows cleared (resume sẽ approve lại).
6. LegacyFallback_NoInnerSteps_Uses_2Stage_Logic
PE không pin WorkflowDefinitionId → service fallback hardcoded policy →
no inner steps → legacy 2-stage Stage=Review/Confirm logic kick in.
IdentityFixture.CreateUserAsync extend +PositionLevel? param (default null
cho admin/system user).
Helper SeedWorkflowDefinitionAsync: tạo definition với 2 steps adjacent
(ChoPurchasing có inner steps + ChoCCM next) — đủ cho FromDefinition build
transition policy guard pass actor role Procurement.
Verify: 83 → **89 test pass** (54 Domain + 35 Infra: 17 codegen + 6 PE WF
versioning + 6 PE 2-stage + 6 PE N-stage). 0 fail.
Pending Chunk E: API endpoints (PATCH /users/{id}/position-level + DTO
extend in PeWorkflowsController bind tự động).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-07 18:23:59 +07:00
8353fe87c0
[CLAUDE] Tests: Chunk E6 — 6 test 2-stage approval (PE) + IdentityFixture helper
...
Đóng "Tests Phase 3 mini cần UserManager DI helper" defer từ session 8.
IdentityFixture (Common/IdentityFixture.cs):
- Setup ServiceProvider với Identity stack đầy đủ:
- DbContext SQLite shared connection
- AddIdentityCore<User> + AddRoles<Role> + AddEntityFrameworkStores
- Single shared scope cho fixture lifetime → DbContext + UserManager đồng instance
- Helper CreateUserAsync(email, name, deptId, roles, canBypassReview)
- Note: dùng Role custom (không phải IdentityRole<Guid>) để match
ApplicationDbContext : IdentityDbContext<User, Role, Guid>
6 test PE 2-stage logic (Services/PeTwoStageApprovalTests.cs):
- NV_Review_Blocks_Phase_Transition (đóng bug anh Kiệt — chính xác)
- TPB_Confirm_After_NV_Review_Allows_Transition (happy path 2-stage)
- NV_With_BypassReview_Allows_Transition_With_IsBypassed_True (bypass NV)
- Admin_Skips_TwoStage_Logic_Entirely (admin bypass)
- Reject_Sets_RejectedFromPhase_And_Forces_DangSoanThao (smart reject)
- Resume_After_Reject_Jumps_Back_To_RejectedPhase (jump-back logic)
Stub FakeNotificationService — best effort path không cần verify.
Note: tests cho Contract + Budget 2-stage skip — logic identical PE, ROI thấp.
Pattern PeTwoStageApprovalTests reusable nếu cần test riêng tương lai.
Total: 54 Domain + 29 Infra (17 codegen + 6 PE WF Application + 6 PE 2-stage)
= **83 test pass** (+6 mới).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-04 13:52:43 +07:00
b874743081
[CLAUDE] Docs+Tests: chốt final session 5 — 77 test (Phase 3 mini PE WF) + 3 gotcha CI + 8 doc updates
...
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m21s
Final close session 5 — bao gồm:
==== Tests Phase 3 mini (NEW) ====
tests/SolutionErp.Infrastructure.Tests/Application/PeWorkflowAdminTests.cs
- 6 test CreatePeWorkflowDefinitionCommandHandler:
- First version → IsActive=true, Version=1, ActivatedAt set
- Second version same Code → auto-increment v2 + deactivate v1 (atomic)
- Different EvaluationType (A vs B) → independent active state
- Persists steps ordered by Order field
- Persists approvers per step
- Third version → v1 + v2 deactivate, v3 active
Total tests: 71 → 77 pass / ~2s (54 Domain + 23 Infra).
Skip Phase 3 full (UpsertOpinion + Budget link validation) — cần
Identity UserManager DI helper, defer session sau.
==== 3 gotcha CI mới (#39 #40 #41 ) ====
- #39 act_runner github.com TCP timeout 21s → manual checkout fix (run #108/#109 fail, #110 pass)
- #40 npm junction cache `tsc not found` after Move-Item — rolled back, hypothesis nested junctions
trong node_modules disrupt .bin/ paths. TODO debug session sau với robocopy hoặc act_runner cache.host
- #41 Gitea Actions paths-ignore behavior — workflow file change vẫn trigger (correct), commit
MD-only skip 100% (verify 512880c → no run #113 )
+ Checklist debug bug mới items 18-20 referencing 3 gotcha trên.
==== Doc updates (8 file) ====
- STATUS.md: header Phase 8 update + 3 row Recently Done CI fixes + cumulative test 71→77
- HANDOFF.md: TL;DR + CI optimize section + Phase status + gotcha count 38→41
- migration-todos.md: Phase 8 §E updated với Phase 3 mini done + CI fixes
- rules.md §7 Testing: rewrite full — stack + test pyramid + quy tắc bổ sung mỗi feature +
workflow user end-of-task (`dotnet test` local trước push) + CI gate behavior
- architecture.md §11: update test pyramid + phased priority + CI optimization sub-section
(3 fix manual checkout / path filter / npm cache rollback) + tốc độ deploy table
- gotchas.md: + #39 #40 #41 đầy đủ (triệu chứng + nguyên nhân + fix + reference)
- ef-core-migration SKILL: Phase 8 update note thêm CI fixes + 77 test
- CLAUDE.md root: test count 71→77 + folder structure + CI/CD pipeline 3 fix section
- memory project_solution_erp.md: session 5 summary + workflow user mới
- session log 2026-04-29-2300-chot-final-ci-tests-gotchas.md (NEW — 9 section detail)
==== Skill audit cron ====
`solution-erp-skill-audit-monthly` next fire 2026-05-01 (2 ngày sau).
Cron survives across sessions (setup commit b904a25 ). Khi fire sẽ:
- Cross-check 6 skill với STATUS/gotchas/migration-todos
- Auto-refresh stale + đề xuất add/archive cho human approve
- Log vào docs/changelog/skill-audit-2026-05.md
- ABORT nếu repo dirty
==== Verify ====
- dotnet test SolutionErp.slnx → 77 pass / ~2s (54 Domain + 23 Infra)
- git status clean sau commit này
- CI: commit này chứa code (test + workflow) → trigger CI test gate
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-04-29 23:43:42 +07:00
df5988b7a9
[CLAUDE] Tests Phase 2: Code generator format + sequence tests (SQLite in-memory)
...
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m16s
Phase 2 — chống regression code generator. 17 test mới integration với
DB thật (SQLite in-memory) tổng cộng 71 test pass < 3 giây.
Test project:
- tests/SolutionErp.Infrastructure.Tests/ (xUnit + FluentAssertions + EF SQLite 10)
- ProjectReference SolutionErp.Infrastructure (transitively get Application + Domain)
- Added vào SolutionErp.slnx
Test fixtures:
- Common/SqliteDbFixture.cs:
- SQLite ":memory:" + shared connection + EnsureCreated() từ DbContext model
- TestApplicationDbContext subclass — override OnModelCreating replace
'nvarchar(max)' → 'TEXT' (SQLite không support max keyword)
- FixedDateTime stub IDateTime cho deterministic year boundary test
Test files:
- Services/ContractCodeGeneratorTests.cs (10 test):
- Format per ContractType (5 type × Project scope) — RG-001 spec
- Framework HĐ (NguyenTacNCC + NguyenTacDV) → year scope thay vì project
- Sequence increment per prefix (3 calls → /01, /02, /03)
- Different prefixes (project / supplier) → independent sequences
- Year change (2026 → 2027) → reset sequence vì prefix khác
- PersistsSequenceRow LastSeq verification
- Services/PurchaseEvaluationCodeGeneratorTests.cs (7 test):
- Format A/B (DuyetNcc → 'A', DuyetNccPhuongAn → 'B')
- Seq là 3-digit padded (001..012)
- Type A và B sequence độc lập trong cùng năm
- Year boundary reset cả A và B
CI gate update (.gitea/workflows/deploy.yml):
- Step "Run integration tests (Infrastructure)" thêm sau Domain tests
- TRX log saved riêng (infra-tests.trx)
- Cả 2 step đều exit non-zero → no deploy
Verify local:
- dotnet test SolutionErp.slnx → Total tests: 71 (54 Domain + 17 Infra) / Passed: 71 / 2.1s
- dotnet build SolutionErp.slnx → 0 error
Phase 3+ pending:
- Application handler tests (CQRS) với EF InMemory hoặc SQLite (~1 ngày)
- API smoke tests qua WebApplicationFactory (~0.5 ngày)
- FE Vitest cho lib utility (~0.5 ngày)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-04-29 13:29:06 +07:00