[CLAUDE] FE-Admin+Docs: PE workflow N-stage Designer + UsersPage cấp + Docs (Chunk F)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m0s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m0s
FE Admin:
- types/users.ts: User +positionLevel field + PositionLevel const +
PositionLevelLabel/Short maps (NV/PP/TP).
- PeWorkflowsPage.tsx Designer extend: InnerStepDto + EditInnerStep types,
copyFromDefinition include, departmentsList query, sub-section "Cấp duyệt
nhỏ trong phòng" per step card với 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.
- UsersPage.tsx: column "Cấp" badge NV/PP/TP emerald (— nếu null) +
action button cycle null→1→2→3→null call PATCH /users/{id}/position-level.
KHÔNG đụng fe-user — admin-only feature (PeWorkflowsPage + UsersPage ở
fe-admin only).
Docs:
- STATUS.md Last updated + Phase summary count (17→19 mig, 83→89 test,
55→56 bảng) + 1 row Recently Done Session 12 (KEEP narrative cũ).
- HANDOFF.md TL;DR Session 12 prepend + 8 cảnh báo Session 13+ + giữ
Session phase 2 narrative.
- migration-todos.md Phase 9 + Session 12 block 6 chunk + 5 defer task.
- session log NEW `2026-05-07-2300-n-stage-workflow.md` đầy đủ rationale
+ per-chunk + bug log + plan hierarchy.
Defer cron audit 2026-06-01: schema-diagram §15 Mig 18 + §16 Mig 19,
skill ef-core-migration Mig 18+19 row, skill contract-workflow N-stage
cross-ref section.
Verify:
- npm run build fe-admin pass (✓ built, 0 TS error)
- dotnet test 89 pass (no regression)
- dotnet build 0 error
🎉 SESSION 12 COMPLETE: N-stage workflow approval Phòng × PositionLevel
PE-only. Backward compat 100% với 2-stage Mig 16. 6 commit per-chunk
A→F. Total 89 test pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -157,6 +157,26 @@ Session log: `2026-04-28-chot-session-4-budget.md`.
|
||||
|
||||
## 📝 Phase 9 — UAT + Ops + carry over (Session 6+ active)
|
||||
|
||||
### ✅ Session 12 done (2026-05-07) — N-stage workflow approval (Mig 18+19, 6 commit per-chunk, PE-only)
|
||||
|
||||
User yêu cầu: workflow level cha (= phase) cấu hình được level con (Phòng × Cấp NV/PP/TP) sequential, mỗi cấp = 1 inner step duyệt riêng, có bypass cùng dept. 6 spec defaults chốt + 6 chunk per-commit.
|
||||
|
||||
- [x] **Chunk A (`13ab533`)** Domain + Migration 18 `AddPeWorkflowInnerStepsAndPositionLevel` — enum PositionLevel (NV/PP/TP), entity PurchaseEvaluationWorkflowStepInnerStep + nav, User.PositionLevel int? + PEDeptApproval.InnerStepId Guid?. EF config FK Cascade Step / Restrict Dept+InnerStep. 3-file rule.
|
||||
- [x] **Chunk B (`0e56bd0`)** Application CQRS DTO — PeWorkflowStepInnerStepDto + extend PeWorkflowStepDto + CreatePeWorkflowStepInnerStepInput (default null backward compat) + Validator child rules + Handler atomic batch insert + UserDto +PositionLevel + SetUserPositionLevelCommand mirror SetBypassReview pattern.
|
||||
- [x] **Chunk C (`0c62e24`)** Service N-stage logic + **Migration 19** `AlterPeDeptApprovalsUniqueFilteredForInnerSteps` (filtered unique legacy `WHERE InnerStepId IS NULL` + new N-stage `WHERE InnerStepId IS NOT NULL`). PurchaseEvaluationWorkflowService refactor — load InnerSteps eager, reject clear N-stage rows tại fromPhase, dept block split hasInnerSteps→N-stage / else→legacy 2-stage. N-stage: match firstPending (Order asc IsRequired) same dept + (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)".
|
||||
- [x] **Chunk D (`3d76c6b`)** Tests N-stage 6 test mới (FirstInner_NV_blocks / All_3_levels_sequential_pass / TP_bypass_skips_lower / Wrong_dept_403 / Reject_clears_rows / Legacy_fallback_no_inner) + IdentityFixture extend `+positionLevel` + helper SeedWorkflowDefinitionAsync 2 step adjacent. **83→89 test pass**.
|
||||
- [x] **Chunk E (`83ffabd`)** API `PATCH /users/{id}/position-level` mirror SetBypassReview + body `{positionLevel:int?}` + Authorize Users.Update.
|
||||
- [x] **Chunk F (current)** FE-Admin types/users.ts + positionLevel field + PositionLevel const + Label/Short maps. PeWorkflowsPage Designer extend InnerStep DTO + EditInnerStep type + 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 + departmentsList query + payload include. UsersPage column "Cấp" badge NV/PP/TP emerald + action button cycle null→1→2→3→null. KHÔNG đụng fe-user (admin-only).
|
||||
|
||||
**Backward compat 100%:** workflow no InnerSteps configured → service fallback legacy 2-stage Mig 16. Data legacy rows InnerStepId=null vẫn enforce unique cũ qua filtered index.
|
||||
|
||||
**Defer Session 13+:**
|
||||
- [ ] Mirror Contract + Budget N-stage (sau khi UAT PE 2-3 tuần ổn). Pattern lặp lại Domain entity + Service logic + Tests reusable từ PE.
|
||||
- [ ] Seed/migrate User.PositionLevel cho 30 demo user (hiện chỉ admin set qua UsersPage cycle).
|
||||
- [ ] schema-diagram.md §15 Mig 18 + §16 Mig 19 update (defer cron audit 2026-06-01 — small drift).
|
||||
- [ ] Skill ef-core-migration row Mig 18+19 (defer cron audit).
|
||||
- [ ] Skill contract-workflow N-stage cross-ref section (defer cron audit).
|
||||
|
||||
### ✅ Session phase 2 done (2026-05-08 00:30) — B12-B14 PE detail polish iterate (3 commit FE-only)
|
||||
|
||||
User UAT iteration tiếp sau wrap-up `6e7a6db`. Áp rule strict verify khi rename/remove (lesson hotfix CI).
|
||||
|
||||
248
docs/changelog/sessions/2026-05-07-2300-n-stage-workflow.md
Normal file
248
docs/changelog/sessions/2026-05-07-2300-n-stage-workflow.md
Normal file
@ -0,0 +1,248 @@
|
||||
# Session 2026-05-07 (S12) — N-stage workflow approval Phòng × PositionLevel
|
||||
|
||||
**Dev:** Claude
|
||||
**Duration:** ~3h
|
||||
**Base commit:** `130903f` (sau Session phase 2 wrap-up `edc6660` + commit nhỏ bỏ button "+ Tạo phiếu mới")
|
||||
**Final commit:** (current Chunk F)
|
||||
**Total commits:** 6 per-chunk
|
||||
|
||||
## Bối cảnh
|
||||
|
||||
User screenshot annotation menu Duyệt NCC: "Phòng A có NV / Phó Phòng / Trưởng Phòng — cấp duyệt nhỏ trong cùng 1 step cha cấu hình được". Mở rộng từ 2-stage Mig 16 (NV.Review/TPB.Confirm) sang N-stage cấu hình động per WorkflowStep:
|
||||
|
||||
- Level cha: WorkflowStep (= 1 phase, vd "Chờ Purchasing")
|
||||
- Level con: chuỗi InnerSteps theo Phòng × PositionLevel với Order sequential
|
||||
- Vd: NV.PRO → PP.PRO → TP.PRO → NV.CCM → PP.CCM → TP.CCM → next phase
|
||||
|
||||
Cả 2 cấp đều cấu hình được qua admin designer.
|
||||
|
||||
## 6 câu spec defaults chốt trước code
|
||||
|
||||
- **Q1 PositionLevel** — enum 1=NV, 2=PP, 3=TP (gọn, dễ Compare). User.PositionLevel int? nullable cho admin/system/external user.
|
||||
- **Q2 Sequential** — pure Order asc (KHÔNG parallel inter-phòng). Mỗi inner step = 1 cấp duyệt riêng.
|
||||
- **Q3 Bypass** — TP có CanBypassReview → skip NV+PP CÙNG dept (audit IsBypassed=true cho cấp dưới). Cross-dept KHÔNG skip.
|
||||
- **Q4 Reject** — về DangSoanThao + RejectedFromPhase set + clear N-stage rows tại phase reject. Resume jump-back tới RejectedFromPhase + re-approve N-stage.
|
||||
- **Q5 Scope** — PE-only first (Contract + Budget mirror sau khi UAT PE ổn).
|
||||
- **Q6(a) Designer UI** — 1 sub-section "Cấp duyệt nhỏ trong phòng" drag-list per step cha, không tách 2 designer.
|
||||
|
||||
## 6 chunk per-commit
|
||||
|
||||
### Chunk A — Domain + Migration 18 (`13ab533`)
|
||||
|
||||
**Files mới (1):**
|
||||
- `Domain/Identity/PositionLevel.cs` — enum NhanVien=1, PhoPhong=2, TruongPhong=3.
|
||||
|
||||
**Files edit (3):**
|
||||
- `Domain/Identity/User.cs` — `+ public PositionLevel? PositionLevel { get; set; }` cuối class.
|
||||
- `Domain/PurchaseEvaluations/PurchaseEvaluationWorkflowDefinition.cs` — class WorkflowStep + nav `List<InnerSteps>` + class mới `PurchaseEvaluationWorkflowStepInnerStep` (Order, DepartmentId, PositionLevel, Name, SlaDays, IsRequired).
|
||||
- `Domain/PurchaseEvaluations/PurchaseEvaluationDepartmentApproval.cs` — `+ public Guid? InnerStepId { get; set; }` (null cho legacy 2-stage rows).
|
||||
|
||||
**Infra edit (3):**
|
||||
- `Infrastructure/Persistence/Configurations/PurchaseEvaluationConfiguration.cs` — config InnerStep table (Cascade Step, Restrict Department, IX (StepId, Order) + IX DeptId).
|
||||
- `Infrastructure/Persistence/Configurations/DepartmentApprovalsConfiguration.cs` — IX InnerStepId.
|
||||
- `Infrastructure/Persistence/ApplicationDbContext.cs` — DbSet<InnerStep>.
|
||||
|
||||
**Migration 18** `AddPeWorkflowInnerStepsAndPositionLevel`:
|
||||
- 1 CREATE TABLE PurchaseEvaluationWorkflowStepInnerSteps
|
||||
- 2 ALTER (User.PositionLevel + PEDeptApproval.InnerStepId)
|
||||
- 3 INDEX
|
||||
- FK Cascade Step / Restrict Dept / Restrict InnerStep
|
||||
|
||||
3-file rule: Migration .cs + Designer + Snapshot.
|
||||
|
||||
**Verify:** dotnet build pass, ef database update LocalDB applied, 83 test pass (no regression).
|
||||
|
||||
### Chunk B — Application CQRS DTO (`0e56bd0`)
|
||||
|
||||
**`Application/PurchaseEvaluations/PeWorkflowAdminFeatures.cs`:**
|
||||
- record `PeWorkflowStepInnerStepDto` (Id, Order, DepartmentId, DepartmentName, PositionLevel, Name, SlaDays, IsRequired).
|
||||
- record `PeWorkflowStepDto` extend `+List<PeWorkflowStepInnerStepDto> InnerSteps`.
|
||||
- `GetPeWorkflowAdminOverviewQueryHandler` — Include InnerSteps OrderBy Order + resolve DeptNames cho display.
|
||||
- record `CreatePeWorkflowStepInnerStepInput` (Order, DeptId, PositionLevel, Name, SlaDays, IsRequired).
|
||||
- record `CreatePeWorkflowStepInput` extend `+List<...InnerSteps>? = null` (default null cho backward compat existing PeWorkflowAdminTests positional `new(...)`).
|
||||
- Validator child rules cho InnerSteps (Order ≥1, DeptId not empty, PositionLevel 1-3, SlaDays ≥0).
|
||||
- `CreatePeWorkflowDefinitionCommandHandler` — convert InnerSteps khi build entity (atomic batch insert qua nav collection).
|
||||
|
||||
**`Application/Users/UserFeatures.cs`:**
|
||||
- record `UserDto` `+int? PositionLevel` field.
|
||||
- ListUsers + GetUser handlers map `(int?)u.PositionLevel`.
|
||||
- record `SetUserPositionLevelCommand(Guid Id, int? PositionLevel)` mirror SetUserBypassReviewCommand.
|
||||
- Validator: PositionLevel null OR 1-3.
|
||||
- Handler: `userManager.UpdateAsync` user.PositionLevel.
|
||||
|
||||
**Verify:** dotnet build 0 error, 83 test pass (PeWorkflowAdminTests existing 6 test pass với InnerSteps default null backward compat).
|
||||
|
||||
### Chunk C — Service N-stage logic + Migration 19 (`0c62e24`)
|
||||
|
||||
**`Infrastructure/Persistence/Configurations/DepartmentApprovalsConfiguration.cs`:**
|
||||
- Drop UNIQUE `(PEId, Phase, Dept, Stage)` Mig 16.
|
||||
- Recreate filtered `WHERE [InnerStepId] IS NULL` (legacy 2-stage rows).
|
||||
- Add new filtered `(PEId, Phase, InnerStepId)` `WHERE [InnerStepId] IS NOT NULL` (N-stage 1 row per inner step per phase).
|
||||
|
||||
**Migration 19** `AlterPeDeptApprovalsUniqueFilteredForInnerSteps`:
|
||||
- DropIndex UX_PEDeptApprovals_PE_Phase_Dept_Stage
|
||||
- CreateIndex 2 filtered
|
||||
|
||||
Lý do: N-stage có thể có 2+ inner step cùng dept (NV/PP/TP) — Stage=Confirm tất cả → violate unique cũ.
|
||||
|
||||
**`Infrastructure/Services/PurchaseEvaluationWorkflowService.cs` refactor TransitionAsync:**
|
||||
1. **Load definition** với `.ThenInclude(s => s.InnerSteps.OrderBy(i => i.Order))` eager + assign `definition` outer scope.
|
||||
2. **Reject branch** thêm: clear N-stage approval rows tại `fromPhase` (resume sẽ approve lại từ inner đầu).
|
||||
3. **Department approval block split:**
|
||||
```
|
||||
if (decision==Approve && targetPhase != Stao && targetPhase != TuChoi
|
||||
&& !isResumingAfterReject && !isAdmin && !isSystem
|
||||
&& actorUserId is Guid actorUid)
|
||||
{
|
||||
var step = def?.Steps.FirstOrDefault(s => s.Phase == fromPhase);
|
||||
var hasInnerSteps = step?.InnerSteps.Count > 0;
|
||||
if (hasInnerSteps) { /* N-stage logic */ }
|
||||
else if (actor.DeptId is Guid deptId) { /* legacy 2-stage Mig 16 */ }
|
||||
}
|
||||
```
|
||||
4. **N-stage logic:**
|
||||
- Yêu cầu actor có DeptId + PositionLevel (else throw 403).
|
||||
- Load existing approvals tại fromPhase với InnerStepId IN [innerIds] → compute doneInnerIds set.
|
||||
- pendingRequired = inners.Where(i => i.IsRequired && !doneInnerIds.Contains(i.Id)).
|
||||
- firstPending = pendingRequired[0].
|
||||
- Match: actorDept == firstPending.Dept AND (actorPos == firstPending.Level OR canBypass + actorPos ≥ firstPending.Level). Mismatch → 403.
|
||||
- Exact match: 1 row upsert (Stage=Confirm, InnerStepId=firstPending, IsBypassed=false).
|
||||
- Bypass: batch upsert tất cả inners cùng dept actor có level từ firstPending.Level đến actorPos (inclusive, IsBypassed=true cho cấp dưới skip).
|
||||
- Recheck stillPending → BLOCK + log Approval/Changelog "duyệt cấp X (còn Y pending)" + return early.
|
||||
- All done → fall through phase transition.
|
||||
5. **Legacy fallback** (else branch) — giữ nguyên logic 2-stage Mig 16 với InnerStepId=null filter.
|
||||
|
||||
**Verify:** dotnet build 0 error, ef database update Mig 19 LocalDB applied, 83 test pass (legacy backward compat OK).
|
||||
|
||||
### Chunk D — Tests N-stage 6 test (`3d76c6b`)
|
||||
|
||||
**`tests/SolutionErp.Infrastructure.Tests/Common/IdentityFixture.cs`** extend:
|
||||
- `CreateUserAsync` `+PositionLevel? positionLevel = null` arg → set User.PositionLevel.
|
||||
|
||||
**`tests/.../Services/PeNStageApprovalTests.cs` (NEW, 6 test):**
|
||||
|
||||
| # | Test | Cover |
|
||||
|---|---|---|
|
||||
| 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 → 3 rows + phase chuyển |
|
||||
| 3 | NStage_TP_Bypass_Skips_Lower_Levels_Same_Dept | TP+canBypass → 3 rows (NV+PP IsBypassed, TP exact) |
|
||||
| 4 | NStage_Wrong_Department_Throws_Forbidden | Actor dept khác → ForbiddenException |
|
||||
| 5 | NStage_Reject_Clears_InnerStep_Rows_At_Phase | Reject → DangSoanThao + clear N-stage rows |
|
||||
| 6 | LegacyFallback_NoInnerSteps_Uses_2Stage_Logic | PE no pinned def → fallback 2-stage Stage=Review |
|
||||
|
||||
**Helper `SeedWorkflowDefinitionAsync`** tạo definition với 2 step adjacent (ChoPurchasing có inner steps + ChoCCM next, no inner) — đủ cho FromDefinition build transition (ChoPurchasing → ChoCCM) policy guard pass actor role Procurement.
|
||||
|
||||
**Bug gặp:** Initial fail 4 test với `ForbiddenException: "Policy không cho phép ChoPurchasing → ChoCCM"`. Root cause: FromDefinition build transitions từ adjacent steps, seed 1 step → no transition. Fix: thêm step 2 ChoCCM mirror role.
|
||||
|
||||
**Verify:** 83 → **89 test pass** (54 Domain + 35 Infra: 17 codegen + 6 PE WF versioning + 6 PE 2-stage + 6 PE N-stage).
|
||||
|
||||
### Chunk E — API endpoint (`83ffabd`)
|
||||
|
||||
**`Api/Controllers/UsersController.cs`:**
|
||||
- `PATCH /api/users/{id}/position-level` body `{positionLevel: int?}` Authorize Users.Update → SetUserPositionLevelCommand.
|
||||
- record `SetPositionLevelBody(int? PositionLevel)`.
|
||||
|
||||
PE Workflow Designer endpoint Create/Get KHÔNG đụng — DTO record đã extend ở Chunk B, JSON body bind tự động.
|
||||
|
||||
**Verify:** dotnet build 0 error 0 warning.
|
||||
|
||||
### Chunk F — FE Designer + UsersPage + Docs (current)
|
||||
|
||||
**`fe-admin/src/types/users.ts`:**
|
||||
- User type `+positionLevel: number | null`.
|
||||
- const `PositionLevel = { NhanVien: 1, PhoPhong: 2, TruongPhong: 3 } as const`.
|
||||
- `PositionLevelLabel: Record<number, string>` (NV/PP/TP với full description).
|
||||
- `PositionLevelShort: Record<number, string>` (NV/PP/TP gọn).
|
||||
|
||||
**`fe-admin/src/pages/system/PeWorkflowsPage.tsx`:**
|
||||
- Type `InnerStepDto` + extend `StepDto` `+innerSteps: InnerStepDto[]`.
|
||||
- Type `EditInnerStep` + extend `EditStep` `+innerSteps: EditInnerStep[]`.
|
||||
- `copyFromDefinition` include innerSteps map.
|
||||
- Default new step `+innerSteps: []`.
|
||||
- `departmentsList` useQuery fetch /departments.
|
||||
- Save mutation payload: `s.innerSteps.map((ii, ix) => ({ order: ix+1, departmentId, positionLevel, name, slaDays, isRequired }))`.
|
||||
- UI sub-section "Cấp duyệt nhỏ trong phòng (sequential — Order asc)" trong từng step card sau "Người duyệt" section, với drag-list rows { Order badge emerald + Select Phòng + Select Cấp + checkbox required + Trash button } + button "+ Thêm cấp duyệt" emerald (disabled khi departmentsList empty).
|
||||
- Empty state hint: "Chưa cấu hình cấp con — workflow fallback logic 2-cấp NV/TPB legacy."
|
||||
|
||||
**`fe-admin/src/pages/system/UsersPage.tsx`:**
|
||||
- Import `PositionLevelShort + PositionLevelLabel`.
|
||||
- Mutation `positionLevelMut` PATCH /users/{id}/position-level.
|
||||
- `nextPositionLevel(current)` cycle null → 1 → 2 → 3 → null.
|
||||
- Column "Cấp" width=w-16 align center: badge emerald NV/PP/TP với tooltip full label, hoặc "—" nếu null.
|
||||
- Action button (kế bên Bypass): text NV/PP/TP/— với color emerald-active vs slate-inactive, tooltip "click để cycle".
|
||||
|
||||
**KHÔNG đụng fe-user** — PeWorkflowsPage + UsersPage admin-only feature.
|
||||
|
||||
**Verify:** npm run build fe-admin pass (✓ built), 0 TS error.
|
||||
|
||||
## E2E verified
|
||||
|
||||
- ✅ `dotnet test SolutionErp.slnx` 89/89 pass (54 Domain + 35 Infra)
|
||||
- ✅ `dotnet build SolutionErp.slnx` 0 error, 2 pre-existing warning DocxRenderer
|
||||
- ✅ `dotnet ef database update` Mig 18+19 LocalDB applied OK
|
||||
- ✅ `npm run build` fe-admin pass — no TS error
|
||||
- 🔄 Manual UAT — defer cho user thử workflow Designer + create version mới có Inner Steps + duyệt qua các cấp
|
||||
|
||||
## Bug + Fix log
|
||||
|
||||
| # | Issue | Fix | Commit |
|
||||
|---|---|---|---|
|
||||
| 1 | UNIQUE conflict khi N-stage 2+ inner step cùng dept Stage=Confirm | Migration 19 filtered unique split legacy/N-stage | `0c62e24` |
|
||||
| 2 | 4 N-stage test fail "Policy không cho phép ChoPurchasing → ChoCCM" | Helper SeedWorkflowDefinitionAsync thêm step 2 adjacent ChoCCM cho FromDefinition build transition | (Chunk D inline) |
|
||||
| 3 | TS6133 unused import PositionLevelShort trong PeWorkflowsPage.tsx | Bỏ khỏi import (dùng ở UsersPage thôi) | (Chunk F inline) |
|
||||
|
||||
## Docs updates
|
||||
|
||||
- ✅ STATUS.md — Last updated + Phase summary count + 1 row Recently Done (KEEP narrative cũ)
|
||||
- ✅ HANDOFF.md — TL;DR Session 12 prepend + 8 cảnh báo Session 13+ + giữ Session phase 2 narrative
|
||||
- ✅ migration-todos.md — Phase 9 thêm Session 12 block 6 chunk + 5 task defer S13+
|
||||
- ✅ Session log (file này)
|
||||
- ⏸️ schema-diagram.md §15 Mig 18 + §16 Mig 19 — defer cron audit 2026-06-01
|
||||
- ⏸️ Skill ef-core-migration Mig 18+19 row + counts — defer cron audit
|
||||
- ⏸️ Skill contract-workflow Phase 9+ N-stage cross-ref section — defer cron audit
|
||||
- ❌ gotchas.md — KHÔNG add (không phát sinh bẫy mới đáng cluster, các bug fix Chunk D là test setup issue, Chunk C unique conflict đã fix tại design)
|
||||
- ❌ rules.md — KHÔNG add (N-stage là feature project-specific, KHÔNG phải coding convention)
|
||||
|
||||
## Stats cumulative (sau Session 12)
|
||||
|
||||
| | Trước S12 | Sau S12 | Diff |
|
||||
|---|---:|---:|---:|
|
||||
| BE LOC | ~14850 | ~15300 | +450 |
|
||||
| API endpoints | ~133 | ~134 | +1 (PATCH /users/{id}/position-level) |
|
||||
| Migrations | 17 | **19** | +2 (Mig 18 + Mig 19) |
|
||||
| DB tables | 55 | **56** | +1 (PEWorkflowStepInnerSteps) |
|
||||
| DB columns mới | — | +2 | User.PositionLevel + PEDeptApproval.InnerStepId |
|
||||
| FE pages | 32 | 32 | 0 (extend existing 2 page) |
|
||||
| FE components mới | — | 0 | Inline UI sub-section trong PeWorkflowsPage |
|
||||
| Tests | 83 | **89** | +6 (PE N-stage approval) |
|
||||
| Docs | ~55 | ~56 | +1 (session log này) |
|
||||
| Commits S12 | — | **+6** | A→F per-chunk |
|
||||
|
||||
## Plan organization sau session 12
|
||||
|
||||
```
|
||||
Plan cha: Phase 9 active — UAT
|
||||
├── Plan con A: Hard blockers (chờ user/ops) — 6 task pending (giữ nguyên)
|
||||
├── Plan con B-E: Done từ Session 7-11+++++++ (giữ narrative cũ)
|
||||
├── Plan con S12: N-stage workflow approval ✅ DONE (6 chunk per-commit)
|
||||
│ ├── ✅ A: Domain + Mig 18
|
||||
│ ├── ✅ B: App CQRS
|
||||
│ ├── ✅ C: Service logic + Mig 19 filtered unique
|
||||
│ ├── ✅ D: 6 test mới
|
||||
│ ├── ✅ E: API endpoint
|
||||
│ └── ✅ F: FE Designer + UsersPage + Docs
|
||||
├── Plan con G: Optional polish (UAT-driven) — 5 task (giữ nguyên)
|
||||
├── Plan con H: Tests Phase 3-5 — 3 sub (giữ nguyên)
|
||||
└── Plan con I: Defer cho Session 13+
|
||||
├── Mirror N-stage sang Contract + Budget (sau UAT PE 2-3 tuần ổn)
|
||||
├── Seed/migrate User.PositionLevel cho 30 demo user
|
||||
├── schema-diagram.md §15 Mig 18 + §16 Mig 19
|
||||
├── Skill ef-core-migration Mig 18+19 row
|
||||
└── Skill contract-workflow N-stage cross-ref
|
||||
```
|
||||
|
||||
## Handoff
|
||||
|
||||
UAT iteration mode. User test live + báo lại nếu cần điều chỉnh. Workflow N-stage backward compat 100% với data legacy 2-stage Mig 16.
|
||||
|
||||
**Cron audit kế:** 2026-06-01 (~25 ngày). Lúc đó update schema-diagram + 2 skill drift đã list ở Defer S13+.
|
||||
Reference in New Issue
Block a user