diff options
| author | joonhoekim <26rote@gmail.com> | 2025-09-02 08:36:03 +0000 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-09-02 08:36:03 +0000 |
| commit | 659c46ed04758584b79a8f97074d3213bb7e252e (patch) | |
| tree | 9e7000873fbdc78df52fbbaac4c6d52f484255cb /lib/vendor-basic-info/use-credit-integration.ts | |
| parent | f72142f6cc46c7be5bf90803d365c2ecd144c53d (diff) | |
(김준회) 벤더기본정보 - 매출정보 처리 (수동입력은 구현하지 않았음)
Diffstat (limited to 'lib/vendor-basic-info/use-credit-integration.ts')
| -rw-r--r-- | lib/vendor-basic-info/use-credit-integration.ts | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/lib/vendor-basic-info/use-credit-integration.ts b/lib/vendor-basic-info/use-credit-integration.ts new file mode 100644 index 00000000..5cdfd04a --- /dev/null +++ b/lib/vendor-basic-info/use-credit-integration.ts @@ -0,0 +1,326 @@ +'use client'; + +import { useState, useEffect, useCallback } from 'react'; +import { getCreditInfo } from '@/lib/oracle-db/nonsap/services/creditService'; + +// 신용평가사 옵션 +const creditServices = [ + { code: 'I', name: '이크레더블' }, + { code: 'K', name: '한국기업데이터' }, + { code: 'N', name: '나이스디앤비' }, + { code: 'E', name: 'NICE신용평가사' } +]; + +interface CreditData { + // 기본 정보 + RESNO: string; + EENTNM: string; + OPEDT: string; + REPR_NM: string; + TYSCALE: string; + RELCMP: string; + ADR: string; + LISTYN: string; + GOODSNM: string; + TELNO: string; + FAXNO: string; + FSTRDRT: string; + + // 매출순위 + MO_1: string; + MO_4: string; + MO_2: string; + MO_5: string; + MO_3: string; + MO_6: string; + + // 매입순위 + MI_1: string; + MI_4: string; + MI_2: string; + MI_5: string; + MI_3: string; + MI_6: string; + + // 지분관계 + GIBUN_RL_1: string; + LSH_STK_RATE1: string; + GIBUN_RL_2: string; + LSH_STK_RATE2: string; + GIBUN_RL_3: string; + LSH_STK_RATE3: string; + + // 기타 정보 + HAPGYE: string; + NOTICE: string; + NOTICE_DT: string; + HPGBNCR_TY: string; + FCLOSDT: string; + LASTGRD: string; + DECISION: string; + FRISKRV: string; + EXPIRE_GB: string; + FWATCHD: string; + SUVDT: string; + ESETDTT: string; + + // 재무년월 + bs_dt0: string; + bs_dt1: string; + bs_dt2: string; + + // 재무현황 + bs59_0: string; // 총자산 + bs59_1: string; + bs59_2: string; + bs91_0: string; // 부채총계 + bs91_1: string; + bs91_2: string; + bs113_0: string; // 자본총계 + bs113_1: string; + bs113_2: string; + pl01_0: string; // 매출액 + pl01_1: string; + pl01_2: string; + pl27_0: string; // 영업이익 + pl27_1: string; + pl27_2: string; + pl71_0: string; // 당기순이익 + pl71_1: string; + pl71_2: string; + + // 재무비율 + TR0053: string; // 부채비율 + TR0052: string; + TR0051: string; + TR0513: string; // 차입금의존도 + TR0512: string; + TR0511: string; + TR0523: string; // 영업이익율 + TR0522: string; + TR0521: string; + TR0103: string; // 매출순이익율 + TR0102: string; + TR0101: string; + TR0223: string; // 매출액증가율 + TR0222: string; + TR0221: string; + TR0013: string; // 유동비율 + TR0012: string; + TR0011: string; +} + +interface CreditServiceResult { + code: string; + name: string; + data: CreditData | null; + dataCount: number; + success: boolean; + error: string | null; +} + +export function useCreditIntegration(vendorId: string) { + const [loading, setLoading] = useState(false); + const [error, setError] = useState<string | null>(null); + const [creditResults, setCreditResults] = useState<CreditServiceResult[]>([]); + const [selectedCreditService, setSelectedCreditService] = useState<string>('auto'); + const [bestResult, setBestResult] = useState<CreditServiceResult | null>(null); + + // 데이터 개수를 계산하는 함수 + const calculateDataCount = (data: CreditData | null): number => { + if (!data) return 0; + + let count = 0; + const fieldsToCheck = [ + // 재무현황 필드들 + 'bs59_0', 'bs59_1', 'bs59_2', // 총자산 + 'bs91_0', 'bs91_1', 'bs91_2', // 부채총계 + 'bs113_0', 'bs113_1', 'bs113_2', // 자본총계 + 'pl01_0', 'pl01_1', 'pl01_2', // 매출액 + 'pl27_0', 'pl27_1', 'pl27_2', // 영업이익 + 'pl71_0', 'pl71_1', 'pl71_2', // 당기순이익 + // 재무비율 필드들 + 'TR0053', 'TR0052', 'TR0051', // 부채비율 + 'TR0513', 'TR0512', 'TR0511', // 차입금의존도 + 'TR0523', 'TR0522', 'TR0521', // 영업이익율 + 'TR0103', 'TR0102', 'TR0101', // 순이익율 + 'TR0223', 'TR0222', 'TR0221', // 매출액증가율 + 'TR0013', 'TR0012', 'TR0011', // 유동비율 + ]; + + fieldsToCheck.forEach(field => { + const value = data[field as keyof CreditData]; + if (value && value.toString().trim() !== '' && value.toString().trim() !== '0') { + count++; + } + }); + + return count; + }; + + // 모든 신용평가사 데이터를 병렬로 조회 + const loadAllCreditData = useCallback(async () => { + if (!vendorId) return; + + setLoading(true); + setError(null); + + try { + const promises = creditServices.map(async (service) => { + try { + const result = await getCreditInfo(vendorId, service.code); + const data = result && result.length > 0 ? result[0] : null; + const dataCount = calculateDataCount(data); + + return { + code: service.code, + name: service.name, + data, + dataCount, + success: true, + error: null + }; + } catch (err) { + console.error(`Error loading credit data for ${service.name}:`, err); + return { + code: service.code, + name: service.name, + data: null, + dataCount: 0, + success: false, + error: `${service.name} 데이터 조회 실패` + }; + } + }); + + const results = await Promise.all(promises); + setCreditResults(results); + + // 모든 신용평가사 조회가 실패했는지 확인 + const allFailed = results.every(result => !result.success); + if (allFailed) { + const failedServices = results.filter(r => !r.success).map(r => r.name).join(', '); + setError(`모든 신용평가사 데이터 조회에 실패했습니다: ${failedServices}`); + setBestResult(null); + return; + } + + // 부분적으로 실패한 경우에도 성공한 것들로 진행 + const successfulResults = results.filter(result => result.success); + + // 데이터 개수가 가장 많은 결과 찾기 (성공한 것들 중에서) + const best = successfulResults.reduce((prev, current) => { + return current.dataCount > prev.dataCount ? current : prev; + }, successfulResults[0]); + + setBestResult(best && best.dataCount > 0 ? best : null); + + // 성공했지만 모든 데이터가 비어있는 경우 + if (successfulResults.length > 0 && successfulResults.every(r => r.dataCount === 0)) { + setError(null); // 오류는 아니므로 에러 메시지 지우기 + } + + } catch (err) { + setError('신용평가 데이터를 불러오는 중 예상치 못한 오류가 발생했습니다.'); + console.error(err); + setBestResult(null); + } finally { + setLoading(false); + } + }, [vendorId]); + + // 신용평가사 선택 변경 핸들러 + const handleCreditServiceChange = (code: string) => { + setSelectedCreditService(code); + }; + + // 현재 선택된 결과 반환 + const getCurrentResult = (): CreditServiceResult | null => { + if (selectedCreditService === 'auto') { + return bestResult; + } + return creditResults.find(r => r.code === selectedCreditService) || null; + }; + + // Credit 데이터를 Basic 페이지 형식으로 변환 + const transformCreditToSalesData = (creditData: CreditData | null) => { + if (!creditData) return null; + + // 날짜 변환 함수 (20.12.31 -> 20201231) + const convertDateToYYYYMMDD = (dateStr: string): string => { + if (!dateStr) return ''; + const parts = dateStr.split('.'); + if (parts.length >= 3) { + let year = parseInt(parts[0]); + const month = parts[1].padStart(2, '0'); + const day = parts[2].padStart(2, '0'); + + // 2자리 연도를 4자리로 변환 + if (year >= 0 && year <= 30) { + year = 2000 + year; + } else if (year >= 70 && year <= 99) { + year = 1900 + year; + } + + return `${year}${month}${day}`; + } + return ''; + }; + + // 숫자 값 정리 함수 + const cleanNumber = (value: string): string => { + if (!value) return '0'; + return value.replace(/,/g, '').trim(); + }; + + const salesInfo: { [year: string]: { totalSales: string; totalDebt: string; totalEquity: string; operatingProfit: string; netIncome: string; } } = {}; + const calculatedMetrics: { [year: string]: { debtRatio: number; borrowingDependency: number; operatingMargin: number; netMargin: number; salesGrowth: number; currentRatio: number; } } = {}; + + // 3개년 데이터 변환 + for (let i = 0; i < 3; i++) { + const yearKey = convertDateToYYYYMMDD(creditData[`bs_dt${i}` as keyof CreditData] as string); + if (!yearKey) continue; + + // 매출정보 변환 + salesInfo[yearKey] = { + totalSales: cleanNumber(creditData[`pl01_${i}` as keyof CreditData] as string), + totalDebt: cleanNumber(creditData[`bs91_${i}` as keyof CreditData] as string), + totalEquity: cleanNumber(creditData[`bs113_${i}` as keyof CreditData] as string), + operatingProfit: cleanNumber(creditData[`pl27_${i}` as keyof CreditData] as string), + netIncome: cleanNumber(creditData[`pl71_${i}` as keyof CreditData] as string), + }; + + // 계산된 지표 변환 (i=0은 최신년도, i=2는 가장 오래된 년도) + calculatedMetrics[yearKey] = { + debtRatio: parseFloat(creditData[`TR005${3-i}` as keyof CreditData] as string) || 0, // TR0053, TR0052, TR0051 + borrowingDependency: parseFloat(creditData[`TR051${3-i}` as keyof CreditData] as string) || 0, // TR0513, TR0512, TR0511 + operatingMargin: parseFloat(creditData[`TR052${3-i}` as keyof CreditData] as string) || 0, // TR0523, TR0522, TR0521 + netMargin: parseFloat(creditData[`TR010${3-i}` as keyof CreditData] as string) || 0, // TR0103, TR0102, TR0101 + salesGrowth: parseFloat(creditData[`TR022${3-i}` as keyof CreditData] as string) || 0, // TR0223, TR0222, TR0221 + currentRatio: parseFloat(creditData[`TR001${3-i}` as keyof CreditData] as string) || 0, // TR0013, TR0012, TR0011 + }; + } + + return { salesInfo, calculatedMetrics }; + }; + + // 초기 데이터 로드 + useEffect(() => { + if (vendorId) { + loadAllCreditData(); + } + }, [vendorId, loadAllCreditData]); + + return { + loading, + error, + creditResults, + selectedCreditService, + bestResult, + getCurrentResult, + handleCreditServiceChange, + transformCreditToSalesData, + creditServices: [...creditServices, { code: 'auto', name: '자동선택 (최적)' }], + reload: loadAllCreditData + }; +} |
