New_Micro_Learning/backend/app/Modules/Teams/Http/TeamController.php

183 خطوط
7.4 KiB
PHP

<?php
namespace App\Modules\Teams\Http;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Modules\Assignments\Application\AssignmentResolver;
use App\Modules\Identity\Application\RolePermissions;
use App\Modules\Identity\Domain\Enums\Permission;
use App\Modules\Identity\Domain\Enums\UserRole;
use App\Modules\Teams\Domain\Team;
use App\Modules\Teams\Http\Requests\AttachTeamUserRequest;
use App\Modules\Teams\Http\Requests\StoreTeamRequest;
use App\Modules\Teams\Http\Requests\UpdateTeamRequest;
use App\Modules\Tenancy\Application\TenantContext;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
final class TeamController extends Controller
{
public function __construct(private readonly TenantContext $tenant, private readonly RolePermissions $permissions, private readonly AssignmentResolver $assignmentResolver) {}
public function index(Request $request): JsonResponse
{
abort_unless($this->permissions->allows($request->user(), Permission::TeamsView), 403);
$query = Team::query()->where('organization_id', $this->tenant->id());
if ($request->user()->role === UserRole::Manager) {
$query->whereHas('managers', fn ($manager) => $manager->whereKey($request->user()->getKey()));
}
$teams = $query->withCount(['members', 'managers'])->orderBy('name')->get()->map(fn (Team $team) => $this->payload($team));
return response()->json(['data' => $teams]);
}
public function store(StoreTeamRequest $request): JsonResponse
{
$this->authorizeDesigner($request);
$team = DB::transaction(function () use ($request): Team {
$team = Team::query()->create([
'organization_id' => $this->tenant->id(),
'name' => $request->validated('name'),
'description' => $request->validated('description'),
'status' => 'active',
'created_by' => $request->user()->getKey(),
]);
if ($request->filled('managerId')) {
$this->attachManagerAndReports($team, $this->manager($request->validated('managerId')));
}
return $team->loadCount(['members', 'managers']);
});
return response()->json(['data' => $this->payload($team)], 201);
}
public function show(Request $request, string $team): JsonResponse
{
abort_unless($this->permissions->allows($request->user(), Permission::TeamsView), 403);
$query = Team::query()->where('organization_id', $this->tenant->id());
if ($request->user()->role === UserRole::Manager) {
$query->whereHas('managers', fn ($manager) => $manager->whereKey($request->user()->getKey()));
}
$model = $query
->withCount(['members', 'managers'])
->with(['members:id,name,email,role,status,department,job_level,direct_manager_id', 'managers:id,name,email,role,status,department,job_level,direct_manager_id'])
->findOrFail($team);
return response()->json(['data' => array_merge($this->payload($model), [
'members' => $model->members->map(fn (User $user) => $this->userPayload($user)),
'managers' => $model->managers->map(fn (User $user) => $this->userPayload($user)),
])]);
}
public function update(UpdateTeamRequest $request, string $team): JsonResponse
{
$this->authorizeDesigner($request);
$model = Team::query()->where('organization_id', $this->tenant->id())->findOrFail($team);
$model->update($request->safe()->only(['name', 'description']));
return response()->json(['data' => $this->payload($model)]);
}
public function attachMember(AttachTeamUserRequest $request, string $team): JsonResponse
{
$this->authorizeDesigner($request);
[$targetTeam, $user] = $this->resolveTeamAndUser($team, $request->validated('userId'));
$targetTeam->members()->syncWithoutDetaching([$user->getKey()]);
$this->assignmentResolver->syncOrganization($this->tenant->id());
return response()->json(['data' => ['attached' => true]]);
}
public function attachManager(AttachTeamUserRequest $request, string $team): JsonResponse
{
$this->authorizeDesigner($request);
$targetTeam = Team::query()->where('organization_id', $this->tenant->id())->findOrFail($team);
$this->attachManagerAndReports($targetTeam, $this->manager($request->validated('userId')));
$this->assignmentResolver->syncOrganization($this->tenant->id());
return response()->json(['data' => ['attached' => true]]);
}
public function detachMember(Request $request, string $team, string $user): JsonResponse
{
$this->authorizeDesigner($request);
[$targetTeam, $targetUser] = $this->resolveTeamAndUser($team, $user);
$targetTeam->members()->detach($targetUser);
return response()->json(['data' => ['detached' => true]]);
}
public function detachManager(Request $request, string $team, string $user): JsonResponse
{
$this->authorizeDesigner($request);
[$targetTeam, $targetUser] = $this->resolveTeamAndUser($team, $user);
$targetTeam->managers()->detach($targetUser);
return response()->json(['data' => ['detached' => true]]);
}
private function authorizeDesigner(Request $request): void
{
abort_unless($this->permissions->allows($request->user(), Permission::TeamsManage), 403);
}
private function resolveTeamAndUser(string $team, string $user): array
{
$targetTeam = Team::query()->where('organization_id', $this->tenant->id())->findOrFail($team);
$targetUser = User::query()->where('organization_id', $this->tenant->id())->findOrFail($user);
return [$targetTeam, $targetUser];
}
private function manager(string $user): User
{
$manager = User::query()->where('organization_id', $this->tenant->id())->findOrFail($user);
if ($manager->role !== UserRole::Manager) {
throw ValidationException::withMessages(['userId' => ['Only a Manager may manage a team.']]);
}
return $manager;
}
private function attachManagerAndReports(Team $team, User $manager): void
{
$team->managers()->syncWithoutDetaching([$manager->getKey()]);
$reports = User::query()
->where('organization_id', $this->tenant->id())
->where('direct_manager_id', $manager->getKey())
->where('status', 'active')
->pluck('id')
->all();
$team->members()->syncWithoutDetaching($reports);
}
private function payload(Team $team): array
{
return [
'id' => $team->getKey(), 'name' => $team->name, 'description' => $team->description,
'status' => $team->status, 'memberCount' => $team->members_count ?? 0,
'managerCount' => $team->managers_count ?? 0,
];
}
private function userPayload(User $user): array
{
return [
'id' => $user->getKey(),
'name' => $user->name,
'email' => $user->email,
'role' => $user->role->value,
'status' => $user->status->value,
'department' => $user->department,
'jobLevel' => $user->job_level,
'directManagerId' => $user->direct_manager_id,
];
}
}