14 KiB
14 KiB
👥 TABELLA AMMINISTRATORI
Tabella master con codice univoco 8 cifre
🎯 CARATTERISTICHE TABELLA
Scopo:
Tabella principale che identifica ogni amministratore con un codice univoco di 8 cifre alfanumeriche
Principio:
Ogni amministratore ha la sua "bolla" di dati completamente isolata
🗄️ STRUTTURA TABELLA
CREATE TABLE amministratori (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
codice_univoco CHAR(8) NOT NULL UNIQUE, -- ES: A1B2C3D4
nome VARCHAR(255) NOT NULL,
cognome VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
telefono VARCHAR(20) NULL,
-- Dati aziendali
nome_studio VARCHAR(255) NULL, -- Nome studio/azienda
partita_iva VARCHAR(11) NULL,
codice_fiscale VARCHAR(16) NULL,
indirizzo TEXT NULL,
citta VARCHAR(255) NULL,
cap VARCHAR(10) NULL,
provincia VARCHAR(2) NULL,
-- Stato e configurazione
is_active BOOLEAN DEFAULT TRUE,
ultimo_accesso TIMESTAMP NULL,
piano_abbonamento ENUM('base', 'professional', 'enterprise') DEFAULT 'base',
data_scadenza_abbonamento DATE NULL,
-- Configurazioni
max_stabili INT DEFAULT 10, -- Limite stabili per piano
max_unita INT DEFAULT 500, -- Limite unità per piano
configurazioni JSON NULL, -- Configurazioni personalizzate
-- Audit
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-- Indici
INDEX idx_codice_univoco (codice_univoco),
INDEX idx_email (email),
INDEX idx_active (is_active),
INDEX idx_piano_abbonamento (piano_abbonamento)
);
⚡ TRIGGER CODICE UNIVOCO
Generazione Automatica 8 Cifre:
DELIMITER $$
CREATE TRIGGER generate_codice_univoco_amministratori
BEFORE INSERT ON amministratori
FOR EACH ROW
BEGIN
DECLARE codice_temp CHAR(8);
DECLARE codice_exists INT DEFAULT 1;
-- Solo se il codice non è già fornito
IF NEW.codice_univoco IS NULL OR NEW.codice_univoco = '' THEN
WHILE codice_exists > 0 DO
-- Genera codice 8 cifre alfanumerico
SET codice_temp = CONCAT(
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', FLOOR(1 + (RAND() * 36)), 1)
);
-- Verifica unicità
SELECT COUNT(*) INTO codice_exists
FROM amministratori
WHERE codice_univoco = codice_temp;
END WHILE;
SET NEW.codice_univoco = codice_temp;
END IF;
END$$
DELIMITER ;
🏗️ MIGRATION LARAVEL
File: database/migrations/2024_08_05_000001_create_amministratori_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
public function up(): void
{
Schema::create('amministratori', function (Blueprint $table) {
$table->id();
$table->char('codice_univoco', 8)->unique();
$table->string('nome');
$table->string('cognome');
$table->string('email')->unique();
$table->string('telefono', 20)->nullable();
// Dati aziendali
$table->string('nome_studio')->nullable();
$table->string('partita_iva', 11)->nullable();
$table->string('codice_fiscale', 16)->nullable();
$table->text('indirizzo')->nullable();
$table->string('citta')->nullable();
$table->string('cap', 10)->nullable();
$table->string('provincia', 2)->nullable();
// Stato e configurazione
$table->boolean('is_active')->default(true);
$table->timestamp('ultimo_accesso')->nullable();
$table->enum('piano_abbonamento', ['base', 'professional', 'enterprise'])->default('base');
$table->date('data_scadenza_abbonamento')->nullable();
// Configurazioni
$table->integer('max_stabili')->default(10);
$table->integer('max_unita')->default(500);
$table->json('configurazioni')->nullable();
$table->timestamps();
// Indici
$table->index(['codice_univoco']);
$table->index(['email']);
$table->index(['is_active']);
$table->index(['piano_abbonamento']);
});
// Crea trigger per codice univoco
$this->createTrigger();
}
public function down(): void
{
DB::unprepared('DROP TRIGGER IF EXISTS generate_codice_univoco_amministratori');
Schema::dropIfExists('amministratori');
}
private function createTrigger(): void
{
DB::unprepared('
DROP TRIGGER IF EXISTS generate_codice_univoco_amministratori;
DELIMITER $$
CREATE TRIGGER generate_codice_univoco_amministratori
BEFORE INSERT ON amministratori
FOR EACH ROW
BEGIN
DECLARE codice_temp CHAR(8);
DECLARE codice_exists INT DEFAULT 1;
IF NEW.codice_univoco IS NULL OR NEW.codice_univoco = "" THEN
WHILE codice_exists > 0 DO
SET codice_temp = CONCAT(
SUBSTRING("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", FLOOR(1 + (RAND() * 36)), 1),
SUBSTRING("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", FLOOR(1 + (RAND() * 36)), 1)
);
SELECT COUNT(*) INTO codice_exists
FROM amministratori
WHERE codice_univoco = codice_temp;
END WHILE;
SET NEW.codice_univoco = codice_temp;
END IF;
END$$
DELIMITER ;
');
}
};
📊 MODEL ELOQUENT
File: app/Models/Amministratore.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Builder;
class Amministratore extends Model
{
protected $fillable = [
'nome',
'cognome',
'email',
'telefono',
'nome_studio',
'partita_iva',
'codice_fiscale',
'indirizzo',
'citta',
'cap',
'provincia',
'is_active',
'piano_abbonamento',
'data_scadenza_abbonamento',
'max_stabili',
'max_unita',
'configurazioni'
];
protected $casts = [
'is_active' => 'boolean',
'ultimo_accesso' => 'datetime',
'data_scadenza_abbonamento' => 'date',
'configurazioni' => 'array',
'max_stabili' => 'integer',
'max_unita' => 'integer',
];
protected $hidden = [
// Nessun campo hidden per ora
];
// Relazioni
public function users(): HasMany
{
return $this->hasMany(User::class, 'amministratore_id');
}
public function stabili(): HasMany
{
return $this->hasMany(Stabile::class, 'amministratore_id');
}
// Scope
public function scopeActive(Builder $query): Builder
{
return $query->where('is_active', true);
}
public function scopeByPiano(Builder $query, string $piano): Builder
{
return $query->where('piano_abbonamento', $piano);
}
// Accessors
public function getNomeCompletoAttribute(): string
{
return "{$this->nome} {$this->cognome}";
}
public function getAbbonamentoAttivoAttribute(): bool
{
return $this->data_scadenza_abbonamento === null ||
$this->data_scadenza_abbonamento->isFuture();
}
public function getCountStabiliAttribute(): int
{
return $this->stabili()->count();
}
public function getCountUnitaAttribute(): int
{
return $this->stabili()
->withCount('unitaImmobiliari')
->get()
->sum('unita_immobiliari_count');
}
// Helper Methods
public function canAddStabile(): bool
{
return $this->count_stabili < $this->max_stabili;
}
public function canAddUnita(): bool
{
return $this->count_unita < $this->max_unita;
}
public function updateUltimoAccesso(): void
{
$this->update(['ultimo_accesso' => now()]);
}
}
🌱 SEEDER DATI DEMO
File: database/seeders/AmministratoriSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Amministratore;
class AmministratoriSeeder extends Seeder
{
public function run(): void
{
// Amministratore demo 1
$admin1 = Amministratore::create([
'nome' => 'Mario',
'cognome' => 'Rossi',
'email' => 'mario.rossi@netgescon.it',
'telefono' => '3331234567',
'nome_studio' => 'Studio Amministrativo Rossi',
'partita_iva' => '12345678901',
'codice_fiscale' => 'RSSMRA70A01H501Z',
'indirizzo' => 'Via Roma 123',
'citta' => 'Milano',
'cap' => '20100',
'provincia' => 'MI',
'piano_abbonamento' => 'professional',
'max_stabili' => 50,
'max_unita' => 2000,
'is_active' => true,
]);
// Amministratore demo 2
$admin2 = Amministratore::create([
'nome' => 'Anna',
'cognome' => 'Verdi',
'email' => 'anna.verdi@netgescon.it',
'telefono' => '3339876543',
'nome_studio' => 'Amministrazioni Verdi S.r.l.',
'partita_iva' => '09876543210',
'codice_fiscale' => 'VRDNNA75B01F205X',
'indirizzo' => 'Corso Italia 456',
'citta' => 'Roma',
'cap' => '00100',
'provincia' => 'RM',
'piano_abbonamento' => 'enterprise',
'max_stabili' => 100,
'max_unita' => 5000,
'is_active' => true,
]);
// Amministratore demo 3 - Base
$admin3 = Amministratore::create([
'nome' => 'Giuseppe',
'cognome' => 'Bianchi',
'email' => 'giuseppe.bianchi@netgescon.it',
'telefono' => '3335551234',
'nome_studio' => 'Studio Bianchi',
'piano_abbonamento' => 'base',
'max_stabili' => 10,
'max_unita' => 500,
'is_active' => true,
]);
$this->command->info('✅ Creati 3 amministratori demo');
$this->command->info("Admin 1 codice: {$admin1->codice_univoco}");
$this->command->info("Admin 2 codice: {$admin2->codice_univoco}");
$this->command->info("Admin 3 codice: {$admin3->codice_univoco}");
}
}
🔧 CONFIGURAZIONI AVANZATE
Configurazioni JSON Esempio:
{
"ui_preferences": {
"theme": "light",
"items_per_page": 20,
"default_view": "grid"
},
"notifications": {
"email_enabled": true,
"sms_enabled": false,
"scadenze_alert_days": 30
},
"features": {
"multi_gestione": true,
"export_excel": true,
"api_access": false
},
"branding": {
"logo_url": "/storage/logos/admin_ABC12345.png",
"primary_color": "#007bff",
"company_name": "Studio Amministrativo XYZ"
}
}
🎯 UTILIZZO PATTERN
Query Base per Amministratore:
// Nel controller
$amministratore = auth()->user()->amministratore;
$codice = $amministratore->codice_univoco; // ES: A1B2C3D4
// Tutti i stabili dell'amministratore
$stabili = $amministratore->stabili()->active()->get();
// Stats amministratore
$stats = [
'stabili_count' => $amministratore->count_stabili,
'unita_count' => $amministratore->count_unita,
'limite_stabili' => $amministratore->max_stabili,
'limite_unita' => $amministratore->max_unita,
];
🎯 TABELLA AMMINISTRATORI DEFINITA
Con codice univoco 8 cifre, trigger automatico e isolamento dati completo
📖 Prossimo: users.md per collegare utenti agli amministratori