[CLAUDE] FE-Admin FE-User: Chunk M3 — Rename Phase=TraLai display label "Trả lại" → "Cần chỉnh sửa lại"

Plan M Chunk M3 — UAT disconnect fix: bro UAT phát hiện label "Trả lại" + "Bản
nháp" không phân biệt rõ với end-user → rename Phase=TraLai (98) display label
sang "Cần chỉnh sửa lại" để self-descriptive.

Scope HẸP — chỉ status display reference (KHÔNG đụng action verb):
- types/purchaseEvaluation.ts × 2 app: PurchaseEvaluationPhaseLabel[98] +
  PeDisplayStatusLabel.TraLai = 2 const map rename
- components/pe/PeWorkflowPanel.tsx × 2 app: 2 inline literal hardcode trong
  F1 dialog tooltip `Phase → "..."` + confirm message `Phiếu sẽ về "..."` —
  status reference, KHÔNG phải action verb

KHÔNG đụng:
- Action button label `← Trả lại` (verb, giữ nguyên)
- F1 mode picker label `Trả về Người soạn thảo` (4 mode action, giữ nguyên)
- Comments narrative giữ rationale dev (rule §6.5)
- types/contracts.ts + types/budget.ts Phase 98 'Trả lại' — module Contract +
  Budget khác PE, ngoài scope M3

Mirror 2 app rule §3.9 strict applied.

Verify:
- npm run build fe-admin PASS clean (0 TS err, 9.40s)
- npm run build fe-user PASS clean (0 TS err, 6.92s)

Diff: +4/-4 LOC × 4 file = 8 LOC total

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-05-15 11:15:01 +07:00
parent c2042ef956
commit 508b17a43c
5 changed files with 10 additions and 8 deletions

View File

