From 3794d89da562f3419bcabd4d1215b1198180ae9e Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Thu, 6 Aug 2026 09:31:58 +0700 Subject: [PATCH] =?UTF-8?q?[CLAUDE]=20Contract:=20KHKK=20thung=20rac=20the?= =?UTF-8?q?o=20khuon=20man=20Duyet=20NCC=20=E2=80=94=20banner=20+=20dau=20?= =?UTF-8?q?xoa=20(FE-only,=200-mig)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Owner gui anh man "Da xoa" cua module Duyet NCC lam MAU ("anh chi la mau — em soi lai KHKK"). Do KHKK thieu 2 thu so voi mau: 1. Banner do "🗑 Phieu da xoa — chi xem. Khong khoi phuc, khong thao tac." PE co o PurchaseEvaluationsListPage:429; KHKK truoc do chi co tooltip hover o panel 2, khong co banner nhin thay duoc. 2. Dau "🗑 xoa ~ gio ngay" tren tung the. PE co o :584; KhkkPlanCard = 0 hit. Banner THAY dropdown trang thai khi xem thung rac (mirror PE): phieu giu NGUYEN phase luc bi xoa, `IsDeleted` moi la thu phan loai => loc trang thai o day la nut chet. Chinh `plansForPe` cung co y KHONG loc phase khi xem thung rac, nen de dropdown lai thi bam ma khong thay gi doi. 🔸 CO Y BO ve "khong con tinh vao luy ke ngan sach" cua ban PE: `grep 'lũy kế'` trong toan bo components/khkk + pages/khkk = 0 hit => be nguyen cau do la khai mot dieu chua chung minh cho module nay. Giu dung phan verify duoc tu chinh ma: khong khoi phuc, khong thao tac. 🔸 Dau xoa dung `updatedAt` chu KHONG phai `deletedAt`: API /deleted tra DTO DUNG CHUNG voi list song nen khong co `deletedAt`/`deletedBy` (KhkkListItemDto chi co createdAt + updatedAt). `AuditingInterceptor` ghi updatedAt ngay luot SaveChanges cua xoa mem => XAP XI. Nhan "~" de khong hua chinh xac; ten nguoi xoa API khong tra nen co y bo trong thay vi doan. Y het ly do ban PE. Co truyen o CA HAI cho dung the (than cay + danh sach phang) — thieu 1 cho la cung mot phieu hien khac nhau o 2 che-do. mirror sha256 khop; build xanh x2 app; tsc sach x2. Co-Authored-By: Claude Opus 5 --- .../src/components/khkk/KhkkListPanel.tsx | 55 +++++++++++++++---- fe-user/src/components/khkk/KhkkListPanel.tsx | 55 +++++++++++++++---- 2 files changed, 90 insertions(+), 20 deletions(-) diff --git a/fe-admin/src/components/khkk/KhkkListPanel.tsx b/fe-admin/src/components/khkk/KhkkListPanel.tsx index 37398a3..b1f4b6c 100644 --- a/fe-admin/src/components/khkk/KhkkListPanel.tsx +++ b/fe-admin/src/components/khkk/KhkkListPanel.tsx @@ -105,12 +105,15 @@ export function KhkkPlanCard({ selected, onSelect, finalize, + deleted, }: { plan: KhkkListItemDto selected: boolean onSelect: (id: string) => void /** Chỉ có khi phiếu ĐANG được chọn (detail đã tải) — list payload không mang cờ này. */ finalize?: { endedByLevelFinalize: boolean; finalizeStepName: string | null } + /** [S176] Đang xem thùng rác ⇒ hiện dấu thời-điểm xóa. Mirror khuôn màn Duyệt NCC. */ + deleted?: boolean }) { const frozen = plan.phase === KhkkPhase.DaDuyet const amount = frozen ? (plan.totalApprovedAmount ?? plan.totalProposedAmount) : plan.totalProposedAmount @@ -160,6 +163,22 @@ export function KhkkPlanCard({ )} · {formatDateTime(plan.createdAt)} + {/* [S176] "Xóa lúc" — mirror khuôn màn Duyệt NCC (`PurchaseEvaluationsListPage:573`). + 🔴 API `/contract-signing-plans/deleted` trả DTO DÙNG CHUNG với list sống ⇒ KHÔNG + có `deletedAt`/`deletedBy`. Mốc dưới là `updatedAt`, mà `AuditingInterceptor` ghi + ngay lượt SaveChanges của thao tác xóa mềm ⇒ XẤP XỈ thời điểm xóa. Nhãn "≈" để + KHÔNG hứa chính xác. Tên người xóa API không trả — cố ý bỏ trống thay vì đoán. */} + {deleted && plan.updatedAt && ( + <> + · + + 🗑 xóa ≈ {formatDateTime(plan.updatedAt)} + + + )}
👤 {plan.drafterFullName ?? '—'} @@ -293,6 +312,7 @@ export function KhkkListPanel({ selected={selectedId === k.id} onSelect={deletedView ? () => { /* phiếu đã xóa: chỉ liệt kê, không mở */ } : onSelect} finalize={selectedId === k.id ? selectedFinalize : undefined} + deleted={deletedView} /> ))} @@ -316,16 +336,30 @@ export function KhkkListPanel({ className="pl-8" />
- + {/* [S176] Thùng rác ⇒ THAY dropdown bằng banner, mirror khuôn màn Duyệt NCC + (`PurchaseEvaluationsListPage:427-431`). + 🔴 Ẩn dropdown là CÓ LÝ DO, không phải cho gọn: phiếu giữ NGUYÊN phase lúc bị xóa, + `IsDeleted` mới là thứ phân loại ⇒ lọc trạng thái ở đây là nút chết. Chính `plansForPe` + bên dưới cũng cố ý KHÔNG lọc phase khi xem thùng rác — để dropdown lại thì người dùng + bấm mà không thấy gì đổi. + 🔸 CỐ Ý BỎ vế "không còn tính vào lũy kế ngân sách" của bản PE: `grep 'lũy kế'` trong + toàn bộ KHKK = 0 hit ⇒ bê nguyên là khai một điều chưa chứng minh cho module này. */} + {deletedView ? ( +
+ 🗑 Phiếu đã xóa — chỉ xem. Không khôi phục, không thao tác. +
+ ) : ( + + )} {/* 🧊 [S175] Dòng "Đang lọc — danh sách lấy thẳng từ máy chủ…" ĐÃ GỠ (anh: "Bỏ mấy dòng này đi"). Đó là chú-thích về CƠ-CHẾ bên trong, người dùng không cần biết cây tải 200 phiếu hay lấy thẳng máy chủ — họ chỉ cần thấy đúng phiếu. */} @@ -412,6 +446,7 @@ export function KhkkListPanel({ selected={selectedId === k.id} onSelect={deletedView ? () => { /* phiếu đã xóa: chỉ liệt kê, không mở */ } : onSelect} finalize={selectedId === k.id ? selectedFinalize : undefined} + deleted={deletedView} /> ))} diff --git a/fe-user/src/components/khkk/KhkkListPanel.tsx b/fe-user/src/components/khkk/KhkkListPanel.tsx index 37398a3..b1f4b6c 100644 --- a/fe-user/src/components/khkk/KhkkListPanel.tsx +++ b/fe-user/src/components/khkk/KhkkListPanel.tsx @@ -105,12 +105,15 @@ export function KhkkPlanCard({ selected, onSelect, finalize, + deleted, }: { plan: KhkkListItemDto selected: boolean onSelect: (id: string) => void /** Chỉ có khi phiếu ĐANG được chọn (detail đã tải) — list payload không mang cờ này. */ finalize?: { endedByLevelFinalize: boolean; finalizeStepName: string | null } + /** [S176] Đang xem thùng rác ⇒ hiện dấu thời-điểm xóa. Mirror khuôn màn Duyệt NCC. */ + deleted?: boolean }) { const frozen = plan.phase === KhkkPhase.DaDuyet const amount = frozen ? (plan.totalApprovedAmount ?? plan.totalProposedAmount) : plan.totalProposedAmount @@ -160,6 +163,22 @@ export function KhkkPlanCard({ )} · {formatDateTime(plan.createdAt)} + {/* [S176] "Xóa lúc" — mirror khuôn màn Duyệt NCC (`PurchaseEvaluationsListPage:573`). + 🔴 API `/contract-signing-plans/deleted` trả DTO DÙNG CHUNG với list sống ⇒ KHÔNG + có `deletedAt`/`deletedBy`. Mốc dưới là `updatedAt`, mà `AuditingInterceptor` ghi + ngay lượt SaveChanges của thao tác xóa mềm ⇒ XẤP XỈ thời điểm xóa. Nhãn "≈" để + KHÔNG hứa chính xác. Tên người xóa API không trả — cố ý bỏ trống thay vì đoán. */} + {deleted && plan.updatedAt && ( + <> + · + + 🗑 xóa ≈ {formatDateTime(plan.updatedAt)} + + + )}
👤 {plan.drafterFullName ?? '—'} @@ -293,6 +312,7 @@ export function KhkkListPanel({ selected={selectedId === k.id} onSelect={deletedView ? () => { /* phiếu đã xóa: chỉ liệt kê, không mở */ } : onSelect} finalize={selectedId === k.id ? selectedFinalize : undefined} + deleted={deletedView} /> ))} @@ -316,16 +336,30 @@ export function KhkkListPanel({ className="pl-8" />
- + {/* [S176] Thùng rác ⇒ THAY dropdown bằng banner, mirror khuôn màn Duyệt NCC + (`PurchaseEvaluationsListPage:427-431`). + 🔴 Ẩn dropdown là CÓ LÝ DO, không phải cho gọn: phiếu giữ NGUYÊN phase lúc bị xóa, + `IsDeleted` mới là thứ phân loại ⇒ lọc trạng thái ở đây là nút chết. Chính `plansForPe` + bên dưới cũng cố ý KHÔNG lọc phase khi xem thùng rác — để dropdown lại thì người dùng + bấm mà không thấy gì đổi. + 🔸 CỐ Ý BỎ vế "không còn tính vào lũy kế ngân sách" của bản PE: `grep 'lũy kế'` trong + toàn bộ KHKK = 0 hit ⇒ bê nguyên là khai một điều chưa chứng minh cho module này. */} + {deletedView ? ( +
+ 🗑 Phiếu đã xóa — chỉ xem. Không khôi phục, không thao tác. +
+ ) : ( + + )} {/* 🧊 [S175] Dòng "Đang lọc — danh sách lấy thẳng từ máy chủ…" ĐÃ GỠ (anh: "Bỏ mấy dòng này đi"). Đó là chú-thích về CƠ-CHẾ bên trong, người dùng không cần biết cây tải 200 phiếu hay lấy thẳng máy chủ — họ chỉ cần thấy đúng phiếu. */} @@ -412,6 +446,7 @@ export function KhkkListPanel({ selected={selectedId === k.id} onSelect={deletedView ? () => { /* phiếu đã xóa: chỉ liệt kê, không mở */ } : onSelect} finalize={selectedId === k.id ? selectedFinalize : undefined} + deleted={deletedView} /> ))}