command?->info('코어 알림 정의 시딩 시작...'); $helper = app(NotificationSyncHelper::class); $definitions = $this->getDefaultDefinitions(); $definedTypes = []; foreach ($definitions as $data) { $definition = $helper->syncDefinition($data); $definedTypes[] = $definition->type; $definedChannels = []; foreach ($data['templates'] as $template) { $helper->syncTemplate($definition->id, $template); $definedChannels[] = $template['channel']; } // 완전 동기화: seeder 에서 제거된 channel 의 template 삭제 $helper->cleanupStaleTemplates($definition->id, $definedChannels); $this->command?->info(" - {$data['type']} 알림 정의 등록 완료"); } // 완전 동기화: seeder 에서 제거된 코어 definition 삭제 (cascade 로 template 도 정리) $helper->cleanupStaleDefinitions('core', 'core', $definedTypes); $this->command?->info('코어 알림 정의 시딩 완료 ('.count($definitions).'종)'); } /** * 코어 기본 알림 정의 데이터를 반환합니다. * * @return array */ public function getDefaultDefinitions(): array { return [ $this->welcomeDefinition(), $this->resetPasswordDefinition(), $this->passwordChangedDefinition(), ]; } /** * 회원가입 환영 알림 정의. * * @return array */ private function welcomeDefinition(): array { return [ 'type' => 'welcome', 'hook_prefix' => 'core.auth', 'extension_type' => 'core', 'extension_identifier' => 'core', 'name' => ['ko' => '회원가입 환영', 'en' => 'Welcome'], 'description' => ['ko' => '회원가입 완료 시 발송되는 환영 알림', 'en' => 'Welcome notification sent upon registration'], 'channels' => ['mail', 'database'], 'hooks' => ['core.auth.after_register'], 'variables' => [ ['key' => 'name', 'description' => '수신자 이름'], ['key' => 'app_name', 'description' => '사이트명'], ['key' => 'action_url', 'description' => '로그인 페이지 URL'], ['key' => 'site_url', 'description' => '사이트 URL'], ], 'templates' => [ [ 'channel' => 'mail', 'recipients' => [['type' => 'trigger_user']], 'subject' => [ 'ko' => '[{app_name}] 회원가입을 환영합니다', 'en' => '[{app_name}] Welcome to Our Service', ], 'body' => [ 'ko' => '

{name}님, 환영합니다!

' .'

{app_name}에 가입해 주셔서 감사합니다.

' .'

이제 모든 서비스를 이용하실 수 있습니다. 아래 버튼을 클릭하여 로그인해 주세요.

' .'
로그인하기
' .'

감사합니다,
{app_name}

', 'en' => '

Welcome, {name}!

' .'

Thank you for joining {app_name}.

' .'

You now have access to all our services. Click the button below to log in.

' .'
Log In
' .'

Thank you,
{app_name}

', ], ], [ 'channel' => 'database', 'recipients' => [['type' => 'trigger_user']], 'subject' => ['ko' => '회원가입을 환영합니다', 'en' => 'Welcome to our service'], 'body' => ['ko' => '{name}님, {app_name}에 가입해 주셔서 감사합니다.', 'en' => 'Welcome {name}, thank you for joining {app_name}.'], 'click_url' => '/mypage', ], ], ]; } /** * 비밀번호 재설정 알림 정의. * * @return array */ private function resetPasswordDefinition(): array { return [ 'type' => 'reset_password', 'hook_prefix' => 'core.auth', 'extension_type' => 'core', 'extension_identifier' => 'core', 'name' => ['ko' => '비밀번호 재설정', 'en' => 'Password Reset'], 'description' => ['ko' => '비밀번호 재설정 요청 시 발송되는 알림', 'en' => 'Notification sent when password reset is requested'], 'channels' => ['mail', 'database'], 'hooks' => ['core.auth.after_reset_password_request'], 'variables' => [ ['key' => 'name', 'description' => '수신자 이름'], ['key' => 'app_name', 'description' => '사이트명'], ['key' => 'action_url', 'description' => '비밀번호 재설정 URL'], ['key' => 'expire_minutes', 'description' => '링크 만료 시간(분)'], ['key' => 'site_url', 'description' => '사이트 URL'], ], 'templates' => [ [ 'channel' => 'mail', 'recipients' => [['type' => 'trigger_user']], 'subject' => [ 'ko' => '[{app_name}] 비밀번호 재설정 안내', 'en' => '[{app_name}] Password Reset Request', ], 'body' => [ 'ko' => '

{name}님, 안녕하세요.

' .'

비밀번호 재설정 요청을 받았습니다. 아래 버튼을 클릭하여 비밀번호를 재설정해 주세요.

' .'

이 링크는 {expire_minutes}분 후 만료됩니다.

' .'
비밀번호 재설정
' .'

비밀번호 재설정을 요청하지 않으셨다면, 이 이메일을 무시해 주세요.

' .'

감사합니다,
{app_name}

', 'en' => '

Hello, {name}.

' .'

We received a request to reset your password. Click the button below to set a new password.

' .'

This link will expire in {expire_minutes} minutes.

' .'
Reset Password
' .'

If you did not request a password reset, please ignore this email.

' .'

Thank you,
{app_name}

', ], ], [ 'channel' => 'database', 'recipients' => [['type' => 'trigger_user']], 'subject' => ['ko' => '비밀번호 재설정 안내', 'en' => 'Password Reset Request'], 'body' => ['ko' => '{name}님, 비밀번호 재설정이 요청되었습니다. 본인이 요청하지 않았다면 이 알림을 무시해 주세요.', 'en' => '{name}, a password reset has been requested. If you did not request this, please ignore this notification.'], 'click_url' => '{action_url}', ], ], ]; } /** * 비밀번호 변경 완료 알림 정의. * * @return array */ private function passwordChangedDefinition(): array { return [ 'type' => 'password_changed', 'hook_prefix' => 'core.auth', 'extension_type' => 'core', 'extension_identifier' => 'core', 'name' => ['ko' => '비밀번호 변경', 'en' => 'Password Changed'], 'description' => ['ko' => '비밀번호 변경 완료 시 발송되는 알림', 'en' => 'Notification sent when password is changed'], 'channels' => ['mail', 'database'], 'hooks' => ['core.auth.after_password_changed'], 'variables' => [ ['key' => 'name', 'description' => '수신자 이름'], ['key' => 'app_name', 'description' => '사이트명'], ['key' => 'action_url', 'description' => '로그인 페이지 URL'], ['key' => 'site_url', 'description' => '사이트 URL'], ], 'templates' => [ [ 'channel' => 'mail', 'recipients' => [['type' => 'trigger_user']], 'subject' => [ 'ko' => '[{app_name}] 비밀번호가 변경되었습니다', 'en' => '[{app_name}] Your Password Has Been Changed', ], 'body' => [ 'ko' => '

{name}님, 안녕하세요.

' .'

계정의 비밀번호가 성공적으로 변경되었습니다.

' .'

본인이 변경하지 않았다면, 즉시 고객 지원팀에 문의하시기 바랍니다.

' .'
로그인하기
' .'

감사합니다,
{app_name}

', 'en' => '

Hello, {name}.

' .'

Your account password has been successfully changed.

' .'

If you did not make this change, please contact our support team immediately.

' .'
Log In
' .'

Thank you,
{app_name}

', ], ], [ 'channel' => 'database', 'recipients' => [['type' => 'trigger_user']], 'subject' => ['ko' => '비밀번호가 변경되었습니다', 'en' => 'Your password has been changed'], 'body' => ['ko' => '{name}님, 비밀번호가 변경되었습니다. 본인이 변경하지 않았다면 즉시 고객 지원팀에 문의하시기 바랍니다.', 'en' => '{name}, your password has been changed. If you did not make this change, please contact support immediately.'], 'click_url' => '/mypage/change-password', ], ], ]; } }