++ gruppi di servizio: sorvegliante con utenza limitata, pacchetto di territori, assegnazione ai membri

Il gruppo ha un sorvegliante (proclamatore con utenza: email e password
temporanea, senza conferma dell'email) e dei membri; l'amministratore
mette in blocco dei territori nel pacchetto del gruppo. Il pacchetto non
e' un'assegnazione e non tocca le statistiche; quando il sorvegliante da'
un territorio a un membro nasce un'assegnazione normale con
gruppo_servizio_id. Al rientro il territorio torna in reparto. Sciogliere
il gruppo libera pacchetto e membri e disattiva l'utenza.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Francesco Picone
2026-10-19 17:51:37 +02:00
parent 5d0ae06eca
commit 96084499f5
41 changed files with 2298 additions and 224 deletions

View File

@@ -0,0 +1,78 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;
/**
* Gruppi di servizio (richiesta del 19 ottobre 2026).
*
* - gruppi_servizio: il gruppo, con il suo sorvegliante (un proclamatore) e
* sciolto_at quando viene sciolto (resta nello storico: le assegnazioni
* nate dal gruppo continuano a dirlo).
* - proclamatori.gruppo_servizio_id: i membri, un solo gruppo a testa.
* - territori.gruppo_servizio_id: il pacchetto del gruppo. Un territorio nel
* pacchetto non ancora dato a nessuno è "in carico al gruppo"; il pacchetto
* non è un'assegnazione e non entra nelle statistiche.
* - assegnazioni.gruppo_servizio_id: l'assegnazione è nata dal gruppo (data
* dal sorvegliante a un membro). È un'assegnazione normale a tutti gli
* effetti, segnata così.
* - users.proclamatore_id: l'utenza del sorvegliante, collegata al suo
* proclamatore. users.disattivato_at: utenza che non può più entrare (un
* gruppo sciolto disattiva quella del suo sorvegliante).
* - Ruolo "sorvegliante" con il solo permesso "gruppo.gestisci". Si crea qui
* e non solo nel seeder, che sulle installazioni esistenti non gira più.
*/
return new class extends Migration
{
public function up(): void
{
Schema::create('gruppi_servizio', function (Blueprint $table) {
$table->id();
$table->string('nome', 100);
$table->foreignId('sorvegliante_id')->nullable()->constrained('proclamatori')->nullOnDelete();
$table->timestamp('sciolto_at')->nullable();
$table->timestamps();
});
Schema::table('proclamatori', function (Blueprint $table) {
$table->foreignId('gruppo_servizio_id')->nullable()->after('attivo')->constrained('gruppi_servizio')->nullOnDelete();
});
Schema::table('territori', function (Blueprint $table) {
$table->foreignId('gruppo_servizio_id')->nullable()->after('prioritario')->constrained('gruppi_servizio')->nullOnDelete();
});
Schema::table('assegnazioni', function (Blueprint $table) {
$table->foreignId('gruppo_servizio_id')->nullable()->after('campaign_id')->constrained('gruppi_servizio')->nullOnDelete();
});
Schema::table('users', function (Blueprint $table) {
$table->foreignId('proclamatore_id')->nullable()->unique()->after('email')->constrained('proclamatori')->nullOnDelete();
$table->timestamp('disattivato_at')->nullable()->after('password_change_required');
});
$permesso = Permission::firstOrCreate(['name' => 'gruppo.gestisci', 'guard_name' => 'web']);
Role::firstOrCreate(['name' => 'sorvegliante', 'guard_name' => 'web'])->givePermissionTo($permesso);
app(PermissionRegistrar::class)->forgetCachedPermissions();
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropConstrainedForeignId('proclamatore_id');
$table->dropColumn('disattivato_at');
});
Schema::table('assegnazioni', fn (Blueprint $table) => $table->dropConstrainedForeignId('gruppo_servizio_id'));
Schema::table('territori', fn (Blueprint $table) => $table->dropConstrainedForeignId('gruppo_servizio_id'));
Schema::table('proclamatori', fn (Blueprint $table) => $table->dropConstrainedForeignId('gruppo_servizio_id'));
Schema::dropIfExists('gruppi_servizio');
Role::where('name', 'sorvegliante')->delete();
Permission::where('name', 'gruppo.gestisci')->delete();
app(PermissionRegistrar::class)->forgetCachedPermissions();
}
};

View File

@@ -25,6 +25,7 @@ class RolesAndPermissionsSeeder extends Seeder
'territori.return',
'audit.view',
'audit.export',
'gruppo.gestisci',
];
foreach ($permissions as $permission) {
@@ -43,7 +44,9 @@ class RolesAndPermissionsSeeder extends Seeder
// Amministratore: all permissions
$admin = Role::firstOrCreate(['name' => 'amministratore']);
$admin->givePermissionTo($permissions);
// Tutti tranne gruppo.gestisci, che è del solo sorvegliante: l'admin
// gestisce i gruppi da settings.manage, non ne ha uno suo.
$admin->givePermissionTo(array_values(array_diff($permissions, ['gruppo.gestisci'])));
// Assistente: proclamatori, campagne, assign, return
$assistente = Role::firstOrCreate(['name' => 'assistente']);
@@ -61,5 +64,10 @@ class RolesAndPermissionsSeeder extends Seeder
'territori.assign',
'territori.return',
]);
// Sorvegliante di gruppo: solo il proprio gruppo di servizio. Il ruolo
// si dà creando un gruppo (Gruppi di servizio), mai dalla pagina Utenti.
$sorvegliante = Role::firstOrCreate(['name' => 'sorvegliante']);
$sorvegliante->givePermissionTo(['gruppo.gestisci']);
}
}