"use client"; // 영업관리 > 구매요청서관리 — 품의서생성 확인 다이얼로그 // wace 1:1: createProposalFromPurchaseReg.do — 선택된 PURCHASE_REG 의 단가+공급업체 입력 품목만 필터해 // PURCHASE_REG_PROPOSAL row 신규 생성. 단가 또는 공급업체가 없는 품목은 제외 목록으로 표시. import React, { useEffect, useState } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { ClipboardCheck, X, AlertTriangle } from "lucide-react"; import { toast } from "sonner"; import { salesPurchaseRequestApi, ProposalTargetPart } from "@/lib/api/salesPurchaseRequest"; interface Props { open: boolean; onClose: () => void; srmObjid: string; // 원본 구매요청서 OBJID requestMngNo?: string; onCreated: (proposalNo: string) => void; } export function ProposalCreateDialog({ open, onClose, srmObjid, requestMngNo, onCreated }: Props) { const [loading, setLoading] = useState(false); const [submitting, setSubmitting] = useState(false); const [targets, setTargets] = useState([]); const [excluded, setExcluded] = useState([]); useEffect(() => { if (!open || !srmObjid) return; setTargets([]); setExcluded([]); setLoading(true); (async () => { try { const data = await salesPurchaseRequestApi.getProposalTargets(srmObjid); setTargets(data.targets ?? []); setExcluded(data.excluded ?? []); } catch (e: any) { toast.error(e?.response?.data?.message ?? e?.message ?? "조회 실패"); } finally { setLoading(false); } })(); }, [open, srmObjid]); const handleCreate = async () => { setSubmitting(true); try { const res = await salesPurchaseRequestApi.createProposal(srmObjid); toast.success(`품의서가 생성되었습니다. (${res.proposal_no})`); onCreated(res.proposal_no); onClose(); } catch (e: any) { toast.error(e?.response?.data?.message ?? e?.message ?? "생성 실패"); } finally { setSubmitting(false); } }; const sumTotal = targets.reduce((s, r) => s + (Number(r.total_price ?? 0) || Number(r.unit_price ?? 0) * Number(r.qty ?? 0)), 0); return ( { if (!o) onClose(); }}> 품의서 생성 {requestMngNo ? `${requestMngNo} 의 ` : ""} 단가 및 공급업체가 입력된 품목으로 품의서를 생성합니다. {loading ? (
대상 품목 조회 중...
) : ( <>
{targets.length > 0 && ( {targets.map((r) => ( ))}
품번 품명 수량 단가 총액 공급업체
{r.part_no} {r.part_name} {fmt(r.qty)} {fmtMoney(r.unit_price)} {fmtMoney(Number(r.total_price ?? 0) || Number(r.unit_price ?? 0) * Number(r.qty ?? 0))} {r.vendor_name || r.vendor_pm}
합계 {fmtMoney(sumTotal)}
)}
{excluded.length > 0 && (
제외 품목 — 공급업체 미입력 ({excluded.length}건) } emptyMsg="" > {excluded.map((r) => ( ))}
품번 품명 수량 단가
{r.part_no} {r.part_name} {fmt(r.qty)} {fmtMoney(r.unit_price)}
)} )}
); } function Section({ title, emptyMsg, children }: { title: React.ReactNode; emptyMsg: string; children: React.ReactNode }) { const hasChildren = React.Children.count(children) > 0; return (
{title}
{hasChildren ? children : (
{emptyMsg}
)}
); } // 수량: 자연수 1,234 / 금액: 1,234.00 (RPS 숫자 포맷 정책) function fmt(n: any) { const v = Math.floor(Number(n ?? 0)); return v.toLocaleString("ko-KR"); } function fmtMoney(n: any) { const v = Number(n ?? 0); return v.toLocaleString("ko-KR", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); }