v7.0.0-beta.2 release
This commit is contained in:
1 parent
6595fd0eb5
commit
fa8eba7a0d
1165 files changed
+107118
-762127
No files matched your search
@@ -5,7 +5,7 @@ namespace Database\Seeders\Sample;
|
||||
use App\Enums\ActivityLogType;
|
||||
use App\Models\ActivityLog;
|
||||
use App\Models\Attachment;
|
||||
use App\Models\MailTemplate;
|
||||
use App\Models\NotificationTemplate;
|
||||
use App\Models\Menu;
|
||||
use App\Models\Role;
|
||||
use App\Models\Schedule;
|
||||
@@ -80,7 +80,7 @@ class ActivityLogSampleSeeder extends Seeder
|
||||
$count += $this->seedAttachmentLogs($admins);
|
||||
|
||||
// 메일 템플릿 로그
|
||||
$count += $this->seedMailTemplateLogs($admins);
|
||||
$count += $this->seedNotificationTemplateLogs($admins);
|
||||
|
||||
// 모듈/플러그인 설정 로그
|
||||
$count += $this->seedExtensionSettingsLogs($admins);
|
||||
@@ -810,35 +810,35 @@ class ActivityLogSampleSeeder extends Seeder
|
||||
* @param Collection $admins 관리자 컬렉션
|
||||
* @return int 생성된 레코드 수
|
||||
*/
|
||||
private function seedMailTemplateLogs(Collection $admins): int
|
||||
private function seedNotificationTemplateLogs(Collection $admins): int
|
||||
{
|
||||
$mailTemplates = MailTemplate::get();
|
||||
if ($mailTemplates->isEmpty()) {
|
||||
$this->command->info(' - 메일 템플릿 데이터 없음 - 메일 템플릿 로그 스킵');
|
||||
$templates = NotificationTemplate::with('definition')->get();
|
||||
if ($templates->isEmpty()) {
|
||||
$this->command->info(' - 알림 템플릿 데이터 없음 - 알림 템플릿 로그 스킵');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$morphType = (new MailTemplate)->getMorphClass();
|
||||
$morphType = (new NotificationTemplate)->getMorphClass();
|
||||
|
||||
$actions = [
|
||||
[
|
||||
'action' => 'mail_template.update', 'key' => 'mail_template_update', 'loggable' => true,
|
||||
'params' => fn ($mt) => ['template_name' => $mt->type],
|
||||
'changes' => fn ($mt) => null,
|
||||
'properties' => fn ($mt) => ['template_type' => $mt->type, 'locale' => ['ko', 'en'][array_rand(['ko', 'en'])]],
|
||||
'action' => 'notification_template.update', 'key' => 'notification_template_update', 'loggable' => true,
|
||||
'params' => fn ($t) => ['template_name' => $t->definition?->type ?? $t->channel],
|
||||
'changes' => fn ($t) => null,
|
||||
'properties' => fn ($t) => ['template_type' => $t->definition?->type ?? '', 'channel' => $t->channel, 'locale' => ['ko', 'en'][array_rand(['ko', 'en'])]],
|
||||
],
|
||||
[
|
||||
'action' => 'mail_template.toggle_active', 'key' => 'mail_template_toggle_active', 'loggable' => true,
|
||||
'params' => fn ($mt) => ['template_name' => $mt->type],
|
||||
'changes' => fn ($mt) => null,
|
||||
'properties' => fn ($mt) => ['template_type' => $mt->type, 'is_active' => (bool) mt_rand(0, 1)],
|
||||
'action' => 'notification_template.toggle_active', 'key' => 'notification_template_toggle_active', 'loggable' => true,
|
||||
'params' => fn ($t) => ['template_name' => $t->definition?->type ?? $t->channel],
|
||||
'changes' => fn ($t) => null,
|
||||
'properties' => fn ($t) => ['template_type' => $t->definition?->type ?? '', 'channel' => $t->channel, 'is_active' => (bool) mt_rand(0, 1)],
|
||||
],
|
||||
];
|
||||
|
||||
$count = $this->generateResourceLogs($mailTemplates, $admins, ActivityLogType::Admin, $morphType, $actions);
|
||||
$count = $this->generateResourceLogs($templates, $admins, ActivityLogType::Admin, $morphType, $actions);
|
||||
|
||||
$this->command->info(" - 메일 템플릿 로그: {$count}건");
|
||||
$this->command->info(" - 알림 템플릿 로그: {$count}건");
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders\Sample;
|
||||
|
||||
use App\Enums\ExtensionOwnerType;
|
||||
use App\Enums\MailSendStatus;
|
||||
use App\Models\MailSendLog;
|
||||
use App\Traits\HasSeederCounts;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
/**
|
||||
* 코어 메일 발송 이력 개발용 시더
|
||||
*
|
||||
* 코어 메일 템플릿(welcome, reset_password, password_changed)을 기반으로
|
||||
* 발송 이력 샘플 데이터를 생성합니다.
|
||||
*
|
||||
* 개발/테스트 용도이므로 설치 시 자동 실행되지 않습니다.
|
||||
* 수동 실행: php artisan db:seed --class=MailSendLogSeeder
|
||||
*/
|
||||
class MailSendLogSeeder extends Seeder
|
||||
{
|
||||
use HasSeederCounts;
|
||||
|
||||
/**
|
||||
* 코어 메일 템플릿 유형별 제목 패턴
|
||||
*
|
||||
* @var array<string, array{ko: string, en: string}>
|
||||
*/
|
||||
private array $templateSubjects = [
|
||||
'welcome' => [
|
||||
'ko' => '[그누보드7] 회원가입을 환영합니다',
|
||||
'en' => '[Gnuboard7] Welcome to Our Service',
|
||||
],
|
||||
'reset_password' => [
|
||||
'ko' => '[그누보드7] 비밀번호 재설정 안내',
|
||||
'en' => '[Gnuboard7] Password Reset Request',
|
||||
],
|
||||
'password_changed' => [
|
||||
'ko' => '[그누보드7] 비밀번호가 변경되었습니다',
|
||||
'en' => '[Gnuboard7] Your Password Has Been Changed',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* 시더 실행
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$count = $this->getSeederCount('mail_send_logs', 30);
|
||||
|
||||
$this->command->info('코어 메일 발송 이력 시딩 시작...');
|
||||
|
||||
$templateTypes = array_keys($this->templateSubjects);
|
||||
$recipients = $this->getRecipients();
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$templateType = $templateTypes[array_rand($templateTypes)];
|
||||
$recipient = $recipients[array_rand($recipients)];
|
||||
$status = $this->randomStatus();
|
||||
$sentAt = $this->randomSentAt();
|
||||
|
||||
MailSendLog::create([
|
||||
'recipient_email' => $recipient['email'],
|
||||
'recipient_name' => $recipient['name'],
|
||||
'subject' => $this->templateSubjects[$templateType]['ko'],
|
||||
'template_type' => $templateType,
|
||||
'extension_type' => ExtensionOwnerType::Core,
|
||||
'extension_identifier' => 'core',
|
||||
'source' => 'notification',
|
||||
'status' => $status->value,
|
||||
'error_message' => $status === MailSendStatus::Failed
|
||||
? $this->randomErrorMessage()
|
||||
: null,
|
||||
'sent_at' => $sentAt,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->command->info("코어 메일 발송 이력 시딩 완료 ({$count}건)");
|
||||
}
|
||||
|
||||
/**
|
||||
* 샘플 수신자 목록을 반환합니다.
|
||||
*
|
||||
* @return array<int, array{email: string, name: string}>
|
||||
*/
|
||||
private function getRecipients(): array
|
||||
{
|
||||
return [
|
||||
['email' => 'hong@example.com', 'name' => '홍길동'],
|
||||
['email' => 'kim@example.com', 'name' => '김철수'],
|
||||
['email' => 'lee@example.com', 'name' => '이영희'],
|
||||
['email' => 'park@example.com', 'name' => '박민수'],
|
||||
['email' => 'choi@example.com', 'name' => '최지은'],
|
||||
['email' => 'jung@example.com', 'name' => '정수민'],
|
||||
['email' => 'kang@example.com', 'name' => '강하늘'],
|
||||
['email' => 'yoon@example.com', 'name' => '윤서연'],
|
||||
['email' => 'john@example.com', 'name' => 'John Doe'],
|
||||
['email' => 'jane@example.com', 'name' => 'Jane Smith'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 가중치 기반 랜덤 상태를 반환합니다.
|
||||
*
|
||||
* @return MailSendStatus
|
||||
*/
|
||||
private function randomStatus(): MailSendStatus
|
||||
{
|
||||
$rand = mt_rand(1, 100);
|
||||
|
||||
if ($rand <= 80) {
|
||||
return MailSendStatus::Sent;
|
||||
} elseif ($rand <= 95) {
|
||||
return MailSendStatus::Failed;
|
||||
}
|
||||
|
||||
return MailSendStatus::Skipped;
|
||||
}
|
||||
|
||||
/**
|
||||
* 최근 90일 내 랜덤 발송 시각을 반환합니다.
|
||||
*
|
||||
* @return Carbon
|
||||
*/
|
||||
private function randomSentAt(): Carbon
|
||||
{
|
||||
return Carbon::now()->subDays(mt_rand(0, 90))->subHours(mt_rand(0, 23))->subMinutes(mt_rand(0, 59));
|
||||
}
|
||||
|
||||
/**
|
||||
* 랜덤 에러 메시지를 반환합니다.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function randomErrorMessage(): string
|
||||
{
|
||||
$messages = [
|
||||
'Connection timed out after 30 seconds',
|
||||
'SMTP server returned 550: Mailbox not found',
|
||||
'DNS resolution failed for mail server',
|
||||
'Authentication failed: Invalid credentials',
|
||||
'Message rejected: Recipient address rejected',
|
||||
];
|
||||
|
||||
return $messages[array_rand($messages)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders\Sample;
|
||||
|
||||
use App\Enums\NotificationLogStatus;
|
||||
use App\Models\NotificationLog;
|
||||
use App\Traits\HasSeederCounts;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
/**
|
||||
* 알림 발송 이력 개발용 시더
|
||||
*
|
||||
* 다양한 채널/타입의 알림 발송 이력 샘플 데이터를 생성합니다.
|
||||
* 개발/테스트 용도이므로 설치 시 자동 실행되지 않습니다.
|
||||
*/
|
||||
class NotificationLogSeeder extends Seeder
|
||||
{
|
||||
use HasSeederCounts;
|
||||
|
||||
/**
|
||||
* 시더 실행.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$count = $this->getSeederCount('notification_logs', 50);
|
||||
|
||||
$this->command->info('알림 발송 이력 시딩 시작...');
|
||||
|
||||
$channels = ['mail', 'database'];
|
||||
$types = [
|
||||
['type' => 'welcome', 'ext_type' => 'core', 'ext_id' => 'core'],
|
||||
['type' => 'reset_password', 'ext_type' => 'core', 'ext_id' => 'core'],
|
||||
['type' => 'password_changed', 'ext_type' => 'core', 'ext_id' => 'core'],
|
||||
['type' => 'order_confirmed', 'ext_type' => 'module', 'ext_id' => 'sirsoft-ecommerce'],
|
||||
['type' => 'order_shipped', 'ext_type' => 'module', 'ext_id' => 'sirsoft-ecommerce'],
|
||||
['type' => 'new_comment', 'ext_type' => 'module', 'ext_id' => 'sirsoft-board'],
|
||||
['type' => 'new_post_admin', 'ext_type' => 'module', 'ext_id' => 'sirsoft-board'],
|
||||
];
|
||||
$recipients = $this->getRecipients();
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$channel = $channels[array_rand($channels)];
|
||||
$typeInfo = $types[array_rand($types)];
|
||||
$recipient = $recipients[array_rand($recipients)];
|
||||
$status = $this->randomStatus();
|
||||
$sentAt = Carbon::now()->subDays(mt_rand(0, 30))->subHours(mt_rand(0, 23))->subMinutes(mt_rand(0, 59));
|
||||
|
||||
NotificationLog::create([
|
||||
'channel' => $channel,
|
||||
'notification_type' => $typeInfo['type'],
|
||||
'extension_type' => $typeInfo['ext_type'],
|
||||
'extension_identifier' => $typeInfo['ext_id'],
|
||||
'recipient_identifier' => $channel === 'mail' ? $recipient['email'] : (string) ($i + 1),
|
||||
'recipient_name' => $recipient['name'],
|
||||
'subject' => "[G7] {$typeInfo['type']} 알림",
|
||||
'status' => $status->value,
|
||||
'error_message' => $status === NotificationLogStatus::Failed ? 'SMTP connection refused' : null,
|
||||
'source' => 'notification',
|
||||
'sent_at' => $sentAt,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->command->info("알림 발송 이력 시딩 완료 ({$count}건)");
|
||||
}
|
||||
|
||||
/**
|
||||
* 샘플 수신자 목록.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getRecipients(): array
|
||||
{
|
||||
return [
|
||||
['email' => 'hong@example.com', 'name' => '홍길동'],
|
||||
['email' => 'kim@example.com', 'name' => '김철수'],
|
||||
['email' => 'lee@example.com', 'name' => '이영희'],
|
||||
['email' => 'park@example.com', 'name' => '박민수'],
|
||||
['email' => 'john@example.com', 'name' => 'John Doe'],
|
||||
['email' => 'jane@example.com', 'name' => 'Jane Smith'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 가중치 기반 랜덤 상태.
|
||||
*
|
||||
* @return NotificationLogStatus
|
||||
*/
|
||||
private function randomStatus(): NotificationLogStatus
|
||||
{
|
||||
$rand = mt_rand(1, 100);
|
||||
|
||||
if ($rand <= 80) {
|
||||
return NotificationLogStatus::Sent;
|
||||
} elseif ($rand <= 95) {
|
||||
return NotificationLogStatus::Failed;
|
||||
}
|
||||
|
||||
return NotificationLogStatus::Skipped;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user