withCount(['events', 'users']); if ($search = request('search')) { $query->where(function ($q) use ($search) { $q->where('name', 'like', "%{$search}%") ->orWhere('slug', 'like', "%{$search}%"); }); } if ($billingStatus = request('billing_status')) { $query->where('billing_status', $billingStatus); } $sortBy = request('sort', 'name'); $sortDirection = request('direction', 'asc'); $query->orderBy( in_array($sortBy, ['name', 'created_at']) ? $sortBy : 'name', $sortDirection === 'desc' ? 'desc' : 'asc', ); return AdminOrganisationResource::collection($query->paginate()); } public function show(string $organisationId): JsonResponse { $organisation = Organisation::withoutGlobalScopes() ->withCount(['events', 'users']) ->findOrFail($organisationId); $organisation->total_persons = Person::withoutGlobalScopes() ->whereIn('event_id', $organisation->events()->select('id')) ->count(); $members = $organisation->users()->orderBy('first_name')->get(); return $this->success([ 'organisation' => new AdminOrganisationResource($organisation), 'members' => MemberResource::collection($members), ]); } public function store(): void { // Organisations are created via the regular endpoint abort(405); } public function update(AdminUpdateOrganisationRequest $request, string $organisationId): JsonResponse { $organisation = Organisation::withoutGlobalScopes()->findOrFail($organisationId); $organisation->update($request->validated()); activity('admin') ->causedBy(auth()->user()) ->performedOn($organisation) ->event('admin.organisation.updated') ->withProperties($request->validated()) ->log('Updated organisation ' . $organisation->name); $organisation->loadCount(['events', 'users']); return $this->success(new AdminOrganisationResource($organisation)); } public function destroy(string $organisationId): JsonResponse { $organisation = Organisation::withoutGlobalScopes()->findOrFail($organisationId); activity('admin') ->causedBy(auth()->user()) ->performedOn($organisation) ->event('admin.organisation.deleted') ->log('Deleted organisation ' . $organisation->name); $organisation->delete(); return response()->json(null, 204); } public function invite(AdminInviteMemberRequest $request, string $organisationId): JsonResponse { $organisation = Organisation::withoutGlobalScopes()->findOrFail($organisationId); $email = $request->validated('email'); $role = $request->validated('role'); // Check if already a member $existingMember = $organisation->users()->where('email', $email)->first(); if ($existingMember) { return $this->error('Gebruiker is al lid van deze organisatie.', 422); } // If user with this email already exists, add directly $existingUser = User::where('email', $email)->first(); if ($existingUser) { $organisation->users()->attach($existingUser, ['role' => $role]); activity('admin') ->causedBy(auth()->user()) ->performedOn($organisation) ->event('admin.organisation.member_invited') ->withProperties(['email' => $email, 'role' => $role, 'direct' => true]) ->log("Added existing user {$email} as {$role}"); return $this->success( new MemberResource($organisation->users()->where('user_id', $existingUser->id)->first()), 'Gebruiker direct toegevoegd als lid.', ); } // Create invitation for unknown email $invitation = new UserInvitation(['email' => $email]); $invitation->invited_by_user_id = auth()->id(); $invitation->organisation_id = $organisation->id; $invitation->role = $role; $invitation->token = hash('sha256', bin2hex(random_bytes(32))); $invitation->status = 'pending'; $invitation->expires_at = now()->addDays(7); $invitation->save(); activity('admin') ->causedBy(auth()->user()) ->performedOn($organisation) ->event('admin.organisation.member_invited') ->withProperties(['email' => $email, 'role' => $role, 'direct' => false]) ->log("Invited {$email} as {$role}"); return $this->created(null, 'Uitnodiging aangemaakt.'); } public function removeMember(string $organisationId, User $user): JsonResponse { $organisation = Organisation::withoutGlobalScopes()->findOrFail($organisationId); if (auth()->id() === $user->id) { return $this->error('Je kunt jezelf niet verwijderen.', 422); } if (!$organisation->users()->where('user_id', $user->id)->exists()) { return $this->notFound('Gebruiker is geen lid van deze organisatie.'); } $organisation->users()->detach($user->id); activity('admin') ->causedBy(auth()->user()) ->performedOn($organisation) ->event('admin.organisation.member_removed') ->withProperties(['user_id' => $user->id, 'email' => $user->email]) ->log("Removed {$user->email} from organisation"); return response()->json(null, 204); } public function updateMemberRole(AdminUpdateMemberRoleRequest $request, string $organisationId, User $user): JsonResponse { $organisation = Organisation::withoutGlobalScopes()->findOrFail($organisationId); if (!$organisation->users()->where('user_id', $user->id)->exists()) { return $this->notFound('Gebruiker is geen lid van deze organisatie.'); } $organisation->users()->updateExistingPivot($user->id, [ 'role' => $request->validated('role'), ]); activity('admin') ->causedBy(auth()->user()) ->performedOn($organisation) ->event('admin.organisation.member_role_updated') ->withProperties(['user_id' => $user->id, 'role' => $request->validated('role')]) ->log("Updated role of {$user->email} to {$request->validated('role')}"); return $this->success( new MemberResource($organisation->users()->where('user_id', $user->id)->first()), ); } }