middleware('auth'); $this->middleware('permission:stampe_rate_templates_view')->only(['index', 'show', 'preview']); $this->middleware('permission:stampe_rate_templates_create')->only(['create', 'store', 'duplicate']); $this->middleware('permission:stampe_rate_templates_edit')->only(['edit', 'update', 'publish', 'unpublish']); $this->middleware('permission:stampe_rate_templates_delete')->only(['destroy']); $this->middleware('permission:stampe_rate_templates_import')->only(['import', 'processImport']); $this->hookManager = app(HookManager::class); } /** * Mostra la lista dei template */ public function index(Request $request) { try { $this->hookManager->execute('stampe_rate.templates.before_index', [$request]); $query = DB::table('stampe_templates') ->where('module', 'stampe_rate') ->where('deleted_at', null); // Filtri if ($request->filled('search')) { $search = $request->get('search'); $query->where(function ($q) use ($search) { $q->where('nome', 'like', "%{$search}%") ->orWhere('descrizione', 'like', "%{$search}%") ->orWhere('tags', 'like', "%{$search}%"); }); } if ($request->filled('categoria')) { $query->where('categoria', $request->get('categoria')); } if ($request->filled('status')) { $query->where('status', $request->get('status')); } // Ordinamento $sortBy = $request->get('sort_by', 'created_at'); $sortDir = $request->get('sort_dir', 'desc'); $query->orderBy($sortBy, $sortDir); $templates = $query->paginate(20); // Statistiche per la dashboard $stats = [ 'total' => DB::table('stampe_templates')->where('module', 'stampe_rate')->where('deleted_at', null)->count(), 'attivi' => DB::table('stampe_templates')->where('module', 'stampe_rate')->where('status', 'attivo')->where('deleted_at', null)->count(), 'bozze' => DB::table('stampe_templates')->where('module', 'stampe_rate')->where('status', 'bozza')->where('deleted_at', null)->count(), 'piu_usato' => DB::table('stampe_templates') ->where('module', 'stampe_rate') ->where('deleted_at', null) ->orderBy('utilizzi_count', 'desc') ->first()?->nome ?? 'N/A' ]; $this->hookManager->execute('stampe_rate.templates.after_index', [$templates, $stats]); return view('modules.stampe-rate.templates.index', compact('templates', 'stats')); } catch (\Exception $e) { Log::error("Errore caricamento template: " . $e->getMessage()); return back()->with('error', 'Errore nel caricamento dei template: ' . $e->getMessage()); } } /** * Mostra il form per creare un nuovo template */ public function create() { try { $this->hookManager->execute('stampe_rate.templates.before_create'); // Categorie disponibili $categorie = [ 'rate_standard' => 'Rate Standard', 'rate_scadute' => 'Rate Scadute', 'rate_personalizzate' => 'Rate Personalizzate', 'avvisi' => 'Avvisi e Comunicazioni', 'riepilogativo' => 'Documenti Riepilogativi' ]; // Template predefiniti per iniziare $templateBase = [ 'semplice' => $this->getTemplateBase('semplice'), 'professionale' => $this->getTemplateBase('professionale'), 'moderno' => $this->getTemplateBase('moderno') ]; return view('modules.stampe-rate.templates.create', compact('categorie', 'templateBase')); } catch (\Exception $e) { Log::error("Errore form template: " . $e->getMessage()); return back()->with('error', 'Errore nel caricamento del form: ' . $e->getMessage()); } } /** * Salva un nuovo template */ public function store(Request $request) { $validator = Validator::make($request->all(), [ 'nome' => 'required|string|max:255', 'descrizione' => 'nullable|string|max:1000', 'categoria' => 'required|string|in:rate_standard,rate_scadute,rate_personalizzate,avvisi,riepilogativo', 'html_content' => 'required|string', 'css_content' => 'nullable|string', 'variabili' => 'nullable|json', 'tags' => 'nullable|string' ]); if ($validator->fails()) { return back()->withErrors($validator)->withInput(); } DB::beginTransaction(); try { $this->hookManager->execute('stampe_rate.templates.before_store', [$request]); $templateId = DB::table('stampe_templates')->insertGetId([ 'nome' => $request->get('nome'), 'descrizione' => $request->get('descrizione'), 'categoria' => $request->get('categoria'), 'module' => 'stampe_rate', 'html_content' => $request->get('html_content'), 'css_content' => $request->get('css_content', ''), 'variabili' => json_encode($request->get('variabili', [])), 'tags' => $request->get('tags'), 'status' => 'bozza', 'versione' => '1.0.0', 'created_by' => auth()->id(), 'created_at' => now(), 'updated_at' => now() ]); // Salva file template se necessario if ($request->hasFile('template_file')) { $path = $request->file('template_file')->store("templates/stampe_rate/{$templateId}", 'local'); DB::table('stampe_templates')->where('id', $templateId)->update(['file_path' => $path]); } DB::commit(); $this->hookManager->execute('stampe_rate.templates.after_store', [$templateId, $request]); // Invalidate cache Cache::tags(['stampe_rate_templates'])->flush(); return redirect()->route('stampeRate.templates.show', $templateId) ->with('success', 'Template creato con successo!'); } catch (\Exception $e) { DB::rollBack(); Log::error("Errore creazione template: " . $e->getMessage()); return back()->with('error', 'Errore nella creazione del template: ' . $e->getMessage())->withInput(); } } /** * Mostra un template specifico */ public function show($templateId) { try { $template = DB::table('stampe_templates') ->where('id', $templateId) ->where('module', 'stampe_rate') ->where('deleted_at', null) ->first(); if (!$template) { return redirect()->route('stampeRate.templates.index') ->with('error', 'Template non trovato'); } $this->hookManager->execute('stampe_rate.templates.before_show', [$template]); // Statistiche utilizzo $stats = [ 'utilizzi_totali' => $template->utilizzi_count ?? 0, 'ultimo_utilizzo' => $template->ultimo_utilizzo, 'stampe_generate' => DB::table('stampe_rate')->where('template_id', $templateId)->count(), 'media_rating' => DB::table('template_ratings')->where('template_id', $templateId)->avg('rating') ?? 0 ]; // Cronologia modifiche (ultime 10) $cronologia = DB::table('template_history') ->where('template_id', $templateId) ->orderBy('created_at', 'desc') ->limit(10) ->get(); return view('modules.stampe-rate.templates.show', compact('template', 'stats', 'cronologia')); } catch (\Exception $e) { Log::error("Errore visualizzazione template: " . $e->getMessage()); return back()->with('error', 'Errore nella visualizzazione del template: ' . $e->getMessage()); } } /** * Mostra il form per modificare un template */ public function edit($templateId) { try { $template = DB::table('stampe_templates') ->where('id', $templateId) ->where('module', 'stampe_rate') ->where('deleted_at', null) ->first(); if (!$template) { return redirect()->route('stampeRate.templates.index') ->with('error', 'Template non trovato'); } // Categorie disponibili $categorie = [ 'rate_standard' => 'Rate Standard', 'rate_scadute' => 'Rate Scadute', 'rate_personalizzate' => 'Rate Personalizzate', 'avvisi' => 'Avvisi e Comunicazioni', 'riepilogativo' => 'Documenti Riepilogativi' ]; return view('modules.stampe-rate.templates.edit', compact('template', 'categorie')); } catch (\Exception $e) { Log::error("Errore modifica template: " . $e->getMessage()); return back()->with('error', 'Errore nel caricamento del template: ' . $e->getMessage()); } } /** * Aggiorna un template esistente */ public function update(Request $request, $templateId) { $validator = Validator::make($request->all(), [ 'nome' => 'required|string|max:255', 'descrizione' => 'nullable|string|max:1000', 'categoria' => 'required|string|in:rate_standard,rate_scadute,rate_personalizzate,avvisi,riepilogativo', 'html_content' => 'required|string', 'css_content' => 'nullable|string', 'variabili' => 'nullable|json', 'tags' => 'nullable|string' ]); if ($validator->fails()) { return back()->withErrors($validator)->withInput(); } DB::beginTransaction(); try { $template = DB::table('stampe_templates') ->where('id', $templateId) ->where('module', 'stampe_rate') ->where('deleted_at', null) ->first(); if (!$template) { return redirect()->route('stampeRate.templates.index') ->with('error', 'Template non trovato'); } $this->hookManager->execute('stampe_rate.templates.before_update', [$templateId, $request]); // Salva cronologia prima della modifica DB::table('template_history')->insert([ 'template_id' => $templateId, 'versione_precedente' => $template->versione, 'modifiche' => json_encode([ 'nome' => $template->nome, 'html_content' => $template->html_content, 'css_content' => $template->css_content ]), 'modificato_da' => auth()->id(), 'created_at' => now() ]); // Incrementa versione $versioneParts = explode('.', $template->versione); $versioneParts[2] = (int)$versioneParts[2] + 1; $nuovaVersione = implode('.', $versioneParts); // Aggiorna template DB::table('stampe_templates')->where('id', $templateId)->update([ 'nome' => $request->get('nome'), 'descrizione' => $request->get('descrizione'), 'categoria' => $request->get('categoria'), 'html_content' => $request->get('html_content'), 'css_content' => $request->get('css_content', ''), 'variabili' => json_encode($request->get('variabili', [])), 'tags' => $request->get('tags'), 'versione' => $nuovaVersione, 'updated_at' => now(), 'updated_by' => auth()->id() ]); DB::commit(); $this->hookManager->execute('stampe_rate.templates.after_update', [$templateId, $request]); // Invalidate cache Cache::tags(['stampe_rate_templates'])->flush(); return redirect()->route('stampeRate.templates.show', $templateId) ->with('success', 'Template aggiornato con successo!'); } catch (\Exception $e) { DB::rollBack(); Log::error("Errore aggiornamento template: " . $e->getMessage()); return back()->with('error', 'Errore nell\'aggiornamento del template: ' . $e->getMessage())->withInput(); } } /** * Elimina un template */ public function destroy($templateId) { DB::beginTransaction(); try { $template = DB::table('stampe_templates') ->where('id', $templateId) ->where('module', 'stampe_rate') ->where('deleted_at', null) ->first(); if (!$template) { return response()->json(['error' => 'Template non trovato'], 404); } // Verifica se è in uso $inUso = DB::table('stampe_rate')->where('template_id', $templateId)->exists(); if ($inUso) { return response()->json(['error' => 'Impossibile eliminare: template in uso'], 400); } $this->hookManager->execute('stampe_rate.templates.before_destroy', [$templateId]); // Soft delete DB::table('stampe_templates')->where('id', $templateId)->update([ 'deleted_at' => now(), 'deleted_by' => auth()->id() ]); DB::commit(); $this->hookManager->execute('stampe_rate.templates.after_destroy', [$templateId]); // Invalidate cache Cache::tags(['stampe_rate_templates'])->flush(); return response()->json(['success' => 'Template eliminato con successo']); } catch (\Exception $e) { DB::rollBack(); Log::error("Errore eliminazione template: " . $e->getMessage()); return response()->json(['error' => 'Errore nell\'eliminazione del template'], 500); } } /** * Duplica un template esistente */ public function duplicate($templateId) { DB::beginTransaction(); try { $template = DB::table('stampe_templates') ->where('id', $templateId) ->where('module', 'stampe_rate') ->where('deleted_at', null) ->first(); if (!$template) { return response()->json(['error' => 'Template non trovato'], 404); } $this->hookManager->execute('stampe_rate.templates.before_duplicate', [$templateId]); $nuovoId = DB::table('stampe_templates')->insertGetId([ 'nome' => $template->nome . ' (Copia)', 'descrizione' => $template->descrizione, 'categoria' => $template->categoria, 'module' => 'stampe_rate', 'html_content' => $template->html_content, 'css_content' => $template->css_content, 'variabili' => $template->variabili, 'tags' => $template->tags, 'status' => 'bozza', 'versione' => '1.0.0', 'created_by' => auth()->id(), 'created_at' => now(), 'updated_at' => now() ]); DB::commit(); $this->hookManager->execute('stampe_rate.templates.after_duplicate', [$templateId, $nuovoId]); // Invalidate cache Cache::tags(['stampe_rate_templates'])->flush(); return response()->json([ 'success' => 'Template duplicato con successo', 'nuovo_id' => $nuovoId, 'redirect' => route('stampeRate.templates.edit', $nuovoId) ]); } catch (\Exception $e) { DB::rollBack(); Log::error("Errore duplicazione template: " . $e->getMessage()); return response()->json(['error' => 'Errore nella duplicazione del template'], 500); } } /** * Pubblica un template (lo rende attivo) */ public function publish($templateId) { try { $updated = DB::table('stampe_templates') ->where('id', $templateId) ->where('module', 'stampe_rate') ->where('deleted_at', null) ->update([ 'status' => 'attivo', 'pubblicato_at' => now(), 'updated_at' => now() ]); if (!$updated) { return response()->json(['error' => 'Template non trovato'], 404); } $this->hookManager->execute('stampe_rate.templates.published', [$templateId]); // Invalidate cache Cache::tags(['stampe_rate_templates'])->flush(); return response()->json(['success' => 'Template pubblicato con successo']); } catch (\Exception $e) { Log::error("Errore pubblicazione template: " . $e->getMessage()); return response()->json(['error' => 'Errore nella pubblicazione del template'], 500); } } /** * Rimuove un template dalla pubblicazione */ public function unpublish($templateId) { try { $updated = DB::table('stampe_templates') ->where('id', $templateId) ->where('module', 'stampe_rate') ->where('deleted_at', null) ->update([ 'status' => 'bozza', 'updated_at' => now() ]); if (!$updated) { return response()->json(['error' => 'Template non trovato'], 404); } $this->hookManager->execute('stampe_rate.templates.unpublished', [$templateId]); // Invalidate cache Cache::tags(['stampe_rate_templates'])->flush(); return response()->json(['success' => 'Template rimosso dalla pubblicazione']); } catch (\Exception $e) { Log::error("Errore rimozione pubblicazione template: " . $e->getMessage()); return response()->json(['error' => 'Errore nella rimozione dalla pubblicazione'], 500); } } /** * Genera anteprima del template */ public function preview($templateId) { try { $template = DB::table('stampe_templates') ->where('id', $templateId) ->where('module', 'stampe_rate') ->where('deleted_at', null) ->first(); if (!$template) { return response()->json(['error' => 'Template non trovato'], 404); } // Dati di esempio per l'anteprima $datiEsempio = [ 'condominio' => [ 'nome' => 'Condominio Example', 'indirizzo' => 'Via Roma 123, 00100 Roma', 'codice_fiscale' => '12345678901', 'amministratore' => 'Mario Rossi' ], 'rata' => [ 'numero' => '001/2025', 'importo' => '150,00', 'scadenza' => '31/01/2025', 'descrizione' => 'Rata mensile gennaio 2025' ], 'proprietario' => [ 'nome' => 'Giuseppe Verdi', 'indirizzo' => 'Via Milano 456, 00200 Roma', 'codice_fiscale' => 'VRDGPP70A01H501X', 'interno' => 'A/12' ] ]; // Sostituisce variabili nel template $htmlContent = $this->sostituisciVariabili($template->html_content, $datiEsempio); return response()->json([ 'success' => true, 'html' => $htmlContent, 'css' => $template->css_content ]); } catch (\Exception $e) { Log::error("Errore anteprima template: " . $e->getMessage()); return response()->json(['error' => 'Errore nella generazione dell\'anteprima'], 500); } } /** * Import template da file */ public function import() { return view('modules.stampe-rate.templates.import'); } /** * Elabora import template */ public function processImport(Request $request) { $validator = Validator::make($request->all(), [ 'template_file' => 'required|file|mimes:json,zip|max:10240' ]); if ($validator->fails()) { return back()->withErrors($validator); } DB::beginTransaction(); try { $file = $request->file('template_file'); $extension = $file->getClientOriginalExtension(); if ($extension === 'json') { $contenuto = json_decode(file_get_contents($file->path()), true); $templateImportati = $this->importaTemplateJSON($contenuto); } else { // ZIP con multipli template $templateImportati = $this->importaTemplateZIP($file); } DB::commit(); // Invalidate cache Cache::tags(['stampe_rate_templates'])->flush(); return redirect()->route('stampeRate.templates.index') ->with('success', "Importati {$templateImportati} template con successo!"); } catch (\Exception $e) { DB::rollBack(); Log::error("Errore import template: " . $e->getMessage()); return back()->with('error', 'Errore nell\'importazione: ' . $e->getMessage()); } } /** * Export template in formato JSON */ public function export($templateId) { try { $template = DB::table('stampe_templates') ->where('id', $templateId) ->where('module', 'stampe_rate') ->where('deleted_at', null) ->first(); if (!$template) { return response()->json(['error' => 'Template non trovato'], 404); } $exportData = [ 'nome' => $template->nome, 'descrizione' => $template->descrizione, 'categoria' => $template->categoria, 'html_content' => $template->html_content, 'css_content' => $template->css_content, 'variabili' => json_decode($template->variabili, true), 'tags' => $template->tags, 'versione' => $template->versione, 'export_date' => now()->toISOString(), 'export_by' => auth()->user()->name ?? 'Sistema' ]; $fileName = 'template_' . slug($template->nome) . '_' . date('Y-m-d') . '.json'; return response()->json($exportData) ->header('Content-Disposition', 'attachment; filename="' . $fileName . '"') ->header('Content-Type', 'application/json'); } catch (\Exception $e) { Log::error("Errore export template: " . $e->getMessage()); return response()->json(['error' => 'Errore nell\'export del template'], 500); } } /** * Marketplace template (per sviluppi futuri) */ public function marketplace() { // Placeholder per marketplace futuro return view('modules.stampe-rate.templates.marketplace'); } /** * Installa template dal marketplace */ public function installFromMarketplace($templateId) { // Placeholder per installazione da marketplace return response()->json(['info' => 'Funzionalità in sviluppo']); } /** * Ottiene template base predefiniti */ private function getTemplateBase($tipo) { $templates = [ 'semplice' => [ 'nome' => 'Template Semplice', 'html' => '
Rata: {{rata.numero}} - Importo: €{{rata.importo}}
