countAutomaticGrants(); $userIds = DB::table('company_user') ->whereIn('granted_via', ['auto', 'auto-upgrade']) ->when($this->option('user'), fn ($query, $userId) => $query->where('user_id', (int) $userId)) ->distinct() ->pluck('user_id'); if ($userIds->isEmpty()) { $this->info('Keine automatisch vergebenen Firmenrechte gefunden — nichts zu tun.'); return self::SUCCESS; } DB::beginTransaction(); try { $bar = $this->output->createProgressBar($userIds->count()); foreach ($userIds->chunk(200) as $chunk) { User::query()->whereIn('id', $chunk->all())->get()->each(function (User $user) use ($contactAccess, $bar): void { $contactAccess->syncMembershipsForEmail($user); $bar->advance(); }); } $bar->finish(); $this->newLine(); $after = $this->countAutomaticGrants(); $revoked = max(0, $before - $after); $summary = "Abgeglichen: {$userIds->count()} User. Automatische Rechte vorher {$before}, nachher {$after}."; if ($this->option('dry-run')) { DB::rollBack(); $this->info($summary.' Probelauf — nichts gespeichert.'); return self::SUCCESS; } $limit = max(self::MAX_REVOKE_ABSOLUTE, (int) ceil($before * self::MAX_REVOKE_SHARE)); if ($revoked > $limit && ! $this->option('force')) { DB::rollBack(); $this->error($summary." Es würden {$revoked} Rechte wegfallen (Grenze {$limit}) — zurückgerollt. Ursache prüfen, nur bei Absicht mit --force wiederholen."); return self::FAILURE; } DB::commit(); $this->info($summary); return self::SUCCESS; } catch (\Throwable $e) { DB::rollBack(); throw $e; } } private function countAutomaticGrants(): int { return DB::table('company_user') ->where('role', 'responsible') ->whereIn('granted_via', ['auto', 'auto-upgrade']) ->count(); } }