netgescon-day0/app/Modules/StampeRate/Controllers/TemplateController.php

775 lines
28 KiB
PHP

<?php
namespace App\Modules\StampeRate\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\Controller;
use App\Services\HookManager;
use Carbon\Carbon;
/**
* Controller per la gestione dei template di stampa
* Modulo: Stampe Rate Avanzate
*
* Gestisce i template HTML/CSS per la generazione dei PDF delle rate
* Include funzionalità di preview, duplicazione, import/export
* e marketplace per template condivisi
*/
class TemplateController extends Controller
{
protected $hookManager;
public function __construct()
{
// Middleware per permessi modulo
$this->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' => '<div class="documento"><h1>{{condominio.nome}}</h1><p>Rata: {{rata.numero}} - Importo: €{{rata.importo}}</p></div>',
'css' => '.documento { font-family: Arial; padding: 20px; }'
],
'professionale' => [
'nome' => 'Template Professionale',
'html' => '<div class="header"><img src="logo.png" alt="Logo"/><h1>{{condominio.nome}}</h1></div><div class="content">{{rata.descrizione}}</div>',
'css' => '.header { border-bottom: 2px solid #333; } .content { margin-top: 20px; }'
],
'moderno' => [
'nome' => 'Template Moderno',
'html' => '<div class="modern-doc"><div class="sidebar">{{proprietario.nome}}</div><div class="main-content">{{rata.descrizione}}</div></div>',
'css' => '.modern-doc { display: flex; } .sidebar { width: 30%; background: #f5f5f5; }'
]
];
return $templates[$tipo] ?? $templates['semplice'];
}
/**
* Sostituisce variabili nel template con dati reali
*/
private function sostituisciVariabili($html, $dati)
{
foreach ($dati as $categoria => $valori) {
foreach ($valori as $campo => $valore) {
$placeholder = "{{" . $categoria . "." . $campo . "}}";
$html = str_replace($placeholder, $valore, $html);
}
}
return $html;
}
/**
* Importa template da JSON
*/
private function importaTemplateJSON($dati)
{
if (!isset($dati['nome']) || !isset($dati['html_content'])) {
throw new \Exception('File JSON non valido');
}
DB::table('stampe_templates')->insert([
'nome' => $dati['nome'] . ' (Importato)',
'descrizione' => $dati['descrizione'] ?? '',
'categoria' => $dati['categoria'] ?? 'rate_standard',
'module' => 'stampe_rate',
'html_content' => $dati['html_content'],
'css_content' => $dati['css_content'] ?? '',
'variabili' => json_encode($dati['variabili'] ?? []),
'tags' => $dati['tags'] ?? '',
'status' => 'bozza',
'versione' => $dati['versione'] ?? '1.0.0',
'created_by' => auth()->id(),
'created_at' => now(),
'updated_at' => now()
]);
return 1;
}
/**
* Importa template da ZIP
*/
private function importaTemplateZIP($file)
{
// Implementazione futura per import multipli da ZIP
throw new \Exception('Import da ZIP non ancora implementato');
}
/**
* API: Ottiene lista template per AJAX
*/
public function getTemplates(Request $request)
{
try {
$query = DB::table('stampe_templates')
->where('module', 'stampe_rate')
->where('status', 'attivo')
->where('deleted_at', null);
if ($request->filled('categoria')) {
$query->where('categoria', $request->get('categoria'));
}
$templates = $query->select('id', 'nome', 'descrizione', 'categoria')->get();
return response()->json(['templates' => $templates]);
} catch (\Exception $e) {
Log::error("Errore API template: " . $e->getMessage());
return response()->json(['error' => 'Errore nel caricamento dei template'], 500);
}
}
}