From 28cbef8eb57733533378c9c05a772a2ca53ae183 Mon Sep 17 00:00:00 2001 From: Mekan1206 Date: Sun, 2 Aug 2026 20:17:16 +0500 Subject: [PATCH] Refactor ShiftForm to streamline field definitions and implement unique code generation for shifts based on their names. Update ShiftFactory to utilize the new code generation method. --- .../Resources/Shifts/Schemas/ShiftForm.php | 29 ++++++------ app/Models/Shift.php | 33 ++++++++++++++ database/factories/ShiftFactory.php | 16 ++++--- tests/Feature/Models/ShiftTest.php | 44 +++++++++++++++++++ 4 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 tests/Feature/Models/ShiftTest.php diff --git a/app/Filament/Resources/Shifts/Schemas/ShiftForm.php b/app/Filament/Resources/Shifts/Schemas/ShiftForm.php index 900963b..51c2c35 100644 --- a/app/Filament/Resources/Shifts/Schemas/ShiftForm.php +++ b/app/Filament/Resources/Shifts/Schemas/ShiftForm.php @@ -14,28 +14,25 @@ class ShiftForm { return $schema ->components([ + TimePicker::make('starts_at') + ->label(__('hr.fields.starts_at')) + ->required() + ->seconds(false), + TimePicker::make('ends_at') + ->label(__('hr.fields.ends_at')) + ->required() + ->seconds(false), + TextInput::make('name') ->label(__('hr.fields.name')) ->required() ->maxLength(255), - TextInput::make('code') - ->label(__('hr.fields.code')) - ->required() - ->maxLength(50) - ->unique(ignoreRecord: true), - TimePicker::make('starts_at') - ->label(__('hr.fields.starts_at')) - ->required() - ->seconds(false), - TimePicker::make('ends_at') - ->label(__('hr.fields.ends_at')) - ->required() - ->seconds(false), + Textarea::make('description') ->label(__('hr.fields.description')) - ->rows(3) - ->columnSpanFull(), - Toggle::make('is_active') + ->rows(3), + + Toggle::make('is_active') ->label(__('hr.fields.active')) ->default(true) ->required(), diff --git a/app/Models/Shift.php b/app/Models/Shift.php index 28e89cf..22e5bbb 100644 --- a/app/Models/Shift.php +++ b/app/Models/Shift.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Support\Str; class Shift extends Model { @@ -34,6 +35,38 @@ class Shift extends Model ]; } + protected static function booted(): void + { + static::saving(function (Shift $shift): void { + if (blank($shift->code) && filled($shift->name)) { + $shift->code = static::generateUniqueCodeFromName( + $shift->name, + $shift->id, + ); + } + }); + } + + public static function generateUniqueCodeFromName(string $name, ?int $ignoreId = null): string + { + $base = Str::upper(Str::slug($name)); + + $query = static::query() + ->when($ignoreId, fn ($query) => $query->where('id', '!=', $ignoreId)); + + if (! $query->clone()->where('code', $base)->exists()) { + return $base; + } + + $maxSuffix = $query->clone() + ->where('code', 'like', "{$base}-%") + ->pluck('code') + ->map(fn (string $code): int => (int) Str::after($code, "{$base}-")) + ->max(); + + return "{$base}-".(($maxSuffix ?? 0) + 1); + } + public function employees(): HasMany { return $this->hasMany(Employee::class); diff --git a/database/factories/ShiftFactory.php b/database/factories/ShiftFactory.php index 11ee48a..e009a96 100644 --- a/database/factories/ShiftFactory.php +++ b/database/factories/ShiftFactory.php @@ -27,14 +27,16 @@ class ShiftFactory extends Factory default => ['starts_at' => '22:00:00', 'ends_at' => '06:00:00'], }; + $name = match ($code) { + 'A' => 'Morning Shift', + 'B' => 'Afternoon Shift', + 'C' => 'Evening Shift', + default => 'Night Shift', + }; + return [ - 'name' => match ($code) { - 'A' => 'Morning Shift', - 'B' => 'Afternoon Shift', - 'C' => 'Evening Shift', - default => 'Night Shift', - }, - 'code' => $code.'-'.fake()->unique()->numerify('###'), + 'name' => $name, + 'code' => Shift::generateUniqueCodeFromName($name), 'starts_at' => $times['starts_at'], 'ends_at' => $times['ends_at'], 'description' => fake()->optional()->sentence(), diff --git a/tests/Feature/Models/ShiftTest.php b/tests/Feature/Models/ShiftTest.php new file mode 100644 index 0000000..126efd1 --- /dev/null +++ b/tests/Feature/Models/ShiftTest.php @@ -0,0 +1,44 @@ +toBe('MORNING-SHIFT'); +}); + +it('generates code on save when code is blank', function (): void { + $shift = Shift::factory()->create([ + 'name' => 'Morning Shift', + 'code' => '', + ]); + + expect($shift->code)->toBe('MORNING-SHIFT'); +}); + +it('does not overwrite an existing code on update', function (): void { + $shift = Shift::factory()->create([ + 'name' => 'Morning Shift', + 'code' => 'MS', + ]); + + $shift->update(['name' => 'Early Shift']); + + expect($shift->fresh()->code)->toBe('MS'); +}); + +it('appends a suffix when the generated code already exists', function (): void { + Shift::factory()->create([ + 'name' => 'Morning Team', + 'code' => 'MORNING', + ]); + + $shift = Shift::factory()->create([ + 'name' => 'Morning', + 'code' => '', + ]); + + expect($shift->code)->toBe('MORNING-1'); +});