*/ public static function legacyCodeCandidates(?Stabile $stabile): array { if (! $stabile instanceof Stabile) { return []; } $rawCandidates = [ trim((string) ($stabile->codice_stabile ?? '')), trim((string) ($stabile->old_id ?? '')), trim((string) ($stabile->cod_stabile ?? '')), ]; $candidates = []; foreach ($rawCandidates as $candidate) { if ($candidate === '') { continue; } $candidates[] = $candidate; $noZero = ltrim($candidate, '0'); if ($noZero !== '' && $noZero !== $candidate) { $candidates[] = $noZero; } } return array_values(array_unique($candidates)); } public static function preferredLegacyCode(?Stabile $stabile): ?string { $candidates = self::legacyCodeCandidates($stabile); return $candidates[0] ?? null; } public static function setFromStabile(Stabile $stabile, ?User $user = null): bool { $user = $user ?? Auth::user(); if ($user instanceof User) { return self::setActiveStabileId($user, (int) $stabile->id); } session([self::SESSION_KEY => (int) $stabile->id]); return true; } public static function resolveActiveStabileId(User $user): ?int { $allowed = self::accessibleStabili($user)->pluck('id')->map(fn($v) => (int) $v)->values(); if ($allowed->isEmpty()) { session()->forget(self::SESSION_KEY); return null; } $sessionId = session(self::SESSION_KEY); if (is_numeric($sessionId)) { $sessionId = (int) $sessionId; if ($allowed->contains($sessionId)) { return $sessionId; } } // Persistenza: prova a ripristinare l'ultimo stabile usato dall'utente. $persistedId = self::getPersistedStabileId($user); if ($persistedId && $allowed->contains($persistedId)) { session([self::SESSION_KEY => $persistedId]); return $persistedId; } $preferredSupplierStabileId = self::resolvePreferredSupplierStabileId($user, $allowed->all()); if ($preferredSupplierStabileId && $allowed->contains($preferredSupplierStabileId)) { session([self::SESSION_KEY => $preferredSupplierStabileId]); return $preferredSupplierStabileId; } $default = (int) config('netgescon.defaults.default_stabile_id', 0); if ($default > 0 && $allowed->contains($default)) { session([self::SESSION_KEY => $default]); return $default; } $first = (int) $allowed->first(); session([self::SESSION_KEY => $first]); return $first; } private static function getPersistedStabileId(User $user): ?int { if (! Schema::hasColumn('users', 'last_stabile_id')) { return null; } $candidate = $user->getAttribute('last_stabile_id'); if (! is_numeric($candidate)) { $candidate = DB::table('users')->where('id', (int) $user->id)->value('last_stabile_id'); } return is_numeric($candidate) ? (int) $candidate : null; } /** * @return Collection */ public static function accessibleStabili(User $user): Collection { // Super-admin / admin: tutto if ($user->hasAnyRole(['super-admin', 'admin'])) { return Stabile::query()->attivi()->orderBy('codice_stabile')->get(); } $hasCollaboratorePivot = Schema::hasTable('collaboratore_stabile'); // Amministratore: per amministratore_id if ($user->hasRole('amministratore') && $user->amministratore) { $owned = Stabile::query() ->attivi() ->byAmministratore($user->amministratore->id) ->get(); // Supporta anche assegnazioni esplicite (stesso pivot dei collaboratori). $assigned = $hasCollaboratorePivot ? $user->stabiliAssegnati()->where('stabili.attivo', true)->get() : collect(); return $owned ->merge($assigned) ->unique('id') ->sortBy(fn(Stabile $s) => (string) $s->codice_stabile) ->values(); } // Collaboratore: via pivot if ($user->hasRole('collaboratore')) { if (! $hasCollaboratorePivot) { return collect(); } return $user->stabiliAssegnati()->where('attivo', true)->orderBy('codice_stabile')->get(); } if ($user->hasRole('fornitore')) { $supplier = self::resolveSupplierForUser($user); if (! $supplier instanceof Fornitore) { return collect(); } $stableIds = self::resolveSupplierAccessibleStableIds($user, $supplier); if ($stableIds === []) { return collect(); } return Stabile::query() ->attivi() ->whereIn('id', $stableIds) ->orderBy('codice_stabile') ->get(); } // Condomino / fornitore: per ora nessun accesso “stabili gestiti” return collect(); } /** * @return array */ private static function resolveSupplierAccessibleStableIds(User $user, Fornitore $supplier): array { $explicitStableIds = []; try { $explicitStableIds = array_merge($explicitStableIds, $user->stabiliAssegnati() ->pluck('stabili.id') ->map(fn($value): int => (int) $value) ->all()); } catch (\Throwable) { // ignore collaborator-style explicit assignments for supplier users } if (Schema::hasTable('fornitore_stabile_impostazioni')) { $explicitStableIds = array_merge($explicitStableIds, DB::table('fornitore_stabile_impostazioni') ->where('fornitore_id', (int) $supplier->id) ->pluck('stabile_id') ->map(fn($value): int => (int) $value) ->all()); } $explicitStableIds = self::normalizeStableIds($explicitStableIds); if ($explicitStableIds !== []) { return $explicitStableIds; } $taxCodeMatchedIds = self::resolveSupplierStableIdsFromTaxCodes($supplier); if ($taxCodeMatchedIds !== []) { return $taxCodeMatchedIds; } $historicalStableIds = []; foreach (['fatture_elettroniche', 'contabilita_fatture_fornitori'] as $table) { if (! Schema::hasTable($table)) { continue; } $historicalStableIds = array_merge($historicalStableIds, DB::table($table) ->where('fornitore_id', (int) $supplier->id) ->whereNotNull('stabile_id') ->pluck('stabile_id') ->map(fn($value): int => (int) $value) ->all()); } return self::normalizeStableIds($historicalStableIds); } /** * @return array */ private static function resolveSupplierStableIdsFromTaxCodes(Fornitore $supplier): array { $taxCodes = collect([ trim((string) ($supplier->partita_iva ?? '')), trim((string) ($supplier->codice_fiscale ?? '')), ])->filter()->unique()->values()->all(); if ($taxCodes === []) { return []; } return self::normalizeStableIds(Stabile::query() ->attivi() ->where(function ($query) use ($taxCodes): void { $query->whereIn('codice_fiscale', $taxCodes) ->orWhereIn('cod_fisc_amministratore', $taxCodes); }) ->pluck('id') ->map(fn($value): int => (int) $value) ->all()); } /** * @param array $stableIds * @return array */ private static function normalizeStableIds(array $stableIds): array { return array_values(array_unique(array_filter( array_map(static fn($value): int => (int) $value, $stableIds), static fn(int $value): bool => $value > 0 ))); } private static function resolvePreferredSupplierStabileId(User $user, array $allowedIds): ?int { if (! $user->hasRole('fornitore') || $allowedIds === []) { return null; } $supplier = self::resolveSupplierForUser($user); if (! $supplier instanceof Fornitore) { return null; } $taxCodes = collect([ trim((string) ($supplier->partita_iva ?? '')), trim((string) ($supplier->codice_fiscale ?? '')), ])->filter()->unique()->values()->all(); if ($taxCodes === []) { return null; } return Stabile::query() ->attivi() ->whereIn('id', array_values(array_unique(array_map('intval', $allowedIds)))) ->where(function ($query) use ($taxCodes): void { $query->whereIn('codice_fiscale', $taxCodes) ->orWhereIn('cod_fisc_amministratore', $taxCodes); }) ->orderBy('codice_stabile') ->value('id'); } private static function resolveSupplierForUser(User $user): ?Fornitore { $email = mb_strtolower(trim((string) $user->email)); if ($email !== '') { $supplier = Fornitore::query() ->whereRaw('LOWER(email) = ?', [$email]) ->orderByDesc('id') ->first(); if ($supplier instanceof Fornitore) { return $supplier; } } $dipendente = FornitoreDipendente::query() ->where('attivo', true) ->where(function ($query) use ($user, $email): void { $query->where('user_id', (int) $user->id); if ($email !== '') { $query->orWhereRaw('LOWER(email) = ?', [$email]); } }) ->orderByDesc('id') ->first(); if (! $dipendente instanceof FornitoreDipendente) { return null; } return Fornitore::query()->find((int) $dipendente->fornitore_id); } public static function getActiveStabileId(?User $user = null): ?int { if ($user) { return self::resolveActiveStabileId($user); } $sessionId = session(self::SESSION_KEY); if (is_numeric($sessionId)) { return (int) $sessionId; } $default = (int) config('netgescon.defaults.default_stabile_id', 0); if ($default > 0) { return $default; } if ($user) { return self::accessibleStabili($user)->first()?->id; } return null; } public static function getActiveStabile(?User $user = null): ?Stabile { $id = self::getActiveStabileId($user); if (! $id) { return null; } if ($user) { return self::accessibleStabili($user)->firstWhere('id', $id); } return Stabile::query()->find($id); } public static function setActiveStabileId(User $user, int $stabileId): bool { $allowed = self::accessibleStabili($user)->pluck('id')->map(fn($v) => (int) $v)->all(); if (! in_array($stabileId, $allowed, true)) { return false; } session([self::SESSION_KEY => $stabileId]); if (Schema::hasColumn('users', 'last_stabile_id')) { try { DB::table('users')->where('id', (int) $user->id)->update(['last_stabile_id' => $stabileId]); } catch (\Throwable) { // best-effort: non bloccare la sessione } } return true; } }