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.
This commit is contained in:
@@ -14,28 +14,25 @@ class ShiftForm
|
|||||||
{
|
{
|
||||||
return $schema
|
return $schema
|
||||||
->components([
|
->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')
|
TextInput::make('name')
|
||||||
->label(__('hr.fields.name'))
|
->label(__('hr.fields.name'))
|
||||||
->required()
|
->required()
|
||||||
->maxLength(255),
|
->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')
|
Textarea::make('description')
|
||||||
->label(__('hr.fields.description'))
|
->label(__('hr.fields.description'))
|
||||||
->rows(3)
|
->rows(3),
|
||||||
->columnSpanFull(),
|
|
||||||
Toggle::make('is_active')
|
Toggle::make('is_active')
|
||||||
->label(__('hr.fields.active'))
|
->label(__('hr.fields.active'))
|
||||||
->default(true)
|
->default(true)
|
||||||
->required(),
|
->required(),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class Shift extends Model
|
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
|
public function employees(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(Employee::class);
|
return $this->hasMany(Employee::class);
|
||||||
|
|||||||
@@ -27,14 +27,16 @@ class ShiftFactory extends Factory
|
|||||||
default => ['starts_at' => '22:00:00', 'ends_at' => '06:00:00'],
|
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 [
|
return [
|
||||||
'name' => match ($code) {
|
'name' => $name,
|
||||||
'A' => 'Morning Shift',
|
'code' => Shift::generateUniqueCodeFromName($name),
|
||||||
'B' => 'Afternoon Shift',
|
|
||||||
'C' => 'Evening Shift',
|
|
||||||
default => 'Night Shift',
|
|
||||||
},
|
|
||||||
'code' => $code.'-'.fake()->unique()->numerify('###'),
|
|
||||||
'starts_at' => $times['starts_at'],
|
'starts_at' => $times['starts_at'],
|
||||||
'ends_at' => $times['ends_at'],
|
'ends_at' => $times['ends_at'],
|
||||||
'description' => fake()->optional()->sentence(),
|
'description' => fake()->optional()->sentence(),
|
||||||
|
|||||||
44
tests/Feature/Models/ShiftTest.php
Normal file
44
tests/Feature/Models/ShiftTest.php
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use App\Models\Shift;
|
||||||
|
|
||||||
|
it('generates an uppercase slug code from name', function (): void {
|
||||||
|
expect(Shift::generateUniqueCodeFromName('Morning Shift'))
|
||||||
|
->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');
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user