diff --git a/src/components/material/ReceivingManagement/ImportInspectionInputModal.tsx b/src/components/material/ReceivingManagement/ImportInspectionInputModal.tsx index 25090005..a4740820 100644 --- a/src/components/material/ReceivingManagement/ImportInspectionInputModal.tsx +++ b/src/components/material/ReceivingManagement/ImportInspectionInputModal.tsx @@ -18,6 +18,8 @@ import { DialogContent, DialogHeader, DialogTitle, + VisuallyHidden, + DialogDescription, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; @@ -668,7 +670,13 @@ export function ImportInspectionInputModal({ // 캡처 실패 시 무시 — rendered_html 없이 저장 진행 } - // 5. 저장 API 호출 + // 5. 저장 API 호출 (rendered_html이 너무 크면 제외 — 413 방지) + const MAX_HTML_SIZE = 500 * 1024; // 500KB 제한 + const safeHtml = renderedHtml && renderedHtml.length <= MAX_HTML_SIZE ? renderedHtml : undefined; + if (renderedHtml && renderedHtml.length > MAX_HTML_SIZE) { + console.warn(`[ImportInspection] rendered_html 크기 초과 (${(renderedHtml.length / 1024).toFixed(0)}KB), 제외하고 저장합니다.`); + } + const result = await saveInspectionData({ templateId: parseInt(template.templateId), itemId, @@ -677,7 +685,7 @@ export function ImportInspectionInputModal({ attachments, receivingId, inspectionResult: overallResult, - rendered_html: renderedHtml, + rendered_html: safeHtml, }); if (result.success) { @@ -755,6 +763,7 @@ export function ImportInspectionInputModal({ 수입검사 + 수입검사 항목 입력 {isLoadingTemplate ? ( diff --git a/src/components/material/ReceivingManagement/InventoryAdjustmentDialog.tsx b/src/components/material/ReceivingManagement/InventoryAdjustmentDialog.tsx index d2afe837..867403c5 100644 --- a/src/components/material/ReceivingManagement/InventoryAdjustmentDialog.tsx +++ b/src/components/material/ReceivingManagement/InventoryAdjustmentDialog.tsx @@ -19,6 +19,8 @@ import { DialogContent, DialogHeader, DialogTitle, + DialogDescription, + VisuallyHidden, } from '@/components/ui/dialog'; import { Select, @@ -127,6 +129,7 @@ export function InventoryAdjustmentDialog({ open, onOpenChange, onSave }: Props) 재고 조정 + 재고 수량 조정
diff --git a/src/components/material/ReceivingManagement/ReceivingDetail.tsx b/src/components/material/ReceivingManagement/ReceivingDetail.tsx index 95a75a1c..5c291ef3 100644 --- a/src/components/material/ReceivingManagement/ReceivingDetail.tsx +++ b/src/components/material/ReceivingManagement/ReceivingDetail.tsx @@ -68,28 +68,30 @@ interface Props { mode?: 'view' | 'edit' | 'new'; } -// 초기 폼 데이터 -const INITIAL_FORM_DATA: Partial = { - materialNo: '', - supplierMaterialNo: '', - lotNo: '', - itemCode: '', - itemName: '', - specification: '', - unit: 'EA', - supplier: '', - manufacturer: '', - receivingQty: undefined, - receivingDate: '', - createdBy: '', - status: 'receiving_pending', - remark: '', - inspectionDate: '', - inspectionResult: '', - certificateFile: undefined, - certificateFileId: undefined, - inventoryAdjustments: [], -}; +// 초기 폼 데이터 생성 (세션 사용자, 오늘 날짜 기본값) +function createInitialFormData(): Partial { + return { + materialNo: '', + supplierMaterialNo: '', + lotNo: '', + itemCode: '', + itemName: '', + specification: '', + unit: 'EA', + supplier: '', + manufacturer: '', + receivingQty: undefined, + receivingDate: getTodayString(), + createdBy: getLoggedInUserName(), + status: 'receiving_pending', + remark: '', + inspectionDate: '', + inspectionResult: '', + certificateFile: undefined, + certificateFileId: undefined, + inventoryAdjustments: [], + }; +} // 로트번호 생성 (YYMMDD-NN) function generateLotNo(): string { @@ -133,7 +135,7 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) { const [error, setError] = useState(null); // 폼 데이터 (등록/수정 모드용) - const [formData, setFormData] = useState>(INITIAL_FORM_DATA); + const [formData, setFormData] = useState>(createInitialFormData); // 업로드된 파일 상태 (File 객체) const [uploadedFile, setUploadedFile] = useState(null); @@ -294,7 +296,13 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) { const result = await createReceiving(saveData); if (result.success) { toast.success('입고가 등록되었습니다.'); - router.push('/ko/material/receiving-management'); + // 등록 완료 후 생성된 입고 상세 페이지로 바로 이동 (목록 경유 방지) + const newId = result.data?.id; + if (newId) { + router.push(`/ko/material/receiving-management/${newId}?mode=view`); + } else { + router.push('/ko/material/receiving-management'); + } return { success: true }; } else { toast.error(result.error || '등록에 실패했습니다.'); diff --git a/src/components/material/ReceivingManagement/ReceivingProcessDialog.tsx b/src/components/material/ReceivingManagement/ReceivingProcessDialog.tsx index a52621e7..3286f38b 100644 --- a/src/components/material/ReceivingManagement/ReceivingProcessDialog.tsx +++ b/src/components/material/ReceivingManagement/ReceivingProcessDialog.tsx @@ -19,6 +19,8 @@ import { DialogContent, DialogHeader, DialogTitle, + DialogDescription, + VisuallyHidden, } from '@/components/ui/dialog'; import { Alert, AlertDescription } from '@/components/ui/alert'; import type { ReceivingDetail, ReceivingProcessFormData } from './types'; @@ -111,6 +113,7 @@ export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete 입고 처리 + 입고 처리 정보 입력
diff --git a/src/components/material/ReceivingManagement/SuccessDialog.tsx b/src/components/material/ReceivingManagement/SuccessDialog.tsx index b0215e87..2bf6c155 100644 --- a/src/components/material/ReceivingManagement/SuccessDialog.tsx +++ b/src/components/material/ReceivingManagement/SuccessDialog.tsx @@ -9,6 +9,9 @@ import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, + VisuallyHidden, + DialogDescription, + DialogTitle, } from '@/components/ui/dialog'; interface Props { @@ -27,6 +30,8 @@ export function SuccessDialog({ open, type, lotNo, onClose }: Props) { return ( !newOpen && onClose()}> + 처리 완료 + 처리 결과 안내