netgescon-master/app/Services/MultiDatabaseService.php
Pikappa2 1b884feda5 v0.7 - UI Universale e Sistema Database Modernizzato
 Completato:
- Database modernizzato con chiavi id standard Laravel
- Relazioni corrette Amministratore→Stabili→Movimenti
- UI universale responsive con sidebar permission-based
- Codici alfanumerici 8 caratteri implementati
- Seeders con dati di test funzionanti
- Documentazione tecnica completa (INSTALL_LINUX, TECHNICAL_SPECS, UPDATE_SYSTEM)

🔧 Miglioramenti:
- Helper userSetting() funzionante
- Sistema multi-database preparato
- .gitignore aggiornato per sicurezza
- Migration cleanup e ottimizzazione

📚 Documentazione:
- Guida installazione Linux completa
- Specifiche tecniche dettagliate
- Sistema aggiornamenti progettato
- Progress log aggiornato
2025-07-07 17:24:30 +02:00

202 lines
6.9 KiB
PHP

<?php
namespace App\Services;
use App\Models\Amministratore;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class MultiDatabaseService
{
/**
* Configura dinamicamente la connessione database per un amministratore.
*/
public static function setupAdminConnection(Amministratore $amministratore): string
{
$connectionName = "admin_{$amministratore->codice_amministratore}";
if ($amministratore->hasDedicatedDatabase()) {
$config = [
'driver' => 'mysql',
'host' => $amministratore->server_database ?? env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => "netgescon_{$amministratore->codice_amministratore}",
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
\PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
];
} else {
// Usa database principale con prefisso
$config = config('database.connections.' . config('database.default'));
$config['prefix'] = "{$amministratore->codice_amministratore}_";
}
Config::set("database.connections.{$connectionName}", $config);
return $connectionName;
}
/**
* Crea il database dedicato per un amministratore.
*/
public static function createAdminDatabase(Amministratore $amministratore): bool
{
try {
$dbName = "netgescon_{$amministratore->codice_amministratore}";
// Connessione root per creare database
$rootConnection = config('database.default');
DB::connection($rootConnection)->statement("CREATE DATABASE IF NOT EXISTS `{$dbName}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
// Setup connessione specifica
$connectionName = static::setupAdminConnection($amministratore);
// Esegui migration sul nuovo database
static::migrateAdminDatabase($connectionName);
// Aggiorna amministratore
$amministratore->update([
'database_attivo' => true,
'database_name' => $amministratore->codice_amministratore
]);
return true;
} catch (\Exception $e) {
\Log::error("Errore creazione database per {$amministratore->codice_amministratore}: " . $e->getMessage());
return false;
}
}
/**
* Esegue le migration sul database amministratore.
*/
private static function migrateAdminDatabase(string $connectionName): void
{
// Migration specifiche per database amministratore
$adminTables = [
'stabili',
'movimenti_contabili',
'allegati',
'gestioni',
'voci_spesa',
'unita_immobiliari',
'proprietari',
'inquilini',
'fornitori_admin', // Fornitori specifici amministratore
'bilanci',
'assemblee',
'verbali',
'preventivi',
'contratti',
];
foreach ($adminTables as $table) {
static::createTableFromMaster($table, $connectionName);
}
}
/**
* Copia struttura tabella dal database master.
*/
private static function createTableFromMaster(string $tableName, string $connectionName): void
{
try {
$masterConnection = config('database.default');
$createSql = DB::connection($masterConnection)
->select("SHOW CREATE TABLE `{$tableName}`")[0]->{'Create Table'};
DB::connection($connectionName)->statement($createSql);
} catch (\Exception $e) {
\Log::warning("Tabella {$tableName} non copiata: " . $e->getMessage());
}
}
/**
* Ottiene la connessione per un amministratore specifico.
*/
public static function getAdminConnection(Amministratore $amministratore): string
{
$connectionName = "admin_{$amministratore->codice_amministratore}";
// Se non esiste la configurazione, creala
if (!config("database.connections.{$connectionName}")) {
return static::setupAdminConnection($amministratore);
}
return $connectionName;
}
/**
* Sincronizza schema tra database master e amministratori.
*/
public static function syncSchemaToAllAdmins(): array
{
$results = [];
$adminsWithDb = Amministratore::where('database_attivo', true)->get();
foreach ($adminsWithDb as $admin) {
try {
$connectionName = static::getAdminConnection($admin);
static::migrateAdminDatabase($connectionName);
$results[$admin->codice_amministratore] = 'success';
} catch (\Exception $e) {
$results[$admin->codice_amministratore] = 'error: ' . $e->getMessage();
}
}
return $results;
}
/**
* Verifica integrità database amministratore.
*/
public static function checkAdminDatabase(Amministratore $amministratore): array
{
try {
$connectionName = static::getAdminConnection($amministratore);
$tables = Schema::connection($connectionName)->getTables();
return [
'status' => 'ok',
'tables_count' => count($tables),
'tables' => array_column($tables, 'name'),
'size' => static::getDatabaseSize($connectionName)
];
} catch (\Exception $e) {
return [
'status' => 'error',
'message' => $e->getMessage()
];
}
}
/**
* Calcola dimensione database.
*/
private static function getDatabaseSize(string $connectionName): string
{
try {
$config = config("database.connections.{$connectionName}");
$dbName = $config['database'];
$size = DB::connection($connectionName)
->select("SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'DB Size in MB' FROM information_schema.tables WHERE table_schema='{$dbName}'")[0]->{'DB Size in MB'};
return $size . ' MB';
} catch (\Exception $e) {
return 'N/A';
}
}
}