big update base struktur tahap 1

This commit is contained in:
Wian Drs
2026-07-27 16:24:09 +07:00
parent 2b3592c4c2
commit 1dd02baa72
169 changed files with 24405 additions and 977 deletions
@@ -0,0 +1,30 @@
<?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::table('users', function (Blueprint $table) {
$table->boolean('is_master')
->default(false)
->after('password');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('is_master');
});
}
};
@@ -0,0 +1,56 @@
<?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) {
if (!Schema::hasColumn('users', 'verification_channel')) {
$table->string('verification_channel')->nullable()->after('status');
}
if (!Schema::hasColumn('users', 'verification_target')) {
$table->string('verification_target')->nullable()->after('verification_channel');
}
if (!Schema::hasColumn('users', 'verification_code')) {
$table->string('verification_code')->nullable()->after('verification_target');
}
if (!Schema::hasColumn('users', 'verification_code_expires_at')) {
$table->timestamp('verification_code_expires_at')->nullable()->after('verification_code');
}
if (!Schema::hasColumn('users', 'verified_at')) {
$table->timestamp('verified_at')->nullable()->after('verification_code_expires_at');
}
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$columns = [];
foreach ([
'verification_channel',
'verification_target',
'verification_code',
'verification_code_expires_at',
'verified_at',
] as $column) {
if (Schema::hasColumn('users', $column)) {
$columns[] = $column;
}
}
if (!empty($columns)) {
$table->dropColumn($columns);
}
});
}
};
@@ -0,0 +1,22 @@
<?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->string('whatsapp_number', 20)->nullable()->after('email');
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('whatsapp_number');
});
}
};
@@ -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::table('users', function (Blueprint $table) {
if (!Schema::hasColumn('users', 'deleted_at')) {
$table->softDeletes();
}
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
if (Schema::hasColumn('users', 'deleted_at')) {
$table->dropSoftDeletes();
}
});
}
};
@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('access_level', 30)
->default('customer')
->after('is_master')
->index();
});
DB::table('users')
->where('is_master', true)
->update(['access_level' => 'master_admin']);
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('access_level');
});
}
};
@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('menu_groups', function (Blueprint $table) {
$table->dropUnique(['name']);
$table->foreignId('tenant_id')
->nullable()
->after('id')
->constrained()
->cascadeOnDelete();
$table->boolean('is_system')->default(false)->after('description');
$table->unique(['tenant_id', 'name']);
});
DB::table('menu_groups')
->whereNull('tenant_id')
->update(['is_system' => true]);
}
public function down(): void
{
Schema::table('menu_groups', function (Blueprint $table) {
$table->dropUnique(['tenant_id', 'name']);
$table->dropConstrainedForeignId('tenant_id');
$table->dropColumn('is_system');
$table->unique('name');
});
}
};
@@ -0,0 +1,22 @@
<?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('user_profiles', function (Blueprint $table) {
$table->dropColumn('phone');
});
}
public function down(): void
{
Schema::table('user_profiles', function (Blueprint $table) {
$table->string('phone', 30)->nullable()->after('nik');
});
}
};
@@ -0,0 +1,34 @@
<?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('stored_files', function (Blueprint $table) {
$table->id();
$table->uuid('uuid')->unique();
$table->foreignId('tenant_id')->nullable()->constrained('tenants')->nullOnDelete();
$table->foreignId('uploaded_by')->nullable()->constrained('users')->nullOnDelete();
$table->string('disk', 50)->default('minio');
$table->string('bucket');
$table->string('object_key', 1024)->unique();
$table->string('original_name');
$table->string('extension', 20)->nullable();
$table->string('mime_type', 150)->nullable();
$table->unsignedBigInteger('size');
$table->string('category', 80)->default('general')->index();
$table->string('visibility', 20)->default('private');
$table->timestamps();
$table->softDeletes();
});
}
public function down(): void
{
Schema::dropIfExists('stored_files');
}
};
@@ -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->foreignId('profile_photo_file_id')
->nullable()
->after('whatsapp_number')
->constrained('stored_files')
->nullOnDelete();
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropConstrainedForeignId('profile_photo_file_id');
});
}
};
@@ -0,0 +1,99 @@
<?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('nas_mikrotiks', function (Blueprint $table) {
$table->id();
$table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->string('connection_type', 20);
$table->string('host');
$table->unsignedSmallInteger('api_port')->nullable()->default(8728);
$table->string('api_username')->nullable();
$table->text('api_password')->nullable();
$table->unsignedSmallInteger('radius_auth_port')->nullable()->default(1812);
$table->unsignedSmallInteger('radius_accounting_port')->nullable()->default(1813);
$table->text('radius_secret')->nullable();
$table->unsignedSmallInteger('timeout')->default(10);
$table->string('status', 20)->default('active');
$table->text('notes')->nullable();
$table->timestamps();
$table->unique(['tenant_id', 'name']);
$table->index(['tenant_id', 'connection_type', 'status']);
});
Schema::create('nas_package_profiles', function (Blueprint $table) {
$table->id();
$table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->string('service_type', 20);
$table->string('external_profile_name')->nullable();
$table->unsignedBigInteger('download_kbps')->nullable();
$table->unsignedBigInteger('upload_kbps')->nullable();
$table->string('local_address')->nullable();
$table->string('remote_address_pool')->nullable();
$table->unsignedInteger('session_timeout')->nullable();
$table->unsignedInteger('idle_timeout')->nullable();
$table->unsignedInteger('shared_users')->default(1);
$table->decimal('price', 15, 2)->default(0);
$table->string('status', 20)->default('active');
$table->text('notes')->nullable();
$table->timestamps();
$table->unique(['tenant_id', 'name']);
$table->index(['tenant_id', 'service_type', 'status']);
});
Schema::create('nas_olts', function (Blueprint $table) {
$table->id();
$table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->string('vendor')->nullable();
$table->string('model')->nullable();
$table->string('host');
$table->unsignedSmallInteger('snmp_port')->default(161);
$table->string('snmp_version', 10)->default('v2c');
$table->text('community')->nullable();
$table->string('security_level', 30)->nullable();
$table->string('security_name')->nullable();
$table->string('auth_protocol', 10)->nullable();
$table->text('auth_password')->nullable();
$table->string('privacy_protocol', 10)->nullable();
$table->text('privacy_password')->nullable();
$table->unsignedSmallInteger('timeout')->default(5);
$table->string('status', 20)->default('active');
$table->text('notes')->nullable();
$table->timestamps();
$table->unique(['tenant_id', 'name']);
$table->index(['tenant_id', 'status']);
});
Schema::create('nas_webfig_devices', function (Blueprint $table) {
$table->id();
$table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->string('device_type')->nullable();
$table->text('url');
$table->string('username')->nullable();
$table->text('password')->nullable();
$table->string('status', 20)->default('active');
$table->text('notes')->nullable();
$table->timestamps();
$table->unique(['tenant_id', 'name']);
$table->index(['tenant_id', 'status']);
});
}
public function down(): void
{
Schema::dropIfExists('nas_webfig_devices');
Schema::dropIfExists('nas_olts');
Schema::dropIfExists('nas_package_profiles');
Schema::dropIfExists('nas_mikrotiks');
}
};
+10 -4
View File
@@ -16,11 +16,17 @@ class DatabaseSeeder extends Seeder
// User::factory(10)->create();
$this->call([
TicketTypeSeeder::class,
MenuListSeeder::class,
]);
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);
User::query()->updateOrCreate(
['email' => 'master@services-core.local'],
[
'name' => 'Master User',
'password' => 'Master@12345',
'is_master' => true,
'access_level' => 'master_admin',
]
);
}
}
+224
View File
@@ -0,0 +1,224 @@
<?php
namespace Database\Seeders;
use App\Models\MenuList;
use Illuminate\Database\Seeder;
class MenuListSeeder extends Seeder
{
/**
* Seed default menu list for CoreUI navigation.
*/
public function run(): void
{
$users = MenuList::updateOrCreate(
['slug' => 'users'],
[
'parent_id' => null,
'name' => 'Pengguna',
'url' => null,
'icon' => 'cil-user',
'component' => null,
'sort_order' => 1,
'is_active' => true,
]
);
MenuList::updateOrCreate(
['slug' => 'users-user'],
[
'parent_id' => $users->id,
'name' => 'Data Pengguna',
'url' => '/users',
'icon' => 'cil-people',
'component' => null,
'sort_order' => 1,
'is_active' => true,
]
);
MenuList::updateOrCreate(
['slug' => 'users-group-menus'],
[
'parent_id' => $users->id,
'name' => 'Grup Menu',
'url' => '/group-menus',
'icon' => 'cil-list-rich',
'component' => null,
'sort_order' => 2,
'is_active' => true,
]
);
MenuList::updateOrCreate(
['slug' => 'tenants'],
[
'parent_id' => null,
'name' => 'Tenant',
'url' => '/tenants',
'icon' => 'cil-layers',
'component' => null,
'sort_order' => 2,
'is_active' => true,
]
);
$ticketing = MenuList::updateOrCreate(
['slug' => 'ticketing'],
[
'parent_id' => null,
'name' => 'Ticketing',
'url' => null,
'icon' => 'cil-description',
'component' => null,
'sort_order' => 3,
'is_active' => true,
]
);
MenuList::updateOrCreate(
['slug' => 'ticketing-material'],
[
'parent_id' => $ticketing->id,
'name' => 'Material',
'url' => '/materials',
'icon' => 'cil-layers',
'component' => null,
'sort_order' => 1,
'is_active' => true,
]
);
MenuList::updateOrCreate(
['slug' => 'ticketing-ticket'],
[
'parent_id' => $ticketing->id,
'name' => 'Tiket',
'url' => '/tickets',
'icon' => 'cil-ticket',
'component' => null,
'sort_order' => 2,
'is_active' => true,
]
);
MenuList::updateOrCreate(
['slug' => 'ticketing-approval'],
[
'parent_id' => $ticketing->id,
'name' => 'Persetujuan',
'url' => '/tickets/approval',
'icon' => 'cil-check-circle',
'component' => null,
'sort_order' => 3,
'is_active' => true,
]
);
MenuList::updateOrCreate(
['slug' => 'ticketing-rejected'],
[
'parent_id' => $ticketing->id,
'name' => 'Ditolak',
'url' => '/tickets/rejected',
'icon' => 'cil-x-circle',
'component' => null,
'sort_order' => 4,
'is_active' => true,
]
);
MenuList::updateOrCreate(
['slug' => 'ticketing-ticket-types'],
[
'parent_id' => $ticketing->id,
'name' => 'Jenis Tiket',
'url' => '/ticket-types',
'icon' => 'cil-tags',
'component' => null,
'sort_order' => 5,
'is_active' => true,
]
);
MenuList::updateOrCreate(
['slug' => 'ticketing-ticket-incidents'],
[
'parent_id' => $ticketing->id,
'name' => 'Insiden Tiket',
'url' => '/ticket-incident-types',
'icon' => 'cil-warning',
'component' => null,
'sort_order' => 6,
'is_active' => true,
]
);
$wilayah = MenuList::updateOrCreate(
['slug' => 'wilayah'],
[
'parent_id' => null,
'name' => 'Wilayah',
'url' => null,
'icon' => 'cil-location-pin',
'component' => null,
'sort_order' => 4,
'is_active' => true,
]
);
foreach ([
['slug' => 'wilayah-desa', 'name' => 'Desa', 'url' => '/wilayah/desa', 'sort_order' => 1],
['slug' => 'wilayah-kecamatan', 'name' => 'Kecamatan', 'url' => '/wilayah/kecamatan', 'sort_order' => 2],
['slug' => 'wilayah-kabupaten', 'name' => 'Kabupaten', 'url' => '/wilayah/kabupaten', 'sort_order' => 3],
['slug' => 'wilayah-provinsi', 'name' => 'Provinsi', 'url' => '/wilayah/provinsi', 'sort_order' => 4],
] as $item) {
MenuList::updateOrCreate(
['slug' => $item['slug']],
[
'parent_id' => $wilayah->id,
'name' => $item['name'],
'url' => $item['url'],
'icon' => 'cil-location-pin',
'component' => null,
'sort_order' => $item['sort_order'],
'is_active' => true,
]
);
}
$nas = MenuList::updateOrCreate(
['slug' => 'nas'],
[
'parent_id' => null,
'name' => 'NAS',
'url' => null,
'icon' => 'cil-settings',
'component' => null,
'sort_order' => 5,
'is_active' => true,
]
);
foreach ([
['slug' => 'nas-mikrotik', 'name' => 'Mikrotik', 'url' => '/nas/mikrotik', 'icon' => 'cil-settings', 'sort_order' => 1],
['slug' => 'nas-package-profiles', 'name' => 'Profile Paket', 'url' => '/nas/package-profiles', 'icon' => 'cil-speedometer', 'sort_order' => 2],
['slug' => 'nas-olt', 'name' => 'OLT', 'url' => '/nas/olt', 'icon' => 'cil-layers', 'sort_order' => 3],
['slug' => 'nas-webfig', 'name' => 'Webfig', 'url' => '/nas/webfig', 'icon' => 'cil-laptop', 'sort_order' => 4],
] as $item) {
MenuList::updateOrCreate(
['slug' => $item['slug']],
[
'parent_id' => $nas->id,
'name' => $item['name'],
'url' => $item['url'],
'icon' => $item['icon'],
'component' => null,
'sort_order' => $item['sort_order'],
'is_active' => true,
]
);
}
}
}