'use server'; import { executeServerAction, type ActionResult } from '@/lib/api/execute-server-action'; import type { PaginatedApiResponse } from '@/lib/api/types'; import { isNextRedirectError } from '@/lib/utils/redirect-error'; import type { Account, AccountFormData, AccountStatus } from './types'; import { BANK_LABELS } from './types'; const API_URL = process.env.NEXT_PUBLIC_API_URL; // ===== API 응답 타입 ===== interface BankAccountApiData { id: number; bank_code: string; bank_name: string; account_number: string; account_holder: string; account_name: string; status: AccountStatus; is_primary: boolean; assigned_user_id?: number; created_at?: string; updated_at?: string; } type BankAccountPaginatedResponse = PaginatedApiResponse; // ===== 데이터 변환 ===== function transformApiToFrontend(apiData: BankAccountApiData): Account { return { id: apiData.id, bankCode: apiData.bank_code, bankName: apiData.bank_name || BANK_LABELS[apiData.bank_code] || apiData.bank_code, accountNumber: apiData.account_number, accountName: apiData.account_name, accountHolder: apiData.account_holder, status: apiData.status, isPrimary: apiData.is_primary, assignedUserId: apiData.assigned_user_id, createdAt: apiData.created_at || '', updatedAt: apiData.updated_at || '', }; } function transformFrontendToApi(data: Partial): Record { return { bank_code: data.bankCode, bank_name: data.bankName || BANK_LABELS[data.bankCode || ''] || data.bankCode, account_number: data.accountNumber, account_holder: data.accountHolder, account_name: data.accountName, status: data.status, }; } // ===== 계좌 목록 조회 ===== export async function getBankAccounts(params?: { page?: number; perPage?: number; search?: string; }): Promise<{ success: boolean; data?: Account[]; meta?: { currentPage: number; lastPage: number; perPage: number; total: number }; error?: string; __authError?: boolean; }> { const searchParams = new URLSearchParams(); if (params?.page) searchParams.set('page', params.page.toString()); if (params?.perPage) searchParams.set('per_page', params.perPage.toString()); if (params?.search) searchParams.set('search', params.search); const queryString = searchParams.toString(); const result = await executeServerAction({ url: `${API_URL}/api/v1/bank-accounts${queryString ? `?${queryString}` : ''}`, transform: (data: BankAccountPaginatedResponse) => ({ accounts: (data?.data || []).map(transformApiToFrontend), meta: { currentPage: data?.current_page || 1, lastPage: data?.last_page || 1, perPage: data?.per_page || 20, total: data?.total || 0 }, }), errorMessage: '계좌 목록 조회에 실패했습니다.', }); return { success: result.success, data: result.data?.accounts, meta: result.data?.meta, error: result.error, __authError: result.__authError }; } // ===== 계좌 상세 조회 ===== export async function getBankAccount(id: number): Promise> { return executeServerAction({ url: `${API_URL}/api/v1/bank-accounts/${id}`, transform: (data: BankAccountApiData) => transformApiToFrontend(data), errorMessage: '계좌 조회에 실패했습니다.', }); } // ===== 계좌 생성 ===== export async function createBankAccount(data: AccountFormData): Promise> { return executeServerAction({ url: `${API_URL}/api/v1/bank-accounts`, method: 'POST', body: transformFrontendToApi(data), transform: (d: BankAccountApiData) => transformApiToFrontend(d), errorMessage: '계좌 등록에 실패했습니다.', }); } // ===== 계좌 수정 ===== export async function updateBankAccount(id: number, data: Partial): Promise> { return executeServerAction({ url: `${API_URL}/api/v1/bank-accounts/${id}`, method: 'PUT', body: transformFrontendToApi(data), transform: (d: BankAccountApiData) => transformApiToFrontend(d), errorMessage: '계좌 수정에 실패했습니다.', }); } // ===== 계좌 삭제 ===== export async function deleteBankAccount(id: number): Promise { return executeServerAction({ url: `${API_URL}/api/v1/bank-accounts/${id}`, method: 'DELETE', errorMessage: '계좌 삭제에 실패했습니다.', }); } // ===== 계좌 상태 토글 ===== export async function toggleBankAccountStatus(id: number): Promise> { return executeServerAction({ url: `${API_URL}/api/v1/bank-accounts/${id}/toggle`, method: 'PATCH', transform: (data: BankAccountApiData) => transformApiToFrontend(data), errorMessage: '상태 변경에 실패했습니다.', }); } // ===== 대표 계좌 설정 ===== export async function setPrimaryBankAccount(id: number): Promise> { return executeServerAction({ url: `${API_URL}/api/v1/bank-accounts/${id}/set-primary`, method: 'PATCH', transform: (data: BankAccountApiData) => transformApiToFrontend(data), errorMessage: '대표 계좌 설정에 실패했습니다.', }); } // ===== 다중 삭제 ===== export async function deleteBankAccounts(ids: number[]): Promise<{ success: boolean; deletedCount?: number; error?: string; }> { try { const results = await Promise.all(ids.map(id => deleteBankAccount(id))); const successCount = results.filter(r => r.success).length; const failedCount = results.filter(r => !r.success).length; if (failedCount > 0 && successCount === 0) { return { success: false, error: '계좌 삭제에 실패했습니다.' }; } if (failedCount > 0) { return { success: true, deletedCount: successCount, error: `${failedCount}개의 계좌 삭제에 실패했습니다.` }; } return { success: true, deletedCount: successCount }; } catch (error) { if (isNextRedirectError(error)) throw error; return { success: false, error: '서버 오류가 발생했습니다.' }; } }