"use client"; /** * 수주서 문서 컴포넌트 (기획서 D1.8 기준 리디자인) * - 출고증(ShipmentOrderDocument)과 동일한 자재 섹션 구조 * - 수주서 전용 헤더 (결재란, 로트번호, 제품코드, 인정번호) * - 배차정보/LOT 컬럼 없음 */ import { useState } from "react"; import { getTodayString } from "@/lib/utils/date"; import { OrderItem } from "../actions"; import { ProductInfo } from "./OrderDocumentModal"; import { ConstructionApprovalTable } from "@/components/document-system"; import { formatNumber } from '@/lib/utils/amount'; // ===== 데이터 타입 ===== interface MotorRow { item: string; type: string; spec: string; qty: number; } interface BendingItem { name: string; spec: string; qty: number; } interface BendingGroup { group: string; items: BendingItem[]; } interface SubsidiaryItem { name: string; spec: string; qty: number; } interface ProductRow { no: number; floor?: string; symbol?: string; product_name?: string; product_type?: string; open_width?: number | string; open_height?: number | string; made_width?: number | string; made_height?: number | string; guide_rail?: string; shaft?: string | number; case_inch?: string | number; bracket?: string; capacity?: string | number; finish?: string; joint_bar?: number | null; } interface SalesOrderDocumentProps { documentNumber?: string; orderNumber: string; certificationNumber?: string; orderDate?: string; client: string; siteName?: string; manager?: string; managerContact?: string; deliveryRequestDate?: string; expectedShipDate?: string; deliveryMethod?: string; address?: string; recipientName?: string; recipientContact?: string; shutterCount?: number; fee?: number; items?: OrderItem[]; products?: ProductInfo[]; remarks?: string; // 실 데이터 props productRows?: ProductRow[]; motorsLeft?: MotorRow[]; motorsRight?: MotorRow[]; bendingParts?: BendingGroup[]; subsidiaryParts?: SubsidiaryItem[]; categoryCode?: string; } // ===== 공통 스타일 ===== const thBase = 'border-r border-gray-400 px-1 py-1'; const tdBase = 'border-r border-gray-300 px-1 py-1'; const tdCenter = `${tdBase} text-center`; const imgPlaceholder = 'flex items-center justify-center border border-dashed border-gray-300 text-gray-400'; export function SalesOrderDocument({ documentNumber = "ABC123", orderNumber, certificationNumber = "-", orderDate = getTodayString(), client, siteName = "-", manager = "-", managerContact = "-", deliveryRequestDate = "-", expectedShipDate = "-", deliveryMethod = "상차", address = "-", recipientName = "-", recipientContact = "-", shutterCount = 0, items: _items = [], products = [], remarks, productRows = [], motorsLeft = [], motorsRight = [], bendingParts = [], subsidiaryParts = [], }: SalesOrderDocumentProps) { const [bottomFinishView, setBottomFinishView] = useState<'screen' | 'steel'>('screen'); const motorRows = Math.max(motorsLeft.length, motorsRight.length); // 절곡물 그룹 데이터 추출 const guideRailItems = bendingParts.find(g => g.group === '가이드레일')?.items ?? []; const caseItems = bendingParts.find(g => g.group === '케이스')?.items ?? []; const bottomItems = bendingParts.find(g => g.group === '하단마감')?.items ?? []; const smokeItems = bendingParts.find(g => g.group === '연기차단재')?.items ?? []; const guideSmokeItems = smokeItems.filter(i => i.name.includes('레일') || i.name.includes('가이드')); const caseSmokeItems = smokeItems.filter(i => i.name.includes('케이스')); // 구분 불가한 연기차단재는 그대로 표시 const otherSmokeItems = smokeItems.filter(i => !i.name.includes('레일') && !i.name.includes('가이드') && !i.name.includes('케이스') ); // 부자재 좌/우 2열 변환 const subsidiaryRows = []; for (let i = 0; i < subsidiaryParts.length; i += 2) { subsidiaryRows.push({ left: subsidiaryParts[i], right: subsidiaryParts[i + 1] ?? null, }); } // 스크린/철재 제품 분리 const screenProducts = productRows.filter(p => p.product_type !== 'steel'); const steelProducts = productRows.filter(p => p.product_type === 'steel'); return (
{/* ========== 헤더: 수주서 제목 + 결재란 ========== */}

수 주 서

문서번호: {documentNumber} 작성일자: {orderDate}
{/* ========== 로트번호 / 제품명 / 제품코드 / 인정번호 ========== */}
로트번호 {orderNumber} 제품명 {products[0]?.productName || productRows[0]?.product_name || "-"} 제품코드 {productRows[0]?.product_name?.split(' ')[0] || "KWS01"} 인정번호 {certificationNumber}
{/* ========== 3열 섹션: 신청업체 | 신청내용 | 납품정보 ========== */}
{/* 신청업체 */}
신청업체
수주일 {orderDate}
수주처 {client}
수주 담당자 {manager}
담당자 연락처 {managerContact}
{/* 신청내용 */}
신청내용
현장명 {siteName}
납기요청일 {deliveryRequestDate}
출고일 {expectedShipDate}
셔터출수량 {shutterCount || productRows.length}개소
{/* 납품정보 */}
납품정보
현장명 {siteName}
인수담당자 {recipientName}
인수자연락처 {recipientContact}
배송방법 {deliveryMethod}
{/* 배송지 주소 - 한 줄 병합 */}
배송지 주소
{address}

