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
164 lines
4.0 KiB
PHP
164 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
class ContattoAnagrafica extends Model
|
|
{
|
|
use HasFactory, SoftDeletes;
|
|
|
|
protected $table = 'contatti_anagrafica';
|
|
|
|
protected $fillable = [
|
|
'anagrafica_id',
|
|
'tipo_contatto',
|
|
'valore',
|
|
'etichetta',
|
|
'principale',
|
|
'attivo',
|
|
'verificato',
|
|
'data_verifica',
|
|
'usa_per_convocazioni',
|
|
'usa_per_comunicazioni',
|
|
'usa_per_emergenze',
|
|
'usa_per_solleciti',
|
|
'note'
|
|
];
|
|
|
|
protected $casts = [
|
|
'principale' => 'boolean',
|
|
'attivo' => 'boolean',
|
|
'verificato' => 'boolean',
|
|
'data_verifica' => 'datetime',
|
|
'usa_per_convocazioni' => 'boolean',
|
|
'usa_per_comunicazioni' => 'boolean',
|
|
'usa_per_emergenze' => 'boolean',
|
|
'usa_per_solleciti' => 'boolean'
|
|
];
|
|
|
|
/**
|
|
* Relazione con l'anagrafica condominiale
|
|
*/
|
|
public function anagraficaCondominiale()
|
|
{
|
|
return $this->belongsTo(AnagraficaCondominiale::class, 'anagrafica_id');
|
|
}
|
|
|
|
/**
|
|
* Scope per contatti attivi
|
|
*/
|
|
public function scopeAttivi($query)
|
|
{
|
|
return $query->where('attivo', true);
|
|
}
|
|
|
|
/**
|
|
* Scope per contatti principali
|
|
*/
|
|
public function scopePrincipali($query)
|
|
{
|
|
return $query->where('principale', true);
|
|
}
|
|
|
|
/**
|
|
* Scope per tipo di contatto
|
|
*/
|
|
public function scopeByTipo($query, $tipo)
|
|
{
|
|
return $query->where('tipo_contatto', $tipo);
|
|
}
|
|
|
|
/**
|
|
* Scope per telefoni
|
|
*/
|
|
public function scopeTelefoni($query)
|
|
{
|
|
return $query->where('tipo_contatto', 'telefono');
|
|
}
|
|
|
|
/**
|
|
* Scope per email
|
|
*/
|
|
public function scopeEmail($query)
|
|
{
|
|
return $query->where('tipo_contatto', 'email');
|
|
}
|
|
|
|
/**
|
|
* Scope per fax
|
|
*/
|
|
public function scopeFax($query)
|
|
{
|
|
return $query->where('tipo_contatto', 'fax');
|
|
}
|
|
|
|
/**
|
|
* Accessor per il valore formattato
|
|
*/
|
|
public function getValoreFormattatoAttribute()
|
|
{
|
|
switch ($this->tipo_contatto) {
|
|
case 'telefono':
|
|
case 'cellulare':
|
|
case 'fax':
|
|
// Formatta numero telefonico
|
|
$numero = preg_replace('/[^0-9+]/', '', $this->valore);
|
|
if (strlen($numero) === 10 && !str_starts_with($numero, '+')) {
|
|
// Numero italiano
|
|
return '+39 ' . substr($numero, 0, 3) . ' ' . substr($numero, 3, 3) . ' ' . substr($numero, 6);
|
|
}
|
|
return $numero;
|
|
case 'email':
|
|
return strtolower($this->valore);
|
|
default:
|
|
return $this->valore;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Accessor per l'icona del tipo di contatto
|
|
*/
|
|
public function getIconaAttribute()
|
|
{
|
|
return match ($this->tipo_contatto) {
|
|
'telefono' => 'phone',
|
|
'cellulare' => 'smartphone',
|
|
'email' => 'email',
|
|
'fax' => 'fax',
|
|
'sito_web' => 'web',
|
|
'social' => 'share',
|
|
default => 'contact'
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Mutator per il valore del contatto
|
|
*/
|
|
public function setValoreAttribute($value)
|
|
{
|
|
$this->attributes['valore'] = trim($value);
|
|
}
|
|
|
|
/**
|
|
* Metodo per validare il contatto
|
|
*/
|
|
public function isValid()
|
|
{
|
|
switch ($this->tipo_contatto) {
|
|
case 'email':
|
|
return filter_var($this->valore, FILTER_VALIDATE_EMAIL) !== false;
|
|
case 'telefono':
|
|
case 'cellulare':
|
|
case 'fax':
|
|
return preg_match('/^[\+]?[0-9\s\-\(\)]{6,}$/', $this->valore);
|
|
case 'sito_web':
|
|
return filter_var($this->valore, FILTER_VALIDATE_URL) !== false;
|
|
default:
|
|
return !empty($this->valore);
|
|
}
|
|
}
|
|
}
|