168 lines
8.1 KiB
PHP
Executable File
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);
|
|
}
|
|
}
|