727 lines
23 KiB
Markdown
727 lines
23 KiB
Markdown
# 🏢 TABELLA STABILI
|
|
## Edifici e condomini gestiti dall'amministratore
|
|
|
|
---
|
|
|
|
## 🎯 **CARATTERISTICHE TABELLA**
|
|
|
|
### **Scopo**:
|
|
Tabella per tutti gli edifici gestiti dall'amministratore - ogni stabile appartiene a un singolo amministratore
|
|
|
|
### **Principio**:
|
|
**Isolamento per amministratore** - ogni stabile ha `amministratore_id` per filtro multi-tenant
|
|
|
|
---
|
|
|
|
## 🗄️ **STRUTTURA TABELLA**
|
|
|
|
```sql
|
|
CREATE TABLE stabili (
|
|
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
amministratore_id BIGINT UNSIGNED NOT NULL, -- FK verso amministratori
|
|
|
|
-- Identificazione stabile
|
|
denominazione VARCHAR(255) NOT NULL, -- Nome condominio/edificio
|
|
codice_interno VARCHAR(50) NULL, -- Codice interno amministratore
|
|
|
|
-- Indirizzo completo
|
|
indirizzo VARCHAR(255) NOT NULL,
|
|
numero_civico VARCHAR(20) NULL,
|
|
scala VARCHAR(50) NULL,
|
|
cap VARCHAR(10) NOT NULL,
|
|
comune_id INT UNSIGNED NULL, -- FK verso comuni_italiani
|
|
provincia VARCHAR(2) NOT NULL,
|
|
regione VARCHAR(50) NULL,
|
|
|
|
-- Dati catastali
|
|
foglio VARCHAR(20) NULL,
|
|
particella VARCHAR(20) NULL,
|
|
subalterno VARCHAR(20) NULL,
|
|
categoria_catastale VARCHAR(10) NULL,
|
|
classe VARCHAR(10) NULL,
|
|
consistenza VARCHAR(50) NULL,
|
|
rendita_catastale DECIMAL(10, 2) NULL,
|
|
|
|
-- Caratteristiche edificio
|
|
anno_costruzione YEAR NULL,
|
|
numero_piani INT NULL,
|
|
numero_unita INT DEFAULT 0, -- Calcolato automaticamente
|
|
ascensore BOOLEAN DEFAULT FALSE,
|
|
riscaldamento_centralizzato BOOLEAN DEFAULT FALSE,
|
|
tipo_edificio ENUM('condominio', 'villetta', 'complesso', 'altro') DEFAULT 'condominio',
|
|
|
|
-- Dati amministrativi
|
|
codice_fiscale_condominio VARCHAR(16) NULL, -- CF del condominio
|
|
partita_iva_condominio VARCHAR(11) NULL,
|
|
data_nomina_amministratore DATE NULL,
|
|
data_scadenza_mandato DATE NULL,
|
|
periodicita_assemblea ENUM('annuale', 'semestrale') DEFAULT 'annuale',
|
|
|
|
-- Configurazioni
|
|
usa_millesimi BOOLEAN DEFAULT TRUE,
|
|
valuta_default VARCHAR(3) DEFAULT 'EUR',
|
|
configurazioni JSON NULL, -- Config specifiche stabile
|
|
|
|
-- Stato
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
note TEXT NULL,
|
|
|
|
-- Audit
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
-- Foreign Keys
|
|
FOREIGN KEY (amministratore_id) REFERENCES amministratori(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (comune_id) REFERENCES comuni_italiani(id) ON DELETE SET NULL,
|
|
|
|
-- Indici
|
|
INDEX idx_amministratore_id (amministratore_id),
|
|
INDEX idx_comune_id (comune_id),
|
|
INDEX idx_denominazione (denominazione),
|
|
INDEX idx_active (is_active),
|
|
INDEX idx_cap (cap),
|
|
INDEX idx_provincia (provincia),
|
|
INDEX idx_tipo_edificio (tipo_edificio),
|
|
|
|
-- Indice composto per ricerche
|
|
INDEX idx_admin_denominazione (amministratore_id, denominazione),
|
|
INDEX idx_admin_active (amministratore_id, is_active)
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 🏗️ **MIGRATION LARAVEL**
|
|
|
|
### **File**: `database/migrations/2024_08_05_000010_create_stabili_table.php`
|
|
|
|
```php
|
|
<?php
|
|
|
|
use Illuminate\Database\Migrations\Migration;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
return new class extends Migration
|
|
{
|
|
public function up(): void
|
|
{
|
|
Schema::create('stabili', function (Blueprint $table) {
|
|
$table->id();
|
|
$table->foreignId('amministratore_id')
|
|
->constrained('amministratori')
|
|
->onDelete('cascade');
|
|
|
|
// Identificazione stabile
|
|
$table->string('denominazione');
|
|
$table->string('codice_interno', 50)->nullable();
|
|
|
|
// Indirizzo completo
|
|
$table->string('indirizzo');
|
|
$table->string('numero_civico', 20)->nullable();
|
|
$table->string('scala', 50)->nullable();
|
|
$table->string('cap', 10);
|
|
$table->unsignedInteger('comune_id')->nullable();
|
|
$table->string('provincia', 2);
|
|
$table->string('regione', 50)->nullable();
|
|
|
|
// Dati catastali
|
|
$table->string('foglio', 20)->nullable();
|
|
$table->string('particella', 20)->nullable();
|
|
$table->string('subalterno', 20)->nullable();
|
|
$table->string('categoria_catastale', 10)->nullable();
|
|
$table->string('classe', 10)->nullable();
|
|
$table->string('consistenza', 50)->nullable();
|
|
$table->decimal('rendita_catastale', 10, 2)->nullable();
|
|
|
|
// Caratteristiche edificio
|
|
$table->year('anno_costruzione')->nullable();
|
|
$table->integer('numero_piani')->nullable();
|
|
$table->integer('numero_unita')->default(0);
|
|
$table->boolean('ascensore')->default(false);
|
|
$table->boolean('riscaldamento_centralizzato')->default(false);
|
|
$table->enum('tipo_edificio', ['condominio', 'villetta', 'complesso', 'altro'])
|
|
->default('condominio');
|
|
|
|
// Dati amministrativi
|
|
$table->string('codice_fiscale_condominio', 16)->nullable();
|
|
$table->string('partita_iva_condominio', 11)->nullable();
|
|
$table->date('data_nomina_amministratore')->nullable();
|
|
$table->date('data_scadenza_mandato')->nullable();
|
|
$table->enum('periodicita_assemblea', ['annuale', 'semestrale'])
|
|
->default('annuale');
|
|
|
|
// Configurazioni
|
|
$table->boolean('usa_millesimi')->default(true);
|
|
$table->string('valuta_default', 3)->default('EUR');
|
|
$table->json('configurazioni')->nullable();
|
|
|
|
// Stato
|
|
$table->boolean('is_active')->default(true);
|
|
$table->text('note')->nullable();
|
|
|
|
$table->timestamps();
|
|
|
|
// Foreign Keys
|
|
$table->foreign('comune_id')
|
|
->references('id')
|
|
->on('comuni_italiani')
|
|
->onDelete('set null');
|
|
|
|
// Indici
|
|
$table->index(['amministratore_id']);
|
|
$table->index(['comune_id']);
|
|
$table->index(['denominazione']);
|
|
$table->index(['is_active']);
|
|
$table->index(['cap']);
|
|
$table->index(['provincia']);
|
|
$table->index(['tipo_edificio']);
|
|
|
|
// Indici composti
|
|
$table->index(['amministratore_id', 'denominazione'], 'idx_admin_denominazione');
|
|
$table->index(['amministratore_id', 'is_active'], 'idx_admin_active');
|
|
});
|
|
}
|
|
|
|
public function down(): void
|
|
{
|
|
Schema::dropIfExists('stabili');
|
|
}
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 **MODEL ELOQUENT**
|
|
|
|
### **File**: `app/Models/Stabile.php`
|
|
|
|
```php
|
|
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
|
|
class Stabile extends Model
|
|
{
|
|
protected $fillable = [
|
|
'amministratore_id',
|
|
'denominazione',
|
|
'codice_interno',
|
|
'indirizzo',
|
|
'numero_civico',
|
|
'scala',
|
|
'cap',
|
|
'comune_id',
|
|
'provincia',
|
|
'regione',
|
|
'foglio',
|
|
'particella',
|
|
'subalterno',
|
|
'categoria_catastale',
|
|
'classe',
|
|
'consistenza',
|
|
'rendita_catastale',
|
|
'anno_costruzione',
|
|
'numero_piani',
|
|
'ascensore',
|
|
'riscaldamento_centralizzato',
|
|
'tipo_edificio',
|
|
'codice_fiscale_condominio',
|
|
'partita_iva_condominio',
|
|
'data_nomina_amministratore',
|
|
'data_scadenza_mandato',
|
|
'periodicita_assemblea',
|
|
'usa_millesimi',
|
|
'valuta_default',
|
|
'configurazioni',
|
|
'is_active',
|
|
'note',
|
|
];
|
|
|
|
protected $casts = [
|
|
'ascensore' => 'boolean',
|
|
'riscaldamento_centralizzato' => 'boolean',
|
|
'usa_millesimi' => 'boolean',
|
|
'is_active' => 'boolean',
|
|
'data_nomina_amministratore' => 'date',
|
|
'data_scadenza_mandato' => 'date',
|
|
'rendita_catastale' => 'decimal:2',
|
|
'configurazioni' => 'array',
|
|
'numero_piani' => 'integer',
|
|
'numero_unita' => 'integer',
|
|
];
|
|
|
|
// Relazioni
|
|
public function amministratore(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Amministratore::class);
|
|
}
|
|
|
|
public function comune(): BelongsTo
|
|
{
|
|
return $this->belongsTo(ComuneItaliano::class, 'comune_id');
|
|
}
|
|
|
|
public function unitaImmobiliari(): HasMany
|
|
{
|
|
return $this->hasMany(UnitaImmobiliare::class);
|
|
}
|
|
|
|
public function gestioni(): HasMany
|
|
{
|
|
return $this->hasMany(Gestione::class);
|
|
}
|
|
|
|
public function documenti(): HasMany
|
|
{
|
|
return $this->hasMany(Documento::class);
|
|
}
|
|
|
|
public function soggetti(): HasMany
|
|
{
|
|
return $this->hasMany(Soggetto::class);
|
|
}
|
|
|
|
// Scope automatico per amministratore corrente
|
|
protected static function booted(): void
|
|
{
|
|
static::addGlobalScope('amministratore', function (Builder $builder) {
|
|
$user = auth()->user();
|
|
if ($user && $user->amministratore_id) {
|
|
$builder->where('amministratore_id', $user->amministratore_id);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Scope
|
|
public function scopeActive(Builder $query): Builder
|
|
{
|
|
return $query->where('is_active', true);
|
|
}
|
|
|
|
public function scopeByTipo(Builder $query, string $tipo): Builder
|
|
{
|
|
return $query->where('tipo_edificio', $tipo);
|
|
}
|
|
|
|
public function scopeByProvincia(Builder $query, string $provincia): Builder
|
|
{
|
|
return $query->where('provincia', $provincia);
|
|
}
|
|
|
|
public function scopeConAscensore(Builder $query): Builder
|
|
{
|
|
return $query->where('ascensore', true);
|
|
}
|
|
|
|
public function scopeConRiscaldamentoCentralizzato(Builder $query): Builder
|
|
{
|
|
return $query->where('riscaldamento_centralizzato', true);
|
|
}
|
|
|
|
// Accessors
|
|
public function getIndirizzoCompletoAttribute(): string
|
|
{
|
|
$parts = array_filter([
|
|
$this->indirizzo,
|
|
$this->numero_civico,
|
|
$this->scala ? "Scala {$this->scala}" : null,
|
|
]);
|
|
|
|
return implode(', ', $parts);
|
|
}
|
|
|
|
public function getLocalitaAttribute(): string
|
|
{
|
|
$parts = array_filter([
|
|
$this->cap,
|
|
$this->comune?->denominazione,
|
|
$this->provincia ? "({$this->provincia})" : null,
|
|
]);
|
|
|
|
return implode(' ', $parts);
|
|
}
|
|
|
|
public function getIndirizzoFormattato(): string
|
|
{
|
|
return "{$this->indirizzo_completo}\n{$this->localita}";
|
|
}
|
|
|
|
public function getMandatoScadutoAttribute(): bool
|
|
{
|
|
return $this->data_scadenza_mandato &&
|
|
$this->data_scadenza_mandato->isPast();
|
|
}
|
|
|
|
public function getGiorniAllaScadenzaAttribute(): ?int
|
|
{
|
|
if (!$this->data_scadenza_mandato) {
|
|
return null;
|
|
}
|
|
|
|
return now()->diffInDays($this->data_scadenza_mandato, false);
|
|
}
|
|
|
|
// Helper Methods
|
|
public function updateNumeroUnita(): void
|
|
{
|
|
$count = $this->unitaImmobiliari()->count();
|
|
$this->update(['numero_unita' => $count]);
|
|
}
|
|
|
|
public function getGestioneAttiva(): ?Gestione
|
|
{
|
|
return $this->gestioni()
|
|
->where('anno_gestione', now()->year)
|
|
->where('is_active', true)
|
|
->first();
|
|
}
|
|
|
|
public function hasGestioneAttiva(): bool
|
|
{
|
|
return $this->getGestioneAttiva() !== null;
|
|
}
|
|
|
|
public function canDelete(): bool
|
|
{
|
|
return $this->unitaImmobiliari()->count() === 0 &&
|
|
$this->gestioni()->count() === 0;
|
|
}
|
|
|
|
public function getStatistiche(): array
|
|
{
|
|
return [
|
|
'numero_unita' => $this->numero_unita,
|
|
'gestioni_totali' => $this->gestioni()->count(),
|
|
'gestioni_attive' => $this->gestioni()->where('is_active', true)->count(),
|
|
'documenti_totali' => $this->documenti()->count(),
|
|
'soggetti_coinvolti' => $this->soggetti()->count(),
|
|
];
|
|
}
|
|
|
|
// Observer Events
|
|
protected static function boot(): void
|
|
{
|
|
parent::boot();
|
|
|
|
static::creating(function ($stabile) {
|
|
// Assegna automaticamente l'amministratore corrente se non specificato
|
|
if (!$stabile->amministratore_id && auth()->check()) {
|
|
$stabile->amministratore_id = auth()->user()->amministratore_id;
|
|
}
|
|
});
|
|
|
|
static::saved(function ($stabile) {
|
|
// Aggiorna conteggio unità dopo salvataggio
|
|
$stabile->updateNumeroUnita();
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🌱 **SEEDER DATI DEMO**
|
|
|
|
### **File**: `database/seeders/StabiliSeeder.php`
|
|
|
|
```php
|
|
<?php
|
|
|
|
namespace Database\Seeders;
|
|
|
|
use Illuminate\Database\Seeder;
|
|
use App\Models\Stabile;
|
|
use App\Models\Amministratore;
|
|
use App\Models\ComuneItaliano;
|
|
|
|
class StabiliSeeder extends Seeder
|
|
{
|
|
public function run(): void
|
|
{
|
|
$amministratori = Amministratore::all();
|
|
|
|
// Trova alcuni comuni per i test
|
|
$milano = ComuneItaliano::where('denominazione', 'Milano')->first();
|
|
$roma = ComuneItaliano::where('denominazione', 'Roma')->first();
|
|
$torino = ComuneItaliano::where('denominazione', 'Torino')->first();
|
|
|
|
foreach ($amministratori as $admin) {
|
|
// Stabile 1 - Condominio grande
|
|
Stabile::create([
|
|
'amministratore_id' => $admin->id,
|
|
'denominazione' => 'Condominio Bella Vista',
|
|
'codice_interno' => 'BV001',
|
|
'indirizzo' => 'Via Roma',
|
|
'numero_civico' => '123',
|
|
'cap' => $admin->id === 1 ? '20100' : ($admin->id === 2 ? '00100' : '10100'),
|
|
'comune_id' => $admin->id === 1 ? $milano?->id : ($admin->id === 2 ? $roma?->id : $torino?->id),
|
|
'provincia' => $admin->id === 1 ? 'MI' : ($admin->id === 2 ? 'RM' : 'TO'),
|
|
'regione' => $admin->id === 1 ? 'Lombardia' : ($admin->id === 2 ? 'Lazio' : 'Piemonte'),
|
|
'foglio' => '123',
|
|
'particella' => '456',
|
|
'categoria_catastale' => 'A/2',
|
|
'classe' => '3',
|
|
'rendita_catastale' => 15000.00,
|
|
'anno_costruzione' => 1985,
|
|
'numero_piani' => 5,
|
|
'ascensore' => true,
|
|
'riscaldamento_centralizzato' => true,
|
|
'tipo_edificio' => 'condominio',
|
|
'data_nomina_amministratore' => now()->subMonths(6),
|
|
'data_scadenza_mandato' => now()->addMonths(6),
|
|
'periodicita_assemblea' => 'annuale',
|
|
'usa_millesimi' => true,
|
|
'is_active' => true,
|
|
]);
|
|
|
|
// Stabile 2 - Villetta
|
|
Stabile::create([
|
|
'amministratore_id' => $admin->id,
|
|
'denominazione' => 'Villa dei Fiori',
|
|
'codice_interno' => 'VF001',
|
|
'indirizzo' => 'Via Dante Alighieri',
|
|
'numero_civico' => '45',
|
|
'cap' => $admin->id === 1 ? '20100' : ($admin->id === 2 ? '00100' : '10100'),
|
|
'comune_id' => $admin->id === 1 ? $milano?->id : ($admin->id === 2 ? $roma?->id : $torino?->id),
|
|
'provincia' => $admin->id === 1 ? 'MI' : ($admin->id === 2 ? 'RM' : 'TO'),
|
|
'regione' => $admin->id === 1 ? 'Lombardia' : ($admin->id === 2 ? 'Lazio' : 'Piemonte'),
|
|
'foglio' => '789',
|
|
'particella' => '012',
|
|
'categoria_catastale' => 'A/7',
|
|
'classe' => '4',
|
|
'rendita_catastale' => 8000.00,
|
|
'anno_costruzione' => 2000,
|
|
'numero_piani' => 2,
|
|
'ascensore' => false,
|
|
'riscaldamento_centralizzato' => false,
|
|
'tipo_edificio' => 'villetta',
|
|
'data_nomina_amministratore' => now()->subYear(),
|
|
'data_scadenza_mandato' => now()->addYear(),
|
|
'periodicita_assemblea' => 'annuale',
|
|
'usa_millesimi' => false,
|
|
'is_active' => true,
|
|
]);
|
|
|
|
// Stabile 3 - Complesso residenziale
|
|
if ($admin->piano_abbonamento !== 'base') {
|
|
Stabile::create([
|
|
'amministratore_id' => $admin->id,
|
|
'denominazione' => 'Residenza Park View',
|
|
'codice_interno' => 'PV001',
|
|
'indirizzo' => 'Viale Europa',
|
|
'numero_civico' => '200',
|
|
'scala' => 'A-B-C',
|
|
'cap' => $admin->id === 1 ? '20100' : ($admin->id === 2 ? '00100' : '10100'),
|
|
'comune_id' => $admin->id === 1 ? $milano?->id : ($admin->id === 2 ? $roma?->id : $torino?->id),
|
|
'provincia' => $admin->id === 1 ? 'MI' : ($admin->id === 2 ? 'RM' : 'TO'),
|
|
'regione' => $admin->id === 1 ? 'Lombardia' : ($admin->id === 2 ? 'Lazio' : 'Piemonte'),
|
|
'anno_costruzione' => 2010,
|
|
'numero_piani' => 8,
|
|
'ascensore' => true,
|
|
'riscaldamento_centralizzato' => true,
|
|
'tipo_edificio' => 'complesso',
|
|
'codice_fiscale_condominio' => '80123456789',
|
|
'data_nomina_amministratore' => now()->subMonths(3),
|
|
'data_scadenza_mandato' => now()->addMonths(9),
|
|
'periodicita_assemblea' => 'annuale',
|
|
'usa_millesimi' => true,
|
|
'configurazioni' => [
|
|
'portierato' => true,
|
|
'videosorveglianza' => true,
|
|
'piscina' => true,
|
|
'palestra' => false,
|
|
],
|
|
'is_active' => true,
|
|
]);
|
|
}
|
|
}
|
|
|
|
$totalStabili = Stabile::count();
|
|
$this->command->info("✅ Creati {$totalStabili} stabili per tutti gli amministratori");
|
|
|
|
// Mostra riassunto per amministratore
|
|
foreach ($amministratori as $admin) {
|
|
$count = $admin->stabili()->count();
|
|
$this->command->info("Admin {$admin->codice_univoco}: {$count} stabili");
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔍 **QUERY PATTERNS**
|
|
|
|
### **Query Base per Amministratore**:
|
|
```php
|
|
// Controller - Lista stabili dell'amministratore corrente
|
|
public function index()
|
|
{
|
|
$stabili = Stabile::with(['comune', 'unitaImmobiliari'])
|
|
->active()
|
|
->orderBy('denominazione')
|
|
->paginate(20);
|
|
|
|
return view('stabili.index', compact('stabili'));
|
|
}
|
|
|
|
// Query con filtri
|
|
public function search(Request $request)
|
|
{
|
|
$query = Stabile::query();
|
|
|
|
if ($request->filled('denominazione')) {
|
|
$query->where('denominazione', 'like', "%{$request->denominazione}%");
|
|
}
|
|
|
|
if ($request->filled('provincia')) {
|
|
$query->where('provincia', $request->provincia);
|
|
}
|
|
|
|
if ($request->filled('tipo_edificio')) {
|
|
$query->byTipo($request->tipo_edificio);
|
|
}
|
|
|
|
$stabili = $query->with('comune')->paginate(20);
|
|
|
|
return view('stabili.index', compact('stabili'));
|
|
}
|
|
```
|
|
|
|
### **Statistiche per Dashboard**:
|
|
```php
|
|
// Controller Dashboard
|
|
public function dashboard()
|
|
{
|
|
$amministratore = auth()->user()->amministratore;
|
|
|
|
$stats = [
|
|
'stabili_totali' => $amministratore->stabili()->count(),
|
|
'stabili_attivi' => $amministratore->stabili()->active()->count(),
|
|
'unita_totali' => $amministratore->stabili()
|
|
->withCount('unitaImmobiliari')
|
|
->get()
|
|
->sum('unita_immobiliari_count'),
|
|
'mandati_in_scadenza' => $amministratore->stabili()
|
|
->whereDate('data_scadenza_mandato', '<=', now()->addDays(30))
|
|
->count(),
|
|
];
|
|
|
|
return view('dashboard', compact('stats'));
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🎛️ **FORM VALIDATION**
|
|
|
|
### **File**: `app/Http/Requests/StabileRequest.php`
|
|
|
|
```php
|
|
<?php
|
|
|
|
namespace App\Http\Requests;
|
|
|
|
use Illuminate\Foundation\Http\FormRequest;
|
|
use Illuminate\Validation\Rule;
|
|
|
|
class StabileRequest extends FormRequest
|
|
{
|
|
public function authorize(): bool
|
|
{
|
|
return auth()->check();
|
|
}
|
|
|
|
public function rules(): array
|
|
{
|
|
$stabileId = $this->route('stabile')?->id;
|
|
|
|
return [
|
|
'denominazione' => 'required|string|max:255',
|
|
'codice_interno' => [
|
|
'nullable',
|
|
'string',
|
|
'max:50',
|
|
Rule::unique('stabili')
|
|
->where('amministratore_id', auth()->user()->amministratore_id)
|
|
->ignore($stabileId)
|
|
],
|
|
'indirizzo' => 'required|string|max:255',
|
|
'numero_civico' => 'nullable|string|max:20',
|
|
'cap' => 'required|string|size:5',
|
|
'provincia' => 'required|string|size:2',
|
|
'comune_id' => 'nullable|exists:comuni_italiani,id',
|
|
'tipo_edificio' => 'required|in:condominio,villetta,complesso,altro',
|
|
'anno_costruzione' => 'nullable|integer|min:1800|max:' . (date('Y') + 5),
|
|
'numero_piani' => 'nullable|integer|min:1|max:100',
|
|
'ascensore' => 'boolean',
|
|
'riscaldamento_centralizzato' => 'boolean',
|
|
'data_nomina_amministratore' => 'nullable|date',
|
|
'data_scadenza_mandato' => 'nullable|date|after:data_nomina_amministratore',
|
|
'codice_fiscale_condominio' => 'nullable|string|size:16',
|
|
'partita_iva_condominio' => 'nullable|string|size:11',
|
|
'rendita_catastale' => 'nullable|numeric|min:0',
|
|
];
|
|
}
|
|
|
|
public function messages(): array
|
|
{
|
|
return [
|
|
'denominazione.required' => 'La denominazione è obbligatoria.',
|
|
'indirizzo.required' => 'L\'indirizzo è obbligatorio.',
|
|
'cap.required' => 'Il CAP è obbligatorio.',
|
|
'cap.size' => 'Il CAP deve essere di 5 cifre.',
|
|
'provincia.required' => 'La provincia è obbligatoria.',
|
|
'codice_interno.unique' => 'Questo codice interno è già utilizzato per un altro stabile.',
|
|
'data_scadenza_mandato.after' => 'La data scadenza deve essere successiva alla data nomina.',
|
|
];
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🎯 **UTILIZZO PATTERN**
|
|
|
|
### **Nel Controller**:
|
|
```php
|
|
// Sempre filtrato per amministratore corrente grazie al Global Scope
|
|
$stabili = Stabile::all(); // Solo stabili dell'amministratore loggato
|
|
|
|
// Query specifiche
|
|
$condomini = Stabile::byTipo('condominio')->get();
|
|
$stabiliMilano = Stabile::byProvincia('MI')->get();
|
|
$conAscensore = Stabile::conAscensore()->get();
|
|
```
|
|
|
|
### **Nei Blade Templates**:
|
|
```blade
|
|
{{-- Lista stabili --}}
|
|
@foreach($stabili as $stabile)
|
|
<div class="card">
|
|
<h3>{{ $stabile->denominazione }}</h3>
|
|
<p>{{ $stabile->indirizzo_formattato }}</p>
|
|
<span class="badge">{{ $stabile->numero_unita }} unità</span>
|
|
|
|
@if($stabile->mandato_scaduto)
|
|
<span class="badge badge-danger">Mandato scaduto</span>
|
|
@elseif($stabile->giorni_alla_scadenza <= 30)
|
|
<span class="badge badge-warning">Scade tra {{ $stabile->giorni_alla_scadenza }} giorni</span>
|
|
@endif
|
|
</div>
|
|
@endforeach
|
|
```
|
|
|
|
---
|
|
|
|
**🎯 TABELLA STABILI DEFINITA**
|
|
**Con isolamento per amministratore, dati catastali completi e gestione mandati**
|
|
|
|
**📖 Prossimo: `gestioni.md` per collegare i periodi amministrativi agli stabili**
|