integer('servizio'); $unitaId = (int) $request->integer('unita'); $requestId = (int) $request->integer('request'); $servizio = StabileServizio::query() ->where('id', $servizioId) ->where('tipo', 'acqua') ->firstOrFail(); $unita = UnitaImmobiliare::query() ->with('stabile:id,denominazione,codice_stabile') ->where('id', $unitaId) ->where('stabile_id', (int) $servizio->stabile_id) ->firstOrFail(); $pendingRequest = $requestId > 0 ? StabileServizioLettura::query() ->where('id', $requestId) ->where('stabile_servizio_id', $servizioId) ->where('unita_immobiliare_id', $unitaId) ->first() : null; $previous = StabileServizioLettura::query() ->where('stabile_servizio_id', $servizioId) ->where('unita_immobiliare_id', $unitaId) ->whereNotNull('lettura_fine') ->when($pendingRequest, fn($query) => $query->where('id', '!=', (int) $pendingRequest->id)) ->orderByDesc('periodo_al') ->orderByDesc('id') ->first(); $submitUrl = URL::temporarySignedRoute('public.water-reading.store', now()->addDays(30), array_filter([ 'servizio' => $servizioId, 'unita' => $unitaId, 'request' => $pendingRequest?->id, ])); return view('public.water-reading.show', [ 'servizio' => $servizio, 'unita' => $unita, 'pendingRequest' => $pendingRequest, 'previous' => $previous, 'submitUrl' => $submitUrl, ]); } public function store(Request $request): RedirectResponse { $servizioId = (int) $request->integer('servizio'); $unitaId = (int) $request->integer('unita'); $requestId = (int) $request->integer('request'); $servizio = StabileServizio::query() ->where('id', $servizioId) ->where('tipo', 'acqua') ->firstOrFail(); $unita = UnitaImmobiliare::query() ->where('id', $unitaId) ->where('stabile_id', (int) $servizio->stabile_id) ->firstOrFail(); $validated = $request->validate([ 'lettura_attuale' => ['required', 'numeric', 'min:0'], 'data_lettura' => ['nullable', 'date'], 'rilevatore_nome' => ['required', 'string', 'max:255'], 'rilevatore_contatto' => ['nullable', 'string', 'max:255'], 'note' => ['nullable', 'string', 'max:2000'], 'foto_1' => ['nullable', 'image', 'max:8192'], 'foto_2' => ['nullable', 'image', 'max:8192'], ]); $pendingRequest = $requestId > 0 ? StabileServizioLettura::query() ->where('id', $requestId) ->where('stabile_servizio_id', $servizioId) ->where('unita_immobiliare_id', $unitaId) ->first() : null; $previous = StabileServizioLettura::query() ->where('stabile_servizio_id', $servizioId) ->where('unita_immobiliare_id', $unitaId) ->whereNotNull('lettura_fine') ->when($pendingRequest, fn($query) => $query->where('id', '!=', (int) $pendingRequest->id)) ->orderByDesc('periodo_al') ->orderByDesc('id') ->first(); $letturaInizio = $previous?->lettura_fine !== null ? (float) $previous->lettura_fine : null; $letturaFine = (float) $validated['lettura_attuale']; $consumo = $letturaInizio !== null ? round($letturaFine - $letturaInizio, 3) : null; if ($consumo !== null && $consumo < 0) { return back()->withErrors([ 'lettura_attuale' => 'La lettura attuale non puo essere inferiore a quella precedente.', ])->withInput(); } $photoAssets = []; foreach (['foto_1', 'foto_2'] as $photoField) { if ($request->hasFile($photoField)) { $file = $request->file($photoField); if (! $file) { continue; } $stored = app(TicketAttachmentUploadService::class)->store( $file, 'letture-acqua-public/' . $servizio->id . '/' . $unita->id, [ 'stored_basename' => 'water-reading-' . $servizio->id . '-' . $unita->id . '-' . $photoField, ] ); $photoAssets[] = [ 'field' => $photoField, 'path' => $stored['path'], 'original_name' => $stored['original_name'] ?? null, 'source_original_name' => $stored['source_original_name'] ?? null, 'mime' => $stored['mime'] ?? null, 'size' => $stored['size'] ?? null, 'metadata' => is_array($stored['metadata'] ?? null) ? $stored['metadata'] : [], ]; } } $photoPaths = array_values(array_filter(array_map( static fn(array $photo): ?string => is_string($photo['path'] ?? null) ? $photo['path'] : null, $photoAssets ))); $payload = [ 'stabile_id' => (int) $servizio->stabile_id, 'stabile_servizio_id' => (int) $servizio->id, 'unita_immobiliare_id' => (int) $unita->id, 'fornitore_id' => $servizio->fornitore_id, 'periodo_dal' => $previous?->periodo_al, 'periodo_al' => isset($validated['data_lettura']) ? Carbon::parse((string) $validated['data_lettura'])->toDateString() : now()->toDateString(), 'tipologia_lettura' => 'autolettura_link_pubblico', 'canale_acquisizione' => 'portale_pubblico', 'workflow_stato' => 'ricevuta', 'riferimento_acquisizione' => $pendingRequest?->riferimento_acquisizione ?: ('PUBREAD:' . (int) $servizio->id . ':' . (int) $unita->id . ':' . now()->format('YmdHis')), 'rilevatore_tipo' => 'link_pubblico', 'rilevatore_nome' => trim((string) $validated['rilevatore_nome']), 'lettura_precedente_valore' => $letturaInizio, 'lettura_inizio' => $letturaInizio, 'lettura_fine' => $letturaFine, 'lettura_foto_path' => $photoPaths[0] ?? null, 'lettura_foto_original_name'=> $photoAssets[0]['original_name'] ?? null, 'lettura_foto_metadata' => [ 'photos' => $photoAssets, 'paths' => $photoPaths, 'contact' => trim((string) ($validated['rilevatore_contatto'] ?? '')), 'note' => trim((string) ($validated['note'] ?? '')), ], 'consumo_valore' => $consumo, 'consumo_unita' => 'mc', 'raw' => [ 'source' => 'public_water_reading_link', 'contact' => trim((string) ($validated['rilevatore_contatto'] ?? '')), 'note' => trim((string) ($validated['note'] ?? '')), 'photo_assets'=> $photoAssets, 'photo_paths' => $photoPaths, 'request_id' => $pendingRequest?->id, ], ]; if ($pendingRequest) { $pendingRequest->fill($payload); $pendingRequest->save(); } else { StabileServizioLettura::query()->create($payload); } return redirect()->back()->with('success', 'Lettura acqua inviata correttamente.'); } }