first&last

This commit is contained in:
sbb45
2026-03-20 15:47:17 +05:00
commit d6441abdd2
230 changed files with 20367 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
*.sqlite*
+37
View File
@@ -0,0 +1,37 @@
<?php
namespace Database\Factories;
use App\Enums\UserRole;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class UserFactory extends Factory
{
protected static ?string $password;
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'role' => fake()->randomElement(UserRole::cases())->value,
'phone' => '+7'.fake()->numerify('9#########'),
'is_active' => true,
'remember_token' => Str::random(10),
];
}
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}
@@ -0,0 +1,40 @@
<?php
use App\Enums\UserRole;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('role')->default(UserRole::CLIENT->value)->index();
$table->string('phone', 32)->nullable();
$table->string('avatar')->nullable();
$table->unsignedBigInteger('department_id')->nullable()->index();
$table->boolean('is_active')->default(true)->index();
$table->timestamp('last_login_at')->nullable();
$table->rememberToken();
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
}
};
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('password_reset_tokens');
}
};
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('failed_jobs');
}
};
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};
@@ -0,0 +1,23 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('departments', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->text('description')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('departments');
}
};
@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->foreign('department_id')
->references('id')
->on('departments')
->nullOnDelete()
->cascadeOnUpdate();
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropForeign(['department_id']);
});
}
};
@@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('equipment_categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique();
$table->text('description')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('equipment_categories');
}
};
@@ -0,0 +1,41 @@
<?php
use App\Enums\EquipmentCondition;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('equipment', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('serial_number')->unique();
$table->string('inventory_number')->unique();
$table->foreignId('category_id')
->constrained('equipment_categories')
->cascadeOnUpdate()
->restrictOnDelete();
$table->foreignId('client_id')
->nullable()
->constrained('users')
->nullOnDelete()
->cascadeOnUpdate();
$table->date('purchase_date')->nullable();
$table->date('warranty_until')->nullable();
$table->string('condition')->default(EquipmentCondition::GOOD->value)->index();
$table->text('notes')->nullable();
$table->timestamps();
$table->index(['client_id', 'category_id']);
$table->index('warranty_until');
});
}
public function down(): void
{
Schema::dropIfExists('equipment');
}
};
@@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('request_types', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->text('description')->nullable();
$table->unsignedInteger('sla_hours')->default(24);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('request_types');
}
};
@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('priorities', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('color_hex', 7);
$table->unsignedTinyInteger('level')->unique();
$table->timestamps();
$table->index('level');
});
}
public function down(): void
{
Schema::dropIfExists('priorities');
}
};
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('statuses', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('color_hex', 7);
$table->string('slug')->unique();
$table->boolean('is_final')->default(false);
$table->unsignedSmallInteger('sort_order')->default(0);
$table->timestamps();
$table->index(['sort_order', 'is_final']);
});
}
public function down(): void
{
Schema::dropIfExists('statuses');
}
};
@@ -0,0 +1,69 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('requests', function (Blueprint $table) {
$table->id();
$table->string('ticket_number')->unique();
$table->string('title');
$table->text('description');
$table->foreignId('type_id')
->constrained('request_types')
->cascadeOnUpdate()
->restrictOnDelete();
$table->foreignId('priority_id')
->constrained('priorities')
->cascadeOnUpdate()
->restrictOnDelete();
$table->foreignId('status_id')
->constrained('statuses')
->cascadeOnUpdate()
->restrictOnDelete();
$table->foreignId('client_id')
->constrained('users')
->cascadeOnUpdate()
->restrictOnDelete();
$table->foreignId('assigned_to')
->nullable()
->constrained('users')
->nullOnDelete()
->cascadeOnUpdate();
$table->foreignId('equipment_id')
->nullable()
->constrained('equipment')
->nullOnDelete()
->cascadeOnUpdate();
$table->string('location')->nullable();
$table->dateTime('planned_at')->nullable();
$table->dateTime('deadline_at')->nullable();
$table->dateTime('started_at')->nullable();
$table->dateTime('completed_at')->nullable();
$table->text('resolution_notes')->nullable();
$table->unsignedTinyInteger('client_rating')->nullable();
$table->text('client_comment')->nullable();
$table->timestamps();
$table->softDeletes();
$table->index('type_id');
$table->index('priority_id');
$table->index('status_id');
$table->index('client_id');
$table->index('assigned_to');
$table->index('equipment_id');
$table->index('deadline_at');
$table->index('created_at');
$table->index(['status_id', 'deadline_at']);
});
}
public function down(): void
{
Schema::dropIfExists('requests');
}
};
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('request_comments', function (Blueprint $table) {
$table->id();
$table->foreignId('request_id')
->constrained('requests')
->cascadeOnDelete()
->cascadeOnUpdate();
$table->foreignId('user_id')
->constrained('users')
->cascadeOnDelete()
->cascadeOnUpdate();
$table->text('body');
$table->boolean('is_internal')->default(false)->index();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('request_comments');
}
};
@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('request_attachments', function (Blueprint $table) {
$table->id();
$table->foreignId('request_id')
->constrained('requests')
->cascadeOnDelete()
->cascadeOnUpdate();
$table->foreignId('user_id')
->nullable()
->constrained('users')
->nullOnDelete()
->cascadeOnUpdate();
$table->string('filename');
$table->string('path');
$table->unsignedBigInteger('size');
$table->timestamps();
$table->index('created_at');
});
}
public function down(): void
{
Schema::dropIfExists('request_attachments');
}
};
@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('activity_logs', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')
->nullable()
->constrained('users')
->nullOnDelete()
->cascadeOnUpdate();
$table->string('model_type');
$table->unsignedBigInteger('model_id');
$table->string('action');
$table->text('description')->nullable();
$table->string('ip_address', 45)->nullable();
$table->timestamp('created_at')->useCurrent();
$table->index(['model_type', 'model_id']);
$table->index('action');
$table->index('created_at');
});
}
public function down(): void
{
Schema::dropIfExists('activity_logs');
}
};
@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('notifications', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('type');
$table->morphs('notifiable');
$table->text('data');
$table->timestamp('read_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('notifications');
}
};
@@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('settings', function (Blueprint $table) {
$table->id();
$table->string('key')->unique();
$table->longText('value')->nullable();
$table->string('type')->default('string');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('settings');
}
};
@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('jobs', function (Blueprint $table) {
$table->id();
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
}
public function down(): void
{
Schema::dropIfExists('jobs');
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('job_batches', function (Blueprint $table) {
$table->string('id')->primary();
$table->string('name');
$table->integer('total_jobs');
$table->integer('pending_jobs');
$table->integer('failed_jobs');
$table->longText('failed_job_ids');
$table->mediumText('options')->nullable();
$table->integer('cancelled_at')->nullable();
$table->integer('created_at');
$table->integer('finished_at')->nullable();
});
}
public function down(): void
{
Schema::dropIfExists('job_batches');
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->integer('expiration');
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->integer('expiration');
});
}
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace Database\Seeders;
use App\Models\ActivityLog;
use App\Models\ServiceRequest;
use App\Models\User;
use Illuminate\Database\Seeder;
class ActivityLogSeeder extends Seeder
{
public function run(): void
{
$users = User::query()->get();
$requests = ServiceRequest::query()->latest()->limit(10)->get();
foreach ($requests as $request) {
ActivityLog::query()->create([
'user_id' => $users->random()->id,
'model_type' => ServiceRequest::class,
'model_id' => $request->id,
'action' => fake()->randomElement(['updated', 'assigned', 'status_changed']),
'description' => fake()->sentence(),
'ip_address' => '127.0.0.1',
'created_at' => now()->subHours(rand(1, 72)),
]);
}
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
$this->call([
DepartmentSeeder::class,
EquipmentCategorySeeder::class,
RequestTypeSeeder::class,
PrioritySeeder::class,
StatusSeeder::class,
UserSeeder::class,
EquipmentSeeder::class,
ServiceRequestSeeder::class,
ActivityLogSeeder::class,
SettingSeeder::class,
]);
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Database\Seeders;
use App\Models\Department;
use Illuminate\Database\Seeder;
class DepartmentSeeder extends Seeder
{
public function run(): void
{
$departments = [
['name' => 'Сервисный отдел', 'description' => 'Ремонт, диагностика и обслуживание оборудования.'],
['name' => 'IT Helpdesk', 'description' => 'Поддержка пользователей и обработка обращений.'],
];
foreach ($departments as $department) {
Department::query()->updateOrCreate(
['name' => $department['name']],
$department
);
}
}
}
@@ -0,0 +1,31 @@
<?php
namespace Database\Seeders;
use App\Models\EquipmentCategory;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
class EquipmentCategorySeeder extends Seeder
{
public function run(): void
{
$categories = [
['name' => 'Ноутбуки', 'description' => 'Мобильные рабочие станции и ноутбуки.'],
['name' => 'Настольные ПК', 'description' => 'Офисные персональные компьютеры.'],
['name' => 'Сетевое оборудование', 'description' => 'Роутеры, коммутаторы, точки доступа.'],
['name' => 'Принтеры и МФУ', 'description' => 'Печатная техника и многофункциональные устройства.'],
];
foreach ($categories as $category) {
EquipmentCategory::query()->updateOrCreate(
['slug' => Str::slug($category['name'])],
[
'name' => $category['name'],
'slug' => Str::slug($category['name']),
'description' => $category['description'],
]
);
}
}
}
+44
View File
@@ -0,0 +1,44 @@
<?php
namespace Database\Seeders;
use App\Enums\EquipmentCondition;
use App\Enums\UserRole;
use App\Models\Equipment;
use App\Models\EquipmentCategory;
use App\Models\User;
use Illuminate\Database\Seeder;
class EquipmentSeeder extends Seeder
{
public function run(): void
{
$categories = EquipmentCategory::query()->get();
$clients = User::query()->where('role', UserRole::CLIENT)->get();
for ($i = 1; $i <= 10; $i++) {
$category = $categories->random();
$client = $clients->random();
Equipment::query()->updateOrCreate(
['inventory_number' => sprintf('INV-%04d', $i)],
[
'name' => fake()->randomElement([
'Ноутбук Dell Latitude',
'HP ProDesk',
'Cisco Router',
'Brother MFC Printer',
'Lenovo ThinkPad',
]).' '.$i,
'serial_number' => sprintf('SN-%08d', 10000000 + $i),
'category_id' => $category->id,
'client_id' => $client->id,
'purchase_date' => now()->subMonths(rand(6, 48))->toDateString(),
'warranty_until' => now()->addDays(rand(-90, 365))->toDateString(),
'condition' => fake()->randomElement(EquipmentCondition::cases())->value,
'notes' => fake()->sentence(),
]
);
}
}
}
+23
View File
@@ -0,0 +1,23 @@
<?php
namespace Database\Seeders;
use App\Models\Priority;
use Illuminate\Database\Seeder;
class PrioritySeeder extends Seeder
{
public function run(): void
{
$priorities = [
['name' => 'Низкий', 'color_hex' => '#10B981', 'level' => 1],
['name' => 'Средний', 'color_hex' => '#3B82F6', 'level' => 2],
['name' => 'Высокий', 'color_hex' => '#F59E0B', 'level' => 3],
['name' => 'Критический', 'color_hex' => '#EF4444', 'level' => 4],
];
foreach ($priorities as $priority) {
Priority::query()->updateOrCreate(['level' => $priority['level']], $priority);
}
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Database\Seeders;
use App\Models\RequestType;
use Illuminate\Database\Seeder;
class RequestTypeSeeder extends Seeder
{
public function run(): void
{
$types = [
['name' => 'Диагностика', 'description' => 'Первичная диагностика и выявление неисправности.', 'sla_hours' => 24],
['name' => 'Аппаратный ремонт', 'description' => 'Замена или ремонт аппаратных компонентов.', 'sla_hours' => 48],
['name' => 'Программная поддержка', 'description' => 'Настройка ОС, ПО, устранение программных ошибок.', 'sla_hours' => 12],
['name' => 'Плановое обслуживание', 'description' => 'Профилактические и регламентные работы.', 'sla_hours' => 72],
['name' => 'Сетевая проблема', 'description' => 'Проблемы с сетью и доступом к ресурсам.', 'sla_hours' => 8],
];
foreach ($types as $type) {
RequestType::query()->updateOrCreate(['name' => $type['name']], $type);
}
}
}
+88
View File
@@ -0,0 +1,88 @@
<?php
namespace Database\Seeders;
use App\Models\ActivityLog;
use App\Models\Equipment;
use App\Models\Priority;
use App\Models\RequestComment;
use App\Models\RequestType;
use App\Models\ServiceRequest;
use App\Models\Status;
use App\Models\User;
use Illuminate\Database\Seeder;
class ServiceRequestSeeder extends Seeder
{
public function run(): void
{
$types = RequestType::query()->get();
$priorities = Priority::query()->orderBy('level')->get();
$statuses = Status::query()->get();
$clients = User::query()->where('role', 'client')->get();
$techs = User::query()->where('role', 'technician')->get();
$equipment = Equipment::query()->get();
for ($i = 1; $i <= 25; $i++) {
$type = $types->random();
$priority = $priorities->random();
$status = $statuses->random();
$client = $clients->random();
$assignee = $techs->random();
$createdAt = now()->subDays(rand(0, 20))->subHours(rand(0, 23));
$deadlineAt = (clone $createdAt)->addHours($type->sla_hours);
$request = ServiceRequest::query()->create([
'ticket_number' => sprintf('SRV-%04d', $i),
'title' => fake()->randomElement([
'Не включается рабочая станция',
'Проблема с печатью документов',
'Нет доступа к корпоративной сети',
'Требуется установка ПО',
'Сильный шум вентилятора',
]),
'description' => fake()->paragraph(3),
'type_id' => $type->id,
'priority_id' => $priority->id,
'status_id' => $status->id,
'client_id' => $client->id,
'assigned_to' => $assignee->id,
'equipment_id' => rand(0, 100) > 20 ? $equipment->random()?->id : null,
'location' => fake()->randomElement(['Офис 101', 'Офис 204', 'Склад', 'Переговорная 2']),
'planned_at' => rand(0, 100) > 50 ? $createdAt->copy()->addHours(rand(2, 24)) : null,
'deadline_at' => $deadlineAt,
'started_at' => rand(0, 100) > 40 ? $createdAt->copy()->addHours(rand(1, 8)) : null,
'completed_at' => $status->is_final ? $deadlineAt->copy()->subHours(rand(0, 6)) : null,
'resolution_notes' => $status->slug === 'resolved' || $status->slug === 'closed'
? fake()->sentence(12)
: null,
'client_rating' => $status->slug === 'closed' ? rand(3, 5) : null,
'client_comment' => $status->slug === 'closed' ? fake()->sentence() : null,
'created_at' => $createdAt,
'updated_at' => now(),
]);
for ($commentIndex = 1; $commentIndex <= rand(1, 3); $commentIndex++) {
$author = rand(0, 1) ? $client : $assignee;
RequestComment::query()->create([
'request_id' => $request->id,
'user_id' => $author->id,
'body' => fake()->sentence(rand(10, 20)),
'is_internal' => $author->role !== 'client' && rand(0, 100) > 60,
'created_at' => $createdAt->copy()->addHours($commentIndex),
'updated_at' => $createdAt->copy()->addHours($commentIndex),
]);
}
ActivityLog::query()->create([
'user_id' => $assignee->id,
'model_type' => ServiceRequest::class,
'model_id' => $request->id,
'action' => 'created',
'description' => "Создана заявка {$request->ticket_number}",
'ip_address' => '127.0.0.1',
'created_at' => $createdAt,
]);
}
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace Database\Seeders;
use App\Models\Setting;
use Illuminate\Database\Seeder;
class SettingSeeder extends Seeder
{
public function run(): void
{
$defaults = [
['key' => 'company_name', 'value' => 'Computer Service', 'type' => 'string'],
['key' => 'company_logo', 'value' => null, 'type' => 'string'],
['key' => 'timezone', 'value' => 'Asia/Yekaterinburg', 'type' => 'string'],
['key' => 'default_sla_hours', 'value' => '24', 'type' => 'integer'],
['key' => 'maintenance_mode', 'value' => '0', 'type' => 'boolean'],
[
'key' => 'email_notifications',
'value' => json_encode([
'assigned' => true,
'status_changed' => true,
'comment_added' => true,
'overdue' => true,
'sla_warning' => true,
], JSON_THROW_ON_ERROR),
'type' => 'json',
],
];
foreach ($defaults as $setting) {
Setting::query()->updateOrCreate(
['key' => $setting['key']],
[
'value' => $setting['value'],
'type' => $setting['type'],
]
);
}
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace Database\Seeders;
use App\Enums\StatusSlug;
use App\Models\Status;
use Illuminate\Database\Seeder;
class StatusSeeder extends Seeder
{
public function run(): void
{
$statuses = [
['name' => 'Новая', 'slug' => StatusSlug::NEW->value, 'color_hex' => '#3B82F6', 'is_final' => false, 'sort_order' => 1],
['name' => 'В работе', 'slug' => StatusSlug::IN_PROGRESS->value, 'color_hex' => '#F59E0B', 'is_final' => false, 'sort_order' => 2],
['name' => 'Ожидание', 'slug' => StatusSlug::WAITING->value, 'color_hex' => '#6366F1', 'is_final' => false, 'sort_order' => 3],
['name' => 'Решена', 'slug' => StatusSlug::RESOLVED->value, 'color_hex' => '#10B981', 'is_final' => false, 'sort_order' => 4],
['name' => 'Закрыта', 'slug' => StatusSlug::CLOSED->value, 'color_hex' => '#6B7280', 'is_final' => true, 'sort_order' => 5],
['name' => 'Отменена', 'slug' => StatusSlug::CANCELLED->value, 'color_hex' => '#EF4444', 'is_final' => true, 'sort_order' => 6],
];
foreach ($statuses as $status) {
Status::query()->updateOrCreate(['slug' => $status['slug']], $status);
}
}
}
+80
View File
@@ -0,0 +1,80 @@
<?php
namespace Database\Seeders;
use App\Enums\UserRole;
use App\Models\Department;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
class UserSeeder extends Seeder
{
public function run(): void
{
$serviceDepartment = Department::query()->where('name', 'Сервисный отдел')->first();
$helpdeskDepartment = Department::query()->where('name', 'IT Helpdesk')->first();
User::query()->updateOrCreate(
['email' => 'admin@service.local'],
[
'name' => 'Главный администратор',
'password' => Hash::make('password'),
'role' => UserRole::ADMIN,
'phone' => '+79990000001',
'department_id' => $helpdeskDepartment?->id,
'is_active' => true,
'email_verified_at' => now(),
]
);
User::query()->updateOrCreate(
['email' => 'manager@service.local'],
[
'name' => 'Сервис-менеджер',
'password' => Hash::make('password'),
'role' => UserRole::MANAGER,
'phone' => '+79990000002',
'department_id' => $serviceDepartment?->id,
'is_active' => true,
'email_verified_at' => now(),
]
);
$technicians = [
['name' => 'Иван Петров', 'email' => 'tech1@service.local'],
['name' => 'Алексей Сидоров', 'email' => 'tech2@service.local'],
['name' => 'Ольга Смирнова', 'email' => 'tech3@service.local'],
];
foreach ($technicians as $technician) {
User::query()->updateOrCreate(
['email' => $technician['email']],
[
'name' => $technician['name'],
'password' => Hash::make('password'),
'role' => UserRole::TECHNICIAN,
'phone' => '+7999'.fake()->numerify('######'),
'department_id' => $serviceDepartment?->id,
'is_active' => true,
'email_verified_at' => now(),
]
);
}
for ($i = 1; $i <= 5; $i++) {
User::query()->updateOrCreate(
['email' => "client{$i}@service.local"],
[
'name' => "Клиент {$i}",
'password' => Hash::make('password'),
'role' => UserRole::CLIENT,
'phone' => '+7991'.str_pad((string) $i, 6, '0', STR_PAD_LEFT),
'department_id' => null,
'is_active' => true,
'email_verified_at' => now(),
]
);
}
}
}