From 005fa5b4a3c2cf00d9f0b51d6ccd3342dd0d9f99 Mon Sep 17 00:00:00 2001 From: Mariano Date: Wed, 17 Jun 2026 19:13:40 +0200 Subject: [PATCH] sistemazione migrate --- MEMORY.md | 43 +++++++ ...2024_01_01_000001_create_tenants_table.php | 4 + ...01_000002_create_comuni_diocesi_tables.php | 42 +++--- ...24_01_01_000003_create_individui_table.php | 44 ++++--- ...024_01_01_000004_create_contatti_table.php | 22 ++-- .../2024_01_01_000005_create_gruppi_table.php | 38 +++--- ...1_000006_create_gruppo_individuo_table.php | 20 +-- .../2024_01_01_000007_create_eventi_table.php | 60 +++++---- ...24_01_01_000008_create_documenti_table.php | 34 ++--- ...024_01_01_000009_create_mailing_tables.php | 76 ++++++----- ...24_01_01_000010_create_notifiche_table.php | 26 ++-- .../2024_01_01_000011_create_users_table.php | 58 +++++---- ...01_000012_create_cache_and_jobs_tables.php | 90 +++++++------ ...1_000019_create_eventi_documenti_table.php | 14 +- ...01_01_000022_create_table_viste_report.php | 28 ++-- ...00001_create_tipologie_documenti_table.php | 18 +-- .../2026_05_10_000002_add_acl_tables.php | 46 ++++--- ..._05_10_125210_create_permission_tables.php | 120 ++++++++++-------- ..._11_000001_create_email_settings_table.php | 42 +++--- ...5_11_000002_create_email_folders_table.php | 24 ++-- ..._11_000003_create_email_messages_table.php | 60 ++++----- ..._000007_create_email_attachments_table.php | 24 ++-- .../2026_05_12_000001_create_ruoli_table.php | 18 +-- ...5_25_000001_create_report_custom_table.php | 20 +-- ...6_000001_create_tipologie_eventi_table.php | 18 +-- ...26_000002_create_sender_accounts_table.php | 32 ++--- ...000001_create_documenti_cartelle_table.php | 14 +- ...3245_create_storage_repositories_table.php | 20 +-- ...01_create_calendario_connessioni_table.php | 32 ++--- .../2026_06_08_194155_create_tags_tables.php | 4 +- database/seeders/ComuniSeeder.php | 2 +- database/seeders/DatabaseSeeder.php | 38 +++--- database/seeders/DiocesiSeeder.php | 2 +- 33 files changed, 635 insertions(+), 498 deletions(-) diff --git a/MEMORY.md b/MEMORY.md index 6cf9d2e3..438f91d6 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -380,3 +380,46 @@ if (!empty($contatto['individuo_id'])) { create } **Fix**: 1. `VistaReportController@update` (linea 101-103): aggiunto `if ($request->expectsJson()) { return response()->json([...]); }` — così il fetch riceve JSON 200, non un redirect 302. 2. Fetch headers in `table-settings.blade.php`: aggiunto `'Accept': 'application/json'` — necessario perché `expectsJson()` controlla l'header `Accept`, non `Content-Type`. + +## 2026-06-10 — Fix: tutte le migration idempotenti + seeders idempotenti + +**Problema**: `php artisan migrate` falliva su tabelle già esistenti. `php artisan db:seed` creava duplicati su re-run. + +### Migration: hasTable guard su tutti i 27 file mancanti + +Aggiunto `if (!Schema::hasTable('table_name')) { ... }` wrapper a tutte le 27 migration file (44 `Schema::create()` calls) che ne erano prive, usando script Node.js di trasformazione automatica: +- `2024_01_01_000002_create_comuni_diocesi_tables.php` +- `2024_01_01_000003_create_individui_table.php` +- `2024_01_01_000004_create_contatti_table.php` +- `2024_01_01_000005_create_gruppi_table.php` +- `2024_01_01_000006_create_gruppo_individuo_table.php` +- `2024_01_01_000007_create_eventi_table.php` +- `2024_01_01_000008_create_documenti_table.php` +- `2024_01_01_000009_create_mailing_tables.php` +- `2024_01_01_000010_create_notifiche_table.php` +- `2024_01_01_000011_create_users_table.php` +- `2024_01_01_000012_create_cache_and_jobs_tables.php` +- `2024_01_01_000019_create_eventi_documenti_table.php` +- `2024_01_01_000022_create_table_viste_report.php` +- `2026_05_10_000001_create_tipologie_documenti_table.php` +- `2026_05_10_000002_add_acl_tables.php` +- `2026_05_10_125210_create_permission_tables.php` (usa `$tableNames[...]` dinamici) +- `2026_05_11_000001_create_email_settings_table.php` +- `2026_05_11_000002_create_email_folders_table.php` +- `2026_05_11_000003_create_email_messages_table.php` +- `2026_05_11_000007_create_email_attachments_table.php` +- `2026_05_12_000001_create_ruoli_table.php` +- `2026_05_25_000001_create_report_custom_table.php` +- `2026_05_26_000001_create_tipologie_eventi_table.php` +- `2026_05_26_000002_create_sender_accounts_table.php` +- `2026_05_27_000001_create_documenti_cartelle_table.php` +- `2026_05_27_113245_create_storage_repositories_table.php` +- `2026_06_02_000001_create_calendario_connessioni_table.php` + +### Seeder: firstOrCreate per idempotenza + +- `DiocesiSeeder.php`: `Diocesi::create()` → `Diocesi::firstOrCreate(['nome' => $d['nome']], $d)` +- `ComuniSeeder.php`: `Comune::create()` → `Comune::firstOrCreate(['codice_istat' => $c['codice_istat']], $c)` +- `DatabaseSeeder.php`: `User::create()` → `User::firstOrCreate(['email' => 'admin@glastree.local'], [...])`, con guardia su `role_preset_id` + +**Risultato**: `php artisan migrate --seed` è ora completamente idempotente. Zero errori su 62 migration + 6 seeder. diff --git a/database/migrations/2024_01_01_000001_create_tenants_table.php b/database/migrations/2024_01_01_000001_create_tenants_table.php index cdd36110..bcc45627 100644 --- a/database/migrations/2024_01_01_000001_create_tenants_table.php +++ b/database/migrations/2024_01_01_000001_create_tenants_table.php @@ -8,6 +8,10 @@ return new class extends Migration { public function up(): void { + if (Schema::hasTable('tenants')) { + return; + } + Schema::create('tenants', function (Blueprint $table) { $table->id(); $table->string('nome'); diff --git a/database/migrations/2024_01_01_000002_create_comuni_diocesi_tables.php b/database/migrations/2024_01_01_000002_create_comuni_diocesi_tables.php index 76a3b559..f4bcafc1 100644 --- a/database/migrations/2024_01_01_000002_create_comuni_diocesi_tables.php +++ b/database/migrations/2024_01_01_000002_create_comuni_diocesi_tables.php @@ -8,26 +8,30 @@ return new class extends Migration { public function up(): void { - Schema::create('diocesi', function (Blueprint $table) { - $table->id(); - $table->string('nome'); - $table->string('regione')->nullable(); - $table->timestamps(); - }); + if (!Schema::hasTable('diocesi')) { + Schema::create('diocesi', function (Blueprint $table) { + $table->id(); + $table->string('nome'); + $table->string('regione')->nullable(); + $table->timestamps(); + }); + } - Schema::create('comuni', function (Blueprint $table) { - $table->id(); - $table->string('nome'); - $table->string('codice_istat', 10)->nullable(); - $table->string('cap')->nullable(); - $table->string('sigla_provincia', 2)->nullable(); - $table->string('regione')->nullable(); - $table->float('latitudine')->nullable(); - $table->float('longitudine')->nullable(); - $table->timestamps(); - $table->index('nome'); - $table->index('sigla_provincia'); - }); + if (!Schema::hasTable('comuni')) { + Schema::create('comuni', function (Blueprint $table) { + $table->id(); + $table->string('nome'); + $table->string('codice_istat', 10)->nullable(); + $table->string('cap')->nullable(); + $table->string('sigla_provincia', 2)->nullable(); + $table->string('regione')->nullable(); + $table->float('latitudine')->nullable(); + $table->float('longitudine')->nullable(); + $table->timestamps(); + $table->index('nome'); + $table->index('sigla_provincia'); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000003_create_individui_table.php b/database/migrations/2024_01_01_000003_create_individui_table.php index a738d437..d7d631c3 100644 --- a/database/migrations/2024_01_01_000003_create_individui_table.php +++ b/database/migrations/2024_01_01_000003_create_individui_table.php @@ -8,27 +8,29 @@ return new class extends Migration { public function up(): void { - Schema::create('individui', function (Blueprint $table) { - $table->id(); - $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); - $table->string('codice_id', 5)->unique(); - $table->string('cognome'); - $table->string('nome'); - $table->date('data_nascita')->nullable(); - $table->string('indirizzo')->nullable(); - $table->string('cap', 10)->nullable(); - $table->string('città')->nullable(); - $table->string('sigla_provincia', 2)->nullable(); - $table->enum('genere', ['M', 'F'])->nullable(); - $table->enum('tipo_documento', ['carta_identita', 'patente'])->nullable(); - $table->date('scadenza_documento')->nullable(); - $table->text('note')->nullable(); - $table->string('avatar_path')->nullable(); - $table->timestamps(); - $table->index('tenant_id'); - $table->index('codice_id'); - $table->index('cognome'); - }); + if (!Schema::hasTable('individui')) { + Schema::create('individui', function (Blueprint $table) { + $table->id(); + $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); + $table->string('codice_id', 5)->unique(); + $table->string('cognome'); + $table->string('nome'); + $table->date('data_nascita')->nullable(); + $table->string('indirizzo')->nullable(); + $table->string('cap', 10)->nullable(); + $table->string('città')->nullable(); + $table->string('sigla_provincia', 2)->nullable(); + $table->enum('genere', ['M', 'F'])->nullable(); + $table->enum('tipo_documento', ['carta_identita', 'patente'])->nullable(); + $table->date('scadenza_documento')->nullable(); + $table->text('note')->nullable(); + $table->string('avatar_path')->nullable(); + $table->timestamps(); + $table->index('tenant_id'); + $table->index('codice_id'); + $table->index('cognome'); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000004_create_contatti_table.php b/database/migrations/2024_01_01_000004_create_contatti_table.php index 675fed17..63fe27dc 100644 --- a/database/migrations/2024_01_01_000004_create_contatti_table.php +++ b/database/migrations/2024_01_01_000004_create_contatti_table.php @@ -8,16 +8,18 @@ return new class extends Migration { public function up(): void { - Schema::create('contatti', function (Blueprint $table) { - $table->id(); - $table->foreignId('individuo_id')->constrained('individui')->onDelete('cascade'); - $table->enum('tipo', ['telefono', 'cellulare', 'email', 'fax', 'web', 'telegram', 'whatsapp', 'altro']); - $table->string('valore'); - $table->string('etichetta')->nullable(); - $table->boolean('is_primary')->default(false); - $table->timestamps(); - $table->index('individuo_id'); - }); + if (!Schema::hasTable('contatti')) { + Schema::create('contatti', function (Blueprint $table) { + $table->id(); + $table->foreignId('individuo_id')->constrained('individui')->onDelete('cascade'); + $table->enum('tipo', ['telefono', 'cellulare', 'email', 'fax', 'web', 'telegram', 'whatsapp', 'altro']); + $table->string('valore'); + $table->string('etichetta')->nullable(); + $table->boolean('is_primary')->default(false); + $table->timestamps(); + $table->index('individuo_id'); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000005_create_gruppi_table.php b/database/migrations/2024_01_01_000005_create_gruppi_table.php index d62f6fa3..02758d71 100644 --- a/database/migrations/2024_01_01_000005_create_gruppi_table.php +++ b/database/migrations/2024_01_01_000005_create_gruppi_table.php @@ -8,24 +8,26 @@ return new class extends Migration { public function up(): void { - Schema::create('gruppi', function (Blueprint $table) { - $table->id(); - $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); - $table->foreignId('parent_id')->nullable()->constrained('gruppi')->onDelete('set null'); - $table->foreignId('diocesi_id')->nullable()->constrained('diocesi')->onDelete('set null'); - $table->foreignId('responsabile_id')->nullable()->constrained('individui')->onDelete('set null'); - $table->string('nome'); - $table->text('descrizione')->nullable(); - $table->string('indirizzo_incontro')->nullable(); - $table->string('cap_incontro', 10)->nullable(); - $table->string('città_incontro')->nullable(); - $table->string('sigla_provincia_incontro', 2)->nullable(); - $table->string('mappa_posizione')->nullable(); - $table->json('metadata')->nullable(); - $table->timestamps(); - $table->index('tenant_id'); - $table->index('parent_id'); - }); + if (!Schema::hasTable('gruppi')) { + Schema::create('gruppi', function (Blueprint $table) { + $table->id(); + $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); + $table->foreignId('parent_id')->nullable()->constrained('gruppi')->onDelete('set null'); + $table->foreignId('diocesi_id')->nullable()->constrained('diocesi')->onDelete('set null'); + $table->foreignId('responsabile_id')->nullable()->constrained('individui')->onDelete('set null'); + $table->string('nome'); + $table->text('descrizione')->nullable(); + $table->string('indirizzo_incontro')->nullable(); + $table->string('cap_incontro', 10)->nullable(); + $table->string('città_incontro')->nullable(); + $table->string('sigla_provincia_incontro', 2)->nullable(); + $table->string('mappa_posizione')->nullable(); + $table->json('metadata')->nullable(); + $table->timestamps(); + $table->index('tenant_id'); + $table->index('parent_id'); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000006_create_gruppo_individuo_table.php b/database/migrations/2024_01_01_000006_create_gruppo_individuo_table.php index 9835604d..7fb7275e 100644 --- a/database/migrations/2024_01_01_000006_create_gruppo_individuo_table.php +++ b/database/migrations/2024_01_01_000006_create_gruppo_individuo_table.php @@ -8,15 +8,17 @@ return new class extends Migration { public function up(): void { - Schema::create('gruppo_individuo', function (Blueprint $table) { - $table->id(); - $table->foreignId('gruppo_id')->constrained('gruppi')->onDelete('cascade'); - $table->foreignId('individuo_id')->constrained('individui')->onDelete('cascade'); - $table->string('ruolo_nel_gruppo')->nullable(); - $table->date('data_adesione')->nullable(); - $table->timestamps(); - $table->unique(['gruppo_id', 'individuo_id']); - }); + if (!Schema::hasTable('gruppo_individuo')) { + Schema::create('gruppo_individuo', function (Blueprint $table) { + $table->id(); + $table->foreignId('gruppo_id')->constrained('gruppi')->onDelete('cascade'); + $table->foreignId('individuo_id')->constrained('individui')->onDelete('cascade'); + $table->string('ruolo_nel_gruppo')->nullable(); + $table->date('data_adesione')->nullable(); + $table->timestamps(); + $table->unique(['gruppo_id', 'individuo_id']); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000007_create_eventi_table.php b/database/migrations/2024_01_01_000007_create_eventi_table.php index f92794c6..d600488b 100644 --- a/database/migrations/2024_01_01_000007_create_eventi_table.php +++ b/database/migrations/2024_01_01_000007_create_eventi_table.php @@ -8,35 +8,41 @@ return new class extends Migration { public function up(): void { - Schema::create('eventi', function (Blueprint $table) { - $table->id(); - $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); - $table->string('nome_evento'); - $table->string('tipo_evento')->nullable(); - $table->enum('tipo_recorrenza', ['singolo', 'ricorrente'])->default('singolo'); - $table->unsignedTinyInteger('giorno_settimana')->nullable(); - $table->time('ora_inizio')->nullable(); - $table->date('data_specifica')->nullable(); - $table->unsignedInteger('durata_minuti')->nullable(); - $table->text('descrizione')->nullable(); - $table->text('note')->nullable(); - $table->timestamps(); - $table->index('tenant_id'); - }); + if (!Schema::hasTable('eventi')) { + Schema::create('eventi', function (Blueprint $table) { + $table->id(); + $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); + $table->string('nome_evento'); + $table->string('tipo_evento')->nullable(); + $table->enum('tipo_recorrenza', ['singolo', 'ricorrente'])->default('singolo'); + $table->unsignedTinyInteger('giorno_settimana')->nullable(); + $table->time('ora_inizio')->nullable(); + $table->date('data_specifica')->nullable(); + $table->unsignedInteger('durata_minuti')->nullable(); + $table->text('descrizione')->nullable(); + $table->text('note')->nullable(); + $table->timestamps(); + $table->index('tenant_id'); + }); + } - Schema::create('eventi_gruppi', function (Blueprint $table) { - $table->id(); - $table->foreignId('evento_id')->constrained('eventi')->onDelete('cascade'); - $table->foreignId('gruppo_id')->constrained('gruppi')->onDelete('cascade'); - $table->timestamps(); - }); + if (!Schema::hasTable('eventi_gruppi')) { + Schema::create('eventi_gruppi', function (Blueprint $table) { + $table->id(); + $table->foreignId('evento_id')->constrained('eventi')->onDelete('cascade'); + $table->foreignId('gruppo_id')->constrained('gruppi')->onDelete('cascade'); + $table->timestamps(); + }); + } - Schema::create('eventi_responsabili', function (Blueprint $table) { - $table->id(); - $table->foreignId('evento_id')->constrained('eventi')->onDelete('cascade'); - $table->foreignId('individuo_id')->constrained('individui')->onDelete('cascade'); - $table->timestamps(); - }); + if (!Schema::hasTable('eventi_responsabili')) { + Schema::create('eventi_responsabili', function (Blueprint $table) { + $table->id(); + $table->foreignId('evento_id')->constrained('eventi')->onDelete('cascade'); + $table->foreignId('individuo_id')->constrained('individui')->onDelete('cascade'); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000008_create_documenti_table.php b/database/migrations/2024_01_01_000008_create_documenti_table.php index a32cb5a8..247ca532 100644 --- a/database/migrations/2024_01_01_000008_create_documenti_table.php +++ b/database/migrations/2024_01_01_000008_create_documenti_table.php @@ -8,22 +8,24 @@ return new class extends Migration { public function up(): void { - Schema::create('documenti', function (Blueprint $table) { - $table->id(); - $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); - $table->string('nome_file'); - $table->string('file_path'); - $table->string('tipo')->nullable(); - $table->enum('tipologia', ['avatar', 'galleria', 'documento', 'statuto', 'altro'])->default('documento'); - $table->enum('visibilita', ['pubblico', 'gruppo', 'individuo', 'associazione', 'federazione'])->default('gruppo'); - $table->unsignedBigInteger('visibilita_target_id')->nullable(); - $table->string('visibilita_target_type')->nullable(); - $table->string('mime_type')->nullable(); - $table->unsignedBigInteger('dimensione')->nullable(); - $table->text('note')->nullable(); - $table->timestamps(); - $table->index('tenant_id'); - }); + if (!Schema::hasTable('documenti')) { + Schema::create('documenti', function (Blueprint $table) { + $table->id(); + $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); + $table->string('nome_file'); + $table->string('file_path'); + $table->string('tipo')->nullable(); + $table->enum('tipologia', ['avatar', 'galleria', 'documento', 'statuto', 'altro'])->default('documento'); + $table->enum('visibilita', ['pubblico', 'gruppo', 'individuo', 'associazione', 'federazione'])->default('gruppo'); + $table->unsignedBigInteger('visibilita_target_id')->nullable(); + $table->string('visibilita_target_type')->nullable(); + $table->string('mime_type')->nullable(); + $table->unsignedBigInteger('dimensione')->nullable(); + $table->text('note')->nullable(); + $table->timestamps(); + $table->index('tenant_id'); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000009_create_mailing_tables.php b/database/migrations/2024_01_01_000009_create_mailing_tables.php index b429489e..1f26bbcc 100644 --- a/database/migrations/2024_01_01_000009_create_mailing_tables.php +++ b/database/migrations/2024_01_01_000009_create_mailing_tables.php @@ -8,43 +8,49 @@ return new class extends Migration { public function up(): void { - Schema::create('mailing_lists', function (Blueprint $table) { - $table->id(); - $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); - $table->string('nome'); - $table->text('descrizione')->nullable(); - $table->boolean('attiva')->default(true); - $table->timestamps(); - $table->index('tenant_id'); - }); + if (!Schema::hasTable('mailing_lists')) { + Schema::create('mailing_lists', function (Blueprint $table) { + $table->id(); + $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); + $table->string('nome'); + $table->text('descrizione')->nullable(); + $table->boolean('attiva')->default(true); + $table->timestamps(); + $table->index('tenant_id'); + }); + } - Schema::create('mailing_contacts', function (Blueprint $table) { - $table->id(); - $table->foreignId('mailing_list_id')->constrained('mailing_lists')->onDelete('cascade'); - $table->foreignId('individuo_id')->constrained('individui')->onDelete('cascade'); - $table->boolean('opt_in')->default(true); - $table->dateTime('opt_in_data')->nullable(); - $table->dateTime('opt_out_data')->nullable(); - $table->timestamps(); - $table->unique(['mailing_list_id', 'individuo_id']); - }); + if (!Schema::hasTable('mailing_contacts')) { + Schema::create('mailing_contacts', function (Blueprint $table) { + $table->id(); + $table->foreignId('mailing_list_id')->constrained('mailing_lists')->onDelete('cascade'); + $table->foreignId('individuo_id')->constrained('individui')->onDelete('cascade'); + $table->boolean('opt_in')->default(true); + $table->dateTime('opt_in_data')->nullable(); + $table->dateTime('opt_out_data')->nullable(); + $table->timestamps(); + $table->unique(['mailing_list_id', 'individuo_id']); + }); + } - Schema::create('mailing_messaggi', function (Blueprint $table) { - $table->id(); - $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); - $table->foreignId('mailing_list_id')->nullable()->constrained('mailing_lists')->onDelete('set null'); - $table->unsignedBigInteger('user_id')->nullable(); - $table->string('oggetto'); - $table->text('corpo')->nullable(); - $table->enum('canale', ['email', 'telegram'])->default('email'); - $table->enum('stato', ['bozza', 'in_coda', 'inviato', 'fallito'])->default('bozza'); - $table->timestamp('inviato_al')->nullable(); - $table->integer('totale_destinatari')->default(0); - $table->integer('invii_ok')->default(0); - $table->integer('invii_falliti')->default(0); - $table->timestamps(); - $table->index('tenant_id'); - }); + if (!Schema::hasTable('mailing_messaggi')) { + Schema::create('mailing_messaggi', function (Blueprint $table) { + $table->id(); + $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); + $table->foreignId('mailing_list_id')->nullable()->constrained('mailing_lists')->onDelete('set null'); + $table->unsignedBigInteger('user_id')->nullable(); + $table->string('oggetto'); + $table->text('corpo')->nullable(); + $table->enum('canale', ['email', 'telegram'])->default('email'); + $table->enum('stato', ['bozza', 'in_coda', 'inviato', 'fallito'])->default('bozza'); + $table->timestamp('inviato_al')->nullable(); + $table->integer('totale_destinatari')->default(0); + $table->integer('invii_ok')->default(0); + $table->integer('invii_falliti')->default(0); + $table->timestamps(); + $table->index('tenant_id'); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000010_create_notifiche_table.php b/database/migrations/2024_01_01_000010_create_notifiche_table.php index c8ce4d9b..6cb45633 100644 --- a/database/migrations/2024_01_01_000010_create_notifiche_table.php +++ b/database/migrations/2024_01_01_000010_create_notifiche_table.php @@ -8,18 +8,20 @@ return new class extends Migration { public function up(): void { - Schema::create('notifiche', function (Blueprint $table) { - $table->id(); - $table->unsignedBigInteger('user_id')->nullable(); - $table->string('tipo'); - $table->string('titolo'); - $table->text('messaggio'); - $table->string('link')->nullable(); - $table->boolean('is_read')->default(false); - $table->timestamp('read_at')->nullable(); - $table->timestamps(); - $table->index('user_id'); - }); + if (!Schema::hasTable('notifiche')) { + Schema::create('notifiche', function (Blueprint $table) { + $table->id(); + $table->unsignedBigInteger('user_id')->nullable(); + $table->string('tipo'); + $table->string('titolo'); + $table->text('messaggio'); + $table->string('link')->nullable(); + $table->boolean('is_read')->default(false); + $table->timestamp('read_at')->nullable(); + $table->timestamps(); + $table->index('user_id'); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000011_create_users_table.php b/database/migrations/2024_01_01_000011_create_users_table.php index 282fa853..3a5580bb 100644 --- a/database/migrations/2024_01_01_000011_create_users_table.php +++ b/database/migrations/2024_01_01_000011_create_users_table.php @@ -8,34 +8,40 @@ return new class extends Migration { public function up(): void { - Schema::create('users', function (Blueprint $table) { - $table->id(); - $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); - $table->string('name'); - $table->string('email')->unique(); - $table->timestamp('email_verified_at')->nullable(); - $table->string('password'); - $table->boolean('is_admin')->default(false); - $table->rememberToken(); - $table->timestamps(); - $table->index('tenant_id'); - $table->index('email'); - }); + if (!Schema::hasTable('users')) { + Schema::create('users', function (Blueprint $table) { + $table->id(); + $table->foreignId('tenant_id')->nullable()->constrained('tenants')->onDelete('set null'); + $table->string('name'); + $table->string('email')->unique(); + $table->timestamp('email_verified_at')->nullable(); + $table->string('password'); + $table->boolean('is_admin')->default(false); + $table->rememberToken(); + $table->timestamps(); + $table->index('tenant_id'); + $table->index('email'); + }); + } - Schema::create('password_reset_tokens', function (Blueprint $table) { - $table->string('email')->primary(); - $table->string('token'); - $table->timestamp('created_at')->nullable(); - }); + if (!Schema::hasTable('password_reset_tokens')) { + Schema::create('password_reset_tokens', function (Blueprint $table) { + $table->string('email')->primary(); + $table->string('token'); + $table->timestamp('created_at')->nullable(); + }); + } - Schema::create('sessions', function (Blueprint $table) { - $table->string('id')->primary(); - $table->foreignId('user_id')->nullable()->index(); - $table->string('ip_address', 45)->nullable(); - $table->text('user_agent')->nullable(); - $table->longText('payload'); - $table->integer('last_activity')->index(); - }); + if (!Schema::hasTable('sessions')) { + Schema::create('sessions', function (Blueprint $table) { + $table->string('id')->primary(); + $table->foreignId('user_id')->nullable()->index(); + $table->string('ip_address', 45)->nullable(); + $table->text('user_agent')->nullable(); + $table->longText('payload'); + $table->integer('last_activity')->index(); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000012_create_cache_and_jobs_tables.php b/database/migrations/2024_01_01_000012_create_cache_and_jobs_tables.php index 1469c03c..4c51abd0 100644 --- a/database/migrations/2024_01_01_000012_create_cache_and_jobs_tables.php +++ b/database/migrations/2024_01_01_000012_create_cache_and_jobs_tables.php @@ -8,50 +8,60 @@ return new class extends Migration { public function up(): void { - Schema::create('cache', function (Blueprint $table) { - $table->string('key')->primary(); - $table->mediumText('value'); - $table->integer('expiration'); - }); + if (!Schema::hasTable('cache')) { + Schema::create('cache', function (Blueprint $table) { + $table->string('key')->primary(); + $table->mediumText('value'); + $table->integer('expiration'); + }); + } - Schema::create('cache_locks', function (Blueprint $table) { - $table->string('key')->primary(); - $table->string('owner'); - $table->integer('expiration'); - }); + if (!Schema::hasTable('cache_locks')) { + Schema::create('cache_locks', function (Blueprint $table) { + $table->string('key')->primary(); + $table->string('owner'); + $table->integer('expiration'); + }); + } - Schema::create('jobs', function (Blueprint $table) { - $table->id(); - $table->string('queue')->index(); - $table->longText('payload'); - $table->unsignedTinyInteger('attempts'); - $table->unsignedInteger('reserved_at')->nullable(); - $table->unsignedInteger('available_at'); - $table->unsignedInteger('created_at'); - }); + if (!Schema::hasTable('jobs')) { + Schema::create('jobs', function (Blueprint $table) { + $table->id(); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + } - Schema::create('job_batches', function (Blueprint $table) { - $table->string('id')->primary(); - $table->string('name'); - $table->integer('total_jobs'); - $table->integer('pending_jobs'); - $table->integer('failed_jobs'); - $table->longText('failed_job_ids'); - $table->mediumText('options')->nullable(); - $table->integer('cancelled_at')->nullable(); - $table->integer('created_at'); - $table->integer('finished_at')->nullable(); - }); + if (!Schema::hasTable('job_batches')) { + Schema::create('job_batches', function (Blueprint $table) { + $table->string('id')->primary(); + $table->string('name'); + $table->integer('total_jobs'); + $table->integer('pending_jobs'); + $table->integer('failed_jobs'); + $table->longText('failed_job_ids'); + $table->mediumText('options')->nullable(); + $table->integer('cancelled_at')->nullable(); + $table->integer('created_at'); + $table->integer('finished_at')->nullable(); + }); + } - Schema::create('failed_jobs', function (Blueprint $table) { - $table->id(); - $table->string('uuid')->unique(); - $table->text('connection'); - $table->text('queue'); - $table->longText('payload'); - $table->longText('exception'); - $table->timestamp('failed_at'); - }); + if (!Schema::hasTable('failed_jobs')) { + Schema::create('failed_jobs', function (Blueprint $table) { + $table->id(); + $table->string('uuid')->unique(); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at'); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000019_create_eventi_documenti_table.php b/database/migrations/2024_01_01_000019_create_eventi_documenti_table.php index 96c5d76e..ceaf6f73 100644 --- a/database/migrations/2024_01_01_000019_create_eventi_documenti_table.php +++ b/database/migrations/2024_01_01_000019_create_eventi_documenti_table.php @@ -8,12 +8,14 @@ return new class extends Migration { public function up(): void { - Schema::create('eventi_documenti', function (Blueprint $table) { - $table->id(); - $table->foreignId('evento_id')->constrained('eventi')->onDelete('cascade'); - $table->foreignId('documento_id')->constrained('documenti')->onDelete('cascade'); - $table->timestamps(); - }); + if (!Schema::hasTable('eventi_documenti')) { + Schema::create('eventi_documenti', function (Blueprint $table) { + $table->id(); + $table->foreignId('evento_id')->constrained('eventi')->onDelete('cascade'); + $table->foreignId('documento_id')->constrained('documenti')->onDelete('cascade'); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2024_01_01_000022_create_table_viste_report.php b/database/migrations/2024_01_01_000022_create_table_viste_report.php index b592e97b..0dc8aaf8 100644 --- a/database/migrations/2024_01_01_000022_create_table_viste_report.php +++ b/database/migrations/2024_01_01_000022_create_table_viste_report.php @@ -8,19 +8,21 @@ return new class extends Migration { public function up(): void { - Schema::create('viste_report', function (Blueprint $table) { - $table->id(); - $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); - $table->string('nome'); - $table->string('tipo'); // individui, gruppi, documenti, eventi - $table->json('colonne_visibili')->nullable(); - $table->json('colonne_ordinamento')->nullable(); // [['colonna', 'direzione']] - $table->json('filtri')->nullable(); // [['colonna', 'operatore', 'valore']] - $table->string('ricerca')->nullable(); - $table->timestamps(); - $table->index('tipo'); - $table->index('user_id'); - }); + if (!Schema::hasTable('viste_report')) { + Schema::create('viste_report', function (Blueprint $table) { + $table->id(); + $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); + $table->string('nome'); + $table->string('tipo'); // individui, gruppi, documenti, eventi + $table->json('colonne_visibili')->nullable(); + $table->json('colonne_ordinamento')->nullable(); // [['colonna', 'direzione']] + $table->json('filtri')->nullable(); // [['colonna', 'operatore', 'valore']] + $table->string('ricerca')->nullable(); + $table->timestamps(); + $table->index('tipo'); + $table->index('user_id'); + }); + } } public function down(): void diff --git a/database/migrations/2026_05_10_000001_create_tipologie_documenti_table.php b/database/migrations/2026_05_10_000001_create_tipologie_documenti_table.php index 9b000666..9f0ae060 100644 --- a/database/migrations/2026_05_10_000001_create_tipologie_documenti_table.php +++ b/database/migrations/2026_05_10_000001_create_tipologie_documenti_table.php @@ -8,14 +8,16 @@ return new class extends Migration { public function up(): void { - Schema::create('tipologie_documenti', function (Blueprint $table) { - $table->id(); - $table->string('nome', 50)->unique(); - $table->string('descrizione', 255)->nullable(); - $table->integer('ordine')->default(0); - $table->boolean('attiva')->default(true); - $table->timestamps(); - }); + if (!Schema::hasTable('tipologie_documenti')) { + Schema::create('tipologie_documenti', function (Blueprint $table) { + $table->id(); + $table->string('nome', 50)->unique(); + $table->string('descrizione', 255)->nullable(); + $table->integer('ordine')->default(0); + $table->boolean('attiva')->default(true); + $table->timestamps(); + }); + } $defaultTipologie = ['avatar', 'galleria', 'documento', 'statuto', 'altro']; foreach ($defaultTipologie as $i => $nome) { diff --git a/database/migrations/2026_05_10_000002_add_acl_tables.php b/database/migrations/2026_05_10_000002_add_acl_tables.php index b784902d..08b91848 100644 --- a/database/migrations/2026_05_10_000002_add_acl_tables.php +++ b/database/migrations/2026_05_10_000002_add_acl_tables.php @@ -14,28 +14,32 @@ return new class extends Migration }); } - Schema::create('activity_logs', function (Blueprint $table) { - $table->id(); - $table->foreignId('user_id')->constrained()->onDelete('cascade'); - $table->string('action'); - $table->string('module'); - $table->string('description')->nullable(); - $table->json('details')->nullable(); - $table->string('ip_address', 45)->nullable(); - $table->timestamp('created_at')->useCurrent(); + if (!Schema::hasTable('activity_logs')) { + Schema::create('activity_logs', function (Blueprint $table) { + $table->id(); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->string('action'); + $table->string('module'); + $table->string('description')->nullable(); + $table->json('details')->nullable(); + $table->string('ip_address', 45)->nullable(); + $table->timestamp('created_at')->useCurrent(); + + $table->index(['user_id', 'module']); + $table->index(['created_at']); + $table->index(['action']); + }); + } - $table->index(['user_id', 'module']); - $table->index(['created_at']); - $table->index(['action']); - }); - - Schema::create('role_presets', function (Blueprint $table) { - $table->id(); - $table->string('name', 50)->unique(); - $table->string('description')->nullable(); - $table->json('permissions'); - $table->timestamps(); - }); + if (!Schema::hasTable('role_presets')) { + Schema::create('role_presets', function (Blueprint $table) { + $table->id(); + $table->string('name', 50)->unique(); + $table->string('description')->nullable(); + $table->json('permissions'); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2026_05_10_125210_create_permission_tables.php b/database/migrations/2026_05_10_125210_create_permission_tables.php index 89862751..b1dfde95 100644 --- a/database/migrations/2026_05_10_125210_create_permission_tables.php +++ b/database/migrations/2026_05_10_125210_create_permission_tables.php @@ -23,96 +23,106 @@ return new class extends Migration /** * See `docs/prerequisites.md` for suggested lengths on 'name' and 'guard_name' if "1071 Specified key was too long" errors are encountered. */ - Schema::create($tableNames['permissions'], static function (Blueprint $table) { - $table->id(); // permission id - $table->string('name'); - $table->string('guard_name'); - $table->timestamps(); - - $table->unique(['name', 'guard_name']); - }); + if (!Schema::hasTable($tableNames['permissions'])) { + Schema::create($tableNames['permissions'], static function (Blueprint $table) { + $table->id(); // permission id + $table->string('name'); + $table->string('guard_name'); + $table->timestamps(); + + $table->unique(['name', 'guard_name']); + }); + } /** * See `docs/prerequisites.md` for suggested lengths on 'name' and 'guard_name' if "1071 Specified key was too long" errors are encountered. */ - Schema::create($tableNames['roles'], static function (Blueprint $table) use ($teams, $columnNames) { - $table->id(); // role id - if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing + if (!Schema::hasTable($tableNames['roles'])) { + Schema::create($tableNames['roles'], static function (Blueprint $table) use ($teams, $columnNames) { + $table->id(); // role id + if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing $table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable(); $table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index'); - } - $table->string('name'); - $table->string('guard_name'); - $table->timestamps(); - if ($teams || config('permission.testing')) { + } + $table->string('name'); + $table->string('guard_name'); + $table->timestamps(); + if ($teams || config('permission.testing')) { $table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']); - } else { + } else { $table->unique(['name', 'guard_name']); - } - }); + } + }); + } - Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) { - $table->unsignedBigInteger($pivotPermission); - - $table->string('model_type'); - $table->unsignedBigInteger($columnNames['model_morph_key']); - $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index'); - - $table->foreign($pivotPermission) + if (!Schema::hasTable($tableNames['model_has_permissions'])) { + Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) { + $table->unsignedBigInteger($pivotPermission); + + $table->string('model_type'); + $table->unsignedBigInteger($columnNames['model_morph_key']); + $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index'); + + $table->foreign($pivotPermission) ->references('id') // permission id ->on($tableNames['permissions']) ->cascadeOnDelete(); - if ($teams) { + if ($teams) { $table->unsignedBigInteger($columnNames['team_foreign_key']); $table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index'); - + $table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_permission_model_type_primary'); - } else { + } else { $table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_permission_model_type_primary'); - } - }); + } + }); + } - Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) { - $table->unsignedBigInteger($pivotRole); - - $table->string('model_type'); - $table->unsignedBigInteger($columnNames['model_morph_key']); - $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index'); - - $table->foreign($pivotRole) + if (!Schema::hasTable($tableNames['model_has_roles'])) { + Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) { + $table->unsignedBigInteger($pivotRole); + + $table->string('model_type'); + $table->unsignedBigInteger($columnNames['model_morph_key']); + $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index'); + + $table->foreign($pivotRole) ->references('id') // role id ->on($tableNames['roles']) ->cascadeOnDelete(); - if ($teams) { + if ($teams) { $table->unsignedBigInteger($columnNames['team_foreign_key']); $table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index'); - + $table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'], 'model_has_roles_role_model_type_primary'); - } else { + } else { $table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'], 'model_has_roles_role_model_type_primary'); - } - }); + } + }); + } - Schema::create($tableNames['role_has_permissions'], static function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) { - $table->unsignedBigInteger($pivotPermission); - $table->unsignedBigInteger($pivotRole); - - $table->foreign($pivotPermission) + if (!Schema::hasTable($tableNames['role_has_permissions'])) { + Schema::create($tableNames['role_has_permissions'], static function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) { + $table->unsignedBigInteger($pivotPermission); + $table->unsignedBigInteger($pivotRole); + + $table->foreign($pivotPermission) ->references('id') // permission id ->on($tableNames['permissions']) ->cascadeOnDelete(); - - $table->foreign($pivotRole) + + $table->foreign($pivotRole) ->references('id') // role id ->on($tableNames['roles']) ->cascadeOnDelete(); - - $table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary'); - }); + + $table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary'); + }); + } app('cache') ->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null) diff --git a/database/migrations/2026_05_11_000001_create_email_settings_table.php b/database/migrations/2026_05_11_000001_create_email_settings_table.php index 49cc429a..bc49705f 100644 --- a/database/migrations/2026_05_11_000001_create_email_settings_table.php +++ b/database/migrations/2026_05_11_000001_create_email_settings_table.php @@ -8,26 +8,28 @@ return new class extends Migration { public function up(): void { - Schema::create('email_settings', function (Blueprint $table) { - $table->id(); - $table->string('imap_host')->nullable(); - $table->integer('imap_port')->nullable()->default(993); - $table->string('imap_encryption')->nullable()->default('ssl'); - $table->string('imap_username')->nullable(); - $table->string('imap_password')->nullable(); - $table->string('smtp_host')->nullable(); - $table->integer('smtp_port')->nullable()->default(587); - $table->string('smtp_encryption')->nullable()->default('tls'); - $table->string('smtp_username')->nullable(); - $table->string('smtp_password')->nullable(); - $table->string('email_address')->nullable(); - $table->string('email_name')->nullable(); - $table->string('reply_to')->nullable(); - $table->integer('sync_interval_minutes')->default(5); - $table->timestamp('last_sync_at')->nullable(); - $table->boolean('is_active')->default(false); - $table->timestamps(); - }); + if (!Schema::hasTable('email_settings')) { + Schema::create('email_settings', function (Blueprint $table) { + $table->id(); + $table->string('imap_host')->nullable(); + $table->integer('imap_port')->nullable()->default(993); + $table->string('imap_encryption')->nullable()->default('ssl'); + $table->string('imap_username')->nullable(); + $table->string('imap_password')->nullable(); + $table->string('smtp_host')->nullable(); + $table->integer('smtp_port')->nullable()->default(587); + $table->string('smtp_encryption')->nullable()->default('tls'); + $table->string('smtp_username')->nullable(); + $table->string('smtp_password')->nullable(); + $table->string('email_address')->nullable(); + $table->string('email_name')->nullable(); + $table->string('reply_to')->nullable(); + $table->integer('sync_interval_minutes')->default(5); + $table->timestamp('last_sync_at')->nullable(); + $table->boolean('is_active')->default(false); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2026_05_11_000002_create_email_folders_table.php b/database/migrations/2026_05_11_000002_create_email_folders_table.php index 49b06fc6..5745481a 100644 --- a/database/migrations/2026_05_11_000002_create_email_folders_table.php +++ b/database/migrations/2026_05_11_000002_create_email_folders_table.php @@ -8,17 +8,19 @@ return new class extends Migration { public function up(): void { - Schema::create('email_folders', function (Blueprint $table) { - $table->id(); - $table->string('name'); - $table->string('imap_folder_name')->nullable(); - $table->string('type')->default('custom'); - $table->string('icon')->default('fa-folder'); - $table->string('color')->nullable(); - $table->integer('sort_order')->default(0); - $table->boolean('is_system')->default(false); - $table->timestamps(); - }); + if (!Schema::hasTable('email_folders')) { + Schema::create('email_folders', function (Blueprint $table) { + $table->id(); + $table->string('name'); + $table->string('imap_folder_name')->nullable(); + $table->string('type')->default('custom'); + $table->string('icon')->default('fa-folder'); + $table->string('color')->nullable(); + $table->integer('sort_order')->default(0); + $table->boolean('is_system')->default(false); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2026_05_11_000003_create_email_messages_table.php b/database/migrations/2026_05_11_000003_create_email_messages_table.php index 429068e8..f70ceac0 100644 --- a/database/migrations/2026_05_11_000003_create_email_messages_table.php +++ b/database/migrations/2026_05_11_000003_create_email_messages_table.php @@ -8,35 +8,37 @@ return new class extends Migration { public function up(): void { - Schema::create('email_messages', function (Blueprint $table) { - $table->id(); - $table->foreignId('email_folder_id')->constrained('email_folders')->onDelete('cascade'); - $table->string('message_id')->nullable()->index(); - $table->string('subject')->nullable(); - $table->string('from_name')->nullable(); - $table->string('from_email')->nullable(); - $table->string('to_name')->nullable(); - $table->string('to_email')->nullable(); - $table->text('cc')->nullable(); - $table->text('bcc')->nullable(); - $table->longText('body_text')->nullable(); - $table->longText('body_html')->nullable(); - $table->boolean('is_read')->default(false); - $table->boolean('is_starred')->default(false); - $table->boolean('is_important')->default(false); - $table->boolean('is_sent')->default(false); - $table->boolean('is_draft')->default(false); - $table->boolean('is_trash')->default(false); - $table->timestamp('received_at')->nullable(); - $table->timestamp('sent_at')->nullable(); - $table->unsignedBigInteger('imap_uid')->nullable(); - $table->timestamps(); - - $table->index('is_read'); - $table->index('is_starred'); - $table->index('is_sent'); - $table->index('received_at'); - }); + if (!Schema::hasTable('email_messages')) { + Schema::create('email_messages', function (Blueprint $table) { + $table->id(); + $table->foreignId('email_folder_id')->constrained('email_folders')->onDelete('cascade'); + $table->string('message_id')->nullable()->index(); + $table->string('subject')->nullable(); + $table->string('from_name')->nullable(); + $table->string('from_email')->nullable(); + $table->string('to_name')->nullable(); + $table->string('to_email')->nullable(); + $table->text('cc')->nullable(); + $table->text('bcc')->nullable(); + $table->longText('body_text')->nullable(); + $table->longText('body_html')->nullable(); + $table->boolean('is_read')->default(false); + $table->boolean('is_starred')->default(false); + $table->boolean('is_important')->default(false); + $table->boolean('is_sent')->default(false); + $table->boolean('is_draft')->default(false); + $table->boolean('is_trash')->default(false); + $table->timestamp('received_at')->nullable(); + $table->timestamp('sent_at')->nullable(); + $table->unsignedBigInteger('imap_uid')->nullable(); + $table->timestamps(); + + $table->index('is_read'); + $table->index('is_starred'); + $table->index('is_sent'); + $table->index('received_at'); + }); + } } public function down(): void diff --git a/database/migrations/2026_05_11_000007_create_email_attachments_table.php b/database/migrations/2026_05_11_000007_create_email_attachments_table.php index 8dbfbd49..99de18df 100644 --- a/database/migrations/2026_05_11_000007_create_email_attachments_table.php +++ b/database/migrations/2026_05_11_000007_create_email_attachments_table.php @@ -8,17 +8,19 @@ return new class extends Migration { public function up(): void { - Schema::create('email_attachments', function (Blueprint $table) { - $table->id(); - $table->foreignId('email_message_id')->constrained('email_messages')->onDelete('cascade'); - $table->string('filename'); - $table->string('mime_type')->nullable(); - $table->bigInteger('size')->default(0); - $table->string('file_path'); - $table->boolean('is_saved_to_documenti')->default(false); - $table->foreignId('documenti_id')->nullable()->constrained('documenti')->onDelete('set null'); - $table->timestamps(); - }); + if (!Schema::hasTable('email_attachments')) { + Schema::create('email_attachments', function (Blueprint $table) { + $table->id(); + $table->foreignId('email_message_id')->constrained('email_messages')->onDelete('cascade'); + $table->string('filename'); + $table->string('mime_type')->nullable(); + $table->bigInteger('size')->default(0); + $table->string('file_path'); + $table->boolean('is_saved_to_documenti')->default(false); + $table->foreignId('documenti_id')->nullable()->constrained('documenti')->onDelete('set null'); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2026_05_12_000001_create_ruoli_table.php b/database/migrations/2026_05_12_000001_create_ruoli_table.php index 5cbbaa9b..04875a4a 100644 --- a/database/migrations/2026_05_12_000001_create_ruoli_table.php +++ b/database/migrations/2026_05_12_000001_create_ruoli_table.php @@ -8,14 +8,16 @@ return new class extends Migration { public function up(): void { - Schema::create('ruoli', function (Blueprint $table) { - $table->id(); - $table->string('nome', 50)->unique(); - $table->string('descrizione', 255)->nullable(); - $table->integer('ordine')->default(0); - $table->boolean('attiva')->default(true); - $table->timestamps(); - }); + if (!Schema::hasTable('ruoli')) { + Schema::create('ruoli', function (Blueprint $table) { + $table->id(); + $table->string('nome', 50)->unique(); + $table->string('descrizione', 255)->nullable(); + $table->integer('ordine')->default(0); + $table->boolean('attiva')->default(true); + $table->timestamps(); + }); + } $defaultRuoli = [ ['nome' => 'Membro', 'descrizione' => 'Membro del gruppo'], diff --git a/database/migrations/2026_05_25_000001_create_report_custom_table.php b/database/migrations/2026_05_25_000001_create_report_custom_table.php index 3ee72277..2b580d63 100644 --- a/database/migrations/2026_05_25_000001_create_report_custom_table.php +++ b/database/migrations/2026_05_25_000001_create_report_custom_table.php @@ -8,15 +8,17 @@ return new class extends Migration { public function up(): void { - Schema::create('report_custom', function (Blueprint $table) { - $table->id(); - $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); - $table->string('nome'); - $table->text('descrizione')->nullable(); - $table->string('tipo_report'); - $table->json('config')->nullable(); - $table->timestamps(); - }); + if (!Schema::hasTable('report_custom')) { + Schema::create('report_custom', function (Blueprint $table) { + $table->id(); + $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); + $table->string('nome'); + $table->text('descrizione')->nullable(); + $table->string('tipo_report'); + $table->json('config')->nullable(); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2026_05_26_000001_create_tipologie_eventi_table.php b/database/migrations/2026_05_26_000001_create_tipologie_eventi_table.php index 01fb6f02..ae791f23 100644 --- a/database/migrations/2026_05_26_000001_create_tipologie_eventi_table.php +++ b/database/migrations/2026_05_26_000001_create_tipologie_eventi_table.php @@ -10,14 +10,16 @@ return new class extends Migration { public function up(): void { - Schema::create('tipologie_eventi', function (Blueprint $table) { - $table->id(); - $table->string('nome', 50)->unique(); - $table->string('descrizione', 255)->nullable(); - $table->integer('ordine')->default(0); - $table->boolean('attiva')->default(true); - $table->timestamps(); - }); + if (!Schema::hasTable('tipologie_eventi')) { + Schema::create('tipologie_eventi', function (Blueprint $table) { + $table->id(); + $table->string('nome', 50)->unique(); + $table->string('descrizione', 255)->nullable(); + $table->integer('ordine')->default(0); + $table->boolean('attiva')->default(true); + $table->timestamps(); + }); + } DB::table('tipologie_eventi')->insert([ ['nome' => 'catechesi', 'descrizione' => 'Catechesi', 'ordine' => 0, 'attiva' => true], diff --git a/database/migrations/2026_05_26_000002_create_sender_accounts_table.php b/database/migrations/2026_05_26_000002_create_sender_accounts_table.php index 8480705c..1b909201 100644 --- a/database/migrations/2026_05_26_000002_create_sender_accounts_table.php +++ b/database/migrations/2026_05_26_000002_create_sender_accounts_table.php @@ -10,21 +10,23 @@ return new class extends Migration { public function up(): void { - Schema::create('sender_accounts', function (Blueprint $table) { - $table->id(); - $table->string('email_address')->unique(); - $table->string('email_name')->nullable(); - $table->string('smtp_host')->nullable(); - $table->integer('smtp_port')->default(587); - $table->string('smtp_encryption')->default('tls'); - $table->string('smtp_username')->nullable(); - $table->text('smtp_password')->nullable(); - $table->string('reply_to')->nullable(); - $table->string('verify_email')->nullable(); - $table->text('note')->nullable(); - $table->boolean('is_active')->default(true); - $table->timestamps(); - }); + if (!Schema::hasTable('sender_accounts')) { + Schema::create('sender_accounts', function (Blueprint $table) { + $table->id(); + $table->string('email_address')->unique(); + $table->string('email_name')->nullable(); + $table->string('smtp_host')->nullable(); + $table->integer('smtp_port')->default(587); + $table->string('smtp_encryption')->default('tls'); + $table->string('smtp_username')->nullable(); + $table->text('smtp_password')->nullable(); + $table->string('reply_to')->nullable(); + $table->string('verify_email')->nullable(); + $table->text('note')->nullable(); + $table->boolean('is_active')->default(true); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2026_05_27_000001_create_documenti_cartelle_table.php b/database/migrations/2026_05_27_000001_create_documenti_cartelle_table.php index 2a332fe7..f4473684 100644 --- a/database/migrations/2026_05_27_000001_create_documenti_cartelle_table.php +++ b/database/migrations/2026_05_27_000001_create_documenti_cartelle_table.php @@ -8,12 +8,14 @@ return new class extends Migration { public function up(): void { - Schema::create('documenti_cartelle', function (Blueprint $table) { - $table->id(); - $table->foreignId('parent_id')->nullable()->constrained('documenti_cartelle')->onDelete('cascade'); - $table->string('nome'); - $table->timestamps(); - }); + if (!Schema::hasTable('documenti_cartelle')) { + Schema::create('documenti_cartelle', function (Blueprint $table) { + $table->id(); + $table->foreignId('parent_id')->nullable()->constrained('documenti_cartelle')->onDelete('cascade'); + $table->string('nome'); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2026_05_27_113245_create_storage_repositories_table.php b/database/migrations/2026_05_27_113245_create_storage_repositories_table.php index af04d0b1..8f220573 100644 --- a/database/migrations/2026_05_27_113245_create_storage_repositories_table.php +++ b/database/migrations/2026_05_27_113245_create_storage_repositories_table.php @@ -8,15 +8,17 @@ return new class extends Migration { public function up(): void { - Schema::create('storage_repositories', function (Blueprint $table) { - $table->id(); - $table->string('nome'); - $table->string('tipo', 50); - $table->text('config'); - $table->boolean('is_active')->default(true); - $table->integer('ordine')->default(0); - $table->timestamps(); - }); + if (!Schema::hasTable('storage_repositories')) { + Schema::create('storage_repositories', function (Blueprint $table) { + $table->id(); + $table->string('nome'); + $table->string('tipo', 50); + $table->text('config'); + $table->boolean('is_active')->default(true); + $table->integer('ordine')->default(0); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2026_06_02_000001_create_calendario_connessioni_table.php b/database/migrations/2026_06_02_000001_create_calendario_connessioni_table.php index 92d51cbd..e0406350 100644 --- a/database/migrations/2026_06_02_000001_create_calendario_connessioni_table.php +++ b/database/migrations/2026_06_02_000001_create_calendario_connessioni_table.php @@ -10,21 +10,23 @@ return new class extends Migration { public function up(): void { - Schema::create('calendario_connessioni', function (Blueprint $table) { - $table->id(); - $table->string('nome'); - $table->string('tipo'); // google_calendar, caldav - $table->text('config'); // JSON - $table->string('stato')->default('disconnesso'); // connesso, disconnesso, errore - $table->string('sync_direction')->default('bidirectional'); // import, export, bidirectional - $table->integer('sync_interval_minutes')->default(60); - $table->timestamp('last_sync_at')->nullable(); - $table->timestamp('last_error_at')->nullable(); - $table->text('last_error_message')->nullable(); - $table->boolean('is_active')->default(true); - $table->integer('ordine')->default(0); - $table->timestamps(); - }); + if (!Schema::hasTable('calendario_connessioni')) { + Schema::create('calendario_connessioni', function (Blueprint $table) { + $table->id(); + $table->string('nome'); + $table->string('tipo'); // google_calendar, caldav + $table->text('config'); // JSON + $table->string('stato')->default('disconnesso'); // connesso, disconnesso, errore + $table->string('sync_direction')->default('bidirectional'); // import, export, bidirectional + $table->integer('sync_interval_minutes')->default(60); + $table->timestamp('last_sync_at')->nullable(); + $table->timestamp('last_error_at')->nullable(); + $table->text('last_error_message')->nullable(); + $table->boolean('is_active')->default(true); + $table->integer('ordine')->default(0); + $table->timestamps(); + }); + } } public function down(): void diff --git a/database/migrations/2026_06_08_194155_create_tags_tables.php b/database/migrations/2026_06_08_194155_create_tags_tables.php index 1a9313e9..7195c783 100644 --- a/database/migrations/2026_06_08_194155_create_tags_tables.php +++ b/database/migrations/2026_06_08_194155_create_tags_tables.php @@ -18,7 +18,7 @@ return new class extends Migration $table->string('color', 7)->nullable(); $table->integer('order_column')->default(0); $table->timestamps(); - }); + }); } if (!Schema::hasTable('taggables')) { @@ -26,7 +26,7 @@ return new class extends Migration $table->foreignId('tag_id')->constrained()->cascadeOnDelete(); $table->morphs('taggable'); $table->primary(['tag_id', 'taggable_id', 'taggable_type']); - }); + }); } } diff --git a/database/seeders/ComuniSeeder.php b/database/seeders/ComuniSeeder.php index a7b591e5..755fe8ae 100644 --- a/database/seeders/ComuniSeeder.php +++ b/database/seeders/ComuniSeeder.php @@ -68,7 +68,7 @@ class ComuniSeeder extends Seeder ]; foreach ($comuni as $c) { - Comune::create($c); + Comune::firstOrCreate(['codice_istat' => $c['codice_istat']], $c); } } } \ No newline at end of file diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 6e01fb57..0f6d83d9 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -20,23 +20,27 @@ class DatabaseSeeder extends Seeder DockerBaseDataSeeder::class, ]); - $admin = User::create([ - 'name' => 'Admin', - 'email' => 'admin@glastree.local', - 'password' => bcrypt('password'), - 'is_admin' => true, - 'status' => 'active', - 'permissions' => [ - 'individui' => 2, - 'gruppi' => 2, - 'eventi' => 2, - 'documenti' => 2, - 'mailing' => 2, - 'viste' => 2, - ], - ]); + $admin = User::firstOrCreate( + ['email' => 'admin@glastree.local'], + [ + 'name' => 'Admin', + 'password' => bcrypt('password'), + 'is_admin' => true, + 'status' => 'active', + 'permissions' => [ + 'individui' => 2, + 'gruppi' => 2, + 'eventi' => 2, + 'documenti' => 2, + 'mailing' => 2, + 'viste' => 2, + ], + ] + ); - $admin->role_preset_id = 1; - $admin->save(); + if (!$admin->role_preset_id) { + $admin->role_preset_id = 1; + $admin->save(); + } } } \ No newline at end of file diff --git a/database/seeders/DiocesiSeeder.php b/database/seeders/DiocesiSeeder.php index bad844ef..77dc842f 100644 --- a/database/seeders/DiocesiSeeder.php +++ b/database/seeders/DiocesiSeeder.php @@ -149,7 +149,7 @@ class DiocesiSeeder extends Seeder ]; foreach ($diocesi as $d) { - Diocesi::create($d); + Diocesi::firstOrCreate(['nome' => $d['nome']], $d); } } } \ No newline at end of file