summaryrefslogtreecommitdiff
path: root/lib/vendors/blacklist-check.ts
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-11-06 17:44:59 +0900
committerjoonhoekim <26rote@gmail.com>2025-11-06 17:44:59 +0900
commit08b73d56c2d887931cecdf2b0af6b277381763e6 (patch)
treee2a1e466445c718dad79c100241048684b8a1923 /lib/vendors/blacklist-check.ts
parentba43cd261d10c6b0c5218a9da3f946993b21de6e (diff)
(김준회) 결재 프리뷰 공통컴포넌트 작성 및 index.ts --> client.ts 분리 (서버사이드 코드가 번들링되어 클라측에서 실행되는 문제 해결 목적)
Diffstat (limited to 'lib/vendors/blacklist-check.ts')
-rw-r--r--lib/vendors/blacklist-check.ts170
1 files changed, 170 insertions, 0 deletions
diff --git a/lib/vendors/blacklist-check.ts b/lib/vendors/blacklist-check.ts
new file mode 100644
index 00000000..c72bb1bf
--- /dev/null
+++ b/lib/vendors/blacklist-check.ts
@@ -0,0 +1,170 @@
+"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<BlacklistCheckResult> {
+ 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,
+ };
+}
+