resolveUserUnita($user); $unitaIds = $unitaImmobiliari->pluck('id')->filter()->map(fn($v) => (int) $v)->all(); $serviziAcqua = StabileServizio::query() ->where('tipo', 'acqua') ->whereIn('stabile_id', $unitaImmobiliari->pluck('stabile_id')->filter()->all()) ->where('attivo', true) ->orderBy('stabile_id') ->orderBy('nome') ->get(); $serviziByUnita = []; foreach ($unitaImmobiliari as $unita) { $serviziByUnita[(int) $unita->id] = $serviziAcqua ->where('stabile_id', (int) $unita->stabile_id) ->values(); } $query = StabileServizioLettura::query() ->with(['stabile', 'servizio', 'unitaImmobiliare']) ->whereIn('unita_immobiliare_id', $unitaIds) ->where('canale_acquisizione', 'portale_condomino') ->orderByDesc('periodo_al') ->orderByDesc('id'); if ($request->filled('unita_immobiliare_id')) { $query->where('unita_immobiliare_id', (int) $request->input('unita_immobiliare_id')); } $letture = $query->paginate(20)->withQueryString(); return view('condomino.letture-acqua.index', [ 'unitaImmobiliari' => $unitaImmobiliari, 'serviziByUnita' => $serviziByUnita, 'letture' => $letture, ]); } public function store(Request $request): RedirectResponse { /** @var User|null $user */ $user = Auth::user(); $validated = $request->validate([ 'unita_immobiliare_id' => ['required', 'integer'], 'stabile_servizio_id' => ['required', 'integer'], 'totale_letto' => ['required', 'numeric', 'min:0'], 'data_lettura' => ['nullable', 'date'], 'foto' => ['nullable', 'image', 'max:8192'], 'note' => ['nullable', 'string', 'max:2000'], ]); $unita = $this->resolveUserUnita($user) ->firstWhere('id', (int) $validated['unita_immobiliare_id']); if (! $unita) { return back()->withErrors([ 'unita_immobiliare_id' => 'Unita immobiliare non accessibile per l\'utente autenticato.', ])->withInput(); } $servizio = StabileServizio::query() ->where('id', (int) $validated['stabile_servizio_id']) ->where('stabile_id', (int) $unita->stabile_id) ->where('tipo', 'acqua') ->first(); if (! $servizio) { return back()->withErrors([ 'stabile_servizio_id' => 'Utenza acqua non valida per l\'unita selezionata.', ])->withInput(); } $dataLettura = isset($validated['data_lettura']) ? Carbon::parse((string) $validated['data_lettura'])->toDateString() : now()->toDateString(); $precedente = StabileServizioLettura::query() ->where('stabile_servizio_id', (int) $servizio->id) ->where('unita_immobiliare_id', (int) $unita->id) ->whereNotNull('lettura_fine') ->orderByDesc('periodo_al') ->orderByDesc('id') ->first(); $totaleLetto = (float) $validated['totale_letto']; $letturaInizio = $precedente?->lettura_fine !== null ? (float) $precedente->lettura_fine : null; $consumo = $letturaInizio !== null ? round($totaleLetto - $letturaInizio, 3) : null; if ($consumo !== null && $consumo < 0) { return back()->withErrors([ 'totale_letto' => 'Il totale letto non puo essere inferiore alla lettura precedente (' . number_format($letturaInizio, 3, ',', '.') . ').', ])->withInput(); } $fotoPath = null; if ($request->hasFile('foto')) { $fotoPath = $request->file('foto')?->store('letture-acqua', 'public'); } $riferimento = 'autolettura-' . (int) ($user?->id ?? 0) . '-' . now()->format('YmdHis'); StabileServizioLettura::create([ 'stabile_id' => (int) $unita->stabile_id, 'stabile_servizio_id' => (int) $servizio->id, 'unita_immobiliare_id' => (int) $unita->id, 'fornitore_id' => $servizio->fornitore_id, 'periodo_dal' => $precedente?->periodo_al, 'periodo_al' => $dataLettura, 'tipologia_lettura' => 'autolettura_utente', 'canale_acquisizione' => 'portale_condomino', 'riferimento_acquisizione' => $riferimento, 'lettura_inizio' => $letturaInizio, 'lettura_fine' => $totaleLetto, 'consumo_valore' => $consumo, 'consumo_unita' => 'mc', 'raw' => [ 'foto_path' => $fotoPath, 'note' => trim((string) ($validated['note'] ?? '')), 'precedente_lettura_id' => $precedente?->id, 'precedente_totale' => $letturaInizio, 'delta_calcolato' => $consumo, ], 'created_by' => $user?->id, ]); return redirect()->route('condomino.letture-acqua.index') ->with('success', 'Autolettura registrata correttamente.'); } private function resolveUserUnita(?User $user): Collection { if (! $user) { return collect(); } $soggettoId = null; if (isset($user->soggetto?->id_soggetto) && is_numeric($user->soggetto->id_soggetto)) { $soggettoId = (int) $user->soggetto->id_soggetto; } elseif (isset($user->soggetto?->id) && is_numeric($user->soggetto->id)) { $soggettoId = (int) $user->soggetto->id; } $query = UnitaImmobiliare::query() ->with('stabile') ->where(function ($q) use ($soggettoId, $user): void { if ($soggettoId) { $q->whereHas('proprieta', function ($qp) use ($soggettoId): void { $qp->where('soggetto_id', $soggettoId); }); } $email = trim((string) $user->email); if ($email !== '') { $q->orWhereIn('id', function ($sub) use ($email): void { $sub->select('ai.unita_immobiliare_id') ->from('affitti_immobili as ai') ->join('rubrica_universale as ru', 'ru.id', '=', 'ai.rubrica_inquilino_id') ->whereNotNull('ai.unita_immobiliare_id') ->whereRaw('LOWER(ru.email) = ?', [mb_strtolower($email)]); }); } }); return $query->orderBy('stabile_id')->orderBy('scala')->orderBy('interno')->get(); } }