netgescon-master/_BACKUP_OLD_netgescon-laravel_INACTIVE/app/Models/Rata.php

382 lines
9.6 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;
/**
* Class Rata
*
* Gestisce le rate singole dei piani di rateizzazione
*
* @package App\Models
*/
class Rata extends Model
{
use HasFactory, SoftDeletes;
protected $table = 'rate';
protected $fillable = [
'codice_rata',
'piano_rateizzazione_id',
'unita_immobiliare_id',
'anagrafica_condominiale_id',
'numero_rata',
'descrizione',
'importo_rata',
'data_scadenza',
'stato',
'importo_pagato',
'importo_residuo',
'data_pagamento',
'note_pagamento',
'dettagli_pagamento',
'metodo_pagamento',
'riferimento_pagamento',
'registrato_da',
// Compatibilità con vecchia struttura
'gestione_id',
'soggetto_id',
'importo',
'tipo_rata',
'note'
];
protected $casts = [
'importo_rata' => 'decimal:2',
'importo_pagato' => 'decimal:2',
'importo_residuo' => 'decimal:2',
'data_scadenza' => 'date',
'data_pagamento' => 'date',
'dettagli_pagamento' => 'array',
'numero_rata' => 'integer',
// Compatibilità
'importo' => 'decimal:2'
];
protected $dates = [
'data_scadenza',
'data_pagamento',
'created_at',
'updated_at',
'deleted_at'
];
/**
* Boot method per generare automaticamente il codice rata
*/
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if (empty($model->codice_rata)) {
$model->codice_rata = self::generaCodiceRata();
}
// Inizializza importo_residuo se non impostato
if (is_null($model->importo_residuo)) {
$model->importo_residuo = $model->importo_rata ?? $model->importo ?? 0;
}
});
}
/**
* Genera un codice univoco per la rata
*/
public static function generaCodiceRata()
{
do {
$codice = 'RT' . strtoupper(Str::random(6));
} while (self::where('codice_rata', $codice)->exists());
return $codice;
}
/**
* Relazione con PianoRateizzazione
*/
public function pianoRateizzazione()
{
return $this->belongsTo(PianoRateizzazione::class);
}
/**
* Relazione con RipartizioneSpese
*/
public function ripartizione()
{
return $this->belongsTo(RipartizioneSpese::class, 'ripartizione_spese_id');
}
/**
* Relazione con UnitaImmobiliare
*/
public function unitaImmobiliare()
{
return $this->belongsTo(UnitaImmobiliare::class);
}
/**
* Relazione con AnagraficaCondominiale
*/
public function anagraficaCondominiale()
{
return $this->belongsTo(AnagraficaCondominiale::class);
}
/**
* Relazione con User (registrato da)
*/
public function registratoDa()
{
return $this->belongsTo(User::class, 'registrato_da');
}
// Relazioni di compatibilità con vecchia struttura
/**
* Relazione con Gestione (compatibilità)
*/
public function gestione()
{
return $this->belongsTo(Gestione::class, 'gestione_id', 'id_gestione');
}
/**
* Relazione con Soggetto (compatibilità)
*/
public function soggetto()
{
return $this->belongsTo(Soggetto::class, 'soggetto_id', 'id_soggetto');
}
/**
* Scope per stato
*/
public function scopeConStato($query, $stato)
{
return $query->where('stato', $stato);
}
/**
* Scope per rate scadute
*/
public function scopeScadute($query)
{
return $query->where('data_scadenza', '<', now()->toDateString())
->whereIn('stato', ['emessa']);
}
/**
* Scope per rate in scadenza
*/
public function scopeInScadenza($query, $giorni = 30)
{
return $query->whereBetween('data_scadenza', [now()->toDateString(), now()->addDays($giorni)->toDateString()])
->whereIn('stato', ['emessa']);
}
/**
* Scope per rate pagate
*/
public function scopePagate($query)
{
return $query->where('stato', 'pagata');
}
/**
* Scope per rate emesse
*/
public function scopeEmesse($query)
{
return $query->where('stato', 'emessa');
}
/**
* Scope per piano rateizzazione
*/
public function scopePerPiano($query, $pianoId)
{
return $query->where('piano_rateizzazione_id', $pianoId);
}
/**
* Scope per unità immobiliare
*/
public function scopePerUnita($query, $unitaId)
{
return $query->where('unita_immobiliare_id', $unitaId);
}
/**
* Metodo per registrare pagamento completo
*/
public function registraPagamento($importo, $metodo = null, $riferimento = null, $note = null, $userId = null)
{
$importoPagamento = min($importo, $this->importo_residuo);
$nuovoImportoPagato = $this->importo_pagato + $importoPagamento;
$nuovoImportoResiduo = $this->importo_rata - $nuovoImportoPagato;
$nuovoStato = $nuovoImportoResiduo <= 0 ? 'pagata' : 'parzialmente_pagata';
$this->update([
'importo_pagato' => $nuovoImportoPagato,
'importo_residuo' => $nuovoImportoResiduo,
'stato' => $nuovoStato,
'data_pagamento' => now(),
'metodo_pagamento' => $metodo,
'riferimento_pagamento' => $riferimento,
'note_pagamento' => $note,
'registrato_da' => $userId ?? auth()->id()
]);
return $this;
}
/**
* Metodo per registrare pagamento parziale
*/
public function registraPagamentoParziale($importo, $metodo = null, $riferimento = null, $note = null, $userId = null)
{
return $this->registraPagamento($importo, $metodo, $riferimento, $note, $userId);
}
/**
* Metodo per annullare la rata
*/
public function annulla($motivo = null)
{
$this->update([
'stato' => 'annullata',
'note_pagamento' => $motivo
]);
return $this;
}
/**
* Metodo per verificare se è scaduta
*/
public function isScaduta()
{
return $this->data_scadenza < now()->toDateString() &&
in_array($this->stato, ['emessa']);
}
/**
* Metodo per verificare se è in scadenza
*/
public function isInScadenza($giorni = 30)
{
$dataLimite = now()->addDays($giorni)->toDateString();
return $this->data_scadenza <= $dataLimite &&
$this->data_scadenza >= now()->toDateString() &&
in_array($this->stato, ['emessa']);
}
/**
* Metodo per aggiornare automaticamente lo stato
*/
public function aggiornaStato()
{
if ($this->stato === 'emessa' && $this->isScaduta()) {
$this->update(['stato' => 'scaduta']);
}
return $this;
}
/**
* Verifica se può essere modificata
*/
public function puoEssereModificata()
{
return in_array($this->stato, ['emessa', 'scaduta']);
}
/**
* Verifica se può essere eliminata
*/
public function puoEssereEliminata()
{
return in_array($this->stato, ['emessa', 'annullata']);
}
/**
* Accessor per importo residuo calcolato
*/
public function getImportoResiduoCalcolatoAttribute()
{
return ($this->importo_rata ?? $this->importo ?? 0) - ($this->importo_pagato ?? 0);
}
/**
* Accessor per stato formattato
*/
public function getStatoFormattatoAttribute()
{
return match ($this->stato) {
'emessa' => 'Emessa',
'pagata' => 'Pagata',
'parzialmente_pagata' => 'Parzialmente Pagata',
'scaduta' => 'Scaduta',
'annullata' => 'Annullata',
default => ucfirst($this->stato)
};
}
/**
* Accessor per metodo pagamento formattato
*/
public function getMetodoPagamentoFormattatoAttribute()
{
return match ($this->metodo_pagamento) {
'bonifico' => 'Bonifico Bancario',
'bollettino' => 'Bollettino Postale',
'contanti' => 'Contanti',
'assegno' => 'Assegno',
'pos' => 'POS/Carta',
'altro' => 'Altro',
default => $this->metodo_pagamento ? ucfirst($this->metodo_pagamento) : 'Non Specificato'
};
}
/**
* Accessor per giorni alla scadenza
*/
public function getGiorniAllaScadenzaAttribute()
{
return now()->diffInDays($this->data_scadenza, false);
}
/**
* Accessor per percentuale pagata
*/
public function getPercentualePagataAttribute()
{
$importoTotale = $this->importo_rata ?? $this->importo ?? 0;
if ($importoTotale == 0) {
return 0;
}
return round((($this->importo_pagato ?? 0) / $importoTotale) * 100, 2);
}
/**
* Accessor compatibilità con vecchia struttura
*/
public function getImportoResiduoAttribute()
{
// Se esiste la nuova colonna, usala
if (isset($this->attributes['importo_residuo'])) {
return $this->attributes['importo_residuo'];
}
// Altrimenti calcola
return $this->getImportoResiduoCalcolatoAttribute();
}
}