[CLAUDE] PurchaseEvaluation: gop Ten goi thau = chon Hang muc cong viec (anh Kiet FDC chot 14:06) - 1 select set ca workItemId + tenGoiThau, phieu cu giu-nguyen null-safe, SHA256 mirror x2 app (S58)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m24s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m24s
This commit is contained in:
@ -185,12 +185,30 @@ export function PeHeaderForm({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Label>Tên gói thầu *</Label>
|
{/* [S58] anh Kiệt (FDC) chốt 06-11: "Hạng mục công việc CHÍNH LÀ tên gói
|
||||||
<Input
|
thầu" → gộp 2 field S57bis thành 1 select: chọn hạng mục set cả
|
||||||
value={form.tenGoiThau}
|
workItemId + tenGoiThau (= tên hạng mục). Phiếu cũ (workItemId null,
|
||||||
onChange={e => setForm({ ...form, tenGoiThau: e.target.value })}
|
tên nhập tay): option đầu "Giữ nguyên" — không ép đổi, PUT null-safe. */}
|
||||||
placeholder="vd Cung cấp bê tông"
|
<Label>Tên gói thầu (Hạng mục công việc) *</Label>
|
||||||
/>
|
<Select
|
||||||
|
value={form.workItemId}
|
||||||
|
onChange={e => {
|
||||||
|
const id = e.target.value
|
||||||
|
const w = workItems.data?.find(x => x.id === id)
|
||||||
|
setForm({ ...form, workItemId: id, tenGoiThau: id ? (w?.name ?? '') : (editId ? form.tenGoiThau : '') })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="">
|
||||||
|
{editId && form.tenGoiThau && !form.workItemId
|
||||||
|
? `Giữ nguyên: ${form.tenGoiThau}`
|
||||||
|
: '-- Chọn hạng mục công việc --'}
|
||||||
|
</option>
|
||||||
|
{workItems.data?.map(w => (
|
||||||
|
<option key={w.id} value={w.id}>
|
||||||
|
{w.category ? `[${w.category}] ` : ''}{w.code} — {w.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -207,23 +225,6 @@ export function PeHeaderForm({
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
{/* S57bis — phiếu dạng "Dự án – Hạng mục công việc" (sếp chốt). Edit-mode
|
|
||||||
CHO đổi (BE UpdateDraft hỗ trợ); phiếu cũ null → bắt đầu rỗng, không ép. */}
|
|
||||||
<Label>Hạng mục công việc {!editId && '*'}</Label>
|
|
||||||
<Select
|
|
||||||
value={form.workItemId}
|
|
||||||
onChange={e => setForm({ ...form, workItemId: e.target.value })}
|
|
||||||
>
|
|
||||||
<option value="">{editId ? '— (giữ nguyên / chưa gắn)' : '-- Chọn --'}</option>
|
|
||||||
{workItems.data?.map(w => (
|
|
||||||
<option key={w.id} value={w.id}>
|
|
||||||
{w.category ? `[${w.category}] ` : ''}{w.code} — {w.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-1.5 flex items-center justify-between">
|
<div className="mb-1.5 flex items-center justify-between">
|
||||||
<Label className="mb-0">Ngân sách (đối chiếu chi phí)</Label>
|
<Label className="mb-0">Ngân sách (đối chiếu chi phí)</Label>
|
||||||
|
|||||||
@ -93,8 +93,7 @@ export function PeWorkspaceCreateView({
|
|||||||
select: rows => rows.filter(r => r.isActive !== false),
|
select: rows => rows.filter(r => r.isActive !== false),
|
||||||
})
|
})
|
||||||
|
|
||||||
// Mig 23 — fetch list quy trình duyệt V2 cho User chọn (filter theo
|
// Mig 23 — fetch list quy trình duyệt V2 (filter ApplicableType khớp defaultType).
|
||||||
// ApplicableType khớp với defaultType: 1=DuyetNcc / 2=DuyetNccPhuongAn).
|
|
||||||
// Mig 25 — chỉ hiện workflows admin đã ghim "cho user chọn" (IsUserSelectable=true).
|
// Mig 25 — chỉ hiện workflows admin đã ghim "cho user chọn" (IsUserSelectable=true).
|
||||||
const approvalWorkflows = useQuery({
|
const approvalWorkflows = useQuery({
|
||||||
queryKey: ['approval-workflows-v2-active', defaultType],
|
queryKey: ['approval-workflows-v2-active', defaultType],
|
||||||
@ -186,36 +185,23 @@ export function PeWorkspaceCreateView({
|
|||||||
</Select>
|
</Select>
|
||||||
{approvalWorkflows.data && approvalWorkflows.data.length === 0 && (
|
{approvalWorkflows.data && approvalWorkflows.data.length === 0 && (
|
||||||
<p className="mt-1 text-[11px] text-amber-700">
|
<p className="mt-1 text-[11px] text-amber-700">
|
||||||
⚠ Chưa có quy trình duyệt cho loại {PurchaseEvaluationTypeLabel[form.type]}. Vào{' '}
|
⚠ Chưa có quy trình duyệt cho loại {PurchaseEvaluationTypeLabel[form.type]}. Liên hệ admin tạo trước.
|
||||||
<span className="font-mono">/system/approval-workflows-v2</span> để tạo trước.
|
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="md:col-span-2">
|
<div className="md:col-span-2">
|
||||||
<Label className="text-[11px]">a. Tên gói thầu *</Label>
|
{/* [S58] anh Kiệt (FDC) chốt 06-11: "Hạng mục công việc CHÍNH LÀ tên
|
||||||
<Input
|
gói thầu" → gộp field c (S57bis) vào a: chọn từ danh mục Hạng mục
|
||||||
value={form.tenGoiThau}
|
thay nhập tay; chọn 1 phát set cả workItemId + tenGoiThau (= tên
|
||||||
onChange={e => setForm({ ...form, tenGoiThau: e.target.value })}
|
hạng mục). Phiếu vẫn lưu cả 2 field BE — không đổi contract. */}
|
||||||
placeholder="vd Cung cấp bê tông"
|
<Label className="text-[11px]">a. Tên gói thầu (Hạng mục công việc) *</Label>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="md:col-span-2">
|
|
||||||
<Label className="text-[11px]">b. Dự án *</Label>
|
|
||||||
<Select
|
|
||||||
value={form.projectId}
|
|
||||||
onChange={e => setForm({ ...form, projectId: e.target.value, budgetId: '' })}
|
|
||||||
>
|
|
||||||
<option value="">— Chọn dự án —</option>
|
|
||||||
{projects.data?.map(p => (
|
|
||||||
<option key={p.id} value={p.id}>{p.code} — {p.name}</option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div className="md:col-span-2">
|
|
||||||
<Label className="text-[11px]">c. Hạng mục công việc *</Label>
|
|
||||||
<Select
|
<Select
|
||||||
value={form.workItemId}
|
value={form.workItemId}
|
||||||
onChange={e => setForm({ ...form, workItemId: e.target.value })}
|
onChange={e => {
|
||||||
|
const id = e.target.value
|
||||||
|
const w = workItems.data?.find(x => x.id === id)
|
||||||
|
setForm({ ...form, workItemId: id, tenGoiThau: id ? (w?.name ?? '') : '' })
|
||||||
|
}}
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
<option value="">— Chọn hạng mục công việc —</option>
|
<option value="">— Chọn hạng mục công việc —</option>
|
||||||
@ -231,6 +217,18 @@ export function PeWorkspaceCreateView({
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="md:col-span-2">
|
||||||
|
<Label className="text-[11px]">b. Dự án *</Label>
|
||||||
|
<Select
|
||||||
|
value={form.projectId}
|
||||||
|
onChange={e => setForm({ ...form, projectId: e.target.value, budgetId: '' })}
|
||||||
|
>
|
||||||
|
<option value="">— Chọn dự án —</option>
|
||||||
|
{projects.data?.map(p => (
|
||||||
|
<option key={p.id} value={p.id}>{p.code} — {p.name}</option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-[11px]">Địa điểm</Label>
|
<Label className="text-[11px]">Địa điểm</Label>
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
@ -185,12 +185,30 @@ export function PeHeaderForm({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Label>Tên gói thầu *</Label>
|
{/* [S58] anh Kiệt (FDC) chốt 06-11: "Hạng mục công việc CHÍNH LÀ tên gói
|
||||||
<Input
|
thầu" → gộp 2 field S57bis thành 1 select: chọn hạng mục set cả
|
||||||
value={form.tenGoiThau}
|
workItemId + tenGoiThau (= tên hạng mục). Phiếu cũ (workItemId null,
|
||||||
onChange={e => setForm({ ...form, tenGoiThau: e.target.value })}
|
tên nhập tay): option đầu "Giữ nguyên" — không ép đổi, PUT null-safe. */}
|
||||||
placeholder="vd Cung cấp bê tông"
|
<Label>Tên gói thầu (Hạng mục công việc) *</Label>
|
||||||
/>
|
<Select
|
||||||
|
value={form.workItemId}
|
||||||
|
onChange={e => {
|
||||||
|
const id = e.target.value
|
||||||
|
const w = workItems.data?.find(x => x.id === id)
|
||||||
|
setForm({ ...form, workItemId: id, tenGoiThau: id ? (w?.name ?? '') : (editId ? form.tenGoiThau : '') })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="">
|
||||||
|
{editId && form.tenGoiThau && !form.workItemId
|
||||||
|
? `Giữ nguyên: ${form.tenGoiThau}`
|
||||||
|
: '-- Chọn hạng mục công việc --'}
|
||||||
|
</option>
|
||||||
|
{workItems.data?.map(w => (
|
||||||
|
<option key={w.id} value={w.id}>
|
||||||
|
{w.category ? `[${w.category}] ` : ''}{w.code} — {w.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -207,23 +225,6 @@ export function PeHeaderForm({
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
{/* S57bis — phiếu dạng "Dự án – Hạng mục công việc" (sếp chốt). Edit-mode
|
|
||||||
CHO đổi (BE UpdateDraft hỗ trợ); phiếu cũ null → bắt đầu rỗng, không ép. */}
|
|
||||||
<Label>Hạng mục công việc {!editId && '*'}</Label>
|
|
||||||
<Select
|
|
||||||
value={form.workItemId}
|
|
||||||
onChange={e => setForm({ ...form, workItemId: e.target.value })}
|
|
||||||
>
|
|
||||||
<option value="">{editId ? '— (giữ nguyên / chưa gắn)' : '-- Chọn --'}</option>
|
|
||||||
{workItems.data?.map(w => (
|
|
||||||
<option key={w.id} value={w.id}>
|
|
||||||
{w.category ? `[${w.category}] ` : ''}{w.code} — {w.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-1.5 flex items-center justify-between">
|
<div className="mb-1.5 flex items-center justify-between">
|
||||||
<Label className="mb-0">Ngân sách (đối chiếu chi phí)</Label>
|
<Label className="mb-0">Ngân sách (đối chiếu chi phí)</Label>
|
||||||
|
|||||||
@ -190,30 +190,18 @@ export function PeWorkspaceCreateView({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="md:col-span-2">
|
<div className="md:col-span-2">
|
||||||
<Label className="text-[11px]">a. Tên gói thầu *</Label>
|
{/* [S58] anh Kiệt (FDC) chốt 06-11: "Hạng mục công việc CHÍNH LÀ tên
|
||||||
<Input
|
gói thầu" → gộp field c (S57bis) vào a: chọn từ danh mục Hạng mục
|
||||||
value={form.tenGoiThau}
|
thay nhập tay; chọn 1 phát set cả workItemId + tenGoiThau (= tên
|
||||||
onChange={e => setForm({ ...form, tenGoiThau: e.target.value })}
|
hạng mục). Phiếu vẫn lưu cả 2 field BE — không đổi contract. */}
|
||||||
placeholder="vd Cung cấp bê tông"
|
<Label className="text-[11px]">a. Tên gói thầu (Hạng mục công việc) *</Label>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="md:col-span-2">
|
|
||||||
<Label className="text-[11px]">b. Dự án *</Label>
|
|
||||||
<Select
|
|
||||||
value={form.projectId}
|
|
||||||
onChange={e => setForm({ ...form, projectId: e.target.value, budgetId: '' })}
|
|
||||||
>
|
|
||||||
<option value="">— Chọn dự án —</option>
|
|
||||||
{projects.data?.map(p => (
|
|
||||||
<option key={p.id} value={p.id}>{p.code} — {p.name}</option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div className="md:col-span-2">
|
|
||||||
<Label className="text-[11px]">c. Hạng mục công việc *</Label>
|
|
||||||
<Select
|
<Select
|
||||||
value={form.workItemId}
|
value={form.workItemId}
|
||||||
onChange={e => setForm({ ...form, workItemId: e.target.value })}
|
onChange={e => {
|
||||||
|
const id = e.target.value
|
||||||
|
const w = workItems.data?.find(x => x.id === id)
|
||||||
|
setForm({ ...form, workItemId: id, tenGoiThau: id ? (w?.name ?? '') : '' })
|
||||||
|
}}
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
<option value="">— Chọn hạng mục công việc —</option>
|
<option value="">— Chọn hạng mục công việc —</option>
|
||||||
@ -229,6 +217,18 @@ export function PeWorkspaceCreateView({
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="md:col-span-2">
|
||||||
|
<Label className="text-[11px]">b. Dự án *</Label>
|
||||||
|
<Select
|
||||||
|
value={form.projectId}
|
||||||
|
onChange={e => setForm({ ...form, projectId: e.target.value, budgetId: '' })}
|
||||||
|
>
|
||||||
|
<option value="">— Chọn dự án —</option>
|
||||||
|
{projects.data?.map(p => (
|
||||||
|
<option key={p.id} value={p.id}>{p.code} — {p.name}</option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-[11px]">Địa điểm</Label>
|
<Label className="text-[11px]">Địa điểm</Label>
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
Reference in New Issue
Block a user