375 lines
13 KiB
PHP
375 lines
13 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Pages\Contabilita;
|
|
|
|
use App\Models\User;
|
|
use App\Models\Stabile;
|
|
use App\Support\StabileContext;
|
|
use BackedEnum;
|
|
use Filament\Pages\Page;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use UnitEnum;
|
|
|
|
class DebitiPagareHub extends Page
|
|
{
|
|
protected static ?string $title = 'Hub Pagamenti (Debiti da Pagare)';
|
|
|
|
protected static ?string $navigationLabel = 'Hub Pagamenti';
|
|
|
|
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-credit-card';
|
|
|
|
protected static UnitEnum|string|null $navigationGroup = 'Contabilità';
|
|
|
|
protected static ?int $navigationSort = 12;
|
|
|
|
protected static ?string $slug = 'contabilita/debiti-da-pagare';
|
|
|
|
protected string $view = 'filament.pages.contabilita.debiti-pagare-hub';
|
|
|
|
public string $activeTab = 'debiti'; // 'debiti', 'movimenti', 'stato_debiti'
|
|
|
|
public ?string $targetDate = null; // Data di riferimento per calcolo debiti residui
|
|
|
|
/** @var array<int, array{id: int, numero_documento: string, data_documento: string, totale: float, netto_da_pagare: float, fornitore_ragione_sociale: string, iban: ?string, descrizione_bonifico: string}> */
|
|
public array $debiti = [];
|
|
|
|
/** @var array<int, array{id: int, data: string, descrizione: string, importo: float, stato: string, invoice_id: ?int, invoice_number: ?string, fornitore: ?string, advice: string}> */
|
|
public array $movimenti = [];
|
|
|
|
/** @var array<int, array{id: int, numero_documento: string, data_documento: string, totale: float, netto_da_pagare: float, fornitore: string, stato_corrente: string, data_chiusura: string}> */
|
|
public array $debitiStorici = [];
|
|
|
|
public float $totaleDebitiStorici = 0.0;
|
|
|
|
public static function canAccess(): bool
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return false;
|
|
}
|
|
|
|
if ($user->hasAnyRole(['super-admin', 'admin'])) {
|
|
return true;
|
|
}
|
|
|
|
return $user->can('contabilita.prima-nota') || $user->can('contabilita.fatture-fornitori');
|
|
}
|
|
|
|
public function getActiveStabile(): ?Stabile
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return null;
|
|
}
|
|
|
|
return StabileContext::getActiveStabile($user);
|
|
}
|
|
|
|
public function mount(): void
|
|
{
|
|
$stabile = $this->getActiveStabile();
|
|
if ($stabile) {
|
|
$gestioneId = $this->resolveActiveGestioneId((int) $stabile->id);
|
|
if ($gestioneId) {
|
|
$gestione = DB::table('gestioni_contabili')->where('id', $gestioneId)->first();
|
|
if ($gestione && $gestione->data_fine) {
|
|
$this->targetDate = $gestione->data_fine;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! $this->targetDate) {
|
|
$this->targetDate = now()->format('Y-12-31');
|
|
}
|
|
|
|
$this->loadTabContent();
|
|
}
|
|
|
|
public function setTab(string $tab): void
|
|
{
|
|
$this->activeTab = $tab;
|
|
$this->loadTabContent();
|
|
}
|
|
|
|
public function updatedTargetDate(): void
|
|
{
|
|
$this->loadTabContent();
|
|
}
|
|
|
|
public function loadTabContent(): void
|
|
{
|
|
if ($this->activeTab === 'debiti') {
|
|
$this->loadDebiti();
|
|
} elseif ($this->activeTab === 'movimenti') {
|
|
$this->loadMovimenti();
|
|
} elseif ($this->activeTab === 'stato_debiti') {
|
|
$this->loadDebitiStorici();
|
|
}
|
|
}
|
|
|
|
public function loadDebiti(): void
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return;
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId || ! Schema::hasTable('contabilita_fatture_fornitori')) {
|
|
$this->debiti = [];
|
|
return;
|
|
}
|
|
|
|
$select = [
|
|
'f.id',
|
|
'f.numero_documento',
|
|
'f.data_documento',
|
|
'f.totale',
|
|
'f.netto_da_pagare',
|
|
'f.stato',
|
|
'f.fornitore_id',
|
|
'f.fattura_elettronica_id',
|
|
];
|
|
|
|
$query = DB::table('contabilita_fatture_fornitori as f')
|
|
->where('f.stabile_id', $stabileId)
|
|
->where(function ($q) {
|
|
$q->where('f.stato', '!=', 'pagato')
|
|
->orWhereNull('f.stato');
|
|
});
|
|
|
|
if (Schema::hasTable('fornitori')) {
|
|
$query->leftJoin('fornitori as forn', 'forn.id', '=', 'f.fornitore_id');
|
|
$select[] = 'forn.ragione_sociale as fornitore_ragione_sociale';
|
|
$select[] = 'forn.iban as fornitore_iban';
|
|
}
|
|
|
|
if (Schema::hasTable('fatture_elettroniche')) {
|
|
$query->leftJoin('fatture_elettroniche as fe', 'fe.id', '=', 'f.fattura_elettronica_id');
|
|
$select[] = 'fe.pagamento_iban as fe_pagamento_iban';
|
|
}
|
|
|
|
$dbRows = $query->select($select)
|
|
->orderBy('f.data_documento')
|
|
->orderBy('f.id')
|
|
->get();
|
|
|
|
$this->debiti = [];
|
|
foreach ($dbRows as $row) {
|
|
$iban = null;
|
|
|
|
if (isset($row->fe_pagamento_iban) && $row->fe_pagamento_iban) {
|
|
$iban = $row->fe_pagamento_iban;
|
|
}
|
|
|
|
if (! $iban && isset($row->fornitore_iban)) {
|
|
$iban = $row->fornitore_iban;
|
|
}
|
|
|
|
$id = (int) $row->id;
|
|
$fornitoreName = $row->fornitore_ragione_sociale ?? 'Fornitore Sconosciuto';
|
|
$numDoc = $row->numero_documento ?? 'N/D';
|
|
|
|
$prefix = "FAT-ID:{$id} ";
|
|
$suffix = " N.{$numDoc}";
|
|
$avail = 140 - strlen($prefix) - strlen($suffix);
|
|
$cleanName = substr($fornitoreName, 0, max(0, $avail));
|
|
$descrizione = $prefix . $cleanName . $suffix;
|
|
|
|
$this->debiti[] = [
|
|
'id' => $id,
|
|
'numero_documento' => $numDoc,
|
|
'data_documento' => $row->data_documento ? Carbon::parse($row->data_documento)->format('d/m/Y') : '—',
|
|
'totale' => (float) $row->totale,
|
|
'netto_da_pagare' => (float) ($row->netto_da_pagare ?? $row->totale),
|
|
'fornitore_ragione_sociale' => $fornitoreName,
|
|
'iban' => $iban ? strtoupper(str_replace(' ', '', $iban)) : null,
|
|
'descrizione_bonifico' => $descrizione,
|
|
];
|
|
}
|
|
}
|
|
|
|
public function loadMovimenti(): void
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return;
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId || ! Schema::hasTable('contabilita_movimenti_banca')) {
|
|
$this->movimenti = [];
|
|
return;
|
|
}
|
|
|
|
$query = DB::table('contabilita_movimenti_banca as m')
|
|
->where('m.stabile_id', $stabileId);
|
|
|
|
if (Schema::hasTable('contabilita_fatture_fornitori')) {
|
|
$query->leftJoin('contabilita_fatture_fornitori as f', 'f.movimento_pagamento_id', '=', 'm.id');
|
|
}
|
|
if (Schema::hasTable('fornitori')) {
|
|
$query->leftJoin('fornitori as forn', 'forn.id', '=', 'm.fornitore_id');
|
|
}
|
|
|
|
$select = [
|
|
'm.id',
|
|
'm.data',
|
|
'm.descrizione',
|
|
'm.descrizione_estesa',
|
|
'm.importo',
|
|
'm.registrazione_id',
|
|
'm.causale',
|
|
];
|
|
|
|
if (Schema::hasTable('contabilita_fatture_fornitori')) {
|
|
$select[] = 'f.id as invoice_id';
|
|
$select[] = 'f.numero_documento as invoice_number';
|
|
}
|
|
if (Schema::hasTable('fornitori')) {
|
|
$select[] = 'forn.ragione_sociale as fornitore_ragione_sociale';
|
|
}
|
|
|
|
$rows = $query->select($select)
|
|
->orderByDesc('m.data')
|
|
->orderByDesc('m.id')
|
|
->get();
|
|
|
|
$this->movimenti = [];
|
|
foreach ($rows as $r) {
|
|
$invId = isset($r->invoice_id) ? $r->invoice_id : null;
|
|
$invNum = isset($r->invoice_number) ? $r->invoice_number : null;
|
|
$forn = isset($r->fornitore_ragione_sociale) ? $r->fornitore_ragione_sociale : null;
|
|
|
|
$isReconciled = ! empty($r->registrazione_id) || ! empty($invId);
|
|
|
|
$advice = '';
|
|
if (! $isReconciled) {
|
|
if ((float) $r->importo < 0) {
|
|
if (in_array((string) $r->causale, ['198', '219', '048', '208'], true)) {
|
|
$advice = 'Spesa bancaria diretta. Configura la regola interbancaria per registrarla in prima nota.';
|
|
} else {
|
|
$advice = 'Uscita bancaria. Registra la fattura fornitore corrispondente o riconcilia manualmente.';
|
|
}
|
|
} else {
|
|
$advice = 'Entrata/Incasso rate. Riconcilia con le rate o gli incassi del condominio.';
|
|
}
|
|
}
|
|
|
|
$this->movimenti[] = [
|
|
'id' => (int) $r->id,
|
|
'data' => $r->data ? Carbon::parse($r->data)->format('d/m/Y') : '—',
|
|
'descrizione' => $r->descrizione ?: 'Movimento banca',
|
|
'importo' => (float) $r->importo,
|
|
'stato' => $isReconciled ? 'quadrato' : 'da_quadrare',
|
|
'invoice_id' => $invId,
|
|
'invoice_number' => $invNum,
|
|
'fornitore' => $forn,
|
|
'advice' => $advice,
|
|
];
|
|
}
|
|
}
|
|
|
|
public function loadDebitiStorici(): void
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return;
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId || ! Schema::hasTable('contabilita_fatture_fornitori') || ! $this->targetDate) {
|
|
$this->debitiStorici = [];
|
|
$this->totaleDebitiStorici = 0.0;
|
|
return;
|
|
}
|
|
|
|
$query = DB::table('contabilita_fatture_fornitori as f')
|
|
->where('f.stabile_id', $stabileId)
|
|
->where('f.data_documento', '<=', $this->targetDate)
|
|
->where(function ($q) {
|
|
$q->where('f.stato', '!=', 'pagato')
|
|
->orWhereNull('f.stato')
|
|
->orWhereNull('f.data_pagamento')
|
|
->orWhere('f.data_pagamento', '>', $this->targetDate);
|
|
});
|
|
|
|
if (Schema::hasTable('fornitori')) {
|
|
$query->leftJoin('fornitori as forn', 'forn.id', '=', 'f.fornitore_id');
|
|
}
|
|
|
|
$select = [
|
|
'f.id',
|
|
'f.numero_documento',
|
|
'f.data_documento',
|
|
'f.totale',
|
|
'f.netto_da_pagare',
|
|
'f.stato',
|
|
'f.data_pagamento',
|
|
];
|
|
|
|
if (Schema::hasTable('fornitori')) {
|
|
$select[] = 'forn.ragione_sociale as fornitore_ragione_sociale';
|
|
}
|
|
|
|
$rows = $query->select($select)
|
|
->orderBy('f.data_documento')
|
|
->orderBy('f.id')
|
|
->get();
|
|
|
|
$this->debitiStorici = [];
|
|
$this->totaleDebitiStorici = 0.0;
|
|
|
|
foreach ($rows as $row) {
|
|
$tot = (float) $row->totale;
|
|
$due = (float) ($row->netto_da_pagare ?? $row->totale);
|
|
$this->totaleDebitiStorici += $due;
|
|
|
|
$chiusoAl = 'Ancora aperto';
|
|
if ($row->stato === 'pagato' && $row->data_pagamento) {
|
|
$chiusoAl = Carbon::parse($row->data_pagamento)->format('d/m/Y');
|
|
}
|
|
|
|
$this->debitiStorici[] = [
|
|
'id' => (int) $row->id,
|
|
'numero_documento' => $row->numero_documento ?? 'N/D',
|
|
'data_documento' => $row->data_documento ? Carbon::parse($row->data_documento)->format('d/m/Y') : '—',
|
|
'totale' => $tot,
|
|
'netto_da_pagare' => $due,
|
|
'fornitore' => $row->fornitore_ragione_sociale ?? 'Fornitore Sconosciuto',
|
|
'stato_corrente' => $row->stato ?? 'N/D',
|
|
'data_chiusura' => $chiusoAl,
|
|
];
|
|
}
|
|
}
|
|
|
|
private function resolveActiveGestioneId(int $stabileId): ?int
|
|
{
|
|
$anno = \App\Support\AnnoGestioneContext::resolveActiveAnno();
|
|
$tipo = \App\Support\GestioneContext::resolveActiveGestione();
|
|
|
|
$match = DB::table('gestioni_contabili')
|
|
->where('stabile_id', $stabileId)
|
|
->where('anno_gestione', $anno)
|
|
->where('tipo_gestione', $tipo)
|
|
->where('stato', 'aperta')
|
|
->orderByDesc('gestione_attiva')
|
|
->orderByDesc('id')
|
|
->first();
|
|
|
|
if (! $match) {
|
|
$match = DB::table('gestioni_contabili')
|
|
->where('stabile_id', $stabileId)
|
|
->where('stato', 'aperta')
|
|
->orderByDesc('gestione_attiva')
|
|
->orderByDesc('id')
|
|
->first();
|
|
}
|
|
|
|
return $match ? (int) $match->id : null;
|
|
}
|
|
}
|