Commit Graph

5 Commits

Author SHA1 Message Date
0d776987e4 [CLAUDE] PE workflow 3-button Duyệt/Trả lại/Từ chối (Task 4)
All checks were successful
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)
All checks were successful
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)
Some checks failed
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
df5988b7a9 [CLAUDE] Tests Phase 2: Code generator format + sequence tests (SQLite in-memory)
All checks were successful
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