114 lines
4.1 KiB
PHP
114 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Domains\Staff\Services;
|
|
|
|
use App\Domains\Auth\Models\User;
|
|
use App\Domains\Authorization\Enums\RoleCode;
|
|
use App\Domains\Catalog\Models\Category;
|
|
use App\Domains\Tenant\Models\Tenant;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class StaffService
|
|
{
|
|
/** @return Collection<int, User> */
|
|
public function list(Tenant $tenant, ?string $search = null): Collection
|
|
{
|
|
return $this->staffQuery($tenant)
|
|
->with(['role', 'scanCategories' => fn ($query) => $query->orderBy('nombre')])
|
|
->when($search, function (Builder $query, string $search): void {
|
|
$query->where(function (Builder $query) use ($search): void {
|
|
$query->where('nombre_apellido', 'like', "%{$search}%")
|
|
->orWhere('dni', 'like', "%{$search}%")
|
|
->orWhere('email', 'like', "%{$search}%");
|
|
});
|
|
})
|
|
->orderBy('nombre_apellido')
|
|
->get();
|
|
}
|
|
|
|
/** @return Collection<int, Category> */
|
|
private function assignableCategories(Tenant $tenant): Collection
|
|
{
|
|
return Category::query()
|
|
->whereNull('categoria_id')
|
|
->where(function (Builder $query) use ($tenant): void {
|
|
$query->where('tenant_code', $tenant->codigo)
|
|
->orWhereHas('catalogItems', fn (Builder $items) => $items
|
|
->where('tenant_code', $tenant->codigo));
|
|
})
|
|
->orderBy('nombre')
|
|
->get();
|
|
}
|
|
|
|
/** @param array<string, mixed> $data */
|
|
public function create(Tenant $tenant, array $data): User
|
|
{
|
|
$this->assertCategoriesBelongToTenant($tenant, $data['category_ids']);
|
|
|
|
return DB::transaction(function () use ($tenant, $data): User {
|
|
$staff = User::query()->create([
|
|
...Arr::only($data, ['nombre_apellido', 'dni', 'email']),
|
|
'email' => mb_strtolower(trim((string) $data['email'])),
|
|
'password' => Str::random(64),
|
|
'rol_codigo' => RoleCode::Scanner->value,
|
|
'tenant_codigo' => $tenant->codigo,
|
|
]);
|
|
$staff->scanCategories()->sync($data['category_ids']);
|
|
|
|
return $staff->load('role', 'scanCategories');
|
|
});
|
|
}
|
|
|
|
/** @param array<string, mixed> $data */
|
|
public function update(Tenant $tenant, int $staffId, array $data): User
|
|
{
|
|
$staff = $this->find($tenant, $staffId);
|
|
$this->assertCategoriesBelongToTenant($tenant, $data['category_ids']);
|
|
|
|
return DB::transaction(function () use ($staff, $data): User {
|
|
$attributes = Arr::only($data, ['nombre_apellido', 'dni', 'email']);
|
|
$attributes['email'] = mb_strtolower(trim((string) $data['email']));
|
|
$staff->update($attributes);
|
|
$staff->scanCategories()->sync($data['category_ids']);
|
|
|
|
return $staff->load('role', 'scanCategories');
|
|
});
|
|
}
|
|
|
|
public function delete(Tenant $tenant, int $staffId): void
|
|
{
|
|
$this->find($tenant, $staffId)->delete();
|
|
}
|
|
|
|
public function find(Tenant $tenant, int $staffId): User
|
|
{
|
|
return $this->staffQuery($tenant)->findOrFail($staffId);
|
|
}
|
|
|
|
private function staffQuery(Tenant $tenant): Builder
|
|
{
|
|
return User::query()
|
|
->where('tenant_codigo', $tenant->codigo)
|
|
->where('rol_codigo', RoleCode::Scanner->value);
|
|
}
|
|
|
|
/** @param array<int, int> $categoryIds */
|
|
private function assertCategoriesBelongToTenant(Tenant $tenant, array $categoryIds): void
|
|
{
|
|
$validIds = $this->assignableCategories($tenant)
|
|
->whereIn('id', $categoryIds)
|
|
->pluck('id');
|
|
|
|
if ($validIds->count() !== count($categoryIds)) {
|
|
throw ValidationException::withMessages([
|
|
'category_ids' => 'Una o más categorías no pertenecen al tenant.',
|
|
]);
|
|
}
|
|
}
|
|
}
|