diff --git a/app/Filament/Pages/Gescon/RubricaUniversaleScheda.php b/app/Filament/Pages/Gescon/RubricaUniversaleScheda.php index f80e518..9e6e90c 100755 --- a/app/Filament/Pages/Gescon/RubricaUniversaleScheda.php +++ b/app/Filament/Pages/Gescon/RubricaUniversaleScheda.php @@ -45,6 +45,8 @@ class RubricaUniversaleScheda extends Page public RubricaUniversale $rubrica; + public string $activeSubTab = 'personale'; + /** @var array> */ public array $fornitori = []; diff --git a/app/Services/Stabili/StabileTransferService.php b/app/Services/Stabili/StabileTransferService.php index a13696b..4040114 100755 --- a/app/Services/Stabili/StabileTransferService.php +++ b/app/Services/Stabili/StabileTransferService.php @@ -39,10 +39,36 @@ public function transfer( } } + // Trasferisci fornitori associati a questo stabile + if (Schema::hasTable('fornitori') && Schema::hasColumn('fornitori', 'amministratore_id')) { + DB::table('fornitori') + ->where('stabile_id', (int) $stabile->id) + ->update(['amministratore_id' => $toId, 'updated_at' => now()]); + } + if (method_exists($destination, 'provisionArchiveIfMissing')) { $destination->provisionArchiveIfMissing(); } + // Spostamento fisico della cartella archivio dello stabile (usa codice_univoco per evitare collisioni) + try { + $pathService = app(\App\Services\TenantArchivePathService::class); + $fromAmm = $fromId > 0 ? Amministratore::find($fromId) : null; + if ($fromAmm) { + $oldPath = $pathService->stabileAbsolutePath($stabile); + // Ricalcola nuovo path dopo cambio amministratore + $stabile->amministratore_id = $toId; + $newPath = $pathService->stabileAbsolutePath($stabile); + + if (is_dir($oldPath) && $oldPath !== $newPath) { + @mkdir(dirname($newPath), 0777, true); + @rename($oldPath, $newPath); + } + } + } catch (\Throwable $e) { + // Non-blocking fallback + } + return StabileAmministratoreTransfer::query()->create([ 'stabile_id' => (int) $stabile->id, 'from_amministratore_id' => $fromId > 0 ? $fromId : null, diff --git a/app/Services/TenantArchivePathService.php b/app/Services/TenantArchivePathService.php index a6f8bc2..b011ac1 100755 --- a/app/Services/TenantArchivePathService.php +++ b/app/Services/TenantArchivePathService.php @@ -42,7 +42,8 @@ public function stabileCode(Stabile | string $stabile): string return $code; } - $code = trim((string) ($stabile->codice_univoco ?: $stabile->codice_stabile ?: '')); + // Usa tassativamente codice_univoco (es. ST-0021 o 0000000C) per evitare collisioni tra amministratori differenti + $code = trim((string) ($stabile->codice_univoco ?: ('ST-' . ($stabile->codice_stabile ?: $stabile->id)))); if ($code === '') { throw new InvalidArgumentException('Stabile senza codice archivio canonico.'); diff --git a/public/adminer.php b/public/adminer.php index d4ce55d..4976271 100644 --- a/public/adminer.php +++ b/public/adminer.php @@ -4,9 +4,8 @@ * * SECURE WRAPPER FOR ADMINER * - Disabled in Production (APP_ENV=production or APP_DEBUG=false) - * - Supports 1-Click Auto-Login to MySQL Staging and PostgreSQL Consolidato + * - Supports 1-Click Instant Auto-Login via ?auto=mysql or ?auto=pgsql * - Auto-connects via TCP (127.0.0.1) to avoid Unix Socket Peer Auth failures - * - Strips and hides credentials from URL query parameters to prevent password leaks */ // 1. ENVIRONMENT SECURITY GUARD @@ -50,7 +49,31 @@ function env_get_val($key, $default = '') { return $default; } -// 2. ADMINER OBJECT CUSTOMIZATION +// 2. AUTO-LOGIN PARAMETER INJECTION +if (isset($_GET['auto'])) { + $dbName = env_get_val('DB_DATABASE', 'netgescon'); + if ($_GET['auto'] === 'pgsql') { + $_POST['auth'] = [ + 'driver' => 'pgsql', + 'server' => '127.0.0.1', + 'username' => 'netgescon', + 'password' => 'netgescon_pass', + 'db' => $dbName, + ]; + } else { + $mySqlUser = env_get_val('DB_USERNAME', 'netgescon_user'); + $mySqlPass = env_get_val('DB_PASSWORD', 'NetGescon2024!'); + $_POST['auth'] = [ + 'driver' => 'server', + 'server' => '127.0.0.1', + 'username' => $mySqlUser, + 'password' => $mySqlPass, + 'db' => $dbName, + ]; + } +} + +// 3. ADMINER OBJECT CUSTOMIZATION function adminer_object() { class NetGesconAdminerSecurity extends \Adminer\Adminer { function name() { @@ -58,10 +81,10 @@ function name() { } function credentials() { - $driver = $_POST["auth"]["driver"] ?? $_GET["pgsql"] ?? "server"; + $driver = $_POST["auth"]["driver"] ?? $_GET["driver"] ?? (isset($_GET["pgsql"]) ? "pgsql" : "server"); $dbHost = "127.0.0.1"; - if ($driver === "pgsql" || isset($_GET["pgsql"])) { + if ($driver === "pgsql" || isset($_GET["pgsql"]) || (isset($_GET["auto"]) && $_GET["auto"] === "pgsql")) { return array($dbHost, "netgescon", "netgescon_pass"); } @@ -81,62 +104,19 @@ function login($login, $password) { function loginForm() { $connection = env_get_val("DB_CONNECTION", "mysql"); - $defaultDriver = ($connection === "pgsql") ? "pgsql" : "server"; $mySqlUser = env_get_val("DB_USERNAME", "netgescon_user"); $mySqlPass = env_get_val("DB_PASSWORD", "NetGescon2024!"); $dbName = env_get_val("DB_DATABASE", "netgescon"); echo '
'; echo 'πŸ”’ NetGescon Secure Dual DB Visualizer
'; - echo 'Clicca su uno dei due pulsanti per accedere all\'istante al Database desiderato su TCP 127.0.0.1:

