'date', 'pubblico' => 'boolean', 'protetto' => 'boolean', 'downloads' => 'integer', 'versione' => 'integer', 'dimensione' => 'integer', 'ultimo_accesso' => 'datetime' ]; protected $dates = [ 'data_scadenza', 'ultimo_accesso', 'created_at', 'updated_at' ]; /** * Relazione con lo stabile */ public function stabile() { return $this->belongsTo(Stabile::class, 'stabile_id', 'id'); } /** * Relazione con l'utente che ha caricato il documento */ public function caricatore() { return $this->belongsTo(User::class, 'caricato_da', 'id'); } /** * Scope: Documenti per categoria */ public function scopePerCategoria($query, $categoria) { return $query->where('categoria', $categoria); } /** * Scope: Documenti pubblici */ public function scopePubblici($query) { return $query->where('pubblico', true); } /** * Scope: Documenti in scadenza */ public function scopeInScadenza($query, $giorni = 30) { return $query->whereNotNull('data_scadenza') ->where('data_scadenza', '<=', now()->addDays($giorni)) ->where('data_scadenza', '>=', now()); } /** * Scope: Documenti scaduti */ public function scopeScaduti($query) { return $query->whereNotNull('data_scadenza') ->where('data_scadenza', '<', now()); } /** * Accessor: Dimensione formattata */ public function getDimensioneFormattataAttribute() { $bytes = $this->dimensione; if ($bytes === 0) return '0 Bytes'; $k = 1024; $sizes = ['Bytes', 'KB', 'MB', 'GB']; $i = floor(log($bytes) / log($k)); return number_format($bytes / pow($k, $i), 2) . ' ' . $sizes[$i]; } /** * Accessor: Icona del file basata sull'estensione */ public function getIconaFileAttribute() { $ext = strtolower(pathinfo($this->nome_file, PATHINFO_EXTENSION)); switch ($ext) { case 'pdf': return 'fa-file-pdf text-danger'; case 'doc': case 'docx': return 'fa-file-word text-primary'; case 'xls': case 'xlsx': return 'fa-file-excel text-success'; case 'jpg': case 'jpeg': case 'png': case 'gif': return 'fa-file-image text-info'; default: return 'fa-file text-secondary'; } } /** * Accessor: Stato scadenza */ public function getStatoScadenzaAttribute() { if (!$this->data_scadenza) { return null; } $oggi = now()->startOfDay(); $scadenza = $this->data_scadenza->startOfDay(); $diffGiorni = $oggi->diffInDays($scadenza, false); if ($diffGiorni < 0) { return ['tipo' => 'scaduto', 'giorni' => abs($diffGiorni), 'classe' => 'danger']; } elseif ($diffGiorni <= 7) { return ['tipo' => 'in_scadenza_critica', 'giorni' => $diffGiorni, 'classe' => 'danger']; } elseif ($diffGiorni <= 30) { return ['tipo' => 'in_scadenza', 'giorni' => $diffGiorni, 'classe' => 'warning']; } return ['tipo' => 'valido', 'giorni' => $diffGiorni, 'classe' => 'success']; } /** * Accessor: URL di download */ public function getUrlDownloadAttribute() { return route('admin.documenti.download', $this->id); } /** * Accessor: URL di visualizzazione */ public function getUrlViewAttribute() { return route('admin.documenti.view', $this->id); } /** * Incrementa il contatore di download */ public function incrementaDownload() { $this->increment('downloads'); $this->update(['ultimo_accesso' => now()]); } /** * Verifica se il file esiste fisicamente */ public function fileEsiste() { return Storage::exists($this->percorso_file); } /** * Elimina il file fisico dal storage */ public function eliminaFile() { if ($this->fileEsiste()) { return Storage::delete($this->percorso_file); } return true; } /** * Array di categorie disponibili */ public static function categorie() { return [ 'contratti' => 'Contratti', 'amministrativi' => 'Documenti Amministrativi', 'tecnici' => 'Documenti Tecnici', 'catastali' => 'Documenti Catastali', 'bancari' => 'Documenti Bancari', 'legali' => 'Documenti Legali', 'assemblee' => 'Verbali Assemblee', 'altri' => 'Altri' ]; } /** * Colori per le categorie */ public static function coloriCategorie() { return [ 'contratti' => 'primary', 'amministrativi' => 'info', 'tecnici' => 'warning', 'catastali' => 'success', 'bancari' => 'secondary', 'legali' => 'danger', 'assemblee' => 'dark', 'altri' => 'light' ]; } /** * Event: Eliminazione del modello */ protected static function boot() { parent::boot(); static::deleting(function ($documento) { // Elimina il file fisico quando viene eliminato il record $documento->eliminaFile(); }); } }