seeder
This commit is contained in:
parent
cc98e0761e
commit
e5cb2e916c
|
|
@ -0,0 +1,71 @@
|
||||||
|
# MPG HRIS - Web Management System
|
||||||
|
|
||||||
|
Sistem Manajemen Sumber Daya Manusia (HRIS) terintegrasi untuk pengelolaan data pegawai, presensi, lembur, dan perizinan. Dibuat menggunakan framework Laravel dengan fokus pada performa dan kemudahan penggunaan.
|
||||||
|
|
||||||
|
## 🚀 Tech Stack
|
||||||
|
|
||||||
|
- **Backend**: Laravel 12.x (PHP 8.2+)
|
||||||
|
- **Frontend**: Blade Templates + Tailwind CSS (v3.x)
|
||||||
|
- **Database**: MySQL 8.x
|
||||||
|
- **Icons**: Heroicons (SVG inline)
|
||||||
|
- **Komponen UI**: Custom Blade Components (Table, Modal, Input, Button, dll.)
|
||||||
|
|
||||||
|
## 🛠 Panduan Instalasi
|
||||||
|
|
||||||
|
Ikuti langkah-langkah berikut untuk menjalankan proyek di lingkungan lokal:
|
||||||
|
|
||||||
|
1. **Clone & Setup Environment**
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# Sesuaikan DB_DATABASE, DB_USERNAME, DB_PASSWORD di .env
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Instal Dependensi Backend**
|
||||||
|
```bash
|
||||||
|
composer install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Instal Dependensi Frontend**
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run build # atau npm run dev untuk development
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Generate App Key & Database**
|
||||||
|
```bash
|
||||||
|
php artisan key:generate
|
||||||
|
php artisan migrate --seed
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Akses Aplikasi**
|
||||||
|
Jalankan `php artisan serve` dan buka `http://localhost:8000`.
|
||||||
|
|
||||||
|
## 📂 Struktur Proyek & Arsitektur
|
||||||
|
|
||||||
|
Proyek ini mengikuti standar **Clean Code** Laravel dengan pemisahan tanggung jawab yang jelas:
|
||||||
|
|
||||||
|
- **Form Requests**: Semua validasi input diletakkan di `app/Http/Requests`.
|
||||||
|
- **Controllers**: Fokus pada pengaturan trafik. Logika query berat dipisahkan ke Eloquent Scopes atau Service.
|
||||||
|
- **Models**: Menggunakan relasi Eloquent yang jelas dan penamaan kolom `snake_case` Bahasa Indonesia.
|
||||||
|
- **Resources**: UI dibangun menggunakan komponen Blade di `resources/views/components`.
|
||||||
|
|
||||||
|
## 📜 Aturan Pengembangan (Project Rules)
|
||||||
|
|
||||||
|
1. **Bahasa**: Gunakan Bahasa Indonesia untuk penjelasan, komentar, dan dokumentasi.
|
||||||
|
2. **Naming Convention**:
|
||||||
|
- Primary Key: `id_nama_tabel` (contoh: `id_divisi`, `id_jabatan`).
|
||||||
|
- Tabel Master: `snake_case`.
|
||||||
|
3. **UI Components**: Gunakan komponen yang sudah ada untuk konsistensi:
|
||||||
|
- `<x-table>`: Wrapper tabel standar.
|
||||||
|
- `<x-input>` & `<x-select>`: Input form standar.
|
||||||
|
- `<x-button>` & `<x-back-button>`: Tombol aksi.
|
||||||
|
- `<x-modal>`: Untuk CRUD Data Master sederhana.
|
||||||
|
|
||||||
|
## 🔑 Akun Default (Seeder)
|
||||||
|
|
||||||
|
- **Super Admin**: `superadmin@mpg.co.id` / `password`
|
||||||
|
- **Admin**: `admin@mpg.co.id` / `admin123`
|
||||||
|
- **Pegawai**: `budi@mpg.co.id` / `Mpg123!`
|
||||||
|
|
||||||
|
---
|
||||||
|
Developed by MPG Team.
|
||||||
|
|
@ -10,55 +10,38 @@ class DatabaseSeeder extends Seeder
|
||||||
{
|
{
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
|
// Panggil MasterDataSeeder terlebih dahulu untuk data dasar (Divisi, Jabatan, Kantor, Role, User Admin)
|
||||||
DB::table('lokasi_kantor')->insert([
|
|
||||||
[
|
|
||||||
'nama_kantor' => 'Notis Digital',
|
|
||||||
'alamat' => 'Jln. Kalimantan No. 1, Jember',
|
|
||||||
'latitude' => -8.172110,
|
|
||||||
'longitude' => 113.700550,
|
|
||||||
'radius_meter' => 200,
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'nama_kantor' => 'Curah Manis Studio',
|
|
||||||
'alamat' => 'Jln. Mastrip, Jember',
|
|
||||||
'latitude' => -8.172110,
|
|
||||||
'longitude' => 113.700550,
|
|
||||||
'radius_meter' => 200,
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
User::factory(10)->create([
|
|
||||||
'id_kantor' => 1,
|
|
||||||
]);
|
|
||||||
|
|
||||||
User::factory(15)->create([
|
|
||||||
'id_kantor' => 2,
|
|
||||||
]);
|
|
||||||
|
|
||||||
User::factory()->create([
|
|
||||||
'nama_lengkap' => 'Julian (Super Admin)',
|
|
||||||
'email' => 'julian@admin.com',
|
|
||||||
'password' => bcrypt('password'),
|
|
||||||
'divisi' => 'IT',
|
|
||||||
'jabatan' => 'Manager',
|
|
||||||
'id_kantor' => 1,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->call([
|
$this->call([
|
||||||
MasterDataSeeder::class,
|
MasterDataSeeder::class,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Tambahan data demo jika diperlukan (Opsional)
|
||||||
|
$kantor = \App\Models\Kantor::first();
|
||||||
|
$divisi = \App\Models\Divisi::first();
|
||||||
|
$jabatan = \App\Models\Jabatan::where('nama_jabatan', 'Staff')->first() ?? \App\Models\Jabatan::first();
|
||||||
|
|
||||||
|
$users = User::factory(5)->create([
|
||||||
|
'id_kantor' => $kantor->id_kantor,
|
||||||
|
'id_divisi' => $divisi->id_divisi,
|
||||||
|
'id_jabatan' => $jabatan->id_jabatan,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$rolePegawai = \App\Models\Role::where('nama_role', 'pegawai')->first();
|
||||||
|
if ($rolePegawai) {
|
||||||
|
foreach ($users as $user) {
|
||||||
|
$user->roles()->attach($rolePegawai->id_role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Panggil seeder fitur lainnya
|
||||||
|
$this->call([
|
||||||
PermissionSeeder::class,
|
PermissionSeeder::class,
|
||||||
PresensiStatusSeeder::class,
|
PresensiStatusSeeder::class,
|
||||||
PresensiSeeder::class,
|
PresensiSeeder::class,
|
||||||
|
|
||||||
JenisIzinSeeder::class,
|
JenisIzinSeeder::class,
|
||||||
StatusPengajuanSeeder::class,
|
StatusPengajuanSeeder::class,
|
||||||
|
|
||||||
PengajuanIzinSeeder::class,
|
PengajuanIzinSeeder::class,
|
||||||
|
SuperAdminSeeder::class, // Menambah super administrator dengan role admin
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,12 @@ class JenisIzinSeeder extends Seeder
|
||||||
{
|
{
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
DB::table('jenis_izin')->delete();
|
$types = ['Sakit', 'Cuti', 'Izin'];
|
||||||
|
foreach ($types as $type) {
|
||||||
DB::table('jenis_izin')->insert([
|
DB::table('jenis_izin')->updateOrInsert(
|
||||||
|
['nama_izin' => $type],
|
||||||
['id_jenis_izin' => 1, 'nama_izin' => 'Sakit'],
|
['updated_at' => now(), 'created_at' => now()]
|
||||||
['id_jenis_izin' => 2, 'nama_izin' => 'Cuti'],
|
);
|
||||||
['id_jenis_izin' => 3, 'nama_izin' => 'Izin'],
|
}
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,54 +13,74 @@ class MasterDataSeeder extends Seeder
|
||||||
{
|
{
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
|
$divIT = Divisi::firstOrCreate(['nama_divisi' => 'Information Technology']);
|
||||||
|
$divHR = Divisi::firstOrCreate(['nama_divisi' => 'Human Resources']);
|
||||||
|
Divisi::firstOrCreate(['nama_divisi' => 'Finance & Accounting']);
|
||||||
|
Divisi::firstOrCreate(['nama_divisi' => 'Marketing']);
|
||||||
|
|
||||||
$divIT = Divisi::create(['nama_divisi' => 'Information Technology']);
|
$jabMgr = Jabatan::firstOrCreate(['nama_jabatan' => 'Manager']);
|
||||||
$divHR = Divisi::create(['nama_divisi' => 'Human Resources']);
|
$jabSpv = Jabatan::firstOrCreate(['nama_jabatan' => 'Supervisor']);
|
||||||
Divisi::create(['nama_divisi' => 'Finance & Accounting']);
|
$jabStf = Jabatan::firstOrCreate(['nama_jabatan' => 'Staff']);
|
||||||
Divisi::create(['nama_divisi' => 'Marketing']);
|
Jabatan::firstOrCreate(['nama_jabatan' => 'Internship']);
|
||||||
|
|
||||||
$jabMgr = Jabatan::create(['nama_jabatan' => 'Manager']);
|
$kPusat = Kantor::firstOrCreate(
|
||||||
$jabSpv = Jabatan::create(['nama_jabatan' => 'Supervisor']);
|
['nama_kantor' => 'Kantor Pusat'],
|
||||||
$jabStf = Jabatan::create(['nama_jabatan' => 'Staff']);
|
[
|
||||||
Jabatan::create(['nama_jabatan' => 'Internship']);
|
'alamat' => 'Jl. Jendral Sudirman No. 1, Jakarta',
|
||||||
|
'latitude' => -6.2088,
|
||||||
|
'longitude' => 106.8456,
|
||||||
|
'radius' => 200
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
$kPusat = Kantor::create([
|
$kCabang = Kantor::firstOrCreate(
|
||||||
'nama_kantor' => 'Kantor Pusat',
|
['nama_kantor' => 'Curah Manis Studio'],
|
||||||
'alamat' => 'Jl. Jendral Sudirman No. 1, Jakarta',
|
[
|
||||||
'tipe' => 'Pusat'
|
'alamat' => 'Jl. Curah Manis, Malang',
|
||||||
]);
|
'latitude' => -7.9839,
|
||||||
|
'longitude' => 112.6214,
|
||||||
|
'radius' => 200
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
$kCabang = Kantor::create([
|
// Roles
|
||||||
'nama_kantor' => 'Curah Manis Studio',
|
$roleAdmin = \App\Models\Role::firstOrCreate(['nama_role' => 'admin']);
|
||||||
'alamat' => 'Jl. Curah Manis, Malang',
|
$roleHrd = \App\Models\Role::firstOrCreate(['nama_role' => 'hrd']);
|
||||||
'tipe' => 'Cabang'
|
$roleManager = \App\Models\Role::firstOrCreate(['nama_role' => 'manager']);
|
||||||
]);
|
$rolePegawai = \App\Models\Role::firstOrCreate(['nama_role' => 'pegawai']);
|
||||||
|
|
||||||
User::create([
|
$admin = User::updateOrCreate(
|
||||||
'nama_lengkap' => 'Super Administrator',
|
['email' => 'admin@mpg.co.id'],
|
||||||
'email' => 'admin@mpg.co.id',
|
[
|
||||||
'password' => Hash::make('admin123'),
|
'nama_lengkap' => 'Super Administrator',
|
||||||
'role' => 'admin',
|
'password' => Hash::make('admin123'),
|
||||||
'nik' => '999999999',
|
'nik' => '999999999',
|
||||||
'status_aktif' => 1,
|
'status_aktif' => 1,
|
||||||
|
'id_divisi' => $divIT->id_divisi,
|
||||||
|
'id_jabatan' => $jabMgr->id_jabatan,
|
||||||
|
'id_kantor' => $kPusat->id_kantor,
|
||||||
|
'tgl_bergabung' => now(),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
if (!$admin->roles()->where('nama_role', 'admin')->exists()) {
|
||||||
|
$admin->roles()->attach($roleAdmin->id_role);
|
||||||
|
}
|
||||||
|
|
||||||
'id_divisi' => $divIT->id_divisi,
|
$pegawai = User::updateOrCreate(
|
||||||
'id_jabatan' => $jabMgr->id_jabatan,
|
['email' => 'budi@mpg.co.id'],
|
||||||
'id_kantor' => $kPusat->id_kantor,
|
[
|
||||||
'tgl_bergabung' => now(),
|
'nama_lengkap' => 'Budi Santoso',
|
||||||
]);
|
'password' => Hash::make('Mpg123!'),
|
||||||
|
'nik' => '350712345678',
|
||||||
User::create([
|
'status_aktif' => 1,
|
||||||
'nama_lengkap' => 'Budi Santoso',
|
'id_divisi' => $divHR->id_divisi,
|
||||||
'email' => 'budi@mpg.co.id',
|
'id_jabatan' => $jabStf->id_jabatan,
|
||||||
'password' => Hash::make('Mpg123!'),
|
'id_kantor' => $kCabang->id_kantor,
|
||||||
'role' => 'pegawai',
|
'tgl_bergabung' => now(),
|
||||||
'nik' => '350712345678',
|
]
|
||||||
'status_aktif' => 1,
|
);
|
||||||
'id_divisi' => $divHR->id_divisi,
|
if (!$pegawai->roles()->where('nama_role', 'pegawai')->exists()) {
|
||||||
'id_jabatan' => $jabStf->id_jabatan,
|
$pegawai->roles()->attach($rolePegawai->id_role);
|
||||||
'id_kantor' => $kCabang->id_kantor,
|
}
|
||||||
'tgl_bergabung' => now(),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,8 @@ public function run(): void
|
||||||
|
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
try {
|
try {
|
||||||
|
$idJenis = DB::table('jenis_izin')->inRandomOrder()->first()->id_jenis_izin;
|
||||||
$idJenis = rand(1, 3);
|
$idStatus = DB::table('status_pengajuan')->inRandomOrder()->first()->id_status;
|
||||||
|
|
||||||
$idStatus = rand(1, 3);
|
|
||||||
|
|
||||||
$tglMulai = now()->addDays(rand(-10, 10));
|
$tglMulai = now()->addDays(rand(-10, 10));
|
||||||
$tglSelesai = (clone $tglMulai)->addDays(rand(1, 3));
|
$tglSelesai = (clone $tglMulai)->addDays(rand(1, 3));
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,15 @@ public function run(): void
|
||||||
$randomMinutes = rand(-10, 30);
|
$randomMinutes = rand(-10, 30);
|
||||||
$jamMasuk = $shiftStart->copy()->addMinutes($randomMinutes);
|
$jamMasuk = $shiftStart->copy()->addMinutes($randomMinutes);
|
||||||
|
|
||||||
$status = 1;
|
$idTepat = DB::table('status_presensi')->where('nama_status', 'Tepat Waktu')->value('id_status') ?? 1;
|
||||||
|
$idTelat = DB::table('status_presensi')->where('nama_status', 'Terlambat')->value('id_status') ?? 2;
|
||||||
|
|
||||||
|
$status = $idTepat;
|
||||||
$alasan = null;
|
$alasan = null;
|
||||||
$toleransi = 10;
|
$toleransi = 10;
|
||||||
|
|
||||||
if ($randomMinutes > $toleransi) {
|
if ($randomMinutes > $toleransi) {
|
||||||
$status = 2;
|
$status = $idTelat;
|
||||||
$alasan = 'Terlambat ' . ($randomMinutes) . ' menit (Dummy Data)';
|
$alasan = 'Terlambat ' . ($randomMinutes) . ' menit (Dummy Data)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,20 @@ class PresensiStatusSeeder extends Seeder
|
||||||
|
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
|
$statuses = [
|
||||||
|
'Tepat Waktu',
|
||||||
|
'Terlambat',
|
||||||
|
'Izin',
|
||||||
|
'Sakit',
|
||||||
|
'Alpha',
|
||||||
|
];
|
||||||
|
|
||||||
DB::table('status_presensi')->insertOrIgnore([
|
foreach ($statuses as $status) {
|
||||||
['id_status' => 1, 'nama_status' => 'Tepat Waktu', 'created_at' => now(), 'updated_at' => now()],
|
DB::table('status_presensi')->updateOrInsert(
|
||||||
['id_status' => 2, 'nama_status' => 'Terlambat', 'created_at' => now(), 'updated_at' => now()],
|
['nama_status' => $status],
|
||||||
['id_status' => 3, 'nama_status' => 'Izin', 'created_at' => now(), 'updated_at' => now()],
|
['created_at' => now(), 'updated_at' => now()]
|
||||||
['id_status' => 4, 'nama_status' => 'Sakit', 'created_at' => now(), 'updated_at' => now()],
|
);
|
||||||
['id_status' => 5, 'nama_status' => 'Alpha', 'created_at' => now(), 'updated_at' => now()],
|
}
|
||||||
]);
|
|
||||||
|
|
||||||
$this->command->info('Tabel status_presensi berhasil diisi!');
|
$this->command->info('Tabel status_presensi berhasil diisi!');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,12 @@ class StatusPengajuanSeeder extends Seeder
|
||||||
{
|
{
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
DB::table('status_pengajuan')->delete();
|
$statuses = ['Disetujui', 'Pending', 'Ditolak'];
|
||||||
|
foreach ($statuses as $status) {
|
||||||
DB::table('status_pengajuan')->insert([
|
DB::table('status_pengajuan')->updateOrInsert(
|
||||||
|
['nama_status' => $status],
|
||||||
['id_status' => 1, 'nama_status' => 'Disetujui'],
|
['updated_at' => now(), 'created_at' => now()]
|
||||||
['id_status' => 2, 'nama_status' => 'Pending'],
|
);
|
||||||
['id_status' => 3, 'nama_status' => 'Ditolak'],
|
}
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue