[CLAUDE] Contract: K2 SP-002 phieu KHKK mang hang-muc + nhom duyet N1-8 (Mig 71) + FE x2 app + 11 test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m12s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m12s
Mig 71 AddKhkkApprovalGroupCatalogAndFinalizeRuntime: +ApprovalGroup (backfill=1)
+EndedByLevelFinalize (K2 de, K3 tieu - ghost-window khai) + Line +CatalogEntryId/
TenHangMuc + unique (Plan,Supplier,CatalogEntry) filtered IsDeleted=0. Rao
1-PE-1-phieu doi (PeId,ApprovalGroup) 2 site + picker OG-7 ExistingGroups + nut
'Tao them cho nhom khac'. Submit-guard va-5 (CHAN null, thang nen cho-qua-legacy;
ghost-window K2->K4b khai) + dem-so-khop (gate F-1: bit duong hang-muc xoa-mem).
List ?group= end-to-end + Tong-Approved list (va-8). FE: select nhom default 1 +
badge N{g} + cot Hang-muc + cot Tong-duyet, SHA-pair 5/5. Gate K2 PASS-WITH-FLAGS
10f: F-1 guard fix + 2 test bit (xoa-mem chan + reflection ?group=); F-2/F-5/F-7/
F-8/F-9 comment-honest; F-3/F-4 docs-delta. Suite 609/0 (45D+564I). Wave co #53 x5,
artifact + relaunch-cat-got cuu 100% (0 mat cong).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@ -25,6 +25,7 @@ import { PipelineTreePanel } from '@/components/pipeline/PipelineTreePanel'
|
||||
import { api } from '@/lib/api'
|
||||
import { cn } from '@/lib/cn'
|
||||
import {
|
||||
KHKK_APPROVAL_GROUP_LABELS,
|
||||
KHKK_PHASE_BADGE,
|
||||
KHKK_PHASE_LABELS,
|
||||
KhkkPhase,
|
||||
@ -134,7 +135,7 @@ export function KhkkListPage() {
|
||||
|
||||
{/* [S162] Cây toàn trình bám trái + nội dung cũ giữ nguyên bên phải (owner
|
||||
chốt AskUser 30-07: "áp cả các trang GĐ khác"). `minmax(0,1fr)` để bảng
|
||||
7 cột không thổi vỡ lưới ở 1366; `<lg` cây xếp trên và tự thu gọn. */}
|
||||
8 cột không thổi vỡ lưới ở 1366; `<lg` cây xếp trên và tự thu gọn. */}
|
||||
<div className="grid gap-5 lg:grid-cols-[19rem_minmax(0,1fr)] xl:grid-cols-[21rem_minmax(0,1fr)]">
|
||||
<PipelineTreePanel currentStage={2} />
|
||||
|
||||
@ -172,7 +173,7 @@ export function KhkkListPage() {
|
||||
</div>
|
||||
|
||||
<div className="card-accent overflow-hidden" style={{ ['--accent' as string]: 'var(--color-brand-500)' }}>
|
||||
{/* [S162] Cột trái ăn ~19rem ⇒ bảng 7 cột cuộn ngang trong thẻ thay vì
|
||||
{/* [S162] Cột trái ăn ~19rem ⇒ bảng 8 cột cuộn ngang trong thẻ thay vì
|
||||
tràn ra ngoài lưới trên laptop 1366. */}
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm">
|
||||
@ -183,6 +184,10 @@ export function KhkkListPage() {
|
||||
<th className="label-eyebrow px-4 py-2.5 text-left">Dự án</th>
|
||||
<th className="label-eyebrow px-4 py-2.5 text-left">Trạng thái</th>
|
||||
<th className="label-eyebrow px-4 py-2.5 text-right">Tổng đề xuất</th>
|
||||
{/* [K2 S164 — vá-8] Σ `ApprovedAmount` (`ListItemDto:64`). Không có cột này
|
||||
thì màn danh sách nói "Tổng đề xuất" còn màn chi tiết nói "Giá duyệt"
|
||||
trên CÙNG một phiếu đã duyệt ⇒ người dùng đọc ra hai con số. */}
|
||||
<th className="label-eyebrow px-4 py-2.5 text-right">Tổng duyệt</th>
|
||||
<th className="label-eyebrow px-4 py-2.5 text-left">Người soạn</th>
|
||||
<th className="label-eyebrow px-4 py-2.5 text-left">Ngày tạo</th>
|
||||
</tr>
|
||||
@ -190,14 +195,14 @@ export function KhkkListPage() {
|
||||
<tbody>
|
||||
{list.isLoading && (
|
||||
<tr>
|
||||
<td colSpan={7} className="px-4 py-8 text-center text-slate-500">
|
||||
<td colSpan={8} className="px-4 py-8 text-center text-slate-500">
|
||||
Đang tải...
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{!list.isLoading && items.length === 0 && (
|
||||
<tr>
|
||||
<td colSpan={7} className="px-4 py-10 text-center text-slate-500">
|
||||
<td colSpan={8} className="px-4 py-10 text-center text-slate-500">
|
||||
<span
|
||||
className="icon-chip mx-auto mb-2 flex"
|
||||
style={{ ['--chip-bg' as string]: '#f1f5f9', ['--chip-fg' as string]: '#94a3b8' }}
|
||||
@ -228,6 +233,18 @@ export function KhkkListPage() {
|
||||
<FileCheck className="h-3.5 w-3.5" />
|
||||
</span>
|
||||
<span className="font-mono text-xs text-brand-800">{k.maKeHoach ?? '—'}</span>
|
||||
{/* [K2 S164] Badge NHÓM DUYỆT — đặt cạnh mã thay vì đẻ cột thứ 9:
|
||||
bảng này đã cuộn ngang ở 1366 khi có cây bên trái (ghi chú S162).
|
||||
`!= null` guard cho payload cũ còn trong cache React Query (trước
|
||||
K2 DTO chưa có field) — thiếu guard thì in ra "Nundefined". */}
|
||||
{k.approvalGroup != null && (
|
||||
<span
|
||||
className="inline-flex items-center rounded border border-violet-300 bg-violet-100 px-1.5 py-0.5 text-[10px] font-semibold text-violet-800"
|
||||
title={KHKK_APPROVAL_GROUP_LABELS[k.approvalGroup] ?? `Nhóm ${k.approvalGroup}`}
|
||||
>
|
||||
N{k.approvalGroup}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
</td>
|
||||
<td className="max-w-xs truncate px-4 py-2.5 font-medium text-brand-800">
|
||||
@ -249,6 +266,11 @@ export function KhkkListPage() {
|
||||
)}
|
||||
</td>
|
||||
<td className="px-4 py-2.5 text-right tabular-nums text-brand-800">{formatVnd(k.totalProposedAmount)}</td>
|
||||
{/* Phiếu chưa duyệt BE trả 0 (không phải null) ⇒ ép về "—" cho khỏi đọc
|
||||
nhầm "đã duyệt 0 đ"; số chỉ hiện khi thật sự có tiền đã chốt. */}
|
||||
<td className="px-4 py-2.5 text-right tabular-nums text-emerald-700">
|
||||
{k.totalApprovedAmount ? formatVnd(k.totalApprovedAmount) : '—'}
|
||||
</td>
|
||||
<td className="px-4 py-2.5 text-xs text-slate-600">{k.drafterFullName ?? '—'}</td>
|
||||
<td className="px-4 py-2.5 text-xs text-slate-600">{formatDate(k.createdAt)}</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user