middleware('permission:stampe.rate.view')->only(['index', 'show']); $this->middleware('permission:stampe.rate.create')->only(['create', 'store', 'generate']); $this->middleware('permission:stampe.rate.update')->only(['edit', 'update']); $this->middleware('permission:stampe.rate.delete')->only(['destroy']); $this->middleware('permission:stampe.rate.send')->only(['send', 'sendBulk']); } /** * Lista stampe rate generate */ public function index(Request $request) { $query = DB::table('stampe_rate') ->join('stabili', 'stampe_rate.stabile_id', '=', 'stabili.id') ->select([ 'stampe_rate.*', 'stabili.denominazione as stabile_nome', 'stabili.indirizzo as stabile_indirizzo' ]) ->where('stampe_rate.created_by', Auth::id()) ->orderBy('stampe_rate.created_at', 'desc'); // Filtri if ($request->filled('stabile_id')) { $query->where('stampe_rate.stabile_id', $request->stabile_id); } if ($request->filled('periodo')) { $query->where('stampe_rate.periodo', $request->periodo); } if ($request->filled('status')) { $query->where('stampe_rate.status', $request->status); } $stampe = $query->paginate(20); // Hook per permettere ad altri moduli di modificare i dati $stampe = HookManager::execute('stampe_rate_list_loaded', $stampe); $stabili = DB::table('stabili') ->where('amministratore_id', Auth::id()) ->select('id', 'denominazione', 'indirizzo') ->get(); return view('modules.stampe-rate.index', compact('stampe', 'stabili')); } /** * Form per generare nuove stampe rate */ public function create() { $stabili = DB::table('stabili') ->where('amministratore_id', Auth::id()) ->select('id', 'denominazione', 'indirizzo') ->get(); $templates = DB::table('stampe_rate_templates') ->where('status', 'active') ->where(function ($query) { $query->where('created_by', Auth::id()) ->orWhere('is_public', true); }) ->select('id', 'name', 'description') ->get(); return view('modules.stampe-rate.create', compact('stabili', 'templates')); } /** * Visualizza i dettagli di una stampa rate */ public function show($stampaId) { $stampa = DB::table('stampe_rate') ->join('stabili', 'stampe_rate.stabile_id', '=', 'stabili.id') ->leftJoin('stampe_rate_templates', 'stampe_rate.template_id', '=', 'stampe_rate_templates.id') ->select([ 'stampe_rate.*', 'stabili.denominazione as stabile_nome', 'stabili.indirizzo as stabile_indirizzo', 'stampe_rate_templates.name as template_nome' ]) ->where('stampe_rate.id', $stampaId) ->where('stampe_rate.created_by', Auth::id()) ->first(); if (!$stampa) { abort(404, 'Stampa rate non trovata'); } // Decodifica i dati JSON $stampa->file_generati = json_decode($stampa->file_generati, true) ?? []; $stampa->parametri_stampa = json_decode($stampa->parametri_stampa, true) ?? []; $stampa->rate_selezionate = json_decode($stampa->rate_selezionate, true) ?? []; // Statistiche di invio (se presenti) $invii = DB::table('stampe_rate_invii') ->where('stampa_id', $stampaId) ->orderBy('created_at', 'desc') ->get(); $statsInvii = [ 'totali' => $invii->count(), 'inviati' => $invii->where('status', 'sent')->count(), 'falliti' => $invii->where('status', 'failed')->count(), 'in_coda' => $invii->where('status', 'pending')->count() ]; return view('modules.stampe-rate.show', compact('stampa', 'invii', 'statsInvii')); } /** * Genera le stampe rate per uno stabile */ public function generate(Request $request) { $request->validate([ 'stabile_id' => 'required|exists:stabili,id', 'periodo' => 'required|string', 'template_id' => 'required|exists:stampe_rate_templates,id', 'include_pdf' => 'boolean', 'auto_send' => 'boolean' ]); try { DB::beginTransaction(); // Hook prima della generazione $data = HookManager::execute('before_stampa_generated', [ 'stabile_id' => $request->stabile_id, 'periodo' => $request->periodo, 'template_id' => $request->template_id, 'user_id' => Auth::id() ]); // Ottieni le rate da stampare $rate = $this->getRateByStabile($request->stabile_id, $request->periodo); if ($rate->isEmpty()) { return response()->json([ 'success' => false, 'message' => 'Nessuna rata trovata per il periodo selezionato' ], 404); } // Crea record stampa principale $stampaId = DB::table('stampe_rate')->insertGetId([ 'stabile_id' => $request->stabile_id, 'periodo' => $request->periodo, 'template_id' => $request->template_id, 'total_rate' => $rate->count(), 'status' => 'generating', 'created_by' => Auth::id(), 'created_at' => now(), 'updated_at' => now() ]); // Genera PDF per ogni rata $generatedFiles = []; foreach ($rate as $rata) { $pdfData = $this->generateRataPDF($rata, $request->template_id); $fileName = "rata_{$rata->id}_{$request->periodo}.pdf"; $filePath = storage_path("app/public/stampe-rate/{$stampaId}/{$fileName}"); // Crea directory se non exists if (!file_exists(dirname($filePath))) { mkdir(dirname($filePath), 0755, true); } // Salva PDF file_put_contents($filePath, $pdfData); // Registra il file generato DB::table('stampe_rate_files')->insert([ 'stampa_id' => $stampaId, 'rata_id' => $rata->id, 'unita_id' => $rata->unita_immobiliare_id, 'file_name' => $fileName, 'file_path' => $filePath, 'file_size' => filesize($filePath), 'created_at' => now() ]); $generatedFiles[] = [ 'rata_id' => $rata->id, 'file_name' => $fileName, 'file_path' => $filePath ]; } // Aggiorna stato stampa DB::table('stampe_rate')->where('id', $stampaId)->update([ 'status' => 'completed', 'generated_files' => count($generatedFiles), 'completed_at' => now(), 'updated_at' => now() ]); DB::commit(); // Hook dopo la generazione $result = HookManager::execute('after_stampa_generated', [ 'stampa_id' => $stampaId, 'files_generated' => $generatedFiles, 'auto_send' => $request->auto_send ]); // Invio automatico se richiesto if ($request->auto_send) { $this->sendBulk($stampaId); } return response()->json([ 'success' => true, 'message' => "Stampe generate con successo: {$rate->count()} rate elaborate", 'stampa_id' => $stampaId, 'files_count' => count($generatedFiles), 'download_url' => route('stampeRate.download', $stampaId) ]); } catch (\Exception $e) { DB::rollback(); return response()->json([ 'success' => false, 'message' => 'Errore durante la generazione: ' . $e->getMessage() ], 500); } } /** * Invia stampe rate via email */ public function send(Request $request, $stampaId) { $request->validate([ 'email_subject' => 'required|string|max:255', 'email_body' => 'required|string', 'send_to' => 'required|array', 'send_to.*' => 'email' ]); $stampa = DB::table('stampe_rate')->where('id', $stampaId)->first(); if (!$stampa) { return response()->json([ 'success' => false, 'message' => 'Stampa non trovata' ], 404); } // Hook prima dell'invio HookManager::execute('before_email_sent', [ 'stampa_id' => $stampaId, 'recipients' => $request->send_to ]); // Ottieni i file da allegare $files = DB::table('stampe_rate_files') ->where('stampa_id', $stampaId) ->get(); $sentCount = 0; $errors = []; foreach ($request->send_to as $email) { try { // Invia email con allegati Mail::send('modules.stampe-rate.emails.rate-email', [ 'subject' => $request->email_subject, 'body' => $request->email_body, 'stampa' => $stampa ], function ($message) use ($email, $request, $files) { $message->to($email) ->subject($request->email_subject); // Allega i PDF foreach ($files as $file) { if (file_exists($file->file_path)) { $message->attach($file->file_path, [ 'as' => $file->file_name, 'mime' => 'application/pdf' ]); } } }); // Registra invio DB::table('stampe_rate_invii')->insert([ 'stampa_id' => $stampaId, 'email' => $email, 'status' => 'sent', 'sent_at' => now(), 'created_at' => now() ]); $sentCount++; } catch (\Exception $e) { $errors[] = "Errore invio a {$email}: " . $e->getMessage(); // Registra errore DB::table('stampe_rate_invii')->insert([ 'stampa_id' => $stampaId, 'email' => $email, 'status' => 'failed', 'error_message' => $e->getMessage(), 'created_at' => now() ]); } } // Hook dopo l'invio HookManager::execute('after_email_sent', [ 'stampa_id' => $stampaId, 'sent_count' => $sentCount, 'errors' => $errors ]); return response()->json([ 'success' => $sentCount > 0, 'message' => "Email inviate: {$sentCount}/" . count($request->send_to), 'sent_count' => $sentCount, 'errors' => $errors ]); } /** * Download ZIP con tutte le stampe */ public function download($stampaId) { $stampa = DB::table('stampe_rate')->where('id', $stampaId)->first(); if (!$stampa) { abort(404, 'Stampa non trovata'); } $files = DB::table('stampe_rate_files') ->where('stampa_id', $stampaId) ->get(); if ($files->isEmpty()) { abort(404, 'Nessun file trovato'); } // Crea ZIP temporaneo $zipFileName = "stampe_rate_{$stampaId}_" . date('Y-m-d_H-i-s') . '.zip'; $zipPath = storage_path("app/temp/{$zipFileName}"); $zip = new \ZipArchive(); $zip->open($zipPath, \ZipArchive::CREATE); foreach ($files as $file) { if (file_exists($file->file_path)) { $zip->addFile($file->file_path, $file->file_name); } } $zip->close(); return response()->download($zipPath)->deleteFileAfterSend(true); } // ============================================= // METODI PRIVATI DI SUPPORTO // ============================================= private function getRateByStabile($stabileId, $periodo) { return DB::table('rate') ->join('unita_immobiliari', 'rate.unita_immobiliare_id', '=', 'unita_immobiliari.id') ->where('unita_immobiliari.stabile_id', $stabileId) ->where('rate.periodo', $periodo) ->select([ 'rate.*', 'unita_immobiliari.numero as unita_numero', 'unita_immobiliari.piano', 'unita_immobiliari.scala' ]) ->get(); } private function generateRataPDF($rata, $templateId) { // Ottieni template $template = DB::table('stampe_rate_templates')->where('id', $templateId)->first(); // Hook per modificare il template $templateData = HookManager::execute('template_loaded', [ 'template' => $template, 'rata' => $rata ]); // Genera HTML dal template $html = view('modules.stampe-rate.templates.pdf', [ 'rata' => $rata, 'template' => $template ])->render(); // Converti in PDF $pdf = PDF::loadHTML($html); $pdf->setPaper('A4', 'portrait'); return $pdf->output(); } }