/** * FCM 푸시 알림 공통 서버 액션 * * 사용 예시: * import { sendFcmNotification, sendApprovalNotification } from '@/lib/actions/fcm'; * * // 기본 알림 발송 * const result = await sendFcmNotification({ title: '알림', body: '내용' }); * * // 결재 알림 발송 (프리셋) * const result = await sendApprovalNotification(); */ 'use server'; import { executeServerAction } from '@/lib/api/execute-server-action'; // ============================================ // 타입 정의 // ============================================ export interface FcmNotificationParams { /** 알림 제목 (필수) */ title: string; /** 알림 본문 (필수) */ body: string; /** 특정 테넌트에게만 발송 */ tenant_id?: number; /** 특정 사용자에게만 발송 */ user_id?: number; /** 플랫폼 필터 (android, ios, web) */ platform?: 'android' | 'ios' | 'web'; /** 알림 채널 ID (Android) */ channel_id?: string; /** 알림 타입 (앱에서 분기 처리용) */ type?: string; /** 클릭 시 이동할 URL */ url?: string; /** 알림 사운드 키 */ sound_key?: string; } export interface FcmResult { success: boolean; error?: string; sentCount?: number; __authError?: boolean; } // ============================================ // 기본 FCM 발송 함수 // ============================================ /** * FCM 푸시 알림 발송 */ export async function sendFcmNotification( params: FcmNotificationParams ): Promise { interface FcmResponseData { success?: number } const result = await executeServerAction({ url: `${process.env.NEXT_PUBLIC_API_URL}/api/v1/admin/fcm/send`, method: 'POST', body: params, errorMessage: 'FCM 발송에 실패했습니다.', }); if (!result.success) { return { success: false, error: result.error, __authError: result.__authError }; } return { success: true, sentCount: result.data?.success || 0, }; } // ============================================ // 프리셋 함수들 (자주 사용하는 알림 타입) // ============================================ /** * 결재 알림 발송 (프리셋) */ export async function sendApprovalNotification( customParams?: Partial ): Promise { return sendFcmNotification({ title: '결재 알림', body: '결재 문서가 완료되었습니다.', type: 'approval', channel_id: 'push_approval_request', ...customParams, }); } /** * 작업지시 알림 발송 (프리셋) */ export async function sendWorkOrderNotification( customParams?: Partial ): Promise { return sendFcmNotification({ title: '작업지시 알림', body: '새로운 작업지시가 있습니다.', type: 'work_order', channel_id: 'work_order', ...customParams, }); } /** * 일반 공지 알림 발송 (프리셋) */ export async function sendNoticeNotification( customParams?: Partial ): Promise { return sendFcmNotification({ title: '공지사항', body: '새로운 공지사항이 있습니다.', type: 'notice', channel_id: 'notice', ...customParams, }); } /** * 신규업체 알림 발송 (프리셋) */ export async function sendNewClientNotification( customParams?: Partial ): Promise { return sendFcmNotification({ title: '신규업체 알림', body: '새로운 업체가 등록되었습니다.', type: 'new_client', channel_id: 'push_vendor_register', ...customParams, }); } /** * 수주 알림 발송 (프리셋) */ export async function sendSalesOrderNotification( customParams?: Partial ): Promise { return sendFcmNotification({ title: '수주 알림', body: '수주가 완료되었습니다.', type: 'sales_order', channel_id: 'push_sales_order', ...customParams, }); } /** * 계약완료 알림 발송 (프리셋) */ export async function sendContractCompletedNotification( customParams?: Partial ): Promise { return sendFcmNotification({ title: '계약 완료 알림', body: '계약이 완료되었습니다.', type: 'contract_completed', channel_id: 'push_contract', ...customParams, }); } /** * 발주완료 알림 발송 (프리셋) */ export async function sendPurchaseOrderNotification( customParams?: Partial ): Promise { return sendFcmNotification({ title: '발주 완료 알림', body: '발주가 완료되었습니다.', type: 'purchase_order', channel_id: 'push_purchase_order', ...customParams, }); }