"use server"; import crypto from 'crypto'; import { oracleKnex } from '@/lib/oracle-db/db'; /** * 문자열을 SHA-1으로 해시하여 대문자로 반환 */ function sha1Hash(text: string): string { return crypto .createHash('sha1') .update(text, 'utf8') .digest('hex') .toUpperCase(); } /** * 생년월일에서 숫자만 추출하고 YYMMDD 형식(6자리)로 변환 * 예: "1999-01-01" -> "990101" * 예: "99-01-01" -> "990101" * 예: "1988-02-06" -> "880206" */ function processBirthDate(birthDate: string | null | undefined): string { if (!birthDate) { throw new Error('생년월일 정보가 없습니다.'); } // 숫자만 추출 const numbersOnly = birthDate.replace(/\D/g, ''); if (numbersOnly.length === 6) { // 6자리(YYMMDD)면 그대로 사용 return numbersOnly; } else if (numbersOnly.length === 8) { // 8자리(YYYYMMDD)면 앞 2자리 제거하여 YYMMDD로 변환 return numbersOnly.substring(2); } else { throw new Error(`생년월일 형식이 올바르지 않습니다. (입력값: ${birthDate}, 숫자 길이: ${numbersOnly.length})`); } } /** * 블랙리스트 검사 결과 타입 */ export interface BlacklistCheckResult { isBlacklisted: boolean; message: string; count?: number; } /** * 단일 벤더의 블랙리스트 여부 확인 */ export async function checkVendorBlacklist( representativeName: string | null | undefined, representativeBirth: string | null | undefined ): Promise { try { // 필수 정보 검증 if (!representativeName || !representativeBirth) { return { isBlacklisted: false, message: '대표자 이름 또는 생년월일 정보가 없어 블랙리스트 검사를 진행할 수 없습니다.', }; } // 이름 해시값 생성 const nameHash = sha1Hash(representativeName); // 생년월일 처리 (YYMMDD 6자리로 변환) let birthProcessed: string; try { birthProcessed = processBirthDate(representativeBirth); } catch (error) { return { isBlacklisted: false, message: error instanceof Error ? error.message : '생년월일 처리 중 오류가 발생했습니다.', }; } // YYMMDD 전체를 해시 계산 // 예: "880206" → SHA1("880206") const birthHash = sha1Hash(birthProcessed); console.log('🔍 [블랙리스트 검사]', { input: representativeBirth, processed: birthProcessed, nameHash, birthHash }); // Oracle DB 조회 const result = await oracleKnex .select(oracleKnex.raw('COUNT(*) as cnt')) .from('SHIVND.AMG0070') .where('NM', nameHash) .andWhere('BRDT', birthHash) .first() as unknown as { cnt?: number; CNT?: number } | undefined; const count = Number(result?.cnt || result?.CNT || 0); const isBlacklisted = count > 0; if (isBlacklisted) { return { isBlacklisted: true, message: '블랙리스트에 등록된 대표자입니다. 가입 승인을 진행할 수 없습니다.', count, }; } return { isBlacklisted: false, message: '블랙리스트 검사 통과', count: 0, }; } catch (error) { console.error('블랙리스트 검사 오류:', error); throw new Error('블랙리스트 검사 중 오류가 발생했습니다.'); } } /** * 여러 벤더의 블랙리스트 여부 일괄 확인 */ export async function checkVendorsBlacklist( vendors: Array<{ id: string; name: string; representativeName: string | null; representativeBirth: string | null; }> ): Promise<{ success: boolean; blacklistedVendors: Array<{ id: string; name: string; message: string }>; checkedCount: number; }> { const blacklistedVendors: Array<{ id: string; name: string; message: string }> = []; for (const vendor of vendors) { try { const result = await checkVendorBlacklist( vendor.representativeName, vendor.representativeBirth ); if (result.isBlacklisted) { blacklistedVendors.push({ id: vendor.id, name: vendor.name, message: result.message, }); } } catch (error) { // 개별 벤더 검사 실패 시에도 계속 진행 console.error(`벤더 ${vendor.name} 블랙리스트 검사 실패:`, error); blacklistedVendors.push({ id: vendor.id, name: vendor.name, message: '블랙리스트 검사 중 오류가 발생했습니다.', }); } } return { success: blacklistedVendors.length === 0, blacklistedVendors, checkedCount: vendors.length, }; }