"use client"; // 자재관리 > 자재리스트 — 자재이동 다이얼로그 // wace 1:1: materialMoveFormPopUp.jsp / saveInventoryMove.do // inventory_mgmt_in 행의 move_qty/move_date/move_user 누적 + 이동 이력 라인 추가 import React, { useEffect, useState } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Save, X } from "lucide-react"; import { toast } from "sonner"; import { NumberInput } from "@/components/common/NumberInput"; import { DateInput } from "@/components/common/DateInput"; import { Input } from "@/components/ui/input"; import { SmartSelect } from "@/components/common/SmartSelect"; import { inventoryMngApi, OptionItem } from "@/lib/api/inventoryMng"; interface MoveRow { in_objid: string; parent_objid: string; part_no: string; part_name: string; use_cnt: number; move_qty: number | ""; location: string; sub_location: string; move_date: string; move_user: string; } interface Props { open: boolean; onClose: () => void; onSaved: () => void; selectedRows: any[]; // 자재리스트에서 체크된 행 (objid 가 parent_objid) } export function MaterialMoveDialog({ open, onClose, onSaved, selectedRows }: Props) { const [rows, setRows] = useState([]); const [userOpts, setUserOpts] = useState([]); const [saving, setSaving] = useState(false); useEffect(() => { if (!open) return; setRows(selectedRows.map((r) => ({ in_objid: "", // 사용자가 in_objid 를 모를 수도 있어 parent 기준으로 1행 처리 후 첫 inventory_mgmt_in 사용 parent_objid: r.objid, part_no: r.part_no ?? "", part_name: r.part_name ?? "", use_cnt: Number(r.use_cnt ?? 0), move_qty: "", location: r.location ?? "", sub_location: r.sub_location ?? "", move_date: new Date().toISOString().slice(0, 10), move_user: "", }))); (async () => { try { setUserOpts(await inventoryMngApi.users()); } catch { /* skip */ } })(); }, [open, selectedRows]); const handleRowChange = (idx: number, patch: Partial) => setRows(rs => rs.map((r, i) => i === idx ? { ...r, ...patch } : r)); const handleSave = async () => { const items = rows.filter((r) => r.move_qty !== "" && Number(r.move_qty) > 0); if (!items.length) return toast.info("이동수량을 입력해주세요."); for (const r of items) { if (Number(r.move_qty) > r.use_cnt) { return toast.warning(`${r.part_no}: 보유수량(${r.use_cnt})보다 큰 이동수량은 불가합니다.`); } if (!r.move_user) { return toast.info(`${r.part_no}: 인수자를 선택해주세요.`); } } setSaving(true); try { // parent_objid 기준으로 백엔드가 첫 inventory_mgmt_in 행을 잡지 못하므로 // 일단 in_objid 가 비면 parent_objid 를 사용 (백엔드에서 fallback 처리). await inventoryMngApi.move(items.map((r) => ({ in_objid: r.parent_objid, move_qty: Number(r.move_qty), location: r.location, sub_location: r.sub_location, move_date: r.move_date, move_user: r.move_user, }))); toast.success("자재가 이동되었습니다."); onSaved(); onClose(); } catch (e: any) { toast.error(e?.response?.data?.message ?? e?.message ?? "이동 실패"); } finally { setSaving(false); } }; return ( !v && onClose()}> 자재 이동 선택한 자재의 이동수량/Location/인수자를 입력합니다.
{rows.map((r, i) => ( ))}
품번 품명 보유수량 이동수량 Location Sub 인계일 인수자
{r.part_no} {r.part_name} {r.use_cnt.toLocaleString()} handleRowChange(i, { move_qty: v })} /> handleRowChange(i, { location: e.target.value })} /> handleRowChange(i, { sub_location: e.target.value })} /> handleRowChange(i, { move_date: v })} /> handleRowChange(i, { move_user: v })} />
); }