아래와 같이 주문하오니 품질 및 납기일을 준수하여 주시기 바랍니다.

{/* ========== 1. 스크린 ========== */} {screenProducts.length > 0 && (

1. 스크린

{screenProducts.map((row) => ( ))}
No 품류 부호 오픈사이즈 제작사이즈 가이드
레일
사프트
(인치)
케이스
(인치)
모터 마감
가로 세로 가로 세로 브라켓트 용량Kg
{row.no} {row.floor ?? '-'} {row.symbol ?? '-'} {row.open_width ? formatNumber(Number(row.open_width)) : '-'} {row.open_height ? formatNumber(Number(row.open_height)) : '-'} {row.made_width ? formatNumber(Number(row.made_width)) : '-'} {row.made_height ? formatNumber(Number(row.made_height)) : '-'} {row.guide_rail ?? '-'} {row.shaft ?? '-'} {row.case_inch ?? '-'} {row.bracket ?? '-'} {row.capacity ?? '-'} {row.finish ?? '-'}
)} {/* ========== 2. 철재 ========== */} {steelProducts.length > 0 && (

2. 철재

{steelProducts.map((row) => ( ))}
No. 부호 오픈사이즈 제작사이즈 가이드
레일
사프트
(인치)
조인트바
(규격)
케이스
(인치)
모터 마감
가로 세로 가로 세로 브라켓트 용량Kg
{row.no} {row.symbol ?? '-'} {row.open_width ? formatNumber(Number(row.open_width)) : '-'} {row.open_height ? formatNumber(Number(row.open_height)) : '-'} {row.made_width ? formatNumber(Number(row.made_width)) : '-'} {row.made_height ? formatNumber(Number(row.made_height)) : '-'} {row.guide_rail ?? '-'} {row.shaft ?? '-'} {row.joint_bar ?? '-'} {row.case_inch ?? '-'} {row.bracket ?? '-'} {row.capacity ?? '-'} {row.finish ?? '-'}
)} {/* ========== 3. 모터 ========== */} {motorRows > 0 && (

3. 모터

{Array.from({ length: motorRows }).map((_, i) => { const left = motorsLeft[i]; const right = motorsRight[i]; return ( ); })}
항목 구분 규격 수량 항목 구분 규격 수량
{left?.item || ''} {left?.type || ''} {left?.spec || ''} {left?.qty ?? ''} {right?.item || ''} {right?.type || ''} {right?.spec || ''} {right?.qty ?? ''}
)} {/* ========== 4. 절곡물 ========== */} {bendingParts.length > 0 && (

4. 절곡물

{/* 4-1. 가이드레일 */} {guideRailItems.length > 0 && (

4-1. 가이드레일

{guideRailItems.map((item, i) => ( {i === 0 && ( )} ))}
  항목 규격 수량
IMG
{item.name} {item.spec} {item.qty}
{/* 가이드레일 연기차단재 */} {guideSmokeItems.length > 0 && (
{guideSmokeItems.map((item, i) => ( {i === 0 && ( )} ))}
  항목 규격 수량
IMG
{item.name} {item.spec} {item.qty}
)}

* 가이드레일 마감재 양측에 설치 - EGI 0.8T + 화이버글라스코팅직물

)} {/* 4-2. 케이스(셔터박스) */} {caseItems.length > 0 && (

4-2. 케이스(셔터박스)

{caseItems.map((item, i) => ( {i === 0 && ( )} ))}
  항목 규격 수량
IMG
{item.name} {item.spec} {item.qty}
{/* 케이스 연기차단재 */} {caseSmokeItems.length > 0 && (
{caseSmokeItems.map((item, i) => ( {i === 0 && ( )} ))}
  항목 규격 수량
IMG
{item.name} {item.spec} {item.qty}
)}

* 전면부, 판넬부 양측에 설치 - EGI 0.8T + 화이버글라스코팅직물

)} {/* 4-3. 하단마감재 */} {bottomItems.length > 0 && (

4-3. 하단마감재

{bottomItems.map((item, i) => ( {i === 0 && ( )} ))}
  항목 규격 수량
IMG
{item.name} {item.spec} {item.qty}
)} {/* 연기차단재 (구분 불가) */} {otherSmokeItems.length > 0 && (

연기차단재

{otherSmokeItems.map((item, i) => ( ))}
항목 규격 수량
{item.name} {item.spec} {item.qty}
)}
)} {/* ========== 5. 부자재 ========== */} {subsidiaryParts.length > 0 && (

5. 부자재

{subsidiaryRows.map((row, i) => ( ))}
항목 규격 수량 항목 규격 수량
{row.left?.name ?? ''} {row.left?.spec ?? ''} {row.left?.qty ?? ''} {row.right?.name ?? ''} {row.right?.spec ?? ''} {row.right?.qty ?? ''}
)} {/* ========== 특이사항 ========== */} {remarks && (

【 특이사항 】

{remarks}
)}
); }