netgescon-master/docs/02-architettura-laravel/specifiche/LARAVEL_FORMS_DOCUMENTATION.md
Pikappa2 480e7eafbd 🎯 NETGESCON - Setup iniziale repository completo
📋 Commit iniziale con:
-  Documentazione unificata in docs/
-  Codice Laravel in netgescon-laravel/
-  Script automazione in scripts/
-  Configurazione sync rsync
-  Struttura organizzata e pulita

🔄 Versione: 2025.07.19-1644
🎯 Sistema pronto per Git distribuito
2025-07-19 16:44:47 +02:00

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