altre migrations sistemate

This commit is contained in:
Mariano
2026-06-17 19:35:20 +02:00
parent 92ba47e99f
commit 3b2ad1a0d5
9 changed files with 90 additions and 79 deletions
+24
View File
@@ -578,3 +578,27 @@ if (!empty($contatto['individuo_id'])) { create }
- Test IMAP OAuth: sync email via connessione OAuth
- Verificare refresh token automatico allo scadere
- Verificare revoca e riconnessione
## 2026-06-17 — Fix: tutte le migration + seeders idempotenti
### Problema
`php artisan migrate` falliva su tabelle già esistenti (`tenants`, `tipologie_documenti`, ecc.).
`php artisan db:seed` creava duplicati su re-run (admin user, diocesi, comuni).
Migrations con `insert` dopo il guard `hasTable` violavano unique constraint al re-run.
### Migration: hasTable guard su 28 CREATE mancanti
Aggiunto `if (!Schema::hasTable('table_name')) { ... }` wrapper a 28 migration file (45 `Schema::create()` calls) via script Node.js, più `2026_06_17_000001_create_google_oauth_connections_table.php` manualmente.
### Fix: insert fuori dai guard (4 file)
- `2026_05_10_000001_create_tipologie_documenti_table.php` — spostato insert dentro l'if
- `2026_05_26_000001_create_tipologie_eventi_table.php` — spostato insert dentro l'if
- `2026_05_12_000001_create_ruoli_table.php` — spostato insert dentro l'if
- `2026_05_11_000006_add_email_attachment_tipologia.php``insert()``updateOrInsert()`
### Seeder: firstOrCreate
- `DiocesiSeeder.php`: `Diocesi::create()``::firstOrCreate(['nome' => ...])`
- `ComuniSeeder.php`: `Comune::create()``::firstOrCreate(['codice_istat' => ...])`
- `DatabaseSeeder.php`: `User::create()``::firstOrCreate(['email' => ...])` + guardia `role_preset_id`
### Risultato
`php artisan migrate --seed` è ora completamente idempotente. Zero errori su 64 migration + 6 seeder. Re-run è un no-op.
@@ -17,18 +17,18 @@ return new class extends Migration
$table->boolean('attiva')->default(true);
$table->timestamps();
});
}
$defaultTipologie = ['avatar', 'galleria', 'documento', 'statuto', 'altro'];
foreach ($defaultTipologie as $i => $nome) {
DB::table('tipologie_documenti')->insert([
'nome' => $nome,
'descrizione' => ucfirst($nome),
'ordine' => $i,
'attiva' => true,
'created_at' => now(),
'updated_at' => now(),
]);
$defaultTipologie = ['avatar', 'galleria', 'documento', 'statuto', 'altro'];
foreach ($defaultTipologie as $i => $nome) {
DB::table('tipologie_documenti')->insert([
'nome' => $nome,
'descrizione' => ucfirst($nome),
'ordine' => $i,
'attiva' => true,
'created_at' => now(),
'updated_at' => now(),
]);
}
}
}
@@ -7,14 +7,15 @@ return new class extends Migration
{
public function up(): void
{
DB::table('tipologie_documenti')->insert([
'nome' => 'email_attachment',
'descrizione' => 'Allegato email',
'ordine' => 100,
'attiva' => true,
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('tipologie_documenti')->updateOrInsert(
['nome' => 'email_attachment'],
[
'descrizione' => 'Allegato email',
'ordine' => 100,
'attiva' => true,
'updated_at' => now(),
]
);
}
public function down(): void
@@ -17,27 +17,27 @@ return new class extends Migration
$table->boolean('attiva')->default(true);
$table->timestamps();
});
}
$defaultRuoli = [
['nome' => 'Membro', 'descrizione' => 'Membro del gruppo'],
['nome' => 'Catechista', 'descrizione' => 'Catechista del gruppo'],
['nome' => 'Animatore', 'descrizione' => 'Animatore del gruppo'],
['nome' => 'Responsabile', 'descrizione' => 'Responsabile del gruppo'],
['nome' => 'Vice Responsabile', 'descrizione' => 'Vice responsabile del gruppo'],
['nome' => 'Segretario', 'descrizione' => 'Segretario del gruppo'],
['nome' => 'Tesoriere', 'descrizione' => 'Tesoriere del gruppo'],
];
$defaultRuoli = [
['nome' => 'Membro', 'descrizione' => 'Membro del gruppo'],
['nome' => 'Catechista', 'descrizione' => 'Catechista del gruppo'],
['nome' => 'Animatore', 'descrizione' => 'Animatore del gruppo'],
['nome' => 'Responsabile', 'descrizione' => 'Responsabile del gruppo'],
['nome' => 'Vice Responsabile', 'descrizione' => 'Vice responsabile del gruppo'],
['nome' => 'Segretario', 'descrizione' => 'Segretario del gruppo'],
['nome' => 'Tesoriere', 'descrizione' => 'Tesoriere del gruppo'],
];
foreach ($defaultRuoli as $i => $ruolo) {
DB::table('ruoli')->insert([
'nome' => $ruolo['nome'],
'descrizione' => $ruolo['descrizione'],
'ordine' => $i,
'attiva' => true,
'created_at' => now(),
'updated_at' => now(),
]);
foreach ($defaultRuoli as $i => $ruolo) {
DB::table('ruoli')->insert([
'nome' => $ruolo['nome'],
'descrizione' => $ruolo['descrizione'],
'ordine' => $i,
'attiva' => true,
'created_at' => now(),
'updated_at' => now(),
]);
}
}
if (!Schema::hasColumn('gruppo_individuo', 'ruolo_id')) {
@@ -19,18 +19,18 @@ return new class extends Migration
$table->boolean('attiva')->default(true);
$table->timestamps();
});
}
DB::table('tipologie_eventi')->insert([
['nome' => 'catechesi', 'descrizione' => 'Catechesi', 'ordine' => 0, 'attiva' => true],
['nome' => 'liturgia', 'descrizione' => 'Liturgia', 'ordine' => 1, 'attiva' => true],
['nome' => 'animazione', 'descrizione' => 'Animazione', 'ordine' => 2, 'attiva' => true],
['nome' => 'formazione', 'descrizione' => 'Formazione', 'ordine' => 3, 'attiva' => true],
['nome' => 'incontro', 'descrizione' => 'Incontro', 'ordine' => 4, 'attiva' => true],
['nome' => 'riunione', 'descrizione' => 'Riunione', 'ordine' => 5, 'attiva' => true],
['nome' => 'festa', 'descrizione' => 'Festa / Sagra', 'ordine' => 6, 'attiva' => true],
['nome' => 'altro', 'descrizione' => 'Altro', 'ordine' => 7, 'attiva' => true],
]);
DB::table('tipologie_eventi')->insert([
['nome' => 'catechesi', 'descrizione' => 'Catechesi', 'ordine' => 0, 'attiva' => true],
['nome' => 'liturgia', 'descrizione' => 'Liturgia', 'ordine' => 1, 'attiva' => true],
['nome' => 'animazione', 'descrizione' => 'Animazione', 'ordine' => 2, 'attiva' => true],
['nome' => 'formazione', 'descrizione' => 'Formazione', 'ordine' => 3, 'attiva' => true],
['nome' => 'incontro', 'descrizione' => 'Incontro', 'ordine' => 4, 'attiva' => true],
['nome' => 'riunione', 'descrizione' => 'Riunione', 'ordine' => 5, 'attiva' => true],
['nome' => 'festa', 'descrizione' => 'Festa / Sagra', 'ordine' => 6, 'attiva' => true],
['nome' => 'altro', 'descrizione' => 'Altro', 'ordine' => 7, 'attiva' => true],
]);
}
}
public function down(): void
@@ -10,6 +10,10 @@ return new class extends Migration
{
public function up(): void
{
if (Schema::hasTable('google_oauth_connections')) {
return;
}
Schema::create('google_oauth_connections', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
+4 -1
View File
@@ -14,7 +14,10 @@ if (PHP_VERSION_ID < 50600) {
echo $err;
}
}
throw new RuntimeException($err);
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php';
+4 -25
View File
@@ -26,12 +26,6 @@ use Composer\Semver\VersionParser;
*/
class InstalledVersions
{
/**
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
* @internal
*/
private static $selfDir = null;
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
@@ -317,18 +311,6 @@ class InstalledVersions
self::$installedByVendor = array();
}
/**
* @return string
*/
private static function getSelfDir()
{
if (self::$selfDir === null) {
self::$selfDir = strtr(__DIR__, '\\', '/');
}
return self::$selfDir;
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
@@ -340,7 +322,6 @@ class InstalledVersions
}
$installed = array();
$copiedLocalDir = false;
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
@@ -349,11 +330,9 @@ class InstalledVersions
} elseif (is_file($vendorDir.'/composer/installed.php')) {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require $vendorDir.'/composer/installed.php';
self::$installedByVendor[$vendorDir] = $required;
$installed[] = $required;
if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $required;
$copiedLocalDir = true;
$installed[] = self::$installedByVendor[$vendorDir] = $required;
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
@@ -371,7 +350,7 @@ class InstalledVersions
}
}
if (self::$installed !== array() && !$copiedLocalDir) {
if (self::$installed !== array()) {
$installed[] = self::$installed;
}
+4 -4
View File
@@ -3,7 +3,7 @@
'name' => 'laravel/laravel',
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => '6909e21b677ae5b7bfe8d8ef3f31b61982b5436e',
'reference' => '92ba47e99f4839d49d5f002915c30a88bb842c6a',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -427,7 +427,7 @@
'laravel/laravel' => array(
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => '6909e21b677ae5b7bfe8d8ef3f31b61982b5436e',
'reference' => '92ba47e99f4839d49d5f002915c30a88bb842c6a',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -732,8 +732,8 @@
'dev_requirement' => false,
'provided' => array(
0 => '1.0 || 2.0 || 3.0',
1 => '1.0|2.0|3.0',
2 => '3.0.0',
1 => '3.0.0',
2 => '1.0|2.0|3.0',
),
),
'psr/simple-cache' => array(