'; + echo 'Clicca su uno dei due link di accesso diretto per aprire l\'elenco tabelle del Database (TCP 127.0.0.1):

'; echo '
'; - echo ''; - echo ''; + echo '🐬 APRI MYSQL STAGING (' . $mySqlUser . ')'; + echo '🐘 APRI POSTGRESQL CONSOLIDATO (netgescon)'; echo '
'; echo '
'; - echo ''; return true; } } @@ -144,7 +124,7 @@ function loginEngine(type) { return new NetGesconAdminerSecurity; } -// 3. INCLUDE CORE ADMINER +// 4. INCLUDE CORE ADMINER if (file_exists(__DIR__ . '/adminer-core.php')) { include __DIR__ . '/adminer-core.php'; } else { diff --git a/resources/views/filament/pages/gescon/rubrica-universale-scheda.blade.php b/resources/views/filament/pages/gescon/rubrica-universale-scheda.blade.php index 3b9265f..73adc82 100755 --- a/resources/views/filament/pages/gescon/rubrica-universale-scheda.blade.php +++ b/resources/views/filament/pages/gescon/rubrica-universale-scheda.blade.php @@ -1,4 +1,26 @@ + {{-- BARRA PULSANTINI ICONICI COMPATTI (SENZA SCROLL ORIZZONTALE) --}} +
+
+ BARRA PULSANTINI ICONICI COMPATTI: +
+
+ 🏒 Elenco + + + +
+
+ + {{-- BARRA PULSANTINI ICONICI SECONDARIA PER DETTAGLI SCHEDA --}} +
+ SOTTO-MENΓ™ SCHEDA: + + + + +
+ @if($isInlineEditing) Modifica Contatto Inline