MAJOR IMPLEMENTATION COMPLETED: ✅ Modern database structure with Laravel best practices ✅ Complete Eloquent relationships (Amministratore→Stabili→Movements) ✅ 8-character alphanumeric codes system (ADM, ANA, MOV, ALL prefixes) ✅ Multi-database architecture for administrators ✅ Complete property management (anagrafica_condominiale, diritti_reali, contratti) ✅ Distribution system for multi-server deployment ✅ Universal responsive UI with permission-based sidebar NEW MODELS & MIGRATIONS: - AnagraficaCondominiale: Complete person/entity management - ContattoAnagrafica: Multi-contact system with usage flags - DirittoReale: Property rights with quotas and percentages - ContrattoLocazione: Rental contracts with landlord/tenant - TipoUtilizzo: Property usage types (residential, commercial, etc.) - Enhanced Stabile: Cadastral data, SDI, rate configuration - Enhanced UnitaImmobiliare: Modern structure with backward compatibility SERVICES & CONTROLLERS: - DistributionService: Multi-server deployment and migration - FileManagerController: Administrator folder management - DistributionController: API for server-to-server communication - MultiDatabaseService: Dynamic database connections READY FOR PRODUCTION: ✅ Database schema: Complete and tested ✅ Models relationships: All working and verified ✅ Code generation: Automatic 8-char codes implemented ✅ Testing: Successful data creation confirmed ✅ Documentation: Complete internal technical docs NEXT PHASE: Millésimal tables, expense categories, cost distribution engine
282 lines
9.7 KiB
PHP
282 lines
9.7 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Amministratore;
|
|
use App\Services\DistributionService;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class ManageDistribution extends Command
|
|
{
|
|
/**
|
|
* The name and signature of the console command.
|
|
*/
|
|
protected $signature = 'distribution:manage
|
|
{action : Action to perform (migrate|status|backup|test)}
|
|
{--administrator= : Administrator code (8 characters)}
|
|
{--target-server= : Target server URL for migration}
|
|
{--all : Apply to all administrators}';
|
|
|
|
/**
|
|
* The console command description.
|
|
*/
|
|
protected $description = 'Manage multi-server distribution of administrators';
|
|
|
|
/**
|
|
* Execute the console command.
|
|
*/
|
|
public function handle()
|
|
{
|
|
$action = $this->argument('action');
|
|
|
|
switch ($action) {
|
|
case 'migrate':
|
|
return $this->migrateAdministrator();
|
|
case 'status':
|
|
return $this->showDistributionStatus();
|
|
case 'backup':
|
|
return $this->backupAdministrator();
|
|
case 'test':
|
|
return $this->testDistribution();
|
|
default:
|
|
$this->error("Unknown action: {$action}");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Migra un amministratore verso un altro server
|
|
*/
|
|
private function migrateAdministrator()
|
|
{
|
|
$adminCode = $this->option('administrator');
|
|
$targetServer = $this->option('target-server');
|
|
|
|
if (!$adminCode) {
|
|
$adminCode = $this->ask('Administrator code (8 characters)');
|
|
}
|
|
|
|
if (!$targetServer) {
|
|
$targetServer = $this->ask('Target server URL');
|
|
}
|
|
|
|
if (!$adminCode || !$targetServer) {
|
|
$this->error('Both administrator code and target server are required');
|
|
return 1;
|
|
}
|
|
|
|
$amministratore = Amministratore::where('codice_amministratore', $adminCode)->first();
|
|
|
|
if (!$amministratore) {
|
|
$this->error("Administrator {$adminCode} not found");
|
|
return 1;
|
|
}
|
|
|
|
$this->info("Starting migration of administrator {$adminCode} to {$targetServer}");
|
|
|
|
// Verifica server target
|
|
$this->info('Checking target server health...');
|
|
$healthCheck = DistributionService::checkServerHealth($targetServer);
|
|
|
|
if (!$healthCheck['success']) {
|
|
$this->error("Target server health check failed: {$healthCheck['error']}");
|
|
return 1;
|
|
}
|
|
|
|
$this->info('Target server is healthy and compatible');
|
|
|
|
// Conferma migrazione
|
|
if (!$this->confirm("Are you sure you want to migrate administrator {$adminCode} to {$targetServer}?")) {
|
|
$this->info('Migration cancelled');
|
|
return 0;
|
|
}
|
|
|
|
// Esegui migrazione
|
|
$this->info('Starting migration process...');
|
|
$result = DistributionService::migrateAdministrator($amministratore, $targetServer);
|
|
|
|
if ($result['success']) {
|
|
$this->info("✅ Migration completed successfully!");
|
|
$this->info("Administrator {$adminCode} is now accessible at: {$result['new_url']}");
|
|
} else {
|
|
$this->error("❌ Migration failed: {$result['error']}");
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Mostra stato della distribuzione
|
|
*/
|
|
private function showDistributionStatus()
|
|
{
|
|
$this->info('NetGesCon Multi-Server Distribution Status');
|
|
$this->info('==========================================');
|
|
|
|
$stats = DistributionService::getDistributionStats();
|
|
|
|
$this->info("Total Administrators: {$stats['total_administrators']}");
|
|
$this->info("Local Administrators: {$stats['local_administrators']}");
|
|
$this->info("Distributed Administrators: {$stats['distributed_administrators']}");
|
|
|
|
$this->newLine();
|
|
$this->info('Server Distribution:');
|
|
|
|
if (empty($stats['servers'])) {
|
|
$this->info(' No distributed servers configured');
|
|
} else {
|
|
foreach ($stats['servers'] as $server) {
|
|
$this->info(" {$server['server']}: {$server['administrators_count']} administrators");
|
|
}
|
|
}
|
|
|
|
$this->newLine();
|
|
$this->info('Status Distribution:');
|
|
foreach ($stats['status_distribution'] as $status => $count) {
|
|
$this->info(" {$status}: {$count}");
|
|
}
|
|
|
|
// Mostra dettagli amministratori distribuiti
|
|
$distributedAdmins = Amministratore::whereNotNull('server_database')->get();
|
|
|
|
if ($distributedAdmins->isNotEmpty()) {
|
|
$this->newLine();
|
|
$this->info('Distributed Administrators Details:');
|
|
$this->table(
|
|
['Code', 'Name', 'Server', 'Status', 'Last Backup'],
|
|
$distributedAdmins->map(function ($admin) {
|
|
return [
|
|
$admin->codice_amministratore,
|
|
$admin->nome_completo,
|
|
$admin->server_database ?: 'localhost',
|
|
$admin->stato_sincronizzazione,
|
|
$admin->ultimo_backup ? $admin->ultimo_backup->format('Y-m-d H:i') : 'Never'
|
|
];
|
|
})
|
|
);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Esegue backup di un amministratore
|
|
*/
|
|
private function backupAdministrator()
|
|
{
|
|
$adminCode = $this->option('administrator');
|
|
$all = $this->option('all');
|
|
|
|
if (!$adminCode && !$all) {
|
|
$adminCode = $this->ask('Administrator code (8 characters) or use --all for all administrators');
|
|
}
|
|
|
|
if ($all) {
|
|
$this->info('Backing up all administrators...');
|
|
$administrators = Amministratore::all();
|
|
} else {
|
|
$administrators = Amministratore::where('codice_amministratore', $adminCode)->get();
|
|
|
|
if ($administrators->isEmpty()) {
|
|
$this->error("Administrator {$adminCode} not found");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
$successCount = 0;
|
|
$errorCount = 0;
|
|
|
|
foreach ($administrators as $admin) {
|
|
$this->info("Backing up administrator {$admin->codice_amministratore}...");
|
|
|
|
$result = DistributionService::performDistributedBackup($admin);
|
|
|
|
if ($result['success']) {
|
|
$this->info("✅ Backup completed for {$admin->codice_amministratore}");
|
|
$successCount++;
|
|
} else {
|
|
$this->error("❌ Backup failed for {$admin->codice_amministratore}: {$result['error']}");
|
|
$errorCount++;
|
|
}
|
|
}
|
|
|
|
$this->info("Backup completed: {$successCount} successful, {$errorCount} errors");
|
|
return $errorCount > 0 ? 1 : 0;
|
|
}
|
|
|
|
/**
|
|
* Testa la funzionalità di distribuzione
|
|
*/
|
|
private function testDistribution()
|
|
{
|
|
$this->info('Testing distribution functionality...');
|
|
|
|
// Test 1: Verifica struttura cartelle
|
|
$this->info('1. Testing folder structure...');
|
|
$testAdmin = Amministratore::first();
|
|
|
|
if (!$testAdmin) {
|
|
$this->error('No administrators found for testing');
|
|
return 1;
|
|
}
|
|
|
|
$archiveInfo = $testAdmin->getArchiveInfo();
|
|
|
|
if ($archiveInfo['exists']) {
|
|
$this->info("✅ Archive exists: {$archiveInfo['path']}");
|
|
$this->info(" Size: {$archiveInfo['size_formatted']}");
|
|
$this->info(" Files: {$archiveInfo['files_count']}");
|
|
} else {
|
|
$this->warn("⚠️ Archive not found for {$testAdmin->codice_amministratore}");
|
|
}
|
|
|
|
// Test 2: Health check locale
|
|
$this->info('2. Testing local health check...');
|
|
$localUrl = config('app.url');
|
|
$healthCheck = DistributionService::checkServerHealth($localUrl);
|
|
|
|
if ($healthCheck['success']) {
|
|
$this->info("✅ Local server health check passed");
|
|
} else {
|
|
$this->error("❌ Local server health check failed: {$healthCheck['error']}");
|
|
}
|
|
|
|
// Test 3: Backup test
|
|
$this->info('3. Testing backup functionality...');
|
|
$backupResult = $testAdmin->createDatabaseBackup();
|
|
|
|
if ($backupResult['success']) {
|
|
$this->info("✅ Backup test passed");
|
|
$this->info(" File: {$backupResult['filename']}");
|
|
$this->info(" Size: " . number_format($backupResult['size']) . " bytes");
|
|
} else {
|
|
$this->error("❌ Backup test failed: {$backupResult['error']}");
|
|
}
|
|
|
|
// Test 4: Migrazione simulata
|
|
$this->info('4. Testing migration preparation...');
|
|
$migrationResult = $testAdmin->prepareForMigration();
|
|
|
|
if ($migrationResult['success']) {
|
|
$this->info("✅ Migration preparation test passed");
|
|
$this->info(" Archive: {$migrationResult['zip_file']}");
|
|
$this->info(" Size: " . number_format($migrationResult['size']) . " bytes");
|
|
|
|
// Cleanup test files
|
|
if (file_exists($migrationResult['zip_file'])) {
|
|
unlink($migrationResult['zip_file']);
|
|
}
|
|
if (file_exists($migrationResult['metadata_file'])) {
|
|
unlink($migrationResult['metadata_file']);
|
|
}
|
|
} else {
|
|
$this->error("❌ Migration preparation test failed: {$migrationResult['error']}");
|
|
}
|
|
|
|
$this->info('Distribution testing completed');
|
|
return 0;
|
|
}
|
|
}
|