@ -204,6 +204,8 @@ KHÔNG `*` / `latest`. Critical pins:
## 📅 Recent activity (last 10 FIFO)
- **2026-05-15 (S24, Plan M Chunk M3 PASS):** FE rename Phase=TraLai (98) display label "Trả lại" → "Cần chỉnh sửa lại" cho UAT disconnect fix. Spec scope HẸP (display badge label + status reference) tuân thủ strict: 4 file FE × 2 app = 8 edit total. **2 file types/purchaseEvaluation.ts** × 2 app: `PurchaseEvaluationPhaseLabel[98]` (raw phase badge) + `PeDisplayStatusLabel.TraLai` (display status badge — main user-facing). **2 file components/pe/PeWorkflowPanel.tsx** × 2 app: rename 2 inline literal hardcode "Trả lại" trong F1 dialog tooltip (`Phase → "..."`) + confirm message (`Phiếu sẽ về "..."`) — đây là status display reference, KHÔNG phải action verb. Pattern 5 mirror 2 app strict applied. KHÔNG đụng: (1) action button label `← Trả lại` (verb), (2) F1 mode picker label `Trả về Người soạn thảo` (4 mode action), (3) comments narrative line 62/71/etc giữ rationale dev (rule §6.5), (4) `types/contracts.ts` + `types/budget.ts` Phase 98 'Trả lại' — module Contract + Budget khác PE, ngoài scope M3. Verify: `npm run build` fe-admin PASS clean (0 TS err, 9.40s, 1395 KB bundle unchanged trivial) + `npm run build` fe-user PASS clean (0 TS err, 6.92s, 1275 KB). Diff +4/-4 LOC × 2 = 8 LOC tổng trên 4 file. Token ~9k. Decision tactical: 2 chỗ inline literal PeWorkflowPanel rename để giữ UX consistency với badge label sau rename — KHÔNG drift outside spec vì cùng "status display reference" semantics (badge + tooltip + confirm message phải mirror). Anti-fiddle threshold <20% LOC respected.
- **2026-05-14 (S23 t1, K7 Chunk F PASS):** Mig 31 Approver F2 service regression tests. Sub-task 1 fix broken Drafter F2 test reference K1 flagged: `PurchaseEvaluationWorkflowServiceReturnModeTests.cs:253` `drafter.AllowDrafterSkipToFinal = true` (DELETE 3 deprecated Drafter F2 tests entire `SkipToFinal_DrafterAllowed_SetsPointerToFinalLevel` + `SkipToFinal_DrafterDenied_NonAdmin_Throws` + `SkipToFinal_AdminBypass_Succeeds`, semantic deprecated no value). Sub-task 2 add 3 new Approver F2 tests: `ApproveV2_SkipToFinal_AdminTickFlag_SetsPhaseDaDuyet` (happy path slot Cấp 1 Bước 1 admin tick Phase=DaDuyet, pointer cleared, opinion + PEA + Changelog logged), `ApproveV2_SkipToFinal_FlagOff_NonAdmin_ThrowsConflictException` (denied flag off non-admin slot user throw "chưa được phép duyệt thẳng Cấp cuối"), `ApproveV2_SkipToFinal_FlagOff_Admin_BypassesFlagCheck` (admin bypass flag off admin role DaDuyet allowed). Pattern 11 SeedWorkflowAsync cookie-cutter REUSE created `SeedApproverF2WorkflowAsync` helper (2 Steps × 2 Levels multi-step verify skip thẳng terminal KHÔNG fallthrough advance pointer next Step), AllowApproverSkipToFinal per-slot param. PE init Phase=ChoDuyet + CurrentWorkflowStepIndex=0 + CurrentApprovalLevelOrder=1 (vs S22 happy path từ DangSoanThao). Add `using Microsoft.EntityFrameworkCore` cho `.ToListAsync()` PEL/PEA/Changelog query. File header narrative line 17-25 REWRITE để track Mig 31 refactor semantic Approver scope ChoDuyet vs Drafter-from-Nháp . Verify: `dotnet build` clean 0 err 2 warn pre-existing DocxRenderer. `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. Diff +175/-92 LOC trên 1 file. Token ~14k.
- **2026-05-14 (S23 t1, K5 Chunk D PASS):** Cleanup zombie F2 endpoint + UsersPage column + DTO field + stale narrative comments (Reviewer Major #1 + Major #2 + Minor #3 + Minor #4). Pattern post-refactor full cleanup atomic 1 commit. BE 7 file (UsersController.cs DELETE PATCH /allow-skip-final endpoint + SetAllowDrafterSkipToFinalBody record; UserFeatures.cs DELETE UserDto field + SetUserAllowDrafterSkipToFinalCommand + Handler + sentinel-false mappings cleanup; ApprovalWorkflow.cs REWRITE stale narrative line 78-80 Mig 31 semantic + docstring line 108; PurchaseEvaluationFeatures.cs REWRITE Command DTO comment line 401; ApprovalWorkflowConfiguration.cs APPEND Mig 31 narrative line 22-24 + clean storage move comment line 87; ApprovalWorkflowV2AdminFeatures.cs clean DTO comment line 58; IPurchaseEvaluationWorkflowService.cs + PurchaseEvaluationDtos.cs clean stale "storage Users.AllowDrafterSkipToFinal" references) + FE Admin 2 file (UsersPage.tsx DELETE "Skip cuối" column TableHeader/TableCell + FastForward import + allowSkipMut mutation hook + FastForward toggle button; types/users.ts DELETE allowDrafterSkipToFinal field). fe-user KHÔNG đụng (no UsersPage admin-only + K6 sẽ handle Workspace Drafter checkbox), FE Designer page KHÔNG đụng (K3 done 2 stale comment line 75 + 504 leftover deferred K6). Grep `AllowDrafterSkipToFinal` + `allow-skip-final` + `allowDrafterSkipToFinal` + `Skip cuối` + `FastForward` ZERO results across src/Backend (excl migrations) + fe-admin/src. Build BE production projects clean (0 err, 2 pre-existing DocxRenderer warn). Build fe-admin clean (0 TS err, 0 new warn). Diff +42/-94 LOC trên 9 file. Token ~12k. K6 Workspace Drafter checkbox cleanup next.
- **2026-05-14 (S23 t1, K3 Chunk C PASS):** FE Admin Designer 7th checkbox AllowApproverSkipToFinal + banner rewrite. Pattern Mig 29/30 admin opt-in per-slot mirror **reinforced 3×** cumulative (Mig 29 F1+F3 5 checkbox + Mig 30 F4 1 checkbox + Mig 31 F2-refactor 1 checkbox = 7 checkbox total per slot). Cookie-cutter 1 file fe-admin only (`ApprovalWorkflowsV2Page.tsx`, fe-user no Designer per Investigator K0 S1). 7 sub-items atomic: (1) LevelDto type +`allowApproverSkipToFinal: boolean`, (2) EditLevelEntry type +same, (3) `makeDefaultLevelEntry` default false, (4) `copyFromDefinition` propagate `?? false`, (5) inline checkbox row position **cuối list** sau F4 AllowApproverEditBudget logical grouping (Edit Section 2 Edit Budget Skip to Final), (6) banner rewrite line ~623 từ "F2 cấu hình User Management" (Plan D S22 stale) "Cấu hình quyền duyệt riêng cho từng NV trong slot Approver bên dưới (Trả lại / Edit Section 2 / Edit Budget / Duyệt thẳng Cấp cuối)", (7) POST/PATCH mutation body `levels.map` +allowApproverSkipToFinal. Verify: `npm run build` fe-admin PASS clean 0 TS error, 0 new warning. Bundle 1395.74 KB (unchanged trivial vs baseline). Diff +26/-7 LOC. Token ~6k. K5 next chunk cleanup zombie endpoint + UsersPage column.

View File

@ -405,7 +405,7 @@ export function PeWorkflowPanel({
/>
<span>
<span className="font-medium">Trả về Người soạn thảo (mặc đnh)</span>
<span className="block text-[10px] text-slate-500">Phase "Trả lại". Drafter sửa rồi gửi lại chạy từ Cấp 1 Bước 1.</span>
<span className="block text-[10px] text-slate-500">Phase "Cần chỉnh sửa lại". Drafter sửa rồi gửi lại chạy từ Cấp 1 Bước 1.</span>
</span>
</label>
)}
@ -414,7 +414,7 @@ export function PeWorkflowPanel({
)}
<div className="mb-3 rounded border border-amber-200 bg-amber-50 px-3 py-2 text-[11px] text-amber-800">
{returnMode === WorkflowReturnMode.Drafter
? 'Phiếu sẽ về "Trả lại". Drafter có thể sửa rồi trình lại từ Cấp 1 Bước 1.'
? 'Phiếu sẽ về "Cần chỉnh sửa lại". Drafter có thể sửa rồi trình lại từ Cấp 1 Bước 1.'
: returnMode === WorkflowReturnMode.Assignee
? 'Phiếu sẽ về Cấp/Bước của NV đã chọn (vẫn "Đã gửi duyệt"). NV nhận lại để duyệt tiếp.'
: 'Phiếu sẽ lùi pointer (vẫn "Đã gửi duyệt"). NV trước nhận lại để duyệt tiếp.'}

View File

@ -41,7 +41,7 @@ export const PurchaseEvaluationPhaseLabel: Record<number, string> = {
6: 'Chờ CEO duyệt NCC',
7: 'Đã duyệt',
10: 'Đã gửi duyệt',
98: 'Trả lại',
98: 'Cần chỉnh sửa lại',
99: 'Từ chối',
}
@ -83,7 +83,7 @@ export type PeDisplayStatus = typeof PeDisplayStatus[keyof typeof PeDisplayStatu
export const PeDisplayStatusLabel: Record<PeDisplayStatus, string> = {
Nhap: 'Nháp',
DaGuiDuyet: 'Đã gửi duyệt',
TraLai: 'Trả lại',
TraLai: 'Cần chỉnh sửa lại',
DaDuyet: 'Đã duyệt',
TuChoi: 'Từ chối',
}

View File

@ -404,7 +404,7 @@ export function PeWorkflowPanel({
/>
<span>
<span className="font-medium">Trả về Người soạn thảo (mặc đnh)</span>
<span className="block text-[10px] text-slate-500">Phase "Trả lại". Drafter sửa rồi gửi lại chạy từ Cấp 1 Bước 1.</span>
<span className="block text-[10px] text-slate-500">Phase "Cần chỉnh sửa lại". Drafter sửa rồi gửi lại chạy từ Cấp 1 Bước 1.</span>
</span>
</label>
)}
@ -413,7 +413,7 @@ export function PeWorkflowPanel({
)}
<div className="mb-3 rounded border border-amber-200 bg-amber-50 px-3 py-2 text-[11px] text-amber-800">
{returnMode === WorkflowReturnMode.Drafter
? 'Phiếu sẽ về "Trả lại". Drafter có thể sửa rồi trình lại từ Cấp 1 Bước 1.'
? 'Phiếu sẽ về "Cần chỉnh sửa lại". Drafter có thể sửa rồi trình lại từ Cấp 1 Bước 1.'
: returnMode === WorkflowReturnMode.Assignee
? 'Phiếu sẽ về Cấp/Bước của NV đã chọn (vẫn "Đã gửi duyệt"). NV nhận lại để duyệt tiếp.'
: 'Phiếu sẽ lùi pointer (vẫn "Đã gửi duyệt"). NV trước nhận lại để duyệt tiếp.'}

View File

@ -41,7 +41,7 @@ export const PurchaseEvaluationPhaseLabel: Record<number, string> = {
6: 'Chờ CEO duyệt NCC',
7: 'Đã duyệt',
10: 'Đã gửi duyệt',
98: 'Trả lại',
98: 'Cần chỉnh sửa lại',
99: 'Từ chối',
}
@ -83,7 +83,7 @@ export type PeDisplayStatus = typeof PeDisplayStatus[keyof typeof PeDisplayStatu
export const PeDisplayStatusLabel: Record<PeDisplayStatus, string> = {
Nhap: 'Nháp',
DaGuiDuyet: 'Đã gửi duyệt',
TraLai: 'Trả lại',
TraLai: 'Cần chỉnh sửa lại',
DaDuyet: 'Đã duyệt',
TuChoi: 'Từ chối',
}