diff --git a/database/migrations/2025_10_14_135811_add_role_and_is_active_to_users_table.php b/database/migrations/2025_10_14_135811_add_role_and_is_active_to_users_table.php new file mode 100644 index 0000000..b62fffa --- /dev/null +++ b/database/migrations/2025_10_14_135811_add_role_and_is_active_to_users_table.php @@ -0,0 +1,29 @@ +enum('role', ['sales', 'ops'])->default('sales')->after('email'); + $table->boolean('is_active')->default(true)->after('role'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn(['role', 'is_active']); + }); + } +}; diff --git a/database/migrations/2025_10_14_135811_create_prospects_table.php b/database/migrations/2025_10_14_135811_create_prospects_table.php new file mode 100644 index 0000000..3be0c3e --- /dev/null +++ b/database/migrations/2025_10_14_135811_create_prospects_table.php @@ -0,0 +1,35 @@ +id(); + $table->foreignId('sales_user_id')->constrained('users')->onDelete('cascade'); + $table->string('company_name', 100); + $table->string('contact_person', 100)->nullable(); + $table->string('email', 100)->nullable(); + $table->string('phone', 20)->nullable(); + $table->text('notes')->nullable(); + $table->timestamps(); + + $table->index('sales_user_id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('prospects'); + } +}; diff --git a/database/migrations/2025_10_14_135812_create_demo_links_table.php b/database/migrations/2025_10_14_135812_create_demo_links_table.php new file mode 100644 index 0000000..d2bb5c7 --- /dev/null +++ b/database/migrations/2025_10_14_135812_create_demo_links_table.php @@ -0,0 +1,37 @@ +id(); + $table->foreignId('prospect_id')->constrained('prospects')->onDelete('cascade'); + $table->foreignId('created_by')->constrained('users')->onDelete('cascade'); + $table->string('token', 64)->unique(); + $table->enum('status', ['active', 'expired', 'revoked'])->default('active'); + $table->timestamp('expires_at'); + $table->unsignedInteger('visit_count')->default(0); + $table->timestamps(); + + $table->index(['token', 'status']); + $table->index('prospect_id'); + $table->index('created_by'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('demo_links'); + } +}; diff --git a/database/seeders/DemoSystemSeeder.php b/database/seeders/DemoSystemSeeder.php new file mode 100644 index 0000000..acf4e40 --- /dev/null +++ b/database/seeders/DemoSystemSeeder.php @@ -0,0 +1,73 @@ + 'OPS001', + 'name' => 'Ops Admin', + 'email' => 'ops@sam.kr', + 'password' => Hash::make('password'), + 'role' => 'ops', + 'is_active' => true, + ]); + + echo "✅ Ops 계정 생성: ops@sam.kr / password\n"; + + // 2. Sales 계정 생성 + $sales = User::create([ + 'user_id' => 'SALES001', + 'name' => 'Sales User', + 'email' => 'sales@sam.kr', + 'password' => Hash::make('password'), + 'role' => 'sales', + 'is_active' => true, + ]); + + echo "✅ Sales 계정 생성: sales@sam.kr / password\n"; + + // 3. 샘플 업체 생성 + $prospect = Prospect::create([ + 'sales_user_id' => $sales->id, + 'company_name' => '테스트 고객사', + 'contact_person' => '홍길동', + 'email' => 'test@example.com', + 'phone' => '010-1234-5678', + 'notes' => 'MVP 테스트용 샘플 업체입니다.', + ]); + + echo "✅ 샘플 업체 생성: {$prospect->company_name}\n"; + + // 4. 샘플 데모 링크 생성 (3일 만료) + $demoLink = DemoLink::create([ + 'prospect_id' => $prospect->id, + 'created_by' => $sales->id, + 'token' => DemoLink::generateToken(), + 'status' => 'active', + 'expires_at' => now()->addDays(3), + 'visit_count' => 0, + ]); + + echo "✅ 샘플 데모 링크 생성: http://dev.sam.kr/d/{$demoLink->token}\n"; + echo "\n"; + echo "🎉 데모 시스템 시더 완료!\n"; + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; + echo "Ops 로그인: ops@sam.kr / password\n"; + echo "Sales 로그인: sales@sam.kr / password\n"; + echo "데모 링크: http://dev.sam.kr/d/{$demoLink->token}\n"; + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; + } +}