/** * 일반계약 결재 템플릿 변수 매핑 함수 * * 제공된 HTML 템플릿의 변수명에 맞춰 매핑 */ 'use server'; import { format } from 'date-fns'; interface ContractSummary { basicInfo: Record; items: Record[]; subcontractChecklist: Record | null; storageInfo?: Record[]; } /** * 일반계약 데이터를 결재 템플릿 변수로 매핑 * * @param contractSummary - 계약 요약 정보 * @returns 템플릿 변수 객체 (Record) */ export async function mapContractToApprovalTemplateVariables( contractSummary: ContractSummary ): Promise> { const { basicInfo, items, subcontractChecklist } = contractSummary; // 날짜 포맷팅 헬퍼 const formatDate = (date: any) => { if (!date) return ''; try { const d = new Date(date); if (isNaN(d.getTime())) return String(date); return format(d, 'yyyy-MM-dd'); } catch { return String(date || ''); } }; // 금액 포맷팅 헬퍼 const formatCurrency = (amount: any) => { if (amount === undefined || amount === null || amount === '') return ''; const num = Number(amount); if (isNaN(num)) return String(amount); return num.toLocaleString('ko-KR'); }; // 계약기간 포맷팅 const contractPeriod = basicInfo.startDate && basicInfo.endDate ? `${formatDate(basicInfo.startDate)} ~ ${formatDate(basicInfo.endDate)}` : ''; // 계약체결방식 const contractExecutionMethod = basicInfo.executionMethod || ''; // 계약종류 const contractType = basicInfo.type || ''; // 업체선정방식 const vendorSelectionMethod = basicInfo.contractSourceType || ''; // 매입 부가가치세 const taxType = basicInfo.taxType || ''; // SHI 지급조건 const paymentTerm = basicInfo.paymentTerm || ''; // SHI 인도조건 const deliveryTerm = basicInfo.deliveryTerm || ''; const deliveryType = basicInfo.deliveryType || ''; // 사외업체 야드 투입 여부 const externalYardEntry = basicInfo.externalYardEntry === 'Y' ? '예' : '아니오'; // 직종 const workType = basicInfo.workType || ''; // 재하도 협력사 const subcontractVendor = basicInfo.subcontractVendorName || ''; // 계약 내용 const contractContent = basicInfo.notes || basicInfo.name || ''; // 계약성립조건 let establishmentConditionsText = ''; if (basicInfo.contractEstablishmentConditions) { try { const cond = typeof basicInfo.contractEstablishmentConditions === 'string' ? JSON.parse(basicInfo.contractEstablishmentConditions) : basicInfo.contractEstablishmentConditions; const active: string[] = []; if (cond.regularVendorRegistration) active.push('정규업체 등록(실사 포함) 시'); if (cond.projectAward) active.push('프로젝트 수주 시'); if (cond.ownerApproval) active.push('선주 승인 시'); if (cond.other) active.push('기타'); establishmentConditionsText = active.join(', '); } catch (e) { console.warn('계약성립조건 파싱 실패:', e); } } // 계약해지조건 let terminationConditionsText = ''; if (basicInfo.contractTerminationConditions) { try { const cond = typeof basicInfo.contractTerminationConditions === 'string' ? JSON.parse(basicInfo.contractTerminationConditions) : basicInfo.contractTerminationConditions; const active: string[] = []; if (cond.standardTermination) active.push('표준 계약해지조건'); if (cond.projectNotAwarded) active.push('프로젝트 미수주 시'); if (cond.other) active.push('기타'); terminationConditionsText = active.join(', '); } catch (e) { console.warn('계약해지조건 파싱 실패:', e); } } // 협력사 정보 const vendorCode = basicInfo.vendorCode || ''; const vendorName = basicInfo.vendorName || ''; const vendorContactPerson = basicInfo.vendorContactPerson || ''; const vendorPhone = basicInfo.vendorPhone || ''; const vendorEmail = basicInfo.vendorEmail || ''; const vendorNote = ''; // 자재 정보 (최대 100건) const materialItems = items.slice(0, 100); const materialCount = items.length; // 보증 정보 const guarantees: Array<{ type: string; order: number; bondNumber: string; rate: string; amount: string; period: string; startDate: string; endDate: string; issuer: string; }> = []; // // 계약보증 (첫 번째 항목만 사용) // if (basicInfo.contractBond) { // const bond = typeof basicInfo.contractBond === 'string' // ? JSON.parse(basicInfo.contractBond) // : basicInfo.contractBond; // if (bond && Array.isArray(bond) && bond.length > 0) { // const b = bond[0]; // guarantees.push({ // type: '계약보증', // order: 1, // bondNumber: b.bondNumber || '', // rate: b.rate ? `${b.rate}%` : '', // amount: formatCurrency(b.amount), // period: b.period || '', // startDate: formatDate(b.startDate), // endDate: formatDate(b.endDate), // issuer: b.issuer || '', // }); // } // } // // 지급보증 (첫 번째 항목만 사용) // if (basicInfo.paymentBond) { // const bond = typeof basicInfo.paymentBond === 'string' // ? JSON.parse(basicInfo.paymentBond) // : basicInfo.paymentBond; // if (bond && Array.isArray(bond) && bond.length > 0) { // const b = bond[0]; // guarantees.push({ // type: '지급보증', // order: 1, // bondNumber: b.bondNumber || '', // rate: b.rate ? `${b.rate}%` : '', // amount: formatCurrency(b.amount), // period: b.period || '', // startDate: formatDate(b.startDate), // endDate: formatDate(b.endDate), // issuer: b.issuer || '', // }); // } // } // // 하자보증 (첫 번째 항목만 사용) // if (basicInfo.defectBond) { // const bond = typeof basicInfo.defectBond === 'string' // ? JSON.parse(basicInfo.defectBond) // : basicInfo.defectBond; // if (bond && Array.isArray(bond) && bond.length > 0) { // const b = bond[0]; // guarantees.push({ // type: '하자보증', // order: 1, // bondNumber: b.bondNumber || '', // rate: b.rate ? `${b.rate}%` : '', // amount: formatCurrency(b.amount), // period: b.period || '', // startDate: formatDate(b.startDate), // endDate: formatDate(b.endDate), // issuer: b.issuer || '', // }); // } // } // // 보증 전체 비고 // const guaranteeNote = basicInfo.guaranteeNote || ''; // 총 계약 금액 계산 const totalContractAmount = items.reduce((sum, item) => { const amount = Number(item.contractAmount || item.totalLineAmount || 0); return sum + (isNaN(amount) ? 0 : amount); }, 0); // 변수 매핑 const variables: Record = { // 계약 기본 정보 '계약번호': String(basicInfo.contractNumber || ''), '계약명': String(basicInfo.name || basicInfo.contractName || ''), '계약체결방식': String(contractExecutionMethod), '계약종류': String(contractType), '구매담당자': String(basicInfo.managerName || basicInfo.registeredByName || ''), '업체선정방식': String(vendorSelectionMethod), '입찰번호': String(basicInfo.linkedBidNumber || ''), '입찰명': String(basicInfo.linkedBidName || ''), '계약기간': contractPeriod, '계약일자': formatDate(basicInfo.registeredAt || basicInfo.createdAt), '매입_부가가치세': String(taxType), '계약_담당자': String(basicInfo.managerName || basicInfo.registeredByName || ''), '계약부서': String(basicInfo.departmentName || ''), '계약금액': formatCurrency(basicInfo.contractAmount), 'SHI_지급조건': String(paymentTerm), 'SHI_인도조건': String(deliveryTerm), 'SHI_인도조건_옵션': String(deliveryType), '선적지': String(basicInfo.shippingLocation || ''), '하역지': String(basicInfo.dischargeLocation || ''), '사외업체_야드_투입여부': externalYardEntry, '프로젝트': String(basicInfo.projectName || basicInfo.projectCode || ''), '직종': String(workType), '재하도_협력사': String(subcontractVendor), '계약내용': String(contractContent), '계약성립조건': establishmentConditionsText, '계약해지조건': terminationConditionsText, // 협력사 정보 '협력사코드': String(vendorCode), '협력사명': String(vendorName), '협력사_담당자': String(vendorContactPerson), '전화번호': String(vendorPhone), '이메일': String(vendorEmail), '비고': String(vendorNote), // 자재 정보 '대상_자재_수': String(materialCount), }; // 자재 정보 변수 (최대 100건) materialItems.forEach((item, index) => { const idx = index + 1; variables[`플랜트_${idx}`] = String(item.plant || ''); variables[`프로젝트_${idx}`] = String(item.projectName || item.projectCode || ''); variables[`자재그룹_${idx}`] = String(item.itemGroup || item.itemCode || ''); variables[`자재그룹명_${idx}`] = String(item.itemGroupName || ''); variables[`자재번호_${idx}`] = String(item.itemCode || ''); variables[`자재상세_${idx}`] = String(item.itemInfo || item.description || ''); variables[`연간단가여부_${idx}`] = String(item.isAnnualPrice ? '예' : '아니오'); variables[`수량_${idx}`] = formatCurrency(item.quantity); variables[`구매단위_${idx}`] = String(item.quantityUnit || ''); variables[`계약단가_${idx}`] = formatCurrency(item.contractUnitPrice || item.unitPrice); variables[`수량단위_${idx}`] = String(item.quantityUnit || ''); variables[`총중량_${idx}`] = formatCurrency(item.totalWeight); variables[`중량단위_${idx}`] = String(item.weightUnit || ''); variables[`계약금액_${idx}`] = formatCurrency(item.contractAmount || item.totalLineAmount); }); // 총 계약 금액 variables['총_계약금액'] = formatCurrency(totalContractAmount); // // 보증 정보 변수 (첫 번째 항목만 사용) // const contractGuarantee = guarantees.find(g => g.type === '계약보증'); // if (contractGuarantee) { // variables['계약보증_차수_1'] = String(contractGuarantee.order); // variables['계약보증_증권번호_1'] = String(contractGuarantee.bondNumber || ''); // variables['계약보증_보증금율_1'] = String(contractGuarantee.rate || ''); // variables['계약보증_보증금액_1'] = String(contractGuarantee.amount || ''); // variables['계약보증_보증기간_1'] = String(contractGuarantee.period || ''); // variables['계약보증_시작일_1'] = String(contractGuarantee.startDate || ''); // variables['계약보증_종료일_1'] = String(contractGuarantee.endDate || ''); // variables['계약보증_발행기관_1'] = String(contractGuarantee.issuer || ''); // variables['계약보증_비고_1'] = String(guaranteeNote); // 기존 보증 전체 비고를 계약보증 비고로 사용 // } // const paymentGuarantee = guarantees.find(g => g.type === '지급보증'); // if (paymentGuarantee) { // variables['지급보증_차수_1'] = String(paymentGuarantee.order); // variables['지급보증_증권번호_1'] = String(paymentGuarantee.bondNumber || ''); // variables['지급보증_보증금율_1'] = String(paymentGuarantee.rate || ''); // variables['지급보증_보증금액_1'] = String(paymentGuarantee.amount || ''); // variables['지급보증_보증기간_1'] = String(paymentGuarantee.period || ''); // variables['지급보증_시작일_1'] = String(paymentGuarantee.startDate || ''); // variables['지급보증_종료일_1'] = String(paymentGuarantee.endDate || ''); // variables['지급보증_발행기관_1'] = String(paymentGuarantee.issuer || ''); // variables['지급보증_비고_1'] = String(guaranteeNote); // 기존 보증 전체 비고를 지급보증 비고로 사용 // } // const defectGuarantee = guarantees.find(g => g.type === '하자보증'); // if (defectGuarantee) { // variables['하자보증_차수_1'] = String(defectGuarantee.order); // variables['하자보증_증권번호_1'] = String(defectGuarantee.bondNumber || ''); // variables['하자보증_보증금율_1'] = String(defectGuarantee.rate || ''); // variables['하자보증_보증금액_1'] = String(defectGuarantee.amount || ''); // variables['하자보증_보증기간_1'] = String(defectGuarantee.period || ''); // variables['하자보증_시작일_1'] = String(defectGuarantee.startDate || ''); // variables['하자보증_종료일_1'] = String(defectGuarantee.endDate || ''); // variables['하자보증_발행기관_1'] = String(defectGuarantee.issuer || ''); // variables['하자보증_비고_1'] = String(guaranteeNote); // 기존 보증 전체 비고를 하자보증 비고로 사용 // } // 하도급 체크리스트 변수 (새로운 템플릿 구조에 맞춤) if (subcontractChecklist) { variables['작업전_서면발급_체크'] = String(subcontractChecklist.workDocumentIssuedCheck || subcontractChecklist.workDocumentIssued || ''); variables['기재사항_1'] = String(subcontractChecklist.legalItem1 || subcontractChecklist.sixLegalItems1 || ''); variables['기재사항_2'] = String(subcontractChecklist.legalItem2 || subcontractChecklist.sixLegalItems2 || ''); variables['기재사항_3'] = String(subcontractChecklist.legalItem3 || subcontractChecklist.sixLegalItems3 || ''); variables['기재사항_4'] = String(subcontractChecklist.legalItem4 || subcontractChecklist.sixLegalItems4 || ''); variables['기재사항_5'] = String(subcontractChecklist.legalItem5 || subcontractChecklist.sixLegalItems5 || ''); variables['기재사항_6'] = String(subcontractChecklist.legalItem6 || subcontractChecklist.sixLegalItems6 || ''); variables['부당대금_결정'] = String(subcontractChecklist.unfairPriceDecision || subcontractChecklist.unfairSubcontractPrice || ''); variables['점검결과'] = String(subcontractChecklist.inspectionResult || subcontractChecklist.overallResult || ''); variables['귀책부서'] = String(subcontractChecklist.responsibleDepartment || subcontractChecklist.overallDepartment || ''); variables['원인'] = String(subcontractChecklist.cause || subcontractChecklist.overallCause || ''); variables['대책'] = String(subcontractChecklist.countermeasure || subcontractChecklist.overallMeasure || ''); } return variables; }