PHASE 2 COMPLETED: MILLÉSIMAL TABLES ✅ MODELS ENHANCED: - TabellaMillesimale: Advanced methods for balance calculation, quota management - DettaglioTabellaMillesimale: Validation, percentage calculation, expense quota - Fixed Eloquent relationships with correct foreign keys (id instead of legacy keys) FEATURES IMPLEMENTED: ✅ Automatic balance verification (totale_millesimi = 1000) ✅ Quota calculation for expense distribution ✅ Standard table types (proprietà_generale, scale, ascensore, etc.) ✅ Validation for positive millesimi values ✅ Automatic code generation for AnagraficaCondominiale (ANA prefix) ✅ Complete relationship testing (Amministratore→Stabili→Unità→Millesimi) TESTING COMPLETED: ✅ Tabella millesimale creation and balance verification ✅ Unità immobiliari creation with correct field names ✅ Millesimi assignment and calculation (470.5882 + 529.4118 = 1000.0000) ✅ Expense quota calculation (€470.59 + €529.41 = €1000.00) ✅ Advanced features: riassunto, percentages, standard types DATABASE STATUS: - 1 Tabella Millesimale: 'Proprietà Generale' (balanced: SI) - 2 Unità Immobiliari: Interno 1 & 2 with correct millesimi - All relationships operational and tested READY FOR PHASE 3: EXPENSE CATEGORIES & VOICE MANAGEMENT
274 lines
6.9 KiB
PHP
274 lines
6.9 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
class AnagraficaCondominiale extends Model
|
|
{
|
|
use HasFactory, SoftDeletes;
|
|
|
|
protected $table = 'anagrafica_condominiale';
|
|
|
|
protected $fillable = [
|
|
'amministratore_id',
|
|
'codice_univoco',
|
|
'tipo_soggetto',
|
|
'cognome',
|
|
'nome',
|
|
'denominazione',
|
|
'codice_fiscale',
|
|
'partita_iva',
|
|
'data_nascita',
|
|
'luogo_nascita',
|
|
'provincia_nascita',
|
|
'sesso',
|
|
'indirizzo_residenza',
|
|
'cap_residenza',
|
|
'citta_residenza',
|
|
'provincia_residenza',
|
|
'nazione_residenza',
|
|
'domicilio_diverso',
|
|
'indirizzo_domicilio',
|
|
'cap_domicilio',
|
|
'citta_domicilio',
|
|
'provincia_domicilio',
|
|
'nazione_domicilio',
|
|
'stato',
|
|
'note',
|
|
'google_contact_id',
|
|
'ultima_sincronizzazione_google'
|
|
];
|
|
|
|
/**
|
|
* Boot del modello per generazione automatica codice
|
|
*/
|
|
protected static function boot()
|
|
{
|
|
parent::boot();
|
|
|
|
static::creating(function ($model) {
|
|
if (empty($model->codice_univoco)) {
|
|
$model->codice_univoco = self::generateUniqueCode();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Genera un codice univoco di 8 caratteri con prefisso ANA
|
|
*/
|
|
private static function generateUniqueCode()
|
|
{
|
|
do {
|
|
$code = 'ANA' . strtoupper(substr(str_shuffle('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 5));
|
|
} while (self::where('codice_univoco', $code)->exists());
|
|
|
|
return $code;
|
|
}
|
|
|
|
protected $casts = [
|
|
'data_nascita' => 'date',
|
|
'ultima_sincronizzazione_google' => 'datetime',
|
|
'domicilio_diverso' => 'boolean',
|
|
'created_at' => 'datetime',
|
|
'updated_at' => 'datetime'
|
|
];
|
|
|
|
/**
|
|
* Relazione con i contatti
|
|
*/
|
|
public function contatti()
|
|
{
|
|
return $this->hasMany(ContattoAnagrafica::class);
|
|
}
|
|
|
|
/**
|
|
* Relazione con i diritti reali
|
|
*/
|
|
public function dirittiReali()
|
|
{
|
|
return $this->hasMany(DirittoReale::class);
|
|
}
|
|
|
|
/**
|
|
* Relazione con i contratti di locazione
|
|
*/
|
|
public function contrattiLocazione()
|
|
{
|
|
return $this->hasMany(ContrattoLocazione::class);
|
|
}
|
|
|
|
/**
|
|
* Scope per anagrafica attiva
|
|
*/
|
|
public function scopeAttivi($query)
|
|
{
|
|
return $query->where('stato', 'attivo');
|
|
}
|
|
|
|
/**
|
|
* Scope per tipo soggetto
|
|
*/
|
|
public function scopeByTipo($query, $tipo)
|
|
{
|
|
return $query->where('tipo_soggetto', $tipo);
|
|
}
|
|
|
|
/**
|
|
* Scope per persone fisiche
|
|
*/
|
|
public function scopePersoneFisiche($query)
|
|
{
|
|
return $query->where('tipo_soggetto', 'persona_fisica');
|
|
}
|
|
|
|
/**
|
|
* Scope per persone giuridiche
|
|
*/
|
|
public function scopePersoneGiuridiche($query)
|
|
{
|
|
return $query->where('tipo_soggetto', 'persona_giuridica');
|
|
}
|
|
|
|
/**
|
|
* Accessor per il nome completo
|
|
*/
|
|
public function getNomeCompletoAttribute()
|
|
{
|
|
if ($this->tipo_soggetto === 'persona_giuridica') {
|
|
return $this->denominazione;
|
|
}
|
|
|
|
return trim($this->nome . ' ' . $this->cognome);
|
|
}
|
|
|
|
/**
|
|
* Accessor per codice anagrafica (compatibilità)
|
|
*/
|
|
public function getCodiceAnagraficaAttribute()
|
|
{
|
|
return $this->codice_univoco;
|
|
}
|
|
|
|
/**
|
|
* Accessor per l'indirizzo completo di residenza
|
|
*/
|
|
public function getIndirizzoResidenzaCompletoAttribute()
|
|
{
|
|
$indirizzo = $this->indirizzo_residenza;
|
|
if ($this->cap_residenza) {
|
|
$indirizzo .= ', ' . $this->cap_residenza;
|
|
}
|
|
if ($this->citta_residenza) {
|
|
$indirizzo .= ' ' . $this->citta_residenza;
|
|
}
|
|
if ($this->provincia_residenza) {
|
|
$indirizzo .= ' (' . $this->provincia_residenza . ')';
|
|
}
|
|
return $indirizzo;
|
|
}
|
|
|
|
/**
|
|
* Accessor per l'indirizzo completo di domicilio
|
|
*/
|
|
public function getIndirizzoDomicilioCompletoAttribute()
|
|
{
|
|
if (!$this->domicilio_diverso) {
|
|
return $this->indirizzo_residenza_completo;
|
|
}
|
|
|
|
$indirizzo = $this->indirizzo_domicilio;
|
|
if ($this->cap_domicilio) {
|
|
$indirizzo .= ', ' . $this->cap_domicilio;
|
|
}
|
|
if ($this->citta_domicilio) {
|
|
$indirizzo .= ' ' . $this->citta_domicilio;
|
|
}
|
|
if ($this->provincia_domicilio) {
|
|
$indirizzo .= ' (' . $this->provincia_domicilio . ')';
|
|
}
|
|
return $indirizzo;
|
|
}
|
|
|
|
/**
|
|
* Metodo per ottenere tutti i contatti per tipo (placeholder - table doesn't exist yet)
|
|
*/
|
|
public function getContattiByTipo($tipo)
|
|
{
|
|
// TODO: Implementare quando sarà creata la tabella contatti
|
|
return collect();
|
|
}
|
|
|
|
/**
|
|
* Metodo per verificare se è attivo
|
|
*/
|
|
public function isAttivo()
|
|
{
|
|
return $this->stato === 'attivo';
|
|
}
|
|
|
|
/**
|
|
* Metodo per ottenere le unità immobiliari di proprietà
|
|
*/
|
|
public function getUnitaImmobiliariProprietario()
|
|
{
|
|
return UnitaImmobiliare::whereHas('dirittiReali', function ($query) {
|
|
$query->where('anagrafica_condominiale_id', $this->id)
|
|
->where('tipo_diritto', 'proprieta')
|
|
->whereNull('data_fine');
|
|
})->get();
|
|
}
|
|
|
|
/**
|
|
* Metodo per ottenere le unità immobiliari in locazione
|
|
*/
|
|
public function getUnitaImmobiliariInquilino()
|
|
{
|
|
return UnitaImmobiliare::whereHas('contrattiLocazione', function ($query) {
|
|
$query->where('anagrafica_condominiale_id', $this->id)
|
|
->where('stato', 'attivo')
|
|
->whereDate('data_inizio', '<=', now())
|
|
->where(function ($q) {
|
|
$q->whereNull('data_fine')
|
|
->orWhereDate('data_fine', '>=', now());
|
|
});
|
|
})->get();
|
|
}
|
|
|
|
/**
|
|
* Metodo per verificare se è un proprietario
|
|
*/
|
|
public function isProprietario()
|
|
{
|
|
return $this->dirittiReali()
|
|
->where('tipo_diritto', 'proprieta')
|
|
->whereNull('data_fine')
|
|
->exists();
|
|
}
|
|
|
|
/**
|
|
* Metodo per verificare se è un inquilino
|
|
*/
|
|
public function isInquilino()
|
|
{
|
|
return $this->contrattiLocazione()
|
|
->where('stato', 'attivo')
|
|
->whereDate('data_inizio', '<=', now())
|
|
->where(function ($query) {
|
|
$query->whereNull('data_fine')
|
|
->orWhereDate('data_fine', '>=', now());
|
|
})
|
|
->exists();
|
|
}
|
|
|
|
/**
|
|
* Relazione con amministratore
|
|
*/
|
|
public function amministratore()
|
|
{
|
|
return $this->belongsTo(Amministratore::class);
|
|
}
|
|
}
|