netgescon-master/app/Http/Controllers/Admin/DocumentoCollegatoController.php

380 lines
14 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\DocumentoCollegato;
use App\Models\Stabile;
use App\Models\RubricaUniversale;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Carbon\Carbon;
class DocumentoCollegatoController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$query = DocumentoCollegato::with(['stabile', 'contatto']);
// Filtri
if ($request->filled('categoria')) {
$query->where('tipo_documento', $request->categoria);
}
if ($request->filled('anno')) {
$query->whereYear('data_sottoscrizione', $request->anno);
}
if ($request->filled('search')) {
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('titolo', 'like', "%{$search}%")
->orWhere('numero_protocollo', 'like', "%{$search}%")
->orWhere('descrizione', 'like', "%{$search}%");
});
}
$documenti = $query->orderBy('created_at', 'desc')->paginate(15);
return view('admin.documenti-collegati.index', compact('documenti'));
}
/**
* Display a listing of the resource for a specific stabile.
*/
public function indexByStabile(Stabile $stabile)
{
$documenti = $stabile->documentiCollegati()
->with('contatto')
->orderBy('created_at', 'desc')
->get();
$statistiche = $this->calcolaStatistiche($stabile);
return response()->json([
'success' => true,
'data' => $documenti,
'statistiche' => $statistiche
]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$stabili = Stabile::orderBy('denominazione')->get();
$contatti = RubricaUniversale::attivi()->orderBy('nome_completo')->get();
return view('admin.documenti-collegati.create', compact('stabili', 'contatti'));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$validated = $request->validate([
'stabile_id' => 'required|exists:stabili,id',
'contatto_id' => 'nullable|exists:rubrica_universale,id',
'tipo_documento' => 'required|in:contratto,assicurazione,certificato,preventivo,fattura,verbale,altro',
'titolo' => 'required|string|max:255',
'descrizione' => 'nullable|string',
'data_sottoscrizione' => 'required|date',
'data_scadenza' => 'nullable|date|after:data_sottoscrizione',
'data_disdetta_limite' => 'nullable|date',
'giorni_preavviso_disdetta' => 'nullable|integer|min:1|max:365',
'tipo_contratto' => 'nullable|in:mensile,bimestrale,trimestrale,semestrale,annuale',
'importo_contratto' => 'nullable|numeric|min:0',
'valuta' => 'string|max:3|default:EUR',
'stato_documento' => 'required|in:attivo,scaduto,disdetto,rinnovato',
'numero_pagine_totali' => 'nullable|integer|min:1',
'note' => 'nullable|string',
'file_documento' => 'nullable|file|mimes:pdf,doc,docx,jpg,jpeg,png|max:10240' // 10MB max
]);
// Genera numero di protocollo automatico
$validated['numero_protocollo'] = $this->generaNumeroProtocollo($validated['tipo_documento']);
$validated['creato_da'] = Auth::id();
// Gestione upload file
if ($request->hasFile('file_documento')) {
$file = $request->file('file_documento');
$fileName = $validated['numero_protocollo'] . '_' . Str::slug($validated['titolo']) . '.' . $file->getClientOriginalExtension();
$filePath = $file->storeAs('documenti-collegati', $fileName, 'public');
$validated['path_file_originale'] = $filePath;
}
$documento = DocumentoCollegato::create($validated);
return redirect()
->route('admin.documenti-collegati.show', $documento)
->with('success', 'Documento creato con successo. Protocollo: ' . $validated['numero_protocollo']);
}
/**
* Store a newly created resource for a specific stabile.
*/
public function storeForStabile(Request $request, Stabile $stabile)
{
$validated = $request->validate([
'contatto_id' => 'nullable|exists:rubrica_universale,id',
'tipo_documento' => 'required|in:contratto,assicurazione,certificato,preventivo,fattura,verbale,altro',
'titolo' => 'required|string|max:255',
'descrizione' => 'nullable|string',
'data_sottoscrizione' => 'required|date',
'data_scadenza' => 'nullable|date|after:data_sottoscrizione',
'data_disdetta_limite' => 'nullable|date',
'giorni_preavviso_disdetta' => 'nullable|integer|min:1|max:365',
'tipo_contratto' => 'nullable|in:mensile,bimestrale,trimestrale,semestrale,annuale',
'importo_contratto' => 'nullable|numeric|min:0',
'valuta' => 'string|max:3|default:EUR',
'stato_documento' => 'required|in:attivo,scaduto,disdetto,rinnovato',
'numero_pagine_totali' => 'nullable|integer|min:1',
'note' => 'nullable|string'
]);
$validated['stabile_id'] = $stabile->id;
$validated['numero_protocollo'] = $this->generaNumeroProtocollo($validated['tipo_documento']);
$validated['creato_da'] = Auth::id();
$documento = DocumentoCollegato::create($validated);
return response()->json([
'success' => true,
'message' => 'Documento creato con successo.',
'data' => $documento->load('contatto'),
'protocollo' => $validated['numero_protocollo']
]);
}
/**
* Display the specified resource.
*/
public function show(DocumentoCollegato $documentoCollegato)
{
$documentoCollegato->load(['stabile', 'contatto', 'createdBy', 'updatedBy']);
return view('admin.documenti-collegati.show', compact('documentoCollegato'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(DocumentoCollegato $documentoCollegato)
{
$stabili = Stabile::orderBy('denominazione')->get();
$contatti = RubricaUniversale::attivi()->orderBy('nome_completo')->get();
return view('admin.documenti-collegati.edit', compact('documentoCollegato', 'stabili', 'contatti'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, DocumentoCollegato $documentoCollegato)
{
$validated = $request->validate([
'contatto_id' => 'nullable|exists:rubrica_universale,id',
'tipo_documento' => 'required|in:contratto,assicurazione,certificato,preventivo,fattura,verbale,altro',
'titolo' => 'required|string|max:255',
'descrizione' => 'nullable|string',
'data_sottoscrizione' => 'required|date',
'data_scadenza' => 'nullable|date|after:data_sottoscrizione',
'data_disdetta_limite' => 'nullable|date',
'giorni_preavviso_disdetta' => 'nullable|integer|min:1|max:365',
'tipo_contratto' => 'nullable|in:mensile,bimestrale,trimestrale,semestrale,annuale',
'importo_contratto' => 'nullable|numeric|min:0',
'valuta' => 'string|max:3',
'stato_documento' => 'required|in:attivo,scaduto,disdetto,rinnovato',
'numero_pagine_totali' => 'nullable|integer|min:1',
'note' => 'nullable|string',
'file_documento' => 'nullable|file|mimes:pdf,doc,docx,jpg,jpeg,png|max:10240'
]);
$validated['modificato_da'] = Auth::id();
// Gestione upload file sostitutivo
if ($request->hasFile('file_documento')) {
// Elimina il file precedente se esiste
if ($documentoCollegato->path_file_originale) {
Storage::disk('public')->delete($documentoCollegato->path_file_originale);
}
$file = $request->file('file_documento');
$fileName = $documentoCollegato->numero_protocollo . '_' . Str::slug($validated['titolo']) . '.' . $file->getClientOriginalExtension();
$filePath = $file->storeAs('documenti-collegati', $fileName, 'public');
$validated['path_file_originale'] = $filePath;
}
$documentoCollegato->update($validated);
return redirect()
->route('admin.documenti-collegati.show', $documentoCollegato)
->with('success', 'Documento aggiornato con successo.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(DocumentoCollegato $documentoCollegato)
{
$stabileId = $documentoCollegato->stabile_id;
// Elimina il file associato
if ($documentoCollegato->path_file_originale) {
Storage::disk('public')->delete($documentoCollegato->path_file_originale);
}
$documentoCollegato->delete();
return redirect()
->route('admin.stabili.show', $stabileId)
->with('success', 'Documento eliminato con successo.');
}
/**
* Download document file.
*/
public function download(DocumentoCollegato $documento)
{
if (!$documento->path_file_originale || !Storage::disk('public')->exists($documento->path_file_originale)) {
return redirect()->back()->with('error', 'File non trovato.');
}
return Storage::disk('public')->download(
$documento->path_file_originale,
$documento->numero_protocollo . '_' . Str::slug($documento->titolo) . '.pdf'
);
}
/**
* Print archive label for document.
*/
public function stampaEtichetta(DocumentoCollegato $documento)
{
return view('admin.documenti-collegati.etichetta', compact('documento'));
}
/**
* Renew a document.
*/
public function rinnova(DocumentoCollegato $documento)
{
// Crea una copia del documento con nuove date
$nuovoDocumento = $documento->replicate();
$nuovoDocumento->numero_protocollo = $this->generaNumeroProtocollo($documento->tipo_documento);
$nuovoDocumento->data_sottoscrizione = Carbon::now();
$nuovoDocumento->data_scadenza = $documento->data_scadenza ?
Carbon::parse($documento->data_scadenza)->addYear() : null;
$nuovoDocumento->stato_documento = 'attivo';
$nuovoDocumento->creato_da = Auth::id();
$nuovoDocumento->save();
// Aggiorna il documento originale
$documento->update(['stato_documento' => 'rinnovato']);
return response()->json([
'success' => true,
'message' => 'Documento rinnovato con successo.',
'nuovo_protocollo' => $nuovoDocumento->numero_protocollo
]);
}
/**
* Get statistics for documents (API).
*/
public function getStatistiche($stabileId = null)
{
$query = DocumentoCollegato::query();
if ($stabileId) {
$query->where('stabile_id', $stabileId);
}
$statistiche = [
'contratti' => $query->clone()->where('tipo_documento', 'contratto')->where('stato_documento', 'attivo')->count(),
'assicurazioni' => $query->clone()->where('tipo_documento', 'assicurazione')->where('stato_documento', 'attivo')->count(),
'scadenze' => $query->clone()->where('data_scadenza', '<=', Carbon::now()->addDays(30))->where('stato_documento', 'attivo')->count(),
'totale' => $query->clone()->count(),
'scaduti' => $query->clone()->where('data_scadenza', '<', Carbon::now())->where('stato_documento', 'attivo')->count()
];
return response()->json([
'success' => true,
'statistiche' => $statistiche
]);
}
/**
* Get documents expiring soon (API).
*/
public function getScadenzeImminenti($giorni = 30)
{
$scadenze = DocumentoCollegato::with(['stabile', 'contatto'])
->where('data_scadenza', '<=', Carbon::now()->addDays($giorni))
->where('data_scadenza', '>=', Carbon::now())
->where('stato_documento', 'attivo')
->orderBy('data_scadenza')
->get();
return response()->json([
'success' => true,
'scadenze' => $scadenze
]);
}
/**
* Generate automatic protocol number.
*/
private function generaNumeroProtocollo($tipoDocumento)
{
$anno = date('Y');
$prefissi = [
'contratto' => 'CONTR',
'assicurazione' => 'ASSIC',
'certificato' => 'CERT',
'preventivo' => 'PREV',
'fattura' => 'FATT',
'verbale' => 'VERB',
'altro' => 'DOC'
];
$prefisso = $prefissi[$tipoDocumento] ?? 'DOC';
// Trova il prossimo numero progressivo per l'anno corrente
$ultimoNumero = DocumentoCollegato::where('numero_protocollo', 'like', "{$prefisso}-{$anno}-%")
->orderBy('numero_protocollo', 'desc')
->first();
$progressivo = 1;
if ($ultimoNumero) {
$parts = explode('-', $ultimoNumero->numero_protocollo);
$progressivo = (int)end($parts) + 1;
}
return sprintf('%s-%s-%03d', $prefisso, $anno, $progressivo);
}
/**
* Calculate statistics for a stabile.
*/
private function calcolaStatistiche(Stabile $stabile)
{
$documenti = $stabile->documentiCollegati();
return [
'contratti' => $documenti->clone()->where('tipo_documento', 'contratto')->where('stato_documento', 'attivo')->count(),
'assicurazioni' => $documenti->clone()->where('tipo_documento', 'assicurazione')->where('stato_documento', 'attivo')->count(),
'scadenze' => $documenti->clone()->where('data_scadenza', '<=', Carbon::now()->addDays(30))->where('stato_documento', 'attivo')->count(),
'totale' => $documenti->clone()->count(),
'scaduti' => $documenti->clone()->where('data_scadenza', '<', Carbon::now())->where('stato_documento', 'attivo')->count()
];
}
}