++ Primo Caricamento

This commit is contained in:
2026-03-30 19:15:13 +02:00
commit 663a68d59b
47 changed files with 3561 additions and 0 deletions

107
app/Models/Customer.php Normal file
View File

@@ -0,0 +1,107 @@
<?php
namespace App\Models;
// ─────────────────────────────────────────────────────────────────────────────
// Model Customer — rappresenta un cliente nel database
//
// In Laravel, un Model è una classe PHP che:
// 1. Mappa una tabella del DB (per default: nome classe pluralizzato → "customers")
// 2. Permette di leggere, creare, aggiornare e cancellare record (CRUD)
// 3. Definisce le relazioni con altri Model
//
// Usa Eloquent ORM: invece di scrivere SQL raw, usi metodi PHP come:
// Customer::all() → SELECT * FROM customers
// Customer::find(1) → SELECT * FROM customers WHERE id=1
// Customer::where('city', 'Roma') → SELECT * FROM customers WHERE city='Roma'
// ─────────────────────────────────────────────────────────────────────────────
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Customer extends Model
{
use HasFactory;
use SoftDeletes; // Soft delete: non cancella davvero dal DB, imposta deleted_at
// ─── Tabella del database ──────────────────────────────────────────────
// Non è necessario specificarlo se il nome è il plurale della classe
// (Customer → customers). Lo specifichiamo esplicitamente per chiarezza.
protected $table = 'customers';
// ─── Campi modificabili (mass assignment) ─────────────────────────────
// Per sicurezza, Laravel blocca l'aggiornamento di massa di tutti i campi.
// Solo i campi elencati qui possono essere modificati con create() o fill().
// Alternativa: usa $guarded = [] per permettere tutto (meno sicuro).
protected $fillable = [
'name', // Ragione sociale o nome completo
'email', // Email principale di contatto
'phone', // Telefono
'city', // Città
'address', // Indirizzo completo
'vat_number', // Partita IVA
'fiscal_code', // Codice fiscale
'type', // 'privato' o 'azienda'
'status', // 'attivo', 'inattivo', 'prospect'
'notes', // Note libere
'contract_value', // Valore contratto annuo
];
// ─── Cast automatici ──────────────────────────────────────────────────
// Eloquent converte automaticamente il tipo quando leggi/scrivi il campo.
// 'decimal:2' → restituisce un float con 2 decimali
// 'boolean' → converte 0/1 del DB in true/false PHP
protected $casts = [
'contract_value' => 'decimal:2',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
// ─── Scope: filtri riutilizzabili ─────────────────────────────────────
// Un "scope" è un metodo che aggiunge condizioni alla query.
// Uso: Customer::active()->get()
// invece di: Customer::where('status', 'attivo')->get()
public function scopeActive($query)
{
return $query->where('status', 'attivo');
}
public function scopeByType($query, string $type)
{
return $query->where('type', $type);
}
public function scopeSearch($query, string $term)
{
return $query->where(function ($q) use ($term) {
$q->where('name', 'like', "%{$term}%")
->orWhere('email', 'like', "%{$term}%")
->orWhere('city', 'like', "%{$term}%")
->orWhere('vat_number', 'like', "%{$term}%");
});
}
// ─── Accessor: trasforma il valore quando lo leggi ───────────────────
// Uso: $customer->badge_color → restituisce il colore Bootstrap
public function getBadgeColorAttribute(): string
{
return match ($this->status) {
'attivo' => 'success',
'inattivo' => 'secondary',
'prospect' => 'warning',
default => 'light',
};
}
public function getTypeLabelAttribute(): string
{
return match ($this->type) {
'privato' => 'Privato',
'azienda' => 'Azienda',
default => 'N/D',
};
}
}

44
app/Models/Setting.php Normal file
View File

@@ -0,0 +1,44 @@
<?php
namespace App\Models;
// ─────────────────────────────────────────────────────────────────────────────
// Model Setting — gestisce le impostazioni dinamiche dell'applicazione
//
// Ogni riga della tabella `settings` è una coppia chiave-valore.
// Esempio:
// key: "items_per_page" value: "15"
// key: "currency_symbol" value: "€"
//
// I valori sono sempre stringhe nel DB. SettingService gestisce il cast
// al tipo corretto (int, bool, string, ecc.) basandosi su config/settings.php
// ─────────────────────────────────────────────────────────────────────────────
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
protected $table = 'settings';
protected $fillable = [
'key',
'value',
'label', // Nome leggibile mostrato nel pannello admin
'group', // Gruppo di appartenenza (es. "Azienda", "Visualizzazione")
'type', // Tipo dato: string, integer, boolean, text
];
// Non usiamo timestamps per le impostazioni (semplifica la tabella)
public $timestamps = true;
// ─── Scope: cerca per chiave ──────────────────────────────────────────
public function scopeForKey($query, string $key)
{
return $query->where('key', $key);
}
public function scopeInGroup($query, string $group)
{
return $query->where('group', $group);
}
}