[CLAUDE] Docs+Skill: chốt Session 14 wrap-up — PE 3-button workflow + Task 2 defer
Session 14 (2026-05-07) docs/skill update:
STATUS.md:
- Last updated + Phase summary count (95→96 test, 20 mig, 57 bảng, 41 gotcha)
- Recently Done row Session 14 chi tiết (3-button + Task 2 in-progress + DesignTime/Runtime DB gotcha)
HANDOFF.md:
- TL;DR Session 14 prepend với 1 commit + Task 2 defer
- 5 cảnh báo Session 15+: TraLai phase orphan / Task 2 sample seed / DesignTime
vs Runtime DB / Budget N-stage defer / schema-diagram §17-19 defer
migration-todos.md: Phase 9 + Session 14 block 4 sub-task done + 2 defer task
Session log NEW `2026-05-07-2500-3-button-workflow.md`:
- Bối cảnh + spec 3-button (Duyệt/Trả lại/Từ chối) + implementation chi tiết
(Domain policy expand + Service tách reject + FE button + dialog warning)
- Tests update (95→96 với +1 NEW Reject_To_TuChoi_Locks_Permanently)
- Task 2 in-progress: DesignTime vs Runtime DB gotcha + API exit 255 sớm
- Plan organization sau S14
Skill ef-core-migration:
- description + heading: 17→20 migration
- Bảng migration history thêm Mig 18-19 (PE) + Mig 20 (Contract)
- Section MỚI "N-stage workflow pattern (Mig 18-20)" — architecture decision
với filtered unique trick + per-module migration packaging guideline
- Phase 8 update: 83→96 test breakdown
Skill contract-workflow:
- Section MỚI "Phase 9+ done (Mig 18-20 — Session 12/13/14)":
* N-stage workflow PE + Contract (entity + filtered unique split + service
refactor + tests + FE Designer + UsersPage cấp + API)
* PE 3-button approval (Duyệt/Trả lại/Từ chối) Session 14
* Defer: Budget N-stage / Phase TraLai=98 orphan
CLAUDE.md root: 16→20 migration + 55→57 bảng + 83→96 test
docs/rules.md §7: Phase 9 active 83→96 test
Verify: dotnet test 96 pass + npm build (skip — pure docs/skill update).
🎉 Session 14 wrap-up complete. Pushed 1 task (3-button) + Task 2 defer.
Cumulative since session start (13h17): 13 commit (1 button removal +
6 PE N-stage Chunk A-F + 5 Contract N-stage Chunk A,B,C,D,F + 1 3-button).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -314,6 +314,54 @@ POST /api/contracts/{id}/transitions { targetPhase: 3, decision: 1, comment: "..
|
||||
- [x] **Lock edit guards** 17 handler khi Phase != DangSoanThao
|
||||
- [x] **CanBypassReview toggle** per User — admin UI + audit IsBypassed=true
|
||||
|
||||
## Phase 9+ done (Mig 18-20 — Session 12/13/14)
|
||||
|
||||
### N-stage workflow (PE Mig 18-19 + Contract Mig 20)
|
||||
|
||||
- [x] **N-stage approval** Phòng × PositionLevel (NV/PP/TP) cấu hình động per
|
||||
WorkflowStep cha. Mỗi inner step = 1 cấp duyệt (Order asc, sequential).
|
||||
- [x] **PositionLevel enum** Domain/Identity (NV=1, PP=2, TP=3) + `User.PositionLevel int?`
|
||||
- [x] **InnerStep entity** + ALTER `*DepartmentApproval.InnerStepId Guid?` per module
|
||||
- [x] **Filtered unique split** (Mig 19 cho PE / gộp Mig 20 cho Contract):
|
||||
legacy `WHERE InnerStepId IS NULL` (Stage Review/Confirm) + N-stage
|
||||
`WHERE InnerStepId IS NOT NULL` (per inner step)
|
||||
- [x] **Service refactor** TransitionAsync — load InnerSteps eager + reject
|
||||
branch clear N-stage rows + dept approval block split: hasInnerSteps→N-stage
|
||||
logic / else→legacy 2-stage. Match firstPending Order asc + (exact level
|
||||
OR canBypass + level≥). Bypass batch upsert NV+PP+TP cùng dept ≤ actor.
|
||||
- [x] **6 test PE N-stage** + **6 test Contract N-stage** (`PeNStageApprovalTests`,
|
||||
`ContractNStageApprovalTests`). Pattern reusable.
|
||||
- [x] **FE Designer** (PeWorkflowsPage + WorkflowsPage) sub-section "Cấp duyệt nhỏ
|
||||
trong phòng" drag-list { Phòng × Cấp + required }
|
||||
- [x] **UsersPage cột Cấp** + cycle button null→1→2→3→null
|
||||
- [x] **API** `PATCH /users/{id}/position-level`
|
||||
|
||||
**Backward compat 100%:** workflow no InnerSteps → service fallback legacy 2-stage
|
||||
Mig 16. Data legacy InnerStepId=null vẫn enforce unique cũ qua filtered index.
|
||||
|
||||
### PE 3-button approval (Session 14 — `0d77698`)
|
||||
|
||||
UI distinguishment 3 hành động cho approver:
|
||||
- **Duyệt** = forward (decision=Approve)
|
||||
- **Trả lại** = về DangSoanThao + Drafter sửa (decision=Reject + target=DangSoanThao
|
||||
→ smart reject pattern Mig 16 + clear N-stage rows + jump-back)
|
||||
- **Từ chối** = Phase=TuChoi (decision=Reject + target=TuChoi → phiếu khoá
|
||||
vĩnh viễn 17 handler Mig 16 lock edit, Drafter phải tạo phiếu mới)
|
||||
|
||||
**Domain policy expand:** NccOnly + NccWithPlan + FromDefinition thêm `(X → TuChoi)`
|
||||
transition cho mọi phase trung gian (trước chỉ DangSoanThao→TuChoi).
|
||||
|
||||
**Service Reject branch tách 2 case:**
|
||||
- target=TuChoi → giữ nguyên (KHÔNG override + KHÔNG set RejectedFromPhase + KHÔNG clear N-stage)
|
||||
- target khác (DangSoanThao) → smart reject (force DangSoanThao + RejectedFromPhase + clear N-stage)
|
||||
|
||||
### Defer
|
||||
|
||||
- Budget N-stage — cần migration `AddBudgetVersionedWorkflow` trước (Budget
|
||||
hardcoded `BudgetPolicy.Default`, chưa có versioned WorkflowDefinition).
|
||||
- Phase TraLai = 98 (Domain enum từ S11+++++++) — orphan, KHÔNG wire (user
|
||||
Session 14 chốt không cần phase trung gian).
|
||||
|
||||
## Tier 4+ (còn thiếu / future)
|
||||
|
||||
- [ ] Warning notification 20% SLA (`SlaWarningSent` flag đã có)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: ef-core-migration
|
||||
description: Tạo/sửa/revert EF Core 10 migration cho SOLUTION_ERP. Dùng khi thêm entity mới, thay đổi schema, rollback migration, debug DesignTimeDbContextFactory fail. Đã có 16 migration sẵn (Init → AddTwoStageDeptApprovalAndSmartReject). Snapshot + Designer + Migration 3-file rule bắt buộc commit đủ.
|
||||
description: Tạo/sửa/revert EF Core 10 migration cho SOLUTION_ERP. Dùng khi thêm entity mới, thay đổi schema, rollback migration, debug DesignTimeDbContextFactory fail. Đã có 20 migration sẵn (Init → AddContractWorkflowInnerStepsAndAlterDeptApprovalUnique). Snapshot + Designer + Migration 3-file rule bắt buộc commit đủ.
|
||||
when-to-use:
|
||||
- "thêm migration"
|
||||
- "EF Core migration"
|
||||
@ -16,7 +16,7 @@ when-to-use:
|
||||
|
||||
> **Context:** .NET 10 + EF Core 10 + SQL Server. DbContext: `ApplicationDbContext` ở `Infrastructure/Persistence/`. Startup: `SolutionErp.Api`.
|
||||
|
||||
## Migration history (17 migration hiện có)
|
||||
## Migration history (20 migration hiện có)
|
||||
|
||||
| # | Name | Tables added / changed |
|
||||
|---|---|---|
|
||||
@ -37,8 +37,29 @@ when-to-use:
|
||||
| **15** | **`AddPurchaseEvaluationDepartmentOpinions`** | **1 bảng `PurchaseEvaluationDepartmentOpinions` (UNIQUE PEId+Kind, max 1 row mỗi PeDepartmentKind per phiếu — Phê duyệt/Ccm/MuaHang/SmPm)** |
|
||||
| **16** | **`AddTwoStageDeptApprovalAndSmartReject`** | **3 bảng `Contract/PurchaseEvaluation/Budget DepartmentApprovals` (UNIQUE TargetId+Phase+Dept+Stage cho 2-stage NV.Review → TPB.Confirm per phòng × phase) + 4 ALTER (`Users.CanBypassReview` bit cho NV bypass + 3 `RejectedFromPhase` int cho smart reject jump-back). Phase 9 — đóng bug "NV duyệt được hết phase" anh Kiệt (FDC) báo. Logic 2-stage trong PurchaseEvaluationWorkflowService chỉ áp PE; HĐ + Budget defer.** |
|
||||
| **17** | **`AddManualBudgetFieldsToPeAndContract`** | **4 ALTER (PE + HĐ × `BudgetManualName` nvarchar(200) + `BudgetManualAmount` decimal(18,2)) — manual budget fallback khi user không link Budget entity approved. KHÔNG XOR với BudgetId, cả 2 cùng null OK. Carry-forward `pe.BudgetManualName/Amount → contract` ở `CreateContractFromEvaluation`. Phase 9 — Session 11 (2026-05-07).** |
|
||||
| **18** | **`AddPeWorkflowInnerStepsAndPositionLevel`** | **N-stage workflow PE — 1 CREATE TABLE `PurchaseEvaluationWorkflowStepInnerSteps` (Order, DepartmentId, PositionLevel, Name, SlaDays, IsRequired) + 2 ALTER (`Users.PositionLevel int?` 1=NV/2=PP/3=TP + `PEDeptApproval.InnerStepId Guid?`) + 3 IX + FK Cascade Step / Restrict Dept+InnerStep. Phase 9+ — Session 12 (2026-05-07).** |
|
||||
| **19** | **`AlterPeDeptApprovalsUniqueFilteredForInnerSteps`** | **Filtered unique split: drop UNIQUE cũ Mig 16 → 2 filtered: legacy `WHERE InnerStepId IS NULL` (Stage Review/Confirm) + N-stage `WHERE InnerStepId IS NOT NULL` (per inner step). Tránh conflict 2 inner step cùng dept Stage=Confirm. Session 12.** |
|
||||
| **20** | **`AddContractWorkflowInnerStepsAndAlterDeptApprovalUnique`** | **N-stage workflow Contract mirror PE Mig 18+19 — GỘP 1 migration: CREATE TABLE `WorkflowStepInnerSteps` + ALTER `ContractDeptApproval.InnerStepId` + DropIndex old + Recreate filtered legacy/N-stage + 3 IX + FK. Session 13 (2026-05-07).** |
|
||||
|
||||
Total: **55 bảng** dbo + `__EFMigrationsHistory` (Mig 17 không thêm bảng, chỉ +4 cột). Xem `docs/database/schema-diagram.md` ERD đầy đủ.
|
||||
Total: **57 bảng** dbo + `__EFMigrationsHistory` (Mig 17 alter cột; Mig 18 + Mig 20 thêm 1 bảng/mỗi; Mig 19 chỉ alter index). Xem `docs/database/schema-diagram.md` ERD đầy đủ.
|
||||
|
||||
## N-stage workflow pattern (Mig 18-20 — Session 12-13)
|
||||
|
||||
Architecture decision đáng ghi cho session sau:
|
||||
|
||||
**Pattern:** Mỗi WorkflowStep cha (= 1 phase) cấu hình động chuỗi InnerSteps con theo Department × PositionLevel với Order sequential. Approver cần khớp DeptId + PositionLevel + Order tiếp theo chưa duyệt. CanBypassReview cho user level cao hơn skip cấp dưới cùng dept.
|
||||
|
||||
**Per-module migration** (PE first, mirror sang Contract sau):
|
||||
- PE: 2 migration tách (Mig 18 schema + Mig 19 alter index) — vì index issue phát hiện sau khi schema đã commit
|
||||
- Contract: 1 migration GỘP (Mig 20) — gộp CREATE TABLE + ALTER + DropIndex + Recreate filtered. Cleaner cho mirror.
|
||||
|
||||
**Filtered unique trick:** legacy 2-stage rows (Mig 16, Stage=Review/Confirm) + N-stage rows (per InnerStep) cùng table `*DepartmentApprovals` → cần unique split:
|
||||
- `UX_*_Phase_Dept_Stage WHERE InnerStepId IS NULL` (legacy, prevent duplicate Review/Confirm cùng phase × dept)
|
||||
- `UX_*_Phase_InnerStep WHERE InnerStepId IS NOT NULL` (N-stage, prevent duplicate per inner step)
|
||||
|
||||
**Backward compat 100%:** workflow no InnerSteps configured → service fallback legacy 2-stage logic Mig 16. Data legacy InnerStepId=null vẫn enforce unique cũ qua filtered index.
|
||||
|
||||
**Budget defer:** Budget chưa có versioned WorkflowDefinition entity (hardcoded `BudgetPolicy.Default`). Để mirror N-stage Budget cần migration `AddBudgetVersionedWorkflow` trước (4 bảng + ALTER `Budget.WorkflowDefinitionId?`). Defer cho user quyết riêng.
|
||||
|
||||
**Phase 7 pending:**
|
||||
- `AddPePaymentTermFields` — tách `PurchaseEvaluations.PaymentTerms` JSON thành 6 column riêng (Session 11+++++ đã thay UI Workspace `<Textarea>` JSON → `<Select>` 8 preset, BE schema vẫn nvarchar(max). Migration tách field defer cho khi BE cần aggregate/filter từng terms riêng)
|
||||
@ -50,7 +71,7 @@ Total: **55 bảng** dbo + `__EFMigrationsHistory` (Mig 17 không thêm bảng,
|
||||
|
||||
**Phase 8 update (2026-04-29 Session 5):**
|
||||
- Migration 15 `AddPurchaseEvaluationDepartmentOpinions` — 1 bảng riêng (UNIQUE PEId+Kind), max 4 row mỗi phiếu cho 4 phòng ban (Phê duyệt/Ccm/MuaHang/SmPm). UPDATE in-place khi user đổi ý, audit qua Changelog.
|
||||
- Tests Phase 1-2-3mini-2stage live: `tests/SolutionErp.Domain.Tests/` (54 test policy state machine) + `tests/SolutionErp.Infrastructure.Tests/` (17 test code generator + 6 test PE WF versioning + 6 test PE 2-stage approval Session 9). **Total 83 test pass / ~3s**. CI fail → no deploy.
|
||||
- Tests Phase 1-2-3mini-2stage-Nstage live: `tests/SolutionErp.Domain.Tests/` (54 test policy state machine) + `tests/SolutionErp.Infrastructure.Tests/` (17 test code generator + 6 test PE WF versioning + 6 test PE 2-stage Session 9 + 6 PE N-stage Session 12 + 6 Contract N-stage Session 13 + 1 PE Reject Từ chối Session 14). **Total 96 test pass / ~3s**. CI fail → no deploy.
|
||||
- CI optimize 3 fix (29/04):
|
||||
- Manual checkout bypass github.com (gotcha #39) — fix TCP timeout 21s
|
||||
- Path filter docs-only skip (gotcha #41) — commit MD-only KHÔNG trigger CI
|
||||
|
||||
@ -50,7 +50,7 @@ Kiến trúc: **.NET 10 Clean Architecture + 2 React FE (admin + user) + SQL Ser
|
||||
- Audit fields: `CreatedAt`, `UpdatedAt`, `CreatedBy`, `UpdatedBy` (`BaseEntity`)
|
||||
- Soft delete: `IsDeleted`, `DeletedAt`, `DeletedBy` (`AuditableEntity`)
|
||||
- Migrations: `dotnet ef migrations add <Name> --project src/Backend/SolutionErp.Infrastructure --startup-project src/Backend/SolutionErp.Api`
|
||||
- **Hiện có 16 migration → 55 bảng** (Phase 9 — Migration 16 `AddTwoStageDeptApprovalAndSmartReject` — 3 bảng `*DepartmentApprovals` + `Users.CanBypassReview` + 3 `RejectedFromPhase` cho smart reject + 2-stage NV/TPB approval per dept)
|
||||
- **Hiện có 20 migration → 57 bảng** (Phase 9+ — Mig 18 `AddPeWorkflowInnerStepsAndPositionLevel` + Mig 19 `AlterPeDeptApprovalsUniqueFilteredForInnerSteps` + Mig 20 `AddContractWorkflowInnerStepsAndAlterDeptApprovalUnique`. N-stage workflow approval Phòng × PositionLevel cấu hình động per WorkflowStep cha. Mỗi inner step = 1 cấp duyệt sequential. Backward compat 100% với 2-stage Mig 16 qua filtered unique. PE 3-button Duyệt/Trả lại/Từ chối)
|
||||
|
||||
### Modules
|
||||
|
||||
@ -84,7 +84,7 @@ tests/
|
||||
└── Application/ (6 test - PeWorkflowDefinition versioning)
|
||||
```
|
||||
|
||||
**83 unit test pass** / ~3s. CI gate + path filter live.
|
||||
**96 unit test pass** / ~3s (54 Domain + 42 Infra: 17 codegen + 6 PE WF + 6 PE 2-stage + 6 PE N-stage S12 + 6 Contract N-stage S13 + 1 PE Reject Từ chối S14). CI gate + path filter live.
|
||||
|
||||
```bash
|
||||
dotnet test SolutionErp.slnx # chạy cả 2 test project
|
||||
|
||||
@ -1,6 +1,63 @@
|
||||
# HANDOFF — Brief 5 phút cho session tiếp theo
|
||||
|
||||
**Last updated:** 2026-05-07 (Session 13 — **Mirror N-stage Contract (Mig 20, 5 commit per-chunk + skip Chunk E auto-bind). Domain → App → Service → Tests +6 → FE Designer. 95 test pass. Budget defer cần versioned WF.**)
|
||||
**Last updated:** 2026-05-07 (Session 14 — **PE 3-button workflow Duyệt/Trả lại/Từ chối — Domain policy expand + Service tách reject 2 case + FE 3-button + 1 test mới = 96 pass. 1 commit `0d77698`. Task 2 sample seed defer (DesignTime vs Runtime DB gotcha + API exit sớm).**)
|
||||
|
||||
## TL;DR Session 14 (07/05 — PE 3-button approval workflow)
|
||||
|
||||
User chỉ thị thay 2-button approval (Duyệt + Reject mơ hồ) bằng **3 hành động rõ ràng** cho approver:
|
||||
- **Duyệt** = forward phase tiếp theo (decision=Approve)
|
||||
- **Trả lại** = về DangSoanThao + Drafter sửa (decision=Reject + target=DangSoanThao). Smart reject pattern Mig 16 + clear N-stage rows + Drafter resume jump-back tới phase đã reject.
|
||||
- **Từ chối** = phase=TuChoi (decision=Reject + target=TuChoi). Phiếu khoá vĩnh viễn (17 handler Mig 16 lock edit). Drafter phải tạo phiếu mới.
|
||||
|
||||
**1 commit (`0d77698`):**
|
||||
|
||||
- **Domain `PurchaseEvaluationPolicy.cs`**: NccOnly + NccWithPlan thêm `(X → TuChoi)` transition cho mọi phase trung gian (ChoPurchasing/ChoDuAn/ChoCCM/ChoCEODuyetPA/ChoCEODuyetNCC) với roles của phase đó. FromDefinition expand: mỗi step (trừ DangSoanThao) thêm (step.Phase → TuChoi) với roles step.
|
||||
- **Service** `PurchaseEvaluationWorkflowService.TransitionAsync` — Reject branch tách 2 case:
|
||||
```
|
||||
if (decision == Reject) {
|
||||
if (target != TuChoi) { // Trả lại
|
||||
RejectedFromPhase = fromPhase
|
||||
target = DangSoanThao // force
|
||||
clear N-stage rows tại fromPhase
|
||||
}
|
||||
// else target=TuChoi: giữ nguyên, KHÔNG set RejectedFromPhase, KHÔNG clear
|
||||
}
|
||||
```
|
||||
- **FE PeWorkflowPanel (admin + user mirror)**: render 3 button rõ:
|
||||
- "✓ Duyệt → <label phase>" brand
|
||||
- "← Trả lại (về Drafter sửa)" red khi `target=DangSoanThao && fromPhase != DangSoanThao`
|
||||
- "✗ Hủy / Từ chối" red khi `target=TuChoi`
|
||||
- Decision logic FE: `isReject = target=TuChoi || isSendBack`
|
||||
- **Dialog confirm**: title rõ theo loại, Cancel case warning đỏ "Phiếu sẽ bị khoá hoàn toàn", SendBack case hint amber "Phiếu về DangSoanThao, Drafter sửa rồi trình lại — workflow tự jump tới phase này".
|
||||
- **Tests update + add 1**:
|
||||
- rename `Reject_Sets_RejectedFromPhase_And_Forces_DangSoanThao` → `Reject_To_DangSoanThao_Sets_RejectedFromPhase_TraLai` (change target TuChoi→DangSoanThao)
|
||||
- NEW `Reject_To_TuChoi_Locks_Permanently_No_RejectedFromPhase` (Phase=TuChoi + RejectedFromPhase null)
|
||||
- update `NStage_Reject_Clears_InnerStep_Rows_At_Phase` target → DangSoanThao
|
||||
- **95 → 96 test pass** (+1 Từ chối).
|
||||
|
||||
**Task 2 sample seed in-progress (defer Session 15+):**
|
||||
|
||||
- Phát hiện gotcha: `DesignTimeDbContextFactory` hardcoded `SolutionErp_Design` connection — `dotnet ef database update` từ session 12-13 thực ra apply lên `_Design` DB, KHÔNG phải `_Dev` runtime DB. Khi user run API → DbInitializer auto-MigrateAsync apply lên `_Dev`.
|
||||
- Đã apply Mig 9-20 lên `SolutionErp_Dev` qua `dotnet ef database update --connection`.
|
||||
- Start API để DbInitializer auto-seed 30 demo user. API exit 255 sớm khi log buffer full (~100 lines) — seeding dở dang (chỉ seed Roles, chưa Users).
|
||||
- Defer Task 2 cho session sau. Cần: user manual `dotnet run` API 1 lần hoàn thành seed, hoặc Claude resume với output redirect to file.
|
||||
|
||||
## ⚠️ CẢNH BÁO Session 15+
|
||||
|
||||
1. **Phase TraLai = 98 (orphan)** — Domain enum đã có từ S11+++++++ nhưng KHÔNG dùng (user chốt Session 14 không cần phase trung gian, chỉ DangSoanThao + TuChoi). Để giữ enum không phá nhưng ko wire vào policy → orphan. Có thể remove migration sau (không gây hại).
|
||||
|
||||
2. **Task 2 sample seed pending**: 2 việc:
|
||||
- Update `Users.PositionLevel` (1=NV, 2=PP, 3=TP) cho 30 demo user đã seed (mapping email pattern: `tpb./ccm./pro./fin./act./equ./hra.` → 3 (TP), `pp.*` → 2 (PP), `nv./qs./` else → 1 (NV), `bod./pm./admin./huy.duong/chau.le` → null)
|
||||
- INSERT N-stage WorkflowDefinition v2 cho DuyetNcc với InnerSteps (PRO + CCM × 3 cấp NV/PP/TP)
|
||||
|
||||
3. **DesignTime vs Runtime DB distinction**: dev có 2 DB:
|
||||
- `SolutionErp_Design` — `dotnet ef migrations add/update` (DesignTimeDbContextFactory hardcode)
|
||||
- `SolutionErp_Dev` — runtime API (appsettings.Development.json)
|
||||
Khi muốn apply migrations lên Dev: `dotnet ef database update --connection "...SolutionErp_Dev..."` hoặc `dotnet run` API (DbInitializer auto-MigrateAsync).
|
||||
|
||||
4. **Budget N-stage defer** — chưa wire vì Budget chưa có versioned WorkflowDefinition. Cần migration `AddBudgetVersionedWorkflow` + `AddBudgetWorkflowInnerSteps`. User quyết riêng (feature mở rộng module lớn).
|
||||
|
||||
5. **schema-diagram §17-19 Mig 18-20** chưa update — defer cron audit 2026-06-01.
|
||||
|
||||
## TL;DR Session 13 (07/05 — Mirror N-stage workflow sang Contract)
|
||||
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
|
||||
> **Update rule:** trước khi bắt đầu 1 task → ghi row vào `🔥 In Progress`. Xong → chuyển sang `✅ Recently Done`.
|
||||
|
||||
**Last updated:** 2026-05-07 (Session 13 — **Mirror N-stage workflow sang Contract (Mig 20): Domain entity WorkflowStepInnerStep + ALTER ContractDeptApproval.InnerStepId + EF + Migration gộp 1 → App CQRS extend → ContractWorkflowService N-stage + legacy 2-stage fallback + smart reject reset → 6 test mới → FE WorkflowsPage Designer InnerSteps. 5 commit per-chunk (E API auto-bind skipped). PE-only first → giờ áp Contract.**)
|
||||
**Last updated:** 2026-05-07 (Session 14 — **PE 3-button workflow approval (Duyệt / Trả lại / Từ chối) — Domain policy expand `(X → TuChoi)` cho mọi phase trung gian + Service tách 2 reject case + FE 3-button rõ ràng + Dialog warning + 1 test mới. 1 commit `0d77698`. Task 2 sample seed in-progress (block on DesignTime vs Runtime DB).**)
|
||||
|
||||
## 📍 Phase hiện tại: **Phase 9 active — UAT** — **57 DB tables, 20 migrations, ~134 API endpoints, 32 FE pages. 95 unit test pass** (54 Domain + 41 Infra). 41 gotcha. 30 demo user. 6 skill. **5 PE display status** (Bản nháp / Đã gửi duyệt / Trả lại / Đã duyệt / Từ chối). **9 PE phase enum** (+TraLai = 98). **N-stage workflow** Phòng × PositionLevel (NV/PP/TP) cấu hình động per WorkflowStep cha — **Mig 18+19 (PE) + Mig 20 (Contract)**. Budget defer (cần versioned WF migration trước).
|
||||
## 📍 Phase hiện tại: **Phase 9 active — UAT** — **57 DB tables, 20 migrations, ~134 API endpoints, 32 FE pages. 96 unit test pass** (54 Domain + 42 Infra). 41 gotcha. 30 demo user. 6 skill. **5 PE display status** (Bản nháp / Đã gửi duyệt / Trả lại / Đã duyệt / Từ chối). **9 PE phase enum** (+TraLai = 98 — orphan, KHÔNG wire). **N-stage workflow** Phòng × PositionLevel (NV/PP/TP) cấu hình động per WorkflowStep cha — **Mig 18+19 (PE) + Mig 20 (Contract)**. Budget defer (cần versioned WF migration trước). **PE 3-button approval** (Duyệt forward / Trả lại smart-reject / Từ chối khoá phiếu).
|
||||
|
||||
### 🌐 Production URLs
|
||||
|
||||
@ -61,6 +61,7 @@
|
||||
|
||||
| Ngày | Ai | Task | Commit |
|
||||
|---|---|---|---|
|
||||
| 2026-05-07 | Claude | **🎯 SESSION 14 — PE 3-button workflow Duyệt/Trả lại/Từ chối + Task 2 sample seed in-progress** — User chỉ thị thay 2-button approval bằng 3 hành động rõ ràng cho approver: **Duyệt** (forward), **Trả lại** (về DangSoanThao + Drafter sửa, smart reject Mig 16 + clear N-stage rows + Drafter resume jump-back), **Từ chối** (Phase=TuChoi, phiếu khoá vĩnh viễn 17 handler Mig 16 lock edit, Drafter phải tạo phiếu mới). 1 commit (`0d77698`): Domain `PurchaseEvaluationPolicy.cs` NccOnly + NccWithPlan thêm `(X → TuChoi)` transition cho mọi phase trung gian (ChoPurchasing/ChoCCM/ChoDuAn/ChoCEODuyetPA/ChoCEODuyetNCC) với roles của phase. FromDefinition expand: mỗi step (trừ DangSoanThao) thêm (step.Phase → TuChoi) với roles step. Service `PurchaseEvaluationWorkflowService.TransitionAsync` — Reject branch tách 2 case: target=TuChoi giữ nguyên (KHÔNG override + KHÔNG set RejectedFromPhase + KHÔNG clear N-stage); target khác (DangSoanThao) → smart reject (force DangSoanThao + RejectedFromPhase + clear N-stage). FE PeWorkflowPanel (admin + user mirror): render 3 button rõ ràng "✓ Duyệt → X" brand / "← Trả lại (về Drafter sửa)" red / "✗ Hủy / Từ chối" red. Decision logic: target=TuChoi || isSendBack → Reject (2), else Approve (1). Dialog confirm: title rõ + Cancel case warning red "phiếu sẽ bị khoá hoàn toàn" + SendBack case hint amber "Phiếu về DangSoanThao, Drafter sửa rồi trình lại — workflow tự jump tới phase này". Tests: rename `Reject_Sets_RejectedFromPhase_And_Forces_DangSoanThao` → `Reject_To_DangSoanThao_Sets_RejectedFromPhase_TraLai` (target từ TuChoi → DangSoanThao). NEW `Reject_To_TuChoi_Locks_Permanently_No_RejectedFromPhase`. Update `NStage_Reject_Clears_InnerStep_Rows_At_Phase` target → DangSoanThao. **95 → 96 test pass** (+1 Từ chối). **Task 2 sample seed in-progress**: dotnet ef database update applied Mig 9-20 lên LocalDB SolutionErp_Dev (trước đó chỉ Mig 1-8 vì DesignTimeDbContextFactory hardcoded SolutionErp_Design ≠ runtime SolutionErp_Dev — gotcha tooling distinction). API start để DbInitializer auto-seed 30 demo user nhưng exit 255 sớm khi log buffer full → seed dở dang. Defer Task 2 cho session sau (cần guidance: seed manual SQL hoặc manual API run + sample N-stage workflow def + Update PositionLevel cho 30 users existing). | `0d77698` |
|
||||
| 2026-05-07 | Claude | **🎯 SESSION 13 — Mirror N-stage workflow sang Contract (Mig 20, 5 commit per-chunk + skip Chunk E API)** — User chỉ thị mirror N-stage từ PE sang Contract. Budget defer (cần versioned WF migration trước, hardcoded BudgetPolicy hiện tại chưa có WorkflowDefinition). 5 chunk per-commit (build + ef + test pass mỗi chunk): **Chunk A (`951ffa3`)** Domain entity `WorkflowStepInnerStep` (Domain/Contracts/) + nav WorkflowStep.InnerSteps + ALTER ContractDepartmentApproval.InnerStepId Guid? + EF config FK Cascade Step / Restrict Dept+InnerStep + **Migration 20** `AddContractWorkflowInnerStepsAndAlterDeptApprovalUnique` GỘP 1 (CREATE TABLE WorkflowStepInnerSteps + ALTER InnerStepId + DropIndex old + Recreate filtered legacy `WHERE InnerStepId IS NULL` + new filtered N-stage `WHERE InnerStepId IS NOT NULL` + 3 IX + 3 FK). **Chunk B (`04cf2a0`)** Application CQRS DTO — `WorkflowStepInnerStepDto` + extend `WorkflowStepDto` + GetWorkflowAdminOverview Include InnerSteps + DeptNames map + `CreateWorkflowStepInnerStepInput` + `CreateWorkflowStepInput` extend (default null backward compat) + Validator child rules + Handler atomic batch insert. **Chunk C (`e247b67`)** ContractWorkflowService refactor mirror PE — load definition InnerSteps eager, reject branch clear N-stage rows tại fromPhase, dept approval block split hasInnerSteps→N-stage logic / else→legacy 2-stage. N-stage flow giống PE: yêu cầu actor có DeptId+PositionLevel, match firstPending Order asc + (exact level OR canBypass + level≥), exact upsert 1 row InnerStepId, bypass batch upsert NV+PP+TP cùng dept ≤ actor (audit IsBypassed cho cấp dưới), recheck stillPending → BLOCK + log "duyệt cấp X (còn Y pending)". **Chunk D (`7c0772a`)** Tests 6 N-stage Contract mirror PE pattern + helper SeedWorkflowDefinitionAsync 2 step adjacent (DangGopY + DangDamPhan) + SeedContractAsync với Project + Supplier seed + FakeChangelogService + FakeContractCodeGenerator stubs. Bug fix: legacy fallback test ban đầu fail (Standard policy DangGopY → DangDamPhan chỉ cho [Drafter, DeptManager], không Procurement) → switched phase pair sang DangKiemTraCCM → DangTrinhKy + role CostControl khớp. Total 89 → **95 test pass**. **Chunk E SKIP** — WorkflowsController auto-bind `[FromBody] CreateWorkflowDefinitionCommand` record qua JSON, no code change cần. **Chunk F (current)** FE-Admin types/users.ts đã có PositionLevel const từ Session 12 reuse. WorkflowsPage Designer extend mirror PeWorkflowsPage Chunk F: InnerStepDto + EditInnerStep types + copyFromDefinition include + departmentsList query + sub-section "Cấp duyệt nhỏ trong phòng" drag-list { Phòng × Cấp + required } + button "+ Thêm cấp duyệt" emerald + payload include Order asc. Empty state hint fallback 2-cấp legacy. KHÔNG đụng fe-user (admin-only). Docs/Skill update. **Backward compat 100%**: workflow Contract no InnerSteps → fallback legacy 2-stage Mig 16. Data legacy InnerStepId=null vẫn enforce unique cũ qua filtered index. Defer Budget mirror cho session sau (cần migration `AddBudgetVersionedWorkflow` trước). | `951ffa3` (A) · `04cf2a0` (B) · `e247b67` (C) · `7c0772a` (D) · (current F) |
|
||||
| 2026-05-07 | Claude | **🎯 SESSION 12 — N-stage workflow approval Phòng × PositionLevel cấu hình động (PE-only first, 6 commit per-chunk + Mig 18+19)** — User yêu cầu mở rộng từ 2-stage Mig 16 (NV.Review/TPB.Confirm) sang N-stage cấu hình động: mỗi WorkflowStep cha (= 1 phase) có thể cấu hình chuỗi InnerSteps con theo Department × PositionLevel với Order sequential. Spec defaults chốt 6 câu (PositionLevel int 1=NV/2=PP/3=TP, sequential pure, bypass cùng dept TP skip NV+PP, smart reject reset N-stage rows về DangSoanThao, PE-only first, designer 1 sub-section InnerSteps). 6 chunk per-commit (build + ef + test pass mỗi chunk per `feedback_per_chunk_commit.md`): **Chunk A (`13ab533`)** Domain enum `PositionLevel` (NV/PP/TP) + entity `PurchaseEvaluationWorkflowStepInnerStep` + ALTER User.PositionLevel int? + ALTER PEDeptApprovals.InnerStepId Guid? + EF config + **Migration 18** `AddPeWorkflowInnerStepsAndPositionLevel` (1 CREATE TABLE + 2 ALTER + 3 index + FK Cascade Step / Restrict Dept/InnerStep). 3-file rule. **Chunk B (`0e56bd0`)** Application CQRS DTO — `PeWorkflowStepInnerStepDto` + extend `PeWorkflowStepDto` + `CreatePeWorkflowStepInnerStepInput` (default null backward compat existing PeWorkflowAdminTests) + Validator child rules + Handler atomic batch insert + UserDto +PositionLevel field + `SetUserPositionLevelCommand` mirror SetBypassReview. **Chunk C (`0c62e24`)** Service N-stage logic — **Migration 19** `AlterPeDeptApprovalsUniqueFilteredForInnerSteps` (filtered unique: legacy `WHERE InnerStepId IS NULL` + N-stage `WHERE InnerStepId IS NOT NULL`) cho phép multi-row cùng dept khác inner step. PurchaseEvaluationWorkflowService refactor: load definition InnerSteps eager + reject branch clear N-stage rows + dept block split hasInnerSteps→N-stage logic / else→legacy 2-stage. N-stage flow: yêu cầu actor có DeptId+PositionLevel, match firstPending (Order asc IsRequired) same dept + (exact level OR canBypass + level≥), exact match upsert 1 row InnerStepId, bypass batch upsert NV+PP+TP cùng dept ≤ actor level (audit IsBypassed cho cấp dưới skip), recheck stillPending → BLOCK + log "duyệt cấp X (còn Y pending)" / all done → fall through phase transition. Backward compat: workflow no InnerSteps fallback legacy + InnerStepId=null filter unique cũ vẫn enforce. **Chunk D (`3d76c6b`)** Tests N-stage 6 test mới (NV first blocks / 3-level sequential pass / TP bypass skips / wrong dept throws 403 / reject clears rows / legacy fallback no inner) + IdentityFixture extend `+positionLevel` arg + helper SeedWorkflowDefinitionAsync 2 step adjacent (ChoPurchasing+ChoCCM) cho FromDefinition build transition policy guard pass. Total 83→**89 test pass**. **Chunk E (`83ffabd`)** API `PATCH /users/{id}/position-level` mirror SetBypassReview pattern + body `{positionLevel:int?}` Authorize Users.Update. **Chunk F (current)** FE-Admin types/users.ts +positionLevel field + PositionLevel const + Label/Short maps. PeWorkflowsPage Designer extend: InnerStepDto type + EditInnerStep type + copyFromDefinition include + departmentsList query + sub-section "Cấp duyệt nhỏ trong phòng" per step card với drag-drop list { Phòng × Cấp + required checkbox } + button "+ Thêm cấp duyệt" (xanh emerald) + payload include innerSteps Order asc. UsersPage column "Cấp" badge NV/PP/TP emerald + action button cycle null→1→2→3→null call positionLevelMut PATCH. KHÔNG đụng fe-user (admin-only feature). Docs/Skill update. PE-only first. Backward compat 100%: workflow no InnerSteps + data legacy 2-stage rows không phá. | `13ab533` (A) · `0e56bd0` (B) · `0c62e24` (C) · `3d76c6b` (D) · `83ffabd` (E) · (current F) |
|
||||
| 2026-05-08 00:30 | Claude | **🎯 SESSION PHASE 2 WRAP-UP — B12-B14 PE detail polish iterate (3 commit FE-only sau wrap-up `6e7a6db`)** — User UAT iteration tiếp, áp rule strict verify khi rename/remove (lesson hotfix CI). 3 batch nhỏ: **B12 (`378c993`)** "Lưu" no-close (chỉ toast + invalidate, KHÔNG đóng workspace) + nút "Xóa phiếu" red bottom CHỈ Bản nháp (soft-delete `IsDeleted=true` qua AuditableEntity, không xóa hoàn toàn DB) + bỏ header bar workspace mode "Sửa header"/"Xóa"/"Đóng" (chuyển hết xuống bottom action bar) + Section 4 column header dùng `s.supplierName` thay `displayName` (NCC master) + Section 3 row chặn xóa NCC khi đã có quotes (`hasQuotes` computed) + tooltip "xóa báo giá trước". **B13 (`e320027`)** InfoTab `useEffect` watch `[autoEdit, canEdit, ev.id, ...]` → re-trigger edit mode khi pencil click phiếu khác (fix useState mount-time only) + sync values từ ev mới (tránh stale state) + Pencil "sáng lên" active state khi `editingRowId === p.id` (bg-brand-100 + text-brand-700 + ring-brand-300 + shadow-sm + tooltip cập nhật) + wire `editingRowId={autoEditHeader ? selectedId : null}` từ Workspace → PeListPanel. **B14 (`d2306b8`)** QuoteDialog bỏ checkbox "Chọn NCC này cho hạng mục" (consolidate winner ở Section 2.a NccSelectorRow, isSelected vẫn gửi BE giữ trạng thái cũ) + winner column Section 4 matrix highlight emerald (header `bg-emerald-50` + `✓ ` prefix + cells `bg-emerald-50 font-semibold` cho ENTIRE column, không chỉ cell có quote) + loading overlay full-screen QuoteDialog (`bg-white/70 backdrop-blur-sm` + spinner ring brand-600 + text "Đang lưu báo giá…"/"Đang xóa…") + NccSelectorRow inline spinner "Đang chọn NCC + sync cột giá Section 4…" + disable Hủy/Xóa/Lưu buttons khi `isSaving`. Verify: `npm run build` × 2 app pass mỗi commit · `dotnet test` 83 pass (KHÔNG regression). | `378c993` (B12) · `e320027` (B13) · `d2306b8` (B14) |
|
||||
|
||||
@ -157,6 +157,22 @@ Session log: `2026-04-28-chot-session-4-budget.md`.
|
||||
|
||||
## 📝 Phase 9 — UAT + Ops + carry over (Session 6+ active)
|
||||
|
||||
### ✅ Session 14 done (2026-05-07) — PE 3-button workflow Duyệt/Trả lại/Từ chối (1 commit)
|
||||
|
||||
User chỉ thị thay 2-button approval (Duyệt + Reject mơ hồ) bằng 3 hành động rõ:
|
||||
- Duyệt = forward
|
||||
- Trả lại = về DangSoanThao + Drafter sửa (smart reject Mig 16 + clear N-stage rows + Drafter resume jump-back)
|
||||
- Từ chối = Phase=TuChoi, phiếu khoá vĩnh viễn (17 handler Mig 16 lock edit)
|
||||
|
||||
- [x] **Domain `PurchaseEvaluationPolicy.cs`** — NccOnly + NccWithPlan thêm (X → TuChoi) transition cho mọi phase trung gian + FromDefinition expand step (trừ DangSoanThao) thêm (step.Phase → TuChoi).
|
||||
- [x] **Service** `PurchaseEvaluationWorkflowService.TransitionAsync` — Reject branch tách 2 case: target=TuChoi giữ nguyên (no override / no RejectedFromPhase / no N-stage clear). target khác (DangSoanThao) → smart reject pattern.
|
||||
- [x] **FE PeWorkflowPanel** (admin + user mirror) — render 3 button "✓ Duyệt → X" / "← Trả lại" / "✗ Hủy / Từ chối" + decision logic + dialog confirm với warning red (Cancel) / amber hint (SendBack).
|
||||
- [x] **Tests** — rename Reject test target TuChoi→DangSoanThao + NEW Reject_To_TuChoi_Locks_Permanently + update NStage_Reject_Clears target. **95 → 96 test pass**.
|
||||
|
||||
**Defer Session 15+:**
|
||||
- [ ] Task 2 sample seed N-stage (block trên DesignTime vs Runtime DB gotcha + API exit sớm khi DbInitializer seeding).
|
||||
- [ ] Phase TraLai = 98 enum orphan — có thể remove migration nếu cleanup, ko gây hại.
|
||||
|
||||
### ✅ Session 13 done (2026-05-07) — Mirror N-stage Contract (Mig 20, 5 commit per-chunk + skip Chunk E auto-bind)
|
||||
|
||||
User chỉ thị mirror N-stage từ PE sang Contract. Budget defer (cần migration `AddBudgetVersionedWorkflow` trước — hardcoded `BudgetPolicy.Default` chưa có WorkflowDefinition entity). Pattern reusable đầy đủ từ PE.
|
||||
|
||||
150
docs/changelog/sessions/2026-05-07-2500-3-button-workflow.md
Normal file
150
docs/changelog/sessions/2026-05-07-2500-3-button-workflow.md
Normal file
@ -0,0 +1,150 @@
|
||||
# Session 2026-05-07 (S14) — PE 3-button workflow Duyệt/Trả lại/Từ chối
|
||||
|
||||
**Dev:** Claude
|
||||
**Duration:** ~1h
|
||||
**Base commit:** `b06bdce` (sau Session 13 Contract N-stage mirror)
|
||||
**Final commit:** `0d77698` (+ Task 2 in-progress, không commit)
|
||||
|
||||
## Bối cảnh
|
||||
|
||||
Sau Session 11+++++++ user thêm Phase TraLai = 98 + FE label/badge. Session 12 bỏ qua wire BE TraLai. Session 14 này user chốt: KHÔNG cần Phase TraLai trung gian (orphan). Thay vào: 3-button approval rõ ràng.
|
||||
|
||||
User wording: "Duyệt Trả lại và Từ chối. Từ chối thì xem như phải làm phiếu mới (khóa hết chức năng). Trả lại → đc điều chỉnh → Gửi duyệt."
|
||||
|
||||
## Spec chốt
|
||||
|
||||
3 hành động cho approver:
|
||||
- **Duyệt** = forward phase tiếp theo (decision=Approve, target=next phase)
|
||||
- **Trả lại** = về DangSoanThao + Drafter sửa (decision=Reject, target=DangSoanThao). Smart reject pattern Mig 16 — set RejectedFromPhase + clear N-stage rows tại fromPhase + Drafter resume jump-back tới phase đã reject.
|
||||
- **Từ chối** = Phase=TuChoi (decision=Reject, target=TuChoi). Phiếu khoá vĩnh viễn (17 handler Mig 16 lock edit khi Phase != DangSoanThao). Drafter phải tạo phiếu mới.
|
||||
|
||||
## Implementation (1 commit `0d77698`)
|
||||
|
||||
### Domain — `PurchaseEvaluationPolicy.cs`
|
||||
|
||||
**NccOnly** + **NccWithPlan** thêm `(X → TuChoi)` transition cho mọi phase trung gian với roles của phase đó:
|
||||
|
||||
```csharp
|
||||
[(ChoPurchasing, TuChoi)] = [Procurement],
|
||||
[(ChoCCM, TuChoi)] = [CostControl],
|
||||
[(ChoCEODuyetNCC, TuChoi)] = [Director, AuthorizedSigner],
|
||||
// + ChoDuAn, ChoCEODuyetPA cho NccWithPlan
|
||||
```
|
||||
|
||||
**FromDefinition** expand: mỗi step (trừ DangSoanThao) thêm `(step.Phase → TuChoi)` với roles step. Trước đây chỉ DangSoanThao→TuChoi (Drafter).
|
||||
|
||||
### Service — `PurchaseEvaluationWorkflowService.TransitionAsync`
|
||||
|
||||
Reject branch tách 2 case:
|
||||
|
||||
```csharp
|
||||
if (decision == Reject) {
|
||||
if (target != TuChoi) { // "Trả lại"
|
||||
RejectedFromPhase = fromPhase
|
||||
target = DangSoanThao // force
|
||||
clear N-stage rows tại fromPhase
|
||||
}
|
||||
// else target=TuChoi: giữ nguyên TuChoi, KHÔNG set RejectedFromPhase, KHÔNG clear N-stage
|
||||
// Phiếu khoá vĩnh viễn — không resume.
|
||||
}
|
||||
```
|
||||
|
||||
### FE — `PeWorkflowPanel.tsx` (admin + user mirror)
|
||||
|
||||
3 button rõ ràng:
|
||||
- "✓ Duyệt → <label phase>" brand (forward)
|
||||
- "← Trả lại (về Drafter sửa)" red khi `target=DangSoanThao && fromPhase != DangSoanThao`
|
||||
- "✗ Hủy / Từ chối" red khi `target=TuChoi`
|
||||
|
||||
Decision logic FE: `isReject = target=TuChoi || isSendBack`.
|
||||
|
||||
Dialog confirm:
|
||||
- Title rõ theo loại hành động
|
||||
- Cancel case: warning red "⚠ Phiếu sẽ bị khoá hoàn toàn. Drafter cần tạo phiếu mới nếu muốn làm lại"
|
||||
- SendBack case: hint amber "Phiếu sẽ về 'Đang soạn thảo'. Drafter có thể sửa rồi trình lại — workflow tự jump tới phase này"
|
||||
|
||||
### Tests
|
||||
|
||||
- **Rename** `Reject_Sets_RejectedFromPhase_And_Forces_DangSoanThao` → `Reject_To_DangSoanThao_Sets_RejectedFromPhase_TraLai` (change target từ TuChoi → DangSoanThao để test Trả lại pattern)
|
||||
- **NEW** `Reject_To_TuChoi_Locks_Permanently_No_RejectedFromPhase` — Phase=TuChoi + RejectedFromPhase=null
|
||||
- **Update** `NStage_Reject_Clears_InnerStep_Rows_At_Phase` target → DangSoanThao
|
||||
|
||||
**95 → 96 test pass** (+1 Từ chối).
|
||||
|
||||
## Task 2 sample seed — IN-PROGRESS (defer S15+)
|
||||
|
||||
User yêu cầu seed sample data N-stage cho Duyệt NCC. Plan:
|
||||
1. Update `Users.PositionLevel` (1=NV, 2=PP, 3=TP) cho 30 demo user đã seed
|
||||
2. INSERT N-stage WorkflowDefinition v2 cho DuyetNcc với InnerSteps (PRO + CCM × 3 cấp NV/PP/TP)
|
||||
|
||||
Phát hiện gotcha quan trọng:
|
||||
- `DesignTimeDbContextFactory` hardcoded `SolutionErp_Design` connection string. `dotnet ef database update` từ Session 12-13 thực ra apply lên `_Design` DB, KHÔNG `_Dev` runtime DB.
|
||||
- Runtime API dùng `_Dev` (appsettings.Development.json `ConnectionStrings:Default`).
|
||||
- DbInitializer.MigrateAsync chạy khi API startup → auto apply migrations lên `_Dev`.
|
||||
|
||||
Đã xử lý:
|
||||
- `dotnet ef database update --connection "...SolutionErp_Dev..."` apply Mig 9-20 lên `_Dev` (trước chỉ Mig 1-8).
|
||||
- Start API để DbInitializer auto-seed 30 demo user. API exit 255 sớm khi log buffer full (~100 lines) — seeding dở dang (chỉ seed Roles, chưa Users).
|
||||
|
||||
Defer Session 15+ vì cần guidance:
|
||||
- (a) User manual `dotnet run` API 1 lần hoàn thành seed → Claude resume seed sample N-stage
|
||||
- (b) Claude resume với output redirect to file (skip log overflow)
|
||||
- (c) Manual SQL seed users (nhưng PasswordHash phức tạp)
|
||||
|
||||
## Verify
|
||||
|
||||
- ✅ `dotnet build` 0 error
|
||||
- ✅ `dotnet test` **96 pass** (54 Domain + 42 Infra)
|
||||
- ✅ `npm build` fe-admin + fe-user pass
|
||||
- ⏸ E2E manual UAT — defer cho user thử 3-button trên menu Duyệt PE
|
||||
|
||||
## Bug + Fix log
|
||||
|
||||
| # | Issue | Fix |
|
||||
|---|---|---|
|
||||
| 1 | Test cũ assume target=TuChoi → Service force DangSoanThao | Update tests: 1 rename + change target sang DangSoanThao + 1 NEW test cho Từ chối behavior |
|
||||
| 2 | DesignTime vs Runtime DB distinction | `--connection` flag override khi `dotnet ef database update` |
|
||||
|
||||
## Docs updates
|
||||
|
||||
- ✅ STATUS.md — Last updated + Phase summary count + Recently Done row Session 14 (KEEP narrative)
|
||||
- ✅ HANDOFF.md — TL;DR Session 14 prepend + 5 cảnh báo Session 15+
|
||||
- ✅ migration-todos.md — Phase 9 + Session 14 block + 2 defer task
|
||||
- ✅ Session log (file này)
|
||||
- ⏸ schema-diagram.md §17 Mig 18 / §18 Mig 19 / §19 Mig 20 — defer cron audit 2026-06-01
|
||||
|
||||
## Stats cumulative (sau Session 14)
|
||||
|
||||
| | Trước S14 | Sau S14 | Diff |
|
||||
|---|---:|---:|---:|
|
||||
| BE LOC | ~15700 | ~15800 | +100 |
|
||||
| API endpoints | ~134 | ~134 | 0 |
|
||||
| Migrations | 20 | 20 | 0 |
|
||||
| DB tables | 57 | 57 | 0 |
|
||||
| FE pages | 32 | 32 | 0 |
|
||||
| Tests | 95 | **96** | +1 (Từ chối) |
|
||||
| Docs | ~57 | ~58 | +1 (session log này) |
|
||||
| Commits | (after S13) | **+1** | `0d77698` |
|
||||
|
||||
## Plan organization sau session 14
|
||||
|
||||
```
|
||||
Plan cha: Phase 9 active — UAT
|
||||
├── Plan con A: Hard blockers (chờ user/ops) — 6 task
|
||||
├── ...
|
||||
├── Plan con S12 ✅ DONE: N-stage PE (Mig 18+19, 6 chunk)
|
||||
├── Plan con S13 ✅ DONE: N-stage Contract (Mig 20, 5 chunk + skip E)
|
||||
├── Plan con S14 ✅ DONE: PE 3-button workflow (1 commit)
|
||||
├── Plan con Task 2 ⏸ DEFER: Sample seed N-stage
|
||||
└── Plan con Defer S15+:
|
||||
├── Budget N-stage (cần versioned WF migration trước)
|
||||
├── Phase TraLai=98 cleanup (orphan, ko gây hại)
|
||||
├── schema-diagram §17-19 Mig 18-20
|
||||
└── Skill ef-core-migration / contract-workflow refresh (cron audit)
|
||||
```
|
||||
|
||||
## Handoff
|
||||
|
||||
UAT iteration mode. PE 3-button approval ready test. Workflow N-stage Contract + PE backward compat 100% với 2-stage Mig 16.
|
||||
|
||||
**Cron audit kế:** 2026-06-01 (~25 ngày).
|
||||
@ -365,7 +365,7 @@ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||||
- User nói "consolidate", "compact", "gọn lại MD", "rõ ràng MD"
|
||||
- Cuối phase đóng (>1 tháng) khi compact STATUS/HANDOFF/migration-todos
|
||||
|
||||
## 7. Testing (Phase 9 active — 83 test pass + CI gate live)
|
||||
## 7. Testing (Phase 9 active — 96 test pass + CI gate live)
|
||||
|
||||
### Stack đã apply
|
||||
|
||||
|
||||
Reference in New Issue
Block a user