netgescon-day0/app/Filament/Pages/Contabilita/RiscossioneAggregata.php

129 lines
5.2 KiB
PHP

<?php
namespace App\Filament\Pages\Contabilita;
use App\Models\User;
use App\Support\StabileContext;
use BackedEnum;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema as DbSchema;
use UnitEnum;
class RiscossioneAggregata extends Page
{
protected static ?string $navigationLabel = 'Riscossione (aggregata)';
protected static ?string $title = 'Riscossione aggregata';
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-document-text';
protected static UnitEnum|string|null $navigationGroup = 'Stabile';
protected static ?int $navigationSort = 46;
protected static ?string $slug = 'contabilita/riscossione-aggregata';
protected string $view = 'filament.pages.contabilita.riscossione-aggregata';
/** @var array<int, array<string, mixed>> */
public array $condomini = [];
/** @var array<int, array<string, mixed>> */
public array $inquilini = [];
public static function canAccess(): bool
{
$user = Auth::user();
return $user instanceof User
&& $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']);
}
public function mount(): void
{
$user = Auth::user();
if (! $user instanceof User) {
abort(403);
}
$stabileId = StabileContext::resolveActiveStabileId($user);
if (! $stabileId) {
Notification::make()
->title('Stabile non selezionato')
->body('Seleziona uno stabile per consultare la riscossione aggregata.')
->warning()
->send();
return;
}
if (! DbSchema::hasTable('rate_emesse')) {
return;
}
// Foglio riscossione: aggrega per soggetto, mantenendo la distinzione C/I in base alla presenza di un diritto su quella unità.
$proprietaSub = DB::table('proprieta')
->selectRaw('unita_immobiliare_id, soggetto_id, MAX(id) as proprieta_match_id')
->groupBy('unita_immobiliare_id', 'soggetto_id');
$rows = DB::table('rate_emesse as r')
->join('unita_immobiliari as u', 'u.id', '=', 'r.unita_immobiliare_id')
->join('soggetti as s', 's.id', '=', 'r.soggetto_responsabile_id')
->leftJoinSub($proprietaSub, 'p', function ($join) {
$join->on('p.unita_immobiliare_id', '=', 'r.unita_immobiliare_id')
->on('p.soggetto_id', '=', 'r.soggetto_responsabile_id');
})
->where('u.stabile_id', (int) $stabileId)
->selectRaw('r.soggetto_responsabile_id as soggetto_id')
// max(p.id) serve solo a derivare il tipo C/I in modo compatibile con ONLY_FULL_GROUP_BY.
->selectRaw('MAX(p.proprieta_match_id) as proprieta_match_id')
->selectRaw('MAX(s.ragione_sociale) as ragione_sociale')
->selectRaw('MAX(s.nome) as nome')
->selectRaw('MAX(s.cognome) as cognome')
->selectRaw('MAX(s.codice_fiscale) as codice_fiscale')
->selectRaw('COUNT(DISTINCT r.numero_rata_progressivo) as n_avvisi')
->selectRaw('COUNT(*) as n_righe')
->selectRaw('COUNT(DISTINCT r.unita_immobiliare_id) as n_unita')
->selectRaw('COALESCE(SUM(r.importo_addebitato_soggetto), 0) as totale_addebitato')
->selectRaw('COALESCE(SUM(r.importo_pagato), 0) as totale_pagato')
->groupBy('r.soggetto_responsabile_id')
->orderByDesc(DB::raw('COALESCE(SUM(r.importo_addebitato_soggetto), 0) - COALESCE(SUM(r.importo_pagato), 0)'))
->limit(2000)
->get();
$mapped = $rows
->map(function ($r): array {
$addebitato = (float) ($r->totale_addebitato ?? 0);
$pagato = (float) ($r->totale_pagato ?? 0);
$residuo = $addebitato - $pagato;
$ragione = trim((string) ($r->ragione_sociale ?? ''));
$nome = trim((string) ($r->nome ?? ''));
$cognome = trim((string) ($r->cognome ?? ''));
$full = trim($nome . ' ' . $cognome);
$nominativo = $ragione !== '' ? $ragione : ($full !== '' ? $full : ('Soggetto #' . (int) ($r->soggetto_id ?? 0)));
$tipo = empty($r->proprieta_match_id) ? 'I' : 'C';
return [
'tipo' => $tipo,
'soggetto_id' => (int) ($r->soggetto_id ?? 0),
'nominativo' => $nominativo !== '' ? $nominativo : '—',
'codice_fiscale' => (string) ($r->codice_fiscale ?? ''),
'n_avvisi' => (int) ($r->n_avvisi ?? 0),
'n_righe' => (int) ($r->n_righe ?? 0),
'n_unita' => (int) ($r->n_unita ?? 0),
'totale_addebitato' => $addebitato,
'totale_pagato' => $pagato,
'residuo' => $residuo,
];
})
->all();
$this->condomini = array_values(array_filter($mapped, fn(array $x) => ($x['tipo'] ?? 'I') === 'C'));
$this->inquilini = array_values(array_filter($mapped, fn(array $x) => ($x['tipo'] ?? 'I') !== 'C'));
}
}