Add employee, user, and user profile models with enums for status and gender

This commit is contained in:
Yoga Pangestu 2026-06-09 19:16:25 +07:00
parent 632296c453
commit ff1ec1ef66
14 changed files with 289 additions and 27 deletions

View File

@ -0,0 +1,10 @@
<?php
namespace App\Enums;
enum EmployeeStatus: string
{
case ACTIVE = 'active';
case INACTIVE = 'inactive';
case RESIGNED = 'resigned';
}

View File

@ -0,0 +1,11 @@
<?php
namespace App\Enums;
enum EmploymentStatus: string
{
case FULL_TIME = 'full_time';
case PART_TIME = 'part_time';
case CONTRACT = 'contract';
case TEMPORARY = 'temporary';
}

9
app/Enums/Gender.php Normal file
View File

@ -0,0 +1,9 @@
<?php
namespace App\Enums;
enum Gender: string
{
case MALE = 'male';
case FEMALE = 'female';
}

85
app/Models/Employee.php Normal file
View File

@ -0,0 +1,85 @@
<?php
namespace App\Models;
use App\Enums\EmployeeStatus;
use App\Enums\EmploymentStatus;
use Illuminate\Database\Eloquent\Attributes\Appends;
use Illuminate\Database\Eloquent\Attributes\Guarded;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
#[Guarded(['id'])]
#[Appends(['base_salary_formatted'])]
class Employee extends Model
{
use SoftDeletes;
protected function casts(): array
{
return [
'join_date' => 'date',
'resign_date' => 'date',
'employment_status' => EmploymentStatus::class,
'employee_status' => EmployeeStatus::class,
'base_salary' => 'integer',
];
}
#[Scope]
public function active(Builder $query): void
{
$query->where('employee_status', EmployeeStatus::ACTIVE->value);
}
#[Scope]
public function inactive(Builder $query): void
{
$query->where('employee_status', EmployeeStatus::INACTIVE->value);
}
#[Scope]
public function resigned(Builder $query): void
{
$query->where('employee_status', EmployeeStatus::RESIGNED->value);
}
public function fullTime(Builder $query): void
{
$query->where('employment_status', EmploymentStatus::FULL_TIME->value);
}
#[Scope]
public function partTime(Builder $query): void
{
$query->where('employee_status', EmploymentStatus::PART_TIME->value);
}
#[Scope]
public function contract(Builder $query): void
{
$query->where('employee_status', EmploymentStatus::CONTRACT->value);
}
#[Scope]
public function temporary(Builder $query): void
{
$query->where('employee_status', EmploymentStatus::TEMPORARY->value);
}
public function baseSalaryFormatted(): Attribute
{
return Attribute::make(
get: fn (int $value) => number_format($value, 0, ',', '.'),
);
}
public function profile(): BelongsTo
{
return $this->belongsTo(UserProfile::class);
}
}

View File

@ -2,31 +2,31 @@
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Guarded;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
#[Fillable(['name', 'email', 'password'])]
#[Guarded(['id'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable
{
/** @use HasFactory<UserFactory> */
use HasFactory, Notifiable;
use HasFactory, Notifiable, SoftDeletes;
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'is_active' => 'boolean',
'last_login_at' => 'datetime',
'password' => 'hashed',
];
}
public function profile(): HasOne
{
return $this->hasOne(UserProfile::class);
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Models;
use App\Enums\Gender;
use Illuminate\Database\Eloquent\Attributes\Guarded;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
#[Guarded(['id'])]
class UserProfile extends Model
{
use SoftDeletes;
protected function casts(): array
{
return [
'gender' => Gender::class,
'birth_date' => 'date',
];
}
public function employee(): HasOne
{
return $this->hasOne(Employee::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}

View File

@ -114,4 +114,5 @@
'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),
'password_default' => env('PASSWORD_DEFAULT', 'Minimal8@'),
];

View File

@ -12,13 +12,17 @@
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->rememberToken();
$table->timestamps();
$table->unsignedBigInteger('id', true);
$table->string('email', 100)->unique();
$table->string('username', 20)->unique();
$table->string('password', 255);
$table->boolean('is_active')->default(true);
$table->timestamp('last_login_at')->nullable();
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
$table->softDeletes();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {

View File

@ -0,0 +1,39 @@
<?php
use App\Enums\Gender;
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('user_profiles', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete()->unique();
$table->string('full_name', 200);
$table->string('phone_number', 20)->nullable();
$table->enum('gender', array_column(Gender::cases(), 'value'))->nullable();
$table->date('birth_date')->nullable();
$table->text('address')->nullable();
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('user_profiles');
}
};

View File

@ -0,0 +1,41 @@
<?php
use App\Enums\EmployeeStatus;
use App\Enums\EmploymentStatus;
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('employees', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete()->unique();
$table->string('employee_code', 20)->unique();
$table->date('join_date');
$table->date('resign_date')->nullable();
$table->enum('employment_status', array_column(EmploymentStatus::cases(), 'value'))->default(EmploymentStatus::FULL_TIME->value);
$table->enum('employee_status', array_column(EmployeeStatus::cases(), 'value'))->default(EmployeeStatus::ACTIVE->value);
$table->unsignedInteger('base_salary');
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('employees');
}
};

View File

@ -2,7 +2,6 @@
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
@ -15,11 +14,8 @@ class DatabaseSeeder extends Seeder
*/
public function run(): void
{
// User::factory(10)->create();
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
$this->call([
UserSeeder::class,
]);
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Database\Seeders;
use App\Enums\Gender;
use App\Models\User;
use App\Models\UserProfile;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
class UserSeeder extends Seeder
{
public function run(): void
{
DB::transaction(function () {
$developer = User::create([
'email' => 'project.pangestuyoga@gmail.com',
'username' => 'pangestu',
'password' => Hash::make(config('auth.password_default')),
]);
UserProfile::create([
'user_id' => $developer->id,
'full_name' => 'Yoga Pangestu',
'phone_number' => '082121495806',
'gender' => Gender::MALE->value,
]);
});
}
}

View File

@ -4,4 +4,4 @@
$response = $this->get(route('home'));
$response->assertOk();
});
});

View File

@ -2,4 +2,4 @@
test('that true is true', function () {
expect(true)->toBeTrue();
});
});