diff --git a/src/app/(dashboard)/(partnerCompany)/managePartner/page.tsx b/src/app/(dashboard)/(partnerCompany)/managePartner/page.tsx index 498c362..0034b8e 100644 --- a/src/app/(dashboard)/(partnerCompany)/managePartner/page.tsx +++ b/src/app/(dashboard)/(partnerCompany)/managePartner/page.tsx @@ -55,13 +55,17 @@ import { AlertDialogTitle } from '@/components/ui/alert-dialog' import {useToast} from '@/hooks/use-toast' -import {DartCorpInfo, PartnerCompany} from '@/types/IFRS/partnerCompany' +import type { + PartnerCompany, + DartCorpInfo, + PartnerCompanyResponse +} from '@/services/partnerCompany' import { - searchCompaniesFromDart, + fetchPartnerCompanies, createPartnerCompany, deletePartnerCompany, - fetchPartnerCompanies, - updatePartnerCompany + updatePartnerCompany, + searchCompaniesFromDart } from '@/services/partnerCompany' // 디바운스 훅 @@ -184,13 +188,6 @@ export default function ManagePartnerPage() { setDialogError(null) setDartSearchResults([]) try { - console.log('DART 검색 요청 파라미터 (페이지):', { - page: 1, - pageSize: 5, - listedOnly: true, - corpNameFilter: debouncedDartSearchQuery - }) - const response = await searchCompaniesFromDart({ page: 1, // origin/develop 에서는 페이지 없었으나, API 스펙에 따라 추가/조정 가능 pageSize: 5, // origin/develop 에서는 10, HEAD 에서는 5. 일단 5로 통일 @@ -198,13 +195,8 @@ export default function ManagePartnerPage() { corpNameFilter: debouncedDartSearchQuery }) - console.log('DART 검색 응답 전체:', response) - setDartSearchResults(response.data || []) // API 응답이 data 배열을 포함한다고 가정 - console.log('DART 검색 결과 설정:', response.data || []) - if ((response.data || []).length === 0) { - console.log('DART 검색 결과 없음') setDialogError(`'${debouncedDartSearchQuery}'에 대한 검색 결과가 없습니다.`) } } catch (error) { diff --git a/src/services/partnerCompany.ts b/src/services/partnerCompany.ts index e74baea..c485070 100644 --- a/src/services/partnerCompany.ts +++ b/src/services/partnerCompany.ts @@ -1,12 +1,72 @@ -import axios from 'axios' -import api from '@/lib/axios' +/** + * 파트너사(협력사) 정보 타입 + */ +export interface PartnerCompany { + id?: string // 파트너사 고유 ID + status?: 'ACTIVE' | 'INACTIVE' | 'PENDING' // 파트너사 상태 + industry?: string // 산업군 + country?: string // 국가 + address?: string // 주소 + corp_code: string // DART corp_code + corp_name: string // 회사명 (API 응답 필드) + stock_code?: string // 주식 코드 + contract_start_date?: string // 계약 시작일 (API 응답 필드 - YYYY-MM-DD 문자열) + modify_date?: string // 수정일 + // 프론트엔드에서 사용할 필드 (API 응답을 변환하여 채움) + companyName: string + contractStartDate: Date +} + +/** + * 파트너사 목록 API 응답 타입 (페이지네이션 포함) + */ +export interface PartnerCompanyResponse { + data: PartnerCompany[] + total: number + page: number + pageSize: number +} + +/** + * DART API 기업 정보 타입 + */ +export interface DartCorpInfo { + corp_code: string // 기업 고유 코드 + corp_name: string // 기업명 + stock_code?: string // 주식 코드 (상장사만 존재) + modify_date: string // 최종 수정일 +} + +/** + * DART API 페이지네이션 응답 타입 + */ +export interface DartApiResponse { + data: DartCorpInfo[] // 기업 정보 목록 + total: number // 전체 항목 수 + page: number // 현재 페이지 번호 + pageSize: number // 페이지 당 항목 수 + totalPages: number // 전체 페이지 수 + hasNextPage: boolean // 다음 페이지 존재 여부 +} + +/** + * 기업 검색 파라미터 타입 + */ +export interface SearchCorpParams { + page?: number + pageSize?: number + listedOnly?: boolean + corpNameFilter?: string +} + +const API_BASE_URL = process.env.NEXT_DART_API_URL || '/api' // 환경 변수 또는 기본값 사용 + import {useAuthStore} from '@/stores/authStore' -import { - DartApiResponse, - PartnerCompany, - PartnerCompanyResponse, - SearchCorpParams -} from '@/types/IFRS/partnerCompany' + +// 파트너사 API 엔드포인트 +const PARTNER_COMPANIES_BASE_PATH = '/api/v1/partners/partner-companies' +const UNIQUE_PARTNER_COMPANY_NAMES_ENDPOINT = `${API_BASE_URL}/api/v1/partners/unique-partner-companies` +const DART_CORP_CODES_ENDPOINT = `${API_BASE_URL}/api/v1/dart/corp-codes` /** * 파트너사 목록을 조회합니다. (페이지네이션 지원) @@ -21,30 +81,34 @@ export async function fetchPartnerCompanies( companyNameFilter?: string ): Promise { try { - const params: Record = { - page, - pageSize - } + const url = new URL(`${API_BASE_URL}${PARTNER_COMPANIES_BASE_PATH}`) + url.searchParams.append('page', page.toString()) + url.searchParams.append('pageSize', pageSize.toString()) if (companyNameFilter) { - params.companyName = companyNameFilter + url.searchParams.append('companyName', companyNameFilter) } - console.log('파트너사 목록 요청 URL:', '/api/v1/partners/partner-companies') - console.log('파트너사 목록 요청 파라미터:', params) - - // X-Member-Id 헤더 추가 (필수 헤더) const token = useAuthStore.getState().accessToken - const headers = token ? {'X-Member-Id': token} : {} - - console.log('요청 헤더:', headers) + const headers: HeadersInit = { + 'Content-Type': 'application/json' + } + if (token) { + headers.Authorization = `Bearer ${token}` + } - const response = await api.get('/api/v1/partners/partner-companies', { - params, + const response = await fetch(url.toString(), { + method: 'GET', headers }) - console.log('파트너사 목록 응답:', response.data) - return response.data + + if (!response.ok) { + throw new Error( + `파트너사 목록을 가져오는 중 오류가 발생했습니다: ${response.status}` + ) + } + + return await response.json() } catch (error) { console.error('파트너사 목록을 가져오는 중 오류:', error) throw error @@ -60,12 +124,30 @@ export async function fetchPartnerCompanyById( id: string ): Promise { try { - const response = await api.get(`/api/v1/partners/partner-companies/${id}`) - return response.data - } catch (error: any) { - if (error.response?.status === 404) { + const token = useAuthStore.getState().accessToken + const headers: HeadersInit = { + 'Content-Type': 'application/json' + } + + if (token) { + headers.Authorization = `Bearer ${token}` + } + + const response = await fetch(`${API_BASE_URL}${PARTNER_COMPANIES_BASE_PATH}/${id}`, { + method: 'GET', + headers + }) + + if (response.status === 404) { return null } + + if (!response.ok) { + throw new Error(`파트너사 정보를 가져오는데 실패했습니다: ${response.status}`) + } + + return await response.json() + } catch (error) { console.error('파트너사 정보 조회 오류:', error) throw error } @@ -82,14 +164,30 @@ export async function createPartnerCompany(partnerInput: { contractStartDate: string }): Promise { try { - // X-Member-Id 헤더 추가 const token = useAuthStore.getState().accessToken - const headers = token ? {'X-Member-Id': token} : {} + const headers: HeadersInit = { + 'Content-Type': 'application/json' + } - const response = await api.post('/api/v1/partners/partner-companies', partnerInput, { - headers + if (token) { + headers.Authorization = `Bearer ${token}` + headers['X-Member-Id'] = token // 또는 토큰에서 추출한 사용자 ID + } + + const response = await fetch(`${API_BASE_URL}${PARTNER_COMPANIES_BASE_PATH}`, { + method: 'POST', + headers, + body: JSON.stringify(partnerInput) }) - return response.data + + if (!response.ok) { + const errorData = await response.json().catch(() => null) + throw new Error( + `파트너사 등록에 실패했습니다: ${response.status} ${errorData?.message || ''}` + ) + } + + return await response.json() } catch (error) { console.error('파트너사 등록 오류:', error) throw error @@ -107,6 +205,15 @@ export async function updatePartnerCompany( partnerData: Partial> ): Promise { try { + const token = useAuthStore.getState().accessToken + const headers: HeadersInit = { + 'Content-Type': 'application/json' + } + + if (token) { + headers.Authorization = `Bearer ${token}` + } + // API 문서에 맞게 요청 데이터 변환 const requestData = { companyName: partnerData.companyName, @@ -118,15 +225,27 @@ export async function updatePartnerCompany( status: partnerData.status } - const response = await api.patch( - `/api/v1/partners/partner-companies/${id}`, - requestData - ) - return response.data - } catch (error: any) { - if (error.response?.status === 404) { + const response = await fetch(`${API_BASE_URL}${PARTNER_COMPANIES_BASE_PATH}/${id}`, { + method: 'PATCH', + headers, + body: JSON.stringify(requestData) + }) + + if (response.status === 404) { return null } + + if (!response.ok) { + const errorData = await response.json().catch(() => null) + throw new Error( + `파트너사 정보 수정에 실패했습니다: ${response.status} ${ + errorData?.message || '' + }` + ) + } + + return await response.json() + } catch (error) { console.error('파트너사 수정 오류:', error) throw error } @@ -138,7 +257,26 @@ export async function updatePartnerCompany( */ export async function deletePartnerCompany(id: string): Promise { try { - await api.delete(`/api/v1/partners/partner-companies/${id}`) + const token = useAuthStore.getState().accessToken + const headers: HeadersInit = { + 'Content-Type': 'application/json' + } + + if (token) { + headers.Authorization = `Bearer ${token}` + } + + const response = await fetch(`${API_BASE_URL}${PARTNER_COMPANIES_BASE_PATH}/${id}`, { + method: 'DELETE', + headers + }) + + if (!response.ok) { + const errorData = await response.json().catch(() => null) + throw new Error( + `파트너사 삭제에 실패했습니다: ${response.status} ${errorData?.message || ''}` + ) + } } catch (error) { console.error('파트너사 삭제 오류:', error) throw error @@ -154,59 +292,47 @@ export async function searchCompaniesFromDart( params: SearchCorpParams ): Promise { try { - console.log('DART 검색 요청 파라미터:', params) // 검색 파라미터 로깅 + const url = new URL(DART_CORP_CODES_ENDPOINT) + + if (params.page !== undefined) { + url.searchParams.append('page', params.page.toString()) + } - const queryParams: Record = { - page: params.page, - pageSize: params.pageSize, - listedOnly: params.listedOnly, - corpNameFilter: params.corpNameFilter + if (params.pageSize !== undefined) { + url.searchParams.append('pageSize', params.pageSize.toString()) } - console.log('DART 요청 쿼리 파라미터:', queryParams) // 쿼리 파라미터 로깅 + if (params.listedOnly !== undefined) { + url.searchParams.append('listedOnly', params.listedOnly.toString()) + } - // DART API 키 헤더 추가 (필요한 경우) - const headers: Record = {} - const apiKey = process.env.NEXT_PUBLIC_DART_API_KEY - if (apiKey) { - headers['X-API-KEY'] = apiKey + if (params.corpNameFilter) { + url.searchParams.append('corpNameFilter', params.corpNameFilter) + } + + const token = useAuthStore.getState().accessToken + const headers: HeadersInit = { + 'Content-Type': 'application/json' } - // 백엔드 컨트롤러는 /dart/corp-codes 경로에 매핑되어 있음 - const apiUrl = '/api/v1/dart/corp-codes' - console.log('DART API 요청 URL:', apiUrl) // API URL 로깅 - console.log('DART API 요청 baseURL:', api.defaults.baseURL) // baseURL 로깅 - console.log('DART API 요청 헤더:', headers) + if (token) { + headers.Authorization = `Bearer ${token}` + // API 키 헤더 추가 + headers['X-API-KEY'] = process.env.NEXT_PUBLIC_DART_API_KEY || '' + } - const response = await api.get(apiUrl, { - params: queryParams, + const response = await fetch(url.toString(), { + method: 'GET', headers }) - console.log('DART API 응답 데이터:', response.data) // 응답 데이터 로깅 - - // 응답 데이터 구조 상세 분석 - if (response.data) { - console.log('DART API 응답 필드 목록:', Object.keys(response.data)) - if ( - response.data.data && - Array.isArray(response.data.data) && - response.data.data.length > 0 - ) { - console.log( - 'DART API 응답 데이터 배열 첫번째 항목 필드:', - Object.keys(response.data.data[0]) - ) - } + if (!response.ok) { + throw new Error(`DART 기업 검색에 실패했습니다: ${response.status}`) } - return response.data + return await response.json() } catch (error) { console.error('DART 기업 검색 오류:', error) - if (axios.isAxiosError(error) && error.response) { - console.error('DART API 응답 상태:', error.response.status) - console.error('DART API 응답 데이터:', error.response.data) - } throw error } } @@ -239,16 +365,33 @@ export async function fetchFinancialRiskAssessment( partnerName?: string ): Promise { try { - const params: Record = {} + const url = new URL( + `${API_BASE_URL}${PARTNER_COMPANIES_BASE_PATH}/${corpCode}/financial-risk` + ) + if (partnerName) { - params.partnerName = partnerName + url.searchParams.append('partnerName', partnerName) } - const response = await api.get( - `/api/v1/partners/partner-companies/${corpCode}/financial-risk`, - {params} - ) - return response.data + // 인증 토큰 및 기타 필요한 헤더 설정 (필요시) + const token = useAuthStore.getState().accessToken + const headers: HeadersInit = { + 'Content-Type': 'application/json' + } + if (token) { + // headers['Authorization'] = `Bearer ${token}`; // 이 API는 인증이 필요 없는 것으로 보임 + } + + const response = await fetch(url.toString(), { + method: 'GET', + headers: headers + }) + + if (!response.ok) { + throw new Error(`재무 위험 정보를 가져오는데 실패했습니다: ${response.status}`) + } + + return await response.json() } catch (error) { console.error('재무 위험 정보 조회 오류:', error) throw error @@ -261,8 +404,29 @@ export async function fetchFinancialRiskAssessment( */ export async function fetchUniquePartnerCompanyNames(): Promise { try { - const response = await api.get('/api/v1/partners/unique-partner-companies') - return response.data.companyNames || [] + const url = new URL(UNIQUE_PARTNER_COMPANY_NAMES_ENDPOINT) + + const token = useAuthStore.getState().accessToken + const headers: HeadersInit = { + 'Content-Type': 'application/json' + } + if (token) { + headers.Authorization = `Bearer ${token}` + } + + const response = await fetch(url.toString(), { + method: 'GET', + headers + }) + + if (!response.ok) { + throw new Error( + `파트너사 이름 목록을 가져오는 중 오류가 발생했습니다: ${response.status}` + ) + } + + const data = await response.json() + return data.companyNames || [] } catch (error) { console.error('파트너사 이름 목록을 가져오는 중 오류:', error) throw error @@ -278,8 +442,29 @@ export async function fetchPartnerCompanyDetail( partnerId: string ): Promise { try { - const response = await api.get(`/api/v1/partners/partner-companies/${partnerId}`) - return response.data + const url = new URL(`${API_BASE_URL}${PARTNER_COMPANIES_BASE_PATH}/${partnerId}`) + + const token = useAuthStore.getState().accessToken + const headers: HeadersInit = { + 'Content-Type': 'application/json' + } + if (token) { + headers.Authorization = `Bearer ${token}` + } + + const response = await fetch(url.toString(), { + method: 'GET', + headers + }) + + if (!response.ok) { + throw new Error( + `파트너사 상세 정보를 가져오는 중 오류가 발생했습니다: ${response.status}` + ) + } + + const data = await response.json() + return data } catch (error) { console.error('파트너사 상세 정보를 가져오는 중 오류:', error) throw error