✅ CONTROLLERS IMPLEMENTATI: - VoceSpesaController: CRUD completo con filtri avanzati, duplicazione, AJAX - RipartizioneSpesaController: Calcolo automatico/manuale, workflow stati - PianoRateizzazioneController: Gestione piani rate con calcolo interessi - RataController: Pagamenti, posticipazioni, report, export CSV ✅ INTERFACCE UI RESPONSIVE: - Voci di Spesa: Elenco filtrato, form creazione Bootstrap 5 - Design System: Layout moderno con Font Awesome, responsive - Filtri Real-time: Aggiornamento automatico con AJAX - Validazioni: Client-side e server-side ✅ SISTEMA AUTORIZZAZIONI: - Policies complete per tutti i modelli - Controlli ownership per amministratori - Role-based access control - Data integrity e security ✅ FUNZIONALITÀ AVANZATE: - Calcoli automatici millesimi e rate - Gestione stati workflow (bozza→confermata→completata) - Codici alfanumerici univoci (SP, RP, PR) - Transazioni atomiche con rollback - Export CSV e reporting 🚀 SISTEMA CORE OPERATIVO: Pronto per gestione completa spese condominiali 📱 UI PRODUCTION-READY: Interfacce moderne e intuitive 🔐 SICUREZZA COMPLETA: Autorizzazioni e validazioni robuste 📊 BUSINESS LOGIC: Calcoli automatici e workflow operativi Next: Implementazione viste rimanenti e sistema plugin
494 lines
13 KiB
Markdown
494 lines
13 KiB
Markdown
# 📋 **NetGesCon Laravel - Documentazione Maschere e Interfacce**
|
|
|
|
## 📍 **STATO DEL PROGETTO**
|
|
- **Fase**: Business Logic Core completata
|
|
- **Prossima fase**: Sviluppo interfacce utente responsive
|
|
- **Livello**: Pronto per sviluppo controller e viste
|
|
|
|
---
|
|
|
|
## 🎯 **STRUTTURA VERIFICATA - COLLEGAMENTI FUNZIONALI**
|
|
|
|
### ✅ **Voci di Spesa → Tabelle Millesimali**
|
|
Le voci di spesa sono correttamente collegate al sistema millesimale:
|
|
|
|
```php
|
|
// VoceSpesa.php - Relazione con tabella millesimale
|
|
public function tabellaMillesimaleDefault()
|
|
{
|
|
return $this->belongsTo(TabellaMillesimale::class, 'tabella_millesimale_default_id');
|
|
}
|
|
|
|
// Collegamento alla ripartizione spese
|
|
public function ripartizioniSpese()
|
|
{
|
|
return $this->hasMany(RipartizioneSpese::class);
|
|
}
|
|
```
|
|
|
|
### ✅ **Workflow Completo di Ripartizione**
|
|
1. **Voce Spesa** → definisce la spesa e tabella millesimale di default
|
|
2. **Ripartizione Spese** → calcola la ripartizione per ogni unità
|
|
3. **Dettaglio Ripartizione** → importo specifico per ogni unità
|
|
4. **Piano Rateizzazione** → gestione pagamenti dilazionati
|
|
5. **Rate** → singole scadenze di pagamento
|
|
|
|
---
|
|
|
|
## 🎨 **STANDARDIZZAZIONE SVILUPPO UI**
|
|
|
|
### **1. Struttura Base per Maschere Laravel**
|
|
|
|
#### **A. Layout Base Responsive**
|
|
```php
|
|
// resources/views/layouts/app.blade.php
|
|
<!DOCTYPE html>
|
|
<html lang="it">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>@yield('title', 'NetGesCon')</title>
|
|
|
|
<!-- Bootstrap 5 + Custom CSS -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="{{ asset('css/netgescon.css') }}" rel="stylesheet">
|
|
|
|
<!-- Font Awesome -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
|
</head>
|
|
<body>
|
|
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
|
<div class="container">
|
|
<a class="navbar-brand" href="{{ route('dashboard') }}">
|
|
<i class="fas fa-building"></i> NetGesCon
|
|
</a>
|
|
<!-- Navigation menu -->
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="container-fluid mt-4">
|
|
<div class="row">
|
|
<div class="col-md-2">
|
|
@include('partials.sidebar')
|
|
</div>
|
|
<div class="col-md-10">
|
|
@yield('content')
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scripts -->
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="{{ asset('js/netgescon.js') }}"></script>
|
|
@yield('scripts')
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
#### **B. Componenti Standard per Form**
|
|
```php
|
|
// resources/views/components/form-input.blade.php
|
|
@props(['name', 'label', 'type' => 'text', 'required' => false, 'value' => ''])
|
|
|
|
<div class="mb-3">
|
|
<label for="{{ $name }}" class="form-label">
|
|
{{ $label }}
|
|
@if($required)
|
|
<span class="text-danger">*</span>
|
|
@endif
|
|
</label>
|
|
<input
|
|
type="{{ $type }}"
|
|
class="form-control @error($name) is-invalid @enderror"
|
|
id="{{ $name }}"
|
|
name="{{ $name }}"
|
|
value="{{ old($name, $value) }}"
|
|
@if($required) required @endif
|
|
>
|
|
@error($name)
|
|
<div class="invalid-feedback">{{ $message }}</div>
|
|
@enderror
|
|
</div>
|
|
```
|
|
|
|
#### **C. Componente Select per Relazioni**
|
|
```php
|
|
// resources/views/components/form-select.blade.php
|
|
@props(['name', 'label', 'options' => [], 'selected' => '', 'required' => false])
|
|
|
|
<div class="mb-3">
|
|
<label for="{{ $name }}" class="form-label">
|
|
{{ $label }}
|
|
@if($required)
|
|
<span class="text-danger">*</span>
|
|
@endif
|
|
</label>
|
|
<select
|
|
class="form-select @error($name) is-invalid @enderror"
|
|
id="{{ $name }}"
|
|
name="{{ $name }}"
|
|
@if($required) required @endif
|
|
>
|
|
<option value="">-- Seleziona --</option>
|
|
@foreach($options as $key => $value)
|
|
<option value="{{ $key }}" @if(old($name, $selected) == $key) selected @endif>
|
|
{{ $value }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
@error($name)
|
|
<div class="invalid-feedback">{{ $message }}</div>
|
|
@enderror
|
|
</div>
|
|
```
|
|
|
|
---
|
|
|
|
## 🏗️ **ARCHITETTURA CONTROLLER E VISTE**
|
|
|
|
### **1. Controller Standard Pattern**
|
|
|
|
#### **A. Controller Base per Gestione CRUD**
|
|
```php
|
|
// app/Http/Controllers/BaseController.php
|
|
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
abstract class BaseController extends Controller
|
|
{
|
|
protected $model;
|
|
protected $viewPath;
|
|
protected $routePrefix;
|
|
|
|
public function index(Request $request)
|
|
{
|
|
$query = $this->model::query();
|
|
|
|
// Filtri standard
|
|
if ($request->has('search')) {
|
|
$query = $this->applySearch($query, $request->search);
|
|
}
|
|
|
|
if ($request->has('stabile_id')) {
|
|
$query->where('stabile_id', $request->stabile_id);
|
|
}
|
|
|
|
$items = $query->paginate(20);
|
|
|
|
return view("{$this->viewPath}.index", compact('items'));
|
|
}
|
|
|
|
abstract protected function applySearch($query, $search);
|
|
|
|
public function create()
|
|
{
|
|
return view("{$this->viewPath}.create", $this->getFormData());
|
|
}
|
|
|
|
public function store(Request $request)
|
|
{
|
|
$this->validateRequest($request);
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
$item = $this->model::create($request->validated());
|
|
DB::commit();
|
|
|
|
return redirect()
|
|
->route("{$this->routePrefix}.show", $item)
|
|
->with('success', 'Elemento creato con successo');
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
return back()->with('error', 'Errore durante la creazione: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
abstract protected function validateRequest(Request $request);
|
|
abstract protected function getFormData();
|
|
}
|
|
```
|
|
|
|
#### **B. Controller Specifico per Voci di Spesa**
|
|
```php
|
|
// app/Http/Controllers/VoceSpesaController.php
|
|
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\VoceSpesa;
|
|
use App\Models\Stabile;
|
|
use App\Models\TabellaMillesimale;
|
|
use Illuminate\Http\Request;
|
|
|
|
class VoceSpesaController extends BaseController
|
|
{
|
|
protected $model = VoceSpesa::class;
|
|
protected $viewPath = 'voci_spesa';
|
|
protected $routePrefix = 'voci-spesa';
|
|
|
|
protected function applySearch($query, $search)
|
|
{
|
|
return $query->where(function($q) use ($search) {
|
|
$q->where('codice', 'LIKE', "%{$search}%")
|
|
->orWhere('descrizione', 'LIKE', "%{$search}%");
|
|
});
|
|
}
|
|
|
|
protected function validateRequest(Request $request)
|
|
{
|
|
return $request->validate([
|
|
'stabile_id' => 'required|exists:stabili,id',
|
|
'descrizione' => 'required|string|max:255',
|
|
'tipo_gestione' => 'required|in:ordinaria,straordinaria,speciale',
|
|
'categoria' => 'required|string',
|
|
'tabella_millesimale_default_id' => 'nullable|exists:tabelle_millesimali,id',
|
|
'ritenuta_acconto_default' => 'nullable|numeric|between:0,100',
|
|
'attiva' => 'boolean',
|
|
'ordinamento' => 'nullable|integer'
|
|
]);
|
|
}
|
|
|
|
protected function getFormData()
|
|
{
|
|
return [
|
|
'stabili' => Stabile::pluck('denominazione', 'id'),
|
|
'tabelleMillesimali' => TabellaMillesimale::pluck('denominazione', 'id'),
|
|
'categorie' => VoceSpesa::getCategorieStandard(),
|
|
'tipiGestione' => VoceSpesa::getTipiGestione()
|
|
];
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🎯 **MASCHERE PRINCIPALI DA IMPLEMENTARE**
|
|
|
|
### **1. Gestione Voci di Spesa**
|
|
- **Lista**: Filtri per stabile, categoria, tipo gestione
|
|
- **Dettaglio**: Visualizzazione completa con storico ripartizioni
|
|
- **Creazione/Modifica**: Form con validazione e selezione tabella millesimale
|
|
|
|
### **2. Gestione Ripartizione Spese**
|
|
- **Wizard di Ripartizione**: Step-by-step per calcolo automatico
|
|
- **Anteprima Ripartizione**: Visualizzazione prima della conferma
|
|
- **Gestione Esenzioni**: Interfaccia per escludere unità specifiche
|
|
|
|
### **3. Gestione Rate**
|
|
- **Piano Rateizzazione**: Creazione piani di pagamento
|
|
- **Calendario Scadenze**: Vista calendario con rate in scadenza
|
|
- **Gestione Pagamenti**: Registrazione e storico pagamenti
|
|
|
|
### **4. Dashboard Amministratore**
|
|
- **Riepilogo Finanziario**: Grafici e statistiche
|
|
- **Scadenze Imminenti**: Alert per rate in scadenza
|
|
- **Stato Ripartizioni**: Monitoraggio ripartizioni aperte
|
|
|
|
---
|
|
|
|
## 🔧 **STRUMENTI E INTEGRAZIONI**
|
|
|
|
### **1. Validazione Client-Side**
|
|
```javascript
|
|
// public/js/netgescon.js
|
|
class NetgesconValidator {
|
|
static validateRipartizione(form) {
|
|
const importo = parseFloat(form.importo_totale.value);
|
|
const tabellaId = form.tabella_millesimale_id.value;
|
|
|
|
if (importo <= 0) {
|
|
this.showError('L\'importo deve essere maggiore di zero');
|
|
return false;
|
|
}
|
|
|
|
if (!tabellaId) {
|
|
this.showError('Seleziona una tabella millesimale');
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static showError(message) {
|
|
// Implementazione notifica errore
|
|
}
|
|
}
|
|
```
|
|
|
|
### **2. API JSON per Interazioni Ajax**
|
|
```php
|
|
// app/Http/Controllers/Api/RipartizioneSpesaController.php
|
|
public function calcolaAnteprima(Request $request)
|
|
{
|
|
$voceSpesa = VoceSpesa::find($request->voce_spesa_id);
|
|
$importoTotale = $request->importo_totale;
|
|
|
|
$ripartizione = new RipartizioneSpese();
|
|
$anteprima = $ripartizione->calcolaAnteprimaRipartizione(
|
|
$voceSpesa,
|
|
$importoTotale,
|
|
$request->tabella_millesimale_id
|
|
);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'anteprima' => $anteprima,
|
|
'totale_calcolato' => $anteprima->sum('importo_calcolato')
|
|
]);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 **TEMI CSS PERSONALIZZATI**
|
|
|
|
### **1. Variabili CSS NetGesCon**
|
|
```css
|
|
/* public/css/netgescon.css */
|
|
:root {
|
|
--primary-color: #2c3e50;
|
|
--secondary-color: #3498db;
|
|
--success-color: #27ae60;
|
|
--warning-color: #f39c12;
|
|
--danger-color: #e74c3c;
|
|
--light-bg: #f8f9fa;
|
|
--dark-text: #2c3e50;
|
|
}
|
|
|
|
.card-netgescon {
|
|
border: none;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.btn-netgescon {
|
|
border-radius: 6px;
|
|
padding: 8px 16px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.table-netgescon {
|
|
border-collapse: separate;
|
|
border-spacing: 0;
|
|
}
|
|
|
|
.table-netgescon th {
|
|
background-color: var(--light-bg);
|
|
border-bottom: 2px solid var(--primary-color);
|
|
font-weight: 600;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔌 **PLUGIN SYSTEM ARCHITECTURE**
|
|
|
|
### **1. Struttura Base per Plugin**
|
|
```php
|
|
// app/Plugins/PluginInterface.php
|
|
interface PluginInterface
|
|
{
|
|
public function register(): void;
|
|
public function boot(): void;
|
|
public function getMenuItems(): array;
|
|
public function getRoutes(): array;
|
|
public function getViews(): array;
|
|
}
|
|
|
|
// app/Plugins/BasePlugin.php
|
|
abstract class BasePlugin implements PluginInterface
|
|
{
|
|
protected $name;
|
|
protected $version;
|
|
protected $description;
|
|
|
|
public function register(): void
|
|
{
|
|
// Registrazione servizi base
|
|
}
|
|
|
|
abstract public function boot(): void;
|
|
}
|
|
```
|
|
|
|
### **2. Plugin Manager**
|
|
```php
|
|
// app/Services/PluginManager.php
|
|
class PluginManager
|
|
{
|
|
protected $plugins = [];
|
|
|
|
public function loadPlugin($pluginClass)
|
|
{
|
|
$plugin = new $pluginClass();
|
|
$plugin->register();
|
|
$plugin->boot();
|
|
|
|
$this->plugins[] = $plugin;
|
|
}
|
|
|
|
public function getMenuItems()
|
|
{
|
|
$items = [];
|
|
foreach ($this->plugins as $plugin) {
|
|
$items = array_merge($items, $plugin->getMenuItems());
|
|
}
|
|
return $items;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 **PROSSIMI STEP IMPLEMENTATIVI**
|
|
|
|
### **Fase 1: Implementazione Controller e Viste Base**
|
|
1. Creazione controller per VoceSpesa, RipartizioneSpese, Rate
|
|
2. Implementazione viste index, create, edit, show
|
|
3. Configurazione rotte e middleware
|
|
|
|
### **Fase 2: Interfacce Avanzate**
|
|
1. Wizard ripartizione spese con preview
|
|
2. Dashboard amministratore con grafici
|
|
3. Calendario scadenze interattivo
|
|
|
|
### **Fase 3: Integrazioni**
|
|
1. Sistema notifiche (email, SMS)
|
|
2. Export PDF/Excel
|
|
3. API REST per app mobile
|
|
|
|
---
|
|
|
|
## 🎯 **CHECKLIST SVILUPPO**
|
|
|
|
### **Backend**
|
|
- [x] Modelli Eloquent completi
|
|
- [x] Relazioni verificate
|
|
- [x] Migration funzionali
|
|
- [ ] Controller CRUD
|
|
- [ ] Validazione form
|
|
- [ ] API endpoints
|
|
|
|
### **Frontend**
|
|
- [ ] Layout responsive
|
|
- [ ] Componenti riutilizzabili
|
|
- [ ] Validazione client-side
|
|
- [ ] Interfacce wizard
|
|
- [ ] Dashboard grafici
|
|
|
|
### **Integrazioni**
|
|
- [ ] Sistema notifiche
|
|
- [ ] Export documenti
|
|
- [ ] Plugin system
|
|
- [ ] Mobile API
|
|
|
|
---
|
|
|
|
**Aggiornato**: 2025-01-27
|
|
**Versione**: 1.0
|
|
**Prossimo update**: Dopo implementazione primi controller
|