380 lines
14 KiB
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()
|
|
];
|
|
}
|
|
}
|