netgescon-day0/app/Http/Controllers/Admin/RiscaldamentoRipartizionePrintController.php

168 lines
8.1 KiB
PHP
Executable File

<?php
namespace App\Http\Controllers\Admin;
use App\Models\FatturaElettronica;
use App\Models\StabileServizioLettura;
use App\Models\UnitaImmobiliare;
use App\Models\User;
use App\Support\StabileContext;
use Dompdf\Dompdf;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Routing\Controller;
use Illuminate\Support\Carbon;
class RiscaldamentoRipartizionePrintController extends Controller
{
public function print(Request $request): View
{
return view('filament.print.riscaldamento-ripartizione-riepilogo', $this->buildReportData($request) + [
'autoprint' => $request->boolean('autoprint', true),
]);
}
public function pdf(Request $request): Response
{
$data = $this->buildReportData($request);
$html = view('filament.print.riscaldamento-ripartizione-riepilogo', $data + ['autoprint' => false])->render();
$dompdf = new Dompdf();
$dompdf->loadHtml($html, 'UTF-8');
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
return response($dompdf->output(), 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="riscaldamento-ripartizione-' . $data['year'] . '.pdf"',
]);
}
/** @return array<string,mixed> */
private function buildReportData(Request $request): array
{
$user = $request->user();
abort_unless($user instanceof User, 403);
$stabileId = (int) $request->integer('stabile_id');
$stabile = StabileContext::accessibleStabili($user)->firstWhere('id', $stabileId);
abort_unless($stabile, 403);
$year = max(2000, min(2100, (int) $request->integer('year', now()->year)));
$selectedIds = collect(explode(',', (string) $request->query('ids', '')))
->map(fn(string $value): int => (int) trim($value))
->filter(fn(int $value): bool => $value > 0)
->values()
->all();
$fattureRows = FatturaElettronica::query()
->where('stabile_id', (int) $stabile->id)
->whereYear('data_fattura', $year)
->when($selectedIds !== [], fn($query) => $query->whereIn('id', $selectedIds))
->whereNotNull('consumo_raw')
->orderByDesc('data_fattura')
->orderByDesc('id')
->get(['id', 'numero_fattura', 'data_fattura', 'totale', 'consumo_raw', 'consumo_riferimento', 'consumo_valore'])
->map(function (FatturaElettronica $fattura): ?array {
$payload = json_decode((string) $fattura->consumo_raw, true);
if (! $this->payloadLooksLikeRiscaldamento(is_array($payload) ? $payload : null)) {
return null;
}
return [
'id' => (int) $fattura->id,
'numero_fattura' => trim((string) ($fattura->numero_fattura ?? '')),
'data_fattura' => optional($fattura->data_fattura)->format('d/m/Y'),
'periodo' => trim((string) ($fattura->consumo_riferimento ?? '')),
'totale_mc' => is_numeric($fattura->consumo_valore) ? (float) $fattura->consumo_valore : 0.0,
'totale_spesa' => is_numeric($fattura->totale) ? (float) $fattura->totale : 0.0,
'utenza' => trim((string) data_get($payload, 'codici.utenza', '')),
'cliente' => trim((string) data_get($payload, 'codici.cliente', '')),
'contratto' => trim((string) data_get($payload, 'codici.contratto', '')),
'matricola' => trim((string) data_get($payload, 'contatore.matricola', '')),
'cbill' => trim((string) data_get($payload, 'pagamento.cbill', '')),
'codice_avviso' => trim((string) data_get($payload, 'pagamento.codice_avviso', '')),
];
})
->filter()
->values();
$unitLabels = UnitaImmobiliare::query()
->where('stabile_id', (int) $stabile->id)
->get(['id', 'codice_unita', 'scala', 'interno'])
->mapWithKeys(function (UnitaImmobiliare $unit): array {
$label = trim(implode(' ', array_filter([
trim((string) ($unit->codice_unita ?? '')),
trim((string) ($unit->scala ?? '')) !== '' ? 'Scala ' . trim((string) $unit->scala) : null,
trim((string) ($unit->interno ?? '')) !== '' ? 'Int. ' . trim((string) $unit->interno) : null,
])));
return [(int) $unit->id => ($label !== '' ? $label : ('UI #' . (int) $unit->id))];
})
->all();
$lettureRows = StabileServizioLettura::query()
->where('stabile_id', (int) $stabile->id)
->whereNotNull('unita_immobiliare_id')
->whereHas('servizio', fn($q) => $q->where('tipo', 'riscaldamento'))
->where(function ($query) use ($year): void {
$query->whereYear('periodo_al', $year)
->orWhere(function ($fallback) use ($year): void {
$fallback->whereNull('periodo_al')->whereYear('periodo_dal', $year);
})
->orWhere(function ($fallback) use ($year): void {
$fallback->whereNull('periodo_al')->whereNull('periodo_dal')->whereYear('created_at', $year);
});
})
->with(['servizio:id,nome,contatore_matricola'])
->orderByDesc('created_at')
->orderByDesc('id')
->get(['id', 'unita_immobiliare_id', 'created_at', 'canale_acquisizione', 'riferimento_acquisizione', 'periodo_dal', 'periodo_al', 'lettura_fine', 'consumo_valore', 'consumo_unita', 'stabile_servizio_id'])
->map(function (StabileServizioLettura $row) use ($unitLabels): array {
return [
'data_ricezione' => optional($row->created_at)->format('d/m/Y H:i'),
'servizio' => trim((string) ($row->servizio?->nome ?? 'Riscaldamento')),
'matricola' => trim((string) ($row->servizio?->contatore_matricola ?? '')),
'unita' => $unitLabels[(int) ($row->unita_immobiliare_id ?? 0)] ?? ('UI #' . (int) $row->unita_immobiliare_id),
'canale' => strtoupper(trim((string) ($row->canale_acquisizione ?? '—'))),
'riferimento' => trim((string) ($row->riferimento_acquisizione ?? '')),
'periodo' => trim(implode(' - ', array_filter([
optional($row->periodo_dal)->format('d/m/Y'),
optional($row->periodo_al)->format('d/m/Y'),
]))),
'lettura_fine' => is_numeric($row->lettura_fine) ? (float) $row->lettura_fine : null,
'consumo_valore' => is_numeric($row->consumo_valore) ? (float) $row->consumo_valore : null,
'consumo_unita' => trim((string) ($row->consumo_unita ?: 'mc')),
];
})
->all();
return [
'stabile' => $stabile,
'year' => $year,
'fattureRows' => $fattureRows,
'lettureRows' => $lettureRows,
'summary' => [
'fatture' => $fattureRows->count(),
'totale_mc' => round((float) $fattureRows->sum('totale_mc'), 3),
'totale_spesa' => round((float) $fattureRows->sum('totale_spesa'), 2),
'letture_ui' => count($lettureRows),
],
'generatedAt' => Carbon::now(),
];
}
private function payloadLooksLikeRiscaldamento(?array $payload): bool
{
if (! is_array($payload) || $payload === []) {
return false;
}
return ($payload['type'] ?? null) === 'riscaldamento'
|| is_array($payload['consumi'] ?? null)
|| is_array($payload['riepilogo_letture'] ?? null)
|| is_array($payload['finestra_autolettura'] ?? null)
|| is_array($payload['codici'] ?? null);
}
}