From e33481efb6b82144b165be8b9bc4ca013157b3ec Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Fri, 19 Jun 2026 11:02:47 +0700 Subject: [PATCH] [CLAUDE] PurchaseEvaluation: Mig 56 ngan sach MA TRAN 3 cot (Du an|PRO|CCM) + badge quyen NS theo role MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit S76 (anh Kiet FDC + chi Tra Sol) — form ngan sach + hien thi quyen nhap NS trong flow: - Part 1: form ngan sach -> MA TRAN 3 cot, moi phong nhap+dieu chinh cot minh (PRO canEditPro / CCM canEditCcm / Du an FE hien-thi-only). Mig 56 +ProInitialAmount/ProAdjustmentAmount (additive-nullable + data-migrate ProEstimate->ProInitial). full moi cot = ban hanh + hieu chinh. - Part 2: Workflow Designer (fe-admin) +badge "NS PRO/CCM" canh approver (suy tu role Admin|Procurement / Admin|CostControl, hien-thi-only no-authz). - Part 3: flow quy trinh fe-user/fe-admin (Duyet NCC) +badge tuong tu. - Fix race mat-du-lieu Part 1 (useIsFetching khoa Luu khi refetch — dong cua-so stale-echo, reviewer Part2/3 bat). - Test 339->344 (+5). 2 workflow review (Part 1 PASS + Part 2/3 PASS). Co-Authored-By: Claude Opus 4.8 --- .gitignore | 6 + fe-admin/src/components/pe/PeDetailTabs.tsx | 312 +- .../src/components/pe/PeWorkflowPanel.tsx | 18 +- .../pages/system/ApprovalWorkflowsV2Page.tsx | 12 +- fe-admin/src/types/purchaseEvaluation.ts | 25 +- fe-user/src/components/pe/PeDetailTabs.tsx | 312 +- fe-user/src/components/pe/PeWorkflowPanel.tsx | 18 +- fe-user/src/types/purchaseEvaluation.ts | 25 +- .../PurchaseEvaluationsController.cs | 4 +- .../ApprovalWorkflowV2AdminFeatures.cs | 17 +- .../Dtos/PurchaseEvaluationDtos.cs | 11 +- .../PeWorkItemBudgetFeatures.cs | 26 +- .../PurchaseEvaluationFeatures.cs | 28 +- .../PurchaseEvaluations/PeWorkItemBudget.cs | 23 +- .../PeWorkItemBudgetConfiguration.cs | 2 + ...oBudgetSplitToPeWorkItemBudget.Designer.cs | 6251 +++++++++++++++++ ...427_AddProBudgetSplitToPeWorkItemBudget.cs | 51 + .../ApplicationDbContextModelSnapshot.cs | 8 + .../Application/PeWorkItemBudgetTests.cs | 150 +- 19 files changed, 6974 insertions(+), 325 deletions(-) create mode 100644 src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/20260619024427_AddProBudgetSplitToPeWorkItemBudget.Designer.cs create mode 100644 src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/20260619024427_AddProBudgetSplitToPeWorkItemBudget.cs diff --git a/.gitignore b/.gitignore index 226d429..be34a0a 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,9 @@ src/Backend/SolutionErp.Api/wwwroot/exports/ # Sub-agent output dumps (JSON/HTML scratch) tmp/ + +# [S76] Guard cwd-misland (feedback_agent_cwd_relative_memory_misland): sub-agent `cd` +# vào fe-user/fe-admin chạy npm build rồi ghi MEMORY.md relative-path → stray +# `fe-*/.claude/agent-memory/...`. Canonical agent-memory ở ROOT `.claude/` vẫn tracked +# (negation `!.claude/**` trên). Pattern AFTER negation → last-match-wins cho path FE-app. +fe-*/.claude/ diff --git a/fe-admin/src/components/pe/PeDetailTabs.tsx b/fe-admin/src/components/pe/PeDetailTabs.tsx index 3288152..949d679 100644 --- a/fe-admin/src/components/pe/PeDetailTabs.tsx +++ b/fe-admin/src/components/pe/PeDetailTabs.tsx @@ -3,7 +3,7 @@ // Duyệt history + Lịch sử thay đổi → moved to Panel 3 (xem PeWorkflowPanel // → PeApprovalsSection + PeHistorySection). import { useEffect, useMemo, useRef, useState } from 'react' -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import { useIsFetching, useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useNavigate } from 'react-router-dom' import { toast } from 'sonner' import { Check, ChevronDown, ChevronRight, Download, Eye, Paperclip, Pencil, Plus, Trash2, Upload } from 'lucide-react' @@ -1057,9 +1057,106 @@ function BudgetBlockHeader({ children }: { children: React.ReactNode }) { ) } +// [S76] Ô tiền compact cho ma trận 3 cột — editable (input + nút Lưu) hoặc display. +// allowNegative cho "hiệu chỉnh tăng giảm" (nút ± đảo dấu). onSave nhận number|null. +function BudgetCell({ value, editable, allowNegative = false, saving, onSave }: { + value: number | null + editable: boolean + allowNegative?: boolean + saving: boolean + onSave: (v: number | null) => void +}) { + const [text, setText] = useState(value != null ? Math.abs(value).toLocaleString('vi-VN') : '') + const [neg, setNeg] = useState((value ?? 0) < 0) + useEffect(() => { + setText(value != null ? Math.abs(value).toLocaleString('vi-VN') : '') + setNeg((value ?? 0) < 0) + }, [value]) + if (!editable) { + return value != null + ? {fmtVndSigned(value)} + : + } + const parse = (): number | null => { + const n = parseVnd(text) + if (n === 0 && text.trim() === '') return null + return allowNegative && neg ? -n : n + } + const dirty = parse() !== value + return ( +
+ {allowNegative && ( + + )} + setText(e.target.value.replace(/[^\d.]/g, ''))} + placeholder="0" + className="h-7 min-w-0 px-1.5 text-right font-mono text-[12px]" + /> + +
+ ) +} + +// [S76] Dòng ghi chú phòng (Ghi chú từ PRO / từ CCM) — Textarea editable hoặc text display. +function BudgetNoteRow({ label, editable, value, setValue, savedValue, saving, onSave }: { + label: string + editable: boolean + value: string + setValue: (v: string) => void + savedValue: string | null + saving: boolean + onSave: () => void +}) { + return ( +
+
{label}
+
+ {editable ? ( +
+