netgescon-master/docs/team/project/app/Models/Assemblea.php
Pikappa2 480e7eafbd 🎯 NETGESCON - Setup iniziale repository completo
📋 Commit iniziale con:
-  Documentazione unificata in docs/
-  Codice Laravel in netgescon-laravel/
-  Script automazione in scripts/
-  Configurazione sync rsync
-  Struttura organizzata e pulita

🔄 Versione: 2025.07.19-1644
🎯 Sistema pronto per Git distribuito
2025-07-19 16:44:47 +02:00

266 lines
7.3 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Assemblea extends Model
{
use HasFactory;
protected $table = 'assemblee';
protected $fillable = [
'stabile_id',
'tipo',
'data_prima_convocazione',
'data_seconda_convocazione',
'luogo',
'note',
'stato',
'data_convocazione',
'data_svolgimento',
'creato_da_user_id',
];
protected $casts = [
'data_prima_convocazione' => 'datetime',
'data_seconda_convocazione' => 'datetime',
'data_convocazione' => 'date',
'data_svolgimento' => 'date',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
/**
* Relazione con Stabile
*/
public function stabile()
{
return $this->belongsTo(Stabile::class, 'stabile_id', 'id_stabile');
}
/**
* Relazione con Ordine del Giorno
*/
public function ordineGiorno()
{
return $this->hasMany(OrdineGiorno::class, 'assemblea_id')->orderBy('numero_punto');
}
/**
* Relazione con Convocazioni
*/
public function convocazioni()
{
return $this->hasMany(Convocazione::class, 'assemblea_id');
}
/**
* Relazione con Presenze
*/
public function presenze()
{
return $this->hasMany(PresenzaAssemblea::class, 'assemblea_id');
}
/**
* Relazione con Verbale
*/
public function verbale()
{
return $this->hasOne(Verbale::class, 'assemblea_id');
}
/**
* Relazione con Documenti
*/
public function documenti()
{
return $this->hasMany(DocumentoAssemblea::class, 'assemblea_id');
}
/**
* Relazione con User creatore
*/
public function creatoDa()
{
return $this->belongsTo(User::class, 'creato_da_user_id');
}
/**
* Scope per stato
*/
public function scopeStato($query, $stato)
{
return $query->where('stato', $stato);
}
/**
* Scope per tipo
*/
public function scopeTipo($query, $tipo)
{
return $query->where('tipo', $tipo);
}
/**
* Invia convocazioni massive
*/
public function inviaConvocazioni($canali = ['email'], $userId)
{
$unitaImmobiliari = $this->stabile->unitaImmobiliari()->with('proprieta.soggetto')->get();
$convocazioniInviate = 0;
foreach ($unitaImmobiliari as $unita) {
foreach ($unita->proprieta as $proprieta) {
$soggetto = $proprieta->soggetto;
foreach ($canali as $canale) {
if ($this->verificaCanaleDisponibile($soggetto, $canale)) {
$convocazione = $this->creaConvocazione($soggetto, $unita, $canale);
if ($this->inviaConvocazione($convocazione)) {
$convocazioniInviate++;
// Registra nel protocollo
$this->registraProtocollo($convocazione, $userId);
}
}
}
}
}
// Aggiorna stato assemblea
$this->update([
'stato' => 'convocata',
'data_convocazione' => now(),
]);
return $convocazioniInviate;
}
/**
* Verifica se il canale è disponibile per il soggetto
*/
private function verificaCanaleDisponibile($soggetto, $canale)
{
switch ($canale) {
case 'email':
return !empty($soggetto->email);
case 'pec':
return !empty($soggetto->pec);
case 'whatsapp':
case 'telegram':
return !empty($soggetto->telefono);
default:
return true;
}
}
/**
* Crea record convocazione
*/
private function creaConvocazione($soggetto, $unita, $canale)
{
return Convocazione::create([
'assemblea_id' => $this->id,
'soggetto_id' => $soggetto->id_soggetto,
'unita_immobiliare_id' => $unita->id_unita,
'canale_invio' => $canale,
'data_invio' => now(),
'esito_invio' => 'inviato',
]);
}
/**
* Invia singola convocazione
*/
private function inviaConvocazione($convocazione)
{
// Implementazione invio basata sul canale
// Qui si integrerebbe con servizi email, SMS, etc.
// Simula invio riuscito
$convocazione->update([
'esito_invio' => 'consegnato',
'riferimento_invio' => 'REF-' . time(),
]);
return true;
}
/**
* Registra comunicazione nel protocollo
*/
private function registraProtocollo($convocazione, $userId)
{
$numeroProtocollo = $this->generaNumeroProtocollo();
RegistroProtocollo::create([
'numero_protocollo' => $numeroProtocollo,
'tipo_comunicazione' => 'convocazione',
'assemblea_id' => $this->id,
'soggetto_destinatario_id' => $convocazione->soggetto_id,
'oggetto' => "Convocazione Assemblea {$this->tipo} - {$this->data_prima_convocazione->format('d/m/Y')}",
'canale' => $convocazione->canale_invio,
'data_invio' => $convocazione->data_invio,
'esito' => $convocazione->esito_invio,
'riferimento_esterno' => $convocazione->riferimento_invio,
'creato_da_user_id' => $userId,
]);
}
/**
* Genera numero protocollo progressivo
*/
private function generaNumeroProtocollo()
{
$anno = date('Y');
$ultimoProtocollo = RegistroProtocollo::whereYear('created_at', $anno)
->orderBy('numero_protocollo', 'desc')
->first();
if ($ultimoProtocollo) {
$numero = intval(substr($ultimoProtocollo->numero_protocollo, -4)) + 1;
} else {
$numero = 1;
}
return 'PROT/' . $anno . '/' . str_pad($numero, 4, '0', STR_PAD_LEFT);
}
/**
* Calcola quorum assemblea
*/
public function calcolaQuorum()
{
$totaleMillesimi = $this->stabile->unitaImmobiliari()->sum('millesimi_proprieta');
$millesimiPresenti = $this->presenze()->sum('millesimi_rappresentati');
return [
'totale_millesimi' => $totaleMillesimi,
'millesimi_presenti' => $millesimiPresenti,
'percentuale_presenza' => $totaleMillesimi > 0 ? ($millesimiPresenti / $totaleMillesimi) * 100 : 0,
'quorum_raggiunto' => $millesimiPresenti >= ($totaleMillesimi / 2),
];
}
/**
* Genera report presenze
*/
public function generaReportPresenze()
{
$presenze = $this->presenze()->with(['soggetto', 'unitaImmobiliare'])->get();
$quorum = $this->calcolaQuorum();
return [
'quorum' => $quorum,
'presenze' => $presenze,
'totale_presenti' => $presenze->where('tipo_presenza', 'presente')->count(),
'totale_delegati' => $presenze->where('tipo_presenza', 'delegato')->count(),
'totale_assenti' => $this->stabile->unitaImmobiliari()->count() - $presenze->count(),
];
}
}