457 lines
14 KiB
Markdown
457 lines
14 KiB
Markdown
# 👥 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**
|
|
|
|
```sql
|
|
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**:
|
|
```sql
|
|
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
|
|
<?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
|
|
<?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
|
|
<?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**:
|
|
```json
|
|
{
|
|
"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**:
|
|
```php
|
|
// 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